SSH隧道与端口转发及内网穿透

20 篇文章 0 订阅

SSH隧道与端口转发及内网穿透

大家都知道SSH是一种安全的传输协议,用在连接服务器上比较多。不过其实除了这个功能,它的隧道转发功能更是吸引人。下面是个人根据自己的需求以及在网上查找的资料配合自己的实际操作所得到的一些心得。

SSH/plink命令的基本资料:

首先,认识下这三个非常强大的命令:

ssh -C -f -N -g -L listen_port:DST_Host:DST_port user@Tunnel_Host 
ssh -C -f -N -g -R listen_port:DST_Host:DST_port user@Tunnel_Host 
ssh -C -f -N -g -D listen_port user@Tunnel_Host

相关参数的解释: 
-f Fork into background after authentication. 
后台认证用户/密码,通常和-N连用,不用登录到远程主机。

-L port:host:hostport 
将本地机(客户机)的某个端口转发到远端指定机器的指定端口. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 同时远程主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有 root 才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport

-R port:host:hostport 
将远程主机(服务器)的某个端口转发到本地端指定机器的指定端口. 工作原理是这样的, 远程主机上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转向出去, 同时本地主机和 host 的 hostport 端口建立连接. 可以在配置文件中指定端口的转发. 只有用 root 登录远程主机才能转发特权端口. IPv6 地址用另一种格式说明: port/host/hostport

-D port 
指定一个本地机器 “动态的’’ 应用程序端口转发. 工作原理是这样的, 本地机器上分配了一个 socket 侦听 port 端口, 一旦这个端口上有了连接, 该连接就经过安全通道转发出去, 根据应用程序的协议可以判断出远程主机将和哪里连接. 目前支持 SOCKS4 协议, 将充当 SOCKS4 服务器. 只有 root 才能转发特权端口. 可以在配置文件中指定动态端口的转发.

-C Enable compression. 
压缩数据传输。

-N Do not execute a shell or command. 
不执行脚本或命令,通常与-f连用。

-g Allow remote hosts to connect to forwarded ports. 
在-L/-R/-D参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。注:这个参数我在实践中似乎始终不起作用。

以上摘录自:http://chenweiguang.blogspot.com/2009/03/ssh.html

建立本地SSH隧道例子

在我们计划建立一个本地SSH隧道之前,我们必须清楚下面这些数据:

  1. 中间服务器d的IP地址
  2. 要访问服务器c的IP地址
  3. 要访问服务器c的端口

现在,我们把上面这张图变得具体一些,给这些机器加上IP地址。并且根据下面这张图列出我们的计划:

Chapter 8 Secure Network (ssh端口映射) - linux-ul - unix-EA

 

  1. 需要访问234.234.234.234的FTP服务,也就是端口21
  2. 中间服务器是123.123.123.123

现在我们使用下面这条命令来达成我们的目的(192.168.0.100上执行)

1.ssh -N -f   -L    2121:234.234.234.234:21    123.123.123.123

2.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隧道

1.ssh -N -f -R 2222:127.0.0.1:22      123.123.123.123

现在,在IP是123.123.123.123的机器上我们用下面的命令就可以登陆公司的IP是192.168.0.100的机器了。

1.ssh -p 2222 localhost

-N,-f 这两个参数我们已经在本地SSH隧道中介绍过了。我们现在重点说说参数-R。该参数的三个部分的含义分别是:

  • 远程机器使用的端口(2222)
  • 需要映射的内部机器的IP地址(127.0.0.1)
  • 需要映射的内部机器的端口(22)

例如:-R X:Y:Z 就是把我们内部的Y机器的Z端口映射到远程机器的X端口上。






SSH端口转发的好处:

    1. 利用SSH通道天然的加密特性

    2. 通过具备访问权限的第三者,突破防火墙对自己的限制,或者隐身


