SSH (Secure Shell) is a widely used network protocol to securely log onto remote systems. One of its features is /SSH Port Forwarding/ (or SSH tunneling). This functionality forwards encrypted connections between a local and a remote computer.
There are 3 types of port forwarding:
local port forwarding
Reverse port forwarding
dynamic port forwarding
Local Port Forwarding
Local port forwarding is created with -L parameter.
We can understand this command this way.
local-host:local-port -> jump-host:jump port ->remote-host:remote-port
If we need to run the following command to setup this SSH tunnel.
ssh -L local-port:remote-host:remote-port jump-host
This command connects to remote-host from the local host. jump host runs a SSH server. It then forwards all connection attempts to local-port on the local machine (a machine that initiated the ssh command) to destination_port port on the remote host. forward_to_host machine must be reachable from the via_host machine. Forwarding can be also done through Linux sockets.
Example of Local Port Forwarding
ssh -L 8080:howtouselinux.com:80 jumphost
In this example we connect with jumphost machine. We then forward any connection to port 8080 on the local machine to port 80 on howtouselinux.com.
As a result, opening localhost:8080 in the browser actually makes a request to a HTTP server (port 80) listening on howtouselinux.com.
ssh -L 4000:127.0.0.1:3306 jumphost
Remote host may also refer to the remote machine through which the ssh connection is made (i.e. jumphost). In that case we can just say 127.0.0.1 or localhost as it's local in the context of already established ssh connection with jumphost. In other words, 127.0.0.1 or localhost refers to jumphost machine.
SSH binds to port 4000 on the local machine. Any traffic that comes to this port is sent to the SSH server that listens on jumphost (remote machine). Once received by jumphost the traffic is then sent to port 3306 of 127.0.0.1, which is jumphost itself.
We can forward multiple ports in a single ssh command:
ssh -L 5544:127.0.0.1:4455 -L 3366:127.0.0.1:6633 Jumphost
Ports numbers less than 1024 or greater than 49151 are reserved for the system. Privileged ports (ports lower then 1024) can only be forwarded by root. If we are using local (or remote) port forwarding, we need to specify the destination server, i.e. jump host.
Port forwarding is enabled by default. If not, check AllowTcpForwarding in /etc/ssh/sshd_config.
Reverse Port Forwarding
Remote port forwarding is created with -R parameter.
We can understand this way.
local-host:local-port <- jump-host:jump port <-remote-host:remote-port
ssh -R remote-port:local-host:local_port remote-host
This command connects to remote-host. Remote host runs a SSH server. It then forwards all connection attempts to the remote port on the remote via_host machine to destination_port port on the local machine (a machine that initiated the ssh command) . Forwarding can be also done through Unix sockets.
Purpose of Reverse Port Forwarding
Let's consider a scenario. We have a Rails application running locally on our computer on port 3000. Our Internet provider don't assign public IPs. People from the external world (Internet) cannot access our home network. It's not possible to connect to our machine directly via the internet. We may, however, set up a remote port forwarding to allow this.
Example of Reverse Port Forwarding
ssh -R 10123:127.0.0.1:123 remote host
ssh connects to remote host. -R makes ssh listen on the port 10123 of remote host. Once there's a process on acme connecting to 10123, ssh server listening on the same remote machine will transfer that connection to the local machine (a machine that initiated the ssh command) and then it'll be forwarded to 127.0.0.1 on the port 123.
Contrary to local port forwarding, 127.0.0.1 refers to the local machine i.e. a machine that initiated the ssh connection.
In other words, remote port forwarding allows to map a port of the local machine onto the remote server via SSH.
ssh -R 7000:127.0.0.1:3000 via_host
People will be able to access your Rails application on port 3000 by pointing their browser to via_host IP address on the port 7000.
Dynamic Port Forwarding (SOCKS5)
Dynamic Port Forwarding allows a communication not on a single port, but across a range of ports. This port forwarding is created using -D parameter. This option will make SSH acts as a SOCKS proxy server.
SOCKS5 is an internet protocol which routes packets between a server and a client using a proxy server. SOCKS5 proxy servers use both TCP and UDP protocols (SOCKS4 only uses TCP).
Purpose of SSH Socks Proxy
A SOCKS proxy is simply a SSH tunnel in which specific applications forward their traffic down the tunnel to the remote server, and then on the server end, the proxy forwards the traffic out to the general Internet. Unlike a VPN, a SOCKS proxy has to be configured for each application separately on the client machine. There is, however, no need to install 3rd party applications to use it.
Proxies usually rewrite data packet headers. This may leads to decrease performance and mislabeling errors. SOCKS5 proxy servers do not rewrite data packet headers. They are more performant and less prone to data routing errors. Unlike HTTP proxies which can only interpret and work with webpages, SOCKS5 proxies can work with any kind of traffic. This is because SOCKS proxy servers are low-level proxies that can handle any program, protocol and any type of traffic.
Dynamic Port Forwarding can handle connections from multiple ports. It analyzes the traffic to determine the proper destination for the given connection. For example, a browser configured to use it as a SOCKS proxy can then access HTTP, HTTPS, FTP, etc. over the same connection. If we are using dynamic port forwarding, we need to configure programs to use a SOCKS proxy server.
Example of Dynamic Port Forwarding (SOCKS)
ssh -D 8123 -f -C -q -N via_host
-D tells SSH to create a SOCKS tunnel on the the port 8123.
-f forks the process to the background.
-C compresses the data before sending it.
-q enables quiet mode.
-N tells SSH that no command will be sent once the tunnel is up.