SSH 协议深度解析:从握手到加密隧道
SSH 这东西,说白了就是远程管理的「安全通道」。我早年做运维时,公司还在用 Telnet,密码明文传输,抓个包就能看到 root 密码。后来换了 SSH,才算是睡了个安稳觉。但你真的了解 SSH 内部是怎么工作的吗?
这一节,我们把它拆开来看。
SSH 的三层架构
SSH 协议分为三层,从上到下依次是:
- 传输层协议:负责服务器认证、密钥交换、数据加密。这是安全的基础。
- 用户认证协议:验证客户端用户的身份。密码、公钥、键盘交互都在这一层。
- 连接协议:将加密通道复用为多个逻辑通道。比如你同时跑 SCP、端口转发、远程命令,都是靠它。
这三层是独立的,但协同工作。我见过有人只改 SSH 端口就觉得安全了,其实连第一层都没搞明白。
密钥交换机制:如何安全地建立信任
SSH 的密钥交换,核心目标是:在不安全的网络上,安全地协商出一个对称加密密钥。
流程大致如下:
- 客户端发起连接,服务器发送自己的主机密钥公钥。
- 双方协商加密算法、MAC 算法、压缩算法等。
- 使用 Diffie-Hellman 算法(或椭圆曲线变体)生成共享密钥。
- 服务器用主机密钥对交换过程中的关键信息签名,客户端验证签名。
- 双方用共享密钥派生会话密钥,后续通信全部加密。
嗯,这里要注意:第一次连接时,客户端会收到服务器的主机密钥指纹。你确认过这个指纹吗?我见过太多人直接输入 yes 跳过验证,结果中间人攻击就进来了。
核心原则:永远不要跳过主机密钥验证。把服务器指纹记录下来,每次连接时比对。
加密算法选择:别用默认配置
SSH 支持多种加密算法,但默认配置往往不是最安全的。我个人习惯,会主动禁用一些老旧算法。
下面这张表,是我常用的算法推荐:
| 算法类型 | 推荐算法 | 应禁用算法 | 说明 |
|---|---|---|---|
| 密钥交换 | curve25519-sha256, diffie-hellman-group-exchange-sha256 | diffie-hellman-group14-sha1, diffie-hellman-group1-sha1 | 椭圆曲线更快更安全,SHA1 已不推荐 |
| 对称加密 | chacha20-poly1305, aes256-gcm | aes128-cbc, 3des-cbc, blowfish-cbc | GCM 模式自带认证,CBC 模式有 padding oracle 风险 |
| MAC 算法 | hmac-sha2-256, hmac-sha2-512 | hmac-sha1, hmac-md5 | SHA1 碰撞攻击已成现实 |
| 主机密钥 | ed25519, rsa-sha2-512 | ssh-rsa (SHA1 签名), dsa | ed25519 性能好,密钥短,推荐优先使用 |
我的经验:在 /etc/ssh/sshd_config 中,用 Ciphers、MACs、KexAlgorithms、HostKeyAlgorithms 四个指令来锁定算法。我曾经帮一家金融客户审计,发现他们还在用 3des-cbc,那台服务器跑了 5 年没重启过……
常见配置优化:让 SSH 既安全又好用
配置优化不是越严越好,还要考虑运维效率。下面是我常用的几项:
- 禁用 root 直接登录:PermitRootLogin no。用普通用户登录,再 su 或 sudo。这是最基本的安全策略。
- 使用密钥认证,禁用密码:PasswordAuthentication no。密码容易被暴力破解,密钥要安全得多。
- 限制登录用户/组:AllowUsers user1 user2 或 AllowGroups sshusers。减少攻击面。
- 修改监听端口:Port 2222。虽然不能真正防住扫描,但能减少日志噪音。
- 启用公钥指纹验证:在客户端配置 StrictHostKeyChecking ask,不要设为 no。
- 设置空闲超时:ClientAliveInterval 300 和 ClientAliveCountMax 2。防止僵尸连接。
警告:修改 SSH 配置前,一定要先开一个备用连接。我曾经在远程服务器上改了配置,结果把自己锁在外面,最后只能让机房同事帮忙重启……嗯,从那以后我改配置前都会先开两个会话。
SSH 密钥交换与加密流程全景图
下面这张图,展示了 SSH 从建立连接到加密通信的完整流程:
实战:SSH 配置文件示例
下面是我个人常用的 sshd_config 安全配置片段。你可以直接参考:
# /etc/ssh/sshd_config 安全加固片段
# 端口和监听
Port 2222
ListenAddress 0.0.0.0
# 认证方式
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
# 密钥算法
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
# 加密算法
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512,hmac-sha2-256
KexAlgorithms curve25519-sha256,diffie-hellman-group-exchange-sha256
# 用户限制
AllowUsers admin devops
AllowGroups sshusers
# 连接控制
ClientAliveInterval 300
ClientAliveCountMax 2
MaxAuthTries 3
MaxSessions 10
# 日志
LogLevel VERBOSE
小技巧:配置改完后,先执行 sshd -t 检查语法,再重启服务。我习惯用 systemctl reload sshd 而不是 restart,这样不会中断现有连接。
避坑指南:我踩过的 SSH 坑
做安全这么多年,SSH 相关的坑没少踩。分享几个典型的:
- 密钥权限问题:私钥文件权限必须是 600,公钥可以是 644。我曾经把私钥设成 644,SSH 直接拒绝使用,排查了半天。
- authorized_keys 文件权限:这个文件以及父目录 ~/.ssh 的权限都不能太宽松。~/.ssh 应该是 700,authorized_keys 是 600。否则 SSH 会忽略这个文件。
- 算法降级攻击:如果服务器同时支持弱算法,攻击者可以强制协商到弱算法。所以一定要显式禁用不安全的算法。
- 主机密钥变更:服务器重装后主机密钥会变,客户端会报错。这时候要确认不是中间人攻击,再手动清除旧的 known_hosts 记录。
嗯,SSH 这东西,配置好了可以很安全,配置不好就是个筛子。希望这一节能帮你把 SSH 的底裤看透。