Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

FreeBSD, IPFW and the SIP/VoIP NAT problem

349 views
Skip to first unread message

O. Hartmann

unread,
Sep 26, 2017, 4:36:19 AM9/26/17
to
Hello,

trying to build a FreeBSD based router/PBX (Asterisk 13) appliance, I ran into
several problems. My questions might have a "noobish" character, so my apology,
my experiences with IPFW are not as thorough as they should be.

Before I'll got into medias res, aquestion about Pine64/AARCH64:

- port net/asterisk13 is supposed to build only on armv6, is aarch64 about
coming soon also supported?
- would a Pine64 running CURRENT (12) be sufficient as a PBX platform (assumed
having 2 GB of RAM)?

My main concern is about IPFW (we do not use PF for some reasons, I have to
stay with IPFW).

I'm a customer of two ITSPs and my SoHo network is behind NAT and not yet IPv6.
The FreeBSD system acting as a router is supposed to have a jail soon
containing the Asterisk 13 IP PBX (at the moment running on the main system).
To provide access to the VoIP infrastructure inside/behind the router/NAT
system, the in-kernel NAT facility of FreeBSD is forwarding the relevant
UPD/TCP ports for VoIP to its destination network, and here I have a problem to
solve.

While it is sumple and easy to forward 5060/udp, 5070/tcp and other ports, it
is a mess and pain in the arse to forward a whole range, say 11000/udp -
35000/udp, which is a range one of my providers is sending RTP on. A second
provider uses another range for RTP, starting at 5000/udp. So, the logical
consequence would be a union set up UDP range to forward, which exapnds then
form 5000/udp to 45000/udp - which is much more a pain ...

