From owner-freebsd-current@freebsd.org Wed Sep 27 11:26:30 2017 Return-Path: Delivered-To: freebsd-current@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id B18F4E31841 for ; Wed, 27 Sep 2017 11:26:30 +0000 (UTC) (envelope-from madpilot@FreeBSD.org) Received: from mail.madpilot.net (grunt.madpilot.net [78.47.145.38]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5C1046E392 for ; Wed, 27 Sep 2017 11:26:29 +0000 (UTC) (envelope-from madpilot@FreeBSD.org) Received: from mail (mail [192.168.254.3]) by mail.madpilot.net (Postfix) with ESMTP id 3y2Frf6TnkzZrX; Wed, 27 Sep 2017 13:26:26 +0200 (CEST) Received: from mail.madpilot.net ([192.168.254.3]) by mail (mail.madpilot.net [192.168.254.3]) (amavisd-new, port 10024) with ESMTP id L89Cb7_6eqUK; Wed, 27 Sep 2017 13:26:24 +0200 (CEST) Received: from marvin.madpilot.net (micro.madpilot.net [88.149.173.206]) by mail.madpilot.net (Postfix) with ESMTPSA; Wed, 27 Sep 2017 13:26:24 +0200 (CEST) Subject: Re: FreeBSD, IPFW and the SIP/VoIP NAT problem References: <20170926103543.0aa03c7a@freyja.zeit4.iv.bundesimmobilien.de> <20170926152955.205a012c@freyja.zeit4.iv.bundesimmobilien.de> Cc: FreeBSD CURRENT To: "O. Hartmann" From: Guido Falsi Message-ID: <38f78ee1-0946-f094-e9a2-42798f656cf4@FreeBSD.org> Date: Wed, 27 Sep 2017 13:26:24 +0200 User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:52.0) Gecko/20100101 Thunderbird/52.3.0 MIME-Version: 1.0 In-Reply-To: <20170926152955.205a012c@freyja.zeit4.iv.bundesimmobilien.de> Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Sep 2017 11:26:30 -0000 Sorry the top posting but Before anything else I need to state a few points. First this post is getting quite VoIP and asterisk specific, so please direct any further replies to me at my email. We're off subject on this list. Also before giving specific answers I need to clarify a few details about SIP/SDP and RTP, since, from your message it looks like you have some misconceptions about some details. In specific how RTP connection endpoints are negotiated and how the connections actually happen after that. (I'll make a general description to be sure everything is clear) SIP accepts connections on only one port (UDP usually but TCP is also supported), 5060 by default, but can be changed. This IP:port combination is what is registered with people wanting to call you, be it SIP REGISTER on a provider, a DNS SRV record, a blind connection on 5060 to an IP returned by an A record or manual registration via your provider website. (these are all method I've seen actually used, there may be others) After the caller connects via SIP to the called party they negotiate the connection. The "media channel" is usually negotiated by embedding SDP packets in the SIP exchange (it's all plain text, you can actually sniff it from the asterisk console, and in fact it's often necessary to be done to understand problems). There is absolutely no rule forcing RTP to be used as the media channel protocol, there are also others, but for phone calls that's what is usually negotiated. But RTP is a different protocol whose only relation to SIP is it being commonly used to actually relay the voice communication between endpoints. RTP is strictly defined to use UDP transport and is a monodirectional protocol, so for VoIP communication you need two RTP channels (or connections if you prefer), one for inbound and one for outbound. In the SDP negotiation each party (there no differentiation between caller and called party) will state where he expects the other party to send it's audio. Various information will be exchanged, including protocol audio format but most important for us IP:port. After negotiation each party performs the connection to the other. Let me rephrase: Your asterisk will be telling your provider to which IP:port is should send it's UDP connection for the audio stream, so you can't control where you are connecting (but that's not a problem, NAT correctly handles that) you have FULL CONTROL of the UDP port range the provider MUST use to connect to you (that is unless they are getting out of their way with a non compliant implementation, in such a case, look for a better provider). That said your situation is quite easy to solve without any special firewall configuration except redirecting a small (50-100) number of UDP ports of your choice. In real world situations this is quite handy since you rarely have full control of the router/firewall and many times all you get is a basic DSL modem/router with very limited FW/NAT functionality. On the other hand if you actually need thousands of UDP ports(that is thousands of simultaneous calls), most probably you also can get a static IP address for your PBX. On 09/26/2017 15:29, O. Hartmann wrote: > On Tue, 26 Sep 2017 11:27:05 +0200 > Guido Falsi wrote: > > 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! > Actually, I don't have ARM64 hardware available right now and no ARM64 jail right now, maybe in a not to distant future I'll have that and be able to perform specific tests, but things standing as they are I cannot state anything definitive on this subject. > For the moment, the ARM based PBX should perform SoHo tasks - three, up to ten > lines at maximum. So you need at most 1 port for SIP and 20 for RTP...a 50 ports range will have space to spare. > >> >> 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. For 2-3 calls I think even a PCEngine or arm64 will have horsepower to spare, even for video calls, unless you go too fancy with resolution. >> >> 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? What do you mean by fail? Having said I don't have such hardware, does asterisk crash on that hardware? Does calls get lost? If the only problem that you mean by "fail" are NAT problems with the media path, that's common in many setups, and there are solutions. > 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. As explained in the start of the message you are misunderstanding how things work here. That's the range you must use to connect to them, but, unless they are using non conforming SIP/SDP and RTP implementations, YOU choose the port range they must connect to you. Specifically with asterisk that range is defined in rtp.conf: [general] rtpstart=10000 rtpend=10050 (choose whatever you like, just avoid the low ports below 1024) Only problem is in SDP asterisk sends a IP:port combination, putting you own machine IP in there. That means it's putting there the LAN IP. If your IP address is static this is easy to resolve, in pjsip.conf you have the directives: external_media_address=1.2.3.4 external_signaling_address=1.2.3.4 local_net=172.16.0.0/12 you can put in your transports, and sip.conf has: localnet=172.16.0.0/12 externaddr = 1.2.3.4 With these you are telling asterisk to always announce the "1.2.3.4" IP when asking for inbound connections to IPs outside the local net. With dynamic IPs things are more tricky. There is no easy way to put the correct dynamic address in those variables and changing tham on the fly will require an asterisk restart(which is not really a big problem since by changing IP you already lost any ongoing calls and invalidated any existing registration). The dynamic IP case is where STUN TURN and ICE become very handy. ICE is quite handy, you just enable it, configure a STUN and, in available, TURN server, and it augments the SDP communication with extra information. It can make things work out of the box in quite complicated situations, even with no redirections on the firewall, but it requires support by both parties, so it could not be an option. But, having configured rtp as above and redirected that range on the firewall, not all is lost. You should check the res_stun_monitor module and it's configuration. There are free stun servers around the internet, so you should be able to use this even if your upstream does not provide it. I don't think it is supported by the pjsip module so in that case you should use the old sip module. >> 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. Creating dynamic holes in IPFW is not necessary in 99% of times. As stated if you have low traffic you can just redirect a small range, if you have high traffic you should be able to afford a dedicated IP. Again remember that YOU control the inbound port range for RTP. Forwarding an high range is not really that risky either, those ports will be anyway closed on the asterisk box until it's expecting some connection, the only problem is that forwarding them causes load on the firewall and doing that with dynamic rules exposes you to DoS via dynamic rule exhaustion. So especially with an high range you should use static FW rules, not the other way round. Also note that in a professional settings there rarely is available a firewall with hole punching functionality on the client premises. People who actually need and have that CAN afford an extra IP usually. Not of lesser importance, there is no way to look at SIPS (SIP+TLS, so encrypted packets) content without terminating the SIP connection, that is you can't just watch inside the packets on the fly is using secure communication. That said if you really want to go the dynamic FW hole punching even if it has no professional use except edge cases and is quite more complicated, error prone and easy to break you should really check out the two ports i Suggested, especially kamailio. Kamailio is a SIP proxy, It will terminate your provider SIP connection and perform all the negotiations(so it can work with secure connections too), giving you a language in which you can check what is negotiated and even change it. I'm not sure but I think it will also allow you to launch scripts during it's negotiations. Such scripts could perform the actual hole punching. Kamailio will NEVER touch the RTP stream, so it will connect to asterisk via SIP informing it of the incoming call and your provider while keeping sending SIP packets to kamailio, will directly connect to asterisk and asterisk directly to your provider for the RTP streams. This is all perfectly standard and catered for by the SIP protocol > > 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 ... Again: look at kamailio, it speaks SIP and can be used to do the inspection. Otherwise, for the inspection solution, there is nothing ready that I'm aware of in FreeBSD. There isn't code in IPFW able to parse SIP/SDP, nor there is a netgraph module with such ability. You should write it yourself. But I think they are not really needed. I hope this helps you understand better what is going on and what are your options. Also gives you material to study further maybe. -- Guido Falsi