Andrei,
Hello
I have following use case:
Endpoint1 <------> NAT <------> SER <------> NAT <------> Endpoint2 10.0.0.10 TCP TCP 192.168.0.4
First of all try to use UDP. NAT traversal works with UDP. Nobody really tested it with TCP. Theoretically you could get it working with unstable ser, special options and a well behaved UA (one that will always reuse the tcp connections and will keep the nat bindings open).
I have been using UDP for kphone and it alvays works fine. But I use Windows Messenger too and it seems to me that the TCP is the only possibility to connect it from a NAT-ed network.
Yes, ser cannot find an open tcp connection and tries to open a new one. To get arround this you should force tcp aliases and use a very high timeout for the tcp connections (if a connection is not used, ser will close it after some time):
- use tcp_accept_aliases=yes in your ser.cfg if you have compliant UAs (I think only kphone knows about them)
- use force_tcp_alias(); if your UAs don't know about tcp alias.
- edit tcp_conn.h and change TCP_CON_TIMEOUT and TCP_CON_SEND_TIMEOUT to a very high value
I changed the constants and now the connections are permanent. But I still haven't solved the problem routing messages. Here is a snippet of code from my cfg file:
if (uri==myself) { if (method=="REGISTER") { # digest authentication if (!www_authorize("i-tel.sk", "subscriber")) { log(1, "Authorization failed\n"); www_challenge("i-tel.sk", "0"); log(1, "www_challenge sent\n"); break; };
# symmetric but don't advertise it -- force use of rport if (client_nat_test("3")) { log(1, "Client is behind a NAT\n"); if (! search("^Record-Route:")) { fix_contact(); force_rport(); }; };
log(1, "Forcing tcp alias\n"); force_tcp_alias();
save("location"); break; }; };
My undersanding is that the function force_tcp_alias() should add the source port of the tcp connection to the list of aliases. Then later existing connections are searched by userid and port to be reused. Please correct me if I'm wrong.
In my case it doesn't work, I found the following message in the log:
tcpconn_add_alias: alias port 5060 for hash 17, id 1
so it tries to add the port 5060 insted of the source port.
Martin
On May 31, 2004 at 13:29, Martin Rusnak mafo@cyberspace.sk wrote:
Andrei,
Hello
I have following use case:
Endpoint1 <------> NAT <------> SER <------> NAT <------> Endpoint2 10.0.0.10 TCP TCP 192.168.0.4
First of all try to use UDP. NAT traversal works with UDP. Nobody really tested it with TCP. Theoretically you could get it working with unstable ser, special options and a well behaved UA (one that will always reuse the tcp connections and will keep the nat bindings open).
I have been using UDP for kphone and it alvays works fine. But I use Windows Messenger too and it seems to me that the TCP is the only possibility to connect it from a NAT-ed network.
At least older WM version allow you to choose the protocol (Accounts/Advanced/Connect using: ....).
Yes, ser cannot find an open tcp connection and tries to open a new one. To get arround this you should force tcp aliases and use a very high timeout for the tcp connections (if a connection is not used, ser will close it after some time):
- use tcp_accept_aliases=yes in your ser.cfg if you have compliant UAs (I think only kphone knows about them)
- use force_tcp_alias(); if your UAs don't know about tcp alias.
- edit tcp_conn.h and change TCP_CON_TIMEOUT and TCP_CON_SEND_TIMEOUT to a very high value
I changed the constants and now the connections are permanent. But I still haven't solved the problem routing messages. Here is a snippet of code from my cfg file:
if (uri==myself) { if (method=="REGISTER") { # digest authentication if (!www_authorize("i-tel.sk", "subscriber")) { log(1, "Authorization failed\n"); www_challenge("i-tel.sk", "0"); log(1, "www_challenge sent\n"); break; };
# symmetric but don't advertise it -- force use of rport if (client_nat_test("3")) { log(1, "Client is behind a NAT\n"); if (! search("^Record-Route:")) { fix_contact(); force_rport(); }; }; log(1, "Forcing tcp alias\n"); force_tcp_alias(); save("location"); break;
}; };
Make sure you do the nat tests/modification for the other requests and replies (not only for REGISTER). Start with a config that worked for udp.
Also note that rport is not so important for tcp. In fact if your tcp connections are not closed, rport is not needed (it willnot be used). The replies are always sent through the same tcp connection the original request came through, if the connection is still alive (using the "i" parameter which is added to the Via header of forwarded tcp requests).
My undersanding is that the function force_tcp_alias() should add the source port of the tcp connection to the list of aliases. Then later existing connections are searched by userid and port to be reused. Please correct me if I'm wrong.
No, force_tcp_alias adds the via port to the aliases list. The connection is identified by (ip_address, source_port). force_tcp_alias adds an alias (ip_address, via_port) for (ip_address, source_port).
In my case it doesn't work, I found the following message in the log:
tcpconn_add_alias: alias port 5060 for hash 17, id 1
so it tries to add the port 5060 insted of the source port.
It's ok, see above.
Andrei
if (uri==myself) { if (method=="REGISTER") { # digest authentication if (!www_authorize("i-tel.sk", "subscriber")) { log(1, "Authorization failed\n"); www_challenge("i-tel.sk", "0"); log(1, "www_challenge sent\n"); break; };
# symmetric but don't advertise it -- force use of rport if (client_nat_test("3")) { log(1, "Client is behind a NAT\n"); if (! search("^Record-Route:")) { fix_contact(); force_rport(); }; };
log(1, "Forcing tcp alias\n"); force_tcp_alias();
save("location"); break; }; };
Make sure you do the nat tests/modification for the other requests and replies (not only for REGISTER). Start with a config that worked for udp.
Also note that rport is not so important for tcp. In fact if your tcp connections are not closed, rport is not needed (it willnot be used). The replies are always sent through the same tcp connection the original request came through, if the connection is still alive (using the "i" parameter which is added to the Via header of forwarded tcp requests).
My undersanding is that the function force_tcp_alias() should add the source port of the tcp connection to the list of aliases. Then later existing connections are searched by userid and port to be reused. Please correct me if I'm wrong.
No, force_tcp_alias adds the via port to the aliases list. The connection is identified by (ip_address, source_port). force_tcp_alias adds an alias (ip_address, via_port) for (ip_address, source_port).
I had another problem: there was always private address in contact of the TCP users behind NAT. The problem was that the function fix_contact() from module mediaproxy works only for the UDP requests. So I modified the source file modules/mediaproxy/functions.h, commented out the statement on line 116:
// if (uri.proto != PROTO_UDP && uri.proto != PROTO_NONE) // return -1;
Now the TCP routing works correctly.
On May 31, 2004 at 20:39, Martin Rusnak mafo@cyberspace.sk wrote:
if (uri==myself) { if (method=="REGISTER") { # digest authentication if (!www_authorize("i-tel.sk", "subscriber")) { log(1, "Authorization failed\n"); www_challenge("i-tel.sk", "0"); log(1, "www_challenge sent\n"); break; };
# symmetric but don't advertise it -- force use of rport if (client_nat_test("3")) { log(1, "Client is behind a NAT\n"); if (! search("^Record-Route:")) { fix_contact(); force_rport(); }; };
log(1, "Forcing tcp alias\n"); force_tcp_alias();
save("location"); break; }; };
Make sure you do the nat tests/modification for the other requests and replies (not only for REGISTER). Start with a config that worked for udp.
Also note that rport is not so important for tcp. In fact if your tcp connections are not closed, rport is not needed (it willnot be used). The replies are always sent through the same tcp connection the original request came through, if the connection is still alive (using the "i" parameter which is added to the Via header of forwarded tcp requests).
My undersanding is that the function force_tcp_alias() should add the source port of the tcp connection to the list of aliases. Then later existing connections are searched by userid and port to be reused. Please correct me if I'm wrong.
No, force_tcp_alias adds the via port to the aliases list. The connection is identified by (ip_address, source_port). force_tcp_alias adds an alias (ip_address, via_port) for (ip_address, source_port).
I had another problem: there was always private address in contact of the TCP users behind NAT. The problem was that the function fix_contact() from module mediaproxy works only for the UDP requests. So I modified the source file modules/mediaproxy/functions.h, commented out the statement on line 116:
// if (uri.proto != PROTO_UDP && uri.proto != PROTO_NONE) // return -1;
Now the TCP routing works correctly.
You would need also some kind of nat ping for tcp, or to configure your UA to send periodically messages (if possible), to keep the nat binding alive.
Andrei
At 08:52 PM 5/31/2004, Andrei Pelinescu-Onciul wrote:
You would need also some kind of nat ping for tcp, or to configure your UA to send periodically messages (if possible), to keep the nat binding alive.
Actually I would be surprised if today's TCP clients were able to deal with NATs very well. It takes persistent TCP connections. In addition to keeping NAT bindings alive, the clients should also reconnect and re-REGISTER if TCP connection closes. This may happen due to a variety of reasons: temporary network failures (NAT reboot), exhausted TCP connections on server side, or server reboot.
-jiri