TranslateProject/sources/tech/20170714 Creating TCP IP port forwarding tunnels with SSH The 8 possible scenarios using OpenSSH.md
2017-10-04 10:26:36 +08:00

17 KiB
Raw Blame History

Creating TCP / IP (port forwarding) tunnels with SSH: The 8 possible scenarios using OpenSSH

The typical function of the Secure Shell (SSH) network protocol is to access a remote system in terminal mode and execute commands there safely, because the data is encrypted. In addition, through this secure data connection, it is possible to create tunnels (  port forwarding  ) between the connected ends so that the TCP / IP connections are channeled through the SSH connection so that we can get away with any Firewall or port blocking whenever we have the possibility to connect with SSH.

As this topic is very much addressed by the entire network:

In this entry we will not go into the details of port forwarding, but pretend to be a  cheat sheet , a quick reference (  cheat sheet  ) on how to forward TCP ports with OpenSSH in the 8 different scenarios that can be given. Other SSH clients such as PuTTY also allow port forwarding, but the configuration will be done with a graphical interface. We will focus on OpenSSH.

In the following examples and situations we will assume that we have an external network and an internal network and between both networks, the only possible connection is an SSH connection between the node of the external external  network1  and the node of the internal internal  network1  . The  external node2  is on the external network and has full connectivity with  external1 . The node  interno2  is on the internal network and has full connectivity with  interno1 .

SSH tunnels: no tunnel

Table of Contents [hide]

Scenario 1: Use on  external1  a TCP service offered by  internal1  (Local port forwarding / bind_address = localhost / host = localhost)

The system  externo1  can be connected to the system  _interno1 _ through OpenSSH and also wants to connect to the system server VNC (port 5900)  interno1 :

SSH Tunnels: Scenario 1

We will achieve this with this command:

External1  $  ssh  -L  7900:  localhost:  5900  user  @  internal1 

Now in the  external system1  we can verify that port 7900 is waiting for connections:

External1  $  netstat  -ltn
Active Internet connections  (only servers)
Proto Recv-Q  Send-Q  Local Address Foreign Address State      
...
Tcp  0  0  127.0.0.1:7900  0.0.0.0:*  LISTEN  
...

We only need to execute now on  external1  :

External1  $  vncviewer localhost  ::  7900 

To connect to the  internal  VNC  server1 .

Note: This way to change the port is not documented in the 

<a  href="http://www.realvnc.com/products/free/4.1/man/vncviewer.html">man vncviewer</a>

. Appears in: About VNCViewer configuration of the output TCP port. This is also how the TightVNC vncviewer does.

Scenario 2: Use on  external2  a TCP service offered by  internal1  (Local port forwarding / bind_address = 0.0.0.0 / host = localhost)

This time we start from a situation similar to the previous one but now we want it to be  external2  who connects to the  internal  VNC  server1 :

SSH Tunnels: Scenario 2

The appropriate command would be this:

External1  $  ssh  -L  0.0.0.0:7900:localhost:5900  user  @  internal1 

It is similar to the first scenario; But in that, if we look at the output of 

netstat

the port, 7900 had been associated with the address of localhost, at 127.0.0.1, so only local processes could connect to it. This time we specify that the port is associated with 0.0.0.0, so that the system accepts connections to any local IP of the machine:

External1  $  netstat  -ltn
Active Internet connections  (only servers)
Proto Recv-Q  Send-Q  Local Address Foreign Address State      
...
Tcp  0  0  0.0.0.0:7900  0.0.0.0:*  LISTEN
... 

So now, from  external2  , we can execute:

External2  $  vncviewer external1  ::  7900 

To connect to the  internal  VNC  server1 .

Instead of specifying the IP 

0.0.0.0 

, we could also use the option 

-g

Allows remote hosts to connect to local forwarded ports  ) like this:

External1  $  ssh  -g  -L  7900:  localhost:  5900  user  @  internal1 

With exactly the same result as the previous command:

External1  $  ssh  -L  0.0.0.0:7900:localhost:5900  user  @  internal1 

On the other hand, if we had wanted to restrict the connection to only one of the local IPs of the system, we could have been more specific:

External1 $ ssh -L 192.168.24.80:7900:localhost:5900 user @ internal1

External1 $ netstat -ltn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State      
...  
Tcp 0 0 192.168.24.80:7900 0.0.0.0:* LISTEN
...

Scenario 3: Use in  internal1  a TCP service offered by  external1  (Remote port forwarding / bind_address = localhost / host = localhost)

In the first scenario, it was the system itself with the SSH server that offered another service. Now the system with the SSH client is the one that offers the service that the system with the SSH server wants to use:

SSH Tunnels: Scenario 3

The command we will use is the same as in the first scenario by changing the parameter 

-L 

to 

-R 

:

External1  $  ssh  -R  7900:  localhost:  5900  user  @  internal1 

And now where we will see that we have port 7900 listening is in  interno1 :

Internal1 $ netstat -lnt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State      
...  
Tcp 0 0 127.0.0.1:7900 0.0.0.0:* LISTEN
...

