把默认的22端口改成高位端口,并彻底禁用密码登录,是加固Ubuntu服务器SSH安全最直接、最有效的两个步骤。这能立刻阻断99%的自动化扫描和暴力破解攻击。下面直接讲具体操作和背后的安全逻辑。
为什么要立刻变更SSH默认端口
互联网上无时无刻都有僵尸网络在扫描22端口,一旦发现开放,就会立即尝试常见用户名和弱密码组合进行登录。这不仅仅是登录成功与否的问题,持续的暴力破解会产生大量日志,消耗CPU和带宽资源。把端口改成高位端口,比如介于49152到65535之间的一个随机数,相当于把你的服务从“众目睽睽之下”移到了一个“隐蔽的角落”。扫描器通常只扫默认端口,没那么多资源全端口扫描,你的服务瞬间就“安静”了。这不是安全依赖隐匿,而是极大地降低了被攻击的概率,属于纵深防御的第一层过滤。
具体操作:修改SSH服务端口
在Ubuntu系统上,变更端口只需要修改一个配置文件。先用root或具有sudo权限的用户登录,然后编辑SSH守护进程的配置文件。
sudo nano /etc/ssh/sshd_config
在文件中找到被注释掉的 #Port 22 这一行。去掉前面的井号,并把22改成你选定的高位端口号,比如 Port 49872。强烈建议在修改前,先用 netstat -tlnp 命令检查一下本地已占用的端口,避免冲突。修改后保存并退出。
变更端口时的防火墙与SELinux/AppArmor配置
这是很多人操作失败导致无法远程连接的关键一步。如果你正在使用UFW防火墙,必须立即允许新的端口通过。
sudo ufw allow 49872/tcp
如果你用的是云服务器,比如阿里云、腾讯云或华为云,还必须登录云控制台,在安全组规则里,添加入方向允许这个新端口的TCP访问规则。这一步必须在重启SSH服务前完成,否则你会立刻被锁在服务器外面。Ubuntu默认使用AppArmor,通常不会主动限制端口变更,但如果你手动配置过严格的网络相关策略,需要检查一下。SELinux在Ubuntu上默认不安装,如果是CentOS等系统迁移过来的习惯,可以忽略。
验证新端口并保留旧端口作为过渡
在完全切换到新端口前,最安全的做法是让新旧端口同时工作一段时间。可以在 sshd_config 文件中添加两行 Port 指令。
Port 22 Port 49872
保存配置后,用 sudo systemctl restart sshd 重启服务。然后,新开一个终端窗口,尝试用新端口连接服务器。
ssh -p 49872 your_user@your_server_ip
确认新端口连接完全正常后,再回到配置文件里删除或注释掉 Port 22 这一行,再次重启SSH服务,并移除UFW里对22端口的允许规则,同时从云安全组中删除22端口规则。至此,端口变更彻底完成。
禁用密码登录的绝对必要性
无论你把端口改得多高,只要密码登录还开着,风险就依然存在。密码是安全链中最薄弱的一环,用户习惯设置的密码强度远远低于系统能抵御的攻击强度。键盘记录、撞库、社会工程学攻击,都能让一个看似复杂的密码瞬间失效。SSH密钥对采用的是非对称加密,私钥永远不会离开你的电脑,其安全强度是密码无法比拟的。禁用密码登录,就是从根源上消灭了暴力破解的可能性。
前提准备:生成并部署SSH密钥对
在禁用密码之前,必须确保你的公钥已经正确部署到服务器上,否则你同样会被锁在外面。在你本地的电脑(可以是Windows、macOS或另一台Linux)上生成密钥对。
ssh-keygen -t ed25519 -C "your_email@example.com"
这里推荐使用Ed25519算法,它比传统的RSA更安全、更快,密钥也更短。一路回车即可,可以设置一个强密码来保护你的私钥,这样即使私钥泄露,攻击者也无法直接使用。生成后,把公钥复制到服务器上。
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 49872 your_user@your_server_ip
这个命令会自动把公钥内容追加到服务器上对应用户家目录的 ~/.ssh/authorized_keys 文件中,并设置好正确的权限。手动操作的话,务必确保 ~/.ssh 目录权限是700,authorized_keys 文件权限是600,否则SSH服务会因安全原因拒绝使用该公钥。
执行禁用密码登录的操作
再次确认你已经能用密钥通过新端口成功登录后,就可以进行最后一步了。编辑SSH配置文件。
sudo nano /etc/ssh/sshd_config
找到以下几个关键指令,确保它们的状态如下。
PasswordAuthentication no ChallengeResponseAuthentication no UsePAM yes PubkeyAuthentication yes
PasswordAuthentication no 是直接禁用密码登录的核心指令。ChallengeResponseAuthentication no 则禁用了基于键盘交互的质询响应认证,这也是一种密码形式,必须一起关闭。保持 UsePAM yes 通常没问题,但如果你追求极致安全且完全理解PAM配置,可以设为no,但一般不建议。最后确保 PubkeyAuthentication yes 是开启状态。保存文件,重启服务。
sudo systemctl restart sshd
不要退出当前的SSH连接,新开一个终端窗口尝试用密钥登录。如果成功,说明配置生效。如果失败,你还有当前的连接可以回滚配置。这就是“保留一个活动会话”的黄金法则。
进阶加固:限制用户和IP访问
变更端口和禁用密码是基础,你还可以做更多。在 sshd_config 文件末尾添加 AllowUsers your_specific_user,可以只允许特定用户SSH登录,彻底断绝其他系统账户的远程访问可能。如果你的登录IP是固定的,可以在UFW或云安全组里,把新端口的来源IP限制为你自己的IP地址,这样即使端口被发现,别人也无法连接。
配置失败排查与回滚
如果因配置错误导致无法连接,不要慌。如果你使用的是云服务器,可以通过云服务商提供的VNC或远程连接功能,直接以控制台方式登录服务器,不受SSH配置影响。登录后,检查 /var/log/auth.log 日志文件,里面会详细记录SSH认证失败的原因,比如权限错误、密钥格式不对等。修正配置后重启服务即可。这是最后的保障手段。
安全性与可用性的平衡见解
很多人担心改端口后自己会忘记,或者觉得太麻烦。我的看法是,安全措施一定要和你的威胁模型匹配。如果只是一台个人测试机,可能觉得无所谓。但任何暴露在公网上的、有数据的服务器,这两步就是底线。你可以在本地SSH客户端配置文件 ~/.ssh/config 里为你的服务器设置别名、端口和密钥路径,这样日常登录只需要一个简单的 ssh my_server 命令,完全不会增加操作复杂度。安全不应该成为效率的阻碍,通过合理的配置,两者完全可以兼得。
