SSH port forwarding

Introduction

In addition to logging in to the server, SSH also has a major purpose, which is to act as an intermediary for encrypted communication, acting as an encryption springboard for communication between two servers, turning the originally unencrypted communication into encrypted communication. This function is called port forwarding, or SSH tunnel.

Port forwarding has two main functions:

(1) The unencrypted data is transmitted in the SSH secure connection, which increases the security of the originally insecure network services. For example, when accessing plaintext services such as Telnet and FTP through port forwarding, the data transmission will be encrypted.

(2) As an encryption springboard for data communication, bypassing network firewalls.

There are three ways to use port forwarding: dynamic forwarding, local forwarding, and remote forwarding. Introduce one by one below.

Dynamic forwarding

Dynamic forwarding means that an encrypted connection is created between the machine and the SSH server, and then the internal communication of the machine for a certain port is forwarded through this encrypted connection. One of its usage scenarios is that all external websites are forwarded through SSH.

Dynamic forwarding requires binding the local port to the SSH server. As for which website the SSH server is going to visit, it is completely dynamic and depends on the original communication, so it is called dynamic forwarding.

$ ssh -D local-port tunnel-host -N

In the above command, -D means dynamic forwarding, local-port is the local port, tunnel-host is the SSH server, and -N means that this SSH connection only performs port forwarding, and cannot be executed without logging in to the remote shell. The remote command can only act as a tunnel.

For example, if the local port is 2121, then the command for dynamic forwarding is as follows.

$ ssh -D 2121 tunnel-host -N

Note that this forwarding uses the SOCKS5 protocol. When accessing an external website, the HTTP request needs to be converted to the SOCKS5 protocol to forward the request on the local port.

The following is an example of use after the SSH tunnel is established.

$ curl -x socks5://localhost:2121 http://www.example.com

In the above command, the -x parameter of curl specifies the proxy server, that is, access to http://www.example.com through the local 2121 port of the SOCKS5 protocol.

If you use dynamic forwarding frequently, you can write the settings into the user's personal configuration file (~/.ssh/config) of the SSH client.

DynamicForward tunnel-host:local-port

Local forwarding

Local forwarding refers to that the SSH server acts as an intermediary springboard to establish an encrypted connection between the local computer and a specific target website. Local forwarding is a forwarding rule established on the SSH client of the local computer.

It will specify a local port (local-port), and all requests sent to that port will be forwarded to the SSH tunnel-host, and then the SSH tunnel-host will act as an intermediary to send the received requests to the target server (target -host) target port (target-port).

$ ssh -L local-port:target-host:target-port tunnel-host

In the above command, the -L parameter means local forwarding, local-port is the local port, target-host is the target server you want to access, target-port is the port of the target server, tunnel- host is a springboard for SSH.

For example, there is an SSH springboard machine tunnel-host. We want to use this machine to establish an SSH tunnel between the local 2121 port and the target website www.example.com port 80. It can be written as follows.

$ ssh -L 2121:www.example.com:80 tunnel-host -N

Then, to access the port 2121 of this machine is to access port 80 of www.example.com.

$ curl http://localhost:2121

Note that the local port forwarding adopts the HTTP protocol and does not need to be converted to the SOCKS5 protocol.

Another example is POP3, an encrypted access mail acquisition protocol.

$ ssh -L 1100:mail.example.com:110 mail.example.com

The above command binds the local port 1100 to port 110 of the mail server mail.example.com (the default port of the POP3 protocol). After the port forwarding is established, the POP3 mail client only needs to access port 1100 of the machine, and the request will be automatically forwarded to port 110 of mail.example.com through the SSH jumper (here is mail.example.com) .

There is a prerequisite for the above situation, that is, mail.example.com must run an SSH server. Otherwise, you must go through another SSH server intermediary, and the executed command must be changed to the following.

$ ssh -L 1100:mail.example.com:110 other.example.com

In the above command, port 1100 of the local machine is still bound to port 110 of mail.example.com, but since mail.example.com does not run an SSH server, it must go through the intermediary of other.example.com. The local POP3 request is sent to port 22 of other.example.com (default port of sshd) through port 1100, and then forwarded to mail.example.com from the latter, and then return the same way after the data is obtained.

Note that using the above intermediary method, only the section from the machine to other.example.com is encrypted, and the section from other.example.com to mail.example.com is not encrypted.

