概述

SSH(Secure Shell)是 Linux 运维的核心通道,也是攻击者的主要目标。一个配置不当的 SSH 服务可能导致服务器被完全接管。从认证机制、服务端硬化、跳板机架构、隧道技术、审计日志到暴力破解防护,全面覆盖 SSH 安全的好的实践。

密钥认证

生成密钥对

# 生成 Ed25519 密钥(推荐)
$ ssh-keygen -t ed25519 -C "admin@sre.wang" -f ~/.ssh/id_ed25519

# 生成 RSA 密钥(兼容性需求,至少 4096 位)
$ ssh-keygen -t rsa -b 4096 -C "admin@sre.wang" -f ~/.ssh/id_rsa

# 生成带密码保护的密钥
$ ssh-keygen -t ed25519 -N "strong-passphrase" -f ~/.ssh/id_ed25519

# 查看密钥指纹
$ ssh-keygen -lf ~/.ssh/id_ed25519.pub
256 SHA256:abc123... admin@sre.wang (ED25519)

密钥算法对比

算法密钥长度安全性性能推荐
Ed25519256 位极高极快首选
RSA-40964096 位兼容场景
RSA-20482048 位不推荐
ECDSA256/384/521有争议(NIST 曲线)
DSA1024 位-已废弃

部署公钥

# 方式 1:ssh-copy-id(推荐)
$ ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server

# 方式 2:手动部署
$ cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# 方式 3:批量部署
$ for host in web-{01..10}; do
    ssh-copy-id -i ~/.ssh/id_ed25519.pub admin@$host
done

authorized_keys 权限控制

# 正确权限
~/.ssh/           → 700
~/.ssh/authorized_keys → 600
私钥文件          → 600

# authorized_keys 中可限制公钥的权限
# 限制来源 IP
from="10.0.0.0/8" ssh-ed25519 AAAAC3... admin@sre.wang

# 限制命令
command="/usr/bin/rsync --server" ssh-ed25519 AAAAC3... backup@sre.wang

# 限制端口转发
no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAAC3... user@sre.wang

# 组合限制
from="10.0.0.0/8",command="/usr/bin/backup.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAAC3... backup@sre.wang

证书认证

传统密钥认证的问题

  • 每台服务器需要部署用户的公钥
  • 密钥撤销困难(需要逐台删除)
  • 无法设置密钥有效期
  • 密钥管理缺乏审计

SSH 证书认证架构

                    [CA 私钥]
                   /          \
          [签发用户证书]    [签发主机证书]
               |                  |
        [用户持有证书]    [服务器配置可信CA]
               |                  |
          [SSH 连接] → [服务器验证证书签名] → [登录成功]

搭建 SSH CA

# 1. 在 CA 服务器上生成 CA 密钥对
$ ssh-keygen -t ed25519 -f ~/.ssh/ca_user_key -C "SSH User CA"
# 不要设置 passphrase(自动化签发需要)

# 2. 签发用户证书
$ ssh-keygen -s ~/.ssh/ca_user_key \
    -I "admin_user" \
    -n admin,root \
    -V +1d \
    ~/.ssh/id_ed25519.pub
# -I: 证书标识(用于审计)
# -n: 允许登录的用户名
# -V: 有效期(+1d = 1 天)

# 生成证书文件: ~/.ssh/id_ed25519-cert.pub

# 3. 在目标服务器配置信任 CA
$ cat ~/.ssh/ca_user_key.pub >> /etc/ssh/user_ca.pub
# 在 /etc/ssh/sshd_config 中添加:
# TrustedUserCAKeys /etc/ssh/user_ca.pub

# 4. 重启 sshd
$ systemctl restart sshd

主机证书(免 known_hosts 确认)

# 1. 在服务器上生成主机密钥对(如果没有)
$ ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""

# 2. 用 CA 签发主机证书
$ ssh-keygen -s ~/.ssh/ca_user_key \
    -I "web01.sre.wang" \
    -h \
    -n web01.sre.wang,web01 \
    -V +52w \
    /etc/ssh/ssh_host_ed25519_key.pub

# 3. 配置 sshd 使用主机证书
# /etc/ssh/sshd_config
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub

