SSH端口转发的坑

连祈
2024-11-05 / 0 评论 / 94 阅读 / 正在检测是否收录...

端口转发分为本地端口转发、远程端口转发、动态端口转发、
本地端口转发是把远程的端口拿到内部来,感觉没啥用。
远程端口转发等效于反向代理,把内网的端口拿到公网去。
动态端口转发我暂时还没用到。

其中我遇到的问题是 配置了ssh远程端口转发后无法公网访问
后来发现是因为我没在远程主机的ssh设置里打开允许外网访问

#/etc/ssh/sshd_config

AllowTcpForwarding yes#允许用户通过 SSH 创建 TCP 转发连接,这可以用于实现端口转发。禁用此功能(设置为 no)将阻止任何类型的 TCP 转发,包括本地、远程和动态转发。默认为YES
GatewayPorts no#控制是否允许远程主机通过 SSH 连接到转发的端口。默认为no
TCPKeepAlive yes#当设置为 yes 时,TCP 会话将在指定时间内发送心跳包,以确保连接处于活动状态。这有助于在网络不稳定时防止连接意外中断。
ClientAliveInterval 60#设置客户端存活检测的间隔时间。该参数指定 SSH 服务器在等待多长时间后向客户端发送存活消息(心跳)。在此示例中,服务器每 60 秒向客户端发送一次请求,以确认客户端仍然在线。
ClientAliveCountMax 1440#设置客户端存活检测的最大失败次数。该参数指定 SSH 服务器在终止连接之前,允许连续未响应的存活消息的最大次数。在此示例中,如果客户端在 1440 次存活消息中未响应,服务器将关闭与客户端的连接。

可算把我好一顿折腾。
详细参考可见 SSH端口转发




SSH 端口转发又称为 SSH 隧道,是通过 SSH 协议建立隧道,实现本地主机和远程主机的端口绑定,数据由 SSH 协议进行加密传输。

SSH 有三种端口转发模式:

本地端口转发(Local port forwarding);
远程端口转发(Remote port forwarding);
动态端口转发;
本文介绍 SSH 的这三种端口转发和持久化工具 autossh。

本地端口转发
SSH 绑定本地端口,将本地端口的访问转发到远端。使用 -L 参数,格式为 本地端口:目标主机:目标主机端口。

假设本地主机为 host1,host1 能够访问 host2, host2 能够访问 host3,但 host1 无法直接访问 host3。

在 host1 上执行:

ssh -L 8888:host3:8000 host2
表示绑定本地 8888 端口,该端口的访问流量会由 host2 转发至 host3:8000 端口。

在 host1 上执行:

1
ssh -L 8888:localhost:8000 host2
表示绑定本地 8888 端口,该端口的访问流量会转发至 host2:8000 端口。注意目标主机的 localhost 指的是目标主机本身。

本地端口默认绑定到 localhost,只能本地访问,若要可以外网访问(绑定 0.0.0.0),可以写成:

ssh -L :8888:host3:8000 host2
远程端口转发
SSH 绑定远程端口,将远程端口的访问转发到本地。使用 -R 参数,格式为 远程主机端口:目标主机:目标主机端口。

SSH 远程端口转发非常适合用来做内网穿透。假如 host1 是公网主机,host2 是内网主机且能够访问公网,host3 是内网主机不能访问公网,但 host2 可以访问 host3。如果要从 host1 访问 host3,可以用 host2 中转。

在 host2 上执行:
ssh -R 8888:host3:8000 host1
表示绑定 host1 的 8888 端口,该端口的访问流量会由 host2 转发至 host3:8000 端口。
在 host2 上执行:

ssh -R 8888:localhost:8000 host1
表示绑定 host1 的 8888 端口,该端口的访问流量会转发至 host2:8000 端口,注意目标主机的 localhost 指的是本地主机(发起 SSH 连接的主机)。

远程端口也是默认绑定到 localhost,若要外网访问(绑定 0.0.0.0),需要修改远程主机的 /etc/ssh/sshd_config 配置:

GatewayPorts yes
记得重启 sshd 服务:

systemctl restart sshd
动态端口转发
上述两种端口转发都是固定端口对固定端口的转发。动态端口转发不必指定端口号,可以将本地任意端口的流量转发到 SSH 远端。

动态端口转发使用 -D 参数,参数为 绑定地址:绑定本地端口。SSH 会启动一个 SOCKS 服务器监听该地址和端口,当使用该端口作为 SOCKS 代理时,请求的流量会被转发到远端。

例如在 host1 上执行

ssh -D 8000 host2
则在 host1 的 Firefox 中指定 localhost:8000 作为 socks 代理时,可以直接访问 host2 能够访问的主机和端口。

SSH 的其他参数
-N 只连接远程主机,不打开远程 shell;
-T 不为这个连接分配 TTY;
这两个参数可以一起使用,代表这个 SSH 连接只用来传输数据,不执行远程操作。

-f 表示 SSH 连接成功后,转入后台运行。
autossh
SSH 连接可能会意外断开或 hang 住,用进程监控工具,并不能有效检测到 hang 住的情况,autossh 就是为了解决这个问题。

autossh 会启动一个 SSH 进程,并实现一个端口转发循环,当发现进程死掉或者端口转发循环的流量停止时,会重启 SSH 进程,有效避免了 hang 住导致 SSH 端口转发不可用的情况。

安装:

sudo apt install autossh
autossh 命令的参数除了 -M 参数(用于手动指定端口转发循环的端口)外,其他参数与 ssh 命令相同,并会把这些参数传递给监视的 SSH 进程。

所以一个稳定的 SSH 远程端口转发的命令可以是:

sh -NT -R 8888:localhost:8000 host1
可以将 autossh 与 supervisor 等进程管理工具配合使用,建立长期稳定的 SSH 端口转发。

0

评论 (0)

取消