安全远程管理的核心:密钥认证、配置加固与跳板机
SSH(Secure Shell)是系统管理员的命脉,也是攻击者的首要目标。全球每天有数百万次SSH暴力破解尝试。正确配置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
| 类型 | 密钥长度 | 安全性 | 性能 | 推荐 |
|---|---|---|---|---|
| Ed25519 | 256-bit | 🟢 极高 | 🟢 极快 | ✅ 首选 |
| ECDSA-P521 | 521-bit | 🟢 高 | 🟡 快 | ⚠️ 备选 |
| RSA-4096 | 4096-bit | 🟢 高 | 🔴 慢 | ⚠️ 兼容用 |
| RSA-2048 | 2048-bit | 🟡 可接受 | 🟡 中等 | ❌ 不推荐 |
| DSA | 1024-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
# /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
# 启动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跳板机(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配置
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
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