Discussion:
[SR-Users] dispatcher behind NAT - lost ACK
Nicholas Gill
2014-10-17 01:09:08 UTC
Permalink
Hello sr-users,

We have Kamailio (behind NAT) configured acting as a proxy in front of
some FreeSWITCH servers.

There appears to be something amiss with my inbound (dispatcher)
configuration which leads to misaddressing / misdelivery of the ACK
after 200 OK (outbound calls appear to be proxied correctly [1]).

Calls from the sip provider incoming to Kamailio are distributed by the
dispatcher module to the FS server (For testing in this simplified
scenario FS and Kamailio are on the same machine):

SIP provider (5060) sends an invite to Kamailio(5061), Kamailio
uses the dispatcher module to select a backend server and forwards the
INVITE to FS(5070) (see inbound-callflow.png; kamailio.ext and
kamailio.int are the same machine, just public/private addresses).

I notice that at no point is a Via/record-route header for the FS server
inserted into the forwarded session. I'm not actually certain this is a
requirement, but I can't think of another obvious way that Kamailio
could proxy the same session to the same FS server.

The 100 Trying seems unremarkable [2], I suspect the 200 OK [3] is
problematic. It has been proxied from the FS server, however contains no
reference to the FS server address either in the via headers nor
record-route (kamailio.int:5070). The incoming ACK [4] then appears to
be misdelivered / lost - Kamailio receives it on the private address and
forwards it to the public address rather than the FS server.

My configuration [5] is built based on the default configuration +
examples from the dispatcher module. There are some provisions for
FreeSWITCH internal/external profiles made so the configuration listens
on 2 different ports. This particular scenario should only use the 5061
port as it involves calls to an external sip provider (briefly 5060
should be proxied to FS:5080 and 5061 should be proxied to FS:5070 and
vice-versa).


If someone can see an issue with the configuration and/or point to an
error in the call flow (i.e. should FS be inserting the Via header?)
that would be greatly appreciated.


Thanks,

-nick

[1] Outbound call flow (see also outbound-callflow.png)
FS(port 5070) sends an invite to Kamailio(5061) (Kamailio is configured
in FS as an outbound proxy), INVITE contains Via header for the FS
server, Kamailio forwards to sip provider, and routes all messages back
and forth correctly.