# 4. 客户端配置信任 CA
# ~/.ssh/known_hosts 或 /etc/ssh/ssh_known_hosts
@cert-authority *.sre.wang ssh-ed25519 AAAAC3...

证书撤销

# 创建撤销列表
$ cat > /etc/ssh/revoked_keys << 'EOF'
ssh-ed25519 AAAAC3... revoked-key-1
ssh-ed25519 AAAAC3... revoked-key-2
EOF

# 在 sshd_config 中配置
RevokedKeys /etc/ssh/revoked_keys

# 或使用 KRL(Key Revocation List)
$ ssh-keygen -k -f revoked_krl -s ~/.ssh/ca_user_key ~/.ssh/id_ed25519.pub
# 在 sshd_config 中配置
RevokedKeys /etc/ssh/revoked_krl

sshd_config 硬化

安全基线配置

# /etc/ssh/sshd_config

# === 协议与加密 ===
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
# 禁用弱密钥
# HostKey /etc/ssh/ssh_host_rsa_key
# HostKey /etc/ssh/ssh_host_ecdsa_key

# 加密算法(仅允许强算法)
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
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman16-sha512

# === 认证 ===
PermitRootLogin no              # 禁止 root 直接登录
PasswordAuthentication no       # 禁用密码认证
KbdInteractiveAuthentication no # 禁用键盘交互认证
ChallengeResponseAuthentication no
PubkeyAuthentication yes        # 启用密钥认证
PermitEmptyPasswords no         # 禁止空密码

# CA 证书认证
TrustedUserCAKeys /etc/ssh/user_ca.pub

# === 访问控制 ===
AllowUsers admin deploy         # 白名单用户
AllowGroups ssh-users           # 白名单用户组
DenyUsers nobody guest          # 黑名单用户

# 来源限制(通过 Match)
Match Address 10.0.0.0/8
    AllowUsers admin root
    PermitRootLogin yes

# === 会话控制 ===
MaxAuthTries 3                  # 最大认证尝试次数
MaxSessions 10                  # 最大会话数
MaxStartups 10:30:60            # 并发未认证连接限制
LoginGraceTime 30               # 认证超时(秒)

# === 超时设置 ===
ClientAliveInterval 300         # 活跃检查间隔(秒)
ClientAliveCountMax 2           # 最多检查次数
# 300 × 2 = 600 秒后断开空闲连接

# === 日志 ===
LogLevel VERBOSE                # 详细日志
SyslogFacility AUTHPRIV
PrintMotd no                    # 不打印 MOTD
PrintLastLog yes                # 显示上次登录时间

# === 转发 ===
AllowTcpForwarding yes          # 根据需求配置
X11Forwarding no                # 禁用 X11 转发
AllowAgentForwarding no         # 禁用 Agent 转发
PermitTunnel no                 # 禁用隧道

# === 其他 ===
UseDNS no                       # 禁用 DNS 反查(加速登录)
GSSAPIAuthentication no         # 禁用 GSSAPI(加速登录)
Banner /etc/ssh/banner          # 登录前提示

配置验证与重载

# 验证配置语法(重要!)
$ sshd -t

# 重载配置(不断开现有连接)
$ systemctl reload sshd
# 或
$ systemctl reload ssh

# 验证当前生效配置
$ sshd -T | grep -E "permitroot|passwordauth|maxauth"

安全操作流程:修改 sshd_config 后,务必保持当前 SSH 会话不断开,另开一个终端测试新配置是否可以正常登录。如果配置有误,可以用原会话恢复。

各参数安全影响

参数默认值安全值风险说明
PermitRootLoginyesnoroot 直接登录被攻破即获最高权限
PasswordAuthenticationyesno密码可被暴力破解
MaxAuthTries63降低暴力破解窗口
ClientAliveInterval0300空闲连接被劫持
X11ForwardingyesnoX11 协议有安全漏洞
AllowTcpForwardingyes按需可用于构建隧道绕过防火墙
UseDNSyesnoDNS 反查延迟 + DNS 欺骗风险

SSH 跳板机

跳板机架构

