详解三种 SSH 端口转发

平时用 ssh 的端口转发功能也不多,总容易忘记,干脆记下来吧。

参数格式

动态端口转发:

ssh -D <local ip>:<local port> <user>@<remote host>

本地端口转发:

ssh -L <listen port>:<dest host>:<dest port> <user>@<remote host>

远程端口转发:

ssh -R <listen port>:<dest host>:<dest port> <user>@<remote host>

下面举例详解这几种转发。

动态端口转发

ssh -D 1080 user@remotehost

所有由本机1080端口发出的流量将经remotehost上某个端口(动态的,所以叫动态端口转发) 转发出去,此时本机1080端口可用做 socks5 代理。

  • 这里的<local ip>可以省略,比如上面的例子,如省略默认绑定到127.0.0.1::1
  • 也可以使用:1080*:1080或加-g选项,效果一样,都绑定0.0.0.0::
  • 使用 0.0.0.0:1080 则不会绑定::(ipv6)

本地端口转发

sudo ssh -L 443:www.baidu.com.com:443 user@remotehost

所有发往本机443(第一个443)端口的流量都会经remotehost转发至www.baidu.com:443(第二个443) 端口,这时我们在/etc/hosts中添加一行:

127.0.0.1 www.baidu.com

再打开浏览器访问 https://www.baidu.com,你会发现一切正常。

你也可以作如下转发来验证转发是否生效:

sudo ssh -L 80:ip.cn:80 user@remotehost
#绑定本地小于1024(不含1024)的端口需要root权限

再添加 hosts:

127.0.0.1 ip.cn

这时访问 http://ip.cn,就会显示远程主机remotehost的公网 ip 了。

同理,如果你另外还有一台远程主机 remotehost2,作如下转发:

ssh -L 2022:remotehost2:22 user@remotehost

然后就可以在本机上用ssh -p 2022 [email protected]来连接remotehost2上的 ssh 服务了。

以上三个例子中,有很重要的一点,我们访问本地端口时,流量都是经由远程主机remotehost来转发,所以例子中的www.baidu.comip.cnremotehost2都是针对远程主机remotehost而言的,如果换成一个内网 ip,也是远程主机remotehost的内网。
还有一点,默认本地端口都是绑定在127.0.0.1、::1,也就是说只有本机可以访问,可以加上参数-g解除这一限制。

远程端口转发

ssh -R 80:ip.cn:80 root@remotehost
#绑定远程主机上小于1024(不含1024)的端口需要远程主机的root权限

在远程主机remotehost上所有发往其80(第一个80)端口的流量将经由本机转发至ip.cn:80(第二个80)端口。在远程主机remotehost添加如下 hosts:

127.0.0.1 ip.cn

再在远程主机remotehost上访问http://ip.cn,会显示本机的 ip:

curl http://ip.cn

这里与前面的本地端口转发一样,远程主机remotehost上的监听端口同样是绑定在127.0.0.1::1上的,并且-g选项此时无效。

要使监听端口能够绑定到非回环地址,需要在 ssh 服务端配置中启用 GatewayPorts 选项。

实例

假设现在有两台主机 A(host-a) 与 B(host-b),均在各自的内网,另外有一台公网主机 C(host-c),想要在 B 上通过 ssh 连接到 A,可以按下面的步骤操作:

1. 在 A 上执行:

ssh -R 2022:localhost:22 userc@host-c

这里的2022端口可自行选定,参数中的localhost:22指的是 A 的22端口

2. 在 B 上执行:

ssh -L 2022:localhost:2022 userc@host-c

参数中前一个2022是 B 上的端口,localhost:2022则是 C 上的2022端口

3. 在 B 上执行:

ssh -p2022 usera@localhost

这样就可以直接登录到 A 了

流量是这样走的:
sshclient -> B:2022 -> sshtunnel -> C:2022 -> sshtunnel -> A:22

小结

本地端口转发和远程端口转发的参数很类似,都是<listen port>:<dest host>:<dest port>的形式,区别和联系如下:

  • 两种转发第一个参数都是监听端口,中间的主机是目标主机,最后是目标主机的端口
  • -L后的监听端口是本地端口,-R后端监听端口是远程主机的端口
  • 默认情况下,监听端口都绑定到127.0.0.1::1,本地端口转发可以加-g选项绑定到0.0.0.0::
  • 本地端口转发流量经由远程主机转发至目标主机;远程端口转发流量经本地主机转发至目标主机
  • 流量由谁转发则<dest host>就相对谁而言;如果<dest host>localhost,则本地端口转发时指远程主机,远程端口转发时指本地主机

标签: Linux

仅有一条评论

  1. 挺好的。学习到了不少东西。

添加新评论