香港服务器安全加固怎么做:限制端口、密钥登录与操作审计

在一个典型的香港服务器运维现场,工程师发现服务器可以远程登录,但 22 端口对所有来源开放,系统中还保留着多个可交互登录账号,关键配置变更也只能从零散的 Shell 历史中追溯。此时不应直接关闭端口或禁用 root,而应先确认当前连接方式、业务监听端口和可用的带外控制台,避免把自己锁在服务器外。
香港服务器的安全加固,核心可以归纳为四个动作:只暴露业务必需端口;将 SSH 管理入口限制到可信来源;使用密钥和最小权限替代共享密码与长期 root 登录;通过系统日志和审计规则记录登录、提权及关键文件变化。每完成一项,都要从本机配置和外部访问两侧验证。
先确认现场状态和回滚条件
加固前至少保留一个当前可用的 SSH 会话,并确认具备以下条件:
- 有一个已经验证可以使用
sudo的管理账号; - 已经准备好该账号的 SSH 公钥,私钥保存在管理终端,不上传到服务器;
- 能够通过云控制台、串口或其他带外方式进入服务器;
- 知道业务实际需要哪些 TCP、UDP 端口;
- 已记录当前防火墙规则、SSH 配置和监听服务。
先查看监听端口和运行中的服务。以下命令适用于大多数使用 systemd 的 Linux 发行版:
sudo ss -lntup
sudo systemctl --type=service --state=running
sudo systemctl --failed
判断端口时,重点看监听地址:
127.0.0.1:端口通常只允许本机访问;0.0.0.0:端口表示监听所有 IPv4 地址;[::]:端口表示可能监听所有 IPv6 地址;- 监听在公网地址上不等于一定能从公网访问,还要结合本机防火墙和上游访问控制判断。
记录规则可以使用:
sudo ufw status numbered 2>/dev/null || true
sudo firewall-cmd --get-active-zones 2>/dev/null || true
sudo firewall-cmd --zone=public --list-all 2>/dev/null || true
ufw 主要见于 Ubuntu、Debian 等系统,firewalld 主要见于部分 RHEL 系发行版。不要在未确认防火墙类型和活动区域前,直接执行清空规则或重置命令。
根据监听结果确定应该开放什么
端口加固不是简单地“端口越少越好”,而是让每个开放端口都能对应到明确的业务或管理用途。工程师可以把 ss 的结果与服务清单逐项对应:
| 端口状态 | 常见含义 | 处理判断 |
|---|---|---|
| 业务确实使用,且需要公网访问 | 对外业务入口 | 仅允许必要协议,并结合应用层认证 |
| 业务使用,但只需本机访问 | 内部组件或本地代理 | 优先绑定 127.0.0.1 或 Unix Socket |
| 只有运维使用 | SSH 或其他管理入口 | 限制来源地址,不对所有公网地址开放 |
| 找不到对应服务 | 未知监听或遗留组件 | 先确认进程和业务影响,再停用或卸载 |
| IPv4 已限制、IPv6 仍开放 | 双栈规则不一致 | 同时检查 IPv4 和 IPv6 访问路径 |
确认进程归属后,再决定是否停止服务:
sudo ss -lntup
sudo systemctl status SERVICE_NAME
sudo systemctl cat SERVICE_NAME
SERVICE_NAME 必须替换为实际服务名。对于未知端口,不应直接执行 kill -9 或删除服务文件。先查看进程、依赖和启动方式;如果确认不再使用,再通过发行版对应的包管理器或 systemctl disable --now 停止,并保留回滚记录。
SSH 使用密钥,并在验证后关闭密码登录
先建立第二条可用的登录路径
在管理终端生成密钥时,推荐使用支持 Ed25519 的 OpenSSH:
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519
私钥应保留在管理终端,并设置保护口令。将公钥放入目标账号的 authorized_keys,可以在仍允许密码登录的阶段使用:
ssh-copy-id -i ~/.ssh/id_ed25519.pub USER@SERVER_IP
如果系统没有 ssh-copy-id,也可以通过服务器控制台手工追加公钥,但不要覆盖原有 authorized_keys。权限应符合以下状态:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R USER:USER ~/.ssh
其中 USER 必须替换成实际账号。执行 chown 前要确认家目录和账号归属,错误的属主会导致公钥认证失败。
从管理终端测试密钥登录:
ssh -o PreferredAuthentications=publickey \
-o PasswordAuthentication=no \
USER@SERVER_IP
只有在这条连接成功、并且账号能够正常执行必要的 sudo 操作后,才适合关闭密码登录。测试时不要先退出原有 SSH 会话。
修改 SSH 配置并校验语法
先备份配置:
sudo cp -a /etc/ssh/sshd_config \
/etc/ssh/sshd_config.before-hardening
在 /etc/ssh/sshd_config 中确认或调整以下配置:
PubkeyAuthentication yes
PermitRootLogin no
PasswordAuthentication no
PermitEmptyPasswords no
MaxAuthTries 3
KbdInteractiveAuthentication no 是否启用,要看服务器是否依赖基于键盘交互的多因素认证。如果现有 MFA 或 PAM 登录流程依赖该方式,不应未经测试就关闭。
修改后先检查语法和生效配置:
sudo sshd -t
sudo sshd -T | grep -E \
'^(pubkeyauthentication|permitrootlogin|passwordauthentication|permitemptypasswords|maxauthtries)'
sshd -t 没有输出通常表示语法检查通过;但它不能证明防火墙、账号权限和密钥本身都正确。确认无误后再重载服务。Ubuntu、Debian 常见服务名为 ssh,部分 RHEL 系系统常见服务名为 sshd:
# Ubuntu、Debian 常见写法
sudo systemctl reload ssh
# 部分 RHEL 系系统
sudo systemctl reload sshd
随后从另一终端重新登录验证。若新连接失败,保留的旧会话仍可用于恢复配置。
是否更换 SSH 端口
单纯把 SSH 从 22 改成其他端口,只能减少部分自动化扫描,不能替代来源地址限制、密钥认证和补丁管理。如果确实需要更换端口,必须同时修改:
- SSH 配置中的
Port; - 本机防火墙;
- 上游访问控制;
- 管理终端的 SSH 连接参数。
例如配置为 2222 后,应先从管理终端测试:
ssh -p 2222 USER@SERVER_IP
确认新端口可用后,再删除旧端口规则。配置中如果存在多个 Port,应先用以下命令确认最终状态:
sudo sshd -T | grep '^port '
限制端口和来源地址
Ubuntu、Debian 使用 UFW 的场景
先查看当前规则,确认没有现成的业务放行项会被覆盖:
sudo ufw status numbered
假设管理终端的固定公网地址为 203.0.113.10,应将示例地址替换为真实地址。先放行受限的 SSH 规则,再考虑删除宽泛的 22/tcp 规则:
sudo ufw allow from 203.0.113.10 to any port 22 proto tcp
如果业务确实需要 HTTP 和 HTTPS,再分别放行:
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
不需要公网访问的端口不要照抄添加。确认受限规则已经存在后,若原来有对所有来源开放的 SSH 规则,再删除对应的宽泛规则:
sudo ufw delete allow 22/tcp
最后设置默认策略时要特别谨慎:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw status verbose
如果 UFW 尚未启用,执行 sudo ufw enable 可能立即改变远程访问结果。应先确认管理来源、业务端口和 IPv6 规则,再从保留的 SSH 会话或控制台执行。
使用 firewalld 的场景
先确认活动区域,不要默认假设一定是 public:
sudo firewall-cmd --get-active-zones
sudo firewall-cmd --zone=ZONE --list-all
将 ZONE 替换为实际区域。可以先添加只允许管理地址访问 SSH 的永久规则,再删除区域中原有的广泛 SSH 服务规则:
sudo firewall-cmd --permanent --zone=ZONE \
--add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port port="22" protocol="tcp" accept'
sudo firewall-cmd --permanent --zone=ZONE --remove-service=ssh
sudo firewall-cmd --reload
如果管理端使用 IPv6,还需要单独设计 IPv6 来源规则;只写 IPv4 规则并不能覆盖 IPv6 访问路径。--remove-service=ssh 可能影响该区域中原有的 SSH 访问,执行前应确认受限规则已经添加,并保留控制台回滚能力。
从服务器外部的授权主机测试端口:
nc -vz SERVER_IP 22
如果 SSH 只允许管理地址访问,应分别从允许地址和不允许地址测试。允许地址无法连接时,依次检查 SSH 监听状态、本机防火墙、上游防火墙和源地址是否发生变化。非管理地址无法连接,可能表现为连接被拒绝或超时,具体取决于防火墙的处理策略。
落实最小权限和系统补丁
密钥登录解决的是“如何认证”,并不代表登录账号拥有合理权限。服务器应使用个人账号而不是多人共享账号,日常操作使用普通账号,只有需要时通过 sudo 提权。
先检查可登录账号和管理组:
getent passwd
getent group sudo 2>/dev/null || true
getent group wheel 2>/dev/null || true
sudo -l -U USER
确认新管理账号可以执行必要操作后,再考虑禁止 root 直接 SSH 登录。不要在尚未验证替代账号之前设置 PermitRootLogin no,否则可能只剩控制台恢复。
如果确实需要限制某个账号的管理范围,可以使用独立的 sudoers 文件,并通过 visudo 校验:
sudo visudo -f /etc/sudoers.d/ops
配置示例:
ops ALL=(root) /usr/bin/systemctl restart app.service, /usr/bin/journalctl -u app.service
这里的 app.service 只是示例,应替换为实际服务。不要为了方便直接授予:
ops ALL=(ALL) ALL
除非已经明确评估了该账号的管理范围。保存后检查权限和语法:
sudo chmod 440 /etc/sudoers.d/ops
sudo visudo -c
补丁更新也应纳入加固流程。先查看可更新内容,再安排维护窗口。Debian、Ubuntu 常见方式如下:
sudo apt update
apt list --upgradable
确认业务兼容、备份有效后再执行升级:
sudo apt upgrade
使用 DNF 的系统可以先检查:
sudo dnf check-update
该命令在存在可更新软件包时可能返回特定退出码,不应仅凭退出码判断命令失败。确认维护窗口后再执行:
sudo dnf upgrade --refresh
升级后检查服务状态、监听端口和当前内核:
sudo systemctl --failed
sudo ss -lntup
uname -r
涉及内核或关键库更新时,可能需要重启才能真正使用新版本。重启前应确认业务具备恢复条件,并通过控制台或其他方式保留救援路径。
用操作审计记录登录、提权和关键变更
Shell 历史只能作为辅助线索,不能替代审计:历史记录可能被清理,也无法可靠覆盖通过脚本、服务或其他会话执行的命令。可以使用 auditd 记录关键文件变化和用户执行行为。
先确认系统是否安装并运行审计服务:
sudo systemctl status auditd
sudo auditctl -s
在支持 /etc/audit/rules.d/ 的系统中,可以创建规则文件:
sudo vi /etc/audit/rules.d/50-hardening.rules
示例规则如下:
-w /etc/ssh/sshd_config -p wa -k ssh_config
-w /etc/sudoers -p wa -k privilege
-w /etc/sudoers.d/ -p wa -k privilege
-w /etc/passwd -p wa -k identity
-w /etc/group -p wa -k identity
-a always,exit -F arch=b64 -S execve -F auid>=1000 -F auid!=4294967295 -k user_commands
这些规则分别关注 SSH 配置、sudo 授权文件、账号和用户命令。execve 规则可能产生较多日志,适合先评估磁盘空间和日志量,再决定是否扩大范围。不要在尚未验证规则前加入 -e 2,因为该选项会锁定审计规则,通常需要重启才能修改。
加载并检查规则:
sudo augenrules --load
sudo auditctl -l
查询审计结果:
sudo ausearch -k ssh_config -i
sudo ausearch -k privilege -i
sudo ausearch -k identity -i
sudo ausearch -k user_commands -ts today -i
登录和 sudo 事件还可以结合系统日志查看。不同发行版的 SSH 服务名可能不同:
sudo journalctl -u ssh --since today
sudo journalctl -u sshd --since today
sudo journalctl --since today | grep -Ei 'sudo|authentication|session'
审计日志需要监控磁盘空间:
df -h
sudo du -sh /var/log/audit 2>/dev/null
本地 root 权限一旦被攻破,攻击者可能修改或删除本地日志。因此,对需要较强追溯能力的环境,应将关键日志转发或备份到权限隔离的独立日志存储中。审计能记录“谁在什么时候做了什么”,但不能替代应用自身的订单、文件、数据库或接口操作日志。
加固后的验证与回滚
完成变更后,建议按以下顺序验证,先验证低风险项目,再验证远程访问:
- 本机确认 SSH 配置通过语法检查,且服务仍在监听预期地址和端口。
- 使用密钥从新终端登录,确认普通账号可以执行需要的
sudo操作。 - 从允许的管理地址测试 SSH,从不允许的地址确认访问被拦截。
- 从外部测试业务端口,只验证实际需要的端口。
- 查看
systemctl --failed、SSH 日志、sudo 日志和审计规则。 - 检查 IPv4、IPv6 是否存在不一致的放行路径。
- 检查升级后服务、定时任务和日志写入是否正常。
如果 SSH 配置导致新连接失败,可在保留的旧会话或控制台中恢复:
sudo cp -a /etc/ssh/sshd_config.before-hardening \
/etc/ssh/sshd_config
sudo sshd -t
sudo systemctl reload ssh
如果使用的是 sshd 服务名,应将最后一条命令替换为:
sudo systemctl reload sshd
防火墙回滚应优先删除本次添加的规则,而不是长期关闭防火墙。只有在控制台确认服务器处于可控状态时,才可临时执行 ufw disable 进行故障定位,因为这会使本机所有入站过滤失效。firewalld 则应删除对应的 rich rule,再执行 firewall-cmd --reload。上游防火墙或外部访问控制仍需单独恢复,不能只回滚服务器本地规则。
复盘时容易漏掉的检查项
- 只限制了 IPv4,却忘记检查
[::]监听和 IPv6 防火墙; - 禁用了密码认证,却没有测试密钥文件权限、账号家目录属主和 PAM 行为;
- 删除了宽泛 SSH 规则,却没有先添加管理来源的受限规则;
- 关闭 root 登录前,没有确认普通管理账号能使用
sudo; - 只看
sshd_config文件,没有用sshd -T检查最终生效配置; - 审计规则已经加载,但
/var/log/audit没有空间监控; - 只保留服务器本地日志,没有考虑 root 权限被取得后的日志篡改;
- 补丁更新后没有检查服务状态、监听端口和是否需要重启;
- 使用共享账号操作,导致审计记录无法对应到具体人员;
- 端口表中遗漏了 UDP 服务,或把“本机监听”误判成“公网必须开放”。
这样处理后,香港服务器的安全边界才不只是“改了几个配置项”,而是能够明确知道哪些端口对外开放、谁可以登录、登录后能做什么,以及关键操作发生后能否被验证和追溯。



