Secure Shell is an indispensable tool for anyone who needs to open a terminal session on a remote host. SSH does more than enable remote login sessions, however, especially for security professionals and network engineers. SSH can secure pipelines using public key cryptography to enable any kind of network traffic — but SSH is also an important cybersecurity tool, used both by security professionals and hackers.
SSH tunneling, also known as SSH port forwarding, is how SSH tunnels network traffic through application ports from the localhost — the computer physically present — to a remote system or vice versa. SSH port forwarding enables two communicating systems to exchange data securely across the internet and through firewalls.
If hackers gain access to a host running SSH on an organization’s internal network, they can use SSH on that host as a secure pipeline for exploiting private network services, so it is vital to understand how SSH access can be used for good — and for evil.
How does SSH work?
The simplest use case for SSH is to log in to a remote host for a terminal emulation session. In this case, a user has the SSH client software to securely connect to another host running an SSH server. SSH depends on the exchange of public keys between client and server to enable authentication of the user and encryption of the data being transmitted over the SSH connection.
SSH client software is almost always available on modern computers. OpenSSH is an open source command-line implementation of SSH that was originally developed for the OpenBSD OS but is now available on almost all Unix-based OSes, including Linux and macOS. OpenSSH was incorporated into Windows versions 10 and newer for use in the command line. PuTTY is an open source GUI version of SSH available for Windows.
Starting an SSH session requires the following:
- The domain name or IP address of the remote machine to access. This remote host must have an instance of the SSH server program, sshd, running.
- Access to an SSH client on the local machine. SSH is usually started by entering the ssh command. Although GUI versions of SSH like PuTTY for Windows can also be used, learning to use the command-line version is a skill that can be applied to almost any modern OS.
- Credentials for a user login with permission to access the remote server.
For example, a terminal session on a remote host called server.example.com with the user ID example-user is initiated with this SSH command:
ssh [email protected]
This command opens a terminal session on the remote server using port 22, the default port for SSH. SSH servers can respond to session requests on other ports as well — for example:
ssh -p 2222 [email protected]
The -p option flag is used to specify port number 2222 on the remote server, which causes SSH to send traffic to port 2222 instead of the default port 22. This only works if the remote server is configured to listen for requests on that port.
SSH can be used with either domain names or IP addresses, so if the host named server.example.com has the IP address 192.0.2.127, the following command has the same effect as the command above:
ssh -p 2222 [email protected]
When making an SSH connection, the server and client exchange public key information and negotiate a secure session key for encrypting SSH data exchanges. The first time an SSH connection is made to a remote host, the option to authenticate the remote host’s public key is available.
In this example, a typical use case for SSH, user example-user is logging into a terminal session with the host at server.example.com. In most cases for this type of use case, the port being used is the default SSH port 22.
SSH tunnels, on the other hand, provide the means to patch together streams of data between processes running on the localhost and the remote host.
SSH tunneling explained
SSH tunneling enables more interesting types of use cases. The three types of SSH tunnels are as follows:
- Local port forwarding enables connecting from your local host — running the SSH client — to a destination server via the SSH server. This approach is used when the destination server is not accessible to the local host — for example, due to firewall filtering — but it is accessible to the SSH server. Local port forwarding is one method of bypassing a firewall from inside a private network to access a particular server that would otherwise be blocked by the firewall.
- Remote port forwarding, or reverse SSH tunneling, is a method for connecting to a destination server from an SSH server, via the SSH client. Less commonly used, remote port forwarding is one method to access an internal server from an outside private network that is otherwise inaccessible from the public internet. This method is used by hackers to exploit systems on private networks.
- Dynamic port forwarding causes all inbound and outbound networking traffic to be routed through SSH on a specified port. This enables SSH connections between any two hosts, with all connections forwarded by the SSH client via an SSH server. It is also the mechanism for setting up a SOCKS proxy server, which passes networking traffic to be encapsulated in an SSH tunnel when the local client software is configured to pass all traffic to the specified port. Dynamic port forwarding can also be used to entirely circumvent the network firewall and gain access to any destination server from inside a private network.
By itself, SSH is an important tool for securing data flows, especially when used to connect servers or clients from outside the firewall. Before experimenting with SSH tunneling, however, be sure to clear the activity with the organization’s IT, networking and security teams.
Example of local port forwarding tunnel
Local port forwarding uses the -L option in the SSH command to flag that a local port will be forwarded through the SSH server to another server or host. In other words, the local host connects to another host running the SSH server and then patches any network data bound for the forwarded port through the SSH server to the desired destination server or host.
For example, if you are using a computer on a private network and you want to access a web server that is blocked by your organization’s firewall, you could redirect the local port 8080 to the desired web server with this command:
ssh -L 8080:social.example.org:80 ssh-server.example.com
In this example, the -L option indicates that the SSH server at ssh-server.example.com should forward port 8080 on the localhost to port 80 on the desired — but restricted — server, social.example.org.
In this example, running the SSH command with the specified ports means you should be able to access the restricted server using a URL in your web browser — http://localhost:8080/ — that points to the specified port on the local host running SSH. SSH forwards the HTTP request through the SSH tunnel to access the desired web server.
Example of remote port forwarding tunnel
Remote port forwarding, or reverse tunneling, is commonly used by hackers of all types, including ethical hackers, penetration testers and malicious hackers. If attackers can exploit just one host inside a private network, they can use that access to potentially exploit any system within the protected network.
To start a reverse tunnel, run the ssh command with the -R option on the host inside the private network you want to use to forward outside network requests to an otherwise restricted host on the private network. Consider the following command, run on a host located inside the firewall perimeter:
ssh -R 5900:localhost:5900 somehost.example.net
In this command, localhost is the host located inside the private network. The port being forwarded — 5900 — is the default port for virtual network computing (VNC), which is a system for remotely controlling a desktop. The system being forwarded to is somehost.example.net, a host accessible to localhost but also located on the protected network. Ordinarily, this host should not be accessible by anyone outside the firewall perimeter, but in this case, localhost has been made accessible to the public internet. This type of forwarding can also be used to exploit privileged access on a host outside the private network that has been given privileges to access restricted services.
In this example, VNC client software can be configured to connect to the domain name for, or public IP address of, localhost on port 5900 to gain control over the desktop for the system somehost.example.net.
In practice, opening a reverse tunnel in this way can be more complicated. Many organizations are aware of this type of exploit — which enables attackers to run remote commands on a protected system — and they usually deploy protections against it. In any case, it is advisable to check with network and IT staff to avoid triggering alerts with a reverse tunnel.
Example of dynamic port forwarding tunnel
Dynamic port forwarding with SSH is often used to set up a SOCKS proxy server. In this example, the SSH client is configured to listen to a specific port on the local host. When it receives traffic on that port, the SSH server encapsulates, or tunnels, the application layer messages into a secure tunnel connecting to the receiving host.
When SOCKS proxies are in use, client software must be configured with the port number on which SSH is accepting traffic to be tunneled. The default port for SOCKS proxies is 1080, so the SSH command to start a SOCKS proxy — aka enabling dynamic port forwarding — is the following:
ssh -D 1080 bastion.example.org
The -D option is used to enable dynamic port forwarding on the local host, so all messages received on port 1080 are forwarded to the host named bastion.example.org. Bastion is a type of host usually positioned outside the firewall perimeter — or inside the network DMZ — and is used to mediate access to external hosts through SSH tunnels.
Learn more about how to permit, restrict and otherwise manage remote system access by configuring SSH tunneling through your firewall.