Summary

  • RFC 3581 lets a SIP client request that the response be sent to the source address and port the server actually observed. A successful reply proves that the current transaction crossed the then-current NAT binding; it does not prove a durable route back to the client.
  • Registration, later dialog requests, cluster failover, keepalive, flow identity and call outcome require their own receipts. Promoting received plus rport into endpoint identity joins claims with different owners and lifetimes.

A SIP phone sends an INVITE from a private address. A translator changes both the address and the UDP source port. The proxy receives the packet and can see the translated tuple. A few moments later, 200 OK returns to that tuple and reaches the phone. The trace is green.

Then another request, sent toward the same user, disappears.

There is no contradiction. The reply and the later request relied on different promises. The first used fresh evidence from an outbound packet and the mapping that packet created. The second needed a still-living reverse path, the right proxy, the right source tuple, a valid registration decision and a route for a different transaction. RFC 3581 solved the first problem and carefully warned against pretending it had solved the second.

Published in August 2003 as a Standards Track document, RFC 3581 adds rport to the top Via header. Its lasting value is not merely a NAT workaround. It is an unusually explicit account of how a narrow repair becomes brittle when an observation is promoted into authority.

The old rule mixed two realities

Base SIP over UDP calculated a response destination in a hybrid way. It took the IP address from the packet's observed source but took the port from the top Via sent-by field. That arrangement helped a server listen for requests and responses on a single advertised socket. Behind a translator, however, half of the answer could describe the public wire while the other half still described the private endpoint.

RFC 3581 lets the client add an empty rport parameter. Empty is important: the client is not asserting the public port. It is asking the receiving server to report and use what the server observed.

The server fills rport with the source port and adds received with the source address, even when the observed address equals the advertised one. For an unreliable unicast transport, with no maddr, the response goes to that pair. It must also leave from the same server address and port on which the request arrived. A symmetric NAT can care about both sides of the tuple.

The mechanism is therefore not “trust the header.” It is “bind the response to the wire observation for this transaction.” The distinction decides what the resulting evidence can support.

A tuple is an observation, not an identity

Suppose the Via says 10.1.1.1:4540, while the proxy sees 192.0.2.1:9988. The latter pair can be the correct return destination at that instant. It does not identify the human, the SIP Address-of-Record, a particular device instance or a permanent public socket. It may be reassigned, expire or be valid only for packets from one remote endpoint.

The proof is narrower still. An empty rport shows that the sender requested the behavior. A numeric rport in a response shows what a server wrote. Only packet receipt at the client proves that this response completed the path. Even then, the receipt says nothing about how long the NAT state will remain, whether a different server can use it or whether a later transaction has the same route.

An evidence system should keep the request's branch, Call-ID, CSeq, original Via, observed source tuple, server instance, receiving interface, responding interface, response status and client receipt together. Saving only reachable=true discards the scope that made the statement true.

The server socket is part of the claim

RFC 3581 requires the response to use the same source address and port that received the request. This matters when a proxy listens on several interfaces or ports. A load balancer may present one service name while several workers own different sockets. A packet accepted from one remote tuple may not be admitted when it originates from another.

A stateful proxy can remember the receiving socket for the life of the transaction. A stateless proxy has to carry enough information in its own Via to reconstruct the correct forwarding decision when the response comes back. “Stateless” does not mean “without provenance.” It means the provenance must travel rather than sit in memory.

This is a useful operational boundary. The service name did not receive the packet; a concrete interface on a concrete instance did. If telemetry records only the logical proxy, failover can look equivalent when the NAT sees it as a different peer. Cluster health and transaction-path health are separate measurements.

The mapping can die before the transaction

RFC 3581 states the dependency directly: the NAT binding must exist for the duration of the transaction. It expected most non-INVITE transactions to finish within then-common UDP timeouts. INVITE can remain unresolved much longer. The document therefore advised continued retransmissions, even after a provisional response, to keep the mapping fresh.

