对于SecureShell(SSH)等网络协议,其主要职责是以终端模式访问远程系统。因为SSH协议对传输的数据进行了加密,所以通过它在远程系统上执行命令是安全的。另外,我们还可以通过在这个加密连接上创建隧道(端口转发),实现两个不同终端之间的互联。这样只要我们能够通过SSH建立连接,就可以绕过防火墙或者端口ban的限制。这个主题在网络世界中有很多应用和讨论:Wikipedia:SSHTunnelingO'Reilly:UsingSSHTunnelingSsh.com:TunnelingExplainedSsh.com:PortForwardingSecurityFocus:SSHPortForwardingRedHatMagazine:SSHPortForwardingWe正在接收下面的内容不讨论端口转发的细节,而是准备介绍一个如何使用OpenSSH完成TCP端口转发的备忘单,里面包含了八个常见的场景。一些SSH客户端,例如PuTTY,也允许通过接口配置进行端口转发。我们关注的是通过OpenSSH实现它的方式。在下面的例子中,我们假设环境中的网络分为两部分:外部网络(network1)和内部网络(network2),这两个网络只能通过externo1和interno1之间的SSH连接。互相拜访。外网节点和内网节点全连接。SSH隧道:无隧道场景1在externo1节点访问interno1节点提供的TCP服务(本地端口转发/绑定地址=localhost/host=localhost)externo1节点可以通过OpenSSH连接到interno1节点,然后我们要在端口5900上运行其访问VNC服务。SSH隧道:场景一我们可以使用如下命令来实现:externo1$ssh-L7900:localhost:5900user@interno1现在我们可以确认externo1节点上7900端口是否处于监听状态:externo1$netstat-ltnActiveInternetconnections(onlyservers)ProtoRecv-QSend-QLocalAddressForeignAddressState...Tcp00127.0.0.1:79000.0.0.0:*LISTEN...我们只需要在externo1节点执行如下命令即可访问内部节点的VNC服务:externo1$vncviewerlocalhost::7900注:vncviewer的man手册中没有提到这种修改端口号的方法。可以在输出TCP端口的AboutVNCViewer配置中看到。这也是TightVNCvncviewer介绍的内容。场景2在externo2节点访问interno1节点提供的TCP服务(本地端口转发/绑定地址=0.0.0.0/host=localhost)。节点连接到interno1上的VNC服务:SSH隧道:场景2正确的命令如下:externo1$ssh-L0.0.0.0:7900:localhost:5900user@interno1看起来类似于场景1中的命令,但是让我们查看netstat命令输出的差异。端口7900绑定到本地(127.0.0.1),因此只有本地进程可以访问它。这次我们将端口关联到0.0.0.0,这样系统就允许任意IP地址的机器访问7900端口。externo1$netstat-ltnActiveInternetconnections(onlyservers)ProtoRecv-QSend-QLocalAddressForeignAddressState...Tcp000.0.0.0:79000.0.0.0:*LISTEN...所以现在在externo2节点上,我们可以执行:externo2$vncviewerexterno1::7900来连接到interno1节点上的VNC服务。除了指定IP为0.0.0.0外,我们还可以使用参数-g(允许远程机器使用本地端口转发),完整命令如下:externo1$ssh-g-L7900:localhost:5900user@interno1这个命令和前面的命令一样可以达到同样的效果:externo1$ssh-L0.0.0.0:7900:localhost:5900user@interno1也就是说如果我们想限制连接到某个IP上系统,我们可以这样定义它:externo1$ssh-L192.168.24.80:7900:localhost:5900user@interno1externo1$netstat-ltnActiveInternetconnections(onlyservers)ProtoRecv-QSend-QLocalAddressForeignAddressState...Tcp00192.168.24.80:79000.0。0.0:*LISTEN...场景3ininterno1访问externo1提供的TCP服务(远程端口转发/绑定地址=localhost/host=localhost)场景1中,SSH服务器与TCP服务在同一个节点(VNC)供应商。现在我们想在SSH客户端所在的节点上提供一个TCP服务(VNC),供SSH服务器访问:SSHTunnels:场景三将场景一中的命令参数由-L替换为-R。完整命令如下:externo1$ssh-R7900:localhost:5900user@interno1然后我们可以看到interno1节点正在监听7900端口:interno1$netstat-lntActiveInternetconnections(onlyservers)ProtoRecv-QSend-QLocalAddressForeignAddressState...Tcp00127。0.0。1:79000.0.0.0:*LISTEN...现在在interno1节点上,我们可以使用如下命令访问externo1上的VNC服务:interno1$vncviewerlocalhost::7900场景4interno2使用externo1上提供的TCP服务(远程端口转发/bindaddress=0.0.0.0/host=localhost)和场景3类似,但是现在我们尝试指定允许访问转发端口的IP(我们在场景2中做的)为0.0.0.0,这样其他节点也可以访问VNC服务:SSHTunnels:场景4正确的命令是:externo1$ssh-R0.0.0.0:7900:localhost:5900user@interno1但是这里有一点需要理解,出于安全原因,如果我们直接执行这条命令可能不会生效,因为我们需要修改SSH服务器的一个参数值GatewayPorts,它的默认值为:no。GatewayPorts此参数指定远程主机是否允许客户端访问转发端口。默认情况下,sshd(8)只允许本机进程访问转发端口。这是为了防止其他主机连接到该转发端口。GatewayPorts参数可以用来告诉sshd允许远程转发端口绑定到非环回地址,远程主机可以访问这些地址。当参数值设置为“no”时,只有本机可以访问转发端口;“yes”表示允许远程转发端口绑定通配地址;或设置为“clientspecified”表示客户端选择哪些主机地址允许访问转发的端口。默认值为“否”。如果我们没有修改服务器配置的权限,我们将无法使用该方案进行端口转发。这是因为在没有其他限制的情况下,用户可以开放一个端口(>1024)来监听来自外部的请求,并转发到localhost:7900。参考这个案例:netcat(Debian#310431:sshd_configshouldwarnabouttheGatewayPortsworkaround.)所以我们修改/etc/ssh/sshd_config并添加以下内容:GatewayPortsclientspecified然后,我们使用以下命令重新加载修改后的配置文件(在在Debian和Ubuntu上)。sudo/etc/init.d/sshreload我们确认interno1节点7900端口有一个监听器,监听来自不同IP的请求:interno1$netstat-ltnActiveInternetconnections(onlyservers)ProtoRecv-QSend-QLocalAddressForeignAddressState...Tcp000.0.0.0:79000.0.0.0:*LISTEN...然后我们就可以在interno2节点上使用VNC服务了:interno2$internalvncviewer1::7900场景5在externo1上使用interno2提供的TCP服务(本地端口转发/绑定地址localhost/host=interno2)SSHTunnels:场景5在这个场景中,我们使用以下命令:externo1$ssh-L7900:interno2:5900user@interno1然后我们可以通过执行以下命令在externo1节点上使用VNC服务:externo1$vncviewerlocalhost::7900场景6在interno1上使用externo2提供的TCP服务(远程端口转发/绑定地址=localhost/host=externo2)SSH隧道:场景6本场景我们使用如下命令:externo1$ssh-R7900:externo2:5900user@interno1然后我们在interno1上执行如下命令就可以访问到VNC服务了:interno1$vncviewerlocalhost::7900场景7在externo2上使用interno2提供的TCP服务(本地端口转发/绑定Setaddress=0.0.0.0/host=interno2)SSHTunnels:场景7在这个场景中,我们使用以下命令:externo1$ssh-L0.0.0.0:7900:interno2:5900user@interno1或者:externo1$ssh-g-L7900:interno2:5900user@interno1然后我们可以在externo2上执行如下命令访问vnc服务:externo2$vncviewerexterno1::7900场景8在interno2上使用externo2提供的TCP服务(远程端口转发/绑定地址=0.0.0.0/host=externo2)SSHTunnels:Scenario8我们在这个场景中使用以下命令:externo1$ssh-R0.0.0.0:7900:externo2:5900user@interno1SSHserver需要配置为:GatewayPortsclientspecifiedaswesaidinScenario4然后我们可以在interno2节点上执行如下命令访问VNC服务:interno2$internalvncviewer1::7900如果我们需要一次创建多个隧道,最好使用配置文件而不是一个可能很长的命令sChoice。假设我们只能通过SSH访问一个特定的网络,同时需要创建多个隧道来访问网络中不同服务器上的服务,比如VNC或者远程桌面。此时只需要创建配置文件$HOME/redirects如下(在SOCKS服务器上)。#SOCKSserverDynamicForward1080#SSHredirectsLocalForward2221serverlinux1:22LocalForward2222serverlinux2:22LocalForward2223172.16.23.45:22LocalForward2224172.16.23.48:22#RDPredirectsforWindowssystemsLocalForward3391serverwindows1:3389LocalForward3392serverwindows2:3389#VNCredirectsforsystemswith"vncserver"LocalForward5902serverlinux1:5901LocalForward5903172.16.23.45:5901然后我们只需要执行如下命令:externo1$ssh-F$HOME/redirectsuser@interno1
