Linux服务器如何修改SSH端口?配置方法与安全注意事项

把 SSH 从默认的 22 端口改到别的端口,是很多运维教程里的第一条"加固建议"。它确实有用,能挡掉大量无差别扫描和自动爆破,日志会清净很多。但它也是新手最容易把自己锁在门外的操作:改完配置一重启,新端口连不上,旧连接一断,就只能去机房或者求救控制台。

这篇文章给出 RHEL、Rocky、CentOS 与 Debian、Ubuntu 两套完整步骤,覆盖 SELinux 的 semanage port 处理、firewalld 与 ufw 的放行、验证清单和回滚方案。核心原则只有一条:在确认新端口能成功登录之前,绝不关闭当前的连接。全文的操作都围绕这个原则设计。

先搞清楚改端口能解决什么

改端口的真实作用是减少噪音,而不是提升安全性。互联网上大量自动化脚本只扫 22 端口,换到高位端口后,日志里的失败登录从每天几千条降到接近零,这让真正的异常更容易被发现。有运维经验的人会注意到,改端口后日志信噪比的提升,往往比省下的那点 CPU 更有价值。

但它不能防住针对性攻击。攻击者只要做一次全端口扫描,就能发现你的 SSH 端口;端口扫描对现代工具来说成本极低。所以它属于"减少暴露"的低成本措施,不能替代密钥登录、禁止 root 登录、限制来源 IP、fail2ban 这些真正的加固手段。把改端口当成安全的全部,是危险的误解。

措施 作用 是否依赖改端口
改默认端口 减少无差别扫描和日志噪音 —
禁用密码、只用密钥 防爆破,效果显著 否
禁止 root 直接登录 降低被攻破后的危害 否
fail2ban 自动封禁爆破来源 否
防火墙限制来源 IP 只放行可信出口,效果最强 否
改端口 低成本,见效快 —

结论是:改端口值得做,但它是组合拳里的一招,不是全部。如果条件允许,限制来源 IP 配合密钥登录的效果远好于单纯改端口。

操作前的三项准备

第一,保留一个已登录的会话。 如果你现在有 SSH 连接,这个窗口在整个操作过程中都不要关。所有验证都在另外开的新窗口里做。这是唯一的保险。

第二,确认带外通道可用。 主流云厂商控制台提供 VNC 或串口终端,它不经过网络,是最后的安全网。动手前先登录一次确认能用,并确认密码或密钥可用。没有带外通道时,风险显著上升,建议改在业务低峰且有应急联系人时操作。

第三,备份配置并记录现状。

sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F-%H%M)
sudo ls -l /etc/ssh/sshd_config*
sudo sshd -T | grep -i '^port'
sudo ss -lntp | grep sshd

记录当前实际监听的端口和配置文件路径,出错时才能快速还原。同时注意 Debian、Ubuntu 的服务名是 ssh,RHEL、Rocky、CentOS 是 sshd,两者不要混用。

另外提一句,Ubuntu 较新版本启用了 socket 激活(systemd socket activation),端口可能由 /lib/systemd/system/ssh.socket 控制,只改 sshd_config 不生效。检查方法:

systemctl status ssh.socket 2>/dev/null
grep -i port /lib/systemd/system/ssh.socket 2>/dev/null

如果 ssh.socket 处于激活状态,需要同时修改 socket 文件里的 ListenStream 并执行 systemctl daemon-reload,否则改完配置后服务仍监听旧端口。这是很多人踩过的坑。

选择端口号

建议选择一万到六万之间、不与其他服务冲突的端口,避开常见服务端口。可以先看看本机已经用了哪些端口,避免撞车:

sudo ss -lntu | awk '{print $5}' | grep -oP ':\K[0-9]+$' | sort -n | uniq

选一个没出现的高位端口,例如 2222 或 58222。注意 2222 虽然常见,但也在自动扫描的常见列表里,若追求更低噪音可选更冷门的数值。无论选哪个,都要确认它不是知名服务端口,可查 /etc/services。

完整操作步骤

以下步骤请按顺序执行,每一步都不要跳过验证。

