Understanding SIP routing

Numerous trouble tickets leading to session timeouts or disconnections often stem from SIP routing errors. SIP routing, is the process to determine the destination for SIP requests (e.g., INVITE, ACK, BYE) or responses (e.g., 200, 302, 503). These headers are instrumental components in mapping out the path for SIP messages.

In this article we cover the basics of SIP routing and expand on a number of common issues we see in the field. Let's get started.

Routing Requests

Routing a request, for this context, is specifically related to non-initial requests. Initial requests (e.g. first REGISTER, INVITE, SUBSCRIBE of a SIP dialog/transaction) are pre-determined by configuration such as a device's SIP proxy, registrar, primary/secondary server or configured peer. 

The simple rule is as follows for "A" and "B", where "A" is initiating the request and "B" is receiving.

  • For requests: "A"'s next hop is determined by "B"'s 200 OK response Record-Route. If absent its Contact header.
  • For requests: "B"'s next hop is determined by "A"s INVITE Record-Route. If absent is Contact header.
  • For responses: "A" or "B" will honor a requests Via header (e.g. an INVITE's via determines where a 100 Trying, 180 or 200 OK will be returned).

Remember CRaVe: "CRaVe" for Contact, Record-Route, and Via. It stands for Contact, Route, and Via. This acronym emphasizes the key SIP headers you should always be mindful of when understanding packet routing.

SIP Call

In this simplistic example we have a SIP endpoint "A" reaching its proxy/server "B". Own its own "B" reaches "C" to complete the call.

  1. "A" sends an INVITE to "B". 
  2. "B" responds with a 100 Trying.
  3. "B" INVITEs "C".
  4. "C" responds to "B" with a 100 Trying.
  5. "C" responds to "B" with a 180 Ringing.
  6. "B" responds to "A" with a 180 ringing.
  7. "C" responds to "B" with a 200 OK.
  8. "B" acknowledges "C"'s 200 OK with a SIP ACK.
    1. This path is determine by "C"'s Record-Route or Contact header in the 200 OK (#7).
  9. "B" responds to "A" with a 200 OK.
  10. "A" acknowledges "B"'s 200 OK with a SIP ACK.
    1. This path is determined by "B"'s Record-Route or Contact header in the 200 OK (#9)

  11. At some point the session comes to an end with a BYE. The BYE can be initiated by A, B or C. If no re-INVITEs or UPDATE requests have occurred then here are the possible scenarios.
    1. "A" sends a BYE to "B" following the same rules as 10a.
    2. "B" sends a BYE to "A". This will use "A"'s Record-Route or Contact in #1.
    3. "B" sends a BYE to "C". This will follow the same rules as 8a.
    4. "C" sends a BYE to "B". This will use "B"'s Record-Route or Contact in #3

Let's dive into #1 as an example:

INVITE sip:+18587542209@ SIP/2.0
Via: SIP/2.0/UDP;branch=z9hG4bK1sansay4204590731rdb59082
Record-Route: <sip:sansay4204590731rdb59082@;lr;transport=udp>
To: <sip:+18587542209@>
From: <sip:+15102845648@>;tag=sansay4204590731rdb59082
Call-ID: 6996482763732362130-1705346258@
Contact: <sip:+15102845648@>
Max-Forwards: 30
Content-Type: application/sdp
Content-Length: 223 

This INVITE has a Record-Route which specifies;lr;transport=udp. This Record-Route will inform B that the next hop for a future request is

Easy right? Let's go over the common failure scenarios.

Common Failure Scenarios


When a device is NATed its Contact address URI loses value. It is the SBC's (or proxy)'s responsibility to learn the endpoints socket (IP address:port:transport) with NAT traversal mechanisms. This is true for any SIP header that affects routing: Record-Route, Contact and Via.

When a device is NATed then the learned socket (IP address, port, transport) will override SIP's exposed socket. Failure to detect NAT will result in requests (e.g. ACK, BYE, re-INVITE) or responses (e.g. 200 OK) to not reach the device's publicly reachable socket. NAT issues will get exposed at various levels of a session. Depending on the direction of the call the issues go may unnoticed until there's a re-INVITE or BYE.

See below an example NAT configuration issue getting in the way of SIP packet routing:

 In this example the ACK is sent to the local address instead of the NAT/publicly reachable address. For this reason the call is torn down within a few seconds of the 200 OK. A lot of times this cases go unnoticed if the packet capture was filtered for specific hosts, which will show no ACK at all.


An INVITE is a unique transaction that requires a three-way handshake: INVITE/200/ACK. Failure to acknowledge the session post-200 will result in the SIP dialog timing out and the call getting disconnected.

200 OK

If a 200 OK can't reach it's intended socket (IP:port:transport) you will see resends being sent several times in according to the sender's SIP timer configuration. The 200 OK resends are a mechanism to compensate against unreliable transport protocol (UDP) for signaling.


A re-INVITE or UPDATE will refresh the route set by the Record-Route or Contact header. At this stage not only delivery issues can occur but often times an issue with a dated/unexpected URI that will cause session processing/matching issues.

Let's take a look at this example:

We are having an issue with one of our carriers in which certain calls are failing to dead air. They are claiming it is due to a DID= tag in the request URI header which appears to be added by the Sansay.

 Following the rules of SIP this re-INVITE in packet #8 @ 29.288 is honoring a new URI that was learned in the original INVITE's Contact header. The recepient of thre re-INVITE does not like this parameter, however. While it is the norm to honor an URI set in route (via Record-Route or Contact) certain strategies such as manipulating the SIP message will resolve this issue.

Missing Port Number

Failure to include the optional port number component when a custom SIP socket is used (e.g. port 5062) will also cause issues. Per RFC3261:

Otherwise, if the Via header field value contains a "maddr"
         parameter, the response MUST be forwarded to the address listed
         there, using the port indicated in "sent-by", or port 5060 if
         none is present. 
For instance, a URI omitting the optional port
         component will not match a URI explicitly declaring port 5060.
         The same is true for the transport-parameter, ttl-parameter,
         user-parameter, and method components.

Missing Transport Protocol

Similar to the above, the default transport protocol is UDP. If a device is not explicit about the transport protocol to be used in its socket, failure to do so when not using UDP may result in issues routing subsequent responses or requests.

300 Multiple Choices / 302 Redirect

This article would be incomplete without acknowledging the significance of SIP's 300 and 302 responses, frequently seen during session establishment.

When processing a 30X response, adherence to the previously outlined rules remains crucial, but with a notable distinction — the Contact header determines the immediate next-hop for SIP requests.

300 Multiple Choices response introduces one or more destinations to try prioritized in a specific order. A 300 may be formatted in one SIP header delimiting URIs by comma or maybe structured as multiple Contact headers.

302 Redirects typically carry a single URI for the subsequent hop.

In both scenarios, the Contact URI in the responses shape the format of the URI for the upcoming request.


In conclusion, always remember CRaVe: Contact, Record-Route, and Via headers. These three key SIP headers are instrumental in understanding SIP packet routing and navigating in-session changes to the SIP URI.



Content aside

  • 4 mths agoLast active
  • 109Views
  • 1 Following