User:Protectbot/source/block-analyzer
From Discworld MUD Wiki
#!/usr/bin/perl # This script is run without arguments. # To run it, you need to: # - Have perl of version 5.10 or later. # - Have the 'wget' tool. # - Have the 'whois' tool. # - Have the 'xmllint' tool. # - Manually fill out $password below with the actual password for the # account. use strict; use 5.010_000; use URI::Escape; use constant RESULT_FILENAME => "results.xml"; use constant COOKIE_FILENAME => "cookie.txt"; use constant API_URL => "{{SERVER}}/w/api.php"; use constant USERNAME => "Protectbot"; use constant NUM_RETURNS => 500; use constant USER_NAME => 0; use constant USER_IP => 1; use constant USER_RANGE => 2; use constant WHOIS_ARIN => 0; use constant WHOIS_RIPE => 1; use constant WHOIS_APNIC => 2; use constant WHOIS_LACNIC => 3; use constant WHOIS_AFRINIC => 4; use constant WHOIS_JPNIC => 5; my $password = <!-- Fill this out yourself -->; my %user_ips; my %net_handles; my $ip; my $whois_server; my $net; my $login_token; my $login_userid; my $login_sessionid; my $login_cookieprefix; sub http_login; sub http_logout; sub get_blocked_ips; sub parse_user; sub query_arin; sub query_ripe; sub query_apnic; sub query_lacnic; sub query_afrinic; sub query_jpnic; # Main execution &http_login($password); sleep(1); &get_blocked_ips(); sleep(1); foreach $ip (keys %user_ips) { $whois_server = &query_arin($ip); if ($whois_server == WHOIS_RIPE) { &query_ripe($ip); } elsif ($whois_server == WHOIS_APNIC) { &query_apnic($ip); } elsif ($whois_server == WHOIS_LACNIC) { &query_lacnic($ip); } elsif ($whois_server == WHOIS_AFRINIC) { &query_afrinic($ip); } elsif ($whois_server == WHOIS_JPNIC) { &query_jpnic($ip); } sleep(0.5); } &http_logout(); print "\n"; print "SUMMARY:\n"; foreach $net (sort { $net_handles{$b} <=> $net_handles{$a} } keys %net_handles) { printf("%-3d: %s\n", $net_handles{$net}, $net); } sub http_login { my ($password) = @_; my $post_data; my $command; # Build the POST data $post_data = "lgname=".USERNAME."&lgpassword=".uri_escape($password); # Execute login print "Logging in... "; $command = "wget -q --save-cookies=".COOKIE_FILENAME." --output-document=".RESULT_FILENAME." --post-data=\"".$post_data."\" \"".API_URL."?action=login&format=xml\""; `$command`; open(RESULTS, RESULT_FILENAME) or die "Could not find ".RESULT_FILENAME."\n"; $_ = <RESULTS>; close(RESULTS); # Check the login was successful if (!(/login result=\"Success\"/)) { print "FAILED\n"; print $_; die; } print "OK\n"; # Save off the tokens /lguserid=\"(?<userid>[^\"]+)\".*lgtoken=\"(?<token>[^\"]+)\" cookieprefix=\"(?<cp>[^\"]+)\" sessionid=\"(?<sessionid>[^\"]+)\"/; $login_userid = $+{userid}; $login_token = $+{token}; $login_cookieprefix = $+{cp}; $login_sessionid = $+{sessionid}; print "Userid: ".$login_userid."\n"; print "Token: ".$login_token."\n"; print "Cookie prefix: ".$login_cookieprefix."\n"; print "Session ID: ".$login_sessionid."\n"; } sub http_logout { my ($password) = @_; my $post_data; my $command; # Execute logout print "Logging out... "; $command = "wget -q --load-cookies=".COOKIE_FILENAME." --output-document=".RESULT_FILENAME." \"".API_URL."?action=logout&format=xml\""; `$command`; # There aren't any useful results to speak of, and there's little we can do # if the logout fails, so just end here. print "OK\n"; } sub get_blocked_ips { my $command; my $output; my @user_data; my $user_line; my $user; my $user_type; # Execute API query to get the following for all templates: # - title # - Current protection level $command = "wget -q --load-cookies=".COOKIE_FILENAME." --output-document=".RESULT_FILENAME." \"".API_URL."?action=query&list=blocks&bkprop=user&bklimit=".NUM_RETURNS."&format=xml\""; `$command`; open(RESULTS, RESULT_FILENAME) or die "Could not find ".RESULT_FILENAME."\n"; $output = <RESULTS>; close(RESULTS); # Parse out the individual user data @user_data = split(/</, $output); shift(@user_data); foreach $user_line (@user_data) { chomp($user_line); if (!($user_line =~ /block user=\"([^\"]*)\"/)) { next; } $user = $1; $user_type = &parse_user($user); if ($user_type == USER_IP) { print "User IP: ".$user."\n"; $user_ips{$user} = 1; } } } sub parse_user { my ($user) = @_; my $result; if ($user =~ /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\/([0-9]{1,2})/) { # Possible IP range if (($1 < 256) && ($2 < 256) && ($3 < 256) && ($4 < 256) && ($5 <= 32)) { # IP range $result = USER_RANGE; } else { # General $result = USER_NAME; } } elsif ($user =~ /([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})/) { # Possible IP if (($1 < 256) && ($2 < 256) && ($3 < 256) && ($4 < 256) && ($5 <= 32)) { # IP $result = USER_IP; } else { # General $result = USER_NAME; } } else { # General $result = USER_NAME; } return $result; } sub query_arin { my ($target) = @_; my $command; my $output; my $line; my @lines; my $org; my $handle; my $result = WHOIS_ARIN; $command = "xmllint --format http://whois.arin.net/rest/ip/".$target; $output = `$command`; @lines = split(/\n/, $output); foreach $line (@lines) { chomp $line; if ($line =~ /<orgRef name=\"([^\"]+)\" handle=\"([^\"]+)\"/) { $org = $1; $handle = $2; if ($handle eq "APNIC") { $result = WHOIS_APNIC; } elsif ($handle eq "RIPE") { $result = WHOIS_RIPE; } elsif ($handle eq "LACNIC") { $result = WHOIS_LACNIC; } elsif ($handle eq "AFRINIC") { $result = WHOIS_AFRINIC; } elsif ($handle eq "JNIC") { $result = WHOIS_JPNIC; } else { printf("%-15s: [ARIN: %s] %s\n", $target, $handle, $org); if (exists $net_handles{$handle}) { $net_handles{$handle} = $net_handles{$handle} + 1; } else { $net_handles{$handle} = 1; } } last; } } return $result; } sub query_ripe { my ($target) = @_; my $command; my $output; my $line; my @lines; my $org = ""; my $handle; $command = "whois -h whois.ripe.net -r \"".$target."\" -T inetnum"; $output = `$command`; @lines = split(/\n/, $output); foreach $line (@lines) { chomp $line; if ($line =~ /^netname:[ ]*(.*)$/) { $handle = $1; } if (($line =~ /^descr:[ ]*(.*)$/) && ($org eq "")) { $org = $1; } } printf("%-15s: [RIPE: %s] %s\n", $target, $handle, $org); if (exists $net_handles{$handle}) { $net_handles{$handle} = $net_handles{$handle} + 1; } else { $net_handles{$handle} = 1; } } sub query_apnic { my ($target) = @_; my $command; my $output; my $line; my @lines; my $org = ""; my $handle; $command = "whois -h whois.apnic.net -r \"".$target."\""; $output = `$command`; @lines = split(/\n/, $output); foreach $line (@lines) { chomp $line; if ($line =~ /^netname:[ ]*(.*)$/) { $handle = $1; } if (($line =~ /^descr:[ ]*(.*)$/) && ($org eq "")) { $org = $1; } } printf("%-15s: [APNIC: %s] %s\n", $target, $handle, $org); if (exists $net_handles{$handle}) { $net_handles{$handle} = $net_handles{$handle} + 1; } else { $net_handles{$handle} = 1; } } sub query_lacnic { my ($target) = @_; my $command; my $output; my $line; my @lines; my $org = ""; my $handle; $command = "whois -h whois.lacnic.net \"".$target."\""; $output = `$command`; @lines = split(/\n/, $output); foreach $line (@lines) { chomp $line; if ($line =~ /^ownerid:[ ]*(.*)$/) { $handle = $1; } if (($line =~ /^owner:[ ]*(.*)$/) && ($org eq "")) { $org = $1; } } printf("%-15s: [LACNIC: %s] %s\n", $target, $handle, $org); if (exists $net_handles{$handle}) { $net_handles{$handle} = $net_handles{$handle} + 1; } else { $net_handles{$handle} = 1; } } sub query_afrinic { my ($target) = @_; my $command; my $output; my $line; my @lines; my $org = ""; my $handle; $command = "whois -h whois.afrinic.net -r \"".$target."\""; $output = `$command`; @lines = split(/\n/, $output); foreach $line (@lines) { chomp $line; if ($line =~ /^netname:[ ]*(.*)$/) { $handle = $1; } if (($line =~ /^descr:[ ]*(.*)$/) && ($org eq "")) { $org = $1; } } printf("%-15s: [AFRINIC: %s] %s\n", $target, $handle, $org); if (exists $net_handles{$handle}) { $net_handles{$handle} = $net_handles{$handle} + 1; } else { $net_handles{$handle} = 1; } } sub query_jpnic { my ($target) = @_; my $command; my $output; my $line; my @lines; my $org = ""; my $handle; $command = "whois -h whois.nic.ad.jp \"NET ".$target."\""; $output = `$command`; @lines = split(/\n/, $output); foreach $line (@lines) { chomp $line; if ($line =~ /\[Network Name\][ ]*(.*)$/) { $handle = $1; } if (($line =~ /\[Organization\][ ]*(.*)$/) && ($org eq "")) { $org = $1; } } printf("%-15s: [JPNIC: %s] %s\n", $target, $handle, $org); if (exists $net_handles{$handle}) { $net_handles{$handle} = $net_handles{$handle} + 1; } else { $net_handles{$handle} = 1; } }