第一步,备份并编辑配置文件。

sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
sudo vi /etc/ssh/sshd_config

找到 Port 那一行。默认它可能被注释掉:

#Port 22

建议的做法是先同时保留两个端口,等新端口验证通过后再移除旧的:

Port 22
Port 2222

sshd 支持多行 Port,会同时监听所有列出的端口。这种"双端口过渡"的方式是风险最低的做法,强烈推荐。如果你一定要一步到位,就只写新端口,但务必保证后续验证环节做到位。

第二步,校验配置语法。

sudo sshd -t && echo "语法正常"

这条命令不会启动服务,只做语法检查。如果报错,会给出文件名和行号。语法不通过时绝对不要重启服务。

第三步,处理 SELinux(仅 RHEL 系需要)。

这是 RHEL、Rocky、CentOS 上最容易被忽略、也最容易导致失败的一步。SELinux 默认只允许 sshd 绑定少数几个端口,直接改成新端口后,服务会启动失败并报 Bind to port 2222 failed: Permission denied。

先确认 SELinux 状态:

getenforce
sestatus

如果是 Enforcing 或 Permissive,都需要登记端口:

# 安装管理工具
sudo dnf install -y policycoreutils-python-utils

# 查看当前 ssh 允许的端口
sudo semanage port -l | grep ssh

# 登记新端口
sudo semanage port -a -t ssh_port_t -p tcp 2222

# 再次确认
sudo semanage port -l | grep ssh

如果提示端口已存在,用 -m 修改而不是 -a 添加:

sudo semanage port -m -t ssh_port_t -p tcp 2222

Debian、Ubuntu 默认使用 AppArmor 而非 SELinux,不需要这一步。

第四步,放行防火墙。

# RHEL、Rocky、CentOS(firewalld)
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

# Debian、Ubuntu(ufw)
sudo ufw allow 2222/tcp
sudo ufw reload
sudo ufw status verbose

云服务器还要在控制台的安全组中放行该端口的入方向,这一步经常漏,导致系统防火墙全对但依然连不上。安全组是云平台侧的访问控制,优先级在系统防火墙之前,两者都要通。

第五步,重启服务。

# RHEL、Rocky、CentOS
sudo systemctl restart sshd

# Debian、Ubuntu
sudo systemctl restart ssh

如果之前启用了 socket 激活的 Ubuntu,需要先停用 socket:

sudo systemctl disable --now ssh.socket
sudo systemctl enable --now ssh.service
sudo systemctl daemon-reload
sudo systemctl restart ssh

第六步,确认监听已生效。

sudo ss -lntp | grep sshd
sudo sshd -T | grep -i '^port'
sudo systemctl status sshd --no-pager

必须看到新端口出现在监听列表里,才能进行下一步。

验证新端口(关键一步)

另开一个终端窗口,不要关掉原来的连接,用新端口测试连接:

ssh -p 2222 user@server_ip

如果登录成功,再检查这些细节:

# 确认登录方式正确
ssh -p 2222 user@server_ip 'echo 登录正常; hostname; whoami'

# 确认 scp、sftp 也能用
scp -P 2222 ./test.txt user@server_ip:/tmp/

注意 scp 用大写 -P 指定端口,ssh 用小写 -p,这是个常见的小坑。

如果新端口连不上,立刻回到原连接排查,不要断开。常见原因按顺序查:

sudo ss -lntp | grep sshd              # 服务是否真的在听新端口
sudo journalctl -u sshd -n 50 --no-pager   # 启动日志有无报错
sudo firewall-cmd --list-ports         # 防火墙是否放行
sudo semanage port -l | grep ssh       # SELinux 是否登记
nc -vz -w 3 server_ip 2222             # 从外部看端口是否可达

从外部用 nc 测试很重要,它能区分"本机监听正常但外部不通"(安全组或防火墙)和"本机根本没监听"(服务或配置问题)。

只有新端口确认可用之后,才回到配置文件删除旧的 22 端口,然后再次重启服务并验证:

