服务器安全加固方案

结论: 服务器安全加固不是一份操作清单,而是一套分层方案——按账户、网络、系统、应用、数据、审计六层建立基线标准,用"紧急/高/中"三级优先级排定实施路线图,并通过自动化扫描与季度复查验证加固效果。有效的加固方案应能在 5 个工作日内完成首批落地,并把基线符合率从不足 50% 提升到 90% 以上。

引言:从"做几项加固"到"建立一套加固体系"

很多团队理解的"服务器安全加固"是做完下面几件事:改 SSH 端口、禁 root 登录、装个 fail2ban、开防火墙。这些动作本身没错,但它们是点状操作,无法回答三个管理者必然要问的问题:

  1. 我们做了多少?还差多少?(覆盖率)
  2. 做到什么程度算合格?(基线标准)
  3. 半年后还是合格的吗?(持续符合性)

这三个问题决定了"操作清单"和"加固方案"的本质区别。清单解决"做什么",方案解决"做多少、做到什么程度、怎么验证、怎么维持"。本文的定位正是后者:给出六层加固体系、可参考的基线标准(含等保 2.0 常识性要求)、可排期的实施路线图与优先级表,以及加固后的验证与复查方法。

需要说明:等保 2.0(GB/T 22239-2019)的正式测评由具备资质的测评机构执行,本文仅提取其中与安全加固直接相关的常识性技术要求作为参考基线,不能替代正式测评。文中命令以 Rocky Linux 9 / Ubuntu 24.04 LTS 为例,截至 2026 年主流发行版均已默认启用 systemd。

一、加固体系的六层模型

服务器安全的攻击面可以拆成六个层次,每层有独立的加固目标和失效后果。理解这个模型,是制定方案的前提。

层次加固目标典型措施失效后果
账户层身份可信、权限最小禁 root 直登、密钥登录、sudo 授权、账号清理、口令策略攻击者直接获得 shell
网络层暴露面最小防火墙白名单、关闭无用端口、安全组、VPN/堡垒机接入任意端口被扫描利用
系统层内核与包可信补丁更新、内核参数、文件权限、服务最小化、SELinux提权、持久化
应用层软件无漏洞版本升级、配置安全、禁用危险函数、容器镜像扫描WebShell、RCE
数据层保密与可恢复传输加密、存储加密、3-2-1 备份、恢复演练数据泄露、勒索不可用
审计层可追溯集中日志、审计规则、文件完整性监控、告警事后无法溯源

为什么必须是六层?因为任一层的单点缺失都会让其他层的投入归零。举例:账户层做得再好(密钥登录),如果网络层把 Redis 6379 暴露在公网且无密码,攻击者无需任何身份即可拿到 shell;反之,网络层收紧了但审计层缺失,被入侵后你连入口在哪都不知道。

六层模型的实践价值在于:它把"安全"从一个模糊目标变成了六张可勾选的检查表,每张表都能量化完成度。

二、账户层加固:身份是第一道门

账户层的核心原则是三句话:不用共享账号、不用密码登录、不给多余权限。

2.1 基线要求

  • 禁止 root 直接 SSH 登录,改为普通用户 + sudo。
  • SSH 强制公钥认证,禁用密码认证(PasswordAuthentication no)。
  • 远程管理账号纳入白名单(AllowUsers / AllowGroups)。
  • 口令复杂度:长度 ≥ 12 位,含大小写字母、数字、特殊字符;有效期 ≤ 90 天;不得复用最近 5 次口令。
  • 登录失败 5 次锁定 10 分钟(对应等保 2.0 的"身份鉴别-登录失败处理")。
  • 空闲会话超时自动断开(TMOUT / ClientAliveInterval)。
  • 清理无用账号:UID=0 的非 root 账号、无口令账号、过期不用的账号。

2.2 可执行的加固配置

bash
# 1. 创建运维账号并授权 sudo(以 opsuser 为例)
useradd -m -s /bin/bash opsuser
mkdir -p /home/opsuser/.ssh && chmod 700 /home/opsuser/.ssh
# 将公钥写入 authorized_keys 后:
chmod 600 /home/opsuser/.ssh/authorized_keys
chown -R opsuser:opsuser /home/opsuser/.ssh
echo "opsuser ALL=(ALL) NOPASSWD:/usr/bin/systemctl,/usr/bin/journalctl" > /etc/sudoers.d/opsuser
chmod 440 /etc/sudoers.d/opsuser

