Merge pull request #6113 from toutoudnf/master

翻译完成
This commit is contained in:
Xingyu.Wang 2017-10-08 20:18:02 -05:00 committed by GitHub
commit d66a9bd0e7
2 changed files with 412 additions and 436 deletions

View File

@ -1,436 +0,0 @@
【toutoudnf@gmail.com】翻译中
Creating TCP / IP (port forwarding) tunnels with SSH: The 8 possible scenarios using OpenSSH
============================================================
The typical function of the [Secure Shell (SSH)][21] 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:
* [Wikipedia: SSH Tunneling][12]
* [OReilly: Using SSH Tunneling][13]
* [Ssh.com: Tunneling Explained][14]
* [Ssh.com: Port Forwarding][15]
* [SecurityFocus: SSH Port Forwarding][16]
* [Red Hat Magazine: SSH Port Forwarding][17]
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][22] in the 8 different scenarios that can be given. Other SSH clients such as [PuTTY][23] 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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_sin_tunel.png)
Table of Contents [[hide][1]]
* [1 Scenario 1: Use on external1 a TCP service offered by internal1 (Local port forwarding / bind_address = localhost / host = localhost)][2]
* [2 Scenario 2: Use on external2 a TCP service offered by internal1 (Local port forwarding / bind_address = 0.0.0.0 / host = localhost)][3]
* [3 Scenario 3: Use in internal1 a TCP service offered by external1 (Remote port forwarding / bind_address = localhost / host = localhost)][4]
* [4 Scenario 4: Use in internal2 a TCP service offered by external1 (Remote port forwarding / bind_address = 0.0.0.0 / host = localhost)][5]
* [5 Scenario 5: Use in external1 a TCP service offered by internal2 (Local port forwarding / bind_address = localhost / host = internal2)][6]
* [6 Scenario 6: Use in internal1 a TCP service offered by external2 (Remote port forwarding / bind_address = localhost / host = external2)][7]
* [7 Scenario 7: Use in external2 a TCP service offered by internal2 (Local port forwarding / bind_address = 0.0.0.0 / host = internal2)][8]
* [8 Scenario 8: Use in internal2 a TCP service offered by external2 (Remote port forwarding / bind_address = 0.0.0.0 / host = external2)][9]
#### 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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_1.png)
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][18]. This is also how [the TightVNC vncviewer][19] 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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_2.png)
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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_3.png)
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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_4-1.png)
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][24] ( [Debian # 310431: sshd_config should warn about the GatewayPorts workaround.][25] )
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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_5.png)
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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_6.png)
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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_7.png)
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](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_8.png)
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][26]. 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][a]
译者:[译者ID](https://github.com/译者ID)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://wesharethis.com/author/ahmad/
[1]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#
[2]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_1_Use_onexternal1a_TCP_service_offered_byinternal1Local_port_forwarding_bind_address_localhost_host_localhost
[3]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_2_Use_onexternal2a_TCP_service_offered_byinternal1Local_port_forwarding_bind_address_0000_host_localhost
[4]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_3_Use_ininternal1a_TCP_service_offered_byexternal1Remote_port_forwarding_bind_address_localhost_host_localhost
[5]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_4_Use_ininternal2a_TCP_service_offered_byexternal1Remote_port_forwarding_bind_address_0000_host_localhost
[6]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_5_Use_inexternal1a_TCP_service_offered_byinternal2Local_port_forwarding_bind_address_localhost_host_internal2
[7]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_6_Use_ininternal1a_TCP_service_offered_byexternal2Remote_port_forwarding_bind_address_localhost_host_external2
[8]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_7_Use_inexternal2a_TCP_service_offered_byinternal2Local_port_forwarding_bind_address_0000_host_internal2
[9]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_8_Use_ininternal2a_TCP_service_offered_byexternal2Remote_port_forwarding_bind_address_0000_host_external2
[10]:https://wesharethis.com/author/ahmad/
[11]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#comments
[12]:http://en.wikipedia.org/wiki/Tunneling_protocol#SSH_tunneling
[13]:http://www.oreillynet.com/pub/a/wireless/2001/02/23/wep.html
[14]:http://www.ssh.com/support/documentation/online/ssh/winhelp/32/Tunneling_Explained.html
[15]:http://www.ssh.com/support/documentation/online/ssh/adminguide/32/Port_Forwarding.html
[16]:http://www.securityfocus.com/infocus/1816
[17]:http://magazine.redhat.com/2007/11/06/ssh-port-forwarding/
[18]:http://www.realvnc.com/pipermail/vnc-list/2006-April/054551.html
[19]:http://www.tightvnc.com/vncviewer.1.html
[20]:https://bufferapp.com/add?url=https%3A%2F%2Fwesharethis.com%2F2017%2F07%2Fcreating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh%2F&text=Creating%20TCP%20/%20IP%20(port%20forwarding)%20tunnels%20with%20SSH:%20The%208%20possible%20scenarios%20using%20OpenSSH
[21]:http://en.wikipedia.org/wiki/Secure_Shell
[22]:http://www.openssh.com/
[23]:http://www.chiark.greenend.org.uk/~sgtatham/putty/
[24]:http://en.wikipedia.org/wiki/Netcat
[25]:http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=310431
[26]:http://en.wikipedia.org/wiki/Remote_Desktop_Services

View File

@ -0,0 +1,412 @@
通过 SSH 实现 TCP / IP 隧道(端口转发):使用 OpenSSH 可能的 8 种场景
============================================================
对于 [Secure Shell (SSH)][21] 这样的网络协议来说,其主要职责就是在终端模式下访问一个远程系统。因为 SSH 协议对传输数据进行了加密,所以通过它在远端系统执行命令是非常安全的。此外,我们还可以在这种加密后的连接上通过创建隧道(端口转发)的方式,来实现两个不同终端间的互联。凭借这种方式,只要我们能通过 SSH 创建连接,就可以绕开防火墙或者端口禁用的限制。
这个话题在网络领域被广泛应用和讨论:
* [Wikipedia: SSH Tunneling][12]
* [OReilly: Using SSH Tunneling][13]
* [Ssh.com: Tunneling Explained][14]
* [Ssh.com: Port Forwarding][15]
* [SecurityFocus: SSH Port Forwarding][16]
* [Red Hat Magazine: SSH Port Forwarding][17]
我们在接下来的内容中并不讨论端口转发的细节,而是准备介绍一个如何使用 [OpenSSH][22] 来完成 TCP 端口转发的速查表,其中包含了八种常见的场景。有些 SSH 客户端,比如 [PuTTY][23],也允许通过界面配置的方式来实现端口转发。而我们着重关注的是通过 OpenSSH 来实现的的方式。
在下面的例子当中我们假设环境中的网络划分为外部网络network1和内部网络network2两部分并且这两个网络之间只能在 external1 与 internal1 之间通过 SSH 连接的方式来互相访问。外部网络的节点之间和内部网络的节点之间是完全联通的。
![SSH tunnels: no tunnel](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_sin_tunel.png)
内容列表:
* [1 场景 1 :在 external1 节点访问由 internal1 节点提供的 TCP 服务(本地端口转发 / 绑定地址 = localhost / 主机 = localhost ][2]
* [2 场景 2在 external2 节点上访问由 internal1 节点提供的 TCP 服务(本地端口转发 / 绑定地址 = 0.0.0.0 / 主机 = localhost][3]
* [3 场景 3在 internal1 上访问由 external1 提供的 TCP 服务(远程端口转发 / 绑定地址 = localhost / 主机 = localhost][4]
* [4 场景 4 internal2 使用 external1 上提供的 TCP 服务(远端端口转发 / 绑定地址 = 0.0.0.0 / 主机 = localhost][5]
* [5 场景 5 :在 external1 上使用由 internal2 提供的 TCP 服务(本地端口转发 / 绑定地址 localhost / 主机 = internal2 ][6]
* [6 场景 6 :在 internal1 上使用由 external2 提供的 TCP 服务(远程端口转发 / 绑定地址 = localhost / host = external2][7]
* [7 场景7 :在 external2 上使用由 internal2 提供的 TCP 服务(本地端口转发 / 绑定地址 = 0.0.0.0 / 主机 = internal2][8]
* [8 场景 8 在 internal2 上使用由 external2 提供的 TCP 服务(远程端口转发 / 绑定地址 = 0.0.0.0 / 主机 = external2][9]
#### 场景 1 :在 external1 节点访问由 internal1 节点提供的 TCP 服务(本地端口转发 / 绑定地址 = localhost / 主机 = localhost
externo1 节点可以通过 OpenSSH 连接到 interno1 节点,之后我们想通过其访问运行在 5900 端口上的 VNC 服务。
![SSH Tunnels: Scenario 1](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_1.png)
我们可以通过下面的命令来实现:
```
External1 $ ssh -L 7900: localhost: 5900 user @ internal1
```
现在,我们可以在 externo1 节点上确认下 7900 端口是否处于监听状态中:
```
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  
...
```
我们只需要在 external1 节点上执行如下命令即可访问 internal 节点的 VNC 服务。:
```
External1 $ vncviewer localhost :: 7900
```
注意:在下面的文档中并未提及这种修改端口号的方式。在[About VNCViewer configuration of the output TCP port][18] 中可以看到。这也是 [the TightVNC vncviewer][19] 所介绍的的。
```
<a href="http://www.realvnc.com/products/free/4.1/man/vncviewer.html">man vncviewer</a>
```
#### 场景 2在 external2 节点上访问由 internal1 节点提供的 TCP 服务(本地端口转发 / 绑定地址 = 0.0.0.0 / 主机 = localhost
这次的场景跟方案 1 的场景的类似,但是我们这次想从 external2 节点来连接到 internal1 上的 VNC 服务:
![SSH Tunnels: Scenario 2](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_2.png)
正确的命令如下:
```
External1 $ ssh -L 0.0.0.0:7900:localhost:5900 user @ internal1
```
看起来跟方案 1 中的命令类似,但是让我们看看 netstat 命令的输出上的区别:
```
netstat
```
7900 端口被绑定到了本地127.0.0.1),所以只有本地进程可以访问。这次我们将端口关联到了 0.0.0.0,所以系统允许任何 IP 地址的机器访问 7900 这个端口。
```
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
...
```
所以现在在 external2 节点上,我们可移执行:
```
External2 $ vncviewer external1 :: 7900
```
来连接到 internal1 节点上的 VNC 服务。
除了将 IP 指定为
```
0.0.0.0
```
之外,我们还可以使用如下参数:
```
-g
```
(允许远程机器使用本地端口转发),完整命令如下:
```
External1 $ ssh -g -L 7900: localhost: 5900 user @ internal1
```
这条命令与前面的命令能实现相同效果:
```
External1 $ ssh -L 0.0.0.0:7900:localhost:5900 user @ internal1
```
换句话说,如果我们想限制只有指定 IP 的机器才能访问转发端口,可以像下面这样定义:
```
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
...
```
#### 场景 3在 internal1 上访问由 external1 提供的 TCP 服务(远程端口转发 / 绑定地址 = localhost / 主机 = localhost
在场景 1 中 SSH 服务器与 TCP 服务VNC提供者在同一个节点上。现在我们想在 SSH 客户端所在的节点上,提供一个 TCP 服务VNC供 SSH 服务端来访问:
![SSH Tunnels: Scenario 3](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_3.png)
将方案 1 中的命令参数由:
```
-L
```
替换为
```
-R
```
完整命令如下:
```
External1 $ ssh -R 7900: localhost: 5900 user @ internal1
```
然后我们就能看到 interno1 节点上对 7900 端口正在监听:
```
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
...
```
现在在 internal1 节点上,我们可以使用如下命令来访问 external1 上的 VNC 服务。
```
Internal1 $ vncviewer localhost :: 7900
```
#### 场景 4 internal2 使用 external1 上提供的 TCP 服务(远端端口转发 / 绑定地址 = 0.0.0.0 / 主机 = localhost
与场景 3 类似,但是现在我们尝试指定允许访问转发端口的 IP就像方案 2 中做的一样)
```
0.0.0.0
```
这样其他节点也可以访问 VNC 服务:
![SSH Tunnels: Scenario 4](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_4-1.png)
正确的命令是:
```
External1 $ ssh -R 0.0.0.0:7900:localhost:5900 user @ internal1
```
但是如果我们直接执行该命令的话可能不会生效,因为我们需要修改 SSH 服务端的一个参数值:
```
GatewayPorts
```
他的默认值是:
```
no
```
> GatewayPorts
>
> 该参数指定了是否允许远程主机访问转发端口。默认情况下sshd(8) 只允许本机进程访问转发端口。这是为了阻止其他主机连接到该转发端口。GatewayPorts 参数可用于指定 sshd 允许哪些远程主机访问转发端口。当参数值设置为 “no” 的时候只有本机可以访问转发端口“yes” 则表示允许符合远程主机 IP 地址通配符规则的远程主机访问该转发端口“clientspecified” 则表示由客户端来选择哪些主机地址允许访问转发端口。默认值是 “no”。
如果我们没有修改服务器配置的权限,我们将不能使用该方案来进行端口转发。这是因为如果没有其他的限制,用户可以开启一个端口(> 1024来监听来自外部的请求并转发到
```
localhost:7900
```
参照这个案例:[netcat][24] ( [Debian # 310431: sshd_config should warn about the GatewayPorts workaround.][25] )
所以我们修改:
```
/etc/ssh/sshd_config
```
添加如下内容:
```
GatewayPorts clientspecified
```
然后,我们使用如下命令来重载修改后的配置文件(在 Debian 和 Ubuntu 上)。
```
sudo /etc/init.d/ssh reload
```
我们确认现在 internal1 节点上存在 7900 端口的监听程序,监听来自不同 IP 的请求:
```
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
...
```
然后我们就可以在 internal2 节点上使用 VNC 服务了:
```
Internal2 $ internal vncviewer1 :: 7900
```
#### 场景 5 :在 external1 上使用由 internal2 提供的 TCP 服务(本地端口转发 / 绑定地址 localhost / 主机 = internal2
![SSH Tunnels: Scenario 5](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_5.png)
在这种场景下我们使用如下命令:
```
External1 $ ssh -L 7900: internal2: 5900 user @ internal1
```
然后我们就能在 external1 节点上,通过执行如下命令来使用 VNC 服务了:
```
External1 $ vncviewer localhost :: 7900
```
#### 场景 6 :在 internal1 上使用由 external2 提供的 TCP 服务(远程端口转发 / 绑定地址 = localhost / host = external2
![SSH Tunnels: Scenario 6](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_6.png)
在这种场景下,我们使用如下命令:
```
External1 $ ssh -R 7900: external2: 5900 user @ internal1
```
然后我们可以在 internal1 上通过执行如下命令来访问 VNC 服务:
```
Internal1 $ vncviewer localhost :: 7900
```
#### 场景7 :在 external2 上使用由 internal2 提供的 TCP 服务(本地端口转发 / 绑定地址 = 0.0.0.0 / 主机 = internal2
![SSH Tunnels: Scenario 7](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_7.png)
本场景下,我们使用如下命令:
```
External1 $ ssh -L 0.0.0.0:7900:internal2:5900 user @ internal1
```
或者:
```
External1 $ ssh -g -L 7900: internal2: 5900 user @ internal1
```
然后我们就可以在 external2 上执行如下命令来访问 vnc 服务:
```
External2 $ vncviewer external1 :: 7900
```
#### 场景 8 在 internal2 上使用由 external2 提供的 TCP 服务(远程端口转发 / 绑定地址 = 0.0.0.0 / 主机 = external2
![SSH Tunnels: Scenario 8](https://wesharethis.com/wp-content/uploads/2017/07/ssh_tunnel_8.png)
本场景下我们使用如下命令:
```
External1 $ ssh -R 0.0.0.0:7900:external2:5900 user @ internal1
```
SSH 服务器需要配置为:
```
GatewayPorts clientspecified
```
就像我们在场景 4 中讲过的那样。
然后我们可以在 internal2 节点上执行如下命令来访问 VNC 服务:
```
Internal2 $ internal vncviewer1 :: 7900
```
如果我们需要一次性的创建多个隧道,使用配置文件的方式替代一个可能很长的命令是一个更好的选择。假设我们只能通过 SSH 的方式访问某个特定网络,同时又需要创建多个隧道来访问该网络内不同服务器上的服务,比如 VNC 或者 [远程桌面][26]。此时只需要创建一个如下的配置文件即可(在 SOCKS 服务器 上)。
```
# 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
```
然后我们只需要执行如下命令:
```
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][a]
译者:[toutoudnf](https://github.com/toutoudnf)
校对:[校对者ID](https://github.com/校对者ID)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出
[a]:https://wesharethis.com/author/ahmad/
[1]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#
[2]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_1_Use_onexternal1a_TCP_service_offered_byinternal1Local_port_forwarding_bind_address_localhost_host_localhost
[3]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_2_Use_onexternal2a_TCP_service_offered_byinternal1Local_port_forwarding_bind_address_0000_host_localhost
[4]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_3_Use_ininternal1a_TCP_service_offered_byexternal1Remote_port_forwarding_bind_address_localhost_host_localhost
[5]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_4_Use_ininternal2a_TCP_service_offered_byexternal1Remote_port_forwarding_bind_address_0000_host_localhost
[6]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_5_Use_inexternal1a_TCP_service_offered_byinternal2Local_port_forwarding_bind_address_localhost_host_internal2
[7]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_6_Use_ininternal1a_TCP_service_offered_byexternal2Remote_port_forwarding_bind_address_localhost_host_external2
[8]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_7_Use_inexternal2a_TCP_service_offered_byinternal2Local_port_forwarding_bind_address_0000_host_internal2
[9]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#Scenario_8_Use_ininternal2a_TCP_service_offered_byexternal2Remote_port_forwarding_bind_address_0000_host_external2
[10]:https://wesharethis.com/author/ahmad/
[11]:https://wesharethis.com/2017/07/creating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh/#comments
[12]:http://en.wikipedia.org/wiki/Tunneling_protocol#SSH_tunneling
[13]:http://www.oreillynet.com/pub/a/wireless/2001/02/23/wep.html
[14]:http://www.ssh.com/support/documentation/online/ssh/winhelp/32/Tunneling_Explained.html
[15]:http://www.ssh.com/support/documentation/online/ssh/adminguide/32/Port_Forwarding.html
[16]:http://www.securityfocus.com/infocus/1816
[17]:http://magazine.redhat.com/2007/11/06/ssh-port-forwarding/
[18]:http://www.realvnc.com/pipermail/vnc-list/2006-April/054551.html
[19]:http://www.tightvnc.com/vncviewer.1.html
[20]:https://bufferapp.com/add?url=https%3A%2F%2Fwesharethis.com%2F2017%2F07%2Fcreating-tcp-ip-port-forwarding-tunnels-ssh-8-possible-scenarios-using-openssh%2F&text=Creating%20TCP%20/%20IP%20(port%20forwarding)%20tunnels%20with%20SSH:%20The%208%20possible%20scenarios%20using%20OpenSSH
[21]:http://en.wikipedia.org/wiki/Secure_Shell
[22]:http://www.openssh.com/
[23]:http://www.chiark.greenend.org.uk/~sgtatham/putty/
[24]:http://en.wikipedia.org/wiki/Netcat
[25]:http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=310431
[26]:http://en.wikipedia.org/wiki/Remote_Desktop_Services