SSH tunneling is the practice of using shell account on various computers and servers to acquire and redirect networking between multiple machines. Becoming more adept at SSH tunneling will make your digital world more portable, and enable you to access targetted machines or content, regardless of what network you or the target are on.
SSH Tunneling is great because it allows fully encrypted communication between two servers, even when the services at either endpoint may not use encryption.
Common Use Cases for SSH Tunneling
- Access services only listening on localhost
- Access router configuration remotely
- Proxy into protected networks
Basic SSH Tunneling Concepts
The first and most important concept to understand around SSH tunneling is that in every communication there is a client and a server. Understanding which machine is which is necessary to understand any of the information below. In general terms the client is the machine that will be initiating the connection. The client machine will not require any incoming permissions. A server in a single ssh connection is the machine running sshd and must be accessible via SSH.
Local forwarding is the act of taking a remote port and mapping it to a local port on the client machine. This is the most common type of connection and enables proxy-like functionality. Local Forwarding is accomplished using the parameter -L (Hyphen, then Capital L). Every local forwarding command is going to be of the format -Lclientport:destination:destinationport. In the formatting of the command, client port is the port on the machine that will begin listening on localhost. Destination and destinationport are the IP/hostname and Port from the perspective of the server. After successfully opening an SSH connection with local forwarding, any attempt to open clientport on localhost will result in the remote server opening a connection to destionation:destinationport.
Note: It is important to note that if you wish to open a lower port number (for example 80, 631, 25, etc) on the client, you must have root permissions. Typically this is not a problem, because there is no real need to have the client open on a lower port number.
Note: It is also important to note that this connection will be listening on localhost:clientport. This means that you will not be able to access the SSH forwarding from a second degree client, without additional SSH tunneling. An example of this would be where I have 3 machines. Machines A1 and A2 are on network A, and machine B1 is on network B. In this example, if I use local forwarding to connect from A2 to B1, A1 will not be able to access any tunneling performed by A2.
Remote forwarding is the more difficult to understand, as it opening a port on the server, and forwarding those requests to the local machine. This is generally less useful, but can still accomplish some interesting things. The format for remote forwarding is as follows -Rserverport:localdestination:localdestinationport. In this case, you must have permissions to open serverport on the server, or tunneling will not succeed. Any requests made to localhost on the serverport in the server environment will be forwarded to localdestination:localdestinationport from the perspective of the client.
There are relatively few real world applications of this, but one that I have run into more than once is attempting to run an SSH server on a machine that has no incoming traffic privileges. In this case I use the protected machine as an SSH client to connect to some less secure machine. In the SSH connection, I forward a remote port (2200 is easy to remember) to the local SSH server (localhost:22) with the following command: -R2200:localhost:22. In this confusing example, it swaps the client server roles allows you to SSH into a protected machine, by establishing an initial connection having the protected machine as a SSH client.
SSH Tunneling Examples
For these examples, assume that there are two private networks (A:192.168.0.* and B:10.0.0.*), and one internet site (C:188.8.131.52). Also assume that there is only one publicly accessible IP from each private network (192.168.0.10 and 10.0.0.10). Finally, both of the private networks have a router/modem configured at *.*.0.1.
Access private network A's router
ssh 192.168.0.10 -L8080:192.168.0.1 Once this connection is established, you can pull up the browser and visit http://localhost:8080 and you will be redirected to the private network's modem configuration. This is a great way to remotely manage port forwarding and NAT without opening your router to the internet.
Access CUPS on a computer not yet configured for sharing
ssh 192.168.0.2 -L6310:localhost:631 - Part of the default CUPS printer configuration is that it only listens on localhost, and is not accessible from other machines. This SSH connection will enable you to open your browser to http://localhost:6310/ and access the private CUPS configuration.
Forwarding X sessions
ssh -XYC 192.168.0.10 - Although not technically using tunnelling, the XYC parameters will establish the $DISPLAY variable on the server, and allow you to run X applications on the server. These X applications will then be shown on the client environment. This typically runs very slowly, but uses the server's CPU and Memory and Disk and Network, rather than the client's. I often use this for remotely running partition management, such as gparted.