3 # Peteris Krumins (peter@catonmat.net)
4 # http://www.catonmat.net -- good coders code, great reuse
6 # A simple TCP proxy that implements IP-based access control
7 # Currently the ports are hard-coded, and it proxies
8 # 0.0.0.0:1080 to localhost:55555.
10 # Written for the article "Turn any Linux computer into SOCKS5
11 # proxy in one command," which can be read here:
13 # http://www.catonmat.net/blog/linux-socks5-proxy
22 my @allowed_ips = ('1.2.3.4', '5.6.7.8', '127.0.0.1', '192.168.1.2');
23 my $ioset = IO::Select->new;
29 my ($host, $port) = @_;
30 return IO::Socket::INET->new(
33 ) || die "Unable to connect to $host:$port: $!";
37 my ($host, $port) = @_;
38 my $server = IO::Socket::INET->new(
43 ) || die "Unable to listen on $host:$port: $!";
48 my $client = $server->accept;
49 my $client_ip = client_ip($client);
51 unless (client_allowed($client)) {
52 print "Connection from $client_ip denied.\n" if $debug;
56 print "Connection from $client_ip accepted.\n" if $debug;
58 my $remote = new_conn('localhost', 55555);
62 $socket_map{$client} = $remote;
63 $socket_map{$remote} = $client;
66 sub close_connection {
68 my $client_ip = client_ip($client);
69 my $remote = $socket_map{$client};
71 $ioset->remove($client);
72 $ioset->remove($remote);
74 delete $socket_map{$client};
75 delete $socket_map{$remote};
80 print "Connection from $client_ip closed.\n" if $debug;
85 return inet_ntoa($client->sockaddr);
90 my $client_ip = client_ip($client);
91 return grep { $_ eq $client_ip } @allowed_ips;
94 print "Starting a server on 0.0.0.0:1080\n";
95 my $server = new_server('0.0.0.0', 1080);
99 for my $socket ($ioset->can_read) {
100 if ($socket == $server) {
101 new_connection($server);
104 next unless exists $socket_map{$socket};
105 my $remote = $socket_map{$socket};
107 my $read = $socket->sysread($buffer, 4096);
109 $remote->syswrite($buffer);
112 close_connection($socket);