Using SSH ProxyCommand to Tunnel Connections
My systems are usually configured to allow ssh connections from a small set of trusted hosts or a bastion host. This is decent security practice but can be a pain when you want to scp a file or grab the stdout of a command from a host outside the trusted area. It also can be problematic if you have hosts on a private subnet and only one host (bastion host or jump box) to get in through. This method will enable transparent access to a host while behind the scenes tunneling through another host. No modification of the server is required. It just involves a few adjustments to the .ssh/config (ssh client config file) in your home directory.
Here’s how it works
A connection is established to the bastion host
+-------+ +--------------+ | you | ---ssh---> | bastion host | +-------+ +--------------+ |
Bastion host runs netcat to establish a connction to the target server
+--------------+ +--------+ | bastion host | ----netcat---> | server | +--------------+ +--------+ |
Your client then connects through the netcat tunnel and reaches the target server
+-----+ +--------------+ +--------+ | you | | bastion host | | server | | | ===ssh=over=netcat=tunnel======================> | | +-----+ +--------------+ +--------+ |
So there are 3 things we need to have happen behind the scenes:
1. Ssh to bastion host.
2. Run netcat command on bastion host.
3. Connect to netcat tunnel.
Here’s how to use the ssh proxycommand
#~/.ssh/config Host superchunk.example.org ProxyCommand ssh [email protected] nc %h %p |
In the above we are telling ssh that when it establishes a connection to superchunk.example.org to do so using the stdin/stdout of the ssh ProxyCommand as a transport. The ssh ProxyCommand then tells the system to first ssh to our bastion host and open a netcat connection to host %h (hostname supplied to ssh) on port %p (port supplied to ssh).
The result is a connection as if you were connecting from a trusted host:
$ ssh superchunk.example.org Password: [email protected]'s password: Last login: Wed Jun 25 12:05:47 2008 from 10.0.0.221 [[email protected] ~]$ |
Now you may be wondering why it prompted me for two passwords. This is because we are effectively sshing into two systems one right after the other. This can be resolved through the use of pre-shared ssh keys or with more advanced methods such as kerberos ticket forwarding.
More info about ssh proxycommand
For more detail you can read the full ssh_config man page here: http://www.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man5/ssh_config.5.
August 12th, 2010 at 5:29 pm
This is an elegant solution, thank you for it.
Do you happen to know if there are any SFTP GUI clients for Linux or Mac which support all of the necessary options in ~/.ssh/config? It appears CyberDuck supports a few options, but not the ProxyCommand option.
[Reply]
September 22nd, 2010 at 12:54 am
why do you need netcat at all? ssh -L should be sufficient or not?
[Reply]
July 29th, 2011 at 9:16 pm
[…] Creating a transparent SSH tunnel through a bastion host using the ProxyCommand configuration parame… – July 29th ( tags: ssh tunnel proxy proxycommand howto guide tutorial transparent ) […]
November 8th, 2011 at 12:51 pm
OpenSSH 5.4 and above have netcat built in.
Just do “ProxyCommand ssh -W %h:%p [email protected]” instead.
[Reply]
klaus thorn Reply:
August 25th, 2014 at 4:49 am
THANKS!
[Reply]
koodawg Reply:
August 25th, 2014 at 9:05 pm
Cool that works, except for 1 thing: When I do an scp over that proxycommand, the file is copied but I get a ‘Killed by signal 1’ afterward
$ scp x myProxyTest:
x 100% 423 0.4KB/s 00:00
Killed by signal 1.
$
Any idea why? Thx.
[Reply]
John Reply:
May 15th, 2015 at 11:51 pm
It’s normal, just redirect the stderr to not see it, ie:
ProxyCommand ssh -W %h:%p host.domain 2> /dev/null
[Reply]
Peter Reply:
October 5th, 2015 at 10:51 am
Never redirect stderr to /dev/null. Nowere. Never.
You will run into trouble and waste time on troubleshooting if you’re not seeing most obvious error messages.
As to the OPs question: Anything is better then ignoring stderr completely. If there is no other solution, try to live with it …
September 6th, 2013 at 10:52 am
[…] http://backdrift.org/transparent-proxy-with-ssh […]
April 23rd, 2017 at 8:35 am
Private note to author: It’s better if you ensure the date of your article is shown, because things can easily become outdated and confusing, such as when you say CyberDuck doesn’t support a particular option, … I can’t figure out if that is a recent observation or one that is 7+ years old and things may have changed.
[Reply]