A short guide to SSH port forwarding

SSH port forwarding, or TCP/IP connection tunneling, is a process whereby a TCP/IP connection that would otherwise be insecure is tunneled through a secure SSH link, thus protecting the tunneled connection from network attacks. Port forwarding can be used to establish a form of a virtual private network (VPN).

To illustrate how port forwarding works, let us use an example. Suppose you are the network administrator in a company that has two buildings. In Building #1, there are numerous workstations residing in the subnet 10.1.1.*. In Building #2, there are multiple servers residing in the subnet 10.2.2.*. The two buildings are separated by a busy street with parking spaces on each side, and the subnets in the two buildings are linked wirelessly through an antenna on the roof of each building. The workstations in Building #1 are running a legacy client application that uses an unencrypted TCP/IP session to communicate sensitive data with the servers in Building #2.

One day, someone in your company notices that an unmarked black van has remained parked on the street between the two buildings for several days. As your CEO realizes that sensitive data is being transmitted unencrypted between the two buildings, he becomes worried that the van parked outside might be collecting the company's confidential information. He orders you to solve the problem ASAP.

What you do is this:

On each of the client workstations in Building #1 (in the above example, workstation 10.1.1.7 is shown), you install an SSH client. On the machine in Building #2 that runs the server for your legacy application, you install an SSH server. You configure the SSH client with the following client-to-server port forwarding rule: for each connection that comes on interface 127.0.0.1 and port 999, forward that connection to the SSH server, and request the SSH server to forward that connection to host 127.0.0.1 (relative to the server), port 123.

Now, your application client doesn't connect to the server directly anymore. Rather, it connects to the SSH client, which encrypts all data before transmission. The SSH client forwards the encrypted data to the SSH server, which decrypts it and forwards it to your application server. Data sent by the server application is similarly encrypted by the SSH server and forwarded back to the client.

Previously, the data that was being radioed between the two buildings was sent in plaintext and could be captured by anyone parking on the street below. Now, the data is encrypted using the SSH protocol, and is virtually impossible to decipher. The next day after installing SSH, you observe that the black unmarked van is gone.

Now, let us comment on the above example. It corresponds with the following C2S (client-to-server) port forwarding rule in the SSH client:

  • Listen interface: 127.0.0.1 (this ensures that only connections from the local client machine, or loopback connections, are accepted for forwarding)
  • Listen port: 999
  • Destination host: 127.0.0.1 (important: the target address is relative to the server, not the client, so 127.0.0.1 will work fine if the target application server is listening on all interfaces - 0.0.0.0)
  • Destination port: 123

Note that the listening interface configured on the SSH client is 127.0.0.1. By configuring the listening interface, you tell the SSH client what kinds of connections it will accept. If you configure the listening interface to 127.0.0.1, the SSH client will only accept connections originating on the same machine. If you configure the listening interface to equal the IP address of one of the network cards on the machine, the SSH client will accept only those connections that arrive through that network card. If you configure the listening address to 0.0.0.0, the SSH client will accept connections regardless of their origin.

Next, you will note that the listening port has been set to 999. The listening port could be set to any figure between 1 and 65535 that is not already occupied by another application listening for connections on the same machine. In this case, the SSH client listening port has been set to 999, but it could just as well have been set to 123, the same port at which the application server is listening.

Now comes the most confusing part: the address of the destination host. It is important to understand that, in a client-to-server port forwarding rule, the target host address is relative to the SSH server, not the client. This is the address that the SSH server will connect to when a connection needs to be forwarded. In this case, the target host address is set to 127.0.0.1 to have the SSH server connect to the application server which is running on the same machine.

Finally, the destination port specifies the port on which the target TCP/IP server is listening - in this case, 123.

The port forwarding configuration shown in the above example is strict: it minimizes the exposure of unencrypted data by constraining the SSH client to reside on the same machine as the application client, and the SSH server to reside on the same machine as the application server.

On the other hand, if you are only concerned about eavesdropping between the SSH client and the server, and do not mind unencrypted data in the local subnets, you might configure your SSH port forwarding rules like this:

This corresponds with the following C2S (client-to-server) port forwarding rule in the SSH client:

  • Listen interface: 0.0.0.0 (this opens up the SSH client's forwarding socket to connections from other machines)
  • Listen port: 123
  • Destination host: 10.2.2.9 (the target application server is not on the same machine as the SSH server, so we need to enter its address as visible from the SSH server)
  • Destination port: 123

With this setup, you only need one SSH client to forward the connections of multiple application clients; since the SSH client's listening address is configured to 0.0.0.0, the application clients do not need to reside on the same machine. With appropriately configured port forwarding rules, you can use the same SSH session to forward connections to multiple application servers, which can reside on machines different from the SSH server.

Even though our examples above only discuss client-to-server port forwarding rules, the concept of server-to-client port forwarding is entirely symmetric. Only the roles are reversed: with S2C forwarding, the listening address is relative to the SSH server, and the destination host address is relative to the SSH client.

It is a common mistake to define both a C2S as well as an S2C rule for the same forwarded connection. This is not necessary and will not work. S2C rules are required only if you are forwarding other connections which are established in the direction from the server to the client. Such connections are normally independent from, and unrelated to, those established from client to server. Only one type of rule is necessary for each connection.