User Tools

Site Tools


tutorials:security:kamailio-security

This is an old revision of the document!


Overview of Security related config snippets

Author of initial tutorial:
Davy Van De Moere
  <davy.van.de.moere@gmail.com>

A list of config snippets you can use in Kamailio to have more fun with Hackers!

Security by Obscurity

Topoh module

Albeit being a bad principle, obscuring your networks insecurities as a part of a wider scheme is a good way to keep malicious people away from your network.

In Kamailio there is a great module called topoh, read Daniels post here.

It helps you to hide details, typical use cases being:

  • protect the addresses of your PSTN gateways - will protect you against people trying to attack them to get free calls
  • protect your internal network topology - when having a big platform with many servers, you do not disclose their addresses
  • interconnection provider - to keep the details of connected parties secret to the other, to prevent a bypass of its service in the future

(bluntly copied)

loadmodule "/usr/local/lib64/kamailio/modules/topoh.so"
modparam("topoh", "mask_key", "YouDoHaveToChangeThisKey")
modparam("topoh", "mask_ip", "10.0.0.1")
modparam("topoh", "mask_callid", 1)

To further protect the topology of your network, add RTPProxy to your config, this makes sure your Asterisk/FreeSwitch/… boxes can be fully hidden.

Firewalling

Portscans are inevitable, but we can fight back by making sure the portscan takes very long and gives random results, consider an iptables setup like the one below, it needs for sure some tweaking to work for you, but it will make an nmap to your box slow and close to fully useless

*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT DROP [0:0]
:CHECK_TCP - [0:0]
:ICMP - [0:0]
:PRIVATE - [0:0]
:PSD - [0:0]
:SERVICES - [0:0]
-A INPUT -i lo -j ACCEPT 
-A INPUT -i eth0 -p ipv6 -j ACCEPT 
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 
-A INPUT -j SERVICES 
-A OUTPUT -o lo -j ACCEPT 
-A OUTPUT -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT 
-A CHECK_TCP -p tcp -m tcp ! --tcp-flags SYN,RST,ACK SYN -m state --state NEW -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,ACK -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,PSH,URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,ACK FIN -m state --state INVALID,NEW,RELATED -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,RST FIN,RST -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags PSH,ACK PSH -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags ACK,URG URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-option 64 -j DROP 
-A CHECK_TCP -p tcp -m tcp --tcp-option 128 -j DROP 
-A ICMP -p icmp -m icmp --icmp-type 11/1 -m limit --limit 5/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 11/0 -m limit --limit 5/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 3 -m limit --limit 10/sec -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -m icmp --icmp-type 8 -m limit --limit 10/sec --limit-burst 10 -m state --state NEW -j ACCEPT 
-A ICMP -p icmp -j DROP 
-A PRIVATE -d 192.168.0.0/16 -j DROP 
-A PRIVATE -d 172.16.0.0/12 -j DROP 
-A PRIVATE -d 10.0.0.0/8 -j DROP 
-A PRIVATE -j RETURN 
-A PSD -p tcp -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-port-unreachable 
-A PSD -p tcp -m statistic --mode random --probability 0.050000 -j TARPIT  --reset 
-A PSD -p tcp -m statistic --mode random --probability 0.500000 -j TARPIT  --tarpit 
-A PSD -p udp -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-port-unreachable 
-A PSD -m statistic --mode random --probability 0.050000 -j REJECT --reject-with icmp-host-unreachable  
-A SERVICES -p icmp -m state --state INVALID -j DROP 
-A SERVICES -p icmp -j ICMP 
-A SERVICES -p tcp -j CHECK_TCP 
-A SERVICES -p udp -m udp --dport 123 -m state --state NEW -j ACCEPT 
-A SERVICES -p udp -m udp --dport 53 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m tcp --dport 53 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m udp -m multiport --dports 5060 -m state --state NEW -j ACCEPT 
-A SERVICES -p tcp -m udp -m multiport --dports 5061 -m state --state NEW -j ACCEPT 
-A SERVICES -i eth0 -j PSD 
COMMIT

Change the server header

When Kamailio sends you a packet back, it will be friendly enough to tell you which version of Kamailio is running. This informs the attacker which types of attacks might make sense.

You can change this by adding the below line in your config (somewhere above the loadmodules), you can use this to obscure which version you're running.

server_header="Server: MS Lync"

Or you can just tell Kamailio to not put a server header:

server_signature=no

Anti-Flood