# 2. SSH 加固(改前务必保留一个已登录会话,避免锁死自己)
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
cat > /etc/ssh/sshd_config.d/99-hardening.conf <<'EOF'
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 30
ClientAliveInterval 300
ClientAliveCountMax 2
AllowUsers opsuser
X11Forwarding no
AllowAgentForwarding no
EOF
sshd -t && systemctl restart sshd     # sshd -t 先做语法校验,防止配错锁死
bash
# 3. 口令策略(PAM)
# RHEL/Rocky 系:
authselect select sssd with-pamaccess --force 2>/dev/null
cat > /etc/security/pwquality.conf <<'EOF'
minlen = 12
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
remember = 5
EOF
# 口令有效期
sed -i 's/^PASS_MAX_DAYS.*/PASS_MAX_DAYS   90/' /etc/login.defs
sed -i 's/^PASS_MIN_DAYS.*/PASS_MIN_DAYS   1/'  /etc/login.defs
sed -i 's/^PASS_WARN_AGE.*/PASS_WARN_AGE   7/'  /etc/login.defs
chage -M 90 opsuser
bash
# 4. 登录失败锁定(faillock / pam_tally2)
# /etc/pam.d/system-auth 与 /etc/pam.d/password-auth 中加入:
# auth    required    pam_faillock.so preauth silent deny=5 unlock_time=600
# auth    [default=die] pam_faillock.so authfail deny=5 unlock_time=600
# account required    pam_faillock.so

# 5. 清理无用账号与可疑账号
awk -F: '$3==0 {print "UID0:", $1}' /etc/passwd                 # 除 root 外不应有其他
awk -F: '($2=="") {print "空口令:", $1}' /etc/shadow            # 不应有输出
awk -F: '$3>=1000 && $7 !~ /nologin|false/ {print $1}' /etc/passwd   # 可登录普通账号清单
bash
# 6. 空闲超时
echo 'export TMOUT=600' > /etc/profile.d/tmout.sh && chmod 644 /etc/profile.d/tmout.sh

风险提示:修改 SSH 配置前必须保留一个已成功登录的会话不断开,并在另一终端验证新配置可登录后再退出。生产环境建议先在单台灰度。

三、网络层加固:把暴露面压到最小

网络层的唯一目标是:公网只能看到必须被看到的端口。

3.1 端口收敛原则

端口/服务建议暴露范围说明
22 / 2222(SSH)仅办公网出口 IP 或 VPN/堡垒机绝大多数服务器不应公网开放 SSH
80 / 443公网源站建议仅放行 CDN 回源段
3306 / 5432 / 6379 / 27017仅内网,绝不公网数据库与缓存是最常被拖库/入侵的入口
2375 / 2376(Docker)绝不公网2375 无鉴权等于交出 root
9200(Elasticsearch)仅内网未授权访问可导致数据泄露
161(SNMP)仅监控服务器默认 community 字符串必须改

3.2 防火墙落地(firewalld 示例)

bash
# 1. 只放行必要服务,默认拒绝
systemctl enable --now firewalld
firewall-cmd --set-default-zone=drop --permanent
firewall-cmd --reload

# 2. 放行业务端口
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https

# 3. SSH 仅允许堡垒机/办公网(rich rule)
firewall-cmd --permanent --remove-service=ssh 2>/dev/null
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="203.0.113.10/32" port protocol="tcp" port="2222" accept'
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port protocol="tcp" port="2222" accept'

# 4. 数据库端口仅内网
firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port protocol="tcp" port="3306" accept'

# 5. 生效并验证
firewall-cmd --reload
firewall-cmd --list-all
nmap -sT -Pn <服务器公网IP>        # 从外部扫描验证暴露面
bash
# 云服务器还需同步配置安全组(云平台安全组优先级通常高于本机防火墙)
# 原则:安全组与本机防火墙做双重白名单,安全组做粗粒度,防火墙做细粒度

3.3 内核网络参数加固

bash
cat > /etc/sysctl.d/99-net-hardening.conf <<'EOF'
# 禁用 IP 转发(非网关/非容器主机)
net.ipv4.ip_forward = 0
# 防 SYN Flood
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_synack_retries = 2
# 忽略 ICMP 广播与伪造源
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# 不接受源路由
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# 不响应重定向
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
EOF
sysctl --system
sysctl -a | grep -E "tcp_syncookies|rp_filter|accept_redirects"

注意:net.ipv4.ip_forward = 1 是 Docker/KVM 宿主机与网关的必需项,容器化宿主机不要关,改为在网络层用 iptables 规则约束转发。

四、系统层加固:打补丁、裁服务、锁权限

4.1 补丁与软件供应链

  • 建立补丁策略:安全补丁 15 天内落地,非安全补丁按季度窗口。
  • 内核补丁需重启,纳入变更窗口;使用 yum --security / dnf update --security 只更新安全补丁可降低风险。
  • 卸载无用软件包,减少攻击面。
bash
# RHEL/Rocky/CentOS 系
dnf install -y dnf-plugin-security 2>/dev/null || yum install -y yum-plugin-security 2>/dev/null
dnf updateinfo list security all            # 列出可用安全更新
dnf update --security -y                    # 仅安装安全更新

# Ubuntu/Debian 系
apt list --upgradable 2>/dev/null | grep -i security
unattended-upgrades --dry-run --debug 2>/dev/null | head -20

# 查看已安装的无用服务与监听端口
systemctl list-unit-files --type=service --state=enabled | grep -vE "sshd|firewalld|nginx|mysql|docker|cron|systemd|rsyslog|auditd|chrony|network"
ss -lntup

4.2 服务最小化

关闭并禁用一切不需要的服务:telnet、ftp、rsh、sendmail、postfix(非邮件服务器)、avahi、cups、rpcbind、nfs(非文件服务器)、xinetd。

