Subject: Re: SSH/Firewall
From: Dario Alcocer <dalcocer@home.com>
Date: Wed, 16 Aug 2000 12:50:40 -0700 (PDT)
>>>>> "Nathan" == Nathan Brown <NBrown@Chrystal.com> writes:
Nathan> At work, we have this firewall through which all
Nathan> connections to the outside world pass
Nathan> through. <snip>
Nathan> ...I am trying to SSH to my box at home. I have no
Nathan> control over the firewall, and am tearing my hair out
Nathan> trying to figure out how to beat it. The only port I know
Nathan> for sure that works is 80, but even that is proxied. The
Nathan> proxy doesn't support SOCKS X proxy either, so that is
Nathan> giving me trouble with one of the clients I
Nathan> tried. <snip>
Nathan> The server works, so that's not an issue, its
Nathan> getting around this firewall that is the issue.
I found myself in the same unfortunate situation once as well.
Thankfully, I did manage to find a solution that worked. Basically it
involves running your SSH server at home on a port that the firewall
will allow encrypted traffic on, and arranging for your ssh client to
proxy its connection. Here are the steps I followed:
1. In my situation, I found out they were using Squid for proxy
connections. It turns out that their Squid server allowed outbound
proxy connections for HTTPS (port 443) or NNTPS (port 563.) So, your
first step is to run the following to launch a second sshd that will
listen to one of these ports:
# tell ssh to listen on nntps port too
/usr/local/sbin/sshd -p 563
2. On your ssh client machine, you'll need to add a proxy command line
to your ~/.ssh/config file, so that ssh will know how to proxy the
connection to your home ssh server:
Host homepc
ProxyCommand /usr/local/bin/ssh-tunnel proxy.acme.com 80 w.x.y.z 563
Of course, for this to work, you'll need to use ssh-tunnel (attached)
and have Perl installed on your ssh client in order for this to work.
Replace 'proxy.acme.com 80' with the correct name and port number
that the proxy server uses, and replace w.x.y.z with the IP address or
fully qualified domain name of your homepc.
3. When you need to connect to home machine, use 'homepc' (or
whatever name you chose to use in Host directive in step 2) as the
machine name to connect to:
$ ssh homepc
4. (Optional) As a bonus, you can use your ssh connection to provide
you encrypted web-surfing access via your home PC, if you or your ISP
runs a proxy server. In particular, @Home subscribers can use ssh's
port forwarding to point to their proxy server:
$ ssh -L 8080:proxy.fed1.sdca.home.com:8080 -C homepc
For this to example to work, you'll have to set your web browser
running on the ssh client to use localhost:8080 as the "proxy", which
will actually send your HTTP traffic encrypted to 'homepc', where
'homepc' will decrypt it and forward it on to
proxy.fed1.sdca.home.com:8080.
Content-Description: ssh-tunnel: proxy interface for ssh
filename="ssh-tunnel"
#!/usr/bin/perl
#
# Usage: ssh-tunnel.pl [daemon port] ssl-proxy port destination_host port
#
# This script can be used by ssh to traverse a www-proxy/firewall that
# supports the http CONNECT command. (Note: Properly setup proxies that allow
# CONNECT will only allow a connection through to SSL ports (443 and 563
# according to squid.))
#
# Example-- connect to host named "remote" outside of your firewall:
#
# $ ssh remote -o'ProxyCommand ssh-tunnel.pl www-proxy 8080 remote 443'
#
# Better yet, insert the ProxyCommand definition for host "remote" in
# your $HOME/.ssh/config file:
#
# .
# .
# Host remote
# ProxyCommand /usr/local/bin/ssh-tunnel.pl www-proxy 8080 %h %p
# .
# .
#
# Originally written by Urban Kaveus <urban@statt.ericsson.se>
#
# Updated by Theo Van Dinter <tvd@chrysalis.com>,<felicity@kluge.net> 4/28/1999
# I use TTSSH under Windows which doesn't support the proxycommand option.
# I made some modifications to this script to help with that:
# 1- The script no longer forks to do IO. Now uses IO::Select to deal with
# multiple filehandles at once.
# 2- The script can optionally "daemonize" itself and sit on a port. When
# a connection is established, the tunnelling process will commence.
# Add in the optional port # to listen to as the first commandline param.
# Ex: "ssh-tunnel 2345 www-proxy 8080 remotehost 443", then start SSH:
# "ssh localhost -p 2345".
# 3- Tested with ActivePerl (Win32)/TeraTerm/TTSSH and UNIX Perl/SSH client.
#
use Socket;
use IO::Select;
$dport = shift if ( $#ARGV > 3 );
($sslproxy,$proxyport,$destination,$destport) = @ARGV;
die "Usage: $0 [daemon port] ssl-proxy port destination port\n"
unless ( $sslproxy && $proxyport && $destination && $destport );
# set up log file
#open(LOG, ">>/tmp/ssh-tunnel.log") ||
# die "unable to open logfile: $!";
#print LOG "====== ssh-tunnel started.\n";
# Set up network communication
$protocol = getprotobyname("tcp");
if ( $dport ) { # do "daemon" thing.
socket(INC, PF_INET, SOCK_STREAM, $protocol) || die "socket:$!";
setsockopt (INC, SOL_SOCKET, SO_REUSEADDR, pack ("l", 1)) || die "setsockopt:$!";
bind(INC,sockaddr_in($dport,INADDR_ANY)) || die "bind: $!";
listen(INC,1) || die "listen:$!";
accept(OUT,INC) || die "accept:$!";
$fhin = $fhout = \*OUT;
}
else { # STDIN/STDOUT used ...
$fhin = \*STDIN;
$fhout = \*STDOUT;
}
# connect to proxy server ...
socket (PROXY, PF_INET, SOCK_STREAM, $protocol) or
die("Failed to create socket:$!");
connect (PROXY, sockaddr_in($proxyport,inet_aton($sslproxy))) or
die("Failed to connect to $sslproxy port $proxyport:$!");
# Force flushing of socket buffers
foreach ( \*PROXY, $fhin, $fhout ) {
select($_); $|=1;
}
# Send a "CONNECT" command to proxy:
print PROXY "CONNECT $destination:$destport HTTP/1.0\r\n\r\n";
# Wait for HTTP status code, bail out if you don't get back a 2xx code.
($status) = (split(/\s+/,<PROXY>))[1];
die "Received a bad status code \"$status\" from proxy server."
if ( int($status/100) != 2 );
# Skip through remaining part of HTTP header (until blank line)
1 until ( <PROXY> =~ /^[\r\n]+$/ );
# Start copying packets in both directions.
$s = IO::Select->new($fhin,\*PROXY);
while ( 1 ) {
foreach $fh ( $s->can_read(10) ) {
exit unless ( defined($num = sysread($fh,$_,4096)) );
exit if $num == 0;
#$tstamp = localtime;
#print LOG $tstamp, ": read ", $num, " bytes.\n";
exit unless ( defined(syswrite( ((fileno($fh)==fileno($fhin))?
PROXY:$fhout),$_,$num)) );
#print LOG $tstamp, ": wrote ", $num, " bytes.\n";
}
}
Hope this helps.
--
Dario Alcocer // dalcocer@home.com
---
http://www.kernel-panic.org
list archives http://www.ultraviolet.org
To unsubscribe, send a message to the address shown in the list-unsubscribe
header of this message.
Note1: Yes, it also works with Putty's
pre-connect.
Note2: If you need to run sshd on port 443 (https) but want to keep
your apache-ssl there, this is
possible.
Back to my (mostly german) homepage