One of the most disturbing and well known problems is that due to the stateful
firewall the RTP session very often is half duplex - it seems one direction
of the RTP connection doesn't make it through IPFW/NAT. As often I search the
net, I always get informed this is a typical problem and solutions are
provided by so called ALGs - since SIP protocol's SDP indicates within the
payload of the packets on which UDP ports both ends wish to establish their
RTP session, it would be "easy" to pinhole the IPFW on exactly those ports for
a theoretical large number of sessions, if IPFW could "divert" those packets
to an instance inspecting SDP (or whatever is used for the RTP port
indication, I'm new to that, sorry for the terminology) and then pinholing the
NAT/IPFW for exactly this purpose without the forwarding mess. I came along
netgraph() while searching for hints and hooks, but it seems a complete Linux
domain, when it somes to appliances like VoIP/IP PBX.

Either, the problem is that trivial on FreeBSD, so no further mentioning is
necessary (which would explain the vast emptyness of explanations, hints and
so on) or FreeBSD is a complete wasteland on this subject - which I also
suspect, since pfSense and OPNsense must have come along with such problems
and I simply do not know or recognise the software used for those purposes.

So, if someone enlightened in this matter stumbles over my question and could
delegate me onto the right way (ports, ng_XXX netgraph ficilities to look at,
some ipfw techniques relevant to the problem apart from the stupid simple
forwarding large ranges of ports) - I'd appreciate this and

thanks in advance for patience and help,

Oliver
_______________________________________________
freebsd...@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-curre...@freebsd.org"

Damjan Jovanovic

unread,
Sep 26, 2017, 5:01:34 AM9/26/17
to
On Tue, Sep 26, 2017 at 10:35 AM, O. Hartmann <ohar...@walstatt.org>
wrote:
Hi

It might be easier if you just enable STUN on Asterisk, and build FreeBSD
from source with my [largely neglected :( ] patch on
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=219918

That way Asterisk should dynamically discover consistent external mappings
for connections, making port forwarding RTP unnecessary.

Damjan

O. Hartmann

unread,
Sep 26, 2017, 8:35:35 AM9/26/17
to

O. Hartmann

unread,
Sep 26, 2017, 9:30:25 AM9/26/17
to
On Tue, 26 Sep 2017 11:27:05 +0200
Guido Falsi <madp...@FreeBSD.org> wrote:

> On 09/26/2017 10:35, O. Hartmann wrote:
> > Hello,
> >
> > trying to build a FreeBSD based router/PBX (Asterisk 13) appliance, I ran
> > into several problems. My questions might have a "noobish" character, so my
> > apology, my experiences with IPFW are not as thorough as they should be.
> >
> > Before I'll got into medias res, aquestion about Pine64/AARCH64:
> >
> > - port net/asterisk13 is supposed to build only on armv6, is aarch64 about
> > coming soon also supported?
>
> I'm maintaining the asterisk ports. At present I don't have any ARM64
> hardware to test it on, but I plan to create an ARM64 jail in poudriere
> so I can try to make it at least build there.

Hello Guido,

I posted by accident the question again to this list as I introduced a typo
when sending it also to the IPFW list. I'm sorry.

I already tried to build net/asterisk13 on my AARCH64 jail, but since I'd like
to have the databases/postgresql96-client aboard and this specific port fails
to build, I gave up - it is, by the way, the only port (pgsql) as far as I
know that fails in my poudriere cross compiling jail. I did not get further,
but I saw that it is supposed to build only for amd64 and armv6.

>
> In such a case would you be willing to test port changes on the hardware
> to actually check it runs?

I'd like to if the efforts are not to much time consuming - I do not have a
working Pine64 image anymore, but I have a Pine64 with 2GB RAM at hand. Months
ago I started playing with cross compiling world/kernel for AARCH64, but I'm
not familiar with crochet and preparing the SD image - but willing to do. But
beware: my home box preparing the cross cimpilation is not the fastest!

>
> > - would a Pine64 running CURRENT (12) be sufficient as a PBX platform
> > (assumed having 2 GB of RAM)?
>
> That very much depends on the kind of load you are expecting.
>
> Asterisk can process a lot of calls. Especially if it can avoid being
> in the media path.

For the moment, the ARM based PBX should perform SoHo tasks - three, up to ten
lines at maximum.

>
> On the other hand if you plan doing a lot of audio transcoding or some
> video transcoding, load can get up quite fast. Compressed codecs like
> the "simple" G729 will make your load grow relatively fast even with
> audio transcoding. Transcoding also lowers call quality so it should
> anyway be avoided as much as possible.

Good to know. But the PBX is more like an experiment for "at home's PBX" and,
if applicable, later for some fellows working scientifically in field and in
need for some small and neat equipement. Video message/streaming is not so much
the focus on the first attempts, but if possible, welcome. if not: not so
tragic.

>
> Also load can go up if you're doing many disk operations. Monitoring and
> saving audio for a bunch of calls can be quite heavy on disk resources
> AND could require additional transcoding.

There are Linux fellows running Asterisk 13 on raspberry Pi3 very successfully
and this little box has only 1GB RAM as far as I know. Why should FreeBSD fail?

>
> >
> > My main concern is about IPFW (we do not use PF for some reasons, I have to
> > stay with IPFW).
> >
> > I'm a customer of two ITSPs and my SoHo network is behind NAT and not yet
> > IPv6. The FreeBSD system acting as a router is supposed to have a jail soon
> > containing the Asterisk 13 IP PBX (at the moment running on the main
> > system). To provide access to the VoIP infrastructure inside/behind the
> > router/NAT system, the in-kernel NAT facility of FreeBSD is forwarding the
> > relevant UPD/TCP ports for VoIP to its destination network, and here I have
> > a problem to solve.
> >
> > While it is sumple and easy to forward 5060/udp, 5070/tcp and other ports,
> > it is a mess and pain in the arse to forward a whole range, say 11000/udp -
> > 35000/udp, which is a range one of my providers is sending RTP on. A second
> > provider uses another range for RTP, starting at 5000/udp. So, the logical
> > consequence would be a union set up UDP range to forward, which exapnds then
> > form 5000/udp to 45000/udp - which is much more a pain ...
>
> The asterisk project has some suggestions on this here [1]

I know those references as I'm with the problem now for a couple of months ...

>
> RTP with NAT+FW is a pain. I'm not aware of any IPFW tools able to
> actively inspect SIP packets (which could also be encrypted if using
> SIPS, so there would be no clean way to inspect them).
>
> Depending on your phone providers you could use a stun and/or turn
> server by enabling the ICE protocol [2], which are all technologies
> supported by asterisk, but require support from your provider. Another
> option is symmetric RTP, which is a trick by creating symmetric port
> numbers connections which sometimes can trick firewalls properly configured.
>
> You setup also forces you to keep asterisk in the media path
> (direct_media=no in peer configuration)

I know. It is configured that way and it works well with one of my providers,
which has "ingres" calls via 10000/udp through 30000/udp. By simply doing a
forwarding of these portranges in the IPFW rules for the NAT section, my
firewall is open on that range! And this open range grows larger with the
second provider, which has another range on which its RTP communications is
attempting to establish ingress calls.

>
> Unluckily none of these technologies is 100% bulletproof.
>
> RTP is not made to play well with NAT, so the professional solution is
> to spare an IP and redirect almost all ports to the SIP/RTP box. Also
> it's much better to do this with static rules, to avoid load problems on
> the FW (see later).
>
>
> You can sidestep the whole issue by running a proxy on your firewall
> machine, if you have control of it. There are a few in the ports tree.
>
> Take a look at:
>
> net/kamailio - It is really a SIP proxy, but can parse SIP/SDP packets
> and modify their content on the fly, allowing you to play neat tricks.
> Requires some knowledge of the protocol and work though. (maybe you can
> get him to punch holes in the firewall, but I have not checked if it's
> possible)
>
> net/rtpproxy: this is more specific and maybe your best bet. Beware of
> the load of proxying RTP in userland though.

Yes, I'm aware of the problemacy regarding NAT and RTP. The problem is the
pinholing of IPFW.


>
>
> >
> > One of the most disturbing and well known problems is that due to the
> > stateful firewall the RTP session very often is half duplex - it seems one
> > direction
>
> Depending on how many simultaneous SIP calls you plan to manage keep an
> eye on your firewall too. each call will create at least 3 states, one
> for SIP and one for each leg of the RTP stream, so it can pile up quite
> fast.
>
> > of the RTP connection doesn't make it through IPFW/NAT. As often I search
> > the net, I always get informed this is a typical problem and solutions are
> > provided by so called ALGs - since SIP protocol's SDP indicates within the
>
> This would require coding it in IPFW, and the load on the firewall could
> be significant.
>
> It could be done in userland maybe, leveraging divert(4) and having a
> daemon listening there and doing the extra work, but this would be quite
> expensive. Depending on your call volume the load could be too much for
> your firewall.

I thought this specific "divert" could be handled by some ng_XXX thingies of
the netgraph() suite?

As far as I know: egress calls open the IPFW in a stateful manner for the
desired UDP ports (two of them if RTCP is not used, otherwise four, in and out)
and if the prerequisite symmetric rtp is enforced and respected, the "other
side" should send back RTP via the already opened ports.

More complicated is the inbound/ingress direction, since the IPFW doesn't know
about the desired UDP ports for RTP (or TCP, doesn't matter here), so somehow
my(!) PBX has to open the IPFW some ways - and I thought this could be done by
an inspection of SDP. I might be wrong here, since I havn't studied the
protocol in deep.

Linux folks talk about a "tracking of communications" - if I recall right. It
sounded to me as they have in IPtables some facility doing exactly this
inspecting stuff.

>
> > payload of the packets on which UDP ports both ends wish to establish their
> > RTP session, it would be "easy" to pinhole the IPFW on exactly those ports
> > for a theoretical large number of sessions, if IPFW could "divert" those
> > packets to an instance inspecting SDP (or whatever is used for the RTP port
> > indication, I'm new to that, sorry for the terminology) and then pinholing
> > the NAT/IPFW for exactly this purpose without the forwarding mess. I came
> > along netgraph() while searching for hints and hooks, but it seems a
> > complete Linux domain, when it somes to appliances like VoIP/IP PBX.
> >
> > Either, the problem is that trivial on FreeBSD, so no further mentioning is
> > necessary (which would explain the vast emptyness of explanations, hints and
> > so on) or FreeBSD is a complete wasteland on this subject - which I also
> > suspect, since pfSense and OPNsense must have come along with such problems
> > and I simply do not know or recognise the software used for those
> > purposes.
>
> I'm not aware of any silver bullets in those products for this.
>
> >
> > So, if someone enlightened in this matter stumbles over my question and
> > could delegate me onto the right way (ports, ng_XXX netgraph ficilities to
> > look at, some ipfw techniques relevant to the problem apart from the stupid
> > simple forwarding large ranges of ports) - I'd appreciate this and
>
> Maybe you could also get fancy with netflow, and that could have a lower
> load but you'd have to create the IP parsing code yourself.
>
> Keep in mind that SIP, being used only for signaling, has a relatively
> low cost on being manipulated(obviously it depends on the load of calls
> being managed but it gets hundreds of calls starting and stopping every
> few seconds to create an heavy SIP traffic).
>
> RTP on the other hand consists on a continuous UDP packet flow, and in
> VoIP it means two for each call, which count directly on the PPS
> (Packets per second) load of you networking equipment, performing
> manipulation on those imposes a constant, heavy per connection load on
> the machines performing it, so you should try to use static FW rules and
> perform no further processing on it unless you have very low call
> volume(let's say that more that 10 through firewall performing extra
> manipulation on RTP streams is starting to be non trivial) or
> appropriate hardware.

All correct and I'd like to go with static rules as far as I can go (on the
other hand, I do not know how IPFW is going to be forced into using dynamic
rulesets on this specific matter ...).

But I think the trivial concern here is the worst case in the RTP/NAT scenario:
how to pinhole (or punchhole?) the IPFW? As I said above, one provider
expects/send RTP from 10000/udp-30000/udp. It is easy to tell asterisk to use
10000-30000 via config rtp.conf. Again: as I understand outgoing connections,
IPFW is opened "statefully" on the desired port and with symmetric RTP, media
data flow on both ends on the same ports. But how is the incoming/ingress case
handled? By forwarding the SIP signalling (and this means, the IPF is
inherently opened for this port), incoming call request contains the desired
RTP ports. In the stateful firewall case, asterisk now should try to contact
the other side exactly via those both ports. But one of those ports is supposed
to be the receiving port, so the asterisk could never establish a stable
outgoing connection - and here is the problem, how to open IPFW (without
ALG/inspecting) - or any stateful firewall? Either my understanding is
completely bullshit or ...
>
>
> Hope this all helps.
>
>
> [1]
> https://wiki.asterisk.org/wiki/display/AST/Configuring+res_pjsip+to+work+through+NAT
>
> [2]
> https://wiki.asterisk.org/wiki/display/AST/Interactive+Connectivity+Establishment+%28ICE%29+in+Asterisk
>


Thank you very much.

Kind regards,

Damjan Jovanovic

unread,
Sep 26, 2017, 10:27:42 AM9/26/17
to
On Tue, Sep 26, 2017 at 3:44 PM, O. Hartmann <o.har...@walstatt.org>
wrote:
> STUN is enabled, but my providers do not support STUN.
>
> I try to figure out how SIP works exactly to make my problem more precise.
> I
> also try to understand the aim of your patch - as far as I know, it does
> exactly as it is needed for the IPW/NAT/VoIP case. And I really regret that
> there are objections to commit the patch ...
>
>
Firstly, if your providers support NAT, you register to them (as opposed to
they register to you, or no registration), and the only VoIP calls are
to/from your providers and to/from the same IP:port you register to (as
opposed to unknown external addresses), then none of this should be
necessary. Just put these on every SIP peer in Asterisk (this is for
chan_sip; not sure about chan_pjsip):

directmedia=no
nat=force_rport,comedia

and register to your provider more often than your NAT timeout is (eg.
every minute), and you should be good. Why? Every registration opens a NAT
mapping that your provider can use to send you calls on. The provider will
also send RTP to the source IP:port it received it from, so when you start
sending RTP you will get RTP back even if it's arriving from an unexpected
IP:port. NAT is not a big problem for SIP clients, only for SIP providers
that have receive packets from unknown addresses.

Otherwise...

Why would your providers need to support STUN? Applications first use STUN
to discover the external IP:port of their internal IP:port, and then
communicate that IP:port to the other side however they usually would (eg.
headers in SIP and SDP packets) - the other side doesn't know or care that
they were discovered through STUN. Any STUN server anywhere on the Internet
can be used for this and should give the same results; see
https://www.voip-info.org/wiki/view/STUN for a list.

My patch ensures UDP NAT hole punching logic can be used properly. With it,
if a packet was sent from an internal IP:port through an external IP:port
(eg. to a STUN server), then any future packet from that internal IP:port
to any other external server:port will go out the same external IP:port,
and no other internal IP:port will use that external IP:port. It's like the
internal IP:port temporarily owns the unique external IP:port and can send
and receive through it to and from anywhere. The same source IP:port will
be seen by all servers, and they can send back to it.

O. Hartmann

unread,
Sep 26, 2017, 1:25:19 PM9/26/17
to
On Tue, 26 Sep 2017 11:00:45 +0200
Damjan Jovanovic <damja...@gmail.com> wrote:

STUN is enabled, but my providers do not support STUN.

I try to figure out how SIP works exactly to make my problem more precise. I
also try to understand the aim of your patch - as far as I know, it does
exactly as it is needed for the IPW/NAT/VoIP case. And I really regret that
there are objections to commit the patch ...

O. Hartmann

unread,
Sep 27, 2017, 7:42:30 AM9/27/17
to
On Tue, 26 Sep 2017 16:26:51 +0200
My providers do support NAT, I suppose, I'm sure with one. Not so
sure about the iberian Telefonica/O2 - they claim, but they are a kind of not
willing to provide substantial informations as they want to force customers to
use the (crap) equipment they offer.

Very often, calling from the outside through the NAT/firewall to the PBX, I
have this half-duplex phenomenon well described in many palces regarding NAT.
In most cases I can hear the answering machine/voicemail from the PBX, but I
can not send an audio stream inside.

When my PBX register to its provider, how is the RTP port port for the ingress
media stream (from the view of my PBX) opened? As I understand stateful IPFW,
someone from the inside needs first to punchhole the firewall. I must confess,
I have a bit of an understanding problem here since I do know know the
protocol. Is there anything on the net explaining this scenario? RFC3261 is
describing SIP, but not the registration ...

>
> directmedia=no
> nat=force_rport,comedia

In chan_pjsip, I found these settings important for NAT on peers in avrious
places on the net:

rtp_symmetric= yes
;rtp_keepalive= 30 (not sure about
; the timing here, I use this
value)
force_rport= yes
rewrite_contact= yes
timers= yes
direct_media= no
disable_direct_media_on_nat= yes

>
> and register to your provider more often than your NAT timeout is (eg.
> every minute), and you should be good. Why? Every registration opens a NAT
> mapping that your provider can use to send you calls on. The provider will
> also send RTP to the source IP:port it received it from, so when you start
> sending RTP you will get RTP back even if it's arriving from an unexpected
> IP:port. NAT is not a big problem for SIP clients, only for SIP providers
> that have receive packets from unknown addresses.

I tried to find lifetime settings or timeout, the only (documented) values I
founf were located in ipfw(8):

net.inet.ip.fw.dyn_ack_lifetime: 300

net.inet.ip.fw.dyn_syn_lifetime: 20

net.inet.ip.fw.dyn_fin_lifetime: 1

net.inet.ip.fw.dyn_rst_lifetime: 1

net.inet.ip.fw.dyn_udp_lifetime: 10

net.inet.ip.fw.dyn_short_lifetime: 5
>
> Otherwise...
>
> Why would your providers need to support STUN? Applications first use STUN
> to discover the external IP:port of their internal IP:port, and then
> communicate that IP:port to the other side however they usually would (eg.
> headers in SIP and SDP packets) - the other side doesn't know or care that
> they were discovered through STUN. Any STUN server anywhere on the Internet
> can be used for this and should give the same results; see
> https://www.voip-info.org/wiki/view/STUN for a list.

I can use the STUN of an other provider, but not sure this is necessary, since
both providers I'm consumer do not offer STUN themselfes.

>
> My patch ensures UDP NAT hole punching logic can be used properly. With it,
> if a packet was sent from an internal IP:port through an external IP:port
> (eg. to a STUN server), then any future packet from that internal IP:port
> to any other external server:port will go out the same external IP:port,
> and no other internal IP:port will use that external IP:port. It's like the
> internal IP:port temporarily owns the unique external IP:port and can send
> and receive through it to and from anywhere. The same source IP:port will
> be seen by all servers, and they can send back to it.


That sounds plausible, but implies that, say the PBX behind the NAT at
IP1:port, is not guaranteed to send exclusively via external IP2:port?

Damjan Jovanovic

unread,
Sep 27, 2017, 8:13:47 AM9/27/17
to
On Tue, Sep 26, 2017 at 11:27 AM, Guido Falsi <madp...@freebsd.org> wrote:

> On 09/26/2017 10:35, O. Hartmann wrote:
>
> > of the RTP connection doesn't make it through IPFW/NAT. As often I
> search the
> > net, I always get informed this is a typical problem and solutions are
> > provided by so called ALGs - since SIP protocol's SDP indicates within
> the
>
> This would require coding it in IPFW, and the load on the firewall could
> be significant.
>
> It could be done in userland maybe, leveraging divert(4) and having a
> daemon listening there and doing the extra work, but this would be quite
> expensive. Depending on your call volume the load could be too much for
> your firewall.
>
>
SIP headers like Proxy-Authorization need to send a cryptographic quality
hash of data that includes the password and the SDP when qop=auth-int, and
the ALG needs to change the IP address and port in the SDP, which changes
this hash. The ALG would have to know your password to calculate the new
hash.

A SIP ALG can thus only work with the weaker qop=auth protection, which
doesn't hash the SDP and is thus less secure (MITM attacks can
capture/modify RTP in transit), and even then it would have to be careful
not to change the SIP headers which are included in the hash.

Since it is the provider that chooses the allowed qop, a general SIP ALG is
impossible unless the ALG knows the password.

Linux has a SIP ALG in iptables, and it's full of problems and best
disabled.

Damjan Jovanovic

unread,
Sep 27, 2017, 8:18:11 AM9/27/17
to
On Wed, Sep 27, 2017 at 1:16 PM, O. Hartmann <o.har...@walstatt.org>
Both sides usually send RTP to each other. When you send RTP through your
NAT to a provider supporting NAT, it should see where you are externally
sending from, and send its future RTP packets back there, even if that
isn't the (internal) IP:port you previously said you would use in your SDP.

This can obviously break in some cases:
- If the voice is intentionally one-way throughout the call, such as
phoning out into an announcement service that intentionally says "sendonly"
in its SDP, so you aren't sending any RTP to it and its RTP can't route
back to you.
- If you use out of band ringback and transfer out an inbound call before
it's answered, so the call hairpins from the provider through you and back.
You have to send RTP to open NAT mappings, but you have nothing to send, as
you first need to receive it, but can't as the NAT mappings aren't open: a
cycle you can't exit.

For those cases, NAT traversal can't be transparent, you have use some kind
of software negotiated NAT traversal: static port forwarding and set
Asterisk's external signaling and media addresses, use STUN with cone NAT
(my patch + STUN/ICE settings in Asterisk's rtp.conf, sip.conf, etc.), or a
NAT traversal protocol such as UPNP or NAT-PMP with supporting software
(which Asterisk currently isn't).
With my patch, every packet from IP1:port1 will be routed out of IP2:port2,
no matter what the destination. Of course software must be written to
detect IP2:port2 for every new socket using something like STUN, and report
IP2:port2 to other parties it wants traffic from.
0 new messages