#!/usr/bin/perl -w #==============================================================================# my $VERSION = 1.2; #==============================================================================# =head1 NAME ssh2ssl - SSH through SSL proxy tunnel =head1 DESCRIPTION Allows you to tunnel an SSH connection through an SSL (https) web proxy. =head1 README To use this script, you will need to the following to your ~/.ssh/config: Host ProxyCommand /path/to/bin/ssh2ssl %h:%p Port 443 You also need to have an sshd running on the far side. Your proxy probably won't let you use port 22, so run an "sshd -p443" on the and access it locally using "ssh " (the port was set in the config above). =head1 PREREQUISITES This script requires the C module. It also requires C, C and C modules. =head1 COREQUISITES none =head1 AUTHOR Gavin Brock http://brock-family.org/gavin =head1 COPYRIGHT (C) 2000 Gavin Brock - This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 CPAN INFO =pod OSNAMES any =pod SCRIPT CATEGORIES Web Networking =cut #==============================================================================# # No user servicable parts below # use 5.005; use strict; use IO::Handle; use IO::Socket; use IO::Select; # Get remote proxy and remote die "Usage: $0 PROXY:PORT REMOTE:PORT\n" if (my ($proxy,$remote) = @ARGV) != 2; print STDERR "ssl2ssh: Connecting to [$remote] via [$proxy]\n"; # Set up file handles my $pxy = IO::Socket::INET->new($proxy) || die "ssl2ssh: Can't open proxy: $!"; my $sto = IO::Handle->new_from_fd(fileno(STDOUT),"w"); my $sti = IO::Handle->new_from_fd(fileno(STDIN), "r"); my $rsel = IO::Select->new($pxy); my $wsel = IO::Select->new($pxy); # Now the clever part. We store the subroutines and buffers in the hash part of # the glob-ref. This gives it a pseudo-object behaviour. # Initalise buffers $$pxy->{'wbuf'} = "CONNECT $remote HTTP/1.0\n\n"; $$sto->{'wbuf'} = ""; sub finished { die "ssl2ssh: Connection closed.\n"; } # Callbacks for IO r/w $$pxy->{'can_write'} = sub { my $bw = $pxy->syswrite($$pxy->{'wbuf'},length $$pxy->{'wbuf'}); substr($$pxy->{'wbuf'},0,$bw,''); $wsel->remove($pxy) unless length $$pxy->{'wbuf'}; }; $$sto->{'can_write'} = sub { my $bw = $sto->syswrite($$sto->{'wbuf'},length $$sto->{'wbuf'}); substr($$sto->{'wbuf'},0,$bw,''); $wsel->remove($sto) unless length $$sto->{'wbuf'}; }; $$sti->{'can_read'} = sub { $sti->sysread($$pxy->{'wbuf'},1024,length $$pxy->{'wbuf'}) || finished; $wsel->add($pxy); }; $$pxy->{'can_read'} = sub { $pxy->sysread(my $buf,1024) || finished; $buf =~ /^HTTP\/1.\d 2\d\d/ || die "ssl2ssh: Server said:\n\n",$buf,"\n"; $rsel->add($sti); $$pxy->{'can_read'} = sub { # Redefine for 2nd time $pxy->sysread($$sto->{'wbuf'},1024,length $$sto->{'wbuf'}) || finished; $wsel->add($sto); }; }; # Loop forever while (my ($r,$w) = IO::Select::select($rsel,$wsel)) { foreach my $i (@$r) { $$i->{'can_read'}->() } foreach my $o (@$w) { $$o->{'can_write'}->() } } # # That's all folks... #==============================================================================#