暴露在公网上的Ubuntu服务器,默认的22端口几乎是恶意扫描器的最爱。每天数万次的暴力破解尝试,不仅拖累服务器性能,更埋下了严重的安全隐患。把SSH端口改掉,再配合禁用密码登录,强制使用密钥认证,能直接挡掉99%的自动化攻击。这不是什么高深操作,但细节处理不到位,很容易把自己锁在服务器外面。
修改前的必要准备动手之前,务必保留一个已连接的终端窗口。如果修改过程中出现配置错误,只要当前会话不断开,你就有机会回滚配置。另外,先确认你手上有一对能用的SSH密钥,并且公钥已经放到了服务器的authorized_keys文件里。如果没有,现在就用ssh-keygen生成,用ssh-copy-id把公钥推上去。测试密钥登录完全正常后,再开始后续操作。很多人就是跳过了验证密钥这一步,结果端口一改、密码一关,自己再也连不上了。
选择新端口的原则端口范围从1到65535,但选端口有讲究。1024以下的端口属于特权端口,需要root权限绑定,虽然能用但没必要。1024到49151是注册端口,部分服务会占用。49152到65535是动态或私有端口,相对干净。建议选一个五位数的端口,比如26489、51872这种,避免和其他常见服务冲突。用命令 ss -tlnp 查看当前监听的端口,确保你选的端口没被占用。选好之后记下来,后续配置会用到。
修改SSH默认端口Ubuntu的SSH服务端配置文件在 /etc/ssh/sshd_config。用编辑器打开它,注意是sshd_config,不是ssh_config,后者是客户端配置,改错了没用。
sudo nano /etc/ssh/sshd_config
找到 #Port 22 这一行。去掉前面的注释符号#,把22改成你选定的端口号。如果这一行被注释掉了,SSH服务就会使用默认的22端口。修改后应该是这样:
Port 26489
保存文件,先别急着重启SSH服务。现在防火墙还挡着新端口,一重启SSH服务绑到新端口上,但防火墙没放行,连接就断了。
配置防火墙放行新端口Ubuntu默认使用ufw管理防火墙。先查看当前状态:
sudo ufw status
如果防火墙是激活状态,需要添加新端口的放行规则。假设新端口是26489:
sudo ufw allow 26489/tcp
这条命令添加允许TCP协议通过26489端口的规则。如果你还开着22端口,先别急着删,等确认新端口能正常连接后再移除旧规则。现在可以重启SSH服务了:
sudo systemctl restart sshd
重启完成后,新开一个终端窗口,用新端口测试连接:
ssh -p 26489 用户名@服务器IP
能连上,说明端口修改成功。这时可以回到原来的终端,把22端口的防火墙规则删掉:
sudo ufw delete allow 22/tcp
如果用的是云服务器,别忘了在云服务商的安全组或防火墙规则里也放行新端口。这是最容易被忽略的地方,安全组默认只开22,你没在云控制台加新端口,外部流量根本进不来。
禁用密码登录,仅允许密钥认证端口换了,但密码登录还开着的话,攻击者扫描到新端口后照样可以暴力破解。所以必须关掉密码登录。继续编辑 sshd_config:
sudo nano /etc/ssh/sshd_config
找到以下几行,确保它们的值如下设置。如果行首有#号就去掉:
PasswordAuthentication no ChallengeResponseAuthentication no UsePAM yes PubkeyAuthentication yes
PasswordAuthentication no 是核心,直接禁用密码认证。ChallengeResponseAuthentication no 关掉质询响应认证,这也是一种交互式认证方式,同样存在被暴力破解的风险。UsePAM 保持yes,因为密钥认证本身也依赖PAM模块进行账户管理。PubkeyAuthentication yes 确保密钥认证是开启状态。
还有一个参数需要留意,PermitRootLogin。如果之前允许root直接登录,现在强烈建议改成 prohibit-password 或者 no。prohibit-password 的意思是root只能通过密钥登录,密码不行。no 则是完全禁止root远程登录。推荐设置为 prohibit-password:
PermitRootLogin prohibit-password
保存文件后,先别重启服务。用 sshd -t 命令测试配置文件语法是否正确:
sudo sshd -t
如果没有输出任何错误信息,说明配置语法没问题。这个习惯能救命,配置写错了直接重启服务,SSH就起不来了。测试通过后,重启SSH服务:
sudo systemctl restart sshd
现在再开一个新终端测试连接。用密码登录应该会被拒绝,用密钥登录则正常通过。如果密钥登录失败,检查本地密钥路径是否正确,服务器上 ~/.ssh/authorized_keys 文件权限是否为600,~/.ssh 目录权限是否为700。权限不对,SSH服务会拒绝使用该公钥。
加固SSH的额外配置端口改了,密码关了,安全基础已经打好了。但还可以再做一些加固,让SSH服务更健壮。在 sshd_config 里追加或修改以下参数:
MaxAuthTries 3 ClientAliveInterval 300 ClientAliveCountMax 2 LoginGraceTime 30 MaxSessions 5 AllowUsers 你的用户名
MaxAuthTries 限制单次连接最多尝试认证次数,超过就断开,拖慢暴力破解速度。ClientAliveInterval 和 ClientAliveCountMax 配合使用,服务端每300秒发一个心跳包,两次无响应就断开僵死连接,避免资源浪费。LoginGraceTime 设置认证超时时间,30秒内没完成认证就断开。MaxSessions 限制单个连接能建立的最大会话数。AllowUsers 是白名单,只允许指定的用户通过SSH登录,这是最有效的访问控制手段,多个用户用空格分隔。
修改完这些参数后,同样用 sshd -t 测试,然后重启服务。
配置Fail2ban自动封禁恶意IP换了端口不代表高枕无忧,专门针对高位数端口的扫描也在增多。Fail2ban能监控日志,发现多次认证失败的IP就自动用防火墙封禁一段时间。安装很简单:
sudo apt update sudo apt install fail2ban -y
安装后,复制一份配置文件进行自定义,不要直接修改默认配置:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
编辑 jail.local,找到 [sshd] 段落,调整参数:
[sshd] enabled = true port = 26489 maxretry = 3 bantime = 3600 findtime = 600
port 要填你修改后的SSH端口。maxretry 是最大重试次数,超过就封禁。bantime 是封禁时长,单位秒,3600就是一小时。findtime 是统计时间窗口,600秒内失败3次就触发。配置完成后启动Fail2ban并设置开机自启:
sudo systemctl enable fail2ban --now
用 sudo fail2ban-client status sshd 可以查看当前封禁状态,被ban的IP列表一目了然。
密钥管理的注意事项强制密钥登录后,密钥本身的安全就成了关键。私钥绝对不能泄露,本地存储的私钥文件权限必须是600。生成密钥对时建议加密码保护,虽然每次连接要多输一次密码,但即使私钥文件被盗,没有密码也无法使用。多台设备访问同一台服务器时,每台设备生成自己的密钥对,把各自的公钥追加到服务器的authorized_keys里,不要共用同一对密钥。定期检查 authorized_keys 文件,移除不再使用的公钥,离职同事的访问权限第一时间清理掉。
验证整体安全性所有配置完成后,做一次全面验证。用nmap扫描一下自己的服务器,确认新端口已开放,旧端口已关闭:
nmap -p 22,26489 服务器IP
22端口应该显示closed或filtered,新端口显示open。再尝试用密码连接,应该被拒绝并提示Permission denied。检查SSH日志确认Fail2ban在正常工作:
sudo tail -f /var/log/auth.log
日志里能看到失败的登录尝试,以及Fail2ban的封禁记录。如果一切正常,这台Ubuntu服务器的SSH安全性已经达到了相当高的水准。后续只需定期更新系统,保持软件包在最新版本,基本可以抵御绝大多数针对SSH的攻击。
