OpenBSD Journal

Stupid SSH Tricks: ProxyCommand

Contributed by merdely on from the ssh-is-teh-awesome dept.

Suppose there is an SSH server inside a remote network that does not have its SSH port exposed to the Internet (named "internal.hostname.tld"). If there is an SSH gateway host that you can SSH to (that has the ability to reach "internal"'s SSH port), you can use the netcat (nc(1)) command with ProxyCommand in ~/.ssh/config to proxy your SSH session to "internal" through "gateway". Read on for more details.

Submit your own Stupid Open{BSD,SSH} Tricks.

Put the following entry in your ~/.ssh/config file:

Host internal.hostname.tld internal
  User          merdely
  HostName      internal.hostname.tld
  ProxyCommand  ssh merdely@gateway.hostname.tld nc %h %p 2> /dev/null

Then, make connect to "internal" as if you could directly: ssh internal.hostname.tld

The ~/.ssh/config entries are:

  • Host: Defines for which host or hosts the configuration section applies. The section ends with a new Host section or the end of the file.
  • User: Defines the username for the SSH connection. Useful if your username on the remote host is different from your local username.
  • HostName: Defines the literal hostname for the remote server. Useful if a nickname for the host is used in the Host line.
  • ProxyCommand: Specifies the proxy command for the connection. This command is launched prior to making the connection to Hostname. %h is replaced with the host defined in HostName and %p is replaced with 22 or is overridden by a Port directive. "2> /dev/null" prevents nc's "Killed by signal 1." message when it exits.
For more information about ssh client configuration options, see ssh_config(5).

(Comments are closed)


  1. By jb (jb) jb@caustic.org on

    All this time, I've just been using ssh -L for that specific problem.

    1. By Anonymous Coward (206.248.190.11) on

      > All this time, I've just been using ssh -L for that specific problem.

      How exactly does tunning a local port through your ssh connection to the gateway machine help the situation any?

      1. By jb (jb) on


        > How exactly does tunning a local port through your ssh connection to the gateway machine help the situation any?

        ssh -L 2222:[internal machine]:22 -N && ssh -p 2222 localhost

        It works. "oh crap, ssh over ssh, that's dumb" is not a reasonable answer for why you'd not do it.

        1. By Anonymous Coward (206.248.190.11) on

          >
          > > How exactly does tunning a local port through your ssh connection to the gateway machine help the situation any?
          >
          > ssh -L 2222:[internal machine]:22 -N && ssh -p 2222 localhost
          >
          > It works. "oh crap, ssh over ssh, that's dumb" is not a reasonable answer for why you'd not do it.

          Actually, it is a reasonable answer for why you'd not do it. The fact that its alot more to type than "ssh somehost" is another reason. In fact, its complex enough that you typed it in wrong for us, demonstrating very nicely why its not as good as using ProxyCommand, which exists for this very purpose.

        2. By Anonymous Coward (24.37.242.64) on

          >
          > > How exactly does tunning a local port through your ssh connection to the gateway machine help the situation any?
          >
          > ssh -L 2222:[internal machine]:22 -N && ssh -p 2222 localhost
          >
          > It works. "oh crap, ssh over ssh, that's dumb" is not a reasonable answer for why you'd not do it.

          If I understand this correctly, this assumes port 2222 (in this example) is open to any host on the inside, from the outside? If so, anyone who has a network unsecured like this deserves what could happen.

          None the less, I guess it's still handy to know or think of tricks like this. =)

          1. By Mike Erdely (merdely) on http://erdelynet.com/

            > > > How exactly does tunning a local port through your ssh connection
            > > > to the gateway machine help the situation any?
            > >
            > > ssh -L 2222:[internal machine]:22 -N && ssh -p 2222 localhost
            > >
            > > It works. "oh crap, ssh over ssh, that's dumb" is not a reasonable
            > > answer for why you'd not do it.
            >
            > If I understand this correctly, this assumes port 2222 (in this example)
            > is open to any host on the inside, from the outside? If so, anyone who
            > has a network unsecured like this deserves what could happen.
            >
            > None the less, I guess it's still handy to know or think of tricks like
            > this. =)

            First, there's an mistake in his example. Probably a more useful version of his command is:
            ssh -f -L 2222:[internal machine]:22 [external machine] "sleep 5" && \
            ssh -p 2222 localhost

            2222 is open only on localhost in the ssh client's machine (assuming GatewayPorts is no, which is the default). Read more about tunneling with SSH. This *does* assume port 22 is open on [external machine].

            -ME

  2. By Anonymous Coward (143.209.103.37) on

    Very slick....I like it!

    1. By Mark Shroyer (Niten) on http://markshroyer.com/

      > Very slick....I like it!

      Yeah, thanks merdely... all this time I've been starting a full-fledged OpenVPN tunnel whenever I needed to SSH into one of my internal hosts for a minute. For some reason this just never occurred to me, even though I've used ProxyCommand before.

  3. By dbt (208.116.167.12) dbt@meat.net on http://meat.net/

    I'm sure that this should be frowned on for some reason, but all of my personal machines get this at the top of the .ssh/config:

    host *
    controlmaster auto
    controlpath ~/.ssh/sock/%r@%h:%p

    1. By Anonymous Coward (153.19.42.16) on

      > I'm sure that this should be frowned on for some reason, but all of my personal machines get this at the top of the .ssh/config:
      >
      > host *
      > controlmaster auto
      > controlpath ~/.ssh/sock/%r@%h:%p
      >

      with this you do something like this:

      host gateway_host
      DynamicForward 127.0.0.1:1080

      host internal_host
      HostName internal_host_ip
      ProxyCommand nc -4 -o -n -X 5 -x 127.0.0.1:1080 %h %p

      the controlmaster prevents your ssh from trying to bind with every connections to gateway_host again to port 1080.

  4. By Anonymous Coward (84.56.91.236) on

    I know that things like this can be accomplished easier with rsync in the meantime, but once in a while I still need this kind of construct:

    tar czf - thisdirectory/ | ssh mob@argh "cd wtf; tar xzf -"

    Transferring single directories is easy this way. Shovelling images over ssh is not much different. Target-partition should be a bit larger, of course. Mr. Calculator, disklabel and growfs are your friends. This is ok for cloning, otherwise way too tedious:

    dd if=/dev/sd0i bs=512 | ssh root@argh "dd of=/dev/sdb"

    Hubert Feyrer used something very similar with his "Ghost for UNIX" (G4U) cloning stuff. Dump/restore might be the better alternatives.

    To backup images only (backup the MBR too):

    dd if=/dev/sd0i | ssh root@argh "gzip -9 > backup-sd0i.dd.gz"


    1. By Anonymous Coward (2001:6f8:128e:3:2c0:9fff:fe1a:6a01) on

      > dd if=/dev/sd0i | ssh root@argh "gzip -9 > backup-sd0i.dd.gz"

      You might want to gzip the data before hitting ssh.

    2. By RC (71.116.240.29) on

      > tar czf - thisdirectory/ | ssh mob@argh "cd wtf; tar xzf -"

      What's wrong with scp?

      $ scp -C -r thisdirectory/ mob@argh:wtf/

      Much easier.

      Also, even if you are going to use tar, I'd make it uncompressed, and then use SSH with compression (-C), that way you compress the tar, as well as encryption packets and the rest of the SSH overhead, and without running gzip TWICE (ie. tar -z and ssh -C).


      Only issue I have with scp is that file/path patterns are evaluated on both the client, and the server, and scp/sshd does nothing to help you out... So, if any characters need to be escaped, you have to do it TWICE. eg

      $ scp -C -r "local file" user@host:"remote\ folder/"



      > dd if=/dev/sd0i | ssh root@argh "gzip -9 > backup-sd0i.dd.gz"

      And now you're sending lots of data uncompressed over the network, only to eventually compress it on the server... Do you have some sort of latent sociopathic hatred for your network? Are you trying to use the network traffic LEDs as your only source of light?

      Unless your local system is ridiculously slow, and your network ridiculously fast, I would do eg.:

      $ gzip -9c < /dev/sd0i | ssh root@argh "dd of=backup-sd0i.dd.gz"

  5. By Siju Oommen George (122.166.40.36) sgeorge.ml@gmail.com on

    Is there no way to stop this at the gateway? No counter trick?

    1. By Anonymous Coward (84.56.91.236) on

      > Is there no way to stop this at the gateway? No counter trick?

      Use a key and stop random flooding attacks with pf.conf

    2. By Mike Erdely (merdely) on http://erdelynet.com/

      > Is there no way to stop this at the gateway? No counter trick?

      These are authenticated connections at "the gateway". Don't give accounts to those you don't want to have access.

      1. By Anonymous Coward (69.70.68.38) on

        > > Is there no way to stop this at the gateway? No counter trick?
        >
        > These are authenticated connections at "the gateway". Don't give accounts to those you don't want to have access.

        If you have access internally via the gateway and it's authenticated, doesn't that defeat the whole purpose of this - in other words, you can just ssh from the gateway to the other ssh server?

        1. By Anonymous Coward (206.248.190.11) on

          > > > Is there no way to stop this at the gateway? No counter trick?
          > >
          > > These are authenticated connections at "the gateway". Don't give accounts to those you don't want to have access.
          >
          > If you have access internally via the gateway and it's authenticated, doesn't that defeat the whole purpose of this - in other words, you can just ssh from the gateway to the other ssh server?

          No, that is the purpose. Rather than having to ssh to gateway, then ssh to internal every time you want to access internal, you just "ssh internal" and have it automatically proxied through gateway for you. Its not about bypassing restrictions, its about convenience.

    3. By sthen (85.158.44.149) on

      > Is there no way to stop this at the gateway? No counter trick?

      Of course (-: PF can restrict local connections by userid.

  6. By niebie (141.5.20.93) on

    Very neat trick. But I noticed one problem in my setup: the nc processes on the gateway were not killed after the ssh connection was closed. After a while some resource limit kicked in and I couldn't connect anymore until I killed the nc processes manually on the gateway.

    The solution: give the nc in ProxyCommand the option -w so it times out after a while (10 seconds works fine for me).

    ProxyCommand ssh me@my.gateway.tld nc %h %p -w 10 2> /dev/null

    1. By vick (123.58.191.67) scutweiqiang.yang@gmail.com on vivisidea.info

      > Very neat trick. But I noticed one problem in my setup: the nc processes on the gateway were not killed after the ssh connection was closed. After a while some resource limit kicked in and I couldn't connect anymore until I killed the nc processes manually on the gateway.
      >
      > The solution: give the nc in ProxyCommand the option -w so it times out after a while (10 seconds works fine for me).
      >
      > ProxyCommand ssh me@my.gateway.tld nc %h %p -w 10 2 /dev/null
      >

      thanks for the ' -w 10 ' solution, it works

  7. By 89385318573! (80.249.194.29) on

    $ /usr/bin/calendar | grep OpenSSH
    Sep 26  OpenSSH born, Sunday 11:56 MST, 1999

  8. By Anonymous Coward (141.113.86.23) on

    or use chainssh for this.

    chainssh is a shell script to smplify the ssh login via multiple sshgateways/firewallgateaways.

    http://chainssh.sourceforge.net/

    1. By Mike Erdely (merdely) on http://erdelynet.com/

      > or use chainssh for this.
      >
      > chainssh is a shell script to smplify the ssh login via multiple
      > sshgateways/firewallgateaways.
      >
      > http://chainssh.sourceforge.net/

      I haven't looked at chainssh, but how/why is this better than using stock OpenSSH features?

  9. By RC (71.116.240.29) on

    TightVNC's -via option makes this kind of thing much simpler.

    ie. $ vncviewer -via merdely@gateway.hostname.tld internal

    No brain-power required. No need to come up with convoluted invocations of nc.

    Personally, in such situations, I'd rather just put a port-forwarding ssh script on the internal machine (ssh -R), tunneling through the firewall to my own remote system. No need to depend on that gateway host...

  10. By Achex (206.248.137.45) on

    you can use ssh -q option instead of 2>/dev/null ...
    (-q = quiet option)

    1. By jf (79.129.79.91) on https://www.echothrust.com

      > you can use ssh -q option instead of 2>/dev/null ...
      Also, ssh option -W %h:%p instead of the nc dependency, for a cleaner solution, e.g:
      host internal-host.example.com
              ProxyCommand ssh -q -W %h:%p proxy-host.example.com 
      

Credits

Copyright © - Daniel Hartmeier. All rights reserved. Articles and comments are copyright their respective authors, submission implies license to publish on this web site. Contents of the archive prior to as well as images and HTML templates were copied from the fabulous original deadly.org with Jose's and Jim's kind permission. This journal runs as CGI with httpd(8) on OpenBSD, the source code is BSD licensed. undeadly \Un*dead"ly\, a. Not subject to death; immortal. [Obs.]