bash
for svc in telnet.socket avahi-daemon cups rpcbind nfs-server postfix; do
  systemctl stop $svc 2>/dev/null
  systemctl disable $svc 2>/dev/null
done
systemctl list-unit-files --state=enabled | wc -l    # 记录基线数量,便于复查对比

4.3 关键文件权限与完整性

bash
# 关键文件权限基线
chmod 600 /etc/shadow /etc/gshadow
chmod 644 /etc/passwd /etc/group
chmod 600 /etc/ssh/sshd_config
chmod 700 /root
chmod 600 /var/log/secure /var/log/auth.log 2>/dev/null

# 查找全局可写文件与无属主文件(后门常见藏身处)
find / -xdev -type f -perm -0002 2>/dev/null | grep -vE "^/(proc|sys|tmp|var/tmp|dev)" | head -20
find / -xdev -nouser -o -nogroup 2>/dev/null | head -20
# 查找设置了 SUID/SGID 的可疑文件
find / -xdev -type f \( -perm -4000 -o -perm -2000 \) 2>/dev/null | grep -vE "^/usr/(bin|sbin|lib)" | head -20

# 文件完整性监控(AIDE)
dnf install -y aide && aide --init && mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz
aide --check | head -40      # 之后定期执行,比对变化

4.4 SELinux / AppArmor

bash
# SELinux(RHEL 系)建议保持 enforcing,不要图省事关掉
getenforce
setenforce 1
sed -i 's/^SELINUX=.*/SELINUX=enforcing/' /etc/selinux/config
semanage port -a -t http_port_t -p tcp 8080    # 非标准端口需授权
# Ubuntu 系用 AppArmor
aa-status

五、应用层加固:软件自身不能有洞

应用层最容易出问题的三类:Web 服务、中间件、容器镜像。

nginx
# Nginx 安全响应头与信息隐藏(/etc/nginx/conf.d/security.conf)
server_tokens off;                      # 隐藏版本号
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;
client_max_body_size 10m;               # 限制上传体积
client_body_timeout 10s;
client_header_timeout 10s;
ini
# PHP 加固(/etc/php.ini 关键项)
expose_php = Off
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,curl_multi_exec,parse_ini_file,show_source
allow_url_include = Off
open_basedir = /var/www/html:/tmp
bash
# 容器镜像漏洞扫描(Trivy,截至 2026 年仍为主流开源方案)
trivy image --severity HIGH,CRITICAL nginx:1.26-alpine
# 容器运行安全:避免 --privileged,只读根文件系统,非 root 用户运行
docker run --read-only --cap-drop=ALL --security-opt no-new-privileges \
  --user 10001:10001 -d myapp:1.0

应用层的管理要点是资产清单 + 版本台账:没有清单就不知道该给谁打补丁。建议至少维护一份表格,记录每台服务器上的 Web 服务、语言运行时、中间件、框架及其版本。

六、数据层与审计层:最后两道防线

6.1 数据层

  • 传输加密:全站 HTTPS(TLS 1.2+,禁用 TLS 1.0/1.1 与弱套件),内网管理通道走 SSH/VPN。
  • 存储加密:敏感字段(身份证、手机、银行卡)应用层加密或数据库 TDE;备份文件加密。
  • 备份:落实 3-2-1 原则(3 份副本、2 种介质、1 份异地/离线),每季度恢复演练一次。
  • 密钥管理:禁止把密钥、数据库密码硬编码进代码或配置文件提交到仓库。

6.2 审计层

审计是"事后能破案"的保证,也是等保 2.0 明确要求的能力。

bash
# 1. 启用 auditd 并配置关键规则
dnf install -y audit && systemctl enable --now auditd
cat > /etc/audit/rules.d/99-hardening.rules <<'EOF'
# 监控账户与权限文件
-w /etc/passwd -p wa -k identity
-w /etc/shadow -p wa -k identity
-w /etc/sudoers -p wa -k sudoers
-w /etc/ssh/sshd_config -p wa -k sshd_config
# 监控计划任务
-w /etc/crontab -p wa -k cron
-w /etc/cron.d/ -p wa -k cron
# 监控命令执行(64 位)
-a always,exit -F arch=b64 -S execve -k exec
# 监控文件删除(防删库跑路)
-a always,exit -F arch=b64 -S unlink -S unlinkat -S rename -S renameat -k delete
EOF
augenrules --load
auditctl -l | head -20
ausearch -k delete --start today | head -20
bash
# 2. 日志集中化(rsyslog 转发到日志服务器,防止本地被删)
cat > /etc/rsyslog.d/90-remote.conf <<'EOF'
*.*  @@10.0.0.100:514        # @@ 表示 TCP,@ 表示 UDP
EOF
systemctl restart rsyslog

# 3. 日志留存 180 天(等保 2.0 常见要求为不少于 6 个月)
sed -i 's/^SystemMaxUse=.*/SystemMaxUse=4G/' /etc/systemd/journald.conf
sed -i 's/^MaxRetentionSec=.*/MaxRetentionSec=180day/' /etc/systemd/journald.conf
systemctl restart systemd-journald