i started to test the latest sr_3.0 that includes andrei's tcp/socket related changes.
twinkle is registered over tcp to sr using source port 59056 destination port 5060. in contact uri twinkle has put port 5074 (i need to configure some fixed port there).
when another ua calls twinkle and i see this in syslog:
Nov 6 07:16:21 localhost /usr/sbin/sip-proxy[30133]: INFO: Routing first INVITE to sip:jh_test_fi@192.98.101.10:5074;transport=tcp and <<null>> Nov 6 07:16:21 localhost /usr/sbin/sip-proxy[30133]: INFO: <core> [tcp_main.c:1928]: tcp_send: quick connect for 0xb54f3e60
when i look wireshark output, i see that sr has created a new tcp connection to twinkle at port 5074 even when there is already is one, but not to that port.
is this twinkle's fault, i.e., should it put in contact uri port 59056 instead?
or should sr figure out that twinkle in fact is behind the tcp connection it created when it registered itself no matter what the port in contact uri is?
-- juha
On Nov 06, 2009 at 08:12, Juha Heinanen jh@tutpro.com wrote:
i started to test the latest sr_3.0 that includes andrei's tcp/socket related changes.
twinkle is registered over tcp to sr using source port 59056 destination port 5060. in contact uri twinkle has put port 5074 (i need to configure some fixed port there).
when another ua calls twinkle and i see this in syslog:
Nov 6 07:16:21 localhost /usr/sbin/sip-proxy[30133]: INFO: Routing first INVITE to sip:jh_test_fi@192.98.101.10:5074;transport=tcp and <<null>> Nov 6 07:16:21 localhost /usr/sbin/sip-proxy[30133]: INFO: <core> [tcp_main.c:1928]: tcp_send: quick connect for 0xb54f3e60
when i look wireshark output, i see that sr has created a new tcp connection to twinkle at port 5074 even when there is already is one, but not to that port.
is this twinkle's fault, i.e., should it put in contact uri port 59056 instead?
Yes, it should do either that, or add an alias parameter to its Via (assuming that the port in Via _is_ 5074). If it does add "alias" to the Via, make sure you have tcp_accept_aliases=yes in the config.
or should sr figure out that twinkle in fact is behind the tcp connection it created when it registered itself no matter what the port in contact uri is?
You can force that, using force_tcp_alias() (adds src_ip:port_in_via as an alias for src_ip:src_port). If the port in Via is not 5074 then you can work around that too, using force_tcp_alias(5074) (based maybe on looking at the contact?), but in this case it's better to reconfigure/fix twinkle.
In general, especially if you have NATed UACs, it's better to always have force_tcp_alias() in the config. It will cause problems only if you have non-NATed broken UACs that don't expect/support symmetric signalling over TCP (e.g. open a new connection for each new request and expect only replies to that request on the connection). OTOH if you don't force_tcp_alias() and the UACs don't add alias to the Via, it's a very slim chance that NATed UACs will work over tcp.
BTW: this is not a change introduced by my recent tcp force_send_socket() change. This is the way tcp always worked. The force_send_socket() change forces the ip of the forced socket. The difference from k behaviour is that k did that only when opening a new connection (if an existing connection did exist albeit with a different src_ip, it would have been used) while sr will reuse a connection only if the src_ip matches with that of the forced socket.
Andrei
Andrei Pelinescu-Onciul writes:
Yes, it should do either that, or add an alias parameter to its Via (assuming that the port in Via _is_ 5074). If it does add "alias" to the Via, make sure you have tcp_accept_aliases=yes in the config.
twinkle does not add alias param to via so looks like its tcp implementation is broken. this comes from source tcp port 34136 to port 5060 at sr:
+++ 6-11-2009 12:06:27.976341 INFO SIP ::send_sip_tcp Send to: tcp:192.98.101.10:5060 REGISTER sip:test.fi SIP/2.0 Via: SIP/2.0/TCP 192.98.101.10:5074;rport;branch=z9hG4bKtabgdwsf Max-Forwards: 70 To: "Juha Heinanen" sip:jh@test.fi From: "Juha Heinanen" sip:jh@test.fi;tag=hqmmp Call-ID: bmybrkvktynbuma@localhost CSeq: 668 REGISTER Contact: sip:jh_test_fi@192.98.101.10:5074;transport=tcp;expires=3600
or should sr figure out that twinkle in fact is behind the tcp connection it created when it registered itself no matter what the port in contact uri is?
You can force that, using force_tcp_alias() (adds src_ip:port_in_via as an alias for src_ip:src_port).
can force_tcp_alias() be called on any register over tcp or should it be tested first that there is no alias in via and that port in register contact uri does not match source port?
In general, especially if you have NATed UACs, it's better to always have force_tcp_alias() in the config. It will cause problems only if you have non-NATed broken UACs that don't expect/support symmetric signalling over TCP (e.g. open a new connection for each new request and expect only replies to that request on the connection).
ok.
OTOH if you don't force_tcp_alias() and the UACs don't add alias to the Via, it's a very slim chance that NATed UACs will work over tcp.
i'll test next what happens when i put twinkle behind nat.
-- juha
On Nov 06, 2009 at 12:20, Juha Heinanen jh@tutpro.com wrote:
Andrei Pelinescu-Onciul writes:
Yes, it should do either that, or add an alias parameter to its Via (assuming that the port in Via _is_ 5074). If it does add "alias" to the Via, make sure you have tcp_accept_aliases=yes in the config.
twinkle does not add alias param to via so looks like its tcp implementation is broken. this comes from source tcp port 34136 to port 5060 at sr:
+++ 6-11-2009 12:06:27.976341 INFO SIP ::send_sip_tcp Send to: tcp:192.98.101.10:5060 REGISTER sip:test.fi SIP/2.0 Via: SIP/2.0/TCP 192.98.101.10:5074;rport;branch=z9hG4bKtabgdwsf Max-Forwards: 70 To: "Juha Heinanen" sip:jh@test.fi From: "Juha Heinanen" sip:jh@test.fi;tag=hqmmp Call-ID: bmybrkvktynbuma@localhost CSeq: 668 REGISTER Contact: sip:jh_test_fi@192.98.101.10:5074;transport=tcp;expires=3600
or should sr figure out that twinkle in fact is behind the tcp connection it created when it registered itself no matter what the port in contact uri is?
You can force that, using force_tcp_alias() (adds src_ip:port_in_via as an alias for src_ip:src_port).
can force_tcp_alias() be called on any register over tcp or should it be tested first that there is no alias in via and that port in register contact uri does not match source port?
You can call it always, for all the requests. It just adds a new alias for the via port if the alias doesn't already exists (accept_tcp_aliases=yes and alias in via does the same thing). So the easiest way is just to add force_tcp_alias() at the beginning of the route block.
If you want to support non symmetric signalling tcp UACs that are not behind NAT (they wouldn't work behind a NAT without static port forwarding rules anyway), you can use force_tcp_alias() only if you detect the UAC is behind the NAT.
I would look at the contact port only if you have really broken UACs that use a different port in Via then the one in the contact.
In general, especially if you have NATed UACs, it's better to always have force_tcp_alias() in the config. It will cause problems only if you have non-NATed broken UACs that don't expect/support symmetric signalling over TCP (e.g. open a new connection for each new request and expect only replies to that request on the connection).
ok.
OTOH if you don't force_tcp_alias() and the UACs don't add alias to the Via, it's a very slim chance that NATed UACs will work over tcp.
i'll test next what happens when i put twinkle behind nat.
Andrei
El Viernes, 6 de Noviembre de 2009, Andrei Pelinescu-Onciul escribió:
I would look at the contact port only if you have really broken UACs that use a different port in Via then the one in the contact.
This is the point. Both must match as both mean "the port in which the UA binds". But this port shouln't match the random source port used to send the initial REGISTER.
El Viernes, 6 de Noviembre de 2009, Juha Heinanen escribió:
Andrei Pelinescu-Onciul writes:
Yes, it should do either that, or add an alias parameter to its Via (assuming that the port in Via _is_ 5074). If it does add "alias" to the Via, make sure you have tcp_accept_aliases=yes in the config.
twinkle does not add alias param to via so looks like its tcp implementation is broken.
It's 100% correct. Please se me previous mail.
this comes from source tcp port 34136 to port 5060 at sr:
+++ 6-11-2009 12:06:27.976341 INFO SIP ::send_sip_tcp Send to: tcp:192.98.101.10:5060 REGISTER sip:test.fi SIP/2.0 Via: SIP/2.0/TCP 192.98.101.10:5074;rport;branch=z9hG4bKtabgdwsf Max-Forwards: 70 To: "Juha Heinanen" sip:jh@test.fi From: "Juha Heinanen" sip:jh@test.fi;tag=hqmmp Call-ID: bmybrkvktynbuma@localhost CSeq: 668 REGISTER Contact: sip:jh_test_fi@192.98.101.10:5074;transport=tcp;expires=3600
El Viernes, 6 de Noviembre de 2009, Andrei Pelinescu-Onciul escribió:
On Nov 06, 2009 at 08:12, Juha Heinanen jh@tutpro.com wrote:
twinkle is registered over tcp to sr using source port 59056 destination port 5060. in contact uri twinkle has put port 5074 (i need to configure some fixed port there).
when another ua calls twinkle and i see this in syslog:
Nov 6 07:16:21 localhost /usr/sbin/sip-proxy[30133]: INFO: Routing first INVITE to sip:jh_test_fi@192.98.101.10:5074;transport=tcp and <<null>> Nov 6 07:16:21 localhost /usr/sbin/sip-proxy[30133]: INFO: <core> [tcp_main.c:1928]: tcp_send: quick connect for 0xb54f3e60
when i look wireshark output, i see that sr has created a new tcp connection to twinkle at port 5074 even when there is already is one, but not to that port.
is this twinkle's fault, i.e., should it put in contact uri port 59056 instead?
Yes, it should do either that,
Hi, I don't agree with it. When a UA uses TCP for registration the following occurs (no NAT between UA and proxy):
- UA listens for *incoming* requests on a predefined port (i.e: 5060 UDP/TCP). - UA sends a TCP REGISTER from a ramdom port (i.e: 12345 TCP). - The "Via" port of the REGISTER MUST be "5060" (the port in which UA listens). - The "Contact" port of the REGISTER MUST be "5060" (the port in which UA listens). Yes, this is what RFC 3261 states. - The proxy must send the response of the REGISTER using the existing TCP connection (as per RFC 3261 18.2.2). - If the connection is no longer open, the proxy must open a new connection to the IP address in the "received" parameter, if present, and port in "Via" "sent-by", and send there the response of the REGISTER.
I think this is totally clear. The problem arises when the proxy must route an incoming request to the location of this UA. In this case:
- A request arrives to the proxy. - The proxy must route it to UA's location so it inspects the location database and fetches the "Contact" value of the UA's REGISTER. The port retrieved is 5060 rather than 12345. - So the proxy routes the request there, to UA's port 5060. Since there is no TCP connection open it must open a new one. It would work as there is no NAT and UA is listening in port 5060 TCP.
NOTE: Must of the UA's accept incoming requests arriving to the port from which they sent the REGISTER, but this is not specified in RFC 3261 at all. Of course, if NAT exists the only solution is using the connection established by the registration process as the proxy couldn't open a new connection with natted UA.
So answering to this question:
is this twinkle's fault, i.e., should it put in contact uri port 59056 instead?
Not at all per RFC 3261. Perhaps the hyper-complex draft-outbound states that the TCP UA must bind on the source port from which the REGISTER is sent, no idea. But for sure RFC 3261 doesn't say that.
or add an alias parameter to its Via (assuming that the port in Via _is_ 5074). If it does add "alias" to the Via, make sure you have tcp_accept_aliases=yes in the config.
What is an "alias" parameter in the Via header?
or should sr figure out that twinkle in fact is behind the tcp connection it created when it registered itself no matter what the port in contact uri is?
You can force that, using force_tcp_alias() (adds src_ip:port_in_via as an alias for src_ip:src_port). If the port in Via is not 5074 then you can work around that too, using force_tcp_alias(5074) (based maybe on looking at the contact?), but in this case it's better to reconfigure/fix twinkle.
Please, explain it again as I don't understand what you mean with "adds src_ip:port_in_via as an alias for src_ip:src_port". However I ensure that Twinkle behaviour is totally correct when using SIP TCP and there is nothing to fix here. In short:
- Twinkle binds on port 5060 TCP (and UDP). - It sends a REGISTER from random port (12345). "Via" and "Contact" contains port 5060. - Twinkle would accept incoming requests to both ports 5060 and 12345. Allowing incoming request to port 12345 helps with NAT, of course, but it's not specified in RFC 3261 at all, and Twinkle (or any UA) could refuse a request incoming from a port different than 5060 (the port it has announced as listening port).
An example of Twinkle TCP REGISTER:
T 2009/11/06 12:13:26.472917 192.168.1.10:38609 -> XX.XX.XX.XX:5062 REGISTER sip:mydomain.net SIP/2.0 Via: SIP/2.0/TCP 192.168.1.10:6060;rport;branch=z9hG4bKsswrheos Contact: sip:ibc_aliax_net@192.168.1.10:6060;transport=tcp;expires=600
In general, especially if you have NATed UACs, it's better to always have force_tcp_alias() in the config. It will cause problems only if you have non-NATed broken UACs that don't expect/support symmetric signalling over TCP (e.g. open a new connection for each new request and expect only replies to that request on the connection).
Symmetric signalling is about using the same src_ip:src_port - dst_ip:dst_port within a transaction, which involves requests and its replies. It's not about different transactions in both ways. For that there is a draft/RFC about TCP reuse and so, but it requires a "Via" parameter and some stuff... RFC 3261 doesn't state that a UA should accept incoming requests to a port different than the binding port.
OTOH if you don't force_tcp_alias() and the UACs don't add alias to the Via, it's a very slim chance that NATed UACs will work over tcp.
I again ask what "add alias to the Via" means :)
Regards.
On Nov 06, 2009 at 12:16, I?aki Baz Castillo ibc@aliax.net wrote:
El Viernes, 6 de Noviembre de 2009, Andrei Pelinescu-Onciul escribi?:
On Nov 06, 2009 at 08:12, Juha Heinanen jh@tutpro.com wrote:
[...]
So answering to this question:
is this twinkle's fault, i.e., should it put in contact uri port 59056 instead?
Not at all per RFC 3261. Perhaps the hyper-complex draft-outbound states that the TCP UA must bind on the source port from which the REGISTER is sent, no idea. But for sure RFC 3261 doesn't say that.
Yes, according to 3261 the behaviour is correct. However if it doesn't support receiving requests on the same port it used to send the REGISTER or other requests it's broken in practice, since it would never work behind a NAT. It's like an udp UAC that has a different port in Via and expects new requests only on that port: it's perfectly valid according to 3261, but it will never work in practice due to NATs.
or add an alias parameter to its Via (assuming that the port in Via _is_ 5074). If it does add "alias" to the Via, make sure you have tcp_accept_aliases=yes in the config.
What is an "alias" parameter in the Via header?
draft-ietf-sip-connect-reuse-00 - it's a parameter added to Via whend sending a request that means the remote side can alias the connection (add an internal ip:src_port as an alias for ip:via_port). The current version of the draft seems to be dealing only with TLS though (it looks like TCP alias is now in draft-jain-sip-transport-layer-connection-reuse-00).
or should sr figure out that twinkle in fact is behind the tcp connection it created when it registered itself no matter what the port in contact uri is?
You can force that, using force_tcp_alias() (adds src_ip:port_in_via as an alias for src_ip:src_port). If the port in Via is not 5074 then you can work around that too, using force_tcp_alias(5074) (based maybe on looking at the contact?), but in this case it's better to reconfigure/fix twinkle.
Please, explain it again as I don't understand what you mean with "adds src_ip:port_in_via as an alias for src_ip:src_port".
It means that requests to twinkle_ip:twinkle_via_port will be sent on the tcp connection from twhinkle_ip:twinkle_src_port, if the connection is still opened.
However I ensure that Twinkle behaviour is totally correct when using SIP TCP and there is nothing to fix here. In short:
- Twinkle binds on port 5060 TCP (and UDP).
- It sends a REGISTER from random port (12345). "Via" and "Contact" contains
port 5060.
- Twinkle would accept incoming requests to both ports 5060 and 12345.
Allowing incoming request to port 12345 helps with NAT, of course, but it's not specified in RFC 3261 at all, and Twinkle (or any UA) could refuse a request incoming from a port different than 5060 (the port it has announced as listening port).
If it accepts request on 12345 then it's ok. It should consider "advertising" it by adding alias to Via though (it's just ;alias somewhere in the via params).
An example of Twinkle TCP REGISTER:
T 2009/11/06 12:13:26.472917 192.168.1.10:38609 -> XX.XX.XX.XX:5062 REGISTER sip:mydomain.net SIP/2.0 Via: SIP/2.0/TCP 192.168.1.10:6060;rport;branch=z9hG4bKsswrheos Contact: sip:ibc_aliax_net@192.168.1.10:6060;transport=tcp;expires=600
In general, especially if you have NATed UACs, it's better to always have force_tcp_alias() in the config. It will cause problems only if you have non-NATed broken UACs that don't expect/support symmetric signalling over TCP (e.g. open a new connection for each new request and expect only replies to that request on the connection).
Symmetric signalling is about using the same src_ip:src_port - dst_ip:dst_port within a transaction, which involves requests and its replies. It's not about different transactions in both ways. For that there is a draft/RFC about TCP reuse and so, but it requires a "Via" parameter and some stuff... RFC 3261 doesn't state that a UA should accept incoming requests to a port different than the binding port.
OTOH if you don't force_tcp_alias() and the UACs don't add alias to the Via, it's a very slim chance that NATed UACs will work over tcp.
I again ask what "add alias to the Via" means :)
Andrei
El Viernes, 6 de Noviembre de 2009, Andrei Pelinescu-Onciul escribió:
Not at all per RFC 3261. Perhaps the hyper-complex draft-outbound states that the TCP UA must bind on the source port from which the REGISTER is sent, no idea. But for sure RFC 3261 doesn't say that.
Yes, according to 3261 the behaviour is correct. However if it doesn't support receiving requests on the same port it used to send the REGISTER or other requests it's broken in practice, since it would never work behind a NAT.
100% agree.
It's like an udp UAC that has a different port in Via and expects new requests only on that port: it's perfectly valid according to 3261, but it will never work in practice due to NATs.
Yes, UDP asymmetric SIP clients. Fortunatelly they are dissapearing :)
or add an alias parameter to its Via (assuming that the port in Via _is_ 5074). If it does add "alias" to the Via, make sure you have tcp_accept_aliases=yes in the config.
What is an "alias" parameter in the Via header?
draft-ietf-sip-connect-reuse-00 - it's a parameter added to Via whend sending a request that means the remote side can alias the connection (add an internal ip:src_port as an alias for ip:via_port). The current version of the draft seems to be dealing only with TLS though (it looks like TCP alias is now in draft-jain-sip-transport-layer-connection-reuse-00).
Ok. so using "force_tcp_alias" then SR behaves as if the request contained "alias" in Via header and tcp_accept_aliases=yes in the config. So requests to that user are sent using an existing TCP connection. Now it's clear, thanks ;)
Hi Juha!
Personally I do not like the alias approach. IIRC correctly there were some security issues with aliases (at least some time ago) and ser does hand aliases a little bit different then described by IETF to avoid this issues.
To solve the situation there are 2 other solutions: 1. in client 2. in server
1. client: The client learns the public socket during REGISTER (Via received+rport in response) and changes its contact in REGISTER and INVITE messages to the new one learned. This is for example what xlite and pjsip does. This approach does not work if the client does not register - if it only sends INVITE then there is no learned socket available in the initial INVITE.
2. server I use the pragmatic, and well working UDP approach. Just call fix_nated_contact/register also for TCP clients. I never had any issues with that.
regards klaus
Juha Heinanen schrieb:
i started to test the latest sr_3.0 that includes andrei's tcp/socket related changes.
twinkle is registered over tcp to sr using source port 59056 destination port 5060. in contact uri twinkle has put port 5074 (i need to configure some fixed port there).
when another ua calls twinkle and i see this in syslog:
Nov 6 07:16:21 localhost /usr/sbin/sip-proxy[30133]: INFO: Routing first INVITE to sip:jh_test_fi@192.98.101.10:5074;transport=tcp and <<null>> Nov 6 07:16:21 localhost /usr/sbin/sip-proxy[30133]: INFO: <core> [tcp_main.c:1928]: tcp_send: quick connect for 0xb54f3e60
when i look wireshark output, i see that sr has created a new tcp connection to twinkle at port 5074 even when there is already is one, but not to that port.
is this twinkle's fault, i.e., should it put in contact uri port 59056 instead?
or should sr figure out that twinkle in fact is behind the tcp connection it created when it registered itself no matter what the port in contact uri is?
-- juha
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribió:
Hi Juha!
Personally I do not like the alias approach. IIRC correctly there were some security issues with aliases (at least some time ago) and ser does hand aliases a little bit different then described by IETF to avoid this issues.
Could I know about those security issues? (just a brief description).
To solve the situation there are 2 other solutions:
in client
in server
client:
The client learns the public socket during REGISTER (Via received+rport in response) and changes its contact in REGISTER
What about if the server doesn't challenge the client? XDD
and INVITE messages to the new one learned. This is for example what xlite and pjsip does. This approach does not work if the client does not register - if it only sends INVITE then there is no learned socket available in the initial INVITE.
If the client doesn't register then it cannot receive responses anyway.
However, the fact is that during a TCP dialog there "should" exist *two* TCP connections (assuming binding port = 5060):
a) UA:random_port - Proxy:5060 b) Proxy:random_port - UA:5060
If UA initiates the dialog the connection a) is created. If Proxy sends an in-dialog request the connection b) is created.
Of course b) is not created when using "alias" or forcing the proxy to reuse the connection established by UA (server solution).
- server
I use the pragmatic, and well working UDP approach. Just call fix_nated_contact/register also for TCP clients. I never had any issues with that.
Neither me, but it could fail if some UA doesn't allow that (never seen it however).
Regards.
Iñaki Baz Castillo schrieb:
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribió:
Hi Juha!
Personally I do not like the alias approach. IIRC correctly there were some security issues with aliases (at least some time ago) and ser does hand aliases a little bit different then described by IETF to avoid this issues.
Could I know about those security issues? (just a brief description).
I do not remember anymore in detail, but I think by spoofing aliases (and the proxy accepts the spoofed alias) it could be possible to intercept SIP messages which are targeted to another user/client behind the same NAT.
To solve the situation there are 2 other solutions:
in client
in server
client:
The client learns the public socket during REGISTER (Via received+rport in response) and changes its contact in REGISTER
What about if the server doesn't challenge the client? XDD
No problem - at least for xlite. It does: 1. REGISTER with local socket 2. 407 3. REGISTER with local socket 4. 200 ok (learn public socket) 5. deREGISTER local socket 6. 200 ok 7. REGISTER with public socket 8. 200 ok
I do not know how pjsip handles this (if it is smarter :-)
and INVITE messages to the new one learned. This is for example what xlite and pjsip does. This approach does not work if the client does not register - if it only sends INVITE then there is no learned socket available in the initial INVITE.
If the client doesn't register then it cannot receive responses anyway.
e.g. call-setup would work, but BYE from callee would fail.
However, the fact is that during a TCP dialog there "should" exist *two* TCP connections (assuming binding port = 5060):
a) UA:random_port - Proxy:5060 b) Proxy:random_port - UA:5060
that's the broken idea of RFC 3261. In fact that will never work due to NAT/FW. The un-standardized approaches are described above and work well. The standardized approach would be sip-outbound, which gives the same result than the un-standardized approach.
regards klaus
If UA initiates the dialog the connection a) is created. If Proxy sends an in-dialog request the connection b) is created.
Of course b) is not created when using "alias" or forcing the proxy to reuse the connection established by UA (server solution).
- server
I use the pragmatic, and well working UDP approach. Just call fix_nated_contact/register also for TCP clients. I never had any issues with that.
Neither me, but it could fail if some UA doesn't allow that (never seen it however).
Regards.
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribió:
I do not remember anymore in detail, but I think by spoofing aliases (and the proxy accepts the spoofed alias) it could be possible to intercept SIP messages which are targeted to another user/client behind the same NAT.
ok.
What about if the server doesn't challenge the client? XDD
No problem - at least for xlite. It does:
- REGISTER with local socket
- 407
- REGISTER with local socket
- 200 ok (learn public socket)
- deREGISTER local socket
- 200 ok
- REGISTER with public socket
- 200 ok
That's really ugly! XDD
However, the fact is that during a TCP dialog there "should" exist *two* TCP connections (assuming binding port = 5060):
a) UA:random_port - Proxy:5060 b) Proxy:random_port - UA:5060
that's the broken idea of RFC 3261.
It's not a broken idea since in IETF world there is no NAT. But yes, the fact is that it's ridiculous!!! How is possible that a TCP communication between two nodes could require two TCP connections??? Terrible design...
In fact that will never work due to NAT/FW. The un-standardized approaches are described above and work well. The standardized approach would be sip-outbound, which gives the same result than the un-standardized approach.
The only difference is that the un-standardized approach forcing the same standardized approach without requiring "alias" parameter in Via header :)
Thanks.
6 nov 2009 kl. 14.54 skrev Klaus Darilion:
Iñaki Baz Castillo schrieb:
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribió:
Hi Juha!
Personally I do not like the alias approach. IIRC correctly there were some security issues with aliases (at least some time ago) and ser does hand aliases a little bit different then described by IETF to avoid this issues.
Could I know about those security issues? (just a brief description).
I do not remember anymore in detail, but I think by spoofing aliases (and the proxy accepts the spoofed alias) it could be possible to intercept SIP messages which are targeted to another user/client behind the same NAT.
To solve the situation there are 2 other solutions:
in client
in server
client:
The client learns the public socket during REGISTER (Via received +rport in response) and changes its contact in REGISTER
What about if the server doesn't challenge the client? XDD
No problem - at least for xlite. It does:
- REGISTER with local socket
- 407
- REGISTER with local socket
- 200 ok (learn public socket)
- deREGISTER local socket
- 200 ok
- REGISTER with public socket
- 200 ok
I do not know how pjsip handles this (if it is smarter :-)
and INVITE messages to the new one learned. This is for example what xlite and pjsip does. This approach does not work if the client does not register - if it only sends INVITE then there is no learned socket available in the initial INVITE.
If the client doesn't register then it cannot receive responses anyway.
e.g. call-setup would work, but BYE from callee would fail.
However, the fact is that during a TCP dialog there "should" exist *two* TCP connections (assuming binding port = 5060): a) UA:random_port - Proxy:5060 b) Proxy:random_port - UA:5060
that's the broken idea of RFC 3261. In fact that will never work due to NAT/FW. The un-standardized approaches are described above and work well. The standardized approach would be sip-outbound, which gives the same result than the un-standardized approach.
SIP-outbound for when NAT is involved and connection-reuse drafts (that Andrei referred to earlier) for when there's no NAT, like between two sip proxys on the public Internet or a local network.
And in addition, there's a lot of work done for TCP/TLS that makes it even more complicated. If you opened a connection to a proxy for berlin.example.com and approved the server certificate and then realize that you're about to set up a new connection to the same proxy, but now for stockholm.example.com - you're not allowed to reuse the first connection.
/O
On Nov 06, 2009 at 14:39, I?aki Baz Castillo ibc@aliax.net wrote:
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribi?:
Hi Juha!
Personally I do not like the alias approach. IIRC correctly there were some security issues with aliases (at least some time ago) and ser does hand aliases a little bit different then described by IETF to avoid this issues.
Could I know about those security issues? (just a brief description).
IIRC the original alias draft required to alias also the IP, so for example a message from ip: 1.2.3.4 with src_port 1234 and having in via 5.6.7.8:5060 would set an alias on the proxy: 5.6.7.8:5060->1.2.3.4:1234 which is evidently a security problem (I can use it to redirect someone else's traffic to me). In ser/sr/kamailio the alias will work only for the port, so in the above example the alias will be: 1.2.3.4:5060->1.2.3.4:1234 and IIRC a message might be logged.
Even using only the port for the alias there can still be problems if there are several UACs behind the same NAT that listen on the same port (e.g. 5060). All of them would add 5060 in the via and on the proxy there would be attempts to set multiple aliases for nat_ip:5060. In this case one UAC will also get the requests intended for the others. This can also be used on purpose, to intercept the messages of the other users behind the same NAT or on the same machine.
To solve the situation there are 2 other solutions:
in client
in server
client:
The client learns the public socket during REGISTER (Via received+rport in response) and changes its contact in REGISTER
Even better would for the client to use STUN over tcp first to find the port and NAT address and then send the REGISTER with the proper ports (on the same connections). Then it could use STUN for keepalives (draft-ietf-behave-rfc3489bis). (in this case sr must be configured with STUN support, e.g. make config STUN=1)
[...]
Andrei
El Viernes, 6 de Noviembre de 2009, Andrei Pelinescu-Onciul escribió:
On Nov 06, 2009 at 14:39, I?aki Baz Castillo ibc@aliax.net wrote:
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribi?:
Hi Juha!
Personally I do not like the alias approach. IIRC correctly there were some security issues with aliases (at least some time ago) and ser does hand aliases a little bit different then described by IETF to avoid this issues.
Could I know about those security issues? (just a brief description).
IIRC the original alias draft required to alias also the IP, so for example a message from ip: 1.2.3.4 with src_port 1234 and having in via 5.6.7.8:5060 would set an alias on the proxy: 5.6.7.8:5060->1.2.3.4:1234 which is evidently a security problem (I can use it to redirect someone else's traffic to me). In ser/sr/kamailio the alias will work only for the port, so in the above example the alias will be: 1.2.3.4:5060->1.2.3.4:1234 and IIRC a message might be logged.
IETF *always* proposes exotic solutions based on user provided information! Really annoying.
Even using only the port for the alias there can still be problems if there are several UACs behind the same NAT that listen on the same port (e.g. 5060). All of them would add 5060 in the via and on the proxy there would be attempts to set multiple aliases for nat_ip:5060. In this case one UAC will also get the requests intended for the others. This can also be used on purpose, to intercept the messages of the other users behind the same NAT or on the same machine.
I though that the "alias" behavior was different:
- UA adds "alias" in Via (with no value, just an empty parameter). - Then the proxy does know that it can reuse the existing connection to route new requests to this UA.
I don't understand why the user has provide address information. Perhaps I read other draft XD
Regards.
Andrei Pelinescu-Onciul schrieb:
On Nov 06, 2009 at 14:39, I?aki Baz Castillo ibc@aliax.net wrote:
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribi?:
- client:
The client learns the public socket during REGISTER (Via received+rport in response) and changes its contact in REGISTER
Even better would for the client to use STUN over tcp first to find the port and NAT address and then send the REGISTER with the proper ports (on the same connections). Then it could use STUN for keepalives (draft-ietf-behave-rfc3489bis). (in this case sr must be configured with STUN support, e.g. make config STUN=1)
Why not make STUN=1 default?
klaus
while doing quite extensive tests on add_contact_alias()/handle_ruri_alias() functions, i noticed a flaw in the reply processing example:
if (!isbflagset("TO_PROXY") { if (is_avp_set("$avp(rr_count)")) { if ($rr_count == $avp(rr_count) + 1) { route(ADD_CONTACT_ALIAS); }; } else { route(ADD_CONTACT_ALIAS); } }
the flaw is that proxy may add double record route instead of a single one and if is does so, then test
if ($rr_count == $avp(rr_count) + 1) {
is wrong. i solved the problem by introducing a second pv $rr_top_count, which has value 2 if top rr is a double one and 1 if not. using it, the test can be written correctly as
if ($rr_count == $avp(rr_count) + $rr_top_count) {
i have updated nathelper.c and alias_example.txt in http://box.tutpro.com/tmp, but would really like to commit the new nathelper.c and update docs to sr_3.0. since these new functions and pvs don't touch any of the existing nathelper code, the commit should be a safe thing to do.
-- juha
6 nov 2009 kl. 14.39 skrev Iñaki Baz Castillo:
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribió:
Hi Juha!
Personally I do not like the alias approach. IIRC correctly there were some security issues with aliases (at least some time ago) and ser does hand aliases a little bit different then described by IETF to avoid this issues.
Could I know about those security issues? (just a brief description).
To solve the situation there are 2 other solutions:
in client
in server
client:
The client learns the public socket during REGISTER (Via received +rport in response) and changes its contact in REGISTER
What about if the server doesn't challenge the client? XDD
and INVITE messages to the new one learned. This is for example what xlite and pjsip does. This approach does not work if the client does not register - if it only sends INVITE then there is no learned socket available in the initial INVITE.
If the client doesn't register then it cannot receive responses anyway.
However, the fact is that during a TCP dialog there "should" exist *two* TCP connections (assuming binding port = 5060):
a) UA:random_port - Proxy:5060 b) Proxy:random_port - UA:5060
If UA initiates the dialog the connection a) is created. If Proxy sends an in-dialog request the connection b) is created.
Of course b) is not created when using "alias" or forcing the proxy to reuse the connection established by UA (server solution).
Imaging having TLS. The B connection would not work unless we had a valid certificate in the UA.
For TLS each TCP connection needs a property on when it's allowed to reuse.
/O
El Sábado, 7 de Noviembre de 2009, Olle E. Johansson escribió:
However, the fact is that during a TCP dialog there "should" exist *two* TCP connections (assuming binding port = 5060):
a) UA:random_port - Proxy:5060 b) Proxy:random_port - UA:5060
If UA initiates the dialog the connection a) is created. If Proxy sends an in-dialog request the connection b) is created.
Of course b) is not created when using "alias" or forcing the proxy to reuse the connection established by UA (server solution).
Imaging having TLS. The B connection would not work unless we had a valid certificate in the UA.
For TLS each TCP connection needs a property on when it's allowed to reuse.
Annoying. Let me a question:
If UA is not behind NAT (but supports and uses sip-outbound), how many TCP connections would exist when communicating with the proxy?
PS: I insinst. How is possible that IETF has designed a protocol in which, by default, two TCP connections are required in a direct communication between A and B?
Iñaki Baz Castillo schrieb:
El Sábado, 7 de Noviembre de 2009, Olle E. Johansson escribió:
However, the fact is that during a TCP dialog there "should" exist *two* TCP connections (assuming binding port = 5060):
a) UA:random_port - Proxy:5060 b) Proxy:random_port - UA:5060
If UA initiates the dialog the connection a) is created. If Proxy sends an in-dialog request the connection b) is created.
Of course b) is not created when using "alias" or forcing the proxy to reuse the connection established by UA (server solution).
Imaging having TLS. The B connection would not work unless we had a valid certificate in the UA.
For TLS each TCP connection needs a property on when it's allowed to reuse.
Annoying. Let me a question:
If UA is not behind NAT (but supports and uses sip-outbound), how many TCP connections would exist when communicating with the proxy?
since October 2009: 1 http://tools.ietf.org/html/rfc5626
regards klaus
PS: I insinst. How is possible that IETF has designed a protocol in which, by default, two TCP connections are required in a direct communication between A and B?
Juha Heinanen schrieb:
Klaus Darilion writes:
- server
I use the pragmatic, and well working UDP approach. Just call fix_nated_contact/register also for TCP clients. I never had any issues with that.
even when client is not behind nat like in the example of the discussion?
In this case it can work also with client receiving responses/in-dialog requests at advertised port (as long as the client is really listening on the advertised port).
But one of my favorites statement is: "Never trust the user". As the contact and Via headers are user provided data I do not trust it. Thus I always enforce symmetric signaling, regardless if client is behind NAT or not and regardless of the used protocol.*
The only exception is if the client is known to be asymmetric (then I have to screen the contact that at least the IP is the src_ip).
regards Klaus
* I once used the somehow "academic" approach with hyper-intelligent NAT detection methods, but I ended up with the "pragmatic" approach which is easier, more secure and works IMO better.
Klaus Darilion writes:
But one of my favorites statement is: "Never trust the user". As the contact and Via headers are user provided data I do not trust it. Thus I always enforce symmetric signaling, regardless if client is behind NAT or not and regardless of the used protocol.*
would it then make sense to use this approach also in the example configs? i haven't check, but i doubt they include it.
-- juha
Juha Heinanen schrieb:
Klaus Darilion writes:
But one of my favorites statement is: "Never trust the user". As the contact and Via headers are user provided data I do not trust it. Thus I always enforce symmetric signaling, regardless if client is behind NAT or not and regardless of the used protocol.*
would it then make sense to use this approach also in the example configs? i haven't check, but i doubt they include it.
I depends if I still want to make money by securing SIP proxy installations ;-)
regards klaus
PS: yes
El Viernes, 6 de Noviembre de 2009, Klaus Darilion escribió:
Juha Heinanen schrieb:
Klaus Darilion writes:
- server
I use the pragmatic, and well working UDP approach. Just call fix_nated_contact/register also for TCP clients. I never had any issues with that.
even when client is not behind nat like in the example of the discussion?
In this case it can work also with client receiving responses/in-dialog requests at advertised port
(as long as the client is really listening on the advertised port).
It should!
But one of my favorites statement is: "Never trust the user". As the contact and Via headers are user provided data I do not trust it. Thus I always enforce symmetric signaling, regardless if client is behind NAT or not and regardless of the used protocol.*
Some SIP ALG routers change the Via/Contact port and set 12345 while the public source port is 12344. Really. So don't believe the user, neither the routers! XD
Klaus Darilion schrieb:
Juha Heinanen schrieb:
Klaus Darilion writes:
- server
I use the pragmatic, and well working UDP approach. Just call >
fix_nated_contact/register also for TCP clients. I never had any issues > with that.
even when client is not behind nat like in the example of the discussion?
In this case it can work also with client receiving responses/in-dialog requests at advertised port (as long as the client is really listening on the advertised port).
But one of my favorites statement is: "Never trust the user". As the contact and Via headers are user provided data I do not trust it. Thus I always enforce symmetric signaling, regardless if client is behind NAT or not and regardless of the used protocol.*
Of course this has some limitations too - e.g. if a local user uses a proxy between client and my proxy - I will incorrectly rewrite the contact to the socket of the other proxy. But in typical service provider deployments there should not be proxies inbetween, or the proxy should be able to recover from this.
regards klaus
The only exception is if the client is known to be asymmetric (then I have to screen the contact that at least the IP is the src_ip).
regards Klaus
- I once used the somehow "academic" approach with hyper-intelligent NAT
detection methods, but I ended up with the "pragmatic" approach which is easier, more secure and works IMO better.
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
Klaus Darilion writes:
- server
I use the pragmatic, and well working UDP approach. Just call fix_nated_contact/register also for TCP clients. I never had any issues with that.
klaus,
rather than fixing the contact, would it be better to incldue the received ip/port info into the rr header that sr is adding?
reasoning is that when you fix the contact, say, of incoming invite, the ack and bye from the callee has incorrect r-uri, i.e., not the original contact of the caller.
if it would be possible to include the received ip/port info into rr header, then sr would know where to send the ack/bye and r-uri would be the original one.
this is similar to what fixing register does, i.e., it stores the received ip/port in a field of location table, and invite to this uri has the original contact.
-- juha
El Sábado, 7 de Noviembre de 2009, Juha Heinanen escribió:
Klaus Darilion writes:
- server
I use the pragmatic, and well working UDP approach. Just call fix_nated_contact/register also for TCP clients. I never had any issues with that.
klaus,
rather than fixing the contact, would it be better to incldue the received ip/port info into the rr header that sr is adding?
reasoning is that when you fix the contact, say, of incoming invite, the ack and bye from the callee has incorrect r-uri, i.e., not the original contact of the caller.
if it would be possible to include the received ip/port info into rr header, then sr would know where to send the ack/bye and r-uri would be the original one.
this is similar to what fixing register does, i.e., it stores the received ip/port in a field of location table, and invite to this uri has the original contact.
I totally agree. But adding this info to Record-Route doesn't like to me. Note that RR value is mirrored by the UAS in the 18X/200 response, so the proxy should replace the value in RR received from the UAS (source address of UAC) with the source address of the UAS. This is a bit annoying as it involves rewritting a parameter value.
I would suggest to add a ";received=SOURCE_IP:SOURCE_PORT" to the Contact URI (not to the header). In this way the in-dialog requests from the caller/callee would look like:
BYE sip:alice@PRIVATE_IP:PRIVATE_PORT;received=SOURCE_IP:SOURCE_PORT SIP/2.0
So SR could route based on this RURI parameter and keep the original Contact as RURI.
Iñaki Baz Castillo writes:
I would suggest to add a ";received=SOURCE_IP:SOURCE_PORT" to the Contact URI (not to the header). In this way the in-dialog requests from the caller/callee would look like:
BYE sip:alice@PRIVATE_IP:PRIVATE_PORT;received=SOURCE_IP:SOURCE_PORT SIP/2.0
inaki,
sound ok to me. if other people don't find any problems with this, should we write a new version of fix_nated_contact that adds the param to contact uri or just try to use existing scripting means (remove contact hf, add a new modified one)?
So SR could route based on this RURI parameter and keep the original Contact as RURI.
i haven't checked if it would be possible to do that in the script (extract and remove received param from r-uri and set $du) or would a new function need to be written for that too.
-- juha
El Sábado, 7 de Noviembre de 2009, Juha Heinanen escribió:
Iñaki Baz Castillo writes:
I would suggest to add a ";received=SOURCE_IP:SOURCE_PORT" to the Contact URI (not to the header). In this way the in-dialog requests from the caller/callee would look like:
BYE sip:alice@PRIVATE_IP:PRIVATE_PORT;received=SOURCE_IP:SOURCE_PORT SIP/2.0
inaki,
sound ok to me. if other people don't find any problems with this, should we write a new version of fix_nated_contact that adds the param to contact uri or just try to use existing scripting means (remove contact hf, add a new modified one)?
It would be great. However I would like to ensure that no broken UA outthere would remove the Contact URI params when generating an in-dialog request. I expect this doesn't occur as it's the same behavior as when using SIP TCP (UA's Contact URI has ";transport=tcp" and this param is present in RURI of in-dialog request from UAS). It should work :)
So SR could route based on this RURI parameter and keep the original Contact as RURI.
i haven't checked if it would be possible to do that in the script (extract and remove received param from r-uri and set $du) or would a new function need to be written for that too.
AFAIK $du is never (until now I mean) set when processing an in-dialog request as we rely on previous modifications performed on Contact URI address. With this proposal it would be required that during in-dialog processing the $du would be set with the value of ";received" param in RURI.
Of course this param just exist in case of a NATted client so dealing manually with it means:
- Extract the RURI ";received" param. - If it exists then set $du with it. - If not leave $du unset.
I would prefer a new nathelper exported function:
"nat_check_received()"
If ";received" param exists it set $du and returns 1. If not, $du is not set and returns 0.
However I would like to check how it works in this scenario:
UA1 --(NAT)-- Proxy1 ----- Proxy2 --(NAT)-- UA2
- UA1 sends INVITE (private address in headers).
- Proxy1 adds ";received" to Contact URI" Contact: sip:ua1@PRIVATE_UA1;received=PUBLIC_UA1
- Proxy 2 checks NAT. It shouldn't inspect the Contact URI !!! or if so, it should also take into account the existance of "received" param!!! (first problem). If not, Proxy2 would also add its own ";received" param: Contact: sip:ua1@PRIVATE_UA1;received=PUBLIC_UA1;received=PROXY1
Hummm, so perhaps playing with Record-Route wourl be better as each RR is just inspected by the proxy adding it...
Comments?
Iñaki Baz Castillo writes:
AFAIK $du is never (until now I mean) set when processing an in-dialog request as we rely on previous modifications performed on Contact URI address. With this proposal it would be required that during in-dialog processing the $du would be set with the value of ";received" param in RURI.
yes.
Of course this param just exist in case of a NATted client so dealing manually with it means:
why only nated? this whole thread started as why two tcp connections are needed to an ua. so the parameter would also be added when request arrives from non-nated tcp ua so that future requests on this dialog back to ua could be made to use the existing tcp connection.
one thing to note is that the parameter needs to be added also to in-dialog requests that have contact header.
I would prefer a new nathelper exported function:
"nat_check_received()"
If ";received" param exists it set $du and returns 1. If not, $du is not set and returns 0.
i would prefer to leave setting if du to the script. it is not a good idea to embed too much functionality to functions. so there should be a function or transformation to remove extract and remove the received parameter in addition of one that inserts the received parameter.
However I would like to check how it works in this scenario:
UA1 --(NAT)-- Proxy1 ----- Proxy2 --(NAT)-- UA2
UA1 sends INVITE (private address in headers).
Proxy1 adds ";received" to Contact URI" Contact: sip:ua1@PRIVATE_UA1;received=PUBLIC_UA1
Proxy 2 checks NAT. It shouldn't inspect the Contact URI !!! or if so, it
should also take into account the existance of "received" param!!! (first problem). If not, Proxy2 would also add its own ";received" param: Contact: sip:ua1@PRIVATE_UA1;received=PUBLIC_UA1;received=PROXY1
i don't see a problem here. proxy should only check nat on requests that it receives from UAs, not from other proxies, because it should be other proxies' job to take care of their own UAs.
-- juha
El Sábado, 7 de Noviembre de 2009, Juha Heinanen escribió:
Of course this param just exist in case of a NATted client so dealing manually with it means:
why only nated? this whole thread started as why two tcp connections are needed to an ua. so the parameter would also be added when request arrives from non-nated tcp ua so that future requests on this dialog back to ua could be made to use the existing tcp connection.
Ok, but for non natted TCP dialogs the usage of "alias" (supported by SR) is a working (and really standarized) solution.
I would prefer a new nathelper exported function:
"nat_check_received()"
If ";received" param exists it set $du and returns 1. If not, $du is not set and returns 0.
i would prefer to leave setting if du to the script. it is not a good idea to embed too much functionality to functions. so there should be a function or transformation to remove extract and remove the received parameter in addition of one that inserts the received parameter.
Well, as it's not so complex it makes sense. Just a question: is it easy to add a *URI* parameter into Contact header?
However I would like to check how it works in this scenario:
UA1 --(NAT)-- Proxy1 ----- Proxy2 --(NAT)-- UA2
UA1 sends INVITE (private address in headers).
Proxy1 adds ";received" to Contact URI" Contact: sip:ua1@PRIVATE_UA1;received=PUBLIC_UA1
Proxy 2 checks NAT. It shouldn't inspect the Contact URI !!! or if so,
it should also take into account the existance of "received" param!!! (first problem). If not, Proxy2 would also add its own ";received" param: Contact: sip:ua1@PRIVATE_UA1;received=PUBLIC_UA1;received=PROXY1
i don't see a problem here. proxy should only check nat on requests that it receives from UAs, not from other proxies, because it should be other proxies' job to take care of their own UAs.
Yes, right :)
Iñaki Baz Castillo writes:
Ok, but for non natted TCP dialogs the usage of "alias" (supported by SR) is a working (and really standarized) solution.
if i understood correctly there just a couple of drafts (no rfc) about alias, and i don't see a point in having two mechanism for the same thing: one for non-nated requests and another for nated and if ua is using tcp or udp.
anyway, what i though is this:
- when request comes in, script always calls alias_contact() on it. alias_contact() checks if request has contact header and if not, does nothing. if request has contact header, alias_contact() adds ;alias=ip:port param to contact uri containing received ip:port if contact ip:port does not match received ip:port. otherwise it does nothing.
- before any in-dialog request is t_relayed, script calls handle_alias() function that checks if r-uri has ;alias param and if so, removes it and sets $du.
this is very simple for the script writer. the only thing that remains to do in the script is to check if incoming invite request comes from behind nat and if so, arm mediaproxy/rtpproxy. of course, if you like, you don't have to call alias_contact() on requests that use tcp and don't come from behind nat, but call force_tcp_alias() instead.
any more comments before i start writing those two functions?
-- juha
Juha Heinanen writes:
- when request comes in, script always calls alias_contact() on it. alias_contact() checks if request has contact header and if not, does nothing. if request has contact header, alias_contact() adds ;alias=ip:port param to contact uri containing received ip:port if contact ip:port does not match received ip:port. otherwise it does nothing.
turns out that there already exists a nathelper function very close to what i propose above: add_rcv_param(). the difference is that it does not check if there is a need to add any. also, nat_uac_test() does not have that kind of test (contact ip:port matches received ip:port).
-- juha
El Domingo, 8 de Noviembre de 2009, Juha Heinanen escribió:
Iñaki Baz Castillo writes:
Ok, but for non natted TCP dialogs the usage of "alias" (supported by SR) is a working (and really standarized) solution.
if i understood correctly there just a couple of drafts (no rfc) about alias, and i don't see a point in having two mechanism for the same thing: one for non-nated requests and another for nated and if ua is using tcp or udp.
anyway, what i though is this:
when request comes in, script always calls alias_contact() on it. alias_contact() checks if request has contact header and if not, does nothing. if request has contact header, alias_contact() adds ;alias=ip:port param to contact uri containing received ip:port if contact ip:port does not match received ip:port. otherwise it does nothing.
before any in-dialog request is t_relayed, script calls handle_alias() function that checks if r-uri has ;alias param and if so, removes it and sets $du.
this is very simple for the script writer. the only thing that remains to do in the script is to check if incoming invite request comes from behind nat and if so, arm mediaproxy/rtpproxy. of course, if you like, you don't have to call alias_contact() on requests that use tcp and don't come from behind nat, but call force_tcp_alias() instead.
any more comments before i start writing those two functions?
I think it's ok.
Iñaki Baz Castillo writes:
Well, as it's not so complex it makes sense. Just a question: is it easy to add a *URI* parameter into Contact header?
it is not that difficult, but i very much would like to see in sr generic transformations for uri handling. now there are transformations to access various parts of uri, but nothing to change anything, e.g., add param to uri, remove param from uri, etc. if we had those, no new functions would be need to be written for this.
-- juha
Juha Heinanen schrieb:
Iñaki Baz Castillo writes:
I would suggest to add a ";received=SOURCE_IP:SOURCE_PORT" to the Contact URI (not to the header). In this way the in-dialog requests from the caller/callee would look like:
BYE sip:alice@PRIVATE_IP:PRIVATE_PORT;received=SOURCE_IP:SOURCE_PORT SIP/2.0
yes, thats better. RR solution would need double-RR to handle the situation.
inaki,
sound ok to me. if other people don't find any problems with this, should we write a new version of fix_nated_contact that adds the param to contact uri or just try to use existing scripting means (remove contact hf, add a new modified one)?
There are already some related functions which maybe can be extended:
There is encode_contact and decode_contact. It has another use case- but maybe could be extended (it would be good to have a function which can do both, adding "received" and encoding, as having 2 functions mangling contact will probably fail): http://www.kamailio.org/docs/modules/1.5.x/siputils.html#id2511673
Regarding the RR solution. There is already half the work done in path module: http://www.kamailio.org/docs/modules/1.5.x/path#id2452987
regards klaus
So SR could route based on this RURI parameter and keep the original Contact as RURI.
i haven't checked if it would be possible to do that in the script (extract and remove received param from r-uri and set $du) or would a new function need to be written for that too.
-- juha
sr-dev mailing list sr-dev@lists.sip-router.org http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-dev
On Nov 07, 2009 at 08:38, Juha Heinanen jh@tutpro.com wrote:
I?aki Baz Castillo writes:
I would suggest to add a ";received=SOURCE_IP:SOURCE_PORT" to the Contact URI (not to the header). In this way the in-dialog requests from the caller/callee would look like:
BYE sip:alice@PRIVATE_IP:PRIVATE_PORT;received=SOURCE_IP:SOURCE_PORT SIP/2.0
inaki,
sound ok to me. if other people don't find any problems with this, should we write a new version of fix_nated_contact that adds the param to contact uri or just try to use existing scripting means (remove contact hf, add a new modified one)?
fix_nated_register() does just that in nathelper(s): it adds a received="uri" parameter to the contacts of a REGISTER, where uri looks like: sip:src_ip:src_port;[transport=...;]dstip=local_ip:local_port .
We would only need to change the function name from fix_nated_register() to fix_contacts().
So SR could route based on this RURI parameter and keep the original Contact as RURI.
i haven't checked if it would be possible to do that in the script (extract and remove received param from r-uri and set $du) or would a new function need to be written for that too.
I have somewhere a function that does just that (using the above format). I used it a long time ago for load balancing (IIRC lb added received="..." to nated contacts when forwarding to the proxies behind it and removed "received" from r-uri, set the proper send socket based on dstip and the destination based on the received=uri when forwarding a message from a proxy to the outside world). I can create a new module for it (if it's not already in one of them).
Andrei
Andrei Pelinescu-Onciul writes:
I have somewhere a function that does just that (using the above format). I used it a long time ago for load balancing (IIRC lb added received="..." to nated contacts when forwarding to the proxies behind it and removed "received" from r-uri, set the proper send socket based on dstip and the destination based on the received=uri when forwarding a message from a proxy to the outside world). I can create a new module for it (if it's not already in one of them).
andrei,
there is a long thread on this and the needed functions have already been written.
the only function that is missing is one that returns the number of rr uris in the message. do you happen to have that somewhere in your closet? it would be highly appreciated.
-- juha
On Nov 09, 2009 at 13:08, Juha Heinanen jh@tutpro.com wrote:
Andrei Pelinescu-Onciul writes:
I have somewhere a function that does just that (using the above format). I used it a long time ago for load balancing (IIRC lb added received="..." to nated contacts when forwarding to the proxies behind it and removed "received" from r-uri, set the proper send socket based on dstip and the destination based on the received=uri when forwarding a message from a proxy to the outside world). I can create a new module for it (if it's not already in one of them).
andrei,
there is a long thread on this and the needed functions have already been written.
You will need also to save the local ip:port on which the packet is received by the proxy. They will be needed when forwarding a packet with and alias in r-uri, to make sure the same socket/ip:port will be used for sending (or else it won't work with nats if you have several listen addresses).
the only function that is missing is one that returns the number of rr uris in the message. do you happen to have that somewhere in your closet? it would be highly appreciated.
No, I don't have anything for counting rr uris.
Andrei
Andrei Pelinescu-Onciul writes:
You will need also to save the local ip:port on which the packet is received by the proxy. They will be needed when forwarding a packet with and alias in r-uri, to make sure the same socket/ip:port will be used for sending (or else it won't work with nats if you have several listen addresses).
i only have one public listen address, which i force in requests to UAs. if you have, for example, a separate listening address for gateways, you will know when request is going to such and you can force that instead.
the only function that is missing is one that returns the number of rr uris in the message. do you happen to have that somewhere in your closet? it would be highly appreciated.
No, I don't have anything for counting rr uris.
i'll write it tomorrow.
-- juha
Andrei Pelinescu-Onciul schrieb:
On Nov 09, 2009 at 13:08, Juha Heinanen jh@tutpro.com wrote:
Andrei Pelinescu-Onciul writes:
I have somewhere a function that does just that (using the above format). I used it a long time ago for load balancing (IIRC lb added received="..." to nated contacts when forwarding to the proxies behind it and removed "received" from r-uri, set the proper send socket based on dstip and the destination based on the received=uri when forwarding a message from a proxy to the outside world). I can create a new module for it (if it's not already in one of them).
andrei,
there is a long thread on this and the needed functions have already been written.
You will need also to save the local ip:port on which the packet is received by the proxy. They will be needed when forwarding a packet with and alias in r-uri, to make sure the same socket/ip:port will be used for sending (or else it won't work with nats if you have several listen addresses).
Isn't that already handled by record-routing? AFAIK RR header contains the socket on which the request was received, and if incoming and outgoing socket differ, then double-RR is used. Thus, isn't the send-socket not already set after loose_route()?
This already works fine with fix_nated_contact(), and the new alias_... functions do not change routing, the just preserve the original contact URI.
regards klaus