1#!/usr/local/bin/perl 2# simple HTTPS proxy with SSL bridging, uses Net::PcapWriter to 3# to log unencrypted traffic 4 5my $listen = '127.0.0.1:8443'; # where to listen 6my $connect = 'www.google.com:443'; # where to connect 7 8use strict; 9use warnings; 10use IO::Socket::SSL; 11use IO::Socket::SSL::Intercept; 12use IO::Socket::SSL::Utils; 13 14my ($proxy_cert,$proxy_key) = CERT_create( 15 CA => 1, 16 subject => { commonName => 'foobar' } 17); 18 19 20my $mitm = IO::Socket::SSL::Intercept->new( 21 proxy_cert => $proxy_cert, 22 proxy_key => $proxy_key, 23); 24 25my $listener = IO::Socket::INET->new( 26 LocalAddr => $listen, 27 Listen => 10, 28 Reuse => 1, 29) or die "failed to create listener: $!"; 30 31while (1) { 32 # get connection from client 33 my $toc = $listener->accept or next; 34 35 # create new connection to server 36 my $tos = IO::Socket::SSL->new( 37 PeerAddr => $connect, 38 SSL_verify_mode => 1, 39 SSL_ca_path => '/etc/ssl/certs', 40 ) or die "ssl connect to $connect failed: $!,$SSL_ERROR"; 41 42 # clone cert from server 43 my ($cert,$key) = $mitm->clone_cert( $tos->peer_certificate ); 44 45 # and upgrade connection to client to SSL with cloned cert 46 IO::Socket::SSL->start_SSL($toc, 47 SSL_server => 1, 48 SSL_cert => $cert, 49 SSL_key => $key, 50 ) or die "failed to ssl upgrade: $SSL_ERROR"; 51 52 # transfer data 53 my $readmask = ''; 54 vec($readmask,fileno($tos),1) = 1; 55 vec($readmask,fileno($toc),1) = 1; 56 while (1) { 57 select( my $can_read = $readmask,undef,undef,undef ) >0 or die $!; 58 # try to read the maximum frame size of SSL to avoid issues 59 # with pending data 60 if ( vec($can_read,fileno($tos),1)) { 61 sysread($tos,my $buf,16384) or last; 62 print $toc $buf; 63 } 64 if ( vec($can_read,fileno($toc),1)) { 65 sysread($toc,my $buf,16384) or last; 66 print $tos $buf; 67 } 68 } 69} 70 71 72