ssh打洞 回首页

一、概述

为什么要使用"ssh打洞"——改善网络连接、突破防火墙的限制、防止窃听

例1:

client在墙内, 但可以访问server, 需要打个洞让server反向以ssh访问client.

# client下ssh到server的10022端口, 开端口11111
ssh -NfR 11111:localhost:22 -p 10022 [email protected]

# 然后在server, ssh回到client
ssh localhost -p 11111
# scp 回到client
scp -P 1111 -r 5.4 [email protected]:/Storage1/CentOS/

例2:

Bob在内网, 有防火墙挡着, 所以Alice没办法向Bob建立连接,
但是Bob在的内网中有一台Carol可以操作并向外网的Alice建立连接。
如果Alice这里有 sshd server, 就可以从Carol用 ssh -R 来反向建立通道:

ssh -R 11432:Bob:1432 Alice

        Bob                     ||              Alice
    +-------------------+       ||      +-------------------+
    |  公司里的Winxp    |       ||      |  家里的           |
    |  Port 1432        |       ||      |  windows 2008 R2  |
    +-------------------+       ||      |  安装了winsshd服务|
           \                    ||      |                   |
            \                   ||      |                   |
       Carol \                  ||      |                   |
    +-------------------+       ||      |                   |
    |  Linux            |       ||      |  ssh server       |
    |  ssh client  --->-+---->--++----->+-->                |
    +-------------------+       ||      +-------------------+

这样在Alice上连 localhost:11432 的时候, ssh 通道会自动把网络包发回Bob机器的1432端口。
这里如果能操作Bob, 那么从Bob直接 ssh Alice 也可以, 就不需要Carol了。
在没有网关权限的情况下, 这个方法是从外网连内网机器的最基本的方法。

例3:

假设Alice, Bob, Carol都是互联网上的机器, 但是Alice和Bob通讯不畅, 想通过Carol中转。可能的方法有:
从Carol往Alice: ssh -R, 从Carol往Bob: ssh -L, 从Alice往Carol: ssh -L, 从Bob往Carol: ssh -R。
有一个要注意的问题是 -L -R 参数开的端口往往只监听localhost, 绑定到外网 IP 可能被禁止,
这时候可以再建一个本地的洞从0.0.0.0:"某个端口"打通到那个本地的洞。

比较新的 ssh 开始带 -D 参数, 可以将 ssh 通道当作 socks4 代理使用。
这个尤其适合连Bob上的ftp。
从Alice通过另一台机器Carol连Bob的ftp碰到的问题是数据连接端口是动态的, 无论 PORT 还是 PASV 模式都需要特殊配置。
比较简单的方法是:
Alice往Carol: ssh -D 3003 端口,
然后配置Alice本地ftp软件使用socks4代理: localhost:3003,
这样ftp软件就可以正常工作了。

这个方法也可以用于浏览有IP限制的网段。
比如从国外无法浏览中国教育网里面的网页, 如果可以用 ssh -D 挂上一台能直连教育网的机器,
那么配置浏览器使用这个 ssh 通道的 socks4 代理就可以了。
另外比如你想下bt但是又想避开米国的耳目, 或者你对某段网路的安全不放心, 也可以用这个办法来方便的加密传输数据,
因为 ssh 通道内传送的数据是加密的。

二、几个特别的例子

例1:
本地端口转发(ssh和连接服务端口的方向一致), 格式: ssh -L "local port":"remote host":"remote port" "SSH hostname"

在Alice上执行:
ssh -L 10389:localhost:389 Bob

        Alice                   ||              Bob
    +-------------------+       ||      +-------------------+
    |  LDAP Client      |       ||      |  LDAP Server      |
    |  Port 10389       |       ||      |  Port 389         |
    |   \               |       ||      |        /          |
    |    \              |       ||      |       /           |
    |     \             |       ||      |      /            |
    |      |            |       ||      |     |             |
    |  ssh client  --->-+---->--++----->+--> ssh server     |
    |                   |       ||      |                   |
    +-------------------+       ||      +-------------------+

这时候Alice通过访问本地的10389实现连到Bob上的389端口.

