HTTP-ProxyTest

 view release on metacpan or  search on metacpan

ProxyTest.pm  view on Meta::CPAN

				croak "Argument -$_: The user this script runs as ",
				  "does not have write access to '$file'";
			}
			require File::Basename;
			my $dir = ( File::Basename::fileparse($file) )[1];
			if ( -d $dir ) {
				last PATHCHECKS if -r $dir and -w _ and -x _;
				croak "Argument -$_: The user this script runs as ",
				  "does not have write access to '$dir'";
			}
			croak "Argument -$_: Can't find any directory '$dir'";
		}
	}

	for ('primary', 'secondary') {
		if ( exists $args{$_} ) {
			ref($args{$_}) eq 'ARRAY' or croak "Argument -$_ shall be an arrayref";
			my $err = grep /\D/ || $_ < 0 || $_ > 65535, @{ $args{$_} };
			$err == 0 or croak "Argument -$_: $err elements are not valid port numbers";
		} else {
			$args{$_} = $defaults{$_};
		}
	}
	$args{primary}->[0] or $args{secondary}->[0] or
	  croak 'There should be at least one port to test';
	unless ( $args{nmap} or $args{primary}->[0] ) {
		croak 'Argument -primary may not refer to an empty list when no Nmap scanning is done';
	}

	for ('timeout', 'log_maxbytes') {
		if ( $args{$_} ) {
			$args{$_} =~ /^\d+$/ or croak "Argument -$_ shall be a positive integer";
		} else {
			$args{$_} = $defaults{$_};
		}
	}

	for ('test_url', 'content_substr') {
		$args{$_} ||= $defaults{$_};
	}
	$useragent = LWP::UserAgent->new(
		timeout => $args{timeout},
		agent => "HTTP::ProxyTest/$VERSION",
		requests_redirectable => [],
	);
	my $res = $useragent->get( $args{test_url} );
	unless ( $res->is_success ) {
		# no fatal error, since a temporary glitch
		# might be the cause of the failure
		carp 'Argument -test_url: Response status ', $res->status_line;
		return undef;
	}
	unless ( index( $res->content, $args{content_substr} ) >= 0 ) {
		croak 'Argument -content_substr: The string ',
		  "'$args{content_substr}' not found in the source of $args{test_url}";
	}

	\%args
}

sub update_whitelist {
	my $whitelist = shift;
	return {} unless $whitelist;

	tie my %white, 'SDBM_File', $whitelist, O_CREAT|O_RDWR, 0666 or die $!;
	my @oldies = grep $white{$_} < $time - 604800, keys %white;
	delete @white{ @oldies };
	\%white
}

sub portselect {
	my ($ip, $args) = @_;
	return $args->{primary} unless $args->{nmap};

	my (%count, @open, @filtered);
	my $ports = join ',', map { $count{$_}++ ? () : $_ }
	  @{ $args->{primary} }, @{ $args->{secondary} };
	my $nmap_result = qx( $args->{nmap} -PN -p $ports $ip );
	croak 'Nmap scan failed' if !$nmap_result or $?;
	while ( $nmap_result =~ m,^(\d+)/tcp\s+(open|filtered)\b,gm ) {
		my ($port, $state) = ($1, $2);
		if ( $state eq 'open' ) {
			push @open, $port;
		} elsif ( grep $_ eq $port, @{ $args->{primary} } ) {
			push @filtered, $port;
		}
	}
	[ @open, @filtered ]
}

sub caught {
	my ($ip, $port, $args) = @_;
	my $host = gethostbyaddr( pack('C4', split /\./, $ip), 2 ) || "IP $ip";
	print "Status: 403 Forbidden\n",
	      "Content-type: text/html; charset=UTF-8\n\n";
	print "<html><head><title>403 Forbidden</title></head><body>\n",
	      "<h1>403 Forbidden</h1>\n<p>The host you are using (<tt>$host</tt>) ",
	      "appears to carry an open proxy on port $port.</p>\n",
	      "</body></html>\n";
	return unless $args->{log};

	open my $log, '+>>', $args->{log} or die $!;
	flock $log, LOCK_EX;
	print $log "Date:      ", scalar localtime $time, "\n",
	           "URL:       ", ( lc substr($ENV{REQUEST_URI}, 0, 4) eq 'http' ?
	             '' : "http://$ENV{HTTP_HOST}" ), "$ENV{REQUEST_URI}\n",
	           "IP:        $ip\n";
	print $log "Host name: $host\n" unless substr($host, 3) eq $ip;
	print $log "Port:      $port\n\n";

	my $oldfh = select $log; $|++; select $oldfh;
	return unless -s $log > $args->{log_maxbytes};

	seek $log, $args->{log_maxbytes} / 2, 0;
	my $latest = do { local $/; <$log> };
	$latest =~ s/.+?\n\n//s;
	seek $log, 0, 0;
	truncate $log, 0;
	print $log $latest;
}



( run in 0.817 second using v1.01-cache-2.11-cpan-e1769b4cff6 )