[sr-dev] Playing with TCP
Klaus Darilion
klaus.mailinglists at pernau.at
Thu Oct 25 19:05:59 CEST 2012
Hi Olle!
On 25.10.2012 17:00, Olle E. Johansson wrote:
> Setup:
>
> One kamailio behind a NAT, one on public IP.
>
> I register a client using the inside Kamailio as an outbound proxy.
> It adds a path header and forwards over TCP to the public server.
> This server saves the registration with the path header and send a
> response, which reaches the client fine.
>
> Calling from the client to it's own number, the INVITE is sent over
> the inside proxy to the outside, it looks up the location database
> then drops the request. It doesn't realize that it has a TCP
> connection it can reuse open. The error message - a timeout - is sent
> back over the connection.
>
> In my dream world, the server would reuse the open TCP connection to
> get back across the NAT. If we can get the response across, we should
> be able to get a new request back.
Kamailio uses the next hop target (probably the URI in the Path header)
and searches for open TCP connections to this target. I guess the Path
header contains the private IP address of the outbound proxy, thus it
does not match the open TCP connection. If there is not outboundproxy,
the solution is simple: as always use fix_nated_register() on REGISTER.
Then, after lookup() the proxy will search for a TCP connection to the
"received" IP:port and find and uses the existing connection.
With the additional proxy, things get more complex.
I see 3 solutions:
1. The outbound proxy announces public IP:port address in the path
header and the NAT has a static port forwarding of this port to the
outbound proxy
2. The outbound proxy announces the ephemeral public IP:port address in
the path header. Eg. open a TCP connection to the proxy, use STUN to get
the public mapping and use it in the Path header (probably needs some
code changes)
3. Use Klaus' pragmatic and secure approach: I guess in this setup the
outbound proxy is in the user's domain, not in the proxy provider's
domain. Thus, I (the proxy provider) does not any user provided data -
the user could write anything into the Path header (eg. the IP address
of my internal gateway). It just remember where the REGISTER came from
(IP:port) and send INVITEs to this IP:port. (aka applying NAT traversal
all the time).
If I read Path support in registrar module correct, on lookup the Path
always overrides the "received" socket information with the loaded
route-set. Thus, you have to either change registrar module to have this
a config option (probably the implementation was a bit short sighted and
did not expected the outbound proxy to be behind NAT) or to manually
override $du after lookup, e.g:
for REGISTER:
fix_nated_register();
for INVITE to user:
lookup(...);
reg_fetch_contacts("location", "$ou", "callee");
$du=$(ulc(callee=>received));
reg_free_contacts("callee");
Of course this is problematic with forking scenarios.
Generally one has to differ who operates the outbound proxy of the user.
If it is the user, then the user is responsible for NAT traversal.
regards
Klaus
PS: I just had an idea of a 4th workaround
on REGISTER add another PATH header on top of the existing ones with the
URI pointing to sip:$si:$sp;transport=$pr
insert_hf("Path: <sip:$si:$sp;transport=$pr>\r\n", "Path");
msg_apply_changes();
save();
on lookup(), the $du is set to the public IP:port, but there is the fake
Route target which should be removed. This is complex as there can be
multiple Route headers.
I think the way to go is to update registrar module to not use the Path
header target as $du but the received column (make it a module option).
... ops ... one more idea:
I think the easiest solution is to put another proxy in front of the
registrar:
user <-> user-obp <-NAT-> ITSP-obp <-> registrar.
In this case you just have to use on the ITSP-obp:
add_path_received() for REGISTER, and
modparam("path", "use_received", 1)
I think it is not necessary to set
modparam("registrar", "path_use_received", 1) on the registrar (actually
I am not sure what this parameter does).
regards
Klaus
> Now, I don't know the inner workings of TCP connection handling here.
> I guess I should test having the client open a connection directly to
> the outside proxy and see if that works.
>
> Would it be possible with the current architecture to get Kamailio to
> reuse an existing TCP connection like this?
>
> I started digging down the TCP code, but lost attention because of
> the complexity and fixed speling erors in other parts instead... Will
> try again.
>
> /O _______________________________________________ sr-dev mailing
> list sr-dev at lists.sip-router.org
> http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
>
More information about the sr-dev
mailing list