角色定义:

    A. 本地服务器,想通过中间服务器B间接访问目标服务器C

    B. 中间服务器,类似于代理,A以B的名义去访问C

    C. 目标服务器,C看到的都是中间服务器B在访问自己


1. 本地端口转发

命令:

    ssh -Nf -L [local_A_address]:local_A_port:target_C_server:target_C_port via_B_server

参数:

    -N,不执行命令

    -f,后台执行

    -L,local本地端口转发

    local_A_address:

        127.0.0.1 - 默认,只能本机使用这个端口转发

        也可以是本机的IP地址,同时其他人可以使用这个IP来使用这个端口转发

    via_B_server:中间服务器

应用:

    A---能访问------>B-------能访问------>C

    A---不能访问----------------------------->C

    A---通过本机端口,以B的名义访问-->C

关闭:

    直接kill -9 建立的SSH连接,下同


2. 远程端口转发

命令:

    ssh -Nf -R [local_A_address]:local_A_port:target_C_server:target_C_port local_A_address

参数:

    -R,remote,远程端口转发

    local_A_address,这个地址为A的IP

应用:

    环境和目的 与 本地端口转发是一样的,这里只是不在本地服务器A上执行命令,而是在中间服务器B上执行

    为什么不直接在服务器A自己身上执行命令呢?这个场景有别于本地端口转发的地方在于A不能主动连接B但反之可以,比如A在外网,B在内网

    而A去访问的时候,同样都是通过自己的IP和端口,同样首先建立AB之间的SSH通道,以服务器B的名义来访问目标服务器C。


3. 动态端口转发

命令:

    ssh -Nf -D [local_A_address]:local_A_port via_B_server

参数:

    -D,dynamic,动态端口转发

应用:

    本地和远程端口转发,都限定了目标服务器以及目标服务器的端口;

    而动态端口转发,A把B作为了自己的全权代理,不限定目标服务器及其端口;

    这里要求在A上,做下代理设置,比如浏览器的代理设定为自己的IP:PORT;

    本地端口转发和远程端口转发,其实都可看着是动态端口转发(代理)的子集

    三者和一般代理的目的和场景都一致,区别在于这里自己A和代理服务器B之前的所有连接都是基于加密的SSH。





三、建立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加 密协议,因此是不会被防火墙上的内容过滤器监控到的。也就是说一切在隧道中传输的数据都是被加密的。当然,离开隧道后的数据还是会保持自己原有的样子,没 有加密的数据还是会被后续的路由设备监控到。

 

 

PS:编者另注

  在大多数情况下,我们建立ssh隧道的时候,往往是想通过一台公网的主机或者是大家都可以访问的主机做跳转机,来访问内部或者外部不能直接访问的机器。所以一般像这种情况下,请将跳转机中的ssh服务器中的GatewayPorts设为yes

  1.建立本地的ssh隧道时,可以指定本地主机的地址,如下:

ssh -Nf -L 192.168.0.100:2121:234.234.234.234:21 123.123.123.123

   那么本地局域网的任何机器访问192.168.0.100:2121都会自动被映射到234.234.234.234:21

  

  2.建立远程的ssh隧道时,可以指定公网的主机地址,不过一般情况是要访问内网的主机,所以这条命令应该在任何一台内网主机上执行,比如在192.168.0.102的主机上运行:

ssh -Nf -R 123.123.123.123:2222:192.168.0.100:22 123.123.123.123

 只要在局域网里192.168.0.102可以直接连接内网主机192.168.0.100,且192.168.0.102可以直接与公网主机123.123.123.123建立ssh连接。那么任何外网主机通过访问公网主机123.123.123.123:2222就会被连接到192.168.0.100:22,从而可以完成外网穿越NAT到内网的访问,而不需要在内网网关和路由器上做任何操作。

   

  另外,你也可以通过Xshell、Putty等工具来实现Linux主机与本地windows的端口转发、socket代理,还有一些像ProxyChains 工具的使用。

     转载:http://blog.csdn.net/dufufd/article/details/75578277

  • 1
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值