[OpenSIPS-Users] Mediaproxy: dialog module sends BYE to wrong location with NAT

Phil Vandry vandry at TZoNE.ORG
Wed Mar 4 19:07:59 CET 2009

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
   - 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

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?


More information about the Users mailing list