Nat – Asterisk behind NAT sets wrong Contact Header

asterisknat;sipvoip

I'm using SIP with asterisk 13.1.0 behind a statically configured NAT.
The servers private_ip differs from the public_ip, where I can reach it.
I've already set these options in the sip.conf file.

externaddr=public_ip:5060
media_address=public_ip
localnet=private_ip/24

If I now try to start a call, the messages work probably until the server sends the OK message to the client. In this message asterisk sets the Contact header to its private and not the public ip.

SIP/2.0 200 OK
From: "Test799" <sip:799@HOSTNAME>;tag=7ajcnltflq
To: <sip:62@HOSTNAME;user=phone>;tag=as08a05471
Call-ID: 54b6479ed3e3-io8z54pk25ve
CSeq: 2 INVITE
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH, MESSAGE
Supported: replaces, timer
Session-Expires: 1800;refresher=uas
Contact: <sip:62@PRIVATE_IP:5060>
Content-Type: application/sdp
Require: timer
Content-Length: ...

v=0
o=root 1234 1234 IN IP4 PUBLIC_IP
c=IN IP4 PUBLIC_IP
...

The UA now sends the following ACK to the PRIVATE_IP, because of the Contact header.

What is wrong with my configuration? Is this a bug in asterisk?

Best Answer

You get this problem, if you use a IPv4 externaddr in combination with the IPv6 bindaddr setting.

;  c) Listen on the IPv4 wildcard.            Example: bindaddr=0.0.0.0
;  d) Listen on the IPv4 and IPv6 wildcards.  Example: bindaddr=::
...
; (Note that using bindaddr=:: will show only a single IPv6 socket in netstat.
;  IPv4 is supported at the same time using IPv4-mapped IPv6 addresses.)

It is important to know that bindaddr=:: does not bind on IPv4 wildcard. It binds on IPv4-mapped IPv6 addresses!