Mediaproxy: dialog module sends BYE to wrong location with NAT

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Mediaproxy: dialog module sends BYE to wrong location with NAT

Phil Vandry
I am using OpenSIPS as a P-CSCF function with NAT traversal support and
mediaproxy (to handle clients that can't open peer-to-peer media streams).
engage_media_proxy() is used together with the dialog module.

I also use standard tricks to handle endpoints behind NAT:
   - When originating from a NATted user, save the original received IP
     address and port in a loose route so that subsequent requests in
     the upstream direction can have their next hop overridden
     (in dsturi)
   - When terminating to a NATted user, rewrite the dsturi to the
     IP address & port that was saved by the registrar in Path (the
     original received IP address and port from when the user
     REGISTERed) and also save it in a loose route for subsequent
     requests
   - For subsequent requests (upstream or downstream), set dsturi as
     appropriate using the parameters in the route

Note: I do not rewrite the Contact header because user agents expect
to have requests addressed to them using the Contact they originally
provided.

Now, the problem:

If the media stream times out, media-dispatcher ends the dialog and the
dialog module synthesizes a BYE in both directions. When the user is
behind NAT, one of the BYEs goes to the wrong place.

The cause of the problem is that the BYE toward the NATted endpoint
goes to the Contact supplied by the endpoint, rather than to the
public IP address & port for the endpoint. There is no way to tell
the dialog module to use an alternate next hop.

The dialog module does save a route set (in each direction) with the
dialog, so I thought there might be a way to record the alternate
next hop into that route set and process it in a manner similar to
other in-dialog requests (see above) but the dialog saves only the
original received route set, not the one augmented by local
record_route() calls. More importantly, the internally generated BYE
requests do not pass through the normal request_route but only
through a special local_route and you are not allowed to override
the dsturi from there.

The only way I can think of to solve this is to make the dialog
module save an optional dsturi with each side of the dialog. For
origination from a NATted user the script must pass a dsturi for
the caller leg and no dsturi for the callee leg, and for termination
to a NATted user the script must pass no dsturi for the caller leg
and a dsturi for the callee leg.

This required source code changes to the dialog module as well as
one small change in the tm module.

How is this problem normally solved?

-Phil

_______________________________________________
Users mailing list
[hidden email]
http://lists.opensips.org/cgi-bin/mailman/listinfo/users
Reply | Threaded
Open this post in threaded view
|

Re: Mediaproxy: dialog module sends BYE to wrong location with NAT

Bogdan-Andrei Iancu
Hi Phil,

You can do some nice tricks with the dialog module (anyhow you already
use it for mediaproxy).

What you can do, instead of using Route hdr as holder for the IP:port of
the nat, you can store this information in the dialog. See
store_dlg_value() and fetch_dlg_value() -
http://www.opensips.org/html/docs/modules/devel/dialog.html#id272552 .

Then, you can use the local_route
(http://www.opensips.org/index.php?n=Resources.DocsCoreRoutes#toc6) to
catch the BYE generated by the dialog module and to set as dsturi the
values you stored in the dialog.

Regards,
Bogdan

Phil Vandry wrote:

> I am using OpenSIPS as a P-CSCF function with NAT traversal support and
> mediaproxy (to handle clients that can't open peer-to-peer media streams).
> engage_media_proxy() is used together with the dialog module.
>
> I also use standard tricks to handle endpoints behind NAT:
>    - When originating from a NATted user, save the original received IP
>      address and port in a loose route so that subsequent requests in
>      the upstream direction can have their next hop overridden
>      (in dsturi)
>    - When terminating to a NATted user, rewrite the dsturi to the
>      IP address & port that was saved by the registrar in Path (the
>      original received IP address and port from when the user
>      REGISTERed) and also save it in a loose route for subsequent
>      requests
>    - For subsequent requests (upstream or downstream), set dsturi as
>      appropriate using the parameters in the route
>
> Note: I do not rewrite the Contact header because user agents expect
> to have requests addressed to them using the Contact they originally
> provided.
>
> Now, the problem:
>
> If the media stream times out, media-dispatcher ends the dialog and the
> dialog module synthesizes a BYE in both directions. When the user is
> behind NAT, one of the BYEs goes to the wrong place.
>
> The cause of the problem is that the BYE toward the NATted endpoint
> goes to the Contact supplied by the endpoint, rather than to the
> public IP address & port for the endpoint. There is no way to tell
> the dialog module to use an alternate next hop.
>
> The dialog module does save a route set (in each direction) with the
> dialog, so I thought there might be a way to record the alternate
> next hop into that route set and process it in a manner similar to
> other in-dialog requests (see above) but the dialog saves only the
> original received route set, not the one augmented by local
> record_route() calls. More importantly, the internally generated BYE
> requests do not pass through the normal request_route but only
> through a special local_route and you are not allowed to override
> the dsturi from there.
>
> The only way I can think of to solve this is to make the dialog
> module save an optional dsturi with each side of the dialog. For
> origination from a NATted user the script must pass a dsturi for
> the caller leg and no dsturi for the callee leg, and for termination
> to a NATted user the script must pass no dsturi for the caller leg
> and a dsturi for the callee leg.
>
> This required source code changes to the dialog module as well as
> one small change in the tm module.
>
> How is this problem normally solved?
>
> -Phil
>
> _______________________________________________
> Users mailing list
> [hidden email]
> http://lists.opensips.org/cgi-bin/mailman/listinfo/users
>
>  


_______________________________________________
Users mailing list
[hidden email]
http://lists.opensips.org/cgi-bin/mailman/listinfo/users
Reply | Threaded
Open this post in threaded view
|

Re: Mediaproxy: dialog module sends BYE to wrong location with NAT

Phil Vandry
On Thu, Mar 05, 2009 at 07:38:28PM +0200, Bogdan-Andrei Iancu wrote:
> What you can do, instead of using Route hdr as holder for the IP:port of
> the nat, you can store this information in the dialog. See
> store_dlg_value() and fetch_dlg_value() -
> http://www.opensips.org/html/docs/modules/devel/dialog.html#id272552 .

Oh, that is very nice. It's like AVPs but they persist for the dialog
instead of only the transaction. I missed it because I am still working
with 1.4.

> Then, you can use the local_route
> (http://www.opensips.org/index.php?n=Resources.DocsCoreRoutes#toc6) to
> catch the BYE generated by the dialog module and to set as dsturi the
> values you stored in the dialog.

No, because the dsturi cannot be changed from within a local_route, see
modules/tm/uac.c line 305 in current SVN revision, and the documentation
confirms it: "Routing and signalling functions are not allowed.".

-Phil

_______________________________________________
Users mailing list
[hidden email]
http://lists.opensips.org/cgi-bin/mailman/listinfo/users
Reply | Threaded
Open this post in threaded view
|

Re: Mediaproxy: dialog module sends BYE to wrong location with NAT

Bogdan-Andrei Iancu
Hi Phil,

Phil Vandry wrote:

> On Thu, Mar 05, 2009 at 07:38:28PM +0200, Bogdan-Andrei Iancu wrote:
>  
>> What you can do, instead of using Route hdr as holder for the IP:port of
>> the nat, you can store this information in the dialog. See
>> store_dlg_value() and fetch_dlg_value() -
>> http://www.opensips.org/html/docs/modules/devel/dialog.html#id272552 .
>>    
>
> Oh, that is very nice. It's like AVPs but they persist for the dialog
> instead of only the transaction. I missed it because I am still working
> with 1.4.
>
>  
>> Then, you can use the local_route
>> (http://www.opensips.org/index.php?n=Resources.DocsCoreRoutes#toc6) to
>> catch the BYE generated by the dialog module and to set as dsturi the
>> values you stored in the dialog.
>>    
>
> No, because the dsturi cannot be changed from within a local_route, see
> modules/tm/uac.c line 305 in current SVN revision, and the documentation
> confirms it: "Routing and signalling functions are not allowed.".
>  
That is correct - I forgot even my own code :D...

With this limitation (maybe I should drop it in the future) it means we
cannot change the routing at BYE time, so what we have to find a way to
do it when the dialog module stores the routing information in the
dialog structure.

If we replace the contact sent by client with the NAT address, will the
client still accept the sequential requests (in your case)?

Regards,
Bogdan


_______________________________________________
Users mailing list
[hidden email]
http://lists.opensips.org/cgi-bin/mailman/listinfo/users
Reply | Threaded
Open this post in threaded view
|

Re: Mediaproxy: dialog module sends BYE to wrong location with NAT

Phil Vandry
On Mon, 09 Mar 2009 13:11:54 +0200, Bogdan-Andrei Iancu wrote:
> With this limitation (maybe I should drop it in the future) it means we
> cannot change the routing at BYE time, so what we have to find a way to
> do it when the dialog module stores the routing information in the
> dialog structure.
>
> If we replace the contact sent by client with the NAT address, will the
> client still accept the sequential requests (in your case)?

I found at least one example where it will not accept the sequential
request. The Cisco 7940 phone running software version P0S3-08-6-00
refuses an in-dialog request to a Request-URI that it doesn't
recognize. I originate a call from this phone and rewrite the Contact
with the NAT public address. When the other end sends a BYE to the
modified (public IP) contact, the Cisco responds with 404 Not found
and the display on the phone shows the call keeps going.

I do not know if the Cisco is the only phone with this problem.

-Phil

_______________________________________________
Users mailing list
[hidden email]
http://lists.opensips.org/cgi-bin/mailman/listinfo/users
Reply | Threaded
Open this post in threaded view
|

Re: Mediaproxy: dialog module sends BYE to wrong location with NAT

Bogdan-Andrei Iancu
Phil Vandry wrote:

> On Mon, 09 Mar 2009 13:11:54 +0200, Bogdan-Andrei Iancu wrote:
>  
>> With this limitation (maybe I should drop it in the future) it means we
>> cannot change the routing at BYE time, so what we have to find a way to
>> do it when the dialog module stores the routing information in the
>> dialog structure.
>>
>> If we replace the contact sent by client with the NAT address, will the
>> client still accept the sequential requests (in your case)?
>>    
>
> I found at least one example where it will not accept the sequential
> request. The Cisco 7940 phone running software version P0S3-08-6-00
> refuses an in-dialog request to a Request-URI that it doesn't
> recognize. I originate a call from this phone and rewrite the Contact
> with the NAT public address. When the other end sends a BYE to the
> modified (public IP) contact, the Cisco responds with 404 Not found
> and the display on the phone shows the call keeps going.
>
> I do not know if the Cisco is the only phone with this problem.
>  
Than, there is no way to do it with the current code. As future solution
I would suggested to make possible with dialog to store kind of OBP for
each leg (to be used for NAT corrections).

Regards,
Bogdan

_______________________________________________
Users mailing list
[hidden email]
http://lists.opensips.org/cgi-bin/mailman/listinfo/users