sudo vi /etc/ssh/sshd_config    # 删除 Port 22 那一行
sudo sshd -t
sudo systemctl restart sshd
sudo ss -lntp | grep sshd

此时仍然不要断开当前连接,再用一个新窗口连一次,成功后才能放心断开旧会话。

回滚方法

任何时候新端口不可用,立即回滚。回滚的前提是你还留着那个旧连接。

方案一:直接还原配置文件。

sudo cp -a /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
sudo sshd -t
sudo systemctl restart sshd
sudo ss -lntp | grep sshd

方案二:改回 22 端口。 如果备份文件丢失,手工编辑配置,把 Port 改回 22,再重启。

方案三:SELinux 登记回滚。

sudo semanage port -d -t ssh_port_t -p tcp 2222

方案四:带外通道修复。 如果已经断开且无法连接,只能通过云控制台的 VNC 或串口终端登录,按上述步骤还原。所以前面强调的"保留会话 + 确认带外通道"不是形式主义,是真正的保命措施。

风险提示: 不要在改端口的同时修改其他 SSH 参数(比如同时禁用密码登录、禁止 root 登录、限制来源 IP)。一次只改一处,出问题才好定位。多项加固分开做,每次验证通过再继续。

顺手完成的配套加固

新端口稳定后,可以考虑在同一个配置文件里完成其余加固,但建议逐项修改、逐项验证。

# /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers ops

每项的含义:禁止 root 直接登录需要你先有可用的普通用户和 sudo 权限;禁用密码登录必须先确认密钥登录已验证可用;AllowUsers 一旦启用,名单外用户会被拒绝,务必把自己列进去。

改完同样要 sshd -t 校验,并在新窗口验证成功后才断开旧连接。这个流程适用于所有 SSH 配置变更,不只是改端口。

常见问题

改完端口服务起不来,sshd -t 也没报错,为什么?

大概率是 SELinux 没登记新端口。看 journalctl -u sshd 里有没有 Permission denied 或 Failed to bind。用 semanage port -a -t ssh_port_t -p tcp 新端口 登记后重启。临时验证可以用 setenforce 0 关闭 SELinux 再试,确认是这个原因后记得恢复为 Enforcing。

为什么本机 ss -lntp 能看到端口,外面还是连不上?

从外到内依次是云安全组、系统防火墙、服务监听。本机看到监听只说明第三层正常。用 nc -vz -w 3 你的公网IP 端口 从另一台机器测试,同时检查控制台安全组的入方向规则。

同时保留 22 和新端口会不安全吗?

短期过渡是安全的,而且推荐这么做。真正的风险是忘记收尾,长期留着 22。建议在新端口验证通过后立刻移除旧端口,并在日历上做个标记。

Ubuntu 改完配置端口没变怎么办?

新版本 Ubuntu 可能启用了 ssh.socket,端口由 socket 单元控制。检查 systemctl status ssh.socket,停用 socket 并启用 service,或者同时修改 socket 文件里的 ListenStream 后 systemctl daemon-reload。

能不能用防火墙做端口转发,不用改 sshd 配置?

可以,用 firewall-cmd --add-forward-port 或 iptables 的 NAT 规则把外部端口转发到内部 22。这样 sshd 不用改,回滚简单。但它只是把暴露点换了个位置,安全性提升有限,且多一层故障点,一般不作为首选。

总结

  • 改端口前必须保留现有会话、确认带外通道可用、备份配置文件,三者缺一不可。
  • 采用"双端口过渡"策略:先让 sshd 同时监听 22 和新端口,验证通过后再移除旧端口。
  • RHEL 系必须执行 semanage port -a -t ssh_port_t -p tcp 新端口,否则服务会因 SELinux 拒绝绑定而启动失败。
  • firewalld、ufw 与云安全组三层都要放行,验证时用外部 nc 测试,能快速区分是服务问题还是访问控制问题。
  • 新端口连续验证成功(登录、scp、重启后自启都正常)之前,绝对不要断开旧连接;改端口只是降噪手段,真正的加固是密钥登录、禁 root、限来源和 fail2ban。