[ISN] SSH Bouncing - How to get through firewalls easily, Part 2.

InfoSec News isn at c4i.org
Fri Sep 24 03:34:01 EDT 2004

|  Linux Security: Tips, Tricks, and Hackery      23-September-2004|
|  Published by Onsight, Inc.                             Edition  |
|                                                                  |
|  http://www.hackinglinuxexposed.com/articles/20040923.html       |

This issue sponsored by Beginning Perl, Second Edition

Hacking Linux Exposed author James Lee's most recent book, Beginning
Perl Second Edition, emphasizes the cross-platform nature of Perl.
Throughout the book, Lee promotes Perl as a legible, sensible
programming language and dispels the myth that Perl is confusing and
obscure. Perfect for the beginning Perl user looking to gain a quick
and masterful grasp on the language, this concise and focused book
begins with the basics and moves on to more advanced features of
Perl, including references, modules, and object-oriented programming.

For reviews and purchasing information, go to http://


SSH Bouncing - How to get through firewalls easily, Part 2.
By Brian Hatch

Summary: Often you'll have firewalls or other network equipment that
doesn't allow direct SSH access to machines behind it. Using a bit of
trickery, you can get through without seemingly jumping through any

Want to win a free copy of Hacking Linux Exposed, Third Edition? Go
to the very bottom of this newsletter to find out how.

Last time I showed you a trick to seamlessly SSH 'through' firewalls
or other devices that don't allow direct SSH access to the machines
behind them, by 'bouncing' off that device. It requires that you have
SSH access to the intermediate host, and what happens is that you set
up your ~/.ssh/config to use a ProxyCommand. This ProxyCommand makes
an SSH connection to the middleman host and runs netcat as follows to
get you connected to the real SSH server:

  nc -w 1 target_host 22

My goal was to be able to be at a command prompt and type 'ssh
hostname' and have it magically reach the endpoint.

Many people pointed out that I could have first established an SSH
connection to the intermediate host with an SSH forward set up, and
then ssh to the local SSH forward port. While I've used that system
many times before, I prefer the netcat solution I detailed last time.
If you want to know why or how the portforward version works, see the
bottom of this article.

So, let's optimise and secure our setup. Right now, you need to have
shell access to the middle-man machine, and the ability to run any
command you want. Plus, you either need to type the password for it,
or you need to have key-based trust enabled.

What I'd prefer is that you can execute the netcat command and only
the netcat command, nothing else. The easiest way to do that is to
use key-based authentication, utilising the ability for the SSH
server to force a command to run when that key is used. If you look
back at my previous articles (http://www.hackinglinuxexposed.com/
articles/20021211.html), you'll see how to create SSH PubKeys/
Identities, including how to use the 'command=' option.

So let's take a look at my $HOME/.ssh/authorized_keys file on the

  $ grep ncssh $HOME/.ssh/authorized_keys
  command="/home/bri/bin/ncssh" ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAp8
  kJbrWjIF0PIpSVdm3aqGSMOgQ7Pm1X87iz2nV1uQV4hMt06= ncssh-proxy-key

You'll note the command="/home/bri/bin/ncssh" line precedes the
public key itself - this forces the /home/bri/bin/ncssh program to
run when this key is used for authentication, regardless what the
user wanted to do. Assuming your key (on your desktop) doesn't have a
passphrase, you'll be able to log into this machine without a
password, and the ncssh program will run automatically.

