If you run an Asterisk server which has the SIP ports exposed to the internet you have probably already noticed a ton of probes, connects which try to initiate calls to numbers with various prefixes. Although this doesn't do much harm if you did your homework and configured your Asterisk properly, it's still annoying. Here is how I deal with those:

sip.conf

The first thing to do is to make sure that unauthorized calls don't land somewhere arbitrary but in a context where we can control them. Hence, in sip.conf, we should set a specific general context:

[general]
context=incoming_guest

In my case that is "incoming_guest".

Guest-context

The easiest way of dealing with those unauthorized calls is to just reject them or dump them into an endless music-on-hold-loop to slow down potential probe scripts. However, I also want guests to be able to call me without having an account on my PBX. So this is my context definition in the dialplan:

[incoming_guest]
exten => stefan,1,Set(CDR(accountcode)="I_GUEST_STEFAN")
exten => stefan,2,Macro(GetCID)
exten => stefan,3,set(CALLERID(all)=GST:${CALLERID(name)} <${CALLERID(num)}>)
exten => stefan,4,Goto(stefan_cd,s,1)
exten => stefan,5,Hangup

exten => _XXXXXXX.,1,Goto(illegal,${EXTEN},1)
exten => _XXXXXXX.,2,Hangup

exten => i,1,Goto(illegal,${EXTEN},1)
exten => i,2,Hangup
exten => t,1,Congestion
exten => t,2,Hangup

Let's have a look at this in detail:

The first thing I do, is define the extension "stefan", so guest can call me at sip:stefan(at)serveraddress. This extension doesn't do much more than set an account-code for the call detail record, check, if we know the caller ID and then add "GST:" in front of the caller ID name. Then it jumps to the contect "stefan_cd" which handles the further call distribution, based on on day and time. The next extension is _XXXXXXX. which reads as "any extension with 7 or more digits". Strictly this is not necessary - the i-extension could handle everything else but I have some future ideas there :). So, this extension sends the caller to the same extension in the context "illegal". Finally, the i-extension also sends any invalid extension (i.e. any extension not defined in this context) to the "illegal" context.

Illegal-context

Now it's time to have some fun:

[illegal]
exten => _X.,1,System(echo "`date +"%Y-%m-%d %H:%M:%S"` Unauthenticated user ${CHANNEL(from)} (source IP: ${CHANNEL(peerip)}) tried to initiate unauthorized SIP call to ${EXTEN} - blocked" >> /var/log/asterisk/illegal.log)
exten => _X.,2,Answer()
exten => _X.,3,Wait(1)
exten => _X.,4,Playback(my/thankyou_illegal_use)
exten => _X.,5,Playback(my/unfortunately_not_stupid)
exten => _X.,6,Playback(my/ofcourse_no_free_access)
exten => _X.,7,Playback(my/pleasenote_IP_recorded)
exten => _X.,8,Playback(my/policeandisp_informed_shortly)
exten => _X.,9,Playback(my/thankyou_attention)
exten => _X.,10,Playback(my/haveaniceday)
exten => _X.,11,Wait(1)
exten => _X.,12,Hangup

The first thing, this context does, is write a line to /var/log/asterisk/illegal.log, recording the from URI and the source IP of the attacker and the number he tried to call. This is evaluated by failed2ban (see below). Then, we are having some fun. The call is accepted and a few audio files are played, telling the caller that his attempt of illegally abusing this PBX has been recorded and the information is being forwarded to his provider and the police.

fail2ban

Of course, we don't want to make any empty promises, so now it's time for fail2ban to kick in. For that, I have defined the follwing new filter in /etc/fail2ban/asterisk-illegal.conf:

# Fail2Ban configuration file
#
# Author: Stefan Gofferje
#
# $Revision: 728 $
#

[INCLUDES]
# Read common prefixes. If any customizations available -- read them from
# common.local
before = common.conf

[Definition]
_daemon = asterisk

# Option:  failregex
# Notes.:  regex to match the password failures messages in the logfile. The
#          host must be matched by a group named "host". The tag "<HOST>" can
#          be used for standard IP/hostname matching and is only an alias for
#          (?:::f{4,6}:)?(?P<host>[\w\-.^_]+)
# Values:  TEXT
#
failregex = ^%(__prefix_line)sUnauthenticated user .* \(source IP: <HOST>\) tried to initiate unauthorized SIP call to .* - blocked$

# Option:  ignoreregex
# Notes.:  regex to ignore. If this regex matches, the line is ignored.
# Values:  TEXT
#
ignoreregex =

The only thing that's now left to do, is to activate this filter and define the appropiate actions in /etc/fail2ban/jail.conf:

[asterisk-illegal]
enabled  = true
filter   = asterisk-illegal
action   = iptables[name=Asterisk, port=sip, protocol=udp]
           sendmail-whois[name=Asterisk, dest=root@xxxxx, sender=root@xxxxx]
           complain[logpath=/var/log/asterisk/illegal.log]
logpath  = /var/log/asterisk/illegal.log
bantime = 86400
maxretry = 5

That triggers an alarm-mail to root after 5 such calls, as well as an automatic complaint mail to the provider of the attacker and finally, the IP is being blocked by iptables. Case closed.