I realized I haven’t written anything about VoIP yet in this blog. It is a very interesting subject and a great way to deliver your employer decent “buck for bang” once you get to know how it works. In this post I will explain how to configure a public DDI (direct dial in) number to point to your mobile phone.
- Asterisk PBX
- SIP/IAX2 client for Android/IOS (anything from the app store)
EDIT: this solution had some isssues. Ironing them out is explained here.
The idea is to get a DDI via SIP trunk through any VoIP provider. Some used to offer this service for free, I got it from a good colleague in London. Yes, I will be using a London based number in this case, but the geo-location is agnostic to this proof of concept. Here’s how it would work:
[PSTN Cloud] –(POTS)– [VoIP Vendor] –(SIP/Internet)– [VPS/Asterisk] –(SIP/3G)– [Mobile/SIP-client]
PSTN Cloud is the network over which regular landline phones operate. POTS is the plain old telephony system, again – the landlines. VoIP Vendors integrate POTS with the Internet and as a result I can purchase a DDI like (+44) 0207 1234 567. The VoIP Vendor will pass calls to my number by initiating a SIP session to my VPS (virtual private server) IP address, where I will have my Asterisk PBX listening on the SIP and RTP ports specified.
I will summarize security concerns later, for now focusing on the functional side. I use the SIP protocol in this example, although IAX2 is a good alternative. For Asterisk to handle incoming connections, little configuration is needed. I need to have two peers configured in sip.conf. One for my vendor, and one for my SIP client on the mobile phone. The SIP client would. as per the standard, register every 60 seconds to ensure Asterisk has a recent enough IP address to which it could redirect incoming calls. Here’s an example (comments start with semi-colon):
root@rzski ~ # cat /etc/asterisk/sip.conf
; general, security and performance settings
context=nonexistent ; in case someone gets up to here, they will not be able to make any costly calls.
Then, naturally Asterisk needs to know how to handle the incoming connections. This is achieved in extensions.conf.
root@rzski ~ # cat /etc/asterisk/extensions.conf
exten => 442071234567,1,Dial(SIP/context_for_mobile,,)
exten => 442071234567,n,Hangup()
There are hundreds of other settings that Asterisk can use, it’s power comes from the excellent customization options and flexibility. I recommend reading the well commented configuration file samples bundled with the source code, as well as visiting the online documentation on Digium’s wiki pages.
Finally, I’d need to configure the SIP client on the mobile. All it takes is to specify the IP:Port, username:password of the VPS and job done.
I mentioned I will use iptables. Asterisk is great at many things, but it only has basic countermeasures for cyber threats. It is optimal to deal with the security issues as much as possible on the network level and leave the session security and functionality layer to Asterisk.
I try to keep my iptables neat – default policy is set to DROP and only a few rules to enable chosen traffic. While for the vendor-VPS communication it is fairly simple – I can white-list connections based on the source IP address (the vendor’s) and the destination port/protocol (to accept SIP and RTP traffic only from them), the other half becomes a bit more problematic. Over 3G or LTE, my mobile can pick a lot of various IP addresses.
I could narrow the area down using GeoIP module, which would allow me to connect from a single country only, but that’s still not ideal. I’m open for a whole country and, what if I travel?
Another option is to simply tighten the password and use fail2ban. While fail2ban works great in many areas, on a busy server having a system daemon working on 50 log in attempts per second is just not the type of workload I want on my server. Plus, they all get a few tries before future connections are dropped, polluting the log files.
I believe security is always a compromise of performance/comfort, but should always be considered depending on the use case. In my case, I control 2 ends: the VPS and the mobile. All I need to do is ensure these two have a token they both know about and filter everything else out. Such token could be a certificate, but I’d need to spend some time coding that into the SIP client. I decided to use the string matching module for iptables to only allow traffic coming from my client based on it’s UserAgent ID. Each (well written) client tries to identify itself with a vendor string when communicating with the server and so do many SIP clients. Even better if that string can be configured – in such case you can append some non-trivial string which then you can tell iptables to allow on exclusive basis.
To obtain or verify the string used in communication between the phone and the server, it would be required to temporarily enable SIP debug (sip set debug on) and review the messages.
### Mobile SIP and RTP access
/sbin/iptables -N SIPREG
/sbin/iptables -A INPUT -p udp --dport 5060 -j SIPREG
/sbin/iptables -A SIPREG -m string --string 'User-Agent: whatever' --algo bm -j ACCEPT
/sbin/iptables -A SIPREG -j DROP
# RTP range
/sbin/iptables -A INPUT -d $PUB_IP -p udp -m udp --dport 5500:5600 -j ACCEPT
And in case something starts spoofing the string somehow (what’s the chance) and try to guess the password, we can throttle that:
# SIP brute force
/sbin/iptables -I INPUT -p udp --dport 5060 -m recent --set --name ASTERISK
/sbin/iptables -I INPUT -p udp --dport 5060 -m recent --update --seconds 15 --hitcount 10 --name ASTERISK -j DROP
Note the SIP user agent string check is in a separate chain to allow managing this traffic in the right order.
One potential pitfall would be if your phone updates the client and thus re-sets the string you’re looking for. Matter of caution.
And that should be all needed to get inbound calls directly to your mobile. Questions / comments / concerns?