请稍侯

ssh隧道、端口转发及内网穿透

08 November 2013

ssh隧道、端口转发及内网穿透

ssh相关知识点概要

  • SSH是一种安全的传输协议,目前最多的主要是用于连接服务器,除了这个之外它的隧道转发功能也是非常强大有用的。
  • 下面介绍一下三个非常强大的命令:

     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参数中,允许远程主机连接到建立的转发的端口,如果不加这个参数,只允许本地主机建立连接。注:而这个参数我在实践中似乎始终不起作用。

建立SSH隧道案例

  • 网络结构说明: 网络拓扑图

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

建立本地SSH隧道

  • 即要实现绕过公司防火墙,访问c某网站服务器。需要在公司内自己的机器上使用如下命令配置来建立一个本地的SSH隧道:
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端口了
  • 参考说明:
    • -N 告诉SSH客户端,这个连接不需要执行任何命令。仅仅做端口转发
    • -f 告诉SSH客户端在后台运行
    • -L 做本地映射端口,被冒号分割的三个部分含义分别是
      • 需要使用的本地端口号
      • 需要访问的目标机器IP地址(IP: 234.234.234.234)
      • 需要访问的目标机器端口(端口: 21)
      • 其中中间服务器是123.123.123.123,需要访问的FTP服务器是234.234.234.234,端口为21
      • -L X:Y:Z的含义是,将IP为Y的机器的Z端口通过中间服务器映射到本地机器的X端口。
    • 最后一个参数是我们用来建立隧道的中间机器的IP地址(IP: 123.123.123.123)

建立远程SSH隧道

  • 即要实现在IP是123.123.123.123的机器上用命令:ssh -p 2222 localhost就可以登陆公司的IP是192.168.0.100的机器。则需要在公司内自己的机器上使用以下命令来建立一个远程SSH隧道:
ssh -N -f -R 2222:127.0.0.1:22 123.123.123.123
  • 参考说明:
    • -N,-f 这两个参数上面已经在本地SSH隧道中说明过了
    • -R。该参数的三个部分的含义分别是:
      • 远程机器使用的端口(2222)
      • 需要映射的内部机器的IP地址(127.0.0.1)
      • 需要映射的内部机器的端口(22)
      • 其中需要访问内部机器的远程机器的IP地址(这里是123.123.123.123)
      • 这里 -R X:Y:Z 就是把我们内部的Y机器的Z端口映射到远程机器的X端口上

通过SSH隧道建立SOCKS服务器

如果需要借助一台中间服务器访问很多资源,一个个映射显然不是办法。这就要用到SSH客户端为我们提供了通过SSH隧道建立SOCKS服务器(动态绑定)的功能。

1. ssh -N -f -D 1080 123.123.123 # 将端口绑定在127.0.0.1上
2. ssh -N -f -D 0.0.0.0:1080 123.123.123.123 # 将端口绑定在0.0.0.0上
  • 使用场景,假设X网络(192.168.18.0/24)有主机A(192.168.18.100),Y网络(192.168.2.0/24)有主机B(192.168.2.100)和主机C(192.168.2.101),已知主机A可以连接主机B,但无法连接主机C。

在主机A执行

ssh -D localhost:8080 root@192.168.2.100

然后主机A上的应用程序就可以通过

SOCKS5 localhost:8080

访问主机C上的服务。

建立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来打开它。


以上参考:

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

三种不同类型的ssh隧道

简单的ssh隧道实现代理上网

SSH Tunnel 实现VPN的功能

SSH隧道翻墙的原理和实现

SSH 隧道转发实战