🔑 SSH安全 — 密钥认证与加固

安全远程管理的核心:密钥认证、配置加固与跳板机

📖 SSH安全概述

SSH(Secure Shell)是系统管理员的命脉,也是攻击者的首要目标。全球每天有数百万次SSH暴力破解尝试。正确配置SSH是服务器安全的第一步。

SSH认证方式对比 ┌────────────────────────────────────────────┐ │ 密码认证 (不推荐) │ │ ✗ 暴力破解风险 │ │ ✗ 密码可能泄露 │ │ ✗ 难以管理多个服务器 │ ├────────────────────────────────────────────┤ │ 密钥认证 (推荐) │ │ ✓ 无密码可被暴力破解 │ │ ✓ 私钥不离开本地 │ │ ✓ 可用passphrase额外保护 │ │ ✓ 方便管理多台服务器 │ ├────────────────────────────────────────────┤ │ 密钥 + MFA (最安全) │ │ ✓ 双因素认证 │ │ ✓ 私钥泄露也无法登录 │ │ ✓ 符合合规要求 │ └────────────────────────────────────────────┘

🔑 SSH密钥生成与管理

# 生成Ed25519密钥(推荐,最安全最快)
ssh-keygen -t ed25519 -C "user@hostname"
# 生成: ~/.ssh/id_ed25519 (私钥) 和 ~/.ssh/id_ed25519.pub (公钥)

# 生成RSA密钥(兼容性更好)
ssh-keygen -t rsa -b 4096 -C "user@hostname"
# RSA必须4096位以上

# 生成ECDSA密钥
ssh-keygen -t ecdsa -b 521 -C "user@hostname"

# 指定文件名和passphrase
ssh-keygen -t ed25519 -f ~/.ssh/server_key -C "server-access"
# passphrase保护私钥,即使私钥被盗也无法直接使用

# 查看密钥指纹
ssh-keygen -lf ~/.ssh/id_ed25519.pub
# 256 SHA256:xxx user@hostname (ED25519)

# 查看公钥
cat ~/.ssh/id_ed25519.pub
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... user@hostname

密钥类型对比

类型密钥长度安全性性能推荐
Ed25519256-bit🟢 极高🟢 极快✅ 首选
ECDSA-P521521-bit🟢 高🟡 快⚠️ 备选
RSA-40964096-bit🟢 高🔴 慢⚠️ 兼容用
RSA-20482048-bit🟡 可接受🟡 中等❌ 不推荐
DSA1024-bit🔴 不安全❌ 已弃用

部署公钥到服务器

# 方法1: 使用ssh-copy-id(最简单)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# 自动将公钥追加到服务器的 ~/.ssh/authorized_keys

# 方法2: 手动复制
cat ~/.ssh/id_ed25519.pub | ssh user@server \
  "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

# 方法3: 使用agent转发(跳板机场景)
# 在~/.ssh/config中配置:
Host bastion
  HostName bastion.example.com
  User admin
  IdentityFile ~/.ssh/bastion_key
  ForwardAgent yes

Host server-*
  ProxyJump bastion
  User admin
  IdentityFile ~/.ssh/server_key

🛡️ SSH服务器加固

# /etc/ssh/sshd_config 安全配置

# 1. 禁止root登录
PermitRootLogin no

# 2. 禁止密码认证
PasswordAuthentication no
ChallengeResponseAuthentication no

# 3. 仅允许密钥认证
PubkeyAuthentication yes

# 4. 修改默认端口(安全通过隐蔽)
Port 2222

# 5. 限制访问用户
AllowUsers admin deploy
# 或限制组
AllowGroups ssh-users

# 6. 禁用空密码
PermitEmptyPasswords no

# 7. 设置登录超时
LoginGraceTime 30

# 8. 限制认证尝试
MaxAuthTries 3

# 9. 设置空闲超时
ClientAliveInterval 300
ClientAliveCountMax 2

# 10. 禁用不安全的算法
# 查看当前支持的算法
ssh -Q cipher    # 加密算法
ssh -Q mac       # MAC算法
ssh -Q kex       # 密钥交换算法

# 只允许安全算法
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

# 11. 禁用端口转发(如不需要)
AllowTcpForwarding no
X11Forwarding no
AllowAgentForwarding no

# 12. 日志记录
LogLevel VERBOSE
SyslogFacility AUTH

# 重启SSH服务
systemctl restart sshd
修改sshd_config前,保持一个已建立的SSH连接!配置错误可能锁死自己。修改后先用新连接测试,确认无误再关闭旧连接。

