Asterisk 18.8.0, PJSIP and rewrite_contact


We are at the moment migrating a lot of Asterisk servers from Asterisk 13 to 18, and from chan_sip to chan_pjsip.

Today we realized that we have problems with the NAT functionality with some devices. We use rewrite_contact to make Asterisk send SIP to the correct places.

In chan_sip the contact of the REGISTER is saved, along with ip/port, and messages to the device are sent to the ip/port with the saved contact in the request-URI. This works very well with all clients that I have encountered.

In chan_pjsip it seems a new contact is created that reflects the true destination. It works usually. The problem with this is that devices that expect the exact contact in the request-URI and discards others will stop working. INVITEs and OPTIONS to the devices are discarded by the device as it doesn’t recognize the URI as its contact.

What are the best practices for this? Is there a way to make chan_pjsip handle this in a way similar to chan_sip?

Best Regards
Torbjörn Abrahamsson

The code should restore the original contact in certain areas, I don’t know if the request URI is one of those or if it applies in the specific scenario. There is no option to change this, it would require code changes to do so.

What device is this happening with?

Thanks for your reply!

I have tried to follow the code, but did not feel sure about it.

Thw following REGISTER is sent to the PBX at, ip from a client behind NAT, with public ip and private ip In the contact the private IP is stated:

Via: SIP/2.0/UDP;branch=z9hG4bKdedad0b00940b6214
Max-Forwards: 70
From: “the_shrimp_sip”;tag=b493bc045b
To: “the_shrimp_sip”
Call-ID: 3101706b33e80ecb
Allow-Events: talk, hold, conference, LocalModeStatus
Authorization: Digest username=“the_shrimp_sip”,realm=“asterisk”,nonce=“1649256487/1be81a0b385441b2e5b005f5e9469ca8”,uri=“”,response=“9262d0a74da3172a0889dd7152f99acd”,algorithm=md5,opaque=“7cf19a834fcec5df”,qop=auth,cnonce=“c941525f”,nc=00000001
Contact: “the_shrimp_sip” sip:the_shrimp_sip@;transport=udp;+sip.instance=“urn:uuid:00000000-0000-1000-8000-00085D34F507
Supported: path, gruu
User-Agent: Aastra 55i/
Aastra-Mac: 00085D34F507
Content-Length: 0

The 200 OK contains a new contact that differs from the one in the request, although it has the private ip. Please note that in this case there is a ;transport=UDP, which should not be there with standard Asterisk code. It is there as the result of a patch, that actually was made to adress a similar problem. The Aastra 55i (yes, old phone, but we have plenty) failed as it did not recognize the contact in the response. So Asterisk thought the device registered, but the device didn’t think so. A small patch that added the transport even if UDP solved this, even though it was not the same letter case.

SIP/2.0 200 OK
Via: SIP/2.0/UDP;rport=1035;received=;branch=z9hG4bKdedad0b00940b6214
Call-ID: 3101706b33e80ecb
From: “the_shrimp_sip”;tag=b493bc045b
To: “the_shrimp_sip”;tag=z9hG4bKdedad0b00940b6214
Date: Wed, 06 Apr 2022 14:48:07 GMT
Contact: sip:the_shrimp_sip@;transport=UDP;expires=3599
Server: pbx
Content-Length: 0

Now, when an INVITE goes out to the device, it looks like the message below. It has the public IP in the request-URI and To-header. I believe that the UDP-parameter is the result of our patch as well.

INVITE sip:the_shrimp_sip@;transport=UDP SIP/2.0
Via: SIP/2.0/UDP;rport;branch=z9hG4bKPjc95a35d3-b22d-4d4c-ad96-486c1bd6df67
From: “Torbjörn Abrahamsson - Wx3 PBX” sip:01@;tag=f6f0143e-2e71-432d-8a9d-1097a833b843
To: sip:the_shrimp_sip@
Contact: sip:asterisk@
Call-ID: 7162ce41-5036-4f53-ac29-2c752fcd17ba
CSeq: 32389 INVITE
Supported: 100rel, timer, replaces, norefersub, histinfo
Session-Expires: 1800
Min-SE: 90
X-CID: b9a94d627303-ufuu44juk2el
Max-Forwards: 70
User-Agent: pbx
Content-Type: application/sdp
Content-Length: 342

Although we have patched the server, the same behavior was present without the patch. We hadn’t encountered a device that failed due to these problems yet. I know I reacted to the change in URL when troubleshooting the problem with the missing transport on the 55i.

The current problem is manifested when using a Ascom IP-DECT Base Station, with firmware 9.0.6. This work fine with Asterisk 13 and chan_sip, but on our new servers with 18 and pjsip it fails. As a fun fact it seems very much older firmwares accepts this, as another one with version 5.1.3 seems to work.

So, that was some more info. Do you agree with my assumption that the URI should be restored in the request-URI?

Thanks for your insights!

I wouldn’t expect it to be, as I see no evidence that that the PJSIP registrar stores both values, at least in terms of the CLI outputs available, and it would confuse any outbound proxy to provide it with an unusable URI. REGISTER is a special case, as the Contact is used to identify to which of several contact addresses the response relates.

Is is not possible to make the Aastra NAT aware? Can you introduce a VPN?

Possibly? You can file an issue, but there is no time frame on when it would get looked into or even if.

Internally we add a parameter to the URI to store the original host/port, for restoration on the 200 OK for REGISTER so the information is present.

Sorry if I was unclear, I meant the assumption the URI should be restored theoretically SIP-wise, not actually what the code does. I.e. if someone says contact me here, I should do just that.

Not sure of what NAT-awareness these devices have, but it will be explored. In the past we have actively skipped all those venues, as chan_sip’s NAT-traversal worked fantastically. Though I can 100% say we will not pursue a VPN solution.

Thank you, we will look at filing a issue.

I will probably put one of my coders on trying to restore the URI as far as possible on outgoing messages. In case of success we will share the result as a patch for review and possible inclusion.

That would fail, as it is saying contact me on a 192… address, which is wrong. The whole point of rewrite contact is to ensure that it isn’t contacted where it says it is, but where it actually appears to be

chan_sip (and chan_pjsip) has a mixture of NAT traversal and broken NAT traversal workaround features. The former are eternal IP and local nets. The latter are force_rport and comedia. The former are to make it a good citizen; the latter to cope with other parties that are bad citizens.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.