Ubuntu服务器的默认配置在账户安全层面并不激进,如果你刚装好系统就放上公网,几分钟内日志里就会出现大量的SSH暴力破解尝试。攻击者利用自动化工具扫描22端口,用常见用户名和弱密码字典反复登录,一旦得手,服务器就会被植入挖矿程序或沦为僵尸网络节点。解决这个问题的核心思路不是单一措施,而是多层防御:让攻击者找不到用户名、猜不中密码、试不了几次就被封禁。
检查当前系统的登录失败记录在动手加固之前,先搞清楚系统正在遭受什么样的攻击,这能帮你判断哪些账户已经被盯上。使用 lastb 命令可以查看所有失败的登录尝试记录:
sudo lastb
如果输出刷屏,说明你的服务器正在被持续扫描。你可以进一步统计攻击者最常用的用户名:
sudo lastb | awk '{print $1}' | sort | uniq -c | sort -nr | head -10
这个命令会列出失败登录次数最多的十个用户名,通常你会看到 root、admin、test、ubuntu、debian 等高频目标。了解这些信息后,你就知道该重点保护哪些账户,也更有动力把下面的措施落实到位。
禁用root直接登录,创建专属管理账户root账户是Linux系统的超级管理员,也是暴力破解的首要目标。无论你的root密码有多复杂,都不应该允许它通过SSH直接登录。正确的做法是创建一个普通用户,通过sudo提权执行管理任务。如果你还没有非root用户,先创建一个:
sudo adduser your_username sudo usermod -aG sudo your_username
创建完成后,务必用这个新用户重新登录一次,确认sudo权限正常工作,再继续修改SSH配置。编辑SSH配置文件:
sudo nano /etc/ssh/sshd_config
找到 PermitRootLogin 这一行,将其值改为 no。如果该行被注释掉了,去掉注释符号并修改:
PermitRootLogin no
同时,你还可以顺便检查一下是否允许密码认证,如果后续会配置密钥登录,可以把密码认证也关掉,但现阶段先保留。保存文件后重启SSH服务使配置生效:
sudo systemctl restart sshd
注意,重启SSH服务不会中断你当前的连接,但建议你保留一个备用终端窗口,以防配置出错导致无法登录。从现在开始,root账户就无法通过SSH直接登录了,攻击者连用户名都需要先猜对,难度大幅提升。
修改默认SSH端口,降低自动化扫描命中率把SSH端口从22改成其他高位端口,是最简单却有效的干扰手段。绝大多数自动化攻击脚本只扫描默认端口,改端口能让99%的噪音流量直接消失。在同一个配置文件 /etc/ssh/sshd_config 中找到 Port 22 这一行,改成你选择的高位端口,比如2222或更不常见的五位数端口:
Port 2222
如果你担心忘记新端口,可以先保留22端口同时监听新端口,测试通过后再移除22。配置多端口写法如下:
Port 22 Port 2222
测试新端口可以正常连接后,删除Port 22这一行,重启SSH服务。之后登录时需要指定端口:
ssh -p 2222 your_username@your_server_ip
别忘了在云服务商的安全组或系统防火墙中放行新端口,否则你会把自己锁在外面。使用ufw的话,操作如下:
sudo ufw allow 2222/tcp sudo ufw delete allow 22/tcp
端口变更后,日志里的暴力破解尝试会断崖式下降。但这不是安全的终点,只是让攻击者更难找到目标,真正决定安全底线的是认证方式。
用SSH密钥替代密码认证密码认证的最大问题是人的记忆有限,大多数人设置的密码长度和复杂度都不足以对抗现代算力。而SSH密钥对使用非对称加密,2048位或4096位的RSA密钥,暴力破解在数学上不可行。如果你还没有密钥对,在本地电脑上生成:
ssh-keygen -t ed25519 -C "your_email@example.com"
这里推荐使用ed25519算法,它比RSA更安全且密钥更短,性能更好。生成后把公钥上传到服务器:
ssh-copy-id -p 2222 your_username@your_server_ip
如果你已经改了SSH端口,记得加上-p参数。上传成功后,先用新密钥测试登录,确认无需密码即可连接。然后再次编辑SSH配置文件,关闭密码认证:
PasswordAuthentication no ChallengeResponseAuthentication no UsePAM no
这三行配置彻底关闭了所有基于密码的认证方式,从此只有持有私钥的人才能登录。这是防止暴力破解的终极手段,因为攻击者根本没有输入密码的机会。但请务必保管好你的私钥文件,建议使用密码保护私钥,并做好备份。
部署Fail2Ban自动封禁攻击IP即使关闭了密码认证,攻击者仍然会尝试连接,消耗服务器资源并产生大量日志噪音。Fail2Ban通过监控日志文件,在检测到多次失败尝试后自动将攻击IP加入防火墙黑名单,封禁一段时间。安装很简单:
sudo apt update sudo apt install fail2ban -y
安装完成后,Fail2Ban会以默认配置运行,但我们需要针对SSH做一些定制。创建本地配置文件覆盖默认设置:
sudo nano /etc/fail2ban/jail.local
写入以下内容:
[sshd] enabled = true port = 2222 filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 3600 findtime = 600
这里的配置含义是:如果在600秒(10分钟)内,某个IP在端口2222上SSH登录失败达到3次,就封禁该IP 3600秒(1小时)。你可以根据实际情况调整这些数值。如果攻击非常猛烈,可以把bantime设得更长,比如86400秒(24小时)。配置完成后启动服务:
sudo systemctl enable fail2ban sudo systemctl start fail2ban
查看封禁状态可以用:
sudo fail2ban-client status sshd
这个命令会显示当前被封禁的IP列表和封禁数量。Fail2Ban不仅能保护SSH,还可以配置保护其他服务,比如Nginx、Apache的登录页面,但SSH是最关键的。
设置强密码策略,兜底非SSH场景即使你使用密钥登录,系统账户仍然需要密码用于sudo提权、本地控制台登录等场景。弱密码在这些场景下同样是隐患。Ubuntu使用PAM模块来管理密码策略,安装libpam-pwquality可以强制密码复杂度要求:
sudo apt install libpam-pwquality -y
然后编辑PAM密码策略配置文件:
sudo nano /etc/pam.d/common-password
找到包含 pam_pwquality.so 的那一行,修改为类似这样的参数:
password requisite pam_pwquality.so retry=3 minlen=12 difok=3 ucredit=-1 lcredit=-1 dcredit=-1 ocredit=-1 enforce_for_root
这些参数的含义是:密码最小长度12位,新密码与旧密码至少有3个字符不同,必须包含至少1个大写字母、1个小写字母、1个数字和1个特殊字符,且对root账户同样强制执行。retry=3表示用户有3次机会输入符合要求的新密码。这样一来,即使某个账户被设置了密码,也不会是123456这种弱口令。
锁定或删除不必要的账户Ubuntu系统默认会有一些服务账户,这些账户通常没有登录权限,但检查一遍总没坏处。查看系统中所有可以登录的账户:
awk -F: '($7 ~ /\/bin\/bash|\/bin\/sh/) {print $1}' /etc/passwd
输出列表中,确认每一个账户都是你认识且需要的。对于不需要登录权限的账户,锁定其密码:
sudo passwd -l username
对于完全不需要的账户,直接删除:
sudo userdel -r username
另外,检查 /etc/shadow 文件中哪些账户有密码哈希值,确保只有必要的账户有密码。攻击者有时会利用一些冷门服务账户的默认密码进行突破,减少攻击面总是好的。
限制允许登录的用户和组在SSH配置中,你可以明确指定哪些用户或用户组允许登录。这是最后的访问控制关口,即使攻击者拿到了某个账户的密钥,如果该账户不在允许列表中,也无法登录。在 /etc/ssh/sshd_config 中添加:
AllowUsers your_username another_user
或者使用用户组控制:
AllowGroups sshusers
如果使用组控制,记得创建对应组并将用户加入:
sudo groupadd sshusers sudo usermod -aG sshusers your_username
配置完成后重启SSH服务。这个白名单机制非常有效,所有不在列表中的账户,即使密码正确、密钥匹配,也会被拒绝登录。
启用SSH连接速率限制除了Fail2Ban在应用层的封禁,你还可以在系统防火墙层面限制SSH端口的连接频率,这能防御更底层的资源消耗型攻击。使用ufw配合iptables的limit模块可以实现:
sudo ufw limit 2222/tcp
这条命令会限制对2222端口的连接速率,默认每分钟最多6个新连接。超过限制后,后续连接会被拒绝,直到下一分钟。这个限制对于正常的SSH使用完全足够,但能有效遏制高速暴力破解工具。你也可以用更精细的iptables规则实现类似效果,但ufw limit已经能满足绝大多数场景。
启用日志监控与告警安全配置部署完毕后,持续的监控能让你在第一时间发现异常。除了定期查看Fail2Ban状态,你还可以配置日志监控工具。一个轻量级的做法是使用logwatch生成每日安全报告:
sudo apt install logwatch -y
配置它每天通过邮件发送SSH相关活动摘要。对于更实时的需求,可以编写简单的脚本监控 /var/log/auth.log,当出现大量失败登录时触发告警。但至少,你应该养成定期手动检查的习惯:
sudo grep "Failed password" /var/log/auth.log | tail -20 sudo grep "Accepted publickey" /var/log/auth.log | tail -10
前者查看最近的失败密码尝试,后者查看成功的密钥登录。如果你看到成功的登录来自不认识的IP,立即排查是否私钥泄露。
保持系统更新,关注安全公告SSH服务本身也可能存在漏洞,虽然OpenSSH的安全记录相当优秀,但历史上仍出现过远程代码执行漏洞。确保系统定期更新:
sudo apt update && sudo apt upgrade -y
可以配置无人值守安全更新,只安装安全补丁而不影响其他软件包:
sudo apt install unattended-upgrades -y sudo dpkg-reconfigure --priority=low unattended-upgrades
选择“是”启用自动安全更新。这样系统会在后台自动安装关键安全补丁,降低因漏洞被利用的风险。
把这套组合拳打下来,你的Ubuntu服务器在账号安全层面已经达到了相当高的水准。攻击者首先很难发现你的SSH端口,即使发现了,也没有root可以尝试,没有密码可以猜测,试错几次就被Fail2Ban封禁,即使偷到某个账户的密钥也不在允许列表中。安全从来不是一劳永逸的事情,但这些措施能让你在绝大多数自动化攻击面前稳如磐石。
