Hack 45. Forward Ports over SSH
Keep network traffic to arbitrary ports secure with SSH port forwarding.
In addition to providing remote shell access and command execution, OpenSSH can also forward arbitrary TCP ports to the other end of your connection. This can be extremely handy for protecting email, web, or any other traffic that you need to keep private (at least, all the way to the other end of the SSH tunnel).
SSH accomplishes local forwarding by binding to a local port, performing encryption, sending the encrypted data to the remote end of the SSH connection, then decrypting it and sending it to the remote host and port you specify. Here, we will start an SSH tunnel with the -L switch (short for local) and use it to tunnel POP traffic on port 110:
# ssh -f -N -L110:mailhost:110 -l user mailhost
Naturally, substitute user with your username and mailhost with your mail server's name or IP address. Note that you will have to be root on your machine for this example, since you'll be binding to a privileged port (110, the POP port). You should also disable any locally running POP daemon (look in /etc/inetd.conf) or it will get in the way.
Now, to encrypt all of your POP traffic, configure your mail client to connect to localhost port 110. It will happily talk to mailhost as if it were connected directly, except that the entire conversation will be encrypted.
The -f flag forks SSH into the background, and -N tells it not to actually run a command on the remote end, but just do the forwarding. If your SSH server supports it, try the -C switch to turn on compression. This can significantly improve the time it takes to download your email.
You can specify as many -L lines as you like when establishing the connection. To also forward outbound email traffic, try this:
# ssh -f -N -L110:mailhost:110 -L25:mailhost:25 -l user mailhost
Set your outbound email host to localhost, and your email traffic will be encrypted as far as mailhost. This generally is useful only if the email is bound for an internal host, or if you can't trust your local network connection (as is the case with most wireless networks). Obviously, once your email leaves mailhost, it will be transmitted in the clear, unless you've encrypted the message with a tool such as PGP or GPG.
If you're already logged into a remote host with SSH and need to forward a port quickly, try this:
- Press Enter.
- Type ~C.
- You should be at an ssh> prompt. Enter the -L line as you would from the command line:
rob@catlin:~$ ~C (it doesn't echo ) ssh> -L8080:localhost:80 Forwarding port.
Your current shell then forwards local port 8080 to catlin's port 80.
You can also allow other (remote) clients to connect to your forwarded port with the -g switch. If you're logged into a remote gateway that serves as a NAT for a private network, enter a command like this:
$ ssh -f -g -N -L8000:localhost:80 10.42.4.6
This command forwards all connections from the gateway's port 8000 to internal host 10.42.4.6's port 80. If the gateway has a live Internet address, anyone from the Net is allowed to connect to the web server on 10.42.4.6 as if it were running on port 8000 of the gateway.
Although SSH also has functionality for acting as a SOCKS 4 proxy with the -D switch [Hack #46], it just isn't well suited for routing all network traffic to the other end of a tunnel. You can use a real encapsulating tunnel such as vtun [Hack #47] in conjunction with SSH to forward everything.
3.7.1. See Also
- man ssh
- SSH, The Secure Shell: The Definitive Guide (http://www.oreilly.com/catalog/sshtdg/) by Daniel J. Barrett and Richard Silverman (O'Reilly)