Here's the ncssh program:

  # ncssh
  # Server-side program to allow clients to run ncssh-proxy
  # or simply 'ssh ... nc -w 1 ipaddr 22' and 'bounce' off
  # this host.
  # BUGS:
  #   Only allows IP addresses.  If that annoys you,
  #   change $IPADDR pattern below.
  #   Ditto for the destination port.
  # Copyright 2003,2004 Brian Hatch
  # Released under the GPL

  # Likely paths for netcat - let's be paranoid and not
  # fall back on just any old thing we find.
  # Bonus points to anyone who knows why /usr/local/lib/pingers is in there.
  my @nc = qw( /usr/bin/nc /usr/local/bin/nc /usr/local/lib/pingers/nc );
  my $nc;
  for my $bin ( @nc ) {
          $nc = $bin if -x $bin

  my $IPADDR = '\d+\.\d+\.\d+\.\d+';

  my $SSHPORT = '22';
  # Change '22' to '\d+' if you want to allow any
  # destination port, not just port 22.

  # The original command (nc -w 1 ip.ad.dr.es 22) is stored by
  # the SSH server in the environment variable SSH_ORIGINAL_COMMAND.

  # If command is just the IP address to which it should connect
  if ( $orig =~ /^ \s* $IPADDR \s* $/x ) {
          $ipaddr = $orig;

  # If command is a 'nc -w ... host 22' style command
  } elsif ( $orig =~ /^ \S* (netcat|nc) \s .*? ($IPADDR) \s $SSHPORT \s* $/x ) {
          $ipaddr = $2;

  # Time to actually run netcat
  if ( $ipaddr ) {
          $nc or print STDERR "No netcat found\n" and exit 1;
          exec $nc, '-w', '1' , $ipaddr, 22;
          die "Unable to exec netcat '$nc': $? $!";
  print STDERR "You're not allowed to execute '$orig'\n";
  exit 1;

This program is very simple[1] -- it takes the original command
(supplied by the ssh client) and determines where the IP address of
the target is within it. By accepting commands of the form 'nc ...
ip.ad.dr.es 22', it should work unchanged with any ProxyCommand you
already have, meaning you can just drop it in and your intermediate
host will be more paranoid instantly.[2]

Your $HOME/.ssh/config can still look exactly the same as before, as
seen here:

  $ head $HOME/.ssh/config
  Host machine1
  Hostname machine1
  HostKeyAlias machine1
  Identity /path/to/ncssh-proxy-key
  ProxyCommand netcat-proxy-command firewall.my_network.com

  Host machine2
  Hostname machine2
  HostKeyAlias machine2
  Identity /path/to/ncssh-proxy-key
  ProxyCommand netcat-proxy-command firewall.my_network.com


(This configuration uses the netcat-proxy-command script shown last

So, using this system, you have the following situation:

  * Client can type 'ssh machinename' and not worry about any of the
    underlying magic.
  * Local $HOME/.ssh/config file details the middleman and
    destination, listing the identity to use (if necessary), and
    causing the netcat-proxy-command to run.
  * Local netcat-proxy-command is responsible for SSHing to the
    middleman and running netcat.
  * Server's authorized_keys file forces the ncssh command to run,
    preventing anyone from actually accessing the server's shell
    account at all.
  * Server's ncssh program verifies supplied IP address and makes
    actual connection to the target.

All told, a paranoid and yet functional solution.

Next time we'll do one more enhancement - make it possible to have
any user on the client machine get access to the Identity/PubKey
that's necessary to bounce off the middleman. This will allow anyone
to log into this machine, and without setting up any keys or
configuration, log into the target machines transparently.


My response to the LocalForward Solution

It's possible to use an SSH LocalForward to tunnel through the
firewall device. You run ssh twice, once to set up the tunnel, and
once to connect to the server behind it:

    $ ssh -f intermediatehost -L 9999:destinationhost:22 sleep +1d
    $ ssh localhost -p 9999

This is a completely legitimate way to do it. The first command logs
into intermediatehost, and sets up a LocalForward using the -L
option. /usr/bin/ssh binds local port 9999, and when you connect to
this port it gets tunnelled inside the SSH connection to
destinationhost's port 22. The next ssh line connects to that port,
and you're hitting the target server. Naturally you need HostKeyAlias
commands to keep the keys happy, as is the case with my netcat

What's the problem with using the forwarding method? Well, it
requires you run the tunnel command first, or set up a daemon to keep
it running all the time. You don't get the benefit of simplicity -
running one command that contains all the setup that's necessary.


Want a free copy of Hacking Linux Exposed, Third Edition?

HLEv3 doesn't exist yet. We haven't written it. But it's time to get
started. Do you have anything new you'd like to see covered in more
detail, or removed entirely? Anything new and interesting you'd like
to see?

If you have ideas you'd like to share, email me[3]. I'll send out a
copy of the book, once it's down in dead-tree format, to one lucky
person picked at random from the useful suggestions.


[1] Simple, and well commented, I hope.

[2] I had a few folks complain that I should not assume your SSH
server runs on port 22, so please change the $SSHPORT value in the
script as appropriate.

[3] Send me email directly at bri at hackinglinuxexposed.com, don't
reply to this mailing list.

Brian Hatch is Chief Hacker at Onsight, Inc and author of Hacking
Linux Exposed and Building Linux VPNs. He's simply too tired to write
anything interesting down here right now. Brian can be reached at
brian at hackinglinuxexposed.com.

This newsletter is distributed by Onsight, Inc.

The list is managed with MailMan (http://www.list.org). You can
subscribe, unsubscribe, or change your password by visiting
http://lists.onsight.com/ or by sending email to
linux_security-request at lists.onsight.com.

Archives of this and previous newsletters are available at


Copyright 2004, Brian Hatch.

More information about the ISN mailing list