[asterisk-dev] PJSIP and RTP address selection

Jaco Kroon jaco at uls.co.za
Tue Sep 18 04:20:18 CDT 2018

Hi Joshua,

Thanks for giving this some thought, I really do appreciate.

I'll aim towards implementing both the first options, users can then
pick for themselves.  I think both the options I've proposed could work,
but one may have benefits over the other that I can't envison currently.

I did actually think of another "trick" over the weekend that could make
RTP seem to come back from the right location, so for reference for
other people (this won't work unless asterisk is set up to assume the
remote side is behind NAT and waits for RTP from source first).

We bind STUN to a single IP in the case here and then DNAT all other IPs
on INPUT to that IP, so say STUN is bound to (basic mode only,
one can probably adjust to make work for full mode too but would be much
more complex since you'd need to inject a related conntrack entry in
some way), then a DNAT like this enables you to utilize basic STUN
against any IP bound on the host:

-A PREROUTING -i bond0 -p udp -m udp --dport 3478 -j DNAT

This creates a conntrack tuple similar to (conntrack -L format, split
over multiple lines):

udp      17 19
   src=original_source dst=original_dest sport=38277 dport=3478
   src= dst=original_source sport=3478 dport=38277
   mark=0 use=1

Given that entry netfilter re-adjusts the source IP on egress from the
host again back to the original incoming destination.  The same should
work even if stun is bound to ANY, you just have to DNAT to the IP that
will be selected by the kernel on egress.

I think the same will hold for RTP, in which case one could perform the
same kind of mapping, out of hand:

-A PREROUTING -i bond0 -p udp -m udp --dport $rtpstart:$((rtpend+1)) -j
DNAT --to-destination

Assuming that is the default source off the box the same should
apply.  It is assumed rtpstart and rtpend is environment variables
containing the values from rtp.conf.

I have not tested this, but I've used this "trick" for things like
multi-homed OpenVPN and other udp based protocols that you really want
to bind to ANY but screws up due to this.  It's a "nasty" solution in my
opinion but it should (might) work.

This solution may retain the benefits of the current configuration that
you were concerned about.  Also, since IPv6 and IPv4 retains independent
entries in the connection tracking table this should still allow jumping
between IPv4 and IPv6 for RTP transport.  In short this might be the
"silver bullet" that you're looking for.  If like me your udp ports is
firewalled to only allow RTP to be received from authenticated sources
this provides some additional protection against rtp bleed type
scenarios.  The downside is that if you suddenly jump between transports
then the firewalling might cause problems.

Anyway, perhaps this is useable to someone, perhaps not.

Kind Regards,

On 2018/09/16 21:18, Joshua Colp wrote:
> On Thu, Sep 13, 2018, at 7:16 PM, Joshua Colp wrote:
>> On Thu, Sep 13, 2018, at 7:00 PM, Matt Fredrickson wrote:
>> <snip - see previous messages for full context, cause this thing is big>
>>>> I have two potential fixes (and two that aren't practical options I
>>>> don't think but might be with knowledge I don't have) both with
>>>> advantages and disadvantages:
> I gave some further thought over this weekend to any other alternative approaches which would have less of an impact but sadly came up empty. I think the list you provided is indeed the available options.

More information about the asterisk-dev mailing list