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
.
Reference link
- An Illustrated Guide to SSH Tunnels, Scott Wiersdorf