例2:
远程端口转发(ssh和连接服务端口的方向相反), 格式: ssh -R "local port":"remote host":"remote port" "SSH hostname"

在Bob上执行:
ssh -R 10389:localhost:389 Alice

        Alice                   ||              Bob
    +-------------------+       ||      +-------------------+
    |  LDAP Client      |       ||      |  LDAP Server      |
    |  Port 10389       |       ||      |  Port 389         |
    |   \               |       ||      |        /          |
    |    \              |       ||      |       /           |
    |     \             |       ||      |      /            |
    |      |            |       ||      |     |             |
    |  ssh server  --->-+---->--++----->+--> ssh client     |
    |                   |       ||      |                   |
    +-------------------+       ||      +-------------------+


例3:
多主机转发应用
格式:
    ssh -CfNg -L "local port":"remote host":"remote port" "SSH hostname"
    ssh -CfNg -R "local port":"remote host":"remote port" "SSH hostname"
SSH提供了 GatewayPorts 关键字, "-g "参数以保证机器Alice能够使用机器Carol建立的本地端口转发.

方案1
在Carol上执行:
ssh -CfNg -L 10389:Bob:389 Donna
然后Alice连接Carol的10389端口即可.

        Alice                   ||              Bob
    +-------------------+       ||      +-------------------+
    |  LDAP Client      |       ||      |  LDAP Server      |
    |                   |       ||      |  Port 389         |
    +-------------------+       ||      +-------------------+
           \                    ||           /
            \                   ||          /
       Carol \                  ||         /    Donna
    +-------------------+       ||      +-------------------+
    |  ssh client       |       ||      |  ssh server       |
    |  Port 10389  --->-+---->--++----->+-->                |
    +-------------------+       ||      +-------------------+


方案2
在Donna上执行:
ssh -CfNg -R 10389:Bob:389 Carol
然后Alice连接Carol的10389端口即可.

        Alice              家里 || 公司         Bob
    +-------------------+       ||      +-------------------+
    |  LDAP Client      |       ||      |  LDAP Server      |
    |                   |       ||      |  Port 389         |
    +-------------------+       ||      +-------------------+
           \                    ||           /
            \                   ||          /
       Carol \                  ||         /    Donna
    +-------------------+       ||      +-------------------+
    |  ssh server       |       ||      |  ssh client       |
    |  Port 10389  --->-+---->--++----->+-->                |
    +-------------------+       ||      +-------------------+


例4:
动态端口转发. 格式: ssh -D "local port" 
当我们在一个不安全的 WiFi 环境下上网,用 SSH 动态转发来保护我们的网页浏览及 MSN 信息无疑是十分必要的。

在Alice上执行:
ssh -D 10001 Donna

        Alice                   ||         WEB, MSN
    +-------------------+       ||             ______
    |  Browser          |       ||            (      )
    |  MSN              |       ||           (   ___)
    |                   |       ||          (____)
    |                   |       ||           /
    |                   |       ||          /
    |                   |       ||         /    Donna
    |  ssh slient       |       ||      +-------------------+
    |                   |       ||      |  ssh server       |
    |              --->-+---->--++----->+-->                |
    +-------------------+       ||      +-------------------+

选择了10001作为本地的端口号,其实在这里 SSH 是创建了一个 SOCKS 代理服务.

-D port
 This works by allocating a socket to listen to port on the local
 side, and whenever a connection is made to this port, the con-
 nection is forwarded over the secure channel, and the applica-
 tion protocol is then used to determine where to connect to from
 the remote machine.  Currently the SOCKS4 and SOCKS5 protocols
 are supported, and ssh will act as a SOCKS server.  Only root
 can forward privileged ports.  Dynamic port forwardings can also
 be specified in the configuration file.

例5:
X转发.
在Alice上执行:
ssh -X Bob

        Alice                   ||              Bob
    +-------------------+       ||      +-------------------+
    |  X Server         |       ||      |  X Client         |
    |   \               |       ||      |        /          |
    |    \              |       ||      |       /           |
    |     \             |       ||      |      /            |
    |      |            |       ||      |     |             |
    |  ssh client  --->-+---->--++----->+--> ssh server     |
    |                   |       ||      |                   |
    +-------------------+       ||      +-------------------+