Effective SSH Tunnels

Exposing services using persistent SSH tunnels and Autossh

In several years of using unix-like operating systems, I just recently needed to use an SSH tunnel for the first time. I’ve been working with a pfSense appliance in an environment where I couldn’t access the appliance from the outside due to it being on a local area network behind a NAT firewall. Because of the nature of the project, I’m only able to get physical access for a short time each day, which isn’t enough to get anything done. I needed to be able to manage the system from home.

After a quick search, I found the command needed to bypass a NAT firewall with an OpenSSH tunnel, given you have another system, a server for example, that has a public IP address. First, this must be allowed in the outside system’s sshd configuration.

Edit /etc/ssh/sshd_config

Uncomment or add the line GatewayPorts yes

Save the file and restart the OpenSSH daemon.

After this, you’re done configuring the host system. Next, you’ll open your ssh tunnel. In my case, I wanted to bind ports 7022 and 7081 on austin.0x.no to ports 22 and 443 (ssh and https) on my pfSense system. This is done like this:

ssh -f -R 7022:localhost:22 -R 7081:localhost:443 t_rex@austin.0x.no -N

The -f flag forks the session to the background. The -N flag means that no command will be executed upon connection. The -R enables a remote tunnel, and more than one can be used if forwarding more than one port, as done in the example.

The tunnel works as expected, making ports 22 and 443 of the pfSense appliance accessible from ports 7022 and 7081 of austin.0x.no. However, upon trying to access it later, I find that the tunnel no longer works. This is due to a lack of activity on the connection causing it to close. This brings us to autossh, a tool designed to automatically monitor and relaunch SSH sessions. No configuration of anything on the local system is really necessary.

Install autossh from source or from your operating system’s package manager. Using autossh, the command is as follows:

autossh -M 20000 -f -N t_rex@austin.0x.no -R 7022:localhost:22 -R 7081:localhost:443 -C

This command performs the same function, except that it monitors the SSH session (monitoring on port 20000, as specified by -M 20000) in order to restart it in the event of the connection being closed. The same syntax is used as far as the specification of the tunnels goes (-R remoteport:localhost:localport).

You’re now left with a persistent SSH tunnel running to bypass the NAT that the local system resides behind. Optionally, one can add the autossh command to be initiated at boot by the init system on the local system.