Using iptables to Enhance Asterisk Security

Being directly exposed to the Internet can wreak havoc on a server. It seems that people will attempt to crack any machine that has Internet presence, so it's important to lock that server down as much as possible. Most software has configurable settings that can minimize the risk footprint. FreePBX, for example, under Settings/Adsterisk SIP Settings gives the administrator the option to set both "Allow SIP Guests" and "Allow Anonymous Inbound SIP Calls" to "No" (which is highly recommended, once a server is up and running, though they can be useful in debugging a newly-created server). But, when possible, it's good to quickly identify and discard potentially malicious packets and prevent the application software from even having to see them. That's our goal here!

iptables is some kernel-based packet-filtering software that has been included in Linux since early in the 2.4 kernel days. It is some great software that can really help to lock a machine down by inspecting packets and only allowing packets that seem to be desirable. It is important to realize that no software is perfect and that it's impossible to create a perfectly secure server, but we can certainly do our best to get as close as possible to that goal.

Following is an example /etc/sysconfig/iptables file from a CentOS 6.4/Asterisk/FreePBX server.


*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:BADSIP - [0:0]
#
# 1- check for and drop suspected malicious SIP packets
#
-A INPUT -p udp -m udp --dport 5060 -m string --string "sundayddr" --algo bm --to 65535 -j BADSIP
-A INPUT -p udp -m udp --dport 5060 -m string --string "sipsak" --algo bm --to 65535 -j BADSIP
-A INPUT -p udp -m udp --dport 5060 -m string --string "sipvicious" --algo bm --to 65535 -j BADSIP
-A INPUT -p udp -m udp --dport 5060 -m string --string "friendly-scanner" --algo bm --to 65535 -j BADSIP
-A INPUT -p udp -m udp --dport 5060 -m string --string "iWar" --algo bm --to 65535 -j BADSIP
-A INPUT -p udp -m udp --dport 5060 -m string --string "sip-scan" --algo bm --to 65535 -j BADSIP
-A INPUT -p udp -m udp --dport 5060 -m string --string "sipcli" --algo bm --to 65535 -j BADSIP
#
# 2- basic allowed packets
#
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
#
# 3- allow SSH connections
#
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT
#
# 4- allow web connections
#
-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT
#
# 5- allow SIP packets that weren't dropped above
#
-A INPUT -m udp -p udp --dport 5060 -j ACCEPT
# 
# 6- allow IAX2 packets
#
-A INPUT -m udp -p udp --dport 4569 -j ACCEPT
#
# 7- allow RTP packets 
#
-A INPUT -m udp -p udp --dport 10000:20000 -j ACCEPT
#
# 8- reject all packets not already accepted
#
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
#
# 9- log malicious-looking SIP packets, and then drop
#
-A BADSIP -j LOG --log-prefix "iptables-badsip: " --log-level 6
-A BADSIP -j DROP
COMMIT

Section 1 scans inbound SIP packets (UDP port 5060, TCP-based SIP and/or alternate port number would be similar) for signatures of potentially malicious packets. It is important to remember that this scanning will only occur on SIP packets, and not on the RTP packets that make up the actual audio of the conversation, so the overhead is not significant.

Section 2 allows all related/established packets (e.g. packets related to connections that our server initiated), ICMP packets, and all packets on the lo interface (an internal, this machine only interface).

Sections 3 through 6 allow for inbound packets for SSH, HTTP (not encrypted), SIP (packets that weren't rejected in the first section), and IAX2 packets (not especially common--it is a protocol like SIP).

Section 7 allows the RTP packets. These are the ones actually carrying the voice conversation. The default configuration for FreePBX is that ports 10000 through 20000 are used for RTP, so we open these up. Note that there will only be a listener for a particular port number when a call is connected.

Section 8 rejects all packets that haven't already been accepted. This example is using the kinder, gentler message of sending back an ICMP message that the packet was not allowed. The other option is to use -J DROP, which simply drops the packet with no response back to the sender

The final section, Section 9, is like a subroutine for packets that we have identified as potentially malicious SIP packets. We log these packets with syslog, and then we drop them. Granted, we could send an ICMP reject packet, like Section 8, but since we think these are likely malicious, it's better to just drop and hope the sender simply thinks that no one is home.

Further Considerations

To further lock things down, installing fail2ban would be recommended. This software tracks unsuccessful attempts to login, and after a certain number of failed attempts, blocks that IP address from trying for a specified period of time. Scanners love to try to connect, which is why strong SIP passwords are recommended. If a server doesn't thwart the attempt, a scanner can keep trying by brute force, day and night, until it finally figures the SIP password

With the exception of SSH, none of this server's connections are encrypted. That means that plain-text passwords can potentially be seen, and voice conversations can potentially be heard. Not completely ideal.