[运维人员] → [跳板机/Bastion] → [内网服务器]
     SSH          SSH
  (公网可达)    (仅内网可达)

ProxyJump 方式(推荐)

# ~/.ssh/config
Host bastion
    HostName bastion.sre.wang
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host web-*
    User deploy
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump bastion          # 通过跳板机连接
    # 或使用旧语法
    # ProxyCommand ssh -W %h:%p bastion

Host web-01
    HostName 10.0.1.10
Host web-02
    HostName 10.0.1.11
Host web-03
    HostName 10.0.1.12

# 使用:直接连接内网服务器
$ ssh web-01
# 实际路径: 运维人员 → bastion → web-01

多级跳板

# ~/.ssh/config
Host bastion-1
    HostName bastion1.sre.wang
    User admin

Host bastion-2
    HostName 10.0.0.2
    User admin
    ProxyJump bastion-1       # 通过第一级跳板

Host internal-db
    HostName 192.168.1.100
    User dba
    ProxyJump bastion-2       # 通过第二级跳板

# 使用
$ ssh internal-db
# 路径: 运维 → bastion-1 → bastion-2 → internal-db

跳板机安全配置

# 跳板机 sshd_config 特殊配置
# /etc/ssh/sshd_config

# 限制跳板机只能转发,不能执行命令
Match Group jump-users
    AllowTcpForwarding yes
    PermitTTY no
    ForceCommand /bin/false    # 禁止执行命令
    X11Forwarding no
    AllowAgentForwarding no

# 或使用受限 shell
Match Group jump-users
    ForceCommand /usr/local/bin/ssh-jump-menu

录制跳板机会话

# 使用 tlog 录制会话
$ dnf install tlog
# /etc/sshd_config
ForceCommand /usr/bin/tlog-rec-session

# 或使用 script 命令
# /etc/profile.d/audit.sh
if [ -n "$SSH_CONNECTION" ]; then
    LOGDIR=/var/log/ssh-session
    mkdir -p $LOGDIR
    script -qf $LOGDIR/${USER}_$(date +%Y%m%d_%H%M%S).log
fi

端口转发与反向隧道

本地端口转发

# 将本地 8080 端口转发到远程服务器的 80 端口
$ ssh -L 8080:localhost:80 user@server
# 访问 localhost:8080 = 访问 server:80

# 转发到远程服务器能访问的第三台机器
$ ssh -L 8080:10.0.0.10:80 user@jump-server
# 通过 jump-server 访问 10.0.0.10:80

# 后台运行
$ ssh -fNL 8080:localhost:80 user@server

# 在 ~/.ssh/config 中配置
Host tunnel
    HostName server.sre.wang
    User admin
    LocalForward 8080 localhost:80

远程端口转发(反向隧道)

# 将远程服务器的 9090 端口转发到本地的 80 端口
$ ssh -R 9090:localhost:80 user@remote-server
# 在 remote-server 上访问 localhost:9090 = 访问本地 80

# 典型场景:内网穿透
# 内网机器 → 公网服务器(反向隧道)
$ ssh -fNR 2222:localhost:22 user@public-server
# 在公网服务器上 ssh -p 2222 user@localhost 即可连接内网机器

# 允许远程端口转发绑定到所有接口
# /etc/ssh/sshd_config (在公网服务器上)
GatewayPorts yes

动态端口转发(SOCKS 代理)

# 创建 SOCKS5 代理
$ ssh -D 1080 user@server
# 本地 1080 端口作为 SOCKS5 代理,流量通过 server 转发

# 使用代理
$ curl --socks5 127.0.0.1:1080 http://internal-service:8080

# 浏览器配置 SOCKS5 代理: 127.0.0.1:1080

# 后台运行
$ ssh -fND 1080 user@server

隧道保活

# ~/.ssh/config
Host tunnel
    HostName server.sre.wang
    User admin
    RemoteForward 2222 localhost:22
    ServerAliveInterval 60       # 每 60 秒发送心跳
    ServerAliveCountMax 3        # 3 次无响应则断开
    ExitOnForwardFailure yes     # 转发失败则断开
    ControlMaster auto           # 复用连接
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 600           # 连接保持 10 分钟