So now from  internal1  we can use the VNC server from  external1  like this:

Internal1  $  vncviewer localhost  ::  7900 

Scenario 4: Use in  internal2  a TCP service offered by  external1  (Remote port forwarding / bind_address = 0.0.0.0 / host = localhost)

Similar to the third scenario but now, as we did in the second scenario, we will associate the forwarded port with the IP 

0.0.0.0 

so that other nodes can use the service:

SSH Tunnels: Scenario 4

The appropriate command is:

External1  $  ssh  -R  0.0.0.0:7900:localhost:5900  user  @  internal1 

However, it is important to understand that, for security reasons, this will not work if in the configuration of the SSH server we do not modify the value of the parameter 

GatewayPorts 

that by default is 

no 

:

GatewayPorts 

Specifies whether remote hosts are allowed to connect to ports forwarded for the client. By default, sshd(8) binds remote port forwardings to the loopback address. This prevents other remote hosts from connecting to forwarded ports. GatewayPorts can be used to specify that sshd should allow remote port forwardings to bind to non-loopback addresses, thus allowing other hosts to connect. The argument may be “no” to force remote port forwardings to be available to the local host only, “yes” to force remote port forwardings to bind to the wildcard address, or “clientspecified” to allow the client to select the address to which the forwarding is bound. The default is “no”.

If we do not have the possibility to modify the configuration of the server, we will not be able to use this type of port forwarding. At least not simply because, if there are no other impediments, a user can open a port (> 1024) to listen to external connections and forward that request to 

localhost:7900 

. This could be done, for example, with netcat ( Debian # 310431: sshd_config should warn about the GatewayPorts workaround. )

So we 

/etc/ssh/sshd_config 

will add:

GatewayPorts clientspecified 

After which we will have to reread the configuration with ” 

sudo  /etc/init.d/ssh reload 

” (Debian and Ubuntu).

We verify that  internal1  is listening for requests from all IPs:

Internal1 $ netstat -ltn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State      
...    
Tcp 0 0 0.0.0.0:7900 0.0.0.0:* LISTEN
...

And we can already use the VNC service from  internal2  :

Internal2 $ internal vncviewer1 :: 7900

Scenario 5: Use in  external1  a TCP service offered by  internal2  (Local port forwarding / bind_address = localhost / host = internal2)

SSH Tunnels: Scenario 5

In this scenario we will use the following command:

External1 $ ssh -L 7900: internal2: 5900 user @ internal1

And we will access the service by running the command in  external1 :

External1 $ vncviewer localhost :: 7900

Scenario 6: Use in  internal1  a TCP service offered by  external2  (Remote port forwarding / bind_address = localhost / host = external2)

SSH Tunnels: Scenario 6

In this scenario we will use the following command:

External1  $  ssh  -R  7900:  external2:  5900  user  @  internal1 

And we will access the service by running the command in  internal1 :

Internal1  $  vncviewer localhost  ::  7900 

Scenario 7: Use in  external2  a TCP service offered by  internal2  (Local port forwarding / bind_address = 0.0.0.0 / host = internal2)

SSH Tunnels: Scenario 7

In this scenario we will use the following command:

External1  $  ssh  -L  0.0.0.0:7900:internal2:5900  user  @  internal1 

Or alternatively:

External1  $  ssh  -g  -L  7900:  internal2:  5900  user  @  internal1 

And we will access the service by running the command in  external2  :

External2  $  vncviewer external1  ::  7900 

Scenario 8: Use in  internal2  a TCP service offered by  external2  (Remote port forwarding / bind_address = 0.0.0.0 / host = external2)

SSH Tunnels: Scenario 8

In this scenario we will use the following command:

External1  $  ssh  -R  0.0.0.0:7900:external2:5900  user  @  internal1 

The SSH server must be configured with ” 

GatewayPorts clientspecified 

”, as we have seen in scenario 4.

And we will access the service by running the command in  internal2 :

Internal2  $  internal vncviewer1  ::  7900 

If we want to create many tunnels at once, it may be convenient to use a configuration file instead of composing a very long command. Lets imagine that our only entry point to a network is through SSH and we need to create tunnels to access the different servers in the network via SSH, VNC or Remote Desktop. We could compose a file like the following with all the redirects that we will need (in relation to the mentioned SOCKS server.

# SOCKS server
DynamicForward 1080

# SSH redirects
LocalForward 2221 serverlinux1: 22
LocalForward 2222 serverlinux2: 22
LocalForward 2223 172.16.23.45:22
LocalForward 2224 172.16.23.48:22

# RDP redirects for Windows systems
LocalForward 3391 serverwindows1: 3389
LocalForward 3392 serverwindows2: 3389

# VNC redirects for systems with "vncserver"
LocalForward 5902 serverlinux1: 5901
LocalForward 5903 172.16.23.45:5901

And we only need to execute this to create all the redirects:

External1  $  ssh  -F  $  HOME  /  redirects user  @  internal1 

via: https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/

作者: Ahmad 译者:译者ID 校对:校对者ID

本文由 LCTT 原创编译,Linux中国 荣誉推出