Skip to content

Instantly share code, notes, and snippets.

@xopr
Last active April 16, 2020 03:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save xopr/9482982786fde3d21fcf5b3ada97a6ee to your computer and use it in GitHub Desktop.
Save xopr/9482982786fde3d21fcf5b3ada97a6ee to your computer and use it in GitHub Desktop.
auto block IP based registrations and invites in FreeSWITCH
#!/usr/bin/env perl
# Blocks IP adresses in 3 steps:
# * unknown REGISTER (Can't find user) is blocked immediately
# * unauthorized INVITE is flagged (and blocked after 3 strikes)
# * authorized INVITES are unflagged (and the IP block is removed when the counter hits 0 (or less))
# * IP based incoming call which is not from a trunk (defined in ACL) is blocked immediately
# this needs some adjustments in the FS config:
# An ACL list of ip adresses of trunks that setup calls to you: <list name="trunks" default="deny">
# Log entry before any public.xml include
# <extension name="IP based call">
# <condition field="${acl(${network_addr} trunks)}" expression="false"/>
# <condition field="${sip_to_host" expression="${local_ip_v4}">
# <action application="log" data="WARNING IP based INVITE not from trunk ${network_addr}"/>
# <action application="respond" data="403"/>
# </condition>
#</extension>
# Mofified auth+flag entry after the public.xml includes
#<extension name="check_auth" continue="true">
# <condition field="${sip_authorized}" expression="^true$" break="never">
# <anti-action application="log" data="WARNING flag unauthorized: ${network_addr} (from ${sip_from_uri} to ${sip_to_uri})"/>
# <anti-action application="respond" data="407"/>
# </condition>
#</extension>
# unflag entry after the default.xml unloop part
#<extension name="authorized" continue="true">
# <condition>
# <action application="log" data="WARNING unflag unauthorized: ${network_addr} (from ${sip_from_uri} to ${sip_to_uri})"/>
# </condition>
#</extension>
use strict;
use warnings;
my %hits = ();
open(my $fd, "<", "/var/log/freeswitch/freeswitch.log") or die "Can't open log";
while(1)
{
if(eof $fd)
{
sleep 1;
$fd->clearerr;
next;
}
my $line = <$fd>;
chomp($line);
if( $line =~ /^.*?Can\'t find user \[.+@\d+\.\d+\.\d+\.\d+\] from (\d+\.\d+\.\d+\.\d+).*?$/ )
{
if ( exists $hits{$1} )
{
$hits{$1}++;
}
else
{
print "Blocking $1..\n";
$hits{$1} = 1;
system("/sbin/iptables -A INPUT -s $1 -j DROP -m comment --comment \"AUTOBLOCK\"");
}
print ( "Register error: $1 ($hits{$1} hits)\n" );
}
elsif( $line =~ /^.*? flag unauthorized: (\d+\.\d+\.\d+\.\d+) \(from .*?$/ )
{
if ( exists $hits{$1} )
{
$hits{$1}++;
}
else
{
#print "Marking $1..\n";
$hits{$1} = 1;
}
print ( "Unauthorized: $1 ($hits{$1} hits)\n" );
if ( $hits{$1} == "3" )
{
print "marking $1\n";
system("/sbin/iptables -A INPUT -s $1 -j DROP -m comment --comment \"AUTOBLOCK\"");
}
}
elsif( $line =~ /^.*? unflag unauthorized: (\d+\.\d+\.\d+\.\d+) \(from .*?$/ )
{
if ( exists $hits{$1} )
{
$hits{$1}--;
}
else
{
#print "Unmarking $1..\n";
$hits{$1} = 0;
}
print ( "Authorized: $1 ($hits{$1} hits)\n" );
if ( $hits{$1} <= "0" )
{
$hits{$1} = 0;
print "unmarking $1\n";
system("/sbin/iptables -D INPUT -s $1 -j DROP -m comment --comment \"AUTOBLOCK\"");
}
}
elsif( $line =~ /^.*? IP based INVITE not (?:from trunk|in ACL) (\d+\.\d+\.\d+\.\d+).*?$/ )
{
if ( exists $hits{$1} )
{
$hits{$1}++;
}
else
{
print "Blocking $1..\n";
$hits{$1} = 1;
system("/sbin/iptables -A INPUT -s $1 -j DROP -m comment --comment \"AUTOBLOCK\"");
}
print ( "Invite error: $1 ($hits{$1} hits)\n" );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment