Repository navigation
Conversation
A socket flagged with send_proxy_protocol is expected to announce the source and destination of the received request. This only happened for stateless forwarding over UDP, in all the other cases the header was carrying the address of the OpenSIPS outbound socket itself: * tm never passes a SIP message to msg_send(), so the transport layer had no receive info for relayed requests, their retransmissions and the locally generated CANCELs and hop-by-hop ACKs. Add msg_send_rcv(), taking the message which provides the receive info separately from the one handed to the raw processing callbacks, and have tm use the request stored in the transaction. Replies and local transactions are not changed. * for stream transports (TCP, TLS, WS, WSS) the header is sent when the connect completes, in TCP main, where there is no message at all. Remember the original endpoints in the connection when it is created and use them when the header is built. Fixes OpenSIPS#4456
The proto_data of a connection is allocated by TCP main in its private memory. When a worker was sending on a TLS connection that had already been initialized by TCP main, but did not get to send its PROXY header yet, tls_async_queue_proxy_header() was dereferencing that pointer in the wrong process, crashing the worker. This was seen when several requests were racing towards a new destination over a socket using send_proxy_protocol. Only TCP main is allowed to use it; the workers have nothing to queue there anyway, as the header is built by TCP main upon the first write.
NormB
marked this pull request as ready for review
November 14, 2026 20:25
A worker sending on a connection whose connect was just completed by TCP main was queueing the PROXY header as an async chunk, while TCP main was about to send the very same header by itself, as none of them had flagged the header as sent yet. With several requests racing towards a new destination, the connection ended up with a second header in the middle of the stream, or with the header following the first request. The header is now sent only by the process doing the actual write on the connection, ahead of the first data. The other processes only attach the original endpoints to the connections they create.
NormB
force-pushed
the
fix/proxy-protocol-orig-src
branch
from
November 14, 2026 21:37
77c0e48 to
d20b290
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Make
send_proxy_protocolsockets advertise the original client in the PROXY header on every outbound path, not only for stateless UDP forwarding.Details
Bug fix. A
send_proxy_protocolsocket puts OpenSIPS' own address in the PROXY header whenever the request is relayed statefully, or over a stream transport:tmsends throughsend_pr_buffer(), which passes no message to the transport, so the header is built from the outbound socket.Two further problems showed up while testing this:
tls_async_queue_proxy_header()dereferencesproto_data(TCP main private memory) from a worker and crashes it. This is independent of the fix: it reproduces on unpatched master and 4.0 with a TLSsend_proxy_protocolsocket when several requests race towards a new destination.Solution
Three commits:
proxy_protocol: advertise the original endpoints on all outbound pathsmsg_send_rcv()lets the caller name the request whose receive info is advertised;msg_send()becomes a wrapper, so existing callers are unchanged.tmpasses the UAS request for relayed branches, including the CANCEL and hop-by-hop ACK it generates for them. Replies and local transactions are not changed.pp_out) and the header is built from there.proto_tls: do not access the TCP main private conn data from workersproxy_protocol: send the stream PROXY header only from the writerTested with a scripted harness that sends raw SIP through OpenSIPS and checks the PROXY header each next hop receives, in both async and sync TCP modes (179 checks):
allow_proxy_protocolchained to outbounddialog+topology_hidingas in [BUG] HAProxy PROXY Protocol implementation doesn't forward the original Source IP. #4456: sequential requests in both directions and the dialog-generated BYEsend-proxy) and behind (accept-proxy) on every stream transportThe header checks fail without the fix and pass with it. The harness also passes under AddressSanitizer.
Limitations:
proto_sctpandproto_ipsecare compiled only.Compatibility
struct tcp_connectiongains app_outmember. Sockets withoutsend_proxy_protocolare not affected. With it, relayed requests now carry the client's address where they used to carry OpenSIPS' own, which is the documented behaviour.The reporter runs 4.0.3; the three commits cherry-pick cleanly onto 4.0 and the harness passes there too.
Closing issues
closes #4456