Hello everyone,
I'm just curious as to see what some of you guys do in regards to handling a Re-Invite that comes back downstream to a NATTED UAC.
For example, call scenario:
UAC -> Kamailio (Fix Nated Contact) -> PSTN
Re-Invite Occurs:
PSTN -> Kamailio -> UAC
UAC (200 OK w/ NAT RFC1918 contact) -> Kamailio (branch flags at this point are not notifying of NAT, due to the downstream direction of the INVITE, so RFC1918 address exists, but does not fix_nated_contact) -> PSTN
PSTN does not appropriately ACK.
So, what are your guys solutions for solving this problem?
Is the best way to add an attribute onto the contact header sent in original INVITE? Are there other ways of handling? What is the best, cleanest method. Possible to handle with AVP's?
Thanks in advanced for all of your input!
Sincerely, Brandon
Handle the request and the reply with far-end NAT traversal detection routines in the same way you would handle a non-sequential INVITE.
On 02/03/2010 03:05 PM, Brandon Armstead wrote:
Hello everyone,
I'm just curious as to see what some of you guys do in regards to
handling a Re-Invite that comes back downstream to a NATTED UAC.
For example, call scenario:
UAC -> Kamailio (Fix Nated Contact) -> PSTN
Re-Invite Occurs:
PSTN -> Kamailio -> UAC
UAC (200 OK w/ NAT RFC1918 contact) -> Kamailio (branch flags at this point are not notifying of NAT, due to the downstream direction of the INVITE, so RFC1918 address exists, but does not fix_nated_contact) -> PSTN
PSTN does not appropriately ACK.
So, what are your guys solutions for solving this problem?
Is the best way to add an attribute onto the contact header sent in original INVITE? Are there other ways of handling? What is the best, cleanest method. Possible to handle with AVP's?
Thanks in advanced for all of your input!
Sincerely, Brandon
Kamailio (OpenSER) - Users mailing list Users@lists.kamailio.org http://lists.kamailio.org/cgi-bin/mailman/listinfo/users http://lists.openser-project.org/cgi-bin/mailman/listinfo/users
El Miércoles, 3 de Febrero de 2010, Brandon Armstead escribió:
Hello everyone,
I'm just curious as to see what some of you guys do in regards to handling a Re-Invite that comes back downstream to a NATTED UAC.
For example, call scenario:
UAC -> Kamailio (Fix Nated Contact) -> PSTN
Re-Invite Occurs:
PSTN -> Kamailio -> UAC
UAC (200 OK w/ NAT RFC1918 contact) -> Kamailio (branch flags at this point are not notifying of NAT, due to the downstream direction of the INVITE, so RFC1918 address exists, but does not fix_nated_contact) -> PSTN
PSTN does not appropriately ACK.
So, what are your guys solutions for solving this problem?
Is the best way to add an attribute onto the contact header sent in original INVITE? Are there other ways of handling? What is the best, cleanest method. Possible to handle with AVP's?
Thanks in advanced for all of your input!
This is IMHO the most common approach:
- UA1 -> Kamailio (fix natted Contact and do loose routing) -> PSTN.
At this point, the dialog info of PSTN endpoint is: - target_uri: "Contact" URI fixed by Kamailio (so a public address). - route set: the IP of Kamailio (which added it in Record-Route).
So when the PSTN endpoint sends the re-INVITE it would look at follows:
INVITE sip:ua1@PUBLIC_ADDRESS_OF_UA1 SIP/2.0 Route: sip:PROXY_IP
Such INVITE is sent to the proxy (due to the presence of a Route header mirrored from the Record-Rooute in the dialog creation).
The proxy does loose routing by removing the Route header and routes the INVITE to the SIP URI present in the request line:
sip:ua1@PUBLIC_ADDRESS_OF_UA1
So the INVITE will reach ua1 as it will use the open mapping in the NAT router.
However this is not a perfect solution as the domain/host part of the original Contact URI is modified by the proxy, so such INVITE could be rejected by UA1 (it doesn't match the SIP URI it set in the original "Contact" header).
But the fact is that this "hack" works in the real world.
Hello,
I do see all the behavior as referenced, however the actual problem is upon receipt of the invite to the UAC, in which it responds with 200 OK and Contact of RFC1918 address, in which is not being fix natted contact because at this point kamailio is not aware of the UAC being behind nat due to the reinvite passing the nat uac test because we can not tell with the invite coming downstream from PSTN, however can only tell upon receipt of 200 ok back from client.
Let me know if this all makes sense and if there is something I am still missing.
Thanks again for all of the help! Sent from my Verizon Wireless BlackBerry
-----Original Message----- From: Iñaki Baz Castillo ibc@aliax.net Date: Wed, 3 Feb 2010 21:17:47 To: users@lists.kamailio.org Subject: Re: [Kamailio-Users] Loose Route / Re-Invite
El Miércoles, 3 de Febrero de 2010, Brandon Armstead escribió:
Hello everyone,
I'm just curious as to see what some of you guys do in regards to handling a Re-Invite that comes back downstream to a NATTED UAC.
For example, call scenario:
UAC -> Kamailio (Fix Nated Contact) -> PSTN
Re-Invite Occurs:
PSTN -> Kamailio -> UAC
UAC (200 OK w/ NAT RFC1918 contact) -> Kamailio (branch flags at this point are not notifying of NAT, due to the downstream direction of the INVITE, so RFC1918 address exists, but does not fix_nated_contact) -> PSTN
PSTN does not appropriately ACK.
So, what are your guys solutions for solving this problem?
Is the best way to add an attribute onto the contact header sent in original INVITE? Are there other ways of handling? What is the best, cleanest method. Possible to handle with AVP's?
Thanks in advanced for all of your input!
This is IMHO the most common approach:
- UA1 -> Kamailio (fix natted Contact and do loose routing) -> PSTN.
At this point, the dialog info of PSTN endpoint is: - target_uri: "Contact" URI fixed by Kamailio (so a public address). - route set: the IP of Kamailio (which added it in Record-Route).
So when the PSTN endpoint sends the re-INVITE it would look at follows:
INVITE sip:ua1@PUBLIC_ADDRESS_OF_UA1 SIP/2.0 Route: sip:PROXY_IP
Such INVITE is sent to the proxy (due to the presence of a Route header mirrored from the Record-Rooute in the dialog creation).
The proxy does loose routing by removing the Route header and routes the INVITE to the SIP URI present in the request line:
sip:ua1@PUBLIC_ADDRESS_OF_UA1
So the INVITE will reach ua1 as it will use the open mapping in the NAT router.
However this is not a perfect solution as the domain/host part of the original Contact URI is modified by the proxy, so such INVITE could be rejected by UA1 (it doesn't match the SIP URI it set in the original "Contact" header).
But the fact is that this "hack" works in the real world.
On 02/03/2010 03:39 PM, brandon@cryy.com wrote:
the actual problem is upon receipt of the invite to the UAC, in which it responds with 200 OK and Contact of RFC1918 address, in which is not being fix natted contact because at this point kamailio is not aware of the UAC being behind nat due to the reinvite passing the nat uac test because we can not tell with the invite coming downstream from PSTN, however can only tell upon receipt of 200 ok back from client.
So, apply the nat_uac_test() to the 200 OK.
Oh, wait. I think I understand what you're asking. Set a flag when the initial INVITE is being processed and NAT is detected; this will show up in the
When handling the initial INVITE from the customer set a flag. This will show back up on re-INVITE. Works for me.
On 02/03/2010 03:43 PM, Alex Balashov wrote:
On 02/03/2010 03:39 PM, brandon@cryy.com wrote:
the actual problem is upon receipt of the invite to the UAC, in which it responds with 200 OK and Contact of RFC1918 address, in which is not being fix natted contact because at this point kamailio is not aware of the UAC being behind nat due to the reinvite passing the nat uac test because we can not tell with the invite coming downstream from PSTN, however can only tell upon receipt of 200 ok back from client.
So, apply the nat_uac_test() to the 200 OK.
El Miércoles, 3 de Febrero de 2010, Alex Balashov escribió:
Oh, wait. I think I understand what you're asking. Set a flag when the initial INVITE is being processed and NAT is detected; this will show up in the
When handling the initial INVITE from the customer set a flag. This will show back up on re-INVITE. Works for me.
Hi, I don't understand what you mean above as a bflag only exists per transaction so it will not be available within the re-INVITE transaction.
On 02/03/2010 04:04 PM, Iñaki Baz Castillo wrote:
El Miércoles, 3 de Febrero de 2010, Alex Balashov escribió:
Oh, wait. I think I understand what you're asking. Set a flag when the initial INVITE is being processed and NAT is detected; this will show up in the
When handling the initial INVITE from the customer set a flag. This will show back up on re-INVITE. Works for me.
Hi, I don't understand what you mean above as a bflag only exists per transaction so it will not be available within the re-INVITE transaction.
Iñaki, you are correct. Sorry, I was confused looking at my config; it turns out I was thinking of the NAT bflag that comes from the registrar.
What about using add_rr_param() to indicate NAT somehow so that this flag can be fished later out of the Record-Route header / Route set on sequential requests and replies?
El Miércoles, 3 de Febrero de 2010, Alex Balashov escribió:
What about using add_rr_param() to indicate NAT somehow so that this flag can be fished later out of the Record-Route header / Route set on sequential requests and replies?
This is exactly what I use to determine if rtpproxy must be added for a re- INVITE and its response (I add ";rtpproxy=yes" in Record-Route of the initial INVITE).
However this trick is not needed at all to fix just the signalling as the "Contact" URI (so the dialog target uri) was already replaced in the initial INVITE/200, and it cannot change within a dialog.
On 02/03/2010 04:22 PM, Iñaki Baz Castillo wrote:
However this trick is not needed at all to fix just the signalling as the "Contact" URI (so the dialog target uri) was already replaced in the initial INVITE/200, and it cannot change within a dialog.
Checked the RFC, you are right.
Then, what the OP must be implying is that the PSTN UA is not following original Contact/dialog target URI bound at start of dialog and is following new Contact (with RFC1918 address) sent in re-INVITE?
El Miércoles, 3 de Febrero de 2010, Alex Balashov escribió:
On 02/03/2010 04:22 PM, Iñaki Baz Castillo wrote:
However this trick is not needed at all to fix just the signalling as the "Contact" URI (so the dialog target uri) was already replaced in the initial INVITE/200, and it cannot change within a dialog.
Checked the RFC, you are right.
Then, what the OP must be implying is that the PSTN UA is not following original Contact/dialog target URI bound at start of dialog and is following new Contact (with RFC1918 address) sent in re-INVITE?
Maybe, however it would be solved with your suggestion (inspect the "Contact" in the 200 from the natted UA and "fix" the private address.
Iñaki Baz Castillo wrote:
El Miércoles, 3 de Febrero de 2010, Alex Balashov escribió:
What about using add_rr_param() to indicate NAT somehow so that this flag can be fished later out of the Record-Route header / Route set on sequential requests and replies?
This is exactly what I use to determine if rtpproxy must be added for a re- INVITE and its response (I add ";rtpproxy=yes" in Record-Route of the initial INVITE).
However this trick is not needed at all to fix just the signalling as the "Contact" URI (so the dialog target uri) was already replaced in the initial INVITE/200, and it cannot change within a dialog.
Are you sure? IIRC the contact may change (the Route set must not change).
They call them target-refreshing requests:
12.2: ... Requests within a dialog MAY contain Record-Route and Contact header fields. However, these requests do not cause the dialog's route set to be modified, although they may modify the remote target URI. Specifically, requests that are not target refresh requests do not modify the dialog's remote target URI, and requests that are target refresh requests do.
regards klaus
El Miércoles, 3 de Febrero de 2010, Klaus Darilion escribió:
Are you sure? IIRC the contact may change (the Route set must not change).
They call them target-refreshing requests:
12.2: ... Requests within a dialog MAY contain Record-Route and Contact header fields. However, these requests do not cause the dialog's route set to be modified, although they may modify the remote target URI. Specifically, requests that are not target refresh requests do not modify the dialog's remote target URI, and requests that are target refresh requests do.
Oh my god! you are right... and I remember having a discussion about it some months/years ago in sip-implementors. True true. The question is: what is a "target refresh request"??
On 02/03/2010 05:48 PM, Iñaki Baz Castillo wrote:
El Miércoles, 3 de Febrero de 2010, Klaus Darilion escribió:
Are you sure? IIRC the contact may change (the Route set must not change).
They call them target-refreshing requests:
12.2: ... Requests within a dialog MAY contain Record-Route and Contact header fields. However, these requests do not cause the dialog's route set to be modified, although they may modify the remote target URI. Specifically, requests that are not target refresh requests do not modify the dialog's remote target URI, and requests that are target refresh requests do.
Oh my god! you are right... and I remember having a discussion about it some months/years ago in sip-implementors. True true. The question is: what is a "target refresh request"??
Seems like it modifies the RURI that sequential requests take, but not the route set, as it says?
El Miércoles, 3 de Febrero de 2010, Klaus Darilion escribió:
Are you sure? IIRC the contact may change (the Route set must not change).
They call them target-refreshing requests:
12.2: ... Requests within a dialog MAY contain Record-Route and Contact header fields. However, these requests do not cause the dialog's route set to be modified, although they may modify the remote target URI. Specifically, requests that are not target refresh requests do not modify the dialog's remote target URI, and requests that are target refresh requests do.
1.upto(1000) do puts "I'll always check RFC 3261 before assuring anything" end
El Miércoles, 3 de Febrero de 2010, Alex Balashov escribió:
On 02/03/2010 03:39 PM, brandon@cryy.com wrote:
the actual problem is upon receipt of the invite to the UAC, in which it responds with 200 OK and Contact of RFC1918 address, in which is not being fix natted contact because at this point kamailio is not aware of the UAC being behind nat due to the reinvite passing the nat uac test because we can not tell with the invite coming downstream from PSTN, however can only tell upon receipt of 200 ok back from client.
So, apply the nat_uac_test() to the 200 OK.
This is not required to be "fixed" as the remote target cannot change within a dialog.
El Miércoles, 3 de Febrero de 2010, brandon@cryy.com escribió:
I do see all the behavior as referenced, however the actual problem is upon receipt of the invite to the UAC, in which it responds with 200 OK and Contact of RFC1918 address, in which is not being fix natted contact because at this point kamailio is not aware of the UAC being behind nat due to the reinvite passing the nat uac test because we can not tell with the invite coming downstream from PSTN, however can only tell upon receipt of 200 ok back from client.
Let me know if this all makes sense and if there is something I am still missing.
I don't get still what you mean. With the approach I told in my previos message communication is possible for all the re-INVITE's (coming from the PSTN or from the UA behind NAT).
Thinking about this a little more, I am not sure I understand the issue, perhaps because the original post is confusing.
Correct me if I'm wrong:
1) If initial INVITE is from NAT'd user to PSTN, when INVITE is received by proxy its Contact is fixed up and it is passed along.
So, replies and sequential requests from PSTN should go to fixed up target URI (mangled Contact URI from client-side INVITE).
2) If initial INVITE is from PSTN to NAT'd user, replies with Contact from NAT'd client are fixed up by proxy and passed along to PSTN. Sequential requests from PSTN go to new, mangled target URI, including re-INVITEs.
Contact 200 OK or other response to re-INVITE from client is fixed up as well, no?
What am I missing?
-- Alex
On 02/03/2010 04:06 PM, Iñaki Baz Castillo wrote:
El Miércoles, 3 de Febrero de 2010, brandon@cryy.com escribió:
I do see all the behavior as referenced, however the actual problem is upon receipt of the invite to the UAC, in which it responds with 200 OK and Contact of RFC1918 address, in which is not being fix natted contact because at this point kamailio is not aware of the UAC being behind nat due to the reinvite passing the nat uac test because we can not tell with the invite coming downstream from PSTN, however can only tell upon receipt of 200 ok back from client.
Let me know if this all makes sense and if there is something I am still missing.
I don't get still what you mean. With the approach I told in my previos message communication is possible for all the re-INVITE's (coming from the PSTN or from the UA behind NAT).
El Miércoles, 3 de Febrero de 2010, Alex Balashov escribió:
Thinking about this a little more, I am not sure I understand the issue, perhaps because the original post is confusing.
Correct me if I'm wrong:
- If initial INVITE is from NAT'd user to PSTN, when INVITE is received
by proxy its Contact is fixed up and it is passed along.
So, replies and sequential requests from PSTN should go to fixed up target URI (mangled Contact URI from client-side INVITE).
- If initial INVITE is from PSTN to NAT'd user, replies with Contact
from NAT'd client are fixed up by proxy and passed along to PSTN. Sequential requests from PSTN go to new, mangled target URI, including re-INVITEs.
Right.
Contact 200 OK or other response to re-INVITE from client is fixed up as well, no?
It could, but it's not required as target uri cannot change after the dialog is established.
This is: upon dialog creation both UA's must send in-dialog requests to the proxy (if it did loose routing) with the RURI pointing to the target uri (set in the initial INVITE/200 by inspecting Contact headers). The Contact in a re- INVITE or its response doesn't matter.
Regards.
El Miércoles, 3 de Febrero de 2010, Iñaki Baz Castillo escribió:
It could, but it's not required as target uri cannot change after the dialog is established.
This is: upon dialog creation both UA's must send in-dialog requests to the proxy (if it did loose routing) with the RURI pointing to the target uri (set in the initial INVITE/200 by inspecting Contact headers). The Contact in a re- INVITE or its response doesn't matter.
Ref:
12.1.2 UAC Behavior -------------------- When a UAC receives a response that establishes a dialog, it constructs the state of the dialog. ... The remote target MUST be set to the URI from the Contact header field of the response. --------------------
On 02/03/2010 04:25 PM, Iñaki Baz Castillo wrote:
This is: upon dialog creation both UA's must send in-dialog requests to the proxy (if it did loose routing) with the RURI pointing to the target uri (set in the initial INVITE/200 by inspecting Contact headers). The Contact in a re- INVITE or its response doesn't matter.
I agree; the RFC is very clear about this. But, I have definitely encountered broken UAs that do not do this and have had to work around it by fixing up Contact headers in sequential INVITEs anew.
Hi Brandon!
This is my pragmatic approach:
During dialog-creating transaction (INVITE, SUBSCRIBE) I decide if a clients gets NAT-traversal* or not. Thus result will be stored in a record-route cookie (add_rr_param()).Therefore, when dooing loose_route I will check the content of this parameter and therefor apply same strategy to in-dialog requests.
* perform NAT traversal always, unless I know for sure that the client does not support symmetric SIP. For doing NAT traversal you can either use fix_nated_contact() - which is not standard conform but works - or use the new add_contact_alias/handle_ruri_alias (kamailio 3.0: http://sip-router.org/docbook/sip-router/branch/master/modules_k/nathelper/n...)
regards klaus
Brandon Armstead wrote:
Hello everyone,
I'm just curious as to see what some of you guys do in regards to handling a Re-Invite that comes back downstream to a NATTED UAC.
For example, call scenario:
UAC -> Kamailio (Fix Nated Contact) -> PSTN
Re-Invite Occurs:
PSTN -> Kamailio -> UAC
UAC (200 OK w/ NAT RFC1918 contact) -> Kamailio (branch flags at this point are not notifying of NAT, due to the downstream direction of the INVITE, so RFC1918 address exists, but does not fix_nated_contact) -> PSTN
PSTN does not appropriately ACK.
So, what are your guys solutions for solving this problem?
Is the best way to add an attribute onto the contact header sent in original INVITE? Are there other ways of handling? What is the best, cleanest method. Possible to handle with AVP's?
Thanks in advanced for all of your input!
Sincerely, Brandon
Kamailio (OpenSER) - Users mailing list Users@lists.kamailio.org http://lists.kamailio.org/cgi-bin/mailman/listinfo/users http://lists.openser-project.org/cgi-bin/mailman/listinfo/users
Klaus Darilion writes:
- perform NAT traversal always, unless I know for sure that the client
does not support symmetric SIP. For doing NAT traversal you can either use fix_nated_contact() - which is not standard conform but works - or use the new add_contact_alias/handle_ruri_alias (kamailio 3.0: http://sip-router.org/docbook/sip-router/branch/master/modules_k/nathelper/n...)
here are the instructions in case someone missed them earlier.
-- juha
add_contact_alias()/handle_ruri_alias() usage example -----------------------------------------------------
supports re-use of tcp sessions between proxy and UAs. supports routing of requests to UAs behind NATs so that r-uri is always what UAs expect. proxying of media is not shown, but can be easily added.
NON_REGISTER_INITIAL_REQUESTS -----------------------------
- call alias_contact() for all non-register initial requests, which don't come from another proxy (which takes care of its own UAs).
- if you know that non-register initial request is going to another proxy, set TO_PROXY flag before relaying the request.
- in cases, where initial request may go to another proxy, but you are not sure about it, store the number of record-route headers in incoming request in an AVP that you can then later test in onreply route and find out, if next hop was a proxy.
route [NON_REGISTER_INITIAL_REQUESTS] {
if (!is_present_hf("Record-Route")) { route(ADD_CONTACT_ALIAS); }; ... if (I_KNOW_FOR_SURE_THAT_NEXT_HOP_IS_ANOTHER_PROXY) { setbflag("TO_PROXY"); };
if (NEXT_HOP_MAY_BE_ANOTHER_PROXY_BUT_I_DONT_KNOW_FOR_SURE) { $avp("rr_count") = $rr_count; }; t_on_reply("REPLY"); if (!t_relay()) ...
route [ADD_CONTACT_ALIAS] { if (!add_contact_alias()) { xlog("L_ERR", "Error in aliasing contact <$ct>\n"); send_reply("400", "Bad request"); exit; }; }
REGISTER_REQUESTS -----------------
- call fix_nated_register() on register requests, if registering ua is behind nat OR is using tcp.
route [REGISTER_REQUESTS] { ... if (isflagset(FROM_NATED) || (proto == TCP)) { fix_nated_register(); if (isflagset(FROM_NATED)) { setbflag("TO_NATED"); }; }; save("location"); ...
IN_DIALOG_REQUESTS ------------------
- call alias_contact() for all in-dialog requests that don't come from another proxy.
- call handle_ruri_alias() for all in-dialog requests before t_relaying them to UAs. next hop is an UA if loose_route() didn't set $du. if next hop is a proxy, set TO_PROXY flag.
route [IN_DIALOG_REQUESTS] {
if (@via[2] == "") { route(ADD_CONTACT_ALIAS); } loose_route(); if ($du == "") { handle_ruri_alias(); switch ($rc) { case -1: xlog("L_ERR", "Failed to handle alias of R-URI <$ru>\n"); send_reply("400", "Bad request"); exit; case 1: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$du>\n"); break; case 2: xlog("L_INFO", "Routing in-dialog $rm from <$fu> to <$ru>\n"); break; }; } else { setbflag("TO_PROXY"); } t_on_reply("REPLY"); if (!t_relay()) { ...
REPLIES -------
- call add_contact_alias() on all replies except the ones that come from another proxy.
onreply_route [REPLY] {
if (!isbflagset("TO_PROXY") { if (is_avp_set("$avp(rr_count)")) { if ($rr_count == $avp(rr_count) + $rr_top_count) { route(ADD_CONTACT_ALIAS); }; } else { route(ADD_CONTACT_ALIAS); } } ...
NOTE ----
- do NOT call fix_nated_contact() on anything, because add_contact_alias() replaces it.