The advice reveals the limit. The tuple carries no expiry time. A successful provisional response is not a lease. A quiet interval, NAT restart, policy change, failover or mapping collision can erase the path while every SIP identity field remains unchanged.

The RFC cited the binding-lifetime discovery procedure in the original STUN specification and warned that discovery could be unreliable. RFC 3489 was later obsoleted by RFC 5389, which was in turn obsoleted by RFC 8489. That history must not be flattened into present-day assurance. What remains durable is the evidence rule: record actual traffic and bounded timers; do not infer a future mapping from an old observation.

Learning an address is not acquiring a route

received and rport also reveal the public tuple seen by the server. A client might be tempted to place that pair into a Contact header, or a proxy into Record-Route, so that later requests return through the NAT. RFC 3581 classifies that use as unilateral self-address fixing and spends more space on its brittleness than on celebrating it.

The mapping has to remain fresh, which may require registrations far more frequently than ordinary registration expiry. A symmetric NAT may accept traffic only from the server that received the original packet. Another member of a cluster can therefore follow the same application record and still miss the client. If the first hop was a proxy rather than the registrar, later requests need to traverse that proxy; RFC 3327 Path supplies that routing statement.

None of those conditions is encoded by the numeric rport alone. The tuple does not name its valid remote peer, its expiration, the responsible edge proxy or the cluster constraint. Treating it as a public endpoint converts hidden conditions into outages.

RFC 3581's exit strategy is revealing. A sounder solution should let a client say that incoming requests must use the connection or flow it established, should account for server clusters and should avoid an excessive refresh penalty. Later SIP Outbound work did exactly this more explicitly: registration bindings can refer to client-initiated flows, multiple flows can coexist, and keepalives can refresh mappings and detect failure.

Later does not mean magical. RFC 6223 separates keepalive negotiation from connection reuse. RFC 5923 addresses reverse requests on connection-oriented transports. RFC 5627 supplies stable routable UA identifiers. Each mechanism owns a different claim. A pong is not registration selection; a flow token is not authorization; a stable URI is not proof that media or a user answered.

Protection does not widen the meaning

The observed source tuple can be sensitive. RFC 3581 points to SIP over TLS for protecting signaling. On a connection-oriented transport, however, rport is chiefly informational; its UDP response-routing behavior is not the reason the response succeeds.

A man in the middle can remove rport and prevent a client behind NAT from receiving the response. Integrity protection can prevent that mutation. It cannot make the observed tuple a durable identity or prove who controls the translated address. The IANA registry can preserve the parameter's coordinated syntax; it cannot attest that a deployment supports it correctly or that a mapping is alive.

The evidence chain therefore needs separate authority at each step: authentication for the SIP identity, wire observation for the transaction tuple, proxy provenance for the response path, Path or flow data for later routing, registrar state for contact selection, dialog state for subsequent requests, and outcome evidence for alerting, answer, media and application completion.

Evidence boundary

This Article identifies no carrier, PBX, SIP provider, user agent, registrar, NAT product, cluster, subscriber, call, incident or media result. It describes the contract in RFC 3581 and the limitations stated in that document. Standards Track status is not deployment evidence.

RFC 3261 supplies the SIP transaction and Via base. RFC 3327 supplies Path. RFC 3424 supplies the IAB's UNSAF criteria. RFC 3489 is historical context only; RFC 5389 and RFC 8489 mark later STUN evolution. RFC 5626 and RFC 6314 supply later Outbound and practice context. RFC 5923, RFC 6223 and RFC 5627 distinguish connection reuse, keepalive and stable UA routing. The IANA registry proves assigned syntax, not live service.

Heng Lu's Running-Code Primacy and Minimum Initial Specification essays are disclosed editorial lenses. They support testing the running path rather than treating protocol declaration as outcome, and keeping the shared repair narrower than local routing policy. They do not establish the RFC authors' intent or any deployment fact.

The bounded conclusion is operationally strict: a response can prove that one packet found one port at one time. Preserve that receipt. Do not sell it as tomorrow's route.

Sources