I can't quite agree that you need two servers for the job and this is
proven to be true by my test setup. Following is how it works:
1. Network setup is as follows:
private public
UA1 NAT SER UA2
[ ]---------{ }--------< >---[ ]
2. SER configured as follows:
route {
if (search("User-Agent: Cisco ATA.*")) {
add_rport();
fix_nated_contact();
};
rewriteFromRoute();
[REGISTRATION STUFF STRIPPED]
if (method=="INVITE") {
addRecordRoute();
};
t_on_positive("1")
# forward to current uri now
if (!t_relay()) {
sl_reply_error();
};
}
reply_route[1] {
if (search("Server: Cisco ATA.*") {
fix_nated_contact();
}
}
3. Registration
When registration request from UA1 arrives, we add received and rport
into the first Via field, which allows us to properly route reply
later on and also we rewrite Contact field with real IP:PORT,
therefore registration information is correct and we can contact UA1
if necessary. By selecting a small registration expiration interval on
UA1 it is possible to keep the nat binding alive.
4. Call from UA1 to UA2
- UA1 send INVITE request to SER. This request is passed through
add_rport() and fix_nated_contact()
- SER replies with 100 Trying to UA1 to the correct address/port due
to received/rport added on the previous step
- SER forwards INVITE request to UA1 with RecordRoute and
rport/received added and Contact fixed
- UA2 replies with 100 Trying. The response contains the second Via
field with correct received/rport, but it doesn't matter since reply
ignored anyway
- UA2 replies with 180 Ringing. The response contains the second Via
field with correct received/rport allowing to forward it properly
- SER forwards 180 Ringing to UA1
- When the user picks up the phone, UA2 replies with 200 OK, again it
contains proper received/rport in the second Via field
- SER forwards 200 OK to UA1
- UA1 replies to SER with ACK, upon receiving it SER inserts
received/rport into the first Via field
- SER forwards ACK to UA2
[call in progress]
- When the user at UA2 hangs us, UA2 seds a BYE to SER with Route
filled with real IP:PORT of the UA1 from the Contact field it received
in the original INVITE
- SER forwards BYE to UA1 using IP:PORT from Route field
- UA1 replies with 200 OK to SER
- SER forwards 200 OK reply to UA2
5. Call from UA2 to UA1
- UA2 send INVITE request to SER
- SER replies with 100 Trying to UA2
- SER looks up into registration database and forwards INVITE to UA1
with RecordRoute added
- UA1 replies with 100 Trying. Received/rport added into the first Via
field, but it doesn't matter since reply ignored anyway
- UA1 replies with 180 Ringing. Received/rport added into the first
Via field, but it doesn't really matter
- SER forwards 180 Ringing to UA1
- When the user picks up the phone, UA1 replies with 200 OK. Contact
field is fixed in reply_route[1]
- SER forwards 200 OK to UA2
- UA2 replies to SER with ACK, Route field is is filled with IP:PORT
from the Contact field in 200 OK
- SER forwards ACK to UA1 using IP:PORT from Route field
[call in progress]
- When the user at UA2 hangs us, UA2 sends a BYE to SER with Route
filled with real IP:PORT of the UA1 from the Contact field it received
in the original 200 OK
- SER forwards BYE to UA1 using IP:PORT from Route field
- UA1 replies with 200 OK to SER
- SER forwards 200 OK reply to UA2
As you can see, as long as signalling concerned, it is possible to
reliably traverse NAT without any additional servers. Of course this
requires a reliable way to determine that a client supports symmetric
signalling. In our particular case, it is done by searching for
"Server: Cisco ATA.*" or "User-Agent: Cisco ATA.*"
-Maxim
Jiri Kuthan wrote:
Few more notes on this construct:
a it takes two servers in series; the first one in chain makes the
NAT fixing job, the other one acts as proxy/registrar; the reason is
the NAT changes to a request are only used to generate outoging request
and do not affect registrar; thus, you first need to send the updated
request out; one could still have only one server running (be it easier
or not) with a routing policy, which makes the request pass the same
server in two rounds -- first one de-natifying, the second real one
b it takes generating symmetric replies and accepting rport in relayed
replies -- I think that is a reasonable thing to add to ser core
c the routing policy needs to be set up in such a way, the de-natifying
instance of SER is always in the path -- otherwise subsequent inbound
requests would be routed based-on Contact directly to NAT, would not
use symmetric path opened by initial REGISTERs and fail;
the denatifier thus needs to use record-routing
d for the same reason, all initial inbound requests to natted users proxied
by the main server need to be statically routed to the de-natifier
-Jiri
the examples bellow demonstrate in ascii charts some more details;
A:B is address:port of natted phone, X:Y the natted A:B, C:D that of
denatifier
network setting:
fone F: A:B NAT N: X:Y proxy D proxy P
~
/------\ ~ /-------------\ /--------------\
|phone | -------->~----------->|denattifying |--------------->|registrar/ |
\------/ ~ |ser/outbound | |inbound proxy |
~ |proxy | \--------------/
\-------------/\ ^
\ /
\----> outbound /
domains
1) registers go from F, are rewritten by D and processed at P
2) INVITEs from F visit D, Contact is rewritten, rport is introduced,
request is record-routed, so that other party's request visit D too;
3) INVITEs from outside visit first P, contacts rewritten previously
by D are put in r-uri, requests are forwarded statically to D,
and D forwardes by uri to the fone F
At 06:27 PM 1/10/2003, Maxim Sobolev wrote:
On Fri, Jan 10, 2003 at 03:37:46PM +0200, Maxim
Sobolev wrote:
Sounds reasonably - I'll do it that way.
I am planning add a new nathelper module, which will export the
following functions:
add_rport() - insert a rport= parameter into the first Via field
fix_nated_contact() - replaces host:port in Contact field with host:port
we received this message from
add_direction_passive() - adds direction=passive option to the SDP
Then it would be possible to do the following at the very top of config
before any other REGISTER/INVITE processing:
if (method == "INVITE" || method == "REGISTER") {
if (search("User-Agent: Cisco ATA.*") {
add_rport();
if (method == "INVITE") {
add_direction_passive();
};
if (method == "REGISTER") {
fix_nated_contact();
};
};
};
Does it sound reasonably for you?
-Maxim
Thanks!
-Maxim
On Fri, Jan 10, 2003 at 02:15:11PM +0100, Jan Janak wrote:
On 10-01 14:32, Maxim Sobolev wrote:
> Folks,
>
> I need an advise on how to better implement one feature, which isn't
> currently present in SER. We need to allow UAs behind NAT properly
> register with the registrar - by "properly" I mean that host:port portion
> of URI in Contact field should not be used, but host:port the request
> came from should be used instead. By definition we know that those UAs
> will support symmetric SIP signalling, so that this scheme will work just
> fine.
>
> In my opinion there are two ways to do it: either add new rewritecontact*
> family of functions similar to rewritehost ones. or add a new flag for
> the save() function. This is where I need your help - which implementation
> looks better for you (or maybe you have even some better idea), since
> we are really interested in inclusion of our changes into the mainline to
> reduce our local hacks.
>
This should be implemented as a standalone module for ser. I want to keep
registrar clean, it should not be aware of NATs. So, create a new module
for ser that will contain all the NAT traversal helper functions, the
functions will be then called from the config script.
That includes modifications of contact, adding rport to Via and so on.
regards, Jan.
_______________________________________________
Serusers mailing list
serusers(a)lists.iptel.org
http://lists.iptel.org/mailman/listinfo/serusers
_______________________________________________
Serusers mailing list
serusers(a)lists.iptel.org
http://lists.iptel.org/mailman/listinfo/serusers
--
Jiri Kuthan
http://iptel.org/~jiri/