World Hopper is a simple yet powerful tool used to connect to remote services through a chain of HTTP (CONNECT) proxy servers for the sole purpose of gaining a higher level of anonymity. It opens a listening socket at port 1337 (default) and then waits for a client to connect. When a client connects, World Hopper builds a chain of proxy servers. Tested with: telnet, pop3 and irc.
57fa74cbd3f55dc2080e93bbb0647c1d1fbca7cff5cc911dfce23bc14a9be586
#!/usr/bin/perl
# Vincent 'rastakid' van Scherpenseel (rastakid [at] syn-ack [dot] org) - 17 May 2005
#
# World Hopper 0.3 (whopper.pl)
# Simple but powerfull tool to connect to remote services through a chain of HTTP (CONNECT) proxy
# servers, to gain high anonymity. Opens a listening socket at port 1337 (default) and then waits
# for a client to connect. When a client connects World Hopper builds a chain of proxy servers.
# Tested OK with: telnet, pop3 and irc.
#
# Usage: whopper.pl <proxyfile> [options] [dest_host:dest_port]
# Proxyfile should contain HTTP CONNECT proxies, each on a new line (host:port).
# If you omit the destination, your connecting client needs to send the CONNECT method request.
#
# Whopper lives at: https://proximus.syn-ack.org/whopper/
# See https://proximus.syn-ack.org/whopper/changelog.txt for changes.
# Load modules
use strict;
use IO::Socket;
use Net::hostent;
use Fcntl qw(:flock :seek);
use POSIX qw(strftime);
my (@proxies, $proxy_host, $proxy_port, $server, $client, $hostinfo, $server_port, $childpid, $proxy_connection, $line, $iterate, $last_proxy, $non_http_output, $logtraffic, $traffic_log, $clienthost, $destination);
$SIG{CHLD} = 'IGNORE'; # Prevent childs from becoming zombies.
# GLOBAL VARIABLES
$server_port = 1337; # set server listening port globally (default is: 1337).
$logtraffic = 0; # enable/disable logtraffic globally (disabled by default).
$traffic_log = "traffic.log"; # set traffic logfile globally (default is: traffic.log).
# Command line reading
if (@ARGV[0] eq "" or @ARGV[0] eq "-H" or @ARGV[0] eq "-h" or @ARGV[0] eq "--help") {
die "Usage: whopper.pl <proxyfile> [options] [dest_host:dest_port]
Options:
-H, -h, --help\t\t\t\tThis help menu
-P (--port) <server port>\t\t\tPort to listen for incoming connections
-L (--logtraffic) <traffic logfile>\t\tLog traffic to <traffic logfile>\n";
}
for ($iterate=1;$iterate<scalar(@ARGV);$iterate++) {
chomp(@ARGV[$iterate]);
# server listening port
if(@ARGV[$iterate] eq "-P" or @ARGV[$iterate] eq "--port") {
chomp(@ARGV[($iterate+1)]);
$server_port = @ARGV[($iterate+1)];
$iterate++; # extra plus 1, argument for -P
}
# traffic logging
elsif(@ARGV[$iterate] eq "-L" or @ARGV[$iterate] eq "--logtraffic") {
$logtraffic = 1;
chomp(@ARGV[($iterate+1)]);
$traffic_log = @ARGV[($iterate+1)];
$iterate++; # extra plus 1, argument for -L
}
# user supplied a destination
else {
$destination = @ARGV[$iterate];
}
}
print "\nWorld Hopper 0.3 - Vincent 'rastakid' van Scherpenseel\n";
print "=" x 54 . "\n\n";
# Read proxy servers from file
open(INF,"$ARGV[0]") or die "Fatal: opening proxyfile (@ARGV[0]) failed with error: $!\n";;
@proxies = <INF>;
close(INF);
@proxies = grep(!/^#/, @proxies); # filter out comments
@proxies = grep(!/^$/, @proxies); # filter out empty lines
print "[ " . (strftime "%c", localtime) . "\tPID: $$ ] Found " . scalar(@proxies) . " proxy servers in @ARGV[0].\n";
if ($logtraffic) {
# Open traffic log for appending
open(TRAFFIC_LOG,">>$traffic_log");
}
# Open listening sockets for clients
$server = IO::Socket::INET->new(LocalPort => $server_port,
Type => SOCK_STREAM,
Reuse => 1,
Listen => SOMAXCONN )
or die "Fatal: listening on port $server_port failed with error: $@\n";
print "[ " . (strftime "%c", localtime) . "\tPID: $$ ] Listening for client connections on port $server_port.\n";
while ($client = $server->accept()) { # Incoming client connection
$non_http_output = 0; # Set to default (no non-HTTP output yet)
$client->autoflush(1);
$hostinfo = gethostbyaddr($client->peeraddr);
$clienthost = $hostinfo ? $hostinfo->name : $client->peerhost;
printf "\n[ " . (strftime "%c", localtime) . "\tPID: $$ ] Client connection from $clienthost.\n";
# Connect to first proxy server
chomp($proxies[0]);
$last_proxy = $proxies[0];
($proxy_host,$proxy_port) = split(/:/,$proxies[0]);
$proxy_connection = IO::Socket::INET->new(Proto => "tcp",
PeerAddr => $proxy_host,
PeerPort => $proxy_port)
or die "Fatal: connecting to proxy server $proxy_host:$proxy_port failed with error: $!";
$proxy_connection->autoflush(1);
print "[ " . (strftime "%c", localtime) . "\tPID: $$ ] Connected to $proxy_host:$proxy_port.\n";
if ($logtraffic) {
# Write line to traffic log
flock(TRAFFIC_LOG, LOCK_EX);
seek(TRAFFIC_LOG,0,2);
print TRAFFIC_LOG "\n\n[ Connection to: $proxy_host:$proxy_port ]\n";
flock(TRAFFIC_LOG, LOCK_UN);
}
# Chain proxy servers
for ($iterate=1;$iterate<scalar(@proxies);$iterate++) {
chomp($proxies[$iterate]);
print $proxy_connection "CONNECT $proxies[$iterate] HTTP/1.0\r\n\r\n";
$last_proxy = $proxies[$iterate];
if ($logtraffic) {
# Write line to traffic log
flock(TRAFFIC_LOG, LOCK_EX);
seek(TRAFFIC_LOG,0,2);
print TRAFFIC_LOG ">CONNECT $proxies[$iterate] HTTP/1.0\r\n\r\n";
flock(TRAFFIC_LOG, LOCK_UN);
}
}
# Check if we only need to proxy or if we have a destination too
if ($destination ne "") {
print $proxy_connection "CONNECT $destination HTTP/1.0\r\n\r\n";
if ($logtraffic) {
# Write line to traffic log
flock(TRAFFIC_LOG, LOCK_EX);
seek(TRAFFIC_LOG,0,2);
print TRAFFIC_LOG ">CONNECT $destination HTTP/1.0\r\n\r\n";
flock(TRAFFIC_LOG, LOCK_UN);
}
}
die "Fatal: forking failed with error: $!" unless defined($childpid = fork());
# Data Input/Output
if ($childpid) {
$iterate = 1;
while (defined ($line = <$proxy_connection>)) {
if ($logtraffic) {
# Write line to traffic log
flock(TRAFFIC_LOG, LOCK_EX);
seek(TRAFFIC_LOG,0,2);
print TRAFFIC_LOG "<$line";
flock(TRAFFIC_LOG, LOCK_UN);
}
# Filter out HTTP code 200s and empty lines on CONNECT (for POP3 and such compatibility)
if (($line =~ /200 Connection established/ or $line =~ /Proxy-agent:/ or $line =~ /Proxy-Agent:/ or $line eq "\r" or $line eq "\n" or $line eq "\r\n") and $non_http_output == 0) {
if ($line =~ /200 Connection established/) {
if ($iterate == scalar(@proxies)) {
print "[ " . (strftime "%c", localtime) . "\tPID: $childpid ] Connected to destination.\n";
} else {
print "[ " . (strftime "%c", localtime) . "\tPID: $childpid ] Connected to $proxies[$iterate].\n";
$iterate++;
}
}
$line = "";
} else {
$non_http_output = 1;
}
print $client $line;
}
kill("TERM", $childpid);
print "[ " . (strftime "%c", localtime) . "\tPID: $childpid ] Disconnect from client: $clienthost.\n";
} else {
while (defined ($line = <$client>)) {
print $proxy_connection $line;
if ($logtraffic) {
# Write line to traffic log
flock(TRAFFIC_LOG, LOCK_EX);
seek(TRAFFIC_LOG,0,2);
print TRAFFIC_LOG ">$line";
flock(TRAFFIC_LOG, LOCK_UN);
}
}
}
}