从去年底开始,使用 SSH 协议连接校外的云服务器就出现了卡死的现象,同时使用 SSH 从 Github 上同步代码也受到影响,而一旦切换到移动数据网络一切又变得正常。今天想解决一下这个问题。
现象
SSH 连接本博客进行测试,使用 -v
参数显示详情:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 $ > ssh -v sunnysab.cn INT ✘ 43s OpenSSH_8.9p1, OpenSSL 1.1.1m 14 Dec 2021 debug1: Reading configuration data /etc/ssh/ssh_config debug1: Connecting to sunnysab.cn [106.15.182.107] port 22. debug1: Connection established. debug1: identity file /home/sunnysab/.ssh/id_rsa type 0 debug1: identity file /home/sunnysab/.ssh/id_rsa-cert type -1 debug1: identity file /home/sunnysab/.ssh/id_ecdsa type -1 debug1: identity file /home/sunnysab/.ssh/id_ecdsa-cert type -1 debug1: identity file /home/sunnysab/.ssh/id_ecdsa_sk type -1 debug1: identity file /home/sunnysab/.ssh/id_ecdsa_sk-cert type -1 debug1: identity file /home/sunnysab/.ssh/id_ed25519 type -1 debug1: identity file /home/sunnysab/.ssh/id_ed25519-cert type -1 debug1: identity file /home/sunnysab/.ssh/id_ed25519_sk type -1 debug1: identity file /home/sunnysab/.ssh/id_ed25519_sk-cert type -1 debug1: identity file /home/sunnysab/.ssh/id_xmss type -1 debug1: identity file /home/sunnysab/.ssh/id_xmss-cert type -1 debug1: identity file /home/sunnysab/.ssh/id_dsa type -1 debug1: identity file /home/sunnysab/.ssh/id_dsa-cert type -1 debug1: Local version string SSH-2.0-OpenSSH_8.9 debug1: Remote protocol version 2.0, remote software version OpenSSH_8.2p1 Ubuntu-4ubuntu0.4 debug1: compat_banner: match: OpenSSH_8.2p1 Ubuntu-4ubuntu0.4 pat OpenSSH* compat 0x04000000 debug1: Authenticating to sunnysab.cn:22 as 'sunnysab' debug1: load_hostkeys: fopen /home/sunnysab/.ssh/known_hosts2: No such file or directory debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: algorithm: curve25519-sha256 debug1: kex: host key algorithm: ssh-ed25519 debug1: kex: server->client cipher: aes128-ctr MAC: hmac-sha1 compression: none debug1: kex: client->server cipher: aes128-ctr MAC: hmac-sha1 compression: none debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
主流的方案是修改 MTU 的值,但是经过测试发现无效果。同时使用 Wireshark 抓包发现双方在协商加密算法时的数据包大小在 1000 字节以下,初步判断和 MTU 的值无关。
切换客户端尝试:
OpenSSH(Windows)
OpenSSH(Linux)
MoTTY(MobaXTerm)
JSCH-0.1(FinalShell)
FAILED
FAILED
PASSED
PASSED
看来只有 OpenSSH 客户端存在这个问题。切换端口尝试,发现将 SSH 端口修改后连接正常。
找到问题
联系信息化技术中心,他们在记录里找到了原因:
也就是说,防火墙对端口为 22 的 SSH 包判断了特征,暂且不说针对特定端口的这种策略是否有效,该漏洞是2000年左右、针对 SSHv1 协议抛出的,而现在早已是 SSHv2 的天下。我表示希望他们删除该规则,但以“场景过于少见”为由被拒绝。想想也是,直接用 OpenSSH Client 的用户还是很少的,但这种解决问题的态度实在让人寒心。
解决方案
自己的服务器可以更改 SSH 端口解决,但是通过 SSH 方式连接到 Github 受到了严重影响。想到了如下三种方案:
SSH 使用代理,但是会影响速度。本来直连挺快的。
使用其他 ssh 客户端代替默认的 OpenSSH client。
通过 Wireshark 对几个客户端的 SSH 数据抓包,发现它们使用的加密算法不一样。或许 curve25519-sha256
加密后的数据触发了防火墙的特征库?那么是否可以尝试替换默认的加密算法避免匹配上防火墙特征?
限于时间和精力,没有继续研究下去,通过代理的方式解决了。修改 /etc/ssh/ssh_config
,在最下方添加代码:
1 2 Host github.com ProxyCommand nc -X 5 -x 127.0.0.1:7890 %h %p
指示 ssh 在创建连接时,使用 netcat ,通过 127.0.0.1:7890
创建到主机 %h (端口 %p)的连接。由于我使用的是 Manjaro,还有一个小坑:
1 2 3 4 5 6 7 8 $ pacman -Ss netcat extra/gnu-netcat 0.7.1-8 GNU rewrite of netcat, the network piping application community/openbsd-netcat 1.218_2-1 [已安装] TCP/IP swiss army knife. OpenBSD variant. community/websocat 1.9.0-1 Command-line client for web sockets, like netcat/curl/socat for ws://
gnu-netcat
版本的 nc
命令不支持 -X
等参数,需要下载 openbsd-netcat
包。
1 $ sudo pacman -S openbsd-netcat
再执行即可:
1 2 3 $ ssh -T git@github.com Hi sunnysab! You've successfully authenticated, but GitHub does not provide shell access.
以上。