Greetings all!

I'm new here, please excuse my noob post or/and codings. I've been searching for months to solve my little issue hope that you monks can help out.

From many resources and examples from the net, I tried to do a threaded http proxy script to speedup my personal needs which intercepts certain slow urls to perform local caching by retrieving from multiple mirrors. Auth basic digest, FTP, HTTP POST/GET etc² including HTTPS CONNECT are already working great as I expected but I'm having problem with sites that needs TSL handshakes.

Do I have to upgrade the accepted listening and remote sockets with IO::Socket::SSL to perform the handshakes? Or is there any special needs to handle the handshakes with normal HTTP CONNECT tunnel? I can't find any tutorials on these but as I recall looking in the http://www.privoxy.org/ source codes, it just implement normal HTTP CONNECT, return "HTTP/1.0 200 Connection established\r\n\r\n" when connected and start forwarding request. Privoxy works but mine in perl doesn't.

Below is a small part of my newbie codings. It's a workable http proxy on all http/https sites but not on those which requires proper handshakes. I've checked in Wireshark and saw the handshakes being done between client and remote but eventually the connection got drop. I've tried non-blocking, adjusting buffer/socket sizes yet no luck. Please help to advise. Thank you.

#!/usr/bin/perl use strict; use warnings; use threads; use IO::Socket; use IO::Select; my $daemon = IO::Socket::INET->new ( LocalAddr => '192.168.1.16', LocalPort => 8888, PeerAddr => inet_ntoa(INADDR_BROADCAST), PeerPort => 8888, Type => SOCK_STREAM, Proto => 'tcp', ReuseAddr => 1, Listen => SOMAXCONN ) or do { print "[ERROR]\t$@\n"; exit 1 }; binmode $daemon; $daemon->blocking(0); $daemon->autoflush(1); while (1) { if (my $browser = $daemon->accept) { binmode $browser; $browser->blocking(0); $browser->autoflush(1); eval { threads->create(\&doConnect, $browser)->detach }; if ($@) { print "[ERROR]\t$@\n"; exit 1 } } select(undef, undef, undef, (int(rand(60)) ? '.001':0)) } sub doConnect { my $browser = shift; my ($server, $ftp, $serverhost, $serverport) = ''; binmode $browser; $browser->blocking(0); $browser->autoflush(1); my $select = IO::Select->new($browser); while (1) { for my $connection ($select->can_read(60)) { my %req = (); my ($uri_host, $uri_port, $crlf) = ''; $connection->sysread(my $buffer, 65536) or goto EXIT; if ($connection == $browser && $buffer =~ /^\w+ +\S+ +\S+\ +015\012/s) { foreach my $pipes (split(/\015\012/, $buffer)) { chomp $pipes; $pipes =~ s/\r\n+//sg; $pipes =~ s/\r+|\n+//sg; $pipes =~ s/^\s+|\s+$//sg; $pipes =~ s/\f+//sg; $pipes =~ s/\s+|\t+/ /sg; unless ($req{METHOD}) { if ($pipes =~ /^(\w+) +(\S+) +(\S+)/s) { $req{METHOD} = uc $1; $req{URI} = $2; $req{PROTO} = uc $3 } else { last } } elsif ($pipes =~ /^(.+)\: (.+)$/) { $req{HEADER_ORIG}{$1} = $2; $req{HEADER_SYST}{lc($1)} = $2 } else { last } } if ($req{HEADER_SYST}{'content-length'}) { while ($buffer =~ /\015\012\015\012/g) { $crlf = pos $buffer; last } } my ($uri_schema, $uri_location, $uri_path, $uri_query, + undef) = ($req{URI} =~ m,(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?: +\?([^#]*))?(?:#(.*))?,); $uri_schema = lc $uri_schema; if ($uri_schema ne 'http' && $uri_schema ne 'https') { $uri_location = $uri_schema; if ($uri_path =~ /^\//) { $uri_schema = 'http' } else { $uri_schema = 'https'; $uri_path = $uri_location } } ($serverhost, $serverport) = split(':', lc $req{HEADER +_SYST}{host}); if ($serverhost eq '' && $uri_host ne '') { $serverhost = $uri_host; $serverport = $uri_port } elsif ($serverhost ne '' && $uri_host ne '' && $server +host ne $uri_host) { $serverhost = $uri_host; $serverport = $uri_port } if (!$serverport) { if ($uri_schema eq 'https' || $req{METHOD} eq 'CON +NECT') { $serverport = 443 } else { $serverport = 80 } } if ($serverhost eq '') { $serverhost = '0.0.0.0'; $serverport = 0 } my $connect_host = $serverhost; my $connect_port = $serverport; if ($req{METHOD} =~ /GET|HEAD|POST|PUT|DELETE|TRACE|OP +TIONS|PATCH|CONNECT/) { $req{URI} = $uri_path . ($uri_query ? "?$uri_query +":''); print "[INFO]\t" . $browser->peerhost . "\tCID:" . + $browser->peerport . "\t$serverhost:$serverport $req{PROTO} $req{MET +HOD} $req{URI}\n"; $server = IO::Socket::INET->new ( PeerAddr => $connect_host, PeerPort => $connect_port, Type => SOCK_STREAM, Proto => 'tcp', ReuseAddr => 1, Timeout => 60 ) or return print "[ERROR]\t$@\n"; $browser->blocking(1); binmode $server; $server->blocking(1); $server->autoflush(1); $select->add($server); my $respond = ''; if ($req{METHOD} eq 'CONNECT') { $respond .= "$req{PROTO} 200 Connection establ +ished\015\012\015\012"; $connection = $server } else { $respond .= "$req{METHOD} $req{URI} $req{PROTO +}\015\012"; for my $list (keys %{$req{HEADER_ORIG}}) { next if $list =~ /^Proxy\-Authorization/i; if ($list =~ /Connection/i) { $respond .= "Connection: $req{HEADER_O +RIG}{$list}\015\012" } else { $respond .= "$list: $req{HEADER_ORIG}{ +$list}\015\012" } } $respond .= "X-Forwarded-For: " . $browser->pe +erhost . "\015\012\015\012"; if ($req{HEADER_SYST}{'content-length'}) { my $content = substr($buffer, $crlf || -$r +eq{HEADER_SYST}{'content-length'}); sysread($connection, $content, $req{HEADER +_SYST}{'content-length'}) if $content eq ''; $respond .= $content if $content ne '' } } $buffer = $respond } } ($connection == $browser ? $server:$browser)->syswrite($bu +ffer) } } EXIT: if ($browser) { $select->remove($browser); $browser->shutdown(2); $browser->close; undef $browser } if ($server) { $select->remove($server); $server->shutdown(2); $server->close; undef $server } threads->exit }

In reply to TLS tunnel through HTTP proxy by Nazar78

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.