Archive for the ‘brute force attack’ tag
Automatically Block Failed SIP Peer Registrations
Previously we posted a little script for quickly checking your asterisk log for failed peer registrations. Building on that script, and with the use of iptables and cron, you can easily (and automatically) block flooding traffic from your system. Iptables, a linux command line program to filter IP traffic, provides high level packet filtering before the traffic can be used to corrupt a program. Cron, the linux time scheduler, enables you to automatically run commands at scheduled time periods.
Set up IP Tables
We will not be discussing the intricacies of iptables in this post. There are excellent tutorials on iptables, and with most things linux, help is only a google away. To help identify the traffic blocked as asterisk related, a new chain will be created appropriately called… asterisk.
Here’s how to add the new chain:
iptables -N asterisk iptables -A INPUT -j asterisk iptables -A FORWARD -j asterisk
This will help identify hosts blocked for failed registrations.
Asterisk’s Log for Failed Registrations
In most cases of a sip flood attack, the host attempts registration to Asterisk. These hosts are identified in the Asterisk log (/var/log/messages) as “No matching peer found.” The following perl script scans /var/log/messages for these patterns, strips the IP address, and puts the IP address into an array.
After the file has been read, the IP addresses are counted (each count is a failed attempt), compared against the existing blocked hosts, and new occurrences are blocked. With this script we are blocking any host after the 4th failed attempt.
Here’s the script (last updated 05 SEP 2010):
#!/usr/bin/perl -w
use strict;
use warnings;
my (@failhost);
my %currblocked;
my %addblocked;
my $action;
open (MYINPUTFILE, "/var/log/asterisk/messages") or die "\n", $!, "Does log file file exist\?\n\n";
while (<MYINPUTFILE>) {
my ($line) = $_;
chomp($line);
if ($line =~ m/\' failed for \'(.*?)\' - No matching peer found/) {
push(@failhost,$1);
}
if ($line =~ m/\' failed for \'(.*?)\' – Wrong password/) {
push(@failhost,$1);
}
}
my $blockedhosts = `/sbin/iptables -n -L asterisk`;
while ($blockedhosts =~ /(.*)/g) {
my ($line2) = $1;
chomp($line2);
if ($line2 =~ m/(\d+\.\d+\.\d+\.\d+)(\s+)/) {
$currblocked{ $1 } = 'blocked';
}
}
while (my ($key, $value) = each(%currblocked)){
print $key . "\n";
}
if (@failhost) {
&count_unique(@failhost);
while (my ($ip, $count) = each(%addblocked)) {
if (exists $currblocked{ $ip }) {
print "$ip already blocked\n";
} else {
$action = `/sbin/iptables -I asterisk -s $ip -j DROP`;
print "$ip blocked. $count attempts.\n";
}
}
} else {
print "no failed registrations.\n";
}
sub count_unique {
my @array = @_;
my %count;
map { $count{$_}++ } @array;
map {($addblocked{ $_ } = ${count{$_}})} sort keys(%count);
}
Schedule the script with cron
The final step is to schedule your script to run every X minutes in cron. We’ve chosen to run our script every 2 minutes, but you can change this to 1 minute or any other time period you choose. Just remember… you can receive thousands of attempts within 2 minutes.
If you have named your script check-failed-regs.pl and placed it in your /usr/local/bin directory, your cron statement would look like this:
*/2 * * * * perl /usr/local/bin/check-failed-regs.pl &> /dev/null
Questions? Comments? We love feedback. Or, contact us for more information.
Perl Script for Asterisk Failed Peer Registrations
I guess this might be better titled as the Quick and Dirty Perl Script… but here we go:
#!/usr/bin/perl -w
use strict;
use warnings;
my (@failhost);
open (MYINPUTFILE, "/var/log/asterisk/$ARGV[0]") or die "\n", $!, "Does log file file exist\?\n\n";
while (<MYINPUTFILE>) {
my ($line) = $_;
chomp($line);
if ($line =~ m/\' failed for \'(.*?)\' - No matching peer found/) {
push(@failhost,$1);
}
}
if (@failhost) {
&count_unique(@failhost);
} else {
print "no failed registrations.\n";
}
sub count_unique {
my @array = @_;
my %count;
map { $count{$_}++ } @array;
#print them out:
map {print "$_ = ${count{$_}}\n"} sort keys(%count);
}
And while we duck from @Merlyn’s criticisms (although we love his criticism), the basic usage is:
perl [Whatever you named it].pl messages
or perl [Whatever you named it].pl messages.1
Results look like:
184.73.53.22 = 13586
64.76.45.100 = 9895
78.46.87.14 = 9960
Or “no failed registrations.” if you have no failed attempts.