#!/usr/bin/perl # # no nonsense ident server by Tikiman # will kill processess that attract too many identd requests use IO::Socket; use IO::Select; $^O =~ /linux/i or die "Sorry, implemented for linux only"; $attempts = "5"; # number of allowed attempts per timespan $timespan = "60"; # timespan # with these settings, a process will get killed if it attracts # 5 identd requests over a 60 second period - this is most likely # to harsh, someting like 20 requests in 60 seconds will work better $timeout = 10; # number of seconds to wait before the connection # gets closed $timeout_cycle = 10; # if your identd server is pretty busy, idle sockets can be eliminated # in a timely manner. Otherwise, the server will just stay in blocking # mode and never check for idle sockets - the timeotu cycle allows the # select loop to time out after a while and sweep out idle sockets. %mappings = ( "root" => "tikiman", "tikiman" => "tikiunF0r" ); # these are username mappings - if you or find it more convenient to # irc as root, you can map root to some other username. `killall in.identd 2>/dev/null`; # kill off any old identd's forkoff(); $server = new IO::Socket::INET ( LocalPort => 113, Listen => 10, Reuse => 1 ); # open a socket $server or die "Can't create server: $@\n"; $sel = new IO::Select($server); while(1) { my $request; foreach my $client ($sel->can_read($timeout_cycle)) { if ($client == $server) { my $newclient = $server->accept; $sel->add($newclient); $timeout{$newclient} = time(); } else { my $read = sysread($client,$request,4098); unless (defined($read) and length($request)) { delete $timeout{$client}; $sel->remove($client); close($client); } $request =~ s/\015|\012|\n//g; # lose any obnoxious characters my($lport,$rport) = split(/\s*,\s*/,$request); # split the request my $locadd = $client->sockhost() . ":$lport"; my $remadd = $client->peerhost() . ":$rport"; my @tmp = split("\n",`netstat -nep 2>/dev/null`); # get netstat foreach (@tmp) { @tmp2 = split(/\s+/); if (($tmp2[3] eq $locadd) and ($tmp2[4] eq $remadd)) { ($procnum,$procname) = split(/\//,$tmp2[8]); ($procuid) = $tmp2[6]; } } my $user = getpwuid($procuid); # print "$user -- $procnum - $procname\n"; # username, process, pname unless(defined($procuid)) { # bogus requests dont even deserve a responce delete $timeout{$client}; $sel->remove($client); close($client); next; } $arrayref = $times{$procnum}; unless($arrayref) { # create array if necessary $arrayref = []; $times{$procnum} = $arrayref; } unshift(@$arrayref, time()); # stick the latest time in the array $back = $arrayref->[$attempts - 1]; # this was the old value if ($back) { pop(@$arrayref); # make sure array doesn't get out of control if ( (time() - $back) < $timespan) { # do we need to kill? kill(9,$procnum); delete $times{$procnum}; shutdown($client,2); next; } } exists $mappings{$user} and $user = $mappings{$user}; print $client "$request : USERID : UNIX : $user\n"; delete $timeout{$client}; $sel->remove($client); close($client); } sweepSocks(); } sweepSocks(); } sub sweepSocks { foreach $handle ($sel->handles) { next if $handle == $server; $tmp = time() - $timeout{$handle}; if ($tmp > $timeout) { delete $timeout{$handle}; $sel->remove($handle); close($handle); } } } sub forkoff { my $kid = fork(); if ($kid) { print "Process launched into background ($kid)\n"; exit; } }