![]() |
|
![]() |
|
|
Thread Tools | Display Modes |
|
|
#1 |
|
Programming Guru
![]() ![]() |
IP blocker
Hey,
for the past few months, i have noticed a increase of invalid login attempts on my webserver (that has ssh running on it). Bascially these are attempts at brute forcing a username and password set....which as many of you know (or at least the ones that hang around on irc or talk to me on MSN) pisses me off. They have never gotten into ssh, but why leave that chance open? I got talking with IR (Infinite Recursion) about this problem...i soon found out that he also had a problem with these things. Then i found out that he had a script to add these ip's to his host.deny file (sorry windows users, this is a linux/unix only thing). Long story short, i decided to code my own script. Here it is: #!/usr/bin/env perl
use Net::SMTP::TLS;
use Switch;
use POSIX;
use Pg;
#use strict;
#Search Patterns:
my @patterns = ("Did not receive identification string","Invalid user","POSSIBLE BREAKIN ATTEMPT");
#db stuff:
#$con_val[0] == the database name.
#$con_val[1] == the host.
#$con_val[2] == the port.
#$con_val[3] == the username for the database.
#$con_val[4] == the password for the database.
my @conn_val = ("sentinel", "localhost", "5432", "sentinel", "fuck_china");
my $ip;
my $date;
my @months;
$months["Jan"] = 0;
$months["Feb"] = 1;
$months["Mar"] = 2;
$months["Apr"] = 3;
$months["May"] = 4;
$months["Jun"] = 5;
$months["Jul"] = 6;
$months["Aug"] = 7;
$months["Sep"] = 8;
$months["Oct"] = 9;
$months["Nov"] = 10;
$months["Dec"] = 11;
my $time = localtime time;
$time =~ m/\b[0-9][0-9][0-9][0-9]\b/;
my $year = $&;
$year -= 2000;
$year += 100;
#connect up to the db.
$conn = Pg::connectdb("host=" . $conn_val[1] . " port=" . $conn_val[2] . " dbname=" . $conn_val[0] . " user=" . $conn_val[3] . " password=" . $conn_val[4]);
#check connection.
if ($conn->status != PGRES_CONNECTION_OK)
{
die "Failed to connect: ".-$conn->errorMessage."\n";
}
open (TAIL, "tail -f auth.log 2>&1 |") or die "can't open pipe:$!";
while (<TAIL>)
{
switch ($_)
{
case m/$patterns[2]/ { next }
case m/$patterns[0]/
{
#log ip, then block and sms details to admin.
#grab ip addy
$_ =~ m/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
$ip = $&;
#grab date
$_ =~ m/\b[A-z]{3} [0-9]{2} [0-9]{1,2}:[0-9]{2}:[0-9]{2}\b/;
$date = $&;
#now, chunk date out into, $month, day, hours, minutes, seconds.
my ($month, $day, $time) = split(/ /, $date);
my ($hour, $min, $sec) = split(/:/, $time);
my $full_date = mktime($sec, $min, $hour, $day, $months[$month], $year);
my $sql = "INSERT INTO log (ip, date) VALUES ('$ip', $full_date)";
my $result = $conn->exec($sql);
open (DENY, ">>", "host.deny") or die "Can't open host.deny!";
print DENY $ip . "\n";
close DENY;
}
case m/$patterns[1]/
{
#get the fucker's ip address.
$_ =~ m/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
$ip = $&;
open (CHECK, "tail -n6 auth.log 2>&1 |") or die "can't open pipe:$!";
my $count = 0;
while (<CHECK>)
{
$_ =~ m/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
$log_ip = $&;
if ($log_ip == $ip)
{
$count += 1;
}
}
close CHECK;
if ($count >= 3)
{
#we have an attempt.
#log and ban.
$_ =~ m/\b[A-z]{3} [0-9]{2} [0-9]{1,2}:[0-9]{2}:[0-9]{2}\b/;
$date = $&;
my ($month, $day, $time) = split(/ /, $date);
my ($hour, $min, $sec) = split(/:/, $time);
my $full_date = mktime($sec, $min, $hour, $day, $months[$month], $year);
my $sql = "INSERT INTO log (ip, date) VALUES ('$ip', $full_date)";
$conn->exec($sql);
#append to host.deny
open (DENY, ">>", "host.deny") or die "Can't open host.deny!";
print DENY $ip . "\n";
close DENY;
}
}
}
} #end of while loop.The code scans your auth.log file, for attempts, adds em to hosts.deny and logs them to a db for furture use. I am now working on making a php script to output a graph based on ip and country code. I have a feeling most attempts will come from china, or atleast a ip that's spoofed to look like china. I plan on expanding this script's features in the future, so any suggestions would be great. One of the ideas for future features that IR and i were talking about is: adding the ip to a .htaccess file to block the ip from accessing web resources. More programs/log files will be supported in the future. It should be noted, you'll have to change some of the stuff in the script for it to work on your box (ie: location of auth.log and hosts.deny). Also, i designed this script so that you can (and should) start it from a script at startup.
__________________
Profanity is the one language that all programmers understand. Check out my Blog <---updated Nov 30 2007! |
|
|
|
|
|
#2 |
|
Programming Guru
![]() ![]() ![]() |
looks good man, let me know the results
__________________
http://jasonpowers.net "There are a thousand hacking at the branches of evil to one who is striking at the root." |
|
|
|
|
|
#3 |
|
Hobbyist Programmer
Join Date: Apr 2005
Posts: 218
Rep Power: 4
![]() |
Nice work Piz, I thought I was the only one with this problem. To be honest, within the first 10mins of starting SSH the log files are filled with invalid passwords too. Im no unix or perl guru so ill have a look at this later.
|
|
|
|
|
|
#4 |
|
I eat cake for breakfast.
![]() ![]() ![]() ![]() Join Date: Jul 2004
Location: In my box.
Posts: 4,434
Rep Power: 9
![]() |
Bad moderator!
* points to the Finished Projects section * :p |
|
|
|
|
|
#5 |
|
Programming Guru
![]() ![]() ![]() |
Technically, it may not be "finished" yet
![]()
__________________
http://jasonpowers.net "There are a thousand hacking at the branches of evil to one who is striking at the root." |
|
|
|
|
|
#6 |
|
Hobbyist Programmer
|
WOW, very good. port??
![]()
__________________
i dont know much about programming but i try to help |
|
|
|
|
|
#7 |
|
Programming Guru
![]() ![]() ![]() |
Port to what OS?
__________________
http://jasonpowers.net "There are a thousand hacking at the branches of evil to one who is striking at the root." |
|
|
|
|
|
#8 | |
|
Programming Guru
![]() ![]() |
Quote:
@Ooble yeah, i know i could have put it into the finished projects, but as IR said, this thing isn't quite finished yet.
__________________
Profanity is the one language that all programmers understand. Check out my Blog <---updated Nov 30 2007! |
|
|
|
|
|
|
#9 |
|
Programming Guru
![]() ![]() |
hey,
just made a rc script for gentoo to run the perl script: #!/sbin/runscript
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
depend() {
before sshd
}
start() {
start-stop-daemon --start --background --pidfile /var/run/monitor.pid --make-pidfile --exec /usr/scripts/monitor.pl
eend $?
}
stop() {
ebegin "Stopping IP Blocker"
start-stop-daemon --stop --pidfile /var/run/monitor.pid --name /usr/scripts/monitor.pl
eend $?
}It should be noted, that this rc script will probably only work on gentoo systems. i still haven't got the stop feature working corectly, but it does start the script at boot once you've added the rc script to a run level (you should add it to the default run level).
__________________
Profanity is the one language that all programmers understand. Check out my Blog <---updated Nov 30 2007! |
|
|
|
|
|
#10 |
|
Programming Guru
![]() ![]() |
Hey,
couple fixes. First off, thanks to IR, the stop fuction of the rc script now works. Here's the changes. stop() {
ebegin "Stopping IP Blocker"
kill $(cat /var/run/monitor.pid)
eend $? "Failed to stop IP Blocker"
}also, i noticed that there is a chance that the ip could be added to hosts.deny more than once. So i added a if statment to grep hosts.deny for the ip. Here's the new version of the ip blocker. #!/usr/bin/env perl
use Net::SMTP::TLS;
use Switch;
use POSIX;
use Pg;
#use strict;
#Search Patterns:
my @patterns = ("Did not receive identification string","Invalid user","POSSIBLE BREAKIN ATTEMPT");
#db stuff:
#$con_val[0] == the database name.
#$con_val[1] == the host.
#$con_val[2] == the port.
#$con_val[3] == the username for the database.
#$con_val[4] == the password for the database.
my @conn_val = ("sentinel", "localhost", "5432", "sentinel", "fuck_china*");
my $ip;
my $date;
my @months;
$months["Jan"] = 0;
$months["Feb"] = 1;
$months["Mar"] = 2;
$months["Apr"] = 3;
$months["May"] = 4;
$months["Jun"] = 5;
$months["Jul"] = 6;
$months["Aug"] = 7;
$months["Sep"] = 8;
$months["Oct"] = 9;
$months["Nov"] = 10;
$months["Dec"] = 11;
my $time = localtime time;
$time =~ m/\b[0-9][0-9][0-9][0-9]\b/;
my $year = $&;
$year -= 2000;
$year += 100;
#connect up to the db.
$conn = Pg::connectdb("host=" . $conn_val[1] . " port=" . $conn_val[2] . " dbname=" . $conn_val[0] . " user=" . $conn_val[3] . " password=" . $conn_val[4]);
#check connection.
if ($conn->status != PGRES_CONNECTION_OK)
{
die "Failed to connect: ".-$conn->errorMessage."\n";
}
open (TAIL, "tail -f /var/log/auth.log 2>&1 |") or die "can't open pipe:$!";
while (<TAIL>)
{
switch ($_)
{
case m/$patterns[2]/ { next }
case m/$patterns[0]/
{
#log ip, then block and sms details to admin.
#grab ip addy
$_ =~ m/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
$ip = $&;
#grab date
$_ =~ m/\b[A-z]{3} [0-9]{2} [0-9]{1,2}:[0-9]{2}:[0-9]{2}\b/;
$date = $&;
#now, chunk date out into, $month, day, hours, minutes, seconds.
my ($month, $day, $time) = split(/ /, $date);
my ($hour, $min, $sec) = split(/:/, $time);
my $full_date = mktime($sec, $min, $hour, $day, $months[$month], $year);
my $sql = "INSERT INTO log (ip, date) VALUES ('$ip', $full_date)";
my $result = $conn->exec($sql);
if (system("grep $ip /etc/hosts.deny") != 0)
{
open (DENY, ">>", "/etc/hosts.deny") or die "Can't open host.deny!";
print DENY "ALL: " . $ip . "\n";
close DENY;
}
}
case m/$patterns[1]/
{
#get the fucker's ip address.
$_ =~ m/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
$ip = $&;
open (CHECK, "tail -n6 /var/log/auth.log 2>&1 |") or die "can't open pipe:$!";
my $count = 0;
while (<CHECK>)
{
$_ =~ m/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
$log_ip = $&;
if ($log_ip == $ip)
{
$count += 1;
}
}
close CHECK;
if ($count >= 3)
{
#we have an attempt.
#log and ban.
$_ =~ m/\b[A-z]{3} [0-9]{2} [0-9]{1,2}:[0-9]{2}:[0-9]{2}\b/;
$date = $&;
my ($month, $day, $time) = split(/ /, $date);
my ($hour, $min, $sec) = split(/:/, $time);
my $full_date = mktime($sec, $min, $hour, $day, $months[$month], $year);
my $sql = "INSERT INTO log (ip, date) VALUES ('$ip', $full_date)";
$conn->exec($sql);
#append to host.deny
if (system("grep $ip /etc/hosts.deny") != 0)
{
open (DENY, ">>", "/etc/hosts.deny") or die "Can't open host.deny!";
print DENY "ALL: " . $ip . "\n";
close DENY;
}
}
}
}
} #end of while loop.
__________________
Profanity is the one language that all programmers understand. Check out my Blog <---updated Nov 30 2007! Last edited by Pizentios; May 24th, 2006 at 2:57 PM. |
|
|
|
![]() |
| Bookmarks |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | |
|
|