Hi Richard!
On 22.06.2012 01:33, Richard Brady wrote:
Hi folks
I've configured Kamailio as a simply multi-homed proxy offering NAT traversa, TCP connection management, etc to FreeSWICH behind it. FreeSWITCH acts as the registrar.
I'm trying to understand the default config and the following things don't make sense to me (I can't find documentation on these):
- The nat=yes flag. What does it mean exactly and why is it on the RR
and not on the Contact/R-URI? Also, when double RR is enabled, why does it get added to both headers?
Kamailio is not dialog-stateful. Thus, when routing an in-dialog request, Kamailio does not know if a media-relay was activated with the initial INVITE. Thus, a "record-route cookie" is used to store the information for the whole dialog.
The proper location (contact or RR) depends on the exact meaning of nat=yes, e.g. it only signal if a media relay is used or also if the client needs NAT-traversal for SIP. In the first case it is a property of the call, in the later case it is a property of the caller/callee. Thus, in the later the contact/RURI would be fine too - but there are also other aspects: for example a call is routed via 2 SIP providers. If both store data in the contact/RURI, then both use the same data location and may confuse the other SIP proxy. If you store the cookie in the RR/Route header, then the cookie will only be interpreted by the proxy which inserted the cookie.
Regarding RR: This is just an implementation thing. IIRC the topmost RR is just ignored and the second (which is relevant as it defines the outgoing socket) is used - but depending of the direction of the request you need the cookie in both Route headers.
Thus, as you see there is not a single "correct" version to do it, but this one seems to work fine.
In the early days I had an "academic" approach and activated NAT-traversal (RTP and SIP) only when really needed and stored the data more detailed using for example: nat=both, nat=caller, nat=callee and nat=none. It was nice and worked - but nowadays I choose the pragmatic approach: always enforce NAT-traversal for SIP (never trust any data provided by the client) and always activate a media relay (less support calls for customers with strange NAT routers and possibility for legal intercept). Thus, in a pragmatic approach the parameter is not needed anymore.
- The FLT_NATS and FLB_NATB flags. I'd like to know what this stands
for, I guess "flag for transaction - NAT" and "flag for branch - NAT" but what do the S and the B stand for? More importantly what do these
IIRC: s....script b....branch
flags mean? Is it correct to say that the first indicates the UAC / A-leg / requester is behind NAT and the second that the UAS / B-leg / responder is behind NAT?
yes. There can be multiple Bs (forking), thus the NAT information must be stored in a branch-flag.
In the the NATMANAGE route of the default config we have:
if (is_request()) { if(has_totag()) { if(check_route_param("nat=yes")) { setbflag(FLB_NATB); } } }
Which to me means "if the message is a request inside an existing dialog ..." and I'm thinking, isn't this a bit late in the dialog to be setting NAT flags?
No. The idea is to make NAT checks on the first INVITE, then store the results in RR-cookies. During in-dialog requests you rely on the cookies.
I would expect to set the flag for the A-leg on the incoming request, and the flag for the B-leg on the incoming reply. I can't point in waiting for the ACK to try and work out whether this leg is behind NAT. And also it seem this set of if statements will also match incoming requests from the A-leg, so why are we setting a brach flag? Does that leg also also get the properties of a branch?
For in-dialog requests it is not about A (caller) and B (callee) but more about "sender of the request" and "receiver of the request". I guess in this case it is setting the branch-flag as the existing logic for NAT traversal (during inital INVITE) is triggered on this certain branch flag. Thus, by setting this specific branch flag the existing code can be reused for in-dialog requests.
- When I get a 200 OK coming from behind NAT it is not subjected to
fix_nated_contact(), and this seems to be because it doesn't have the FLB_NATB flag set:
if (is_reply()) { if(isbflagset(FLB_NATB)) { fix_nated_contact(); } }
When processing the initial INVITE, the lookup() function returns the destination addresses of all Bs and if these Bs need NAT traversal (by setting the FLB_NATB flag for the respective branches. This flag is also available during response processing. And if set, the contact will be fixed.
Thus, if the clients needs NAT traversal, but NAT traversal is not done, this indicates that the FLB_NATB flag was not set for this client during lookup(), which indicates that the NAT flag was not set when the save() function was called which indicates that the NAT-detection logic in REGISTER handling did not detected that NAT traversal is needed.
regards Klaus