[2] 100 Trying
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP
sip.provider.com:5060;branch=z9hG4bKfffb.7c81ee53.0;rport=5060
Via: SIP/2.0/UDP
far.external.ip;received=far.external.ip;rport=5060;branch=z9hG4bK4Qg7Ng27BvHrK
From: "Nicholas Gill" <sip:0384171966-***@public.gmane.org>;tag=j3KQmpvmg6mvr
To: <sip:0390156842-ISr2AyILkvtEwdCo8/***@public.gmane.org>
Call-ID: aa7174e7-d028-1232-4b95-001cc0dd11e9
CSeq: 66413636 INVITE
Server: kamailio (4.1.6 (x86_64/linux))
Content-Length: 0

[3] Proxied 200 OK (Kamailio -> Sip Provider)
SIP/2.0 200 OK
Via: SIP/2.0/UDP
sip.provider.com:5060;rport=5060;branch=z9hG4bKfffb.7c81ee53.0
Via: SIP/2.0/UDP
far.external.ip;received=far.external.ip;rport=5060;branch=z9hG4bK4Qg7Ng27BvHrK
Record-Route: <sip:kamailio.ext:5061;lr=on>
Record-Route: <sip:sip.provider.com;lr;ftag=j3KQmpvmg6mvr;did=0ec.84ff82b1>
From: "Nicholas Gill" <sip:0384171966-***@public.gmane.org>;tag=j3KQmpvmg6mvr
To: <sip:0390156842-ISr2AyILkvtEwdCo8/***@public.gmane.org>;tag=BFvQmggHrg74m
Call-ID: aa7174e7-d028-1232-4b95-001cc0dd11e9
CSeq: 66413636 INVITE
Contact: <sip:0390156842-j+PTJLu+***@public.gmane.org:5070;transport=udp>
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE,
REGISTER, REFER, NOTIFY
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, refer
Content-Type: application/sdp
Content-Disposition: session
Content-Length: 270
X-FS-Support: update_display,send_info

[4] Incoming ACK (Sip Provider -> Kamailio)
ACK sip:0390156842-j+PTJLu+TTolwo/***@public.gmane.org:5061;transport=udp SIP/2.0
Record-Route: <sip:sip.provider.com;lr;ftag=j3KQmpvmg6mvr>
Via: SIP/2.0/UDP sip.provider.com:5060;branch=z9hG4bKfffb.7c81ee53.2
Via: SIP/2.0/UDP
far.external.ip;received=far.external.ip;rport=5060;branch=z9hG4bK509ZQBKB947aF

Route: <sip:kamailio.ext:5061;lr=on>
Max-Forwards: 69
From: "Nicholas Gill" <sip:0384171966-***@public.gmane.org>;tag=j3KQmpvmg6mvr
To: <sip:0390156842-ISr2AyILkvtEwdCo8/***@public.gmane.org>;tag=BFvQmggHrg74m
Call-ID: aa7174e7-d028-1232-4b95-001cc0dd11e9
CSeq: 66413636 ACK
Contact: <sip:gw+Exetel-***@public.gmane.org:5060;transport=udp;gw=Exetel>
Proxy-Authorization: Digest username="0384171900",
realm="far.external.ip", nonce="xxxx", algorithm=MD5,
uri="sip:0390156842-ISr2AyILkvtEwdCo8/***@public.gmane.org", response="xxxx"
Content-Length: 0
P-hint: rr-enforced

[5] Kamailio configuration (based on default configuration). Dispatcher
set 1 is FS internal profile (5080) and set 2 is external profile (5070)
...
#!define WITH_NAT
...
alias="kamailio.int:5060"
alias="kamailio.int:5061"
alias="kamailio.ext:5060"
alias="kamailio.ext:5061"

listen=udp:kamailio.int:5060 advertise kamailio.ext:5060
listen=udp:kamailio.int:5061 advertise kamailio.ext:5061
port=5060
port=5061
...
loadmodule "dispatcher.so"
modparam("dispatcher", "flags", 2)
modparam("dispatcher", "list_file", "/etc/kamailio/dispatcher.list")
modparam("dispatcher", "dst_avp", "$avp(AVP_DST)")
modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)")
modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)")
#modparam("dispatcher", "ds_ping_interval", 60)
...
modparam("nathelper", "sipping_from", "sip:pinger-***@public.gmane.org")
...
request_route {
...
# Not from FS servers gets dispatched to FS servers.
if(!ds_is_from_list("1") and !ds_is_from_list("2"))
{
route(DISPATCH);
}

# Requests from FS External profile routed out via specific port.
if(ds_is_from_list("2"))
$fs="udp:kamailio.int:5061";
...
}

route[DISPATCH] {
if(dst_port==5061)
{
$fs="udp:kamailio.int:5061";
# Hash over to uri for test purposes
if(!ds_select_dst("2", "2"))
{
send_reply("404", "No destination");
exit;
}
}
else
{
# Hash over to uri for test purposes
if(!ds_select_dst("1", "2"))
{
send_reply("404", "No destination");
exit;
}
}

xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");
t_on_failure("RTF_DISPATCH");
route(RELAY);
exit;
}
failure_route[RTF_DISPATCH] {
if (t_is_canceled()) {
exit;
}
# next DST - only for 500 or local timeout
if (t_check_status("500")
or (t_branch_timeout() and !t_branch_replied()))
{
if(ds_next_dst())
{
t_on_failure("RTF_DISPATCH");
route(RELAY);
exit;
}
}
}
...
Ovidiu Sas
2014-10-17 13:37:59 UTC
Permalink
It seems that you SIP provider detects your NAT settings and it is
trying to fix it, which breaks your setup.
See the Contact in the 200OK: Contact:
<sip:0390156842-j+PTJLu+***@public.gmane.org:5070;transport=udp>
Which is bad, it should be the IP of the FS server.
See the RURI in ACK: sip:0390156842-j+PTJLu+TTolwo/***@public.gmane.org:5061;transport=udp
The IP was switched from int to ext.

Probably a better setup would be to listen on multiple interfaces, one
for external traffic and one for internal traffic.
And then you will need to ask your SIP provider to stop messing with
the Contact header or you will need to circumvent that by doing some
header and routing manipulations.


Regards,
Ovidiu Sas
Post by Nicholas Gill
Hello sr-users,
We have Kamailio (behind NAT) configured acting as a proxy in front of some
FreeSWITCH servers.
There appears to be something amiss with my inbound (dispatcher)
configuration which leads to misaddressing / misdelivery of the ACK after
200 OK (outbound calls appear to be proxied correctly [1]).
Calls from the sip provider incoming to Kamailio are distributed by the
dispatcher module to the FS server (For testing in this simplified scenario
SIP provider (5060) sends an invite to Kamailio(5061), Kamailio uses the
dispatcher module to select a backend server and forwards the INVITE to
FS(5070) (see inbound-callflow.png; kamailio.ext and kamailio.int are the
same machine, just public/private addresses).
I notice that at no point is a Via/record-route header for the FS server
inserted into the forwarded session. I'm not actually certain this is a
requirement, but I can't think of another obvious way that Kamailio could
proxy the same session to the same FS server.
The 100 Trying seems unremarkable [2], I suspect the 200 OK [3] is
problematic. It has been proxied from the FS server, however contains no
reference to the FS server address either in the via headers nor
record-route (kamailio.int:5070). The incoming ACK [4] then appears to be
misdelivered / lost - Kamailio receives it on the private address and
forwards it to the public address rather than the FS server.
My configuration [5] is built based on the default configuration + examples
from the dispatcher module. There are some provisions for FreeSWITCH
internal/external profiles made so the configuration listens on 2 different
ports. This particular scenario should only use the 5061 port as it involves
calls to an external sip provider (briefly 5060 should be proxied to FS:5080
and 5061 should be proxied to FS:5070 and vice-versa).
If someone can see an issue with the configuration and/or point to an error
in the call flow (i.e. should FS be inserting the Via header?) that would be
greatly appreciated.
Thanks,
-nick
[1] Outbound call flow (see also outbound-callflow.png)
FS(port 5070) sends an invite to Kamailio(5061) (Kamailio is configured in
FS as an outbound proxy), INVITE contains Via header for the FS server,
Kamailio forwards to sip provider, and routes all messages back and forth
correctly.
[2] 100 Trying
SIP/2.0 100 trying -- your call is important to us
Via: SIP/2.0/UDP
sip.provider.com:5060;branch=z9hG4bKfffb.7c81ee53.0;rport=5060
Via: SIP/2.0/UDP
far.external.ip;received=far.external.ip;rport=5060;branch=z9hG4bK4Qg7Ng27BvHrK
Call-ID: aa7174e7-d028-1232-4b95-001cc0dd11e9
CSeq: 66413636 INVITE
Server: kamailio (4.1.6 (x86_64/linux))
Content-Length: 0
[3] Proxied 200 OK (Kamailio -> Sip Provider)
SIP/2.0 200 OK
Via: SIP/2.0/UDP
sip.provider.com:5060;rport=5060;branch=z9hG4bKfffb.7c81ee53.0
Via: SIP/2.0/UDP
far.external.ip;received=far.external.ip;rport=5060;branch=z9hG4bK4Qg7Ng27BvHrK
Record-Route: <sip:kamailio.ext:5061;lr=on>
Record-Route: <sip:sip.provider.com;lr;ftag=j3KQmpvmg6mvr;did=0ec.84ff82b1>
Call-ID: aa7174e7-d028-1232-4b95-001cc0dd11e9
CSeq: 66413636 INVITE
User-Agent: IMX
Accept: application/sdp
Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER,
REFER, NOTIFY
Supported: timer, path, replaces
Allow-Events: talk, hold, conference, refer
Content-Type: application/sdp
Content-Disposition: session
Content-Length: 270
X-FS-Support: update_display,send_info
[4] Incoming ACK (Sip Provider -> Kamailio)
Record-Route: <sip:sip.provider.com;lr;ftag=j3KQmpvmg6mvr>
Via: SIP/2.0/UDP sip.provider.com:5060;branch=z9hG4bKfffb.7c81ee53.2
Via: SIP/2.0/UDP
far.external.ip;received=far.external.ip;rport=5060;branch=z9hG4bK509ZQBKB947aF
Route: <sip:kamailio.ext:5061;lr=on>
Max-Forwards: 69
Call-ID: aa7174e7-d028-1232-4b95-001cc0dd11e9
CSeq: 66413636 ACK
Proxy-Authorization: Digest username="0384171900", realm="far.external.ip",
response="xxxx"
Content-Length: 0
P-hint: rr-enforced
[5] Kamailio configuration (based on default configuration). Dispatcher set
1 is FS internal profile (5080) and set 2 is external profile (5070)
...
#!define WITH_NAT
...
alias="kamailio.int:5060"
alias="kamailio.int:5061"
alias="kamailio.ext:5060"
alias="kamailio.ext:5061"
listen=udp:kamailio.int:5060 advertise kamailio.ext:5060
listen=udp:kamailio.int:5061 advertise kamailio.ext:5061
port=5060
port=5061
...
loadmodule "dispatcher.so"
modparam("dispatcher", "flags", 2)
modparam("dispatcher", "list_file", "/etc/kamailio/dispatcher.list")
modparam("dispatcher", "dst_avp", "$avp(AVP_DST)")
modparam("dispatcher", "grp_avp", "$avp(AVP_GRP)")
modparam("dispatcher", "cnt_avp", "$avp(AVP_CNT)")
#modparam("dispatcher", "ds_ping_interval", 60)
...
...
request_route {
...
# Not from FS servers gets dispatched to FS servers.
if(!ds_is_from_list("1") and !ds_is_from_list("2"))
{
route(DISPATCH);
}
# Requests from FS External profile routed out via specific port.
if(ds_is_from_list("2"))
$fs="udp:kamailio.int:5061";
...
}
route[DISPATCH] {
if(dst_port==5061)
{
$fs="udp:kamailio.int:5061";
# Hash over to uri for test purposes
if(!ds_select_dst("2", "2"))
{
send_reply("404", "No destination");
exit;
}
}
else
{
# Hash over to uri for test purposes
if(!ds_select_dst("1", "2"))
{
send_reply("404", "No destination");
exit;
}
}
xlog("L_DBG", "--- SCRIPT: going to <$ru> via <$du>\n");
t_on_failure("RTF_DISPATCH");
route(RELAY);
exit;
}
failure_route[RTF_DISPATCH] {
if (t_is_canceled()) {
exit;
}
# next DST - only for 500 or local timeout
if (t_check_status("500")
or (t_branch_timeout() and !t_branch_replied()))
{
if(ds_next_dst())
{
t_on_failure("RTF_DISPATCH");
route(RELAY);
exit;
}
}
}
...
_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users
--
VoIP Embedded, Inc.
http://www.voipembedded.com
Nicholas Gill
2014-10-24 03:40:52 UTC
Permalink
Hi Ovidiu,
Post by Ovidiu Sas
Which is bad, it should be the IP of the FS server.
I investigated and I'm not sure this is the issue.

Unfortunately when I named the various addresses it obscured the fact
that the ip address kamailio.int is the IP address of the freeswitch
server - i.e. FS and Kamailio were hosted on the same machine for that test.

Regarding multiple interfaces the configuration does listen on two
ports, one for internal and one for external. What benefit would making
this on two distinct interfaces bring?

Cheers,

-nick

Loading...