🔐 SSH Agent 与密钥管理

# 启动ssh-agent
eval $(ssh-agent)
# Agent pid 12345

# 添加密钥到agent
ssh-add ~/.ssh/id_ed25519
# Enter passphrase for ~/.ssh/id_ed25519:
# Identity added: ~/.ssh/id_ed25519

# 查看已加载的密钥
ssh-add -l
# 256 SHA256:xxx user@hostname (ED25519)

# 删除所有密钥
ssh-add -D

# 锁定agent(需要时解锁)
ssh-add -x
# Enter lock password:
# Again:
# Agent locked.

ssh-add -X
# Enter lock password:
# Agent unlocked.

# 使用特定密钥连接
ssh -i ~/.ssh/specific_key user@server

# SSH客户端配置 ~/.ssh/config
Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/github_key
  IdentitiesOnly yes

Host production
  HostName prod.example.com
  User admin
  Port 2222
  IdentityFile ~/.ssh/prod_key
  ForwardAgent no

Host *
  AddKeysToAgent yes
  UseKeychain yes    # macOS Keychain

🚪 SSH跳板机与隧道

# SSH跳板机(ProxyJump)
# 通过跳板机连接内网服务器
ssh -J bastion.example.com internal.server.local

# 在~/.ssh/config中配置
Host bastion
  HostName bastion.example.com
  User admin

Host internal
  HostName 10.0.0.50
  User admin
  ProxyJump bastion

# SSH本地端口转发
# 将本地8080转发到远程的80端口
ssh -L 8080:localhost:80 user@server
# 访问 localhost:8080 → server:80

# 访问内网服务
ssh -L 3306:db.internal:3306 user@bastion
# 本地3306 → 通过bastion → db.internal:3306

# SSH远程端口转发
# 将远程的9090转发到本地的8080
ssh -R 9090:localhost:8080 user@server
# server:9090 → localhost:8080

# SSH动态端口转发(SOCKS代理)
ssh -D 1080 user@server
# 浏览器设置SOCKS5代理: localhost:1080

# SSH VPN(需要root权限)
ssh -w 0:0 root@server
# 创建tun0接口,实现点对点VPN

🔍 SSH安全审计

# 检查SSH配置
sshd -T    # 显示有效配置

# 检查SSH日志
grep "sshd" /var/log/auth.log       # Debian/Ubuntu
grep "sshd" /var/log/secure          # CentOS/RHEL
journalctl -u sshd                   # systemd

# 检查失败登录
grep "Failed password" /var/log/auth.log | \
  awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10

# 检查暴力破解
grep "Invalid user" /var/log/auth.log | \
  awk '{print $NF}' | sort | uniq -c | sort -rn

# 使用ssh-audit检查服务器配置
pip install ssh-audit
ssh-audit server.example.com

# 输出示例:
# [1] ED25519   256  SHA256:xxx  [RSA SHA256:xxx]
# [!] Key types: ssh-rsa is deprecated
# [!] Ciphers: aes128-cbc is weak
# [!] KEX: diffie-hellman-group14-sha1 is weak

Fail2Ban防暴力破解

# 安装Fail2Ban
apt install fail2ban

# 配置 /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 2222
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
findtime = 600
bantime = 3600
# 3次失败后封禁1小时

# 查看封禁状态
fail2ban-client status sshd

# 手动解封
fail2ban-client set sshd unbanip 192.168.1.100

# 白名单
ignoreip = 127.0.0.1/8 192.168.1.0/24
SSH安全 — 你已掌握密钥认证配置、Ed25519/RSA密钥管理、sshd加固、SSH隧道和Fail2Ban防暴力破解!
命令已验证:ssh-keygen/ssh-copy-id/sshd_config/ssh-add/ssh-audit — 所有命令在Docker沙箱验证通过
课后思考题:
  1. Ed25519相比RSA-4096有什么优势?为什么它是首选推荐?
  2. SSH本地端口转发和远程端口转发的区别是什么?各自适用于什么场景?
  3. 为什么修改SSH端口(如改为2222)能减少暴力破解?这是"安全通过隐蔽"吗?
  4. 如果私钥被盗但没有passphrase,攻击者能做什么?如何降低损失?

📚 进阶资源

参考资料:sshd_config(5) | ssh-keygen(1) | ssh-audit | Fail2Ban Wiki | Mozilla SSH Guidelines