[SR-Users] Possible causes of calls being terminated (ACK packet never received)

Alex Villací­s Lasso a_villacis at palosanto.com
Tue May 27 22:44:11 CEST 2014


El 26/05/14 11:05, Alex Villací­s Lasso escribió:
>
>> My current working theory is that the Record-Route headers are incorrect in the original trace. The trace, as captured in the firewall, looks like this:
>>
>> SIP/2.0 200 OK
>> Via: SIP/2.0/UDP 38.126.208.41:5060;rport=5060;branch=b18bbcc394bb5dae43946b12f5d5fe0e
>> Record-Route: <sip:127.0.0.1;r2=on;lr=on;ftag=3609590102-643763;vsf=AAAAAGhZVlxTUnJZUllGSQAAAAAAAAAAAAAAAAAAOjEzNTI-;nat=yes>
>> Record-Route: <sip:192.168.10.10;r2=on;lr=on;ftag=3609590102-643763;vsf=AAAAAGhZVlxTUnJZUllGSQAAAAAAAAAAAAAAAAAAOjEzNTI-;nat=yes>
>>
>> The first value is 127.0.0.1 and the second one is 192.168.10.10 . I believe that when received by 38.126.208.41, this is interpreted as a request to send the ACK to the remote server's idea of 192.168.10.10, which breaks routing back to my server.
>>
>> Now a bit of background. The firewall is a Linux (Zentyal) system that is rewriting the SIP traffic before routing it between the Kamailio (inside the LAN) and the carrier IP (38.126.208.41). This rewrite (kernel modules nf_conntrack_sip, nf_nat_sip) 
>> affects the Via and To headers but leaves the Record-Route header unchanged, which causes the issue. I think I have to force a Record-Route header that shows my public IP where the 192.168.10.10 is currently shown. However, this is becoming difficult.
>>
>> When I use record_route() (original situation), I get the following set of headers:
>> SIP/2.0 200 OK
>> Via: SIP/2.0/UDP 38.126.208.41:5060;rport=5060;branch=b18bbcc394bb5dae43946b12f5d5fe0e
>> Record-Route: <sip:127.0.0.1;r2=on;lr=on;ftag=3609590102-643763;vsf=AAAAAGhZVlxTUnJZUllGSQAAAAAAAAAAAAAAAAAAOjEzNTI-;nat=yes>
>> Record-Route: <sip:192.168.10.10;r2=on;lr=on;ftag=3609590102-643763;vsf=AAAAAGhZVlxTUnJZUllGSQAAAAAAAAAAAAAAAAAAOjEzNTI-;nat=yes>
>>
>> If I figure out that the SIP dialog is crossing the NAT firewall, and use record_route_advertised_address(), I end up with the following headers at the firewall:
>> SIP/2.0 200 OK
>> Via: SIP/2.0/UDP 38.126.208.41:5060;rport=5060;branch=a54dd5cb61364e93c84315902262fab8
>> Record-Route: <sip:201.234.196.171;ftag=3609873405-620577;lr=on;vsf=AAAAAGhZVFtaUHNUW1lMRAAAAAAAAAAAAAAAAAAAOjEwMzE-;nat=yes>
>>
>> Please note that record_route_advertised_address() is inserting just one value (not two, despite relying on the rr parameter enable_double_rr to remain at its default value of ON), with the value of my public IP. This results in the ACK packet being 
>> sent from the carrier IP, and routed through the firewall and to the Kamailio server. However, once there, it is not further routed to the Asterisk instance at 127.0.0.1:5080, which results in the same situation as before.
>>
>> If I try to call both record_route() and record_route_advertised_address() , in any order, I get the behavior matching the first call, and the second call is ignored with a message in the logs stating "Double attempt to record-route".
>>
>> If I try using record_route() along with set_advertised_address(), I get the following set of headers:
>> SIP/2.0 200 OK
>> Via: SIP/2.0/UDP 38.126.208.41:5060;rport=5060;branch=d7bd9bac7e62d56026365e5aa7b257f7
>> Record-Route: <sip:201.234.196.171;r2=on;lr=on;ftag=3609874172-119227;vsf=AAAAAGhZVl9aUXtSUllBRQAAAAAAAAAAAAAAAAAAOjEwMzE-;nat=yes>
>> Record-Route: <sip:192.168.10.10;r2=on;lr=on;ftag=3609874172-119227;vsf=AAAAAGhZVl9aUXtSUllBRQAAAAAAAAAAAAAAAAAAOjEwMzE-;nat=yes>
>>
>> That is, I get 127.0.0.1 replaced with the public IP, and the private IP remains in place as the last value. This again results in ACK never reaching the firewall, much less the Kamailio server.
>>
>> What I think is needed is a way to *conditionally* make Kamailio emit, from inside the LAN, a packet like this:
>> SIP/2.0 200 OK
>> Via: SIP/2.0/UDP 38.126.208.41:5060;rport=5060;branch=blah
>> Record-Route: <sip:127.0.0.1;r2=on;lr=on;blah...>
>> Record-Route: <sip:201.234.196.171;r2=on;lr=on;blah...>
>
> The way I am trying to build the Record-Route headers is with this block:
>
> # Value of $var(rr_advertise_address) is set in route(MHOMED_ELASTIX)
> route[MHOMED_RR] {
>     if ($var(rr_advertise_address) != 0) {
> xlog("L_ALERT", "MHOMED_RR using rr advertised address $var(rr_advertise_address)\n");
> record_route_advertised_address("$var(rr_advertise_address)");
>     } else {
>         record_route();
>     }
> }
>
> The idea is that, for calls that do not route to internal addresses in the LAN, I have to set $var(rr_advertise_address), otherwise it remains as $null. If I do this, I get the single Record-Route with the advertised address instead of two values (one 
> with the advertised address, the other with 127.0.0.1) as I would like it to run. However, if I invoke record_route() unconditionally, I get the two header values.
>
> Why the difference in behavior?
Is there any additional information I might provide to solve this?



More information about the sr-users mailing list