One of the most common issues I see when people deploy SIP is calls hanging up after approximately 30 seconds or traffic not going to where it should. This can be hard for users to grasp and is primarily due to the fact that SIP embeds routing information (IP addresses and ports) within the signaling itself. When SIP was originally created this would have been perfectly fine but in a day and age where NAT is prevalent and the IP address and port may be internal, issues can arise. Let’s take a look at the basic areas which are applicable to most people!
The Via header in a SIP message shows the path that a message took, and determines where responses should be sent to. By default in Asterisk we send to the source IP address and port of the request, overcoming any NAT issues. There are some devices, however, that this does not work properly with. An example is some Cisco phones that require you send responses to the port provided in the Via header. This can be accomplished in chan_pjsip by setting the “force_rport” option to “no” on the endpoint.
The Contact header in a SIP message provides a target for where subsequent requests should be sent to. The Contact header is present in calls, registrations, subscriptions, and more. As you might expect when a device is behind NAT it might not know its public IP address and port and would instead place its private IP address and port in the Contact header. If a SIP device receives this header and is not on the same network it would be unable to contact the device. In a call scenario this exhibits itself upon answering a call. A 200 OK with a Contact header is sent to indicate that the call is answered and the other party then sends an ACK message to the target in the Contact header. If this is not received the 200 OK will be retransmitted until the sender gives up and terminates the call generally after approximately 30 seconds. The chan_pjsip module provides the “rewrite_contact” option to overcome this. It changes the received Contact header to be the actual source IP address and port of the SIP request and effectively ignores what the other party stated.
SDP c= and m= Lines
Media is not immune to NAT as many people likely know. Just like SIP signaling the IP address and port for where media should be sent to is also exchanged in SDP in the “c=” and “m=” lines. Just like with the Contact header a device may not put the correct information in resulting in media being sent to the wrong target. This can be resolved using the “rtp_symmetric” option in chan_pjsip. This configuration option instructs the Asterisk RTP implementation to latch on to the source of media it receives and send outgoing media to that target instead, ignoring what was presented in the “c=” and “m=” lines.
I hope this has provided a bit of insight into a very common problem that people see, why it occurs, and how to resolve it. You’ll note I haven’t covered if Asterisk is behind NAT but instead focused on SIP in general and for devices behind NAT. Don’t despair as there is an excellent wiki page which covers that subject.