Wednesday, May 25, 2011

Dynamically Restrict Access to Asterisk SIP 5060 using iptables

We have an asterisk deployment where we have users who work from home so their phones need to be able to connect to asterisk remotely.  In order to limit the number of security threats to our system we lock it down by using the permit and deny settings of SIP Peers to make sure that only those users can get in.

In order to do this for external users we originally allowed every IP to connect, simply relying on using very strong random passwords (40+ character random passwords, unique per extension), and fail2ban to block repeated attempts.  This has been working for us for the last year and a half but I decided to take our security one step further and lock it down to the exact IP of the phone.

We use Aastra 6731i and 6757i devices which have the ability to grab a URL when they boot up, the startup event.  In the aastra.cfg you would have this line:
action uri startup: http://asteriskpbx/aastraphone.php?action=register&ext=$$SIPUSERNAME$$

This tells the phone to grab aastraphone.php at startup.  We use this to keep track of phones, so I decided I would use it to add an addtional layer of IP security to our system.

First, you need to have access to iptables from your web server (or you can pass commands another way, this is a quick and dirty method).

Install & Configure Sudo
apt-get install sudo
add the following lines to /etc/sudoers
#give access to iptables
Cmnd_Alias IPT=/sbin/iptables

#give access to iptables to the account apache is running under, for me www-data
# User privilege specification

Build aastraphone.php
This will insert an allow rule for the given IP at the top of the input chain.  It will not be removed automatically, so you should probably use some mechanism for going through and cleaning up these entries.  A quick and dirty method would be to put the allow rules in a chain and then flush the chain nightly.  The next time the phone polls the web page it would then be re-authorized for access.  Not a great solution, but for 9-5 shops it would work great at midnight.  A more elegant solution would be to track them in a database and check the database every once in a while for IP's that need to be removed.  

Additionally, the realtime version of this is able to check and see if an IP is supposed to be allowed to connect in from the outside world, this solution does not do that it assumes that if the phone knows how to get to the aastraphone.php file that it is allowed to connect externally.  Because of this it is important to have configured the permit and deny options in sip.conf to prevent peers from being used externally if they shouldn't.

$ext = $_REQUEST['ext'];
if($ext > 0 && is_numeric($ext)){
system("sudo /sbin/iptables -I INPUT 1 -s {$_SERVER['REMOTE_ADDR']} -p udp --dport 5060 -j ACCEPT");

Configure IPTables Default Rules
Your system will need to be configured to allow internal hosts to connect, and reject external hosts to connect to your SIP port by default.  Using the following commands should handle this for you.  Using the related/established rule is important so that your communication with your SIP providers stays fully functional.
#by default block all access from the outside work to your asterisk system
iptables -A INPUT -s -d -m state --state INVALID -j DROP
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -I INPUT -p udp --dport 5060 -s -j ACCEPT #allow all 192.168.x.x hosts to connect
iptables -I INPUT -p udp --dport 5060 -j DROP #block all others that don't match a rule.  Alternatively you could use the default policy for input drop.
iptables -I INPUT -p tcp --dport 80 -j ACCEPT #allow web traffic for the aastraphone.php file to function

This solution assumes you leave the web server open to the world, as the phones will need to be able to get to that to gain access to SIP/5060.  

No comments:

Post a Comment