Get network versatility with SSH tunneling and netcat

Vincent Danen explains how to use netcat with SSH tunneling when you need to create a secure connection to a server from a remote location.

SSH is a versatile protocol and OpenSSH, a versatile tool -- so much so, that it can be used for a lot of extremely cool things. Throw in netcat, another Swiss Army Knife networking tool that is even more all-purpose than SSH (in terms of networking capabilities), and you get the network versatility of netcat with the strong encryption and authentication of SSH.

One of the best uses for netcat and SSH is to create a transparent SSH tunnel through a secure bastion host. This essentially means that you connect to a secure host in order to reach another host, using the bastion host as a transparent middle-man. There are a number of reasons to require something like this. The most common, by far, is a locked-down SSH server that restricts access to all but a few known IPs, usually via tcp_wrapper rules or firewall rules.

For someone on the road that requires secure access to the server, this would be impossible as the IP they are currently using is untrusted and would be rejected by the server. With a bastion host, you can have an open SSH port (protected by a good firewall, SSH public keys and other hardening techniques to prevent abuse or compromise) that you can reach on the road, and have this bastion host set as a secure client to the server you are trying to reach.

To accomplish that, you need to use the bastion host as a proxy: you connect to the bastion, and it then creates a connection to the server. With netcat, we can do this transparently by running netcat on the bastion host to establish the connection to the target server.

To configure this, edit the ~/.ssh/config file and create a new entry:

    ProxyCommand ssh nc %h %p

This simple configuration tells OpenSSH to create a connection to (the end-target server) by using the ProxyCommand connection as a transport. The ProxyCommand tells the system to ssh to (the bastion host) and run nc %h %p on that host; the %h is replaced with the hostname supplied to ssh ( and %p is replaced by the port (22, by default).

If you use password authentication, you will be prompted for your password twice: once on the bastion and again on the server. If you use SSH public keys, you will not be asked for a password at all as the key will be forwarded over the connection (if you don't make use of something like keychain, you will have to supply the private key's passphrase).

This can be used to do more than just provide SSH logins. It can also be used to forward local ports to the remote host. For instance, if you wanted to connect to the MySQL server on port 3306 of, add the following line after the ProxyCommand line:

    LocalForward 33306 localhost:3306

This will forward all connections to port 33306 on the local client system to port 3306 on the remote host, via the proxy.

Get the PDF version of this tip.