如何建立本地SSH隧道
在我们计划建立一个本地SSH隧道之前,我们必须清楚下面这些数据:
中间服务器d的IP地址
要访问服务器c的IP地址
要访问服务器c的端口
现在,我们把上面这张图变得具体一些,给这些机器加上IP地址。并且根据下面这张图列出我们的计划:
需要访问234.234.234.234的FTP服务,也就是端口21
中间服务器是123.123.123.123
现在我们使用下面这条命令来达成我们的目的
ssh -N -f -L 2121:234.234.234.234:21 123.123.123.123
ftp localhost:2121 # 现在访问本地2121端口,就能连接234.234.234.234的21端口了
这里我们用到了SSH客户端的三个参数,下面我们一一做出解释:
-N 告诉SSH客户端,这个连接不需要执行任何命令。仅仅做端口转发
-f 告诉SSH客户端在后台运行
-L 做本地映射端口,被冒号分割的三个部分含义分别是
需要使用的本地端口号
需要访问的目标机器IP地址(IP: 234.234.234.234)
需要访问的目标机器端口(端口: 21)
最后一个参数是我们用来建立隧道的中间机器的IP地址(IP: 123.123.123.123)
我们再重复一下-L参数的行为。-L X:Y:Z的含义是,将IP为Y的机器的Z端口通过中间服务器映射到本地机器的X端口。
在这条命令成功执行之后,我们已经具有绕过公司防火墙的能力,并且成功访问到了我们喜欢的一个FTP服务器了。
如何建立远程SSH隧道
通过建立本地SSH隧道,我们成功地绕过防火墙开始下载FTP上的资源了。那么当我们在家里的时候想要察看下载进度怎么办呢?大多数公司的网络是通过路由器接入互联网的,公司内部的机器不会直接与互联网连接,也就是不能通过互联网直接访问。通过线路D-B-A访问公司里的机器a便是不可能的。也许你已经注意到了,虽然D-B-A这个方向的连接不通,但是A-B-D这个方向的连接是没有问题的。那么,我们能否利用一条已经连接好的A-B-D方向的连接来完成D-B-A方向的访问呢?答案是肯定的,这就是远程SSH隧道的用途。
与本地SSH一样,我们在建立远程SSH隧道之前要清楚下面几个参数:
需要访问内部机器的远程机器的IP地址(这里是123.123.123.123)
需要让远程机器能访问的内部机器的IP地址(这里因为是想把本机映射出去,因此IP是127.0.0.1)
需要让远程机器能访问的内部机器的端口号(端口:22)
在清楚了上面的参数后,我们使用下面的命令来建立一个远程SSH隧道
ssh -N -f -R 2222:127.0.0.1:22 123.123.123.123
现在,在IP是123.123.123.123的机器上我们用下面的命令就可以登陆公司的IP是192.168.0.100的机器了。
ssh -p 2222 localhost
-N,-f 这两个参数我们已经在本地SSH隧道中介绍过了。我们现在重点说说参数-R。该参数的三个部分的含义分别是:
远程机器使用的端口(2222)
需要映射的内部机器的IP地址(127.0.0.1)
需要映射的内部机器的端口(22)
例如:-R X:Y:Z 就是把我们内部的Y机器的Z端口映射到远程机器的X端口上。
建立SSH隧道的几个技巧
自动重连
隧道可能因为某些原因断开,例如:机器重启,长时间没有数据通信而被路由器切断等等。因此我们可以用程序控制隧道的重新连接,例如一个简单的循环或者使用 djb’s daemontools . 不管用哪种方法,重连时都应避免因输入密码而卡死程序。关于如何安全的避免输入密码的方法,请参考我的 如何实现安全的免密码ssh登录 。这里请注意,如果通过其他程序控制隧道连接,应当避免将SSH客户端放到后台执行,也就是去掉-f参数。
保持长时间连接
有些路由器会把长时间没有通信的连接断开。SSH客户端的TCPKeepAlive选项可以避免这个问题的发生,默认情况下它是被开启的。如果它被关闭了,可以在ssh的命令上加上-o TCPKeepAlive=yes来开启。
另一种方法是,去掉-N参数,加入一个定期能产生输出的命令。例如: top或者vmstat。下面给出一个这种方法的例子:
ssh -R 2222:localhost:22 123.123.123.123 "vmstat 30"
检查隧道状态
有些时候隧道会因为一些原因通信不畅而卡死,例如:由于传输数据量太大,被路由器带入stalled状态。这种时候,往往SSH客户端并不退出,而是卡死在那里。一种应对方法是,使用SSH客户端的ServerAliveInterval和ServerAliveCountMax选项。ServerAliveInterval会在隧道无通信后的一段设置好的时间后发送一个请求给服务器要求服务器响应。如果服务器在ServerAliveCountMax次请求后都没能响应,那么SSH客户端就自动断开连接并退出,将控制权交给你的监控程序。这两个选项的设置方法分别是在ssh时加入-o ServerAliveInterval=n和-o ServerAliveCountMax=m。其中n, m可以自行定义。
如何将端口绑定到外部地址上
使用上面的方法,映射的端口只能绑定在127.0.0.1这个接口上。也就是说,只能被本机自己访问到。如何才能让其他机器访问这个端口呢?我们可以把这个映射的端口绑定在0.0.0.0的接口上,方法是加上参数-b 0.0.0.0。同时还需要打开SSH服务器端的一个选项-GatewayPorts。默认情况下它应当是被打开的。如果被关闭的话,可以在/etc/sshd_config中修改GatewayPorts no为GatewayPorts yes来打开它。
如何寻找中间服务器
如果你家里使用ADSL上网,多半你会比较幸运。一般的ADSL(例如 联通 的ADSL)都是有互联网地址的。你只需要在家里的路由器上一台装有OpenSSH server机器的SSH端口映射出去即可。同时一些提供SSH访问的虚拟主机也可以用于这一用途。例如: Hostmonser 或者 Dreamhost .
通过SSH隧道建立SOCKS服务器
如果我们需要借助一台中间服务器访问很多资源,一个个映射显然不是高明的办法(事实上,高明确实没有用这个方法)。幸好,SSH客户端为我们提供了通过SSH隧道建立SOCKS服务器的功能。
通过下面的命令我们可以建立一个通过123.123.123.123的SOCKS服务器。
ssh -N -f -D 1080 123.123.123 # 将端口绑定在127.0.0.1上
ssh -N -f -D 0.0.0.0:1080 123.123.123.123 # 将端口绑定在0.0.0.0上
通过SSH建立的SOCKS服务器使用的是SOCKS5协议,在为应用程序设置SOCKS代理的时候要特别注意。
总结
至此,我们已经对如何利用SSH隧道有一个基本的认识了。现在,文章开始时的那些问题应该迎刃而解了吧。这里要特别说一下,由于SSH隧道也使用了SSH加密协议,因此是不会被防火墙上的内容过滤器监控到的。也就是说一切在隧道中传输的数据都是被加密的。当然,离开隧道后的数据还是会保持自己原有的样子,没有加密的数据还是会被后续的路由设备监控到。
除了SSH端口转发外,另一个办法就是SSH反向隧道。SSH反向隧道这个概念其实很简单。为此,你需要在限制性家用网络外面有另一个主机,即所谓的“中继主机”(relay host),你可以从所在地方通过SSH连接到该主机。你可以使用带公共IP地址的虚拟专用服务器(VPS)实例来建立中继主机。然后要做的就是建立一条持久性SSH隧道,从你家用网络的服务器通向公共中继主机。有了这条隧道,你就可以从中继主机“连回”到家用服务器(这就是为什么它叫“反向”隧道)。无论你人在什么地方,或者你家用网络中的NAT或防火墙限制多严格,只要你可以连接到中继主机,就可以连接到家用服务器。\x0d\x0a在Linux上建立SSH反向隧道\x0d\x0a不妨看看我们如何可以建立并使用一条SSH反向隧道。我们假设下列设置。我们将建立一条从家用服务器(homeserver)到中继服务器(relayserver)的SSH反向隧道,那样我们就可以从另一台名为clientcomputer的计算机,通过中继服务器以SSH的方式连接到家用服务器。中继服务器的公共IP地址是1.1.1.1。\x0d\x0a在家用服务器上,打开通向中继服务器的SSH连接,如下所示。\x0d\x0ahomeserver~$ ssh -fN -R 10022:localhost:22 relayserver_user@1.1.1.1\x0d\x0a这里的端口10022是你可以选择的任何随意的端口号。只要确保该端口没有被中继服务器上的其他程序所使用就行。\x0d\x0a“-R 10022:localhost:22”选项定义了反向隧道。它通过中继服务器的端口1022,将流量转发到家用服务器的端口22。\x0d\x0a若使用“-fN”选项,一旦你成功验证了身份、登录到SSH服务器,SSH就会径直进入后台。如果你不想在远程SSH服务器上执行任何命令,只想转发端口,就像在本文的示例中,这个选项很有用。\x0d\x0a运行上述命令后,你将直接回到家用服务器的命令提示符。\x0d\x0a登录进入到中继服务器,核实127.0.0.1:10022绑定到sshd。如果是这样,那意味着反向隧道已正确建立起来。\x0d\x0arelayserver~$ sudo netstat -nap | grep 10022\x0d\x0atcp 0 0 127.0.0.1:10022 0.0.0.0:* LISTEN 8493/sshd\x0d\x0a现在可以从其他任何计算机(比如clientcomputer),登录进入到中继服务器。然后访问家用服务器,如下所示。\x0d\x0arelayserver~$ ssh -p 10022 homeserver_user@localhost\x0d\x0a需要注意的一个地方就是,你为localhost输入的SSH登录信息/密码应该适用于家用服务器,而不是适用于中继服务器,因为你是通过隧道的本地端点登录进入到家用服务器。所以别为中继服务器输入登录信息/密码。成功登录后,你就接入到了家用服务器。\x0d\x0a通过SSH反向隧道,直接连接到NAT后面的服务器\x0d\x0a虽然上述方法让你可以连接到NAT后面的家用服务器,但是你需要登录两次,先登录到中继服务器,然后登录到家用服务器。这是由于中继服务器上SSH隧道的端点绑定到回送地址(127.0.0.1)。\x0d\x0a但实际上,只要单次登录到中继服务器,就可以直接连接到NAT后面的家用服务器。为此,你需要让中继服务器上的sshd不仅可以从回送地址转发端口,还可以从外部主机转发端口。这可以通过在中继服务器上运行的sshd里面指定GatewayPorts选项来实现。\x0d\x0a打开中继服务器的/etc/ssh/sshd_conf,添加下面这一行。\x0d\x0arelayserver~$ vi /etc/ssh/sshd_conf\x0d\x0aGatewayPorts clientspecified\x0d\x0a重启sshd。\x0d\x0a基于Debian的系统:\x0d\x0arelayserver~$ sudo /etc/init.d/ssh restart\x0d\x0a基于红帽的系统:\x0d\x0arelayserver~$ sudo systemctl restart sshd\x0d\x0a现在不妨从家用服务器开始建立SSH反向隧道,如下所示。\x0d\x0ahomeserver~$ ssh -fN -R 1.1.1.1:10022:localhost:22 relayserver_user@1.1.1.1\x0d\x0a登录进入到中继服务器,用netstat命令核实SSH反向隧道已成功建立起来。\x0d\x0arelayserver~$ sudo netstat -nap | grep 10022\x0d\x0atcp 0 0 1.1.1.1:10022 0.0.0.0:* LISTEN 1538/sshd: dev\x0d\x0a不像之前的情况,隧道的端点现在是1.1.1.1:10022(中继服务器的公共IP地址),而不是127.0.0.1:10022。这意味着,可以从外部主机连接到隧道端点。\x0d\x0a现在可以从其他任何计算机(比如clientcomputer),输入下列命令,访问NAT后面的家用服务器。\x0d\x0aclientcomputer~$ ssh -p 10022 homeserver_user@1.1.1.1\x0d\x0a在上述命令中,虽然1.1.1.1是中继服务器的公共IP地址,但homeserver_user必须是与家用服务器关联的用户帐户。这是由于,你实际登录进入的主机是家用服务器,而不是中继服务器。后者只是将你的SSH流量中继转发到家用服务器而已。\x0d\x0a在Linux上建立持久性SSH反向隧道\x0d\x0a想必你已明白了如何建立一条SSH反向隧道,现在不妨让隧道具有“持久性”,那样隧道随时建立并运行起来(无论面对什么样的情况:暂时网络拥塞、SSH超时还是中继主机重启等)。毕竟,要是隧道没有始终建立起来,你也就无法可靠地连接到家用服务器。\x0d\x0a为了建立持久性隧道,我要使用一款名为autossh的工具。顾名思义,万一SSH会话由于任何原因而断开,这个程序让你可以自动重启SSH会话。所以,让SSH反向隧道保持持久连接很有用。\x0d\x0a第一步,不妨建立无需密码的SSH登录机制,从家用服务器登录到中继服务器。那样一来,autossh就能重启断开的SSH反向隧道,不需要用户干预。\x0d\x0a下一步,将autossh安装到发起隧道的家用服务器上。\x0d\x0a从家用服务器运行带下列变量的autossh,从而建立一条通向中继服务器的持久性SSH隧道。\x0d\x0ahomeserver~$ autossh -M 10900 -fN -o "PubkeyAuthentication=yes" -o "StrictHostKeyChecking=false" -o "PasswordAuthentication=no" -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" -R 1.1.1.1:10022:localhost:22 relayserver_user@1.1.1.1\x0d\x0a“-M 10900”选项指定了中继服务器上的一个监控端口,将用来交换测试数据,以监控SSH会话。该端口不应该被中继服务器上的任何程序所使用。\x0d\x0a“-fN”选项传递给ssh命令,让SSH隧道可以在后台运行。\x0d\x0a“-o XXXX”选项指令ssh执行下列 *** 作:\x0d\x0a•使用密钥验证,而不是密码验证。\x0d\x0a•自动接受(未知的)SSH主机密钥。\x0d\x0a•每60秒就交换持久连接(keep-alive)消息。\x0d\x0a•最多发送3个持久连接消息,而不接受任何响应。\x0d\x0a与SSH反向隧道有关的其余选项仍与之前一样。\x0d\x0a如果你希望SSH隧道一启动就自动建立起来,可以在/etc/rc.local中添加上述的autossh命令。SSH隧道是一种通过加密的SSH连接传输任意网络数据的方法。它可以用来为任何应用程序添加加密通道;也可以用它来实现VPN和跨防火墙访问局域网的服务。
SSH是一个通过不受信任的网络进行安全远程登录和文件传输的标准。通过SSH隧道传输TCP/IP数据,它还提供了一种使用端口转发保护任何给定应用程序数据流量的方法。采用了这种方法后,应用程序的数据流量都会走SSH的加密连接,从而不会被窃听或拦截。对于本身不支持加密的应用程序来说,使用SSH隧道可以很方便地添加网络安全性。
上图简要介绍了SSH隧道。不可信网络的安全连接建立在SSH客户端和SSH服务器之间。这个连接是加密的,可用于保护机密性和完整性,并且可以对通信方进行身份验证。
客户端应用使用SSH来连接到服务端应用。隧道启用后
通过上面的转发,无需修改应用程序,就能保证应用程序客户端和服务端通信的安全。
这个方式的缺点是,任何能登陆服务器的用户都可以启用端口转发。内部IT人员经常在他们的家里的机器或云上的服务器上启用转发,从而能在企业内网中,从工作机器上访问家里的机器或云上的服务器。黑客或恶意软件会利用类似的方式在局域网中留一个后门。还可以在多个设备上开启隧道,攻击者通过在这些隧道中跳来跳去来隐藏踪迹。
本地代理用于将端口从客户端计算机转发到服务端计算机。SSH客户端监听来自某个端口的连接,当它收到连接时,将请求通过隧道转发到SSH服务器;然后SSH服务器将请求转到目标端口。
本地转发比较常见的场景有:
在OpenSSH中,使用 -L 参数开启本地转发
这个命令工作的过程如下图
默认情况下,其他的机器都能够连接到本地的SSH客户端指定的端口;为了安全起见,一般绑定地址,将连接来源限制在同一主机的程序
也可以在 OpenSSH客户端的配置中 配置本地转发,这样就不用单独输入命令行了
比如在~/.ssh/config中这样写
这样在开启转发的时候只需要输入 ssh serverfw 而不用再输入完整的命令了
如果希望通过本地计算机,让远程服务器 remote 可以连接到 server 上的服务,可以使用SSH远程转发。
使用SSH远程转发一个典型的用途是,在企业内部开一个后门,让公网的计算机可以访问到企业的某个内部服务,这个是有一定风险的,使用的时候需要特别小心。
在OpenSSH中,远程转发通过 -R 参数开启,在本地计算机上输入命令
上面命令的工作过程如下
默认情况下,OpenSSH仅允许从服务器主机(上图的 remote )连接到远程转发端口 server:p2 ,如果想要其他的主机也能连上 server:p2 ,需要在 sshd_config 文件中设置
如果需要指定来源IP,可以将配置改为
比如
将只允许52.192.1.73到端口8080的连接
OpenSSH的远程转发支持多个规则,比如
同样的,可以在 ~/.ssh/config 配置host,比如
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)