# 使用 autossh 自动重连
$ autossh -M 0 -fN tunnel
# -M 0: 禁用监控端口,依赖 ServerAliveInterval

隧道使用场景速查

场景命令说明
访问远程数据库ssh -L 3306:db:3306 jump通过跳板机访问数据库
内网穿透ssh -R 2222:localhost:22 public从公网访问内网
SOCKS 代理ssh -D 1080 server全局代理
访问内部 Webssh -L 8080:internal-web:80 jump通过跳板机访问内部 Web
文件传输ssh -L 21:ftp:21 jump通过隧道访问 FTP

SSH Agent

工作原理

[SSH Agent] ← [SSH Client] ← [Remote Server]
[私钥存储在 Agent 中]
     
1. SSH Client 需要认证时,请求 Agent 签名
2. Agent 用私钥签名,但不导出私钥
3. Client 将签名发送给 Server
4. 私钥永远不离开 Agent

基本使用

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

# 添加密钥
$ ssh-add ~/.ssh/id_ed25519
# 如果密钥有 passphrase,会提示输入

# 查看已添加的密钥
$ ssh-add -l
256 SHA256:abc123... admin@sre.wang (ED25519)

# 删除密钥
$ ssh-add -d ~/.ssh/id_ed25519

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

Agent 转发

# 启用 Agent 转发(单次)
$ ssh -A user@jump-server
# 在 jump-server 上可以直接用本地的密钥连接第三台服务器

# 在 ~/.ssh/config 中配置
Host jump-server
    ForwardAgent yes

# 安全风险:跳板机上的 root 可以使用你的 Agent
# 生产环境建议使用 ProxyJump 替代 Agent 转发

Agent 安全好的实践

# 1. 设置 Agent 超时
$ ssh-add -t 3600 ~/.ssh/id_ed25519  # 1 小时后自动删除

# 2. 确认签名请求
$ ssh-add -c ~/.ssh/id_ed25519
# 每次使用密钥时需要确认

# 3. 限制 Agent 转发
# 不要在不受信任的服务器上启用 ForwardAgent

# 4. 使用 SSH Agent 代替在服务器上存储私钥
# ❌ 不好的做法:将私钥复制到每台服务器
# ✅ 好的做法:通过 Agent 转发使用本地私钥

审计日志

SSH 日志位置

# Debian/Ubuntu
$ journalctl -u ssh
# 或
$ tail -f /var/log/auth.log

# RHEL/CentOS
$ journalctl -u sshd
# 或
$ tail -f /var/log/secure

关键日志事件

# 登录成功
$ journalctl -u sshd | grep "Accepted"
# Accepted publickey for admin from 10.0.0.1 port 54321 ssh2: ED25519 SHA256:abc123

# 登录失败
$ journalctl -u sshd | grep "Failed"
# Failed password for invalid user admin from 1.2.3.4 port 54321 ssh2

# 无效用户尝试
$ journalctl -u sshd | grep "Invalid"
# Invalid user admin from 1.2.3.4 port 54321

# 连接断开
$ journalctl -u sshd | grep "Disconnected"
# Disconnected from user admin 10.0.0.1 port 54321

# 证书认证
$ journalctl -u sshd | grep "Certificate"
# Certificate ID "admin_user" (serial 0) for user admin from CA accepted

日志分析

# 统计失败登录的来源 IP
$ journalctl -u sshd --since "24 hours ago" | grep "Failed" | awk '{print $NF}' | sort | uniq -c | sort -rn | head -20

# 统计成功登录的用户
$ journalctl -u sshd --since "24 hours ago" | grep "Accepted" | awk '{print $4, $6}' | sort | uniq -c | sort -rn

# 检测暴力破解(同一 IP 多次失败)
$ journalctl -u sshd --since "1 hour ago" | grep "Failed" | awk '{print $NF}' | sort | uniq -c | sort -rn | awk '$1 > 10 {print "ALERT:", $0}'

# 查看当前在线用户
$ who
$ w
$ last -n 20

配置详细日志

# /etc/ssh/sshd_config
LogLevel VERBOSE
# VERBOSE 级别会记录:
# - 密钥指纹
# - 证书 ID
# - 认证方法
# - 端口转发

