#!/usr/bin/perl -w use strict; use Getopt::Std; use IO::Socket; use IO::Select; sub usage { <<"EndUsage"; $0 lets you snoop on the conversation between a client and server. $0 -i clientport -o serverhost:port [-1] [-v] -i incoming port to listen to -o outgoing port to make connection to -1 only process one client request, then exit -v verbose caveats: o Does not handle multiple simultaneous connections. o Reads are asynchronous, writes are synchronous. o Messages larger than 64K will be segmented. EndUsage } use vars qw($opt_i $opt_o $opt_1 $opt_v); getopts('i:o:1:v') and $opt_o or die usage; my $proxy_port = $opt_i or die usage; my ($server_host, $server_port) = $opt_o =~ /^(.+):(\d+)$/ or die usage; my $verbose = 1 if $opt_v; my $only_one = 1 if $opt_1; $SIG{TERM} = $SIG{INT} = $SIG{HUP} = \&shutdown; my $proxy = IO::Socket::INET->new(LocalPort => $proxy_port, Type => SOCK_STREAM, Proto => 'tcp', Reuse => 1, Listen => 1) or die "Can't listen on port $proxy_port: $!\n"; print "[listening on port $proxy_port]\n" if $verbose; my ($client, $server); OUTER: while ($client = $proxy->accept) { my ($client_host, $client_port) = (gethostbyaddr($client->peeraddr, AF_INET) || $client->peerhost, $client->peerport); print "[connection from $client_host on $client_port]\n" if $verbose; $server = IO::Socket::INET->new(PeerAddr => $server_host, PeerPort => $server_port, Proto => 'tcp', Type => SOCK_STREAM) or die "Can't connect to $server_host:$server_port\n"; print "[connected to server $server_host:$server_port]\n" if $verbose; my $selector = IO::Select->new($client, $server); CONNECTION: while (my @ready = $selector->can_read) { for my $sock (@ready) { my ($who, $target) = ($sock == $client ? ('client', $server) : ('server', $client)); my $msgbuf; unless ($sock->sysread($msgbuf, 64 * 1024)) { print "[$who closed connection]\n" if $verbose; last CONNECTION; } $msgbuf =~ s/^Host:\s+(.+)/Host: $server_host/m if $sock == $client; (my $safebuf = $msgbuf) =~ tr/\011\012\015\040-\176\240-\376/./cs; print "\n===== \U$who\E:\n$safebuf"; print "\n" unless substr($safebuf, -1, 1) eq "\n"; $target->syswrite($msgbuf, length $msgbuf); } last OUTER if $only_one; } print "[closing connection]\n" if $verbose; $client->shutdown(2) if $client; $server->shutdown(2) if $server; } sub shutdown { print "[shutting down]\n" if $verbose; $client->shutdown(2) if $client; $server->shutdown(2) if $server; $proxy ->shutdown(2); exit(0); }