#!/usr/bin/perl -w #==============================================================================# my $VERSION = 1.5; #==============================================================================# =head1 NAME ssh2ssl - SSH through SSL proxy tunnel =head1 DESCRIPTION Allows you to tunnel an SSH connection through an SSL (https) web proxy. =head1 USAGE 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 TIPS =head2 DISCONNECTS Most proxies and some firewalls will disconnect idle sessions, so if your ssh sessions are being dropped, you have several options. The easiest is to just leave something like 'top' running in your session while you are not using it. Similarly you could also tunnel an X application to generate traffic. However the best way is to add the following to entries into you sshd.config : ClientAliveInterval 15 ClientAliveCountMax 3 These will cause the ssh daemon to check the client is ok, and so creates a small amount of traffic to keep the session alive. =head1 PREREQUISITES This script requires the C, C and C modules. =head1 COREQUISITES none =head1 AUTHOR Gavin Brock http://brock-family.org/gavin =head1 COPYRIGHT (C) 2004 Gavin Brock - This script is free software; you can redistribute it and/or modify it under the same terms as Perl itself. =head1 README This script allows you to tunnel an SSH connection through an SSL (https) web proxy. =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 "ssh2ssl: Connecting to [$remote] via [$proxy]\n"; # Set up file handles my $pxy = IO::Socket::INET->new($proxy) || die "ssh2ssl: 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 "ssh2ssl: 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 "ssh2ssl: 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... #==============================================================================#