If you have installed FusionPBX from the installation scripts you will notice it has already some fail2ban configurations. If you are using my RPMs, it does not include any kind of this configuration as my philosophy is to specialize in the package to do one thing, not a do-it-all. Anyway, if you are only using FusionPBX with FreeSWITCH as a personal PBX those rules should be more than enough.

I recommend you do a quick reading of my previous fail2ban post where I describe the gap between Layer 7 exposures versus Layer 3 controls. You will understand my thinking.

If you are more serious about your PBX or you are running a business you will find at one point those rules are not enough. I will explain myself a little more. As a commercial service, your exposure to the world is bigger; your domain is advertised, telephones do DNS, HTTP and SIP requests to your servers and sooner than later you will start getting your first kiddy scripts targeting your servers. As you grow, you will find your customers are far from being technical; they do many dumb things (wrong password, because they changed something on the service or inside jobs from tech staff, are some examples) which leads to fail2ban rule executions.

There is nothing more harmful than a bad review from an ignorant customer. They do not know why they are being blocked. So, here is where we need to tun fail2ban and add some important information to pre-block offending IPs.

Basic IPTable Rules

There are some TCP attacks that you can not stop with Fail2ban, they are layer-4 specific such as an invalid combination of the TCP flags. Here there are some rules you should add.

iptables -I INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -I INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -I INPUT -p tcp --tcp-flags ALL ALL -j DROP
iptables -I INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
iptables -I INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
iptables -I INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -I INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP

The Security Due Diligence Logic

The logic is easy as follows,

  1. The IP is checked against fail2ban, if fail2ban finds an offending IP that is not white-listed then the connection is dropped, otherwise, it continues the evaluation.
  2. The IP is then checked against a semi-static white list, if the IP is listed then the connection is accepted, otherwise, it continues the evaluation.
  3. The IP is then checked against a semi-static black-list, if the IP is listed then the connection is dropped, otherwise, the connection is accepted.

Fail2ban will review constantly the logs, and if a rule is fired, then it will review if the offending IP is auto-whitelisted. I will use this capability to prevent the customer from harming himself. This scenario is very common with customers with multiple extensions behind a single link (remember the NAT, one public IP serving many private ones). Fail2ban and FreeSWITCH will only see the public IP reported by the logs, therefore I highly recommend accepting the risk of having an offending device in a customer network rather than cancelling the service. The problem is when fail2ban acts, it is hard to realize why as there is not any evidence to find the reason. There are other ways to find an offending device within a white-listed network. I will write another article about that.

Dynamic Whitelists & Fail2ban Configuration

Whitelisting Registered Users' IPs

Dynamic whitelists, as explained before fail2ban can auto-include or auto-exclude an IP from the whitelist. This feature is very handy these days when the NAT is used.

You will need to get the FreeSWITCH filters. The best way to get them is from the GitHub website of FusionPBX. You will need to enable systemd journal support and add the ignorecommand parameter pointing to the customized script.

To do this, you need to write a customized script to get the answer like the one I am sharing with you:

 

#!/bin/bash
mc_server='localhost'
mc_port=11211
mc_ttl=300
key="registration_$1"
#v=`echo -e "get $key\r" | nc $mc_server $mc_port | awk '/^VALUE $1/{a=1;next}/^END/{a=0}a'`
v=$(echo -e "get $key\r" | nc localhost 11211 | grep -v '^VALUE'|grep -v '^END')
#echo $key: $v
if [ -z "$v" ]; then
/usr/bin/fs_cli -x 'show registrations' | /usr/bin/cut -d',' -f 6 | /usr/bin/tail -n +2 | /usr/bin/head -n-2 | /usr/bin/sort -u | /usr/bin/grep $1
if [ $? -eq 0 ]; then
val=$(date)
let bytes=$(echo -n "$val"|wc -c)
echo -e "set $key 0 $mc_ttl $bytes\r\n$val\r" | nc $mc_server $mc_port
/usr/bin/logger $1 whitelisted and stored in memcached as $key
exit 0
else
/usr/bin/logger $1 NOT whitelisted
exit 1
fi
else
/usr/bin/logger $1 whitelisted from memcached as $key
exit 0
fi

Modify your fail2ban jails to call this script.

UPDATE: This opens to a question: how to handle misconfigured extensions or inside jobs? I have addressed that in my article that talks about how to handle attacks on your FreeSWITCH/FusionPBX behind NATs.

Unhandled Incoming Calls

If your FusionPBX deployment is not brand new and you have been updating it from older releases, you are likely missing the not-found dial plan. Add a dial plan in the public context with the following characteristics:

  • order 999
  • context public
  • log action WARNING [inbound routes] 404 not found ${sip_network_ip}

This will allow the FusionPBX / FreeSWITCH 404 filter to work properly.

Let's pre-screen using the VoIP BlackList

The diagram talks about some semi-static whitelists and blacklists. This is archived using the VoIP Blacklist service. A service which it is free, without guarantee but it helps us to pre-screen some offending IPs reported by other users.

The whitelist will help us to prevent any service cut from an IP that could be assigned to any customer. For example, if your service is targetting Australia, you would like to whitelist all Australian IPs, later you will need to put another kind of control, but for now, you will not block any Australian source.

The blacklist works with inverse logic, if the IP is listed, the connection is dropped automatically.

You can use the script I have modified from the original published at www.voipbl.org.

#!/bin/bash 
# Check if chain exists and create one if required
if [ `iptables -L | grep -c "Chain BLACKLIST-INPUT"` -lt 1 ]; then
 echo 'Creating BLACKLIST-INPUT'
 /sbin/iptables -N BLACKLIST-INPUT
 /sbin/iptables -D INPUT -j BLACKLIST-INPUT
 /sbin/iptables -I INPUT 1 -j BLACKLIST-INPUT
fi


# Empty the chain
echo 'Empting BLACKLIST-INPUT'
/sbin/iptables -F BLACKLIST-INPUT
/sbin/iptables -A BLACKLIST-INPUT -j RETURN
echo 'Importing BLACKLIST-INPUT'
# modify this line to add your BL/WLs
wget -qO - 'http://www.voipbl.org/update/?wc[]=CA&wc[]=US' |\
 awk '{print "if [ ! -z \""$1"\" -a \""$1"\" !=  \"#\" ]; then /sbin/iptables -I BLACKLIST-INPUT -s \""$1"\" -j DROP;fi;"}' | sh

/usr/bin/systemctl restart fail2ban

Install it, I recommend you put a crontab that reloads every four hours.

What's next?

At this point, your FusionPBX (FreeSWITCH) should be hardened enough allowing your customers to always have service. But, if you want to close any open doors, you can do the following:

  1. Block port 5060 to allow only incoming connections from countries your customers are from. If you do not have anyone from Korea, there is no point in allowing IPs from that country
  2. Block port 5080 to allow only incoming connections from your upstream carrier. If you are not using any eNUM technique, it is smart to block all but trust IPs. I am pretty sure your upstream carrier can give you the signalling IP.

Remember you can always contact me if you need this done for you.

Good luck! 

";