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):
1. 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.
2. 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.
3. 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.
4. 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