Skip to content

Commit a61f498

Browse files
committed
usage: tcp-proxy2.pl <local port> <host:port>
0 parents  commit a61f498

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

tcp-proxy2.pl

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/perl
2+
#
3+
# Peteris Krumins ([email protected])
4+
# http://www.catonmat.net -- good coders code, great reuse
5+
#
6+
#
7+
# Written for the article "A TCP Proxy in Perl":
8+
#
9+
# http://catonmat.net/blog/perl-tcp-proxy
10+
#
11+
12+
use warnings;
13+
use strict;
14+
15+
use IO::Socket::INET;
16+
use IO::Select;
17+
18+
my @allowed_ips = ('all', '10.10.10.5');
19+
my $ioset = IO::Select->new;
20+
my %socket_map;
21+
22+
my $debug = 1;
23+
24+
sub new_conn {
25+
my ($host, $port) = @_;
26+
return IO::Socket::INET->new(
27+
PeerAddr => $host,
28+
PeerPort => $port
29+
) || die "Unable to connect to $host:$port: $!";
30+
}
31+
32+
sub new_server {
33+
my ($host, $port) = @_;
34+
my $server = IO::Socket::INET->new(
35+
LocalAddr => $host,
36+
LocalPort => $port,
37+
ReuseAddr => 1,
38+
Listen => 100
39+
) || die "Unable to listen on $host:$port: $!";
40+
}
41+
42+
sub new_connection {
43+
my $server = shift;
44+
my $remote_host = shift;
45+
my $remote_port = shift;
46+
47+
my $client = $server->accept;
48+
my $client_ip = client_ip($client);
49+
50+
unless (client_allowed($client)) {
51+
print "Connection from $client_ip denied.\n" if $debug;
52+
$client->close;
53+
return;
54+
}
55+
print "Connection from $client_ip accepted.\n" if $debug;
56+
57+
my $remote = new_conn($remote_host, $remote_port);
58+
$ioset->add($client);
59+
$ioset->add($remote);
60+
61+
$socket_map{$client} = $remote;
62+
$socket_map{$remote} = $client;
63+
}
64+
65+
sub close_connection {
66+
my $client = shift;
67+
my $client_ip = client_ip($client);
68+
my $remote = $socket_map{$client};
69+
70+
$ioset->remove($client);
71+
$ioset->remove($remote);
72+
73+
delete $socket_map{$client};
74+
delete $socket_map{$remote};
75+
76+
$client->close;
77+
$remote->close;
78+
79+
print "Connection from $client_ip closed.\n" if $debug;
80+
}
81+
82+
sub client_ip {
83+
my $client = shift;
84+
return inet_ntoa($client->sockaddr);
85+
}
86+
87+
sub client_allowed {
88+
my $client = shift;
89+
my $client_ip = client_ip($client);
90+
return grep { $_ eq $client_ip || $_ eq 'all' } @allowed_ips;
91+
}
92+
93+
die "Usage: $0 <local port> <remote_host:remote_port>" unless @ARGV == 2;
94+
95+
my $local_port = shift;
96+
my ($remote_host, $remote_port) = split ':', shift();
97+
98+
99+
print "Starting a server on 0.0.0.0:$local_port\n";
100+
my $server = new_server('0.0.0.0', $local_port);
101+
$ioset->add($server);
102+
103+
while (1) {
104+
for my $socket ($ioset->can_read) {
105+
if ($socket == $server) {
106+
new_connection($server, $remote_host, $remote_port);
107+
}
108+
else {
109+
next unless exists $socket_map{$socket};
110+
my $remote = $socket_map{$socket};
111+
my $buffer;
112+
my $read = $socket->sysread($buffer, 4096);
113+
if ($read) {
114+
$remote->syswrite($buffer);
115+
}
116+
else {
117+
close_connection($socket);
118+
}
119+
}
120+
}
121+
}
122+

0 commit comments

Comments
 (0)