SSH 协议建立过程

  1. TCP 连接
    客户端连接服务器 22 端口。

  2. 版本交换(明文)
    双方互发 SSH 协议版本,如 SSH-2.0-OpenSSH_9.9。

  3. 算法协商(明文)
    双方各自发送 SSH_MSG_KEXINIT,列出支持的:

    • 密钥交换算法 KEX
    • 主机密钥算法
    • 对称加密算法
    • MAC 算法
      双方协商出一组共同支持的算法。
  4. 密钥交换(临时密钥)
    客户端生成临时密钥对 (a, A),发送 A。
    服务器生成临时密钥对 (b, B),发送 B。
    双方各自计算共享秘密:
    客户端:K = a * B
    服务器:K = b * A
    两者得到相同的 K。
    临时私钥不发送,用完即弃。

  5. 交换哈希与服务器签名(长期主机密钥)
    双方计算:
    H = hash(V_C, V_S, I_C, I_S, K_S, A, B, K)
    其中 K_S 是服务器长期主机公钥。
    服务器用长期主机私钥对 H 签名,发送签名。
    客户端用 known_hosts 中的服务器主机公钥验签。
    验签通过 → 确认服务器身份,且交换内容未被篡改。
    验签失败 → 中断连接,提示主机密钥变更或中间人攻击。

  6. 派生会话密钥(本地计算,不发送)
    双方各自执行:
    会话密钥 = KDF(K, H, 会话ID, 标签, 长度)
    派生出的密钥双向独立:

    • 客户端到服务器:加密密钥、IV、MAC 密钥
    • 服务器到客户端:加密密钥、IV、MAC 密钥
      这些会话密钥是临时的。
  7. SSH_MSG_NEWKEYS
    双方各自发送 SSH_MSG_NEWKEYS,通知对方准备切换。
    之后所有消息都用新会话密钥加密和完整性保护。

  8. 用户认证(加密通道内)

    • 公钥认证:用户用长期私钥签名,服务器用 authorized_keys 中的公钥验签。
    • 密码认证:密码在加密通道内发送。
      用户密钥只用于认证,不参与会话密钥派生。
  9. 连接层与数据传输
    建立多个通道:shell、SFTP、端口转发等。
    数据用对称加密保护,并用 MAC/AEAD 保证完整性。

  10. 重密钥
    达到数据量或时间阈值后,重新执行密钥交换,派生新会话密钥。

  11. 连接关闭
    发送 SSH_MSG_DISCONNECT,销毁临时密钥和会话密钥,关闭 TCP。

ssh本身的加固

# /etc/ssh/sshd_config

Port 22222 # SSH 监听端口
AddressFamily inet # 使用 IPv4;inet6 为 IPv6,any 为两者都可用
ListenAddress 0.0.0.0 # 监听所有 IPv4 地址;服务器多 IP 时可指定具体 IP

PermitRootLogin no # 禁止 root 通过 SSH 直接登录
PubkeyAuthentication yes # 启用密钥登录
PasswordAuthentication no # 禁用密码登录
PermitEmptyPasswords no # 禁止空密码登录
KbdInteractiveAuthentication no # 禁用键盘交互认证(可能含密码、OTP、2FA)
# ChallengeResponseAuthentication no # 旧版 OpenSSH 的旧名字
UsePAM yes # 使用 PAM 做账户检查、会话管理;纯密钥登录通常保留

MaxAuthTries 3 # 每次连接最大认证尝试次数
LoginGraceTime 60 # 认证阶段的宽限期,超时断开
ClientAliveInterval 300 # 每 300 秒发送一次保活探测
ClientAliveCountMax 2 # 连续 2 次无响应则断开,总计约 10 分钟

AllowGroups ssh-users # 只允许 ssh-users 组登录
# AllowUsers admin ops # 也可以直接指定允许的用户

X11Forwarding no # 禁止 X11 图形界面转发
AllowAgentForwarding no # 禁止 SSH 代理转发,防止远程偷用本地密钥
AllowTcpForwarding no # 禁止 TCP 端口转发(ssh -L / -R / -D 失效)
PermitTunnel no # 禁止 tun/tap 隧道设备
GatewayPorts no # 远程转发只绑定回环地址,不暴露到所有接口

LogLevel VERBOSE # 日志级别,记录更详细的登录、认证、密钥指纹信息

一些细碎内容还可以扩展
KbdInteractiveAuthentication 即键盘交互认证 在前面的ssh协议分析时候也写过 ssh在认证时会有两种选择 一种是密钥登陆一种就是键盘认证 这里的键盘认证不知局限于密码登录 其实还有2FA等等 一般作为仅允许密钥登陆的附属设置
GatewayPorts 控制远程转发端口绑定到哪个地址 与之对应的是转发到本地

  • no:只绑定到回环地址(默认,最安全)。
  • yes:绑定到通配地址,所有接口。
  • clientspecified:由客户端指定绑定地址。
    loglevel很明显就是日志记录等级
    LogLevel 可选值从少到多大致是:
等级 含义
QUIET 几乎不记录
FATAL 只记录致命错误
ERROR 只记录错误
INFO 默认,记录常规信息
VERBOSE 更详细,记录登录、认证、密钥指纹等
DEBUG / DEBUG1 调试级别,信息很多
DEBUG2 更详细
DEBUG3 最详细,日志量极大
加固也可以通过防火墙来限制 这里使用麒麟自带的

国产化的替代即用

阶段 国际算法 国密算法
版本交换 明文 明文
算法协商 curve25519、ed25519、aes、hmac-sha2 sm2-sm3、sm2、sm4-ctr、hmac-sm3
密钥交换 ECDH / DH SM2 密钥交换
交换哈希 SHA-256 SM3
服务器签名 Ed25519 / RSA SM2 签名
客户端验签 known_hosts 中国际公钥 known_hosts 中 SM2 公钥
KDF 基于 SHA-256 基于 SM3
会话加密 AES / ChaCha20 SM4
完整性 HMAC-SHA256 / Poly1305 HMAC-SM3
用户认证 Ed25519 / RSA SM2
重密钥 重新 ECDH/DH 重新 SM2 密钥交换

流程不变,信任模型不变:临时密钥负责机密性和前向保密,长期密钥负责身份验证和防中间人。国密改造只是把算法套件从国际标准替换为国产商用密码标准。