Revision 126

Date:
2010/01/05 15:13:31
Author:
dpavlin
Revision Log:
SSL Man-In-The-Middle v0.1. Copyright (C) Vlatko Kosturjak, Kost

Distributed under GPL v2+.
Files:

Legend:

 
Added
 
Removed
 
Modified
  • trunk/mitm-ssl.pl

     
    1 #!/usr/bin/perl
    2 # SSL Man-In-The-Middle v0.1. Copyright (C) Vlatko Kosturjak, Kost
    3 # Distributed under GPL v2+.
    4
    5 use strict;
    6 use POSIX;
    7 use IO::Socket::SSL;
    8 use Getopt::Long;
    9
    10 my $localport;
    11 my $localaddr;
    12 my $help;
    13 my $host;
    14 my $port;
    15 my $daemon;
    16 my $buffersize= 2048;
    17 my $logtype;
    18 my $logdir;
    19 my $daemon;
    20 my $serverkey; my $servercert; my $serverdh;
    21
    22 $| = 1;
    23
    24 my $goresult = GetOptions ( "lport=i" => \$localport,
    25 "laddr=s" => \$localaddr,
    26 "rport=i" => \$port,
    27 "raddr=s" => \$host,
    28 "logtype=i" => \$logtype,
    29 "logdir=s" => \$logdir,
    30 "daemon" => \$daemon,
    31 "serverkey=s" => \$serverkey,
    32 "servercert=s" => \$servercert,
    33 "serverdh=s" => \$serverdh,
    34 "help" => \$help
    35 );
    36
    37 if ($help) {
    38 print <<"END";
    39 SSL Man-In-The-Middle v0.1. Copyright (C) Vlatko Kosturjak, Kost
    40 Distributed under GPL v2+.
    41
    42 Usage: $0 [OPTIONS]
    43
    44 --lport <port> Listening port (default 80)
    45 --laddr <address> Listening address (default localhost)
    46 --rport <port> Remote port to connect to (default 8080)
    47 --raddr <address> Remote address to connect to (default localhost)
    48 --serverkey <file> Certificate key file for local SSL server
    49 --servercert <file> Certificate file for local SSL server
    50 --serverdh <file> Diffie-Helman file for key exchange
    51 --log <type> Type of log where 0 is no log (default 0)
    52 --logdir Directory to log to (default .)
    53 --daemon Daemonize (work in background)
    54 --help Display this help message
    55 END
    56 exit;
    57 }
    58
    59 # set default values
    60 $localport=8080 unless ($localport);
    61 $localaddr="127.0.0.1" unless ($localaddr);
    62 $port=80 unless ($port);
    63 $host="127.0.0.1" unless ($host);
    64 $logdir="." unless ($logdir);
    65
    66 my %o = ( 'dir' => $logdir, 'port' => $localport, 'toport' => $port, 'tohost' => $host );
    67
    68 if ($daemon) {
    69 my $pid = fork;
    70 exit if $pid;
    71 die "$!" unless defined($pid);
    72 POSIX::setsid() or die "$!";
    73 }
    74
    75 my $ah = IO::Socket::SSL->new(
    76 'LocalPort' => $localport,
    77 'LocalAddr' => $localaddr,
    78 'Reuse' => 1,
    79 'Proto' => 'tcp',
    80 'SSL_verify_mode' => '0',
    81 'SSLdhfile' => $serverdh,
    82 'SSL_cert_file' => $servercert,
    83 'SSL_key_file' => $serverkey,
    84 'Listen' => 10
    85 ) || die "$!";
    86
    87 $SIG{'CHLD'} = 'IGNORE';
    88 my $num = 0;
    89
    90 while (1) {
    91 my $ch = $ah->accept();
    92 if ( !$ch ) { print STDERR "cannot accept: $!\n"; next; }
    93 ++$num;
    94 my $pid = fork();
    95 if ( !defined($pid) ) { print STDERR "cannot fork while(1) $!\n"; }
    96 elsif ( $pid == 0 ) { $ah->close(SSL_no_shutdown => 1); Run( \%o, $ch, $num ); }
    97 else { $ch->close(SSL_no_shutdown => 1); }
    98 }
    99
    100 sub Run {
    101 my ( $o, $ch, $num ) = @_;
    102 my $th = IO::Socket::SSL->new(
    103 'PeerAddr' => $o->{'tohost'},
    104 'PeerPort' => $o->{'toport'},
    105 'SSL_use_cert' => '0',
    106 'SSL_verify_mode' => '0',
    107 # 'SSL_cipher_list' => 'NUL:LOW:EXP:ADH',
    108 'SSL_version' => 'SSLv3', # SSLv3, SSLv2, TLSv1
    109 'Proto' => 'tcp'
    110 );
    111 if ( !$th ) { print "cannot connect th: $!"; exit 0; }
    112 else { print "connected!"; }
    113 my $fh;
    114 if ( $o->{'dir'} ) {
    115 $fh = Symbol::gensym();
    116 open( $fh, ">$o->{'dir'}/tunnel$num.log" ) or die "$!";
    117 }
    118 $ch->autoflush();
    119 $th->autoflush();
    120 my $httpheader="";
    121 my $httpbuf="";
    122 while ( $ch || $th ) {
    123 my $rin = "";
    124 vec( $rin, fileno($ch), 1 ) = 1 if $ch;
    125 vec( $rin, fileno($th), 1 ) = 1 if $th;
    126 my ( $rout, $eout );
    127 select( $rout = $rin, undef, $eout = $rin, 120 );
    128 if ( !$rout && !$eout ) { }
    129 my $cbuffer = "";
    130 my $tbuffer = "";
    131
    132 if ( $ch
    133 && ( vec( $eout, fileno($ch), 1 ) || vec( $rout, fileno($ch), 1 ) )
    134 )
    135 {
    136 my $result = sysread( $ch, $tbuffer, $buffersize );
    137 if ( !defined($result) ) {
    138 print STDERR "$!\n";
    139 exit 0;
    140 }
    141 if ( $result == 0 ) { exit 0; }
    142 }
    143 if ( $th
    144 && ( vec( $eout, fileno($th), 1 ) || vec( $rout, fileno($th), 1 ) )
    145 )
    146 {
    147 my $result = sysread( $th, $cbuffer, $buffersize );
    148 if ( !defined($result) ) { print STDERR "$!\n"; exit 0; }
    149 if ( $result == 0 ) { exit 0; }
    150 }
    151 if ( $fh && $tbuffer ) { ( print $fh "[c]".$tbuffer."[/c]" ); }
    152 while ( my $len = length($tbuffer) ) {
    153 my $res = syswrite( $th, $tbuffer, $len );
    154 if ( $res > 0 ) { $tbuffer = substr( $tbuffer, $res ); }
    155 else { print STDERR "$!\n"; }
    156 }
    157 if ( $fh && $cbuffer ) { ( print $fh "[s]".$cbuffer."[/s]"); }
    158 while ( my $len = length($cbuffer) ) {
    159 my $res = syswrite( $ch, $cbuffer, $len );
    160 if ( $res > 0 ) { $cbuffer = substr( $cbuffer, $res ); }
    161 else { print STDERR "$!\n"; }
    162 }
    163 }
    164 }
    165