ETOOBUSY 🚀 minimal blogging for the impatient
Proxy setup for Netcat in Perl
TL;DR
Adding support for
CONNECT
setup in a Netcat for Perl. All code in a single sweep inside this snippet.
In Reinventing Netcat in Perl we saw a way of putting some code that implements the basic functionality of Netcat in Perl.
Now it’s time to look at the support for HTTP proxies that accept the
CONNECT
method:
package IO::Flows::HttpProxy;
use v5.24;
use warnings;
use experimental 'signatures';
no warnings 'experimental::signatures';
use Exporter 'import';
our @EXPORT_OK = qw< proxy_CONNECT >;
sub _peer_socket ($hp) {
my ($host, $port) = split m{:}mxs, $hp;
require IO::Socket::INET;
IO::Socket::INET->new(
Proto => 'tcp',
PeerAddr => $host,
PeerPort => $port,
) or die "IO::Socket $!\n";
}
sub proxy_CONNECT ($proxy, $target, $credentials = undef) {
state $CRLF = "\x{0d}\x{0a}";
my $pxy = _peer_socket($proxy);
my @request = (
"CONNECT $target HTTP/1.1",
"Host: $target",
);
if (defined $credentials) {
require MIME::Base64;
$credentials = MIME::Base64::encode_base64($credentials, '');
push @request, "Proxy-Authorization: Basic $credentials";
}
my $flower = IO::Flows->new;
my $sid = $flower->add_flow(
{
read => {fh => undef},
write => {fh => $pxy, shutdown => 0},
buffer => join($CRLF, @request, '', ''),
}
);
my $rflow = {
read => {fh => $pxy, shutdown => 0},
write => {fh => undef},
buffer => '',
};
my $rid = $flower->add_flow($rflow);
while ('necessary') {
$flower->spin or die "whatevah\n";
$rflow->{buffer} =~ s{\A (.*?) (?-x:\x{0d}?\x{0a}\x{0d}?\x{0a}) }{}mxs or next;
my $headers = $1;
print {*STDERR} "HEADERS:\n>$headers<\n";
return (
{
read => { fh => $pxy },
buffer => $rflow->{buffer},
},
{
write => { fh => $pxy },
buffer => '',
},
);
}
}
1;
package main;
my ($rpxy, $wpxy) = IO::Flows::HttpProxy::proxy_CONNECT(@ARGV);
my $flower = IO::Flows->new;
$flower->add_flow({$rpxy->%*, write => { fh => \*STDOUT }});
$flower->add_flow({$wpxy->%*, read => { fh => \*STDIN }});
1 while $flower->spin;
$flower->close_all;
The idea is to create the connection to the proxy and handle the initial
part where the other connection is setup. After that, we use
IO::Flows
to revert to the old Netcat behaviour: connect the
standard I/O descriptors with the socket to the proxy.
All code in a single sweep inside this snippet.
Stay safe folks!