The moment you put a machine on the Internet, it will be scanned. And it won't take long until a <i>Friendly-Scanner</i> floods your machine.

Three types of attacks are to be recognized:

1/ bruteforcing username/password:

Your Kamailio setup can process thousands of SIP packets per second, and at those rates it is worthwhile for attackers to guess credentials which allow them to call out. When users are allowed to create their own passwords, there will be weak passwords.

2/ bruteforcing prefixes:

A typical configuration error is to take shortcuts in your config. In SS7 a typical method to arrange routing, is by adding prefixes to URI's. Attackers know this, and attempt to guess prefixes which behave differently.

3/ Denial of Service:

Whenever you have a packet arriving on your Kamailio machine, it will require a bit of time of your CPU. For some packets there is additional processing done, e.g. whenever credentials are checked you can have a query being executed.

When debugging your setup, it can be very annoying when you see thousands of packets passing over your screen. (stealing content from asipto)

Pike

The pike module tracks the number of SIP messages per source IP address, per period. Pike is a very easy to add to your config:

loadmodule "pike.so"
 
...
 
# ----- pike params -----
modparam("pike", "sampling_time_unit", 2)
modparam("pike", "reqs_density_per_unit", 20)
modparam("pike", "remove_latency", 4)
 
...
 
route {
  if (!pike_check_req()) {
    xlog("L_ALERT","ALERT: pike block $rm from $fu (IP:$si:$sp)\n");
    exit;
  }
  ...
}

In recent sample configs you can just enable #!define WITH_ANTIFLOOD in your config to have this done.

Banning for a period of time

You can add htable module with a special hash table that can store the list of banned IPs and forbid traffic from it for a period of time. Here is an example blocking the IP 5 minutes (autoexpires value in seconds for htable definition):

loadmodule "htable.so"
...
modparam("htable", "htable", "ipban=>size=8;autoexpire=300;")
 
...
 
route {
  if($sht(ipban=>$si)!=$null)
  {
     # ip is already blocked - keep the node warm
     pike_check_req();
     xdbg("request from blocked IP - $rm from $fu (IP:$si:$sp)\n");
     exit;
  }
  if (!pike_check_req()) {
     $sht(ipban=>$si) = 1;
     xlog("L_ALERT","ALERT: pike block $rm from $fu (IP:$si:$sp)\n");
     exit;
  }
...
}

So, even if the attacker lowers the rate, it is still banned for 5 minutes. This approach has the benefit of printing the PIKE alert every 5 minutes, being easier to sport in syslog file the IP addresses that persist in flooding. By configuration, htable module will delete the entry automatically after 300sec.

Also, you can print the list of banned IP addresses using Siremis (via MI Commands panel) or kamctl:

kamctl fifo sht_dump ipban

Fail2Ban

Fail2ban can scan syslog files for specific messages based on regular expressions and act upon matching by banning IP addresses.

Therefore you can print such message to syslog using xlog(). Fail2ban will match it and ban the traffic coming from the IP address you mention in the message.

Create /etc/fail2ban/filter.d/kamailio.conf with following content:

[Definition]
# filter for kamailio messages
failregex = Blocking traffic from <HOST>

Edit /etc/fail2ban/jail.conf and add:

findtime  = 600

[kamailio-iptables]
enabled  = true
filter   = kamailio
action   = iptables-allports[name=KAMAILIO, protocol=all]
logpath  = /var/log/kamailio.log # update it with your kamailio log path
maxretry = 10
bantime  = 1800

In Kamailio configuration, use next line whenever you want to ban an IP for half an hour:

xlog("Blocking traffic from $si\n");

Note: $si is a config file variable that expands at runtime to source IP address. In the syslog you will get messages like:

… Blocking traffic from 1.2.3.4 For example, plugging it in the above Kamailio snippets:

...
	$var(exp) = $Ts - 900;
        if($sht(a=>$au::last_auth) > $var(exp))
        {
            sl_send_reply("403", "Try later");
            xlog("Blocking traffic from $si\n");
            exit;
        } else {
            $sht(a=>$au::auth_count) = 0;
        }
...

Now, with this logic, if a user fails to authenticate 3 times in a row during 15 minutes, then the IP address of last registration attempt is blocked in firewall for half an hour by fail2ban.

You can do something similar for pike alerts.

tutorials/security/kamailio-security.1390925384.txt.gz · Last modified: 2014/01/28 17:09 by davy.van.de.moere_gmail.com