# 审计日志
# /etc/audit/audit.rules
-w /etc/ssh/sshd_config -p wa -k ssh_config_change
-w /etc/ssh/ -p wa -k ssh_key_change

Fail2ban

工作原理

[SSH 日志] → [Fail2ban 日志解析] → [匹配失败规则] → [调用 iptables/nftables] → [封禁 IP]
                                   [jail.local 配置]

安装与配置

# 安装
$ apt install fail2ban      # Debian/Ubuntu
$ dnf install fail2ban       # RHEL/CentOS

# 配置(不要直接修改 jail.conf,创建 jail.local)
# /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
port = ssh
filter = sshd
backend = systemd
maxretry = 3                  # 最大失败次数
findtime = 600                # 检测窗口(秒)
bantime = 3600                # 封禁时长(秒)
bantime.increment = true      # 递增封禁
bantime.maxtime = 604800      # 最大封禁 7 天
ignoreip = 127.0.0.1/8 10.0.0.0/8  # 白名单
action = iptables-allports    # 封禁所有端口

Fail2ban 管理

# 启动
$ systemctl enable --now fail2ban

# 查看 SSH jail 状态
$ fail2ban-client status sshd
Status for the jail: sshd
|- Filter
|  |- Currently failed: 2
|  |- Total failed:     156
|  `- File list:        /var/log/auth.log
`- Actions
   |- Currently banned: 5
   |- Total banned:     23
   `- Banned IP list:   1.2.3.4 5.6.7.8 ...

# 手动封禁 IP
$ fail2ban-client set sshd banip 1.2.3.4

# 手动解封 IP
$ fail2ban-client set sshd unbanip 1.2.3.4

# 查看所有 jail
$ fail2ban-client status

自定义规则

# /etc/fail2ban/filter.d/sshd-aggressive.conf
[INCLUDES]
before = common.conf

[Definition]
failregex = ^%(__prefix_line)sFailed publickey for invalid user <FMT_USER>.*</FMT_USER> from <HOST> port \d+ ssh2$
            ^%(__prefix_line)sInvalid user <FMT_USER>.*</FMT_USER> from <HOST> port \d+$
            ^%(__prefix_line)sConnection closed by <HOST> port \d+ \[preauth\]$

ignoreregex =

# /etc/fail2ban/jail.d/sshd.local
[sshd]
enabled = true
filter = sshd-aggressive
maxretry = 2
findtime = 300
bantime = 86400

实战案例

案例 1:生产环境 SSH 完整配置

# === 服务端配置 ===
# /etc/ssh/sshd_config

# 协议与加密
Protocol 2
HostKey /etc/ssh/ssh_host_ed25519_key
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org

# 认证
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3

# 证书认证
TrustedUserCAKeys /etc/ssh/user_ca.pub

# 访问控制
AllowGroups ssh-users admin-group
MaxStartups 10:30:100

# 超时
ClientAliveInterval 300
ClientAliveCountMax 0  # 无响应立即断开

# 日志
LogLevel VERBOSE

# 转发
AllowTcpForwarding yes
X11Forwarding no
AllowAgentForwarding no

# === 客户端配置 ===
# ~/.ssh/config

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    HashKnownHosts yes
    StrictHostKeyChecking ask

Host bastion
    HostName bastion.sre.wang
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host prod-*
    User deploy
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump bastion
    StrictHostKeyChecking yes

案例 2:SSH 证书自动化签发

#!/bin/bash
# /usr/local/bin/ssh-cert-issue.sh
# 为用户签发短期有效的 SSH 证书

CA_KEY=~/.ssh/ca_user_key
USER_PUBKEY=$1
USERNAME=$2
VALIDITY=${3:-1d}

if [ $# -lt 2 ]; then
    echo "Usage: $0 <user_pubkey> <username> [validity]"
    exit 1
fi

# 签发证书
ssh-keygen -s $CA_KEY \
    -I "$USERNAME@$(date +%Y%m%d)" \
    -n $USERNAME \
    -V +$VALIDITY \
    -O clear \
    -O permit-pty \
    -O force-command="/usr/local/bin/ssh-audit-wrapper.sh" \
    $USER_PUBKEY

echo "Certificate issued:"
ssh-keygen -L -f ${USER_PUBKEY%.pub}-cert.pub

案例 3:使用 SSH 隧道访问内网服务

# 场景:通过跳板机访问内网 PostgreSQL
# 内网 PostgreSQL: 192.168.1.100:5432
# 跳板机: bastion.sre.wang

# 方法 1:本地端口转发
$ ssh -fNL 15432:192.168.1.100:5432 bastion
$ psql -h localhost -p 15432 -U admin -d mydb

# 方法 2:在 ~/.ssh/config 中配置
Host db-tunnel
    HostName bastion.sre.wang
    User admin
    LocalForward 15432 192.168.1.100:5432

$ ssh -fN db-tunnel
$ psql -h localhost -p 15432 -U admin -d mydb

# 方法 3:使用 autossh 保持隧道
$ autossh -M 0 -fN db-tunnel

# 方法 4:使用 ProxyCommand 直接连接(无需隧道)
$ psql "host=192.168.1.100 port=5432 user=admin dbname=mydb \
        sslmode=disable \
        hostaddr=127.0.0.1 \
        port=15432"

SSH 安全检查清单

#!/bin/bash
# SSH 安全审计脚本

echo "=== SSH 安全检查 ==="

# 1. 检查 root 登录
ROOT_LOGIN=$(sshd -T | grep permitrootlogin)
echo "Root Login: $ROOT_LOGIN"

# 2. 检查密码认证
PWD_AUTH=$(sshd -T | grep passwordauthentication)
echo "Password Auth: $PWD_AUTH"

# 3. 检查密钥算法
echo "Host Keys:"
ls -la /etc/ssh/ssh_host_*

# 4. 检查加密配置
echo "Ciphers:"
sshd -T | grep ciphers
echo "MACs:"
sshd -T | grep macs

# 5. 检查 MaxAuthTries
MAX_AUTH=$(sshd -T | grep maxauthtries)
echo "Max Auth Tries: $MAX_AUTH"

# 6. 检查 Fail2ban
if systemctl is-active --quiet fail2ban; then
    echo "Fail2ban: Active"
    fail2ban-client status sshd
else
    echo "Fail2ban: INACTIVE (WARNING)"
fi

# 7. 检查 known_hosts
echo "Known Hosts entries: $(wc -l < ~/.ssh/known_hosts 2>/dev/null || echo 0)"

# 8. 检查密钥权限
echo "SSH Directory Permissions:"
ls -ld ~/.ssh
ls -la ~/.ssh/authorized_keys 2>/dev/null

# 9. 检查最近登录
echo "Recent Logins:"
last -n 5

# 10. 检查失败登录
echo "Failed Logins (last 24h):"
journalctl -u sshd --since "24 hours ago" 2>/dev/null | grep "Failed" | wc -l

总结

SSH 是系统运维的核心通道,其安全配置直接关系到整个基础设施的安全。核心要点:

  1. 密钥认证是基础:Ed25519 是首选算法,密码认证必须禁用,authorized_keys 中可限制来源 IP 和命令。
  2. 证书认证是进阶方案:集中管理用户密钥、支持有效期、支持撤销,适合大规模团队和合规要求。
  3. sshd_config 硬化是必须的:禁用 root 登录、限制加密算法、设置超时和最大尝试次数。
  4. 跳板机是标准架构:ProxyJump 是现代方案,比 Agent 转发更安全。
  5. 端口转发要按需开放:AllowTcpForwarding 根据实际需求配置,X11 和 Agent 转发建议关闭。
  6. 审计日志是安全基石:LogLevel VERBOSE 记录密钥指纹和证书 ID,定期分析失败登录。
  7. Fail2ban 是防暴力破解的标配:配合递增封禁策略,有效遏制自动化攻击。
  8. SSH 安全是纵深防御的一环:需要配合防火墙、入侵检测、网络分段等综合防护。

SSH 安全的黄金法则:最小权限 + 多层防御。每个配置项都应遵循最小权限原则,同时配合跳板机、Fail2ban、审计日志形成多层防御体系。