Welcome to the modern Internet – an Internet of spam and worms.
I’ve come to the conclusion (along with several others) that over 50% of my spam and worm traffic originates from Korea and China.
Which is funny – considering that China has gone to great extremes to build ‘The great firewall of China’ – The least they could do if they were going to oppress their people and keep them from the truth is keep them from the rest of us while they’re at it yeah?
And the Koreans? well.. they don’t seem to care what they do on the net, I’ve sent hundreds of spam notices to abuse mail boxes, never slows it down.
So, after a quick Google. I present you with the code below – inspired by http://www.okean.com/
I know, I could have done “better” and used curl or something, but the idea was to keep it small, compact and with the least amount of dependencies.
I’m also aware I could have just downloaded the dnsbl version of the table I’ve used here… but I’m more just as concerned with bogus ssh traffic as I am with emails
#!/usr/bin/perl
###############################################################################################
## Sinokorea firewall script - v1.0 - Freman
###############################################################################################
## Very simple little script to download, cache and install Okeans list of
## sinokorean ip subnets as an IPTables firewall chain
##
## Once you've run this script simply type
## iptables -I INPUT -j sinokorea
##
## Things you can change...
## List/URLToFetch: The URL to fetch
## List/Cache: The Path to cache it to
## IPTables/Path: Where your IPTables are
## IPTables/ChainName: The IPTables ChainName
## OKPorts: What ports you want to give them access to through the firewall
##
## For more information about the list of IP addresses used by this script please visit the
## Okean website: http://www.okean.com/
##
## To contact me visit my website: http://fremnet.net
###############################################################################################
##
## ChangeLog:-
## 2005-11-01:
## Initial Release
##
###############################################################################################
use Data::Dumper;
use IO::Socket;
use strict;
use vars qw(%Config);
%Config = (
'List' => {
'URLToFetch' => 'http://www.okean.com/sinokoreacidr.txt',
'Cache' => '/tmp/sinokoreacidr.txt',
},
'IPTables' => {
'Path' => '/sbin/iptables',
'ChainName' => 'sinokorea',
},
'OKPorts' => qw/tcp:80/,
);
&DoCache($Config{'List'}{'URLToFetch'},$Config{'List'}{'Cache'});
my $CheckChains = `${Config{'IPTables'}{'Path'}} -L -n | grep ${Config{'IPTables'}{'ChainName'}}`;
if ($CheckChains =~ /${Config{'IPTables'}{'ChainName'}}/) {
system("${Config{'IPTables'}{'Path'}} -F ${Config{'IPTables'}{'ChainName'}}");
} else {
system("${Config{'IPTables'}{'Path'}} -N ${Config{'IPTables'}{'ChainName'}}");
}
foreach my $OKPort (@{Config{'OKPorts'}}) {
my ($Proto,$Port) = split(/:/,$OKPort);
system("${Config{'IPTables'}{'Path'}} -A ${Config{'IPTables'}{'ChainName'}} -p $Proto --destination-port $Port -j RETURN");
}
open(F,"<$Config{'List'}{'Cache'}");
while (my $Line = <F>) {
next if ($Line =~ /^#/);
chomp($Line);
my ($IP,$Area) = split(/ +/,$Line);
system("${Config{'IPTables'}{'Path'}} -A ${Config{'IPTables'}{'ChainName'}} --destination $IP -j DROP");
}
system("${Config{'IPTables'}{'Path'}} -A ${Config{'IPTables'}{'ChainName'}} -j RETURN");
sub DoCache {
my $URL = shift;
my $CacheFile = shift;
my $Updated = &GetCacheStamp($CacheFile);
my $NewDate = &GetDate($URL);
if (!($NewDate eq $Updated)) {
my %Data = &FetchURL($URL,'GET');
open(F,">$CacheFile");
print F "#Updated $NewDate\n";
print F $Data{'Body'};
close(F);
}
}
sub GetCacheStamp {
my $File = shift;
my $CacheStamp = '';
if (-f $File) {
open(F,$File);
my $Line = <F>;
close(F);
chomp($Line);
$Line =~ /^#Updated (.*)$/;
$CacheStamp = $1;
}
return $CacheStamp;
}
sub GetDate {
my $URL = shift;
my %Fetched = &FetchURL($URL,'HEAD');
return $Fetched{'Last-Modified'};
}
sub FetchURL {
my $URL = shift;
my $Method = shift;
my %Parsed = &ParseURL($URL);
my $Sock = new IO::Socket::INET(
PeerAddr => $Parsed{'Host'},
PeerPort => $Parsed{'Port'},
Proto => 'tcp',
);
die "Could not open connection to $URL: $!\n" unless $Sock;
print $Sock "$Method ${Parsed{'Path'}} HTTP/1.0\r\n";
print $Sock "Host: ${Parsed{'Host'}}\r\n";
print $Sock "User-Agent: SinoKoreaTables/1.0\r\n";
print $Sock "Accept: text/plain\r\n\r\n";
my %Headers;
while (my $Line = <$Sock>) {
$Line =~ s/[\r\n]+//gi;
$Line =~ s/[\r\n]+//gi;
if ($Line =~ /^(.*?): (.*)$/) {
$Headers{$1} = $2;
} elsif ($Line =~ /^HTTP (\d+)/) {
$Headers{'Response'} = $1;
} elsif ($Line eq '') {
last;
}
}
while (my $Line = <$Sock>) {
chomp($Line);
$Headers{'Body'} .= "$Line\n";
}
close($Sock);
return %Headers;
}
sub ParseURL {
my $URL = shift;
$URL =~ /http:\/\/([^\/]*)(\/.*)/;
my ($Host,$Port) = split(/:/,$1);
$Port = 80 || $Port;
my $Path = $2;
return (
'Host' => $Host,
'Port' => $Port,
'Path' => $Path,
);
};