1. 项目概述为什么SSHD加固是运维的必修课最近在排查一台暴露在公网的测试服务器日志时发现/var/log/secure里塞满了Failed password for invalid user的条目时间戳密集得像雨点。这再典型不过了就是脚本小子在用字典在暴力撞库。这让我想起很多朋友在云上开了台ECS装好系统、配好IP就觉得万事大吉直接开始部署应用。殊不知你的22端口SSH默认端口就像黑夜中的灯塔无时无刻不在吸引着全球扫描器的“关照”。SSH服务是Linux服务器的生命线也是最大的风险入口之一。一次成功的暴力破解意味着攻击者拿到了与你同级别的系统权限数据泄露、服务瘫痪、沦为肉鸡后果不堪设想。因此“SSHD登录加固”绝非一个可选项而是每一位服务器管理员无论是运维工程师、开发者还是个人站长在将服务器接入网络后必须立即执行的基础安全操作。它不涉及高深莫测的零日漏洞利用而是通过一系列成熟、有效的配置调整显著提高攻击者的入侵成本和难度将绝大多数自动化攻击挡在门外。本指南将脱离那些泛泛而谈的安全建议深入/etc/ssh/sshd_config这个核心配置文件结合实战日志分析为你拆解从端口、协议、用户、认证到网络层面的多层防御策略并提供可直接复制粘贴的配置片段和排错命令。我们的目标很简单让你的SSH服务从“裸奔”变成“堡垒”。2. SSH服务与暴力破解攻防基础2.1 SSH协议简析与默认风险SSHSecure Shell协议为我们提供了加密的远程登录和命令执行通道其守护进程sshd监听TCP 22端口。默认安装后sshd的配置通常是为了最大兼容性但这带来了几个典型风险点允许密码登录虽然方便但弱密码或常见密码在暴力破解面前不堪一击。监听所有接口sshd默认监听0.0.0.0所有IPv4地址和::所有IPv6地址意味着从任何网络都可以尝试连接。允许root直接登录攻击者一旦破解root密码即获得完全控制权。使用协议版本1SSHv1协议存在已知缺陷早已被淘汰但一些老旧配置可能仍允许。暴力破解攻击者正是利用这些“便利”。他们通过扫描工具发现开放22端口的服务器然后使用庞大的用户名/密码字典以极高的频率发起登录尝试。日志中常见的pam_unix(sshd:auth): authentication failure就是这种攻击的痕迹。2.2 从日志识别攻击迹象学会看日志是防御的第一步。攻击活动在日志中并非无迹可寻。# 查看安全相关日志CentOS/RHEL系 sudo tail -f /var/log/secure # 查看安全相关日志Debian/Ubuntu系 sudo tail -f /var/log/auth.log你需要关注以下几种高频出现的失败信息模式针对无效用户的爆破Failed password for invalid user {username} from {ip} port {port} ssh2。这说明攻击者在随机尝试常见用户名如admin, test, user, oracle等。针对有效用户的爆破Failed password for {valid_username} from {ip} port {port} ssh2。这更危险说明攻击者可能通过信息泄露或枚举知道了你系统上存在的真实用户名正在集中火力破解其密码。连接即断开大量Received disconnect from {ip} port {port}:11: Bye Bye或Connection closed by authenticating user。这可能是在进行协议探测或快速尝试。当你发现同一个IP地址在短时间内如几分钟内产生数十甚至上百条失败记录时就可以基本断定这是暴力破解行为。注意不要一看到失败登录就惊慌。管理员自己输错密码、自动化脚本配置错误也会产生失败记录。关键鉴别特征是时间频率和IP来源的集中度。真正的攻击通常来自你不熟悉的境外IP且尝试频率极高。3. 核心加固策略与sshd_config详解所有加固操作的核心都是修改SSH服务端的配置文件/etc/ssh/sshd_config。修改前务必先备份sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak。每次修改后需要重载或重启SSH服务使配置生效sudo systemctl reload sshd或sudo systemctl restart sshd。强烈建议在修改配置后保持一个当前的SSH连接不退出新开一个连接测试成功后再关闭旧会话以防配置错误导致自己也无法登录。3.1 认证方式革新彻底禁用密码登录这是最有效、最根本的加固措施没有之一。用密钥对认证替代密码认证。原理SSH密钥对包含一个公钥放在服务器~/.ssh/authorized_keys中和一个私钥用户自己妥善保管。登录时客户端用私钥签名一个挑战码服务器用公钥验证。由于私钥不在网络上传输且通常有密码保护其安全性远高于可能被暴力破解或嗅探的密码。操作步骤本地生成密钥对在你自己电脑上操作ssh-keygen -t ed25519 -C your_emailexample.com # -t 指定算法ed25519比传统的rsa更安全快速。也可以用 -t rsa -b 4096命令会提示你输入保存路径直接回车用默认和私钥密码passphrase。设置一个强密码能为私钥再加一把锁。将公钥上传到服务器ssh-copy-id -i ~/.ssh/id_ed25519.pub your_usernameyour_server_ip如果ssh-copy-id不可用可以手动将本地~/.ssh/id_ed25519.pub文件的内容追加到服务器的~/.ssh/authorized_keys文件中。测试密钥登录ssh -i ~/.ssh/id_ed25519 your_usernameyour_server_ip确保可以不输入服务器用户密码但可能需要输入私钥的passphrase即可登录。服务器端配置 编辑/etc/ssh/sshd_config找到并修改以下行PubkeyAuthentication yes PasswordAuthentication no # 关键设为 no ChallengeResponseAuthentication no UsePAM no # 如果确定只用密钥可以关闭PAM认证模块但关闭前需确认无其他依赖。更稳妥的做法是先确保密钥登录绝对可用再将PasswordAuthentication设为no。实操心得在关闭密码认证前我习惯在sshd_config里加一行AuthenticationMethods publickey对于新版本OpenSSH这明确指定只允许公钥认证。另外务必检查~/.ssh和~/.ssh/authorized_keys的权限~/.ssh应为700drwx------authorized_keys应为600-rw-------权限过大会导致密钥认证失败。3.2 访问控制精细化用户与网络白名单即使使用了密钥进一步收缩访问范围也能减少暴露面。用户访问控制禁止root直接登录这是黄金准则。用普通用户登录后再通过sudo提权。PermitRootLogin no限制允许登录的用户或用户组AllowUsers alice bob admin192.168.1.0/24 # 只允许alice, bob登录且admin只能从指定网段登录 AllowGroups sshusers # 只允许属于sshusers组的用户登录也可以使用DenyUsers和DenyGroups黑名单但白名单原则更安全。网络层访问控制修改默认端口将端口从22改为一个大于1024的非知名端口能避开大部分自动化扫描。Port 2222 # 可以指定多个Port行同时监听多个端口重要修改端口后防火墙规则也要相应调整。同时连接时需指定端口ssh -p 2222 userhost。限制监听IP如果服务器有多个IP但SSH只应从特定管理IP访问。ListenAddress 192.168.1.100 # 只监听内网IP ListenAddress 203.0.113.10 # 可以监听多个特定IP利用TCP Wrappers可选老派但有效的额外层。在/etc/hosts.allow和/etc/hosts.deny中配置。# /etc/hosts.allow sshd: 192.168.1., .yourdomain.com # /etc/hosts.deny sshd: ALL注意事项修改端口是一把双刃剑。它确实能减少噪音日志但也可能带来“安全通过隐匿性”的错觉绝不能替代密钥认证等核心措施。并且要确保你和你的团队都牢记新端口号。我曾见过有人改了端口却忘了更新自动化运维脚本导致半夜故障无法连接的尴尬情况。3.3 协议与算法强化禁用弱加密套件确保只使用强加密算法淘汰老旧、不安全的协议和算法。# 禁用不安全的SSHv1协议 Protocol 2 # 配置加密算法、MAC消息认证码算法和密钥交换算法 Ciphers chacha20-poly1305openssh.com,aes256-gcmopenssh.com,aes128-gcmopenssh.com,aes256-ctr,aes192-ctr,aes128-ctr MACs hmac-sha2-512-etmopenssh.com,hmac-sha2-256-etmopenssh.com,umac-128-etmopenssh.com KexAlgorithms curve25519-sha256,curve25519-sha256libssh.org,diffie-hellman-group-exchange-sha256这些算法列表是按照优先顺序排列的客户端和服务器会协商使用双方都支持的最优先算法。使用ssh -Q cipher或mac,kex可以查看本地OpenSSH支持的算法列表。3.4 会话与连接参数调优合理的超时和连接限制可以释放资源并增加攻击者的成本。# 客户端空闲超时时间秒超时后自动断开连接 ClientAliveInterval 300 ClientAliveCountMax 2 # 在发送多少次存活消息后断开 # 这意味着空闲 300*2600 秒10分钟后断开 # 限制最大并发未认证连接数减缓暴力破解速度 MaxStartups 10:30:100 # 格式 start:rate:full。表示前10个连接正常接收第11到第40个按30%概率拒绝超过100个全部拒绝。 # 限制每个IP的最大并发连接数需要高版本OpenSSH或配合其他工具如fail2ban # 在sshd_config中直接限制能力有限通常依赖外部工具。4. 高级防御与主动监控仅靠sshd_config是静态防御。面对持续攻击我们需要动态的、主动的防御和监控手段。4.1 使用Fail2ban实现动态防火墙封锁Fail2ban是一个经典的入侵防御框架它监控系统日志如/var/log/secure当发现同一IP在短时间内有多次失败登录尝试时自动调用防火墙如iptables, firewalld规则将该IP临时或永久封禁。安装与基础配置以CentOS/RHEL为例安装sudo yum install epel-release sudo yum install fail2ban sudo systemctl enable --now fail2ban创建本地监狱配置不建议直接修改/etc/fail2ban/jail.conf而是创建/etc/fail2ban/jail.local。[DEFAULT] # 封禁IP的默认时间秒 bantime 3600 # 查找时间窗口秒 findtime 600 # 在findtime内最大失败次数 maxretry 5 # 使用的防火墙后端 banaction firewallcmd-ipset action %(action_mwl)s # 会执行封禁并发送邮件通知需配置邮件 [sshd] enabled true port ssh,2222 # 如果你修改了SSH端口这里一定要加上 filter sshd logpath /var/log/secure maxretry 3 # 对SSHD可以更严格一些对于Debian/Ubuntulogpath可能需要改为/var/log/auth.log。重启并检查状态sudo systemctl restart fail2ban sudo fail2ban-client status sudo fail2ban-client status sshd # 查看sshd监狱详情Fail2ban会动态添加防火墙规则。你可以用sudo iptables -L -n或sudo firewall-cmd --list-all查看被封禁的IP。踩坑记录最大的坑就是忘记在[sshd]部分添加自定义的SSH端口。如果你把SSH改到了2222端口但Fail2ban只监控ssh22端口那么攻击者针对2222端口的暴力破解就不会触发封禁。另一个坑是logpath配置错误务必确认你的系统认证日志的实际路径。4.2 基于网络层的防火墙策略系统自带的防火墙如firewalld或ufw是第一道屏障。使用firewalld (RHEL/CentOS):sudo firewall-cmd --permanent --add-servicessh # 如果端口是22 sudo firewall-cmd --permanent --add-port2222/tcp # 如果端口是2222 sudo firewall-cmd --reload # 更严格的做法只允许特定IP段访问SSH端口 sudo firewall-cmd --permanent --remove-servicessh sudo firewall-cmd --permanent --add-rich-rulerule familyipv4 source address192.168.1.0/24 port protocoltcp port2222 accept sudo firewall-cmd --reload使用ufw (Ubuntu/Debian):sudo ufw allow 2222/tcp comment SSH Management Port sudo ufw enable4.3 日志监控与告警防御的最后一环是感知。你需要知道是否有人正在攻击你以及攻击的规模。实时日志监控使用tail -f或journalctl -f -u sshd实时查看。编写简单的分析脚本定期分析日志统计失败尝试。#!/bin/bash # 分析过去一小时失败登录尝试最多的前10个IP LOGFILE/var/log/secure echo Top 10 IPs with failed SSH attempts in last hour: grep $(date -d 1 hour ago %b %_d %H:) $LOGFILE | grep Failed password | awk {print $11} | sort | uniq -c | sort -nr | head -10可以将此脚本加入cron定时任务并将输出通过邮件或即时通讯工具发送给自己。使用专业监控系统如ELK StackElasticsearch, Logstash, Kibana、Grafana Loki等可以构建更强大的日志聚合、分析和可视化告警平台。5. 完整配置示例与深度排错指南5.1 一份生产环境可用的sshd_config参考以下是一份集成了上述多项措施的配置文件示例/etc/ssh/sshd_config。请根据你的实际情况调整参数尤其是端口、允许用户和监听地址。# 基本设置 Port 2222 ListenAddress 192.168.1.100 # 按需修改或注释掉以监听所有地址 Protocol 2 HostKey /etc/ssh/ssh_host_ed25519_key HostKey /etc/ssh/ssh_host_rsa_key # 日志 SyslogFacility AUTHPRIV LogLevel VERBOSE # 或 INFODEBUG会记录太多信息 # 认证核心设置 PermitRootLogin no StrictModes yes MaxAuthTries 3 # 每个连接最大认证尝试次数 MaxSessions 5 # 每个网络连接的最大会话数 PubkeyAuthentication yes AuthorizedKeysFile .ssh/authorized_keys PasswordAuthentication no # 关键禁用密码 ChallengeResponseAuthentication no UsePAM no # 如果只用密钥且无其他依赖可关闭 # 允许的用户白名单按需修改 AllowUsers alice bob charlie203.0.113.0/24 # 加密算法强化 Ciphers chacha20-poly1305openssh.com,aes256-gcmopenssh.com,aes128-gcmopenssh.com,aes256-ctr,aes192-ctr,aes128-ctr MACs hmac-sha2-512-etmopenssh.com,hmac-sha2-256-etmopenssh.com,umac-128-etmopenssh.com KexAlgorithms curve25519-sha256,curve25519-sha256libssh.org,diffie-hellman-group-exchange-sha256 # 连接与会话管理 ClientAliveInterval 300 ClientAliveCountMax 2 UseDNS no # 如果内网DNS解析慢或不可靠建议设为no以加速连接 GSSAPIAuthentication no # 通常用不到关闭以加速连接 # 其他安全与性能 Compression delayed # 延迟压缩对低速连接有帮助 AllowTcpForwarding yes # 按需如果需要端口转发 X11Forwarding no # 除非需要否则关闭 PrintMotd no # 通常通过pam.d配置这里关闭 PrintLastLog yes TCPKeepAlive yes5.2 配置后无法登录的紧急排查流程在应用了严格配置特别是首次禁用密码登录后最怕的就是把自己也锁在外面。请按此流程排查检查当前连接确保还有一个活跃的SSH连接窗口没有关闭。这是你的“救命稻草”。检查sshd服务状态sudo systemctl status sshd如果状态是failed或inactive查看详细错误sudo journalctl -xe -u sshd。常见错误是配置文件语法错误如拼写错误、布尔值写成了yes/no之外的词。以调试模式启动sshd在服务器控制台物理机或云平台的VNC上操作。sudo /usr/sbin/sshd -d -p 2222-d表示调试模式会在前台输出详细日志。在另一个终端尝试连接观察服务器端的输出通常会明确提示错误原因如“Permission denied (publickey)”或“Could not load host key”。检查密钥文件权限这是密钥登录失败的最常见原因。服务器上对应用户的~/.ssh目录权限必须是700(drwx------)。~/.ssh/authorized_keys文件权限必须是600(-rw-------)。上级目录用户家目录的权限不能是group或others可写。检查SELinux/AppArmor这些安全模块可能会阻止sshd读取密钥文件。SELinux (CentOS/RHEL)临时禁用排查sudo setenforce 0。如果问题解决需要调整上下文sudo restorecon -Rv ~/.ssh。AppArmor (Ubuntu)检查日志sudo dmesg | grep apparmor。回滚配置如果以上都无法解决且你已无法登录只能通过云平台控制台或物理控制台将/etc/ssh/sshd_config恢复到你备份的版本或一个最简化的、允许密码登录的版本然后重启sshd。5.3 日常维护与安全检查清单加固不是一劳永逸的需要定期维护。定期更新sudo yum update openssh-server或sudo apt update sudo apt upgrade openssh-server。定期审计密钥检查~/.ssh/authorized_keys文件移除不再使用或来历不明的公钥。定期查看日志养成习惯定期grep Failed password /var/log/secure | wc -l看看攻击尝试次数。检查Fail2ban状态sudo fail2ban-client status查看被封禁的IP列表是否异常。端口扫描自检在确保授权的前提下可以从外部网络使用nmap扫描你的服务器确认只有预期的端口如2222对SSH开放。6. 总结与个人实践心得服务器安全是一个“纵深防御”的体系SSH加固是这个体系中最关键、最靠外的一环。我个人的经验是“密钥认证非默认端口Fail2ban”这三板斧已经足以抵御99%的自动化脚本和初级攻击者。对于更重要的资产再叠加用户白名单、网络层防火墙限制甚至考虑使用证书认证或双因素认证将安全等级提到最高。在整个实施过程中我最深刻的体会有两点一是测试、测试、再测试。任何可能影响登录的配置变更都必须在一个保持活跃的会话窗口里测试通过后再实施。二是日志是你的眼睛。不要嫌日志枯燥多看看/var/log/secure你就能对攻击的态势有最直观的感受。安全本质上是一个持续的过程而不是一个可以勾选完成的状态。通过本指南的系统性配置你可以为你的Linux服务器构建一个坚固的SSH访问堡垒让你能更安心地将精力投入到业务本身而不是疲于应对各种安全告警。