It is best to add the -N parameter to this command, which means that the remote command will not be executed from the SSH springboard, so that SSH will only act as a tunnel. There is also a -f parameter which means that the SSH connection is running in the background.

If you often use local forwarding, you can write the settings into the user's personal configuration file (~/.ssh/config) of the SSH client.

Host test.example.com
LocalForward client-IP:client-port server-IP:server-port

Remote forwarding

Remote forwarding refers to the forwarding rules established on the remote SSH server.

It is the reverse of local forwarding. After establishing an SSH tunnel from a local computer to a remote computer, local forwarding is to access the remote computer through the local computer, and remote forwarding is to access the local computer through the remote computer. Its command format is as follows.

$ ssh -R remote-port:target-host:target-port -N remotehost

In the above command, the -R parameter indicates remote port forwarding, remote-port is the port of the remote computer, target-host and target-port are the target server and its port, and remotehost is the remote computer.

The remote forwarding is mainly aimed at the situation of the internal network. Here are two examples.

The first example is that a server on the internal network localhost opens a service on port 80. This port 80 can be mapped to port 8080 of the my.public.server server with a public IP address through remote forwarding. By accessing the address of my.public.server:8080, you can access port 80 of that intranet server.

$ ssh -R 8080:localhost:80 -N my.public.server

The above command is executed on the intranet localhost server to establish an SSH tunnel from localhost to my.public.server. After running, if the user accesses my.public.server:8080, it will be automatically mapped to localhost:80.

The second example is that the local computer local is on the external network, the SSH springboard and the target server my.private.server are both on the internal network, and the SSH springboard must be used to access the target server. However, the local computer local cannot access the SSH springboard in the intranet, and the SSH springboard can access the local computer.

Since the machine cannot access the internal network SSH jumper, it cannot initiate an SSH tunnel from the external network to establish port forwarding. It must be reversed to initiate a tunnel from the SSH jumper to establish port forwarding. At this time, remote port forwarding is formed. The springboard machine executes the following command to bind the port 2121 of the local computer local to access my.private.server:80.

$ ssh -R 2121:my.private.server:80 -N local

The above command is executed on the SSH springboard to establish a tunnel from the springboard to local, and the exit of this tunnel is mapped to my.private.server:80.

Obviously, remote forwarding requires that the local computer local also has an SSH server installed, so that it can accept remote logins from the SSH springboard.

After executing the above command, the tunnel from the springboard to local has been established. Then, you can access the target server from the local computer, that is, execute the following command on the local computer.

$ curl http://localhost:2121

After the machine executes the above command, it will output the content returned by the port 80 of the server my.private.server.

If you frequently perform remote port forwarding, you can write the settings into the user's personal configuration file (~/.ssh/config) of the SSH client.

Host remote-forward
  HostName test.example.com
  RemoteForward remote-port target-host:target-port

After completing the above settings, execute the following command to establish remote forwarding.

$ ssh -N remote-forward

# Equivalent to
$ ssh -R remote-port:target-host:target-port -N test.example.com

Examples

Let's look at two examples of port forwarding.

Easy VPN

VPN is used to establish an encrypted tunnel between the external network and the internal network. The server on the internal network cannot be accessed directly from the external network. It must pass through a jumper. If the local machine can access the jumper, you can use SSH to forward locally, which is a simple implementation of a VPN.

$ ssh -L 2080:corp-server:80 -L 2443:corp-server:443 tunnel-host -N

The above command binds the port 2080 of the local machine to the port 80 of the intranet server through the SSH springboard machine, and binds the port 2443 of the machine to the port 443 of the intranet server.

Two-level springboard

Port forwarding can have multiple levels. For example, two SSH tunnels are created, and the first tunnel is forwarded to the second tunnel, and the second tunnel can access the target server.

First, create a first-level tunnel on this machine.

$ ssh -L 7999:localhost:2999 tunnel1-host

The above command establishes a tunnel between the local 7999 port and tunnel1-host. The exit of the tunnel is localhost:2999 of tunnel1-host, that is, after tunnel1-host receives the request from this machine , Forwarded to its own 2999 port.

Then, execute the following command on the first springboard machine (tunnel1-host) to create a second level tunnel.

$ ssh -L 2999:target-host:7999 tunnel2-host -N

The above command connects the port 2999 of the first springboard machine tunnel1-host to the port 7999 of the target server target-host through the second springboard machine tunnel2-host.

The final effect is that if you access the 7999 port of the local machine, it will be forwarded to the 7999 port of the target-host.