1: #!/usr/bin/perl 2: #This program has been tested on Debian 2.2 and Win2k, and works fine on both 3: #All comments encouraged, the nice ones will be appreciated 4: #GPL by Jepri 5: 6: 7: #Things that could be added to make this extremely neat: 8: #Assign unique numbers to the open connections so that we can see 9: #how long they've been open for 10: 11: #Add a little bit of AI to detect evil banner server sites 12: 13: #Find a way to swat the connections that we don't like 14: 15: #Copy selected IP addresses to the clipboard so the user can paste them into 16: #junkbuster. 17: 18: #Or just insert them ourselves... 19: 20: #OS cheat. Unix and BSD always have /etc/passwd 21: -e '/etc/passwd' or my $windows=1; 22: if ($windows) { 23: print "Updating windows installation...\n\n\n"; 24: require PPM; 25: #Returns a list of all the installed packages. Why can't CPAN do the same? 26: my %temp=PPM::InstalledPackageProperties(); 27: PPM::InstallPackage("package" => "Tk") unless $temp{Tk}; 28: PPM::InstallPackage("package" => "Net::DNS") unless $temp{qw(Net-DNS)}; 29: } 30: else { 31: #Painfull way of finding if modules are installed. Should be eval('require module'); 32: my %mods=( Tk=>0, 'Net/DNS'=>0 ); 33: print "Updating *nix installation\n"; 34: print @INC; 35: foreach $dir (@INC) { 36: foreach $file (keys %mods) { 37: $mods{$file}=1 if (`ls -lR $dir | grep $file`); 38: } 39: } 40: my $needtoload=0; 41: foreach $file (keys %mods) {$needtoload=1 unless $mods{$file};} 42: if ($needtoload) { 43: require CPAN; 44: for $mod (qw(Tk Net::DNS)){ 45: my $obj = CPAN::Shell->expand('Module',$mod); 46: $obj->install; 47: } 48: } 49: } 50: 51: require Tk; 52: require Tk::After; 53: require Tk::Listbox; 54: 55: require Net::DNS::Resolver; 56: require Net::DNS::Packet; 57: require Net::DNS::RR; 58: 59: use Socket; 60: use strict; 61: use diagnostics; 62: 63: my %ripname; #Cache of DNS lookups by addr 64: my $nextconnum=1; #Increment each time you use it to assign a unique number to a connection 65: my $res = new Net::DNS::Resolver; 66: my $packet=new Net::DNS::Packet; 67: #Replace these IP numbers with your own DNS servers. Only do this if perl fails 68: #to detect your nameserver automatically 69: #$res->nameservers("10.0.0.1 10.0.0.2); #Space separated list of nameservers to query 70: $res->tcp_timeout(30); #If we don't get a result in 30 secs we never will 71: $res->retry(1); #Screw retrying too 72: my @connlist; #Should have the following keys: id (unique), proto, lip, lp, rip, rp, state 73: my $numofconnections=0; #number of currently open connections 74: my %pending; #List of IPs being looked up 75: my %socket; #sockets corresponding to IP lookups 76: my %broken; #IP numbers which can't be looked up 77: my %activetime; #Total time links to site have been open (by ip) 78: my $timerperiod=1000; #what it says, make it larger if your 79: #system starts to grind 80: my @visited; 81: 82: 83: 84: #Might as well do the states while I'm here. I can never pass up the chance to be 85: #a smartarse <- Note spelling, this is the right way. 86: my %portstate=(ESTABLISHED=>"In progress", SYN_WAIT=>"Dolphin!", TIME_WAIT=>"Closing", CLOSE_WAIT=>"Closing", FIN_WAIT=>"Dolphin!!"); 87: #If you see too many dolphins in your connection list then something fishy 88: #is going on :) 89: 90: my $main = MainWindow->new; 91: $main->title("Status"); 92: my $top1 = $main->Toplevel; 93: $top1->title("All visited sites"); 94: my $currconn; 95: 96: $top1->Label(-text => 'All the computers you have connected to')->pack(); 97: #my $allcons=$top1->Listbox(-height=>0,-width=>0)->pack; 98: my $allcons = $top1->Scrolled('Listbox',-relief => "sunken", 99: -background => "gray60", 100: -width => 90, 101: -height => 30,)->pack(-expand => 1, -fill => 'both' ); 102: 103: 104: my $Timer = Tk::After->new($main,$timerperiod,'repeat',\&update); 105: my %listbox; 106: 107: sub make_win { 108: $currconn = $main ->Toplevel; 109: $currconn->title("Current connections"); 110: $currconn->Label(-text => 'Computers you are connecting to')->pack; 111: $listbox{proto}= $currconn->Listbox(-height=>0,-width=>0);#->pack(-side=>"left"); 112: $listbox{lip}= $currconn->Listbox(-height=>0,-width=>0);#->pack(-side=>"left"); 113: #$listbox{lp}= $currconn->Listbox(-height=>0,-width=>0)->pack(-side=>"left"); 114: $listbox{rip}= $currconn->Listbox(-height=>0,-width=>0)->pack(-side=>"left"); 115: $listbox{rp}= $currconn->Listbox(-height=>0,-width=>0)->pack(-side=>"left"); 116: $listbox{state}= $currconn->Listbox(-height=>0,-width=>0)->pack(-side=>"left"); 117: } 118: 119: sub dest_win { 120: $currconn->destroy; 121: } 122: 123: 124: make_win(); 125: 126: my $DNScalls = $main -> Label(-text => 'DNS calls active: 0')->pack(-side=>'top'); 127: my $DNSbroken = $main -> Label(-text => 'DNS calls failed: 0')->pack(-side=>'top'); 128: my $totalips = $main -> Label(-text => 'Total hosts visited: 0')->pack(-side=>'top'); 129: my $dispcurrconns = $main -> Label(-text => 'Total connections active: 0')->pack(-side=>'top'); 130: 131: 132: 133: 134: #This hands control to the Tk module, everything we do happens on a callback 135: Tk::MainLoop(); 136: 137: 138: 139: sub update { 140: do_DNS(); 141: my @connections = get_connlist(); 142: unless ($numofconnections == @connections) { 143: if ($numofconnections<@connections) { 144: dest_win(); 145: make_win(); 146: $numofconnections=@connections; 147: } 148: } 149: @connlist=(); 150: if ($#connections) { 151: foreach (@connections) { 152: my $regexp; 153: if ($windows) {$regexp='\s+(\S+)\s+(\S+):(\d+)\s+(\S+):(\d+)\s+(\S+)'} 154: else {$regexp='(\S+)\s+\S+\s+\S+\s+(\S+):(\d+)\s+(\S+):(\d+)\s+(\S+)'} 155: reset; 156: if (/$regexp/){ 157: push @connlist, { id=>$nextconnum++, proto=>$1, lip=>$2, lp=>$3, rip=>$4, rp=>$5, state=>$6}; 158: $activetime{$4}+=$timerperiod; 159: } 160: } 161: } 162: 163: 164: foreach my $key (keys %listbox) {$listbox{$key}->delete(0,'end');} 165: 166: #This updates the list of all connected machines unless the user is currently inspecting it. 167: unless ( $allcons->focusCurrent == $top1) { 168: $allcons->delete(0,'end'); 169: foreach my $key (keys %ripname) {$allcons->insert(0,$ripname{$key});} 170: } 171: #Populate connection list in window 172: foreach my $i (0..$#connlist) { 173: $ripname{$connlist[$i]{rip}}=$connlist[$i]{rip} unless ($ripname{$connlist[$i]{rip}}); 174: $listbox{proto}->insert(0,$connlist[$i]{proto}); 175: $listbox{lip}->insert(0, $connlist[$i]{lip}); 176: #$listbox{lp}->insert(0, protobyport($connlist[$i]{lp})); 177: $listbox{rip}->insert(0, $ripname{$connlist[$i]{rip}}); 178: my $x; 179: if (protobyport($connlist[$i]{rp}) eq "Unknown") {$x=protobyport($connlist[$i]{lp});} else {$x=protobyport($connlist[$i]{rp})} 180: $listbox{rp}->insert(0, $x); 181: $listbox{state}->insert(0,$portstate{$connlist[$i]{state}}); 182: } 183: $listbox{proto}-> insert(0,"What's happening?"); 184: $listbox{rip}->insert(0,"Other machine"); 185: $listbox{rp}->insert(0,"Link type"); 186: #$listbox{lp}->insert(0,"Link type"); 187: $listbox{state}->insert(0,"Status"); 188: 189: $DNScalls->configure(-text=> "DNS calls in progress: ".scalar(keys(%socket))); 190: $DNSbroken->configure(-text=> "DNS calls failed: ".scalar(keys(%broken))); 191: $totalips->configure(-text=> "Total hosts visited: ".scalar(keys(%ripname))); 192: $dispcurrconns ->configure(-text => "Total connections active: ".scalar(@connections)); 193: 194: 195: } 196: 197: 198: sub do_DNS { 199: foreach my $ips (keys %ripname) { 200: #If $ips hasn't been resolved to a hostname 201: if ($ips eq $ripname{$ips}){ 202: #And it's not in the process of being resolved, or otherwise dead 203: unless ($broken{$ips} or $pending{$ips}) { 204: #Put it on the pending list 205: $pending{$ips} = 1; 206: #Start an IP->Hostname lookup on it 207: $socket{$ips} = $res->bgsend($ips); 208: } 209: } 210: } 211: #Now go through the pending list and see if any have been successfully 212: #looked up since the last time we checked 213: foreach my $ips (keys %pending) { 214: #If we have a result... 215: if ($socket{$ips} && $res->bgisready($socket{$ips})) { 216: #Read our result 217: $packet = $res->bgread($socket{$ips}); 218: #Clean up 219: delete $socket{$ips}; 220: delete $pending{$ips}; 221: my @answer=$packet->answer if $packet; 222: #If no RRs then IP does not have an official hostname, put it 223: #on the broken list 224: if (@answer == 0) {$broken{$ips}=1;} 225: else { 226: foreach my $rr (@answer) { 227: #Calling this on a bad RR has the convenient effect 228: #of ending this Tk::Timer callback 229: #IIRC only PTRs may be used in reverse zones 230: if ($rr->type eq "PTR") { 231: $ripname{$ips}=$rr->ptrdname; 232: } else { 233: $broken{$ips}=1; 234: } 235: last; 236: } 237: } 238: } 239: else { 240: #print "It's not ready yet :(\n"; 241: } 242: } 243: } 244: 245: sub protobyport { 246: my $portnum=shift; 247: #For some reason I can't get the portnames working under windows so I get to do port naming 248: #for myself. Oh well, it's a bit of fun for me 249: my %protobyport=( 250: 80=>"World Wide Wait", 251: 110=>"Receiving Mail", 252: 143=>"Receiving Mail", 253: 23=>"Telnet", 254: 21 =>"FTP", 255: 25=>"Sending Mail", 256: 1234=>"Back Orifice. You have been hacked. Hahahahah"); 257: 258: if ($protobyport{$portnum}) { 259: return $protobyport{$portnum}; 260: } 261: else { 262: #Insert the proper linux getprotobynum or whatever it's called... 263: #return $portnum; 264: return "Unknown"; 265: } 266: } 267: 268: sub get_connlist { 269: #I could do this so much better with the marvellous Net::Pcap module 270: #but then I couldn't have used it on windows, which is an operating system 271: #that needs this kind of utility more than Linux does. 272: if ($windows) { 273: my $connections = `netstat -n`; 274: $connections =~ s/(.*)State..//s; 275: return split(/\n/, $connections); 276: } 277: else{ 278: my $connections = `netstat -n -Ainet`; 279: $connections =~ s/(?:..*)State..//s; 280: return split(/\n/, $connections); 281: } 282: } 283:
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Tk app to show the computers you are connecting to
by TheoPetersen (Priest) on Feb 13, 2001 at 23:58 UTC | |
by jepri (Parson) on Feb 14, 2001 at 16:37 UTC | |
Re: Tk app to show the computers you are connecting to
by Fingo (Monk) on Mar 04, 2001 at 02:57 UTC | |
Re: Tk app to show the computers you are connecting to
by SilverB1rd (Scribe) on Feb 16, 2001 at 01:39 UTC |
Back to
Craft