一、概述
1.1 背景介绍
Linux 主机的“安全问题”在生产中往往不是 0/1,而是一个持续被配置细节放大的风险曲线:同一套业务在不同团队、不同镜像、不同运维习惯下,最终暴露面会出现数量级差异。
常见误判主要有三类:
- “装了杀软/EDR 就安全”:主机被暴露的第一步通常来自弱口令、SSH 暴露、sudo 滥用、内核参数不当、日志审计缺失等配置问题;EDR 只能覆盖部分已知攻击链。
- “只要开防火墙就行”:防火墙是重要的一层,但如果账号策略、权限边界、审计链路缺失,攻击者在内网横向时仍然非常顺。
- “一次加固就一劳永逸”:加固是持续过程,需要把基线、变更、回滚、验证、监控串成闭环,否则一次误改就能把主机变成不可维护状态(锁死 SSH、sudo 失效、业务端口误封等)。
本文按“调优避坑类”方式组织:先讲默认值与适用边界,再给出高频误改与风险矩阵,最后给出可落地的推荐配置、回滚方案与验证动作,并覆盖 账号安全、SSH 加固、防火墙、内核参数、文件权限、审计日志 六大方向。
1.2 安全基线对照表(CIS 视角 + 生产落地视角)
说明:CIS Benchmark 的要求会因发行版与版本而不同。表中给出“方向对照”,落地时仍需按发行版官方文档与企业合规要求调整。
| | | | |
|---|
| 密码复杂度/有效期、失败锁定、root 登录限制、最小权限 sudo | | | |
| 禁止密码登录、限制来源、强算法、空闲断开、Banner | | | |
| | | | |
| 反欺骗、关闭重定向、SYN 防护、core dump 控制、ASLR | | | |
| umask、关键文件权限、禁止 SUID/SGID 滥用、/tmp 防护 | permissions, mount options | | |
| | | | |
1.3 适用场景
- 互联网暴露主机:跳板机、边缘节点、对外 API 网关、独立对外提供 SSH 的运维主机。
- 内网关键业务主机:支付、订单、账号、权限、核心数据库周边。
- 交付前基线统一:镜像制作、金镜像、自动化装机(PXE/Cloud-init/Ansible)。
- 合规与审计要求:等保、ISO27001、SOC2 相关审计留证。
- 事故后补强:发生爆破、异常登录、横向移动、提权疑似后。
1.4 环境要求
| | |
|---|
| RHEL/CentOS 7/8/9、Rocky/Alma、Ubuntu 20.04/22.04/24.04、Debian 11/12 | 不同发行版 PAM/sshd/auditd 路径略有差异 |
| | |
| firewalld 或 nftables/iptables | |
| | 与 systemd-journald/rsyslog 配合 |
| | |
| Prometheus/Agent、ELK/EFK、SIEM(可选) | |
1.5 安全加固坐标系(不要“东一榔头西一棒子”)
本文把主机加固拆成 5 个层次,所有动作都要能定位到坐标系,并能回滚与验证:
| | | |
|---|
| | | ss/iptables/firewalld 状态、sshd_config |
| | | /etc/login.defs、PAM、faillock |
| | | |
| | | |
| | | audit.log、journald、SIEM 告警 |
二、详细步骤(调优避坑类结构)
本章分三段:
- 2.1 默认值与适用边界:告诉你“系统默认大概是什么”“哪些场景别乱改”。
- 2.2 常见误改与风险边界:把最常见的“自杀式加固”写清楚。
- 2.3 推荐调整、回滚与验证:给出可以直接落地的配置块 + 验证命令链。
2.1 默认值和适用场景
2.1.1 账号安全默认值概览
不同发行版默认策略差异较大,尤其是口令策略与失败锁定。
- Ubuntu/Debian:常见依赖 PAM(pam_pwquality / pam_faillock 或旧的 pam_tally2),默认并不一定启用强复杂度。
- RHEL 系:system-auth/password-auth 栈较完整,但企业镜像可能被二次改动。
关键默认文件:
/etc/login.defs:密码有效期、最小长度(并不强制复杂度)。/etc/pam.d/*:认证栈(真正决定复杂度/锁定/限制)。
验证命令链:
# 当前密码策略相关文件ls -l /etc/login.defs /etc/security/pwquality.conf 2>/dev/null || true# 失败锁定(RHEL系常见)command -v faillock >/dev/null && faillock --user root || true# PAM 栈(不同发行版路径不同)ls -l /etc/pam.d/system-auth /etc/pam.d/password-auth 2>/dev/null || true
2.1.2 SSH 默认值概览
OpenSSH 默认通常偏“可用性优先”,在互联网暴露环境需要收紧。
关键默认点:
PasswordAuthentication:很多发行版默认 yes。PermitRootLogin:可能是 prohibit-password 或 yes(老系统)。- 加密算法:新版本默认更安全,但兼容旧客户端时会被人为放宽。
验证命令链:
sshd -T | egrep -i 'passwordauthentication|permitrootlogin|pubkeyauthentication|kexalgorithms|ciphers|macs' | sed 's/^/sshd -T: /'# 已暴露监听ss -lntp | egrep ':22\b|:2222\b' || true
2.1.3 防火墙默认值概览
- firewalld:默认 zone 往往是
public,入站策略可能较宽。 - nftables/iptables:很多主机默认没有规则,等同“全开”。
验证命令链:
# firewalldcommand -v firewall-cmd >/dev/null && firewall-cmd --state && firewall-cmd --get-default-zone && firewall-cmd --list-all || true# nftablescommand -v nft >/dev/null && nft list ruleset | head -n 50 || true# iptablescommand -v iptables >/dev/null && iptables -S || true
2.1.4 内核参数默认值概览(sysctl)
常见默认风险点:
net.ipv4.conf.*.accept_redirects/send_redirects/accept_source_route:部分系统默认未完全关闭。net.ipv4.ip_forward:在路由/容器主机可能开启,业务机通常不需要。fs.suid_dumpable、kernel.core_pattern:影响 core dump 与泄露。
验证命令链:
sysctl -a 2>/dev/null | egrep 'accept_redirects|send_redirects|accept_source_route|rp_filter|ip_forward|randomize_va_space|kptr_restrict|dmesg_restrict|fs\.suid_dumpable' | sort
2.1.5 文件权限与挂载默认值概览
- 默认
umask 可能是 022(更偏可读),关键服务建议更严。 /tmp 多数系统未强制 noexec,nodev,nosuid(兼容性考虑)。
验证命令链:
umaskmount | egrep ' on /tmp | on /var/tmp | on /dev/shm ' || truestat -c '%a %U:%G %n' /etc/passwd /etc/shadow /etc/gshadow /etc/ssh/sshd_config 2>/dev/null || true
2.1.6 审计与日志默认值概览
验证命令链:
systemctl is-enabled auditd 2>/dev/null || truesystemctl is-active auditd 2>/dev/null || true# journald 持久化grep -E '^(Storage|SystemMaxUse|SystemKeepFree|MaxRetentionSec)=' /etc/systemd/journald.conf 2>/dev/null || truejournalctl --disk-usage 2>/dev/null || true
2.2 常见误改和风险边界
2.2.1 高风险误改清单(先看这个,再动手)
| | |
|---|
直接把 PasswordAuthentication no 写入 sshd_config 并立即重启 | | 先开第二个 SSH 会话、先用 sshd -t 校验、再 reload |
把 PermitRootLogin no 但没有预留 sudo 账号 | root 入口被关,sudo 又不可用会直接“失联” | |
防火墙 default deny 后忘记放行业务端口/健康检查端口 | | |
rp_filter=1 | | 多网卡/策略路由用 2(loose)或按接口精细配置 |
给 /tmp 加 noexec 但业务/安装脚本依赖临时执行 | | |
| audit 规则堆满(每个 syscalls 都记录) | | 只对关键动作审计,启用 rotate、设置阈值告警 |
2.2.2 根因矩阵:加固后“看起来像故障”的现象如何定位
| | | | |
|---|
| ss -lntp | journalctl -u sshd -n 200 | | |
| /var/log/auth.log | sshd -T | | |
| sudo -l | | | |
| dmesg | | | |
| | du -sh /var/log/* | | |
2.3 推荐调整、回滚与验证(20项关键配置)
建议原则:
- 每一项都要有回滚手段;2) 每一项都要有验证命令;3) 先灰度、后全量;4) 所有变更落盘可追溯(配置备份 + 变更记录)。
下面的 20 项按六大域组织:
2.3.1 账号安全(1/20):最小化可登录账号 + 锁定无用系统账号
推荐调整:
- 对无交互登录需求的系统账号,将 shell 设置为
/sbin/nologin 或 /usr/sbin/nologin。
# 找出可登录账号(shell 非 nologin/false)awk -F: '($7 !~ /(nologin|false)$/){print $1"\t"$7}' /etc/passwd# 锁定账号(示例:olduser)passwd -l olduserusermod -s /sbin/nologin olduser 2>/dev/null || usermod -s /usr/sbin/nologin olduser# 验证锁定状态passwd -S olduser || true
回滚:
passwd -u olduserusermod -s /bin/bash olduser
风险边界:不要锁定正在跑业务的服务账号(如应用进程需要 su/sudo 或登录执行维护脚本的账号)。
2.3.2 账号安全(2/20):口令复杂度(pam_pwquality)
推荐调整:启用并收紧口令质量(长度、字符类、重复限制)。
Ubuntu/Debian 常见配置:/etc/security/pwquality.conf
# /etc/security/pwquality.confminlen = 14dcredit = -1ucredit = -1lcredit = -1ocredit = -1maxrepeat = 3maxclassrepeat = 4gecoscheck = 1reject_username = 1
RHEL 系常见在 PAM 栈中指定(示例片段):
password requisite pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok
验证:
# 尝试给测试账号设置弱口令(应被拒绝)# passwd testuser# 查看 pwquality 生效路径grep -R "pam_pwquality" -n /etc/pam.d 2>/dev/null | head
回滚:恢复原 pwquality.conf 与 PAM 文件(见第 3 章脚本“备份/回滚”)。
风险边界:过度收紧会导致自动化账号/机器人账号改密失败,建议把机器账号改为密钥/令牌机制,不要靠弱口令。
2.3.3 账号安全(3/20):密码有效期与最小更改间隔(login.defs)
推荐调整:
/etc/login.defs 建议值:
PASS_MAX_DAYS 90PASS_MIN_DAYS 1PASS_WARN_AGE 14
验证:
chage -l <username>
回滚:将 PASS_* 恢复或只对特定用户用 chage 定向设置。
风险边界:对大量账号直接统一改会触发集中改密潮,建议分批推进并结合 IAM 流程。
2.3.4 账号安全(4/20):登录失败锁定(pam_faillock)
推荐调整:对本地认证启用失败锁定,降低爆破成功率。
RHEL 8/9 示例(system-auth/password-auth 常见写法):
auth required pam_faillock.so preauth silent deny=5 unlock_time=900 fail_interval=900auth [default=die] pam_faillock.so authfail deny=5 unlock_time=900 fail_interval=900account required pam_faillock.so
验证:
# 连续输错密码后查看faillock --user <username># 解锁faillock --user <username> --reset
回滚:移除 pam_faillock 相关行或恢复备份。
风险边界:
- 需要明确“锁定的是谁”:对运维账号也锁定会增加值班风险。
- 建议配套“break-glass”账号(强权限、强审计、离线保管)。
2.3.5 账号安全(5/20):限制 su(仅 wheel 组可 su)
推荐调整:启用 pam_wheel 限制 su。
/etc/pam.d/su 示例:
auth required pam_wheel.so use_uid group=wheel
验证:
getent group wheel || grep '^wheel:' /etc/group# 非 wheel 用户执行 su 应失败# su -
回滚:注释/移除该行。
风险边界:在不使用 su、只用 sudo 的团队可不启用,避免对历史脚本造成影响。
2.3.6 账号安全(6/20):sudo 最小权限与日志
推荐调整:
- 业务运维按职责拆分 sudoers(命令级最小化)。
/etc/sudoers.d/ops-minimal 示例(权限文件必须 0440):
Defaults use_ptyDefaults logfile="/var/log/sudo.log"Defaults loglinelen=0# 仅允许运维组执行 systemctl/journalctl 等%ops ALL=(root) NOPASSWD: /bin/systemctl, /bin/journalctl# 禁止通配符给出 /bin/bash 之类的逃逸命令
验证:
visudo -csudo -lsudo systemctl status sshdsudo tail -n 5 /var/log/sudo.log 2>/dev/null || true
回滚:删除/恢复 sudoers.d 文件(先用备份)。
风险边界:
NOPASSWD 不是原罪,但必须配套审计与来源控制。
2.3.7 SSH(7/20):禁止 root 直接登录(保留可审计的 sudo 入口)
推荐调整:
- 内网可控:至少
prohibit-password(仅允许密钥)
/etc/ssh/sshd_config:
PermitRootLogin no
验证:
sshd -t && systemctl reload sshdsshd -T | grep -i permitrootlogin
回滚:改回 prohibit-password 或 yes(仅临时救援,需配套来源限制)。
2.3.8 SSH(8/20):关闭口令登录,强制公钥(生产推荐)
/etc/ssh/sshd_config:
PasswordAuthentication noKbdInteractiveAuthentication noPubkeyAuthentication yesAuthenticationMethods publickey
验证:
sshd -tsshd -T | egrep -i 'passwordauthentication|kbdinteractiveauthentication|authenticationmethods'# 在另一个终端用密钥登录验证# ssh -i ~/.ssh/id_ed25519 user@host
回滚:临时打开 PasswordAuthentication yes(必须同时限制来源 IP,并设置时间窗口)。
风险边界:
2.3.9 SSH(9/20):限制可登录用户/组(AllowUsers/AllowGroups)
/etc/ssh/sshd_config:
AllowGroups ops wheel# 或者精确到用户:AllowUsers alice bob
验证:
getent group ops wheel || truesshd -T | egrep -i 'allowgroups|allowusers'
回滚:注释该行或加入必要账号。
风险边界:
- 与集中账号(LDAP/SSSD)结合时,需要确认组名解析正常。
2.3.10 SSH(10/20):收紧算法(Kex/Ciphers/MACs)并考虑兼容性
/etc/ssh/sshd_config(示例,需按版本调整):
KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.orgCiphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctrMACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.comHostKeyAlgorithms ssh-ed25519,rsa-sha2-512,rsa-sha2-256
验证:
sshd -T | egrep -i 'kexalgorithms|ciphers|macs|hostkeyalgorithms'# 从客户端探测(需要 nmap 或 ssh -Q)ssh -Q cipher | headssh -Q kex | head
回滚:恢复为发行版默认或逐步放宽(不要一次性把弱算法全开)。
风险边界:某些老设备/老系统的 ssh 客户端不支持新算法,需在跳板/堡垒层做兼容隔离。
2.3.11 SSH(11/20):空闲断开与连接限制(防止挂起会话滥用)
/etc/ssh/sshd_config:
ClientAliveInterval 300ClientAliveCountMax 2LoginGraceTime 30MaxAuthTries 3MaxSessions 10
验证:
sshd -T | egrep -i 'clientaliveinterval|clientalivecountmax|logingracetime|maxauthtries|maxsessions'
回滚:恢复原值。
2.3.12 SSH(12/20):记录与提示(Banner、日志级别)
/etc/ssh/sshd_config:
LogLevel VERBOSEBanner /etc/issue.net
/etc/issue.net 示例:
Authorized access only. All activity may be monitored and reported.
验证:
sshd -T | egrep -i 'loglevel|banner'
风险边界:Banner 不要泄露系统版本与内部信息。
2.3.13 防火墙(13/20):入站默认拒绝 + 最小放行(含回滚窗口)
以 firewalld 为例(nftables/iptables 类似):
# 查看当前区与规则firewall-cmd --get-default-zonefirewall-cmd --list-all# 示例:只放行 SSH(22) + 业务(443) + 监控(9100)firewall-cmd --permanent --add-service=sshfirewall-cmd --permanent --add-service=httpsfirewall-cmd --permanent --add-port=9100/tcp# reload 前先在当前会话确认规则firewall-cmd --reloadfirewall-cmd --list-all
回滚:
# 删除放行firewall-cmd --permanent --remove-port=9100/tcp || truefirewall-cmd --permanent --remove-service=https || truefirewall-cmd --reload
验证:
ss -lntp# 从允许来源探测端口# nc -vz <host> 22 443 9100
风险边界:要把集群健康检查端口、配置下发端口、日志/监控出站依赖一起纳入“端口清单”。
2.3.14 防火墙(14/20):管理面隔离(来源 IP 白名单/跳板机)
推荐:SSH 仅允许运维网段或跳板机 IP。
firewalld rich rule 示例:
# 仅允许 10.10.0.0/16 访问 22firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.10.0.0/16" port port="22" protocol="tcp" accept'# 其他来源拒绝(如果 zone 默认 accept,需要显式 drop)firewall-cmd --permanent --add-rich-rule='rule family="ipv4" port port="22" protocol="tcp" drop'firewall-cmd --reload
验证:
firewall-cmd --list-rich-rules
风险边界:多跳板、多运维网段时要确保白名单完整,否则会误伤。
2.3.15 内核参数(15/20):反欺骗与重定向关闭(sysctl)
/etc/sysctl.d/99-hardening.conf:
# 反欺骗与路由相关net.ipv4.conf.all.rp_filter = 1net.ipv4.conf.default.rp_filter = 1# 关闭 ICMP 重定向接收/发送net.ipv4.conf.all.accept_redirects = 0net.ipv4.conf.default.accept_redirects = 0net.ipv4.conf.all.send_redirects = 0net.ipv4.conf.default.send_redirects = 0# 禁止 source routenet.ipv4.conf.all.accept_source_route = 0net.ipv4.conf.default.accept_source_route = 0
应用与验证:
sysctl --systemsysctl net.ipv4.conf.all.rp_filter net.ipv4.conf.all.accept_redirects net.ipv4.conf.all.send_redirects
回滚:删除该 sysctl 文件或恢复备份后 sysctl --system。
风险边界:
- 多网卡/策略路由:建议
rp_filter=2(loose),或按接口设置。
2.3.16 内核参数(16/20):SYN flood 防护与连接行为收敛
/etc/sysctl.d/99-hardening.conf 增补:
net.ipv4.tcp_syncookies = 1net.ipv4.tcp_max_syn_backlog = 4096net.ipv4.tcp_synack_retries = 3net.ipv4.tcp_syn_retries = 5net.ipv4.tcp_fin_timeout = 15
验证:
sysctl net.ipv4.tcp_syncookies net.ipv4.tcp_max_syn_backlog
风险边界:此类参数需要结合业务连接模型与压测数据;不要在无压测情况下极端收紧。
2.3.17 内核参数(17/20):内核信息泄露与调试面收紧(ASLR/dmesg/kptr)
/etc/sysctl.d/99-hardening.conf 增补:
kernel.randomize_va_space = 2kernel.kptr_restrict = 2kernel.dmesg_restrict = 1fs.suid_dumpable = 0
验证:
sysctl kernel.randomize_va_space kernel.kptr_restrict kernel.dmesg_restrict fs.suid_dumpable
风险边界:某些调试与崩溃分析需要 core dump;生产可以按需对特定服务开启,而不是全局开启。
2.3.18 文件权限(18/20):关键文件权限基线(shadow/sudoers/ssh)
推荐基线:
# 典型期望:# /etc/shadow 000/400/600 仅 root 可读# /etc/sudoers 440 root:root# /etc/ssh/sshd_config 600 root:rootchown root:root /etc/shadow /etc/gshadow /etc/sudoers /etc/ssh/sshd_configchmod 600 /etc/shadow /etc/gshadow /etc/ssh/sshd_configchmod 440 /etc/sudoers# 验证stat -c '%a %U:%G %n' /etc/shadow /etc/gshadow /etc/sudoers /etc/ssh/sshd_configvisudo -c
回滚:恢复为发行版默认权限(建议从包管理器校验:rpm -V sudo openssh-server 或 debsums)。
风险边界:
- 如果把 sudoers 权限设错(如 644),sudo 会拒绝工作。
2.3.19 文件权限与挂载(19/20):/tmp、/dev/shm 防护(nodev,nosuid,noexec)
推荐调整:在安全要求高的环境,把临时目录挂载选项收紧。
/etc/fstab 示例(需结合实际分区):
tmpfs /dev/shm tmpfs defaults,nodev,nosuid,noexec 0 0tmpfs /tmp tmpfs defaults,nodev,nosuid,noexec,mode=1777 0 0
应用与验证:
mount -o remount /tmpmount -o remount /dev/shmmount | egrep ' on /tmp | on /dev/shm '# 验证 noexec(应失败)cat > /tmp/test_exec.sh <<'EOF'#!/usr/bin/env bashecho okEOFchmod +x /tmp/test_exec.sh/tmp/test_exec.sh || echo"noexec 生效,执行被拒绝"rm -f /tmp/test_exec.sh
回滚:移除 noexec 后 remount;若业务依赖临时执行,可只对 /dev/shm 做收紧。
风险边界:
- 某些语言/框架会在 /tmp 生成可执行临时文件;必须在灰度验证。
2.3.20 审计日志(20/20):auditd 关键规则 + 留存与告警阈值
推荐调整:只审计“高价值动作”,避免全量 syscalls。
/etc/audit/rules.d/hardening.rules 示例:
# 删除旧规则并设置缓冲-D-b 8192-f 1# 账户与权限关键文件-w /etc/passwd -p wa -k identity-w /etc/shadow -p wa -k identity-w /etc/group -p wa -k identity-w /etc/gshadow -p wa -k identity# sudoers 变更-w /etc/sudoers -p wa -k scope-w /etc/sudoers.d/ -p wa -k scope# sshd 配置-w /etc/ssh/sshd_config -p wa -k sshd# 特权命令执行(按需选取)-a always,exit -F arch=b64 -S execve -F euid=0 -k privileged# 时间修改-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change-w /etc/localtime -p wa -k time-change# 网络配置变更-a always,exit -F arch=b64 -S sethostname,setdomainname -k system-locale-w /etc/hosts -p wa -k system-locale-w /etc/sysctl.conf -p wa -k sysctl-w /etc/sysctl.d/ -p wa -k sysctl
应用与验证:
augenrules --load 2>/dev/null || truesystemctl restart auditd# 触发一次 sudoers 读取与查看近期事件auditctl -sausearch -k scope -ts recent | head -n 20
回滚:恢复 rules.d 目录备份并重载规则。
风险边界:
-f 1 表示审计失败时触发告警(不同策略含义不同),生产需评估;不要在磁盘不足情况下强制启用。
三、示例代码和配置
本章提供可复用的配置与脚本,目标是“配置-执行-验证-回滚”闭环。
3.1 完整配置样例:sshd_config(可按需裁剪)
# 文件位置:/etc/ssh/sshd_configPort 22Protocol 2PermitRootLogin noPasswordAuthentication noKbdInteractiveAuthentication noPubkeyAuthentication yesAuthenticationMethods publickeyAllowGroups ops wheelLogLevel VERBOSEBanner /etc/issue.netClientAliveInterval 300ClientAliveCountMax 2LoginGraceTime 30MaxAuthTries 3MaxSessions 10# 算法(按 OpenSSH 版本调整)KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.orgCiphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes256-ctrMACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com# 禁止转发(跳板机按需开放)AllowTcpForwarding noX11Forwarding noPermitTunnel no# 限制环境变量注入AcceptEnv LANG LC_*
说明:
AllowGroups 会影响集中账号解析,启用前确认 getent group 正常。- 禁止转发会影响部分隧道类运维方式(如 ssh -L),需要在跳板层统一规划。
3.2 完整配置样例:sysctl 加固文件
# 文件位置:/etc/sysctl.d/99-hardening.conf# 网络基础防护net.ipv4.conf.all.accept_redirects = 0net.ipv4.conf.default.accept_redirects = 0net.ipv4.conf.all.send_redirects = 0net.ipv4.conf.default.send_redirects = 0net.ipv4.conf.all.accept_source_route = 0net.ipv4.conf.default.accept_source_route = 0net.ipv4.icmp_echo_ignore_broadcasts = 1net.ipv4.icmp_ignore_bogus_error_responses = 1# 反欺骗(多网卡/策略路由按需改为 2)net.ipv4.conf.all.rp_filter = 1net.ipv4.conf.default.rp_filter = 1# SYN 与连接行为(需要压测验证)net.ipv4.tcp_syncookies = 1net.ipv4.tcp_max_syn_backlog = 4096net.ipv4.tcp_synack_retries = 3net.ipv4.tcp_syn_retries = 5net.ipv4.tcp_fin_timeout = 15# 信息泄露与调试面kernel.randomize_va_space = 2kernel.kptr_restrict = 2kernel.dmesg_restrict = 1fs.suid_dumpable = 0
应用:
sysctl --system
3.3 完整配置样例:auditd 规则(关键动作审计)
# 文件位置:/etc/audit/rules.d/hardening.rules-D-b 8192-f 1-w /etc/passwd -p wa -k identity-w /etc/shadow -p wa -k identity-w /etc/group -p wa -k identity-w /etc/gshadow -p wa -k identity-w /etc/sudoers -p wa -k scope-w /etc/sudoers.d/ -p wa -k scope-w /etc/ssh/sshd_config -p wa -k sshd-a always,exit -F arch=b64 -S execve -F euid=0 -k privileged-a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change-w /etc/localtime -p wa -k time-change-w /etc/sysctl.conf -p wa -k sysctl-w /etc/sysctl.d/ -p wa -k sysctl
验证:
augenrules --load 2>/dev/null || truesystemctl restart auditdausearch -k identity -ts recent | head
3.4 脚本一:快速采集加固证据(适合工单/复盘留档)
#!/usr/bin/env bashset -euo pipefail# 文件名:collect-hardening-evidence.sh# 作用:采集主机加固相关证据与关键配置# 适用场景:变更前对比、变更后留档、审计抽查# 使用方法:sudo bash collect-hardening-evidence.sh /tmp/hardening-evidence# 输入参数:输出目录# 输出结果:在输出目录生成多个文本文件# 风险提示:只读采集,风险低OUT_DIR="${1:-/tmp/hardening-evidence}"mkdir -p "$OUT_DIR"{echo"== time =="; date -Isechoecho"== os =="; cat /etc/os-release 2>/dev/null || trueechoecho"== kernel =="; uname -aechoecho"== sshd -T (selected) =="; sshd -T 2>/dev/null | egrep -i 'port|permitrootlogin|passwordauthentication|pubkeyauthentication|authenticationmethods|allowusers|allowgroups|loglevel|clientaliveinterval|ciphers|macs|kexalgorithms' || trueechoecho"== listening ports =="; ss -lntpechoecho"== firewall ==";ifcommand -v firewall-cmd >/dev/null; then firewall-cmd --state && firewall-cmd --get-default-zone && firewall-cmd --list-all; fiifcommand -v nft >/dev/null; then nft list ruleset | head -n 200; fiifcommand -v iptables >/dev/null; then iptables -S; fiechoecho"== sysctl (selected) =="; sysctl -a 2>/dev/null | egrep 'rp_filter|accept_redirects|send_redirects|accept_source_route|tcp_syncookies|randomize_va_space|kptr_restrict|dmesg_restrict|fs\.suid_dumpable' | sortechoecho"== critical file perms =="; stat -c '%a %U:%G %n' /etc/passwd /etc/shadow /etc/gshadow /etc/sudoers /etc/ssh/sshd_config 2>/dev/null || trueechoecho"== auditd =="; systemctl is-active auditd 2>/dev/null || true; auditctl -s 2>/dev/null || true} | tee "$OUT_DIR/summary.txt" >/dev/null# 单独保存配置文件(若存在)cp -a /etc/ssh/sshd_config "$OUT_DIR/" 2>/dev/null || truecp -a /etc/sysctl.conf "$OUT_DIR/" 2>/dev/null || truecp -a /etc/sysctl.d "$OUT_DIR/" 2>/dev/null || truecp -a /etc/audit/rules.d "$OUT_DIR/" 2>/dev/null || trueecho"Evidence collected in: $OUT_DIR"
3.5 脚本二:加固前自动备份(强烈建议每次变更先跑)
#!/usr/bin/env bashset -euo pipefail# 文件名:backup-hardening-configs.sh# 作用:对关键配置进行时间戳备份# 适用场景:任何加固/变更前# 使用方法:sudo bash backup-hardening-configs.sh /var/backups/hardening# 输入参数:备份根目录# 输出结果:创建一个带时间戳的备份目录# 风险提示:只读复制,风险低BACKUP_ROOT="${1:-/var/backups/hardening}"TS="$(date +%Y%m%d-%H%M%S)"DST="$BACKUP_ROOT/$TS"mkdir -p "$DST"copy_if_exists() {local p="$1"if [ -e "$p" ]; then mkdir -p "$DST$(dirname "$p")" cp -a "$p""$DST$p"fi}copy_if_exists /etc/ssh/sshd_configcopy_if_exists /etc/login.defscopy_if_exists /etc/security/pwquality.confcopy_if_exists /etc/pam.dcopy_if_exists /etc/sudoerscopy_if_exists /etc/sudoers.dcopy_if_exists /etc/sysctl.confcopy_if_exists /etc/sysctl.dcopy_if_exists /etc/fstabcopy_if_exists /etc/audit/auditd.confcopy_if_exists /etc/audit/rules.dprintf'Backup created: %s\n'"$DST"
3.6 脚本三:加固变更验证(集中跑一遍,避免遗漏)
#!/usr/bin/env bashset -euo pipefail# 文件名:verify-hardening.sh# 作用:对关键加固项做一致性检查与输出# 适用场景:变更后自检、上线前检查# 使用方法:sudo bash verify-hardening.sh# 输入参数:无# 输出结果:标准输出,便于工单留存# 风险提示:只读检查,风险低fail=0check() {local name="$1"; shiftecho"[CHECK] $name"if"$@"; thenecho" PASS"elseecho" FAIL" fail=1fi}# sshd 语法check "sshd config syntax" sshd -t# sshd 关键项check "sshd: PermitRootLogin is no" bash -lc "sshd -T | grep -qi '^permitrootlogin no$'"check "sshd: PasswordAuthentication is no" bash -lc "sshd -T | grep -qi '^passwordauthentication no$'"# 防火墙状态(若使用 firewalld)ifcommand -v firewall-cmd >/dev/null; then check "firewalld running" firewall-cmd --statefi# sysctl 关键项check "sysctl: accept_redirects=0" bash -lc "sysctl -n net.ipv4.conf.all.accept_redirects | grep -qx '0'"check "sysctl: send_redirects=0" bash -lc "sysctl -n net.ipv4.conf.all.send_redirects | grep -qx '0'"# 关键文件权限check "/etc/shadow perms" bash -lc "stat -c '%a' /etc/shadow 2>/dev/null | egrep -qx '400|000|600'"check "/etc/sudoers perms" bash -lc "stat -c '%a' /etc/sudoers 2>/dev/null | grep -qx '440'"# auditdif systemctl is-active auditd >/dev/null 2>&1; thenecho"[INFO] auditd active" auditctl -s || trueelseecho"[WARN] auditd not active"fiexit"$fail"
3.7 脚本四:一键回滚(从备份目录恢复关键文件)
#!/usr/bin/env bashset -euo pipefail# 文件名:rollback-hardening.sh# 作用:从备份目录回滚关键配置# 适用场景:误改导致登录/业务异常,需要快速恢复# 使用方法:sudo bash rollback-hardening.sh /var/backups/hardening/20260101-010101# 输入参数:备份目录(由 backup-hardening-configs.sh 生成)# 输出结果:恢复配置并提示下一步# 风险提示:会覆盖系统配置,需在控制台/带外通道可用时操作SRC="${1:?backup dir required}"restore_if_exists() {local p="$1"if [ -e "$SRC$p" ]; then mkdir -p "$(dirname "$p")" cp -a "$SRC$p""$p"echo"restored: $p"fi}restore_if_exists /etc/ssh/sshd_configrestore_if_exists /etc/login.defsrestore_if_exists /etc/security/pwquality.confrestore_if_exists /etc/pam.drestore_if_exists /etc/sudoersrestore_if_exists /etc/sudoers.drestore_if_exists /etc/sysctl.confrestore_if_exists /etc/sysctl.drestore_if_exists /etc/fstabrestore_if_exists /etc/audit/auditd.confrestore_if_exists /etc/audit/rules.decho"Reloading services (best-effort) ..."systemctl reload sshd 2>/dev/null || truesysctl --system 2>/dev/null || truesystemctl restart auditd 2>/dev/null || trueecho"Rollback done. Re-test SSH/sudo and service health."
3.8 脚本五:审计日志归桶(按关键事件分桶,便于排障/复盘)
#!/usr/bin/env bashset -euo pipefail# 文件名:bucket-security-logs.sh# 作用:把常见安全事件从日志中归桶:SSH失败、sudo、用户变更、审计关键 key# 适用场景:安全事件排查、审计抽查、事故复盘# 使用方法:sudo bash bucket-security-logs.sh /var/log /tmp/sec-buckets# 输入参数:日志目录、输出目录# 输出结果:在输出目录生成多类事件文件# 风险提示:只读读取日志,风险低LOG_DIR="${1:-/var/log}"OUT_DIR="${2:-/tmp/sec-buckets}"mkdir -p "$OUT_DIR"AUTH_LOG=""if [ -f "$LOG_DIR/auth.log" ]; then AUTH_LOG="$LOG_DIR/auth.log"; fiif [ -f "$LOG_DIR/secure" ]; then AUTH_LOG="$LOG_DIR/secure"; fiif [ -n "$AUTH_LOG" ]; then egrep -i 'Failed password|Invalid user|authentication failure'"$AUTH_LOG" | tail -n 2000 > "$OUT_DIR/ssh_failed.log" || true egrep -i 'sudo:'"$AUTH_LOG" | tail -n 2000 > "$OUT_DIR/sudo.log" || true egrep -i 'useradd|usermod|passwd\[|chage'"$AUTH_LOG" | tail -n 2000 > "$OUT_DIR/account_change.log" || truefiAUDIT_LOG="$LOG_DIR/audit/audit.log"if [ -f "$AUDIT_LOG" ]; then egrep ' key=(identity|scope|sshd|privileged|sysctl|time-change)'"$AUDIT_LOG" | tail -n 5000 > "$OUT_DIR/audit_key_events.log" || truefiecho"Buckets written to: $OUT_DIR"
四、实际应用案例(4个生产环境加固案例)
案例以“现象→判断→下钻→证据→根因→修复→验证→防再发”组织,并给出可复用检查点。
4.1 案例一:互联网跳板机遭遇 SSH 爆破(从告警到闭环)
4.1.1 现场现象
4.1.2 第一轮判断
先确认是否为外部爆破与来源集中:
# 统计失败来源 IP(示例:auth.log)awk '/Failed password/ {print $(NF-3)}' /var/log/auth.log | sort | uniq -c | sort -nr | head# 当前连接ss -tn state established '( sport = :22 )' | head
4.1.3 第二轮下钻
核对 sshd 是否允许口令登录、是否开启失败锁定:
sshd -T | egrep -i 'passwordauthentication|permitrootlogin|loglevel'command -v faillock >/dev/null && faillock --user <被攻击账号> || true
4.1.4 关键证据
日志片段示例(/var/log/auth.log):
Mar 11 10:21:01 bastion sshd[12345]: Failed password for invalid user admin from 203.0.113.10 port 51234 ssh2Mar 11 10:21:03 bastion sshd[12346]: Failed password for root from 203.0.113.10 port 51288 ssh2
4.1.5 根因
- 跳板机对公网暴露 22,且启用了
PasswordAuthentication yes,缺少来源白名单与失败锁定,导致爆破成本极低。
4.1.6 修复动作
- 长期修复:关闭口令登录,强制公钥;启用失败锁定;收紧
MaxAuthTries。
4.1.7 修复后验证
# 验证只有白名单能访问 22firewall-cmd --list-rich-rules# 验证口令关闭sshd -T | grep -i '^passwordauthentication no$'# 观察 30 分钟失败次数是否明显下降# 可结合日志或指标统计
4.1.8 防再发建议
- 把“跳板机必须白名单 + 禁止口令 + 失败锁定”做成上线门禁。
4.2 案例二:内网业务机加固后服务异常(rp_filter 误伤回包)
4.2.1 现场现象
4.2.2 第一轮判断
先确认是否网络层丢包与路由异常:
ip aip routesysctl net.ipv4.conf.all.rp_filter
4.2.3 第二轮下钻
该主机存在多网卡与策略路由,严格反向路径校验会丢弃“非对称路由回包”。
抓取内核丢包统计(示意):
dmesg | tail -n 50nstat -az | egrep 'IpInNoRoutes|IpInDiscards|TcpExtTCPAbortOnMemory'
4.2.4 关键证据
rp_filter=1(strict)在策略路由主机触发回包丢弃。
4.2.5 根因
- 把通用加固配置“无差别”套到了多网卡/策略路由主机。
4.2.6 修复动作
- 将
rp_filter 调整为 2(loose)或按接口定向配置。
sysctl -w net.ipv4.conf.all.rp_filter=2sysctl -w net.ipv4.conf.default.rp_filter=2# 固化到 sysctl 文件sed -i 's/net.ipv4.conf.all.rp_filter = 1/net.ipv4.conf.all.rp_filter = 2/' /etc/sysctl.d/99-hardening.confsed -i 's/net.ipv4.conf.default.rp_filter = 1/net.ipv4.conf.default.rp_filter = 2/' /etc/sysctl.d/99-hardening.confsysctl --system
4.2.7 修复后验证
- 指标侧:P99 延迟回落、超时率下降(第 6 章给出指标表)。
4.2.8 防再发建议
- 加固要“按角色模板化”:单网卡业务机 vs 多网卡网关/容器节点必须分模板。
4.3 案例三:/tmp noexec 导致发布脚本失败(加固与可用性冲突)
4.3.1 现场现象
- 发布失败,错误提示“Permission denied”。
4.3.2 第一轮判断
快速确认是否为挂载选项导致:
mount | grep ' on /tmp '# 尝试在 /tmp 执行最小脚本printf'#!/bin/sh\necho ok\n' > /tmp/x && chmod +x /tmp/x && /tmp/x
4.3.3 第二轮下钻
发布工具把临时执行文件放在 /tmp,noexec 会拒绝执行。
4.3.4 关键证据
4.3.5 根因
- 没有对发布链路做灰度验证就强制启用
/tmp noexec。
4.3.6 修复动作
两种稳妥做法:
- 更推荐:发布工具改用应用专用目录(如
/var/lib/app/tmp),并只对 /dev/shm 做 noexec。
4.3.7 修复后验证
/tmp 不再作为可执行临时目录或仅在白名单机器启用。
4.3.8 防再发建议
- 把
/tmp noexec 纳入“需要业务验证的高风险加固项”,统一灰度策略。
4.4 案例四:审计规则过量导致磁盘告警(审计要可持续)
4.4.1 现场现象
4.4.2 第一轮判断
du -sh /var/log/* | sort -h | tailwc -l /var/log/audit/audit.logauditctl -l | wc -l
4.4.3 第二轮下钻
发现审计规则包含大量 syscalls 全量记录,并且没有有效轮转策略。
4.4.4 关键证据
4.4.5 根因
4.4.6 修复动作
- 配置 logrotate 或 auditd 的 max_log_file 与 rotate。
/etc/audit/auditd.conf 关键项示例:
max_log_file = 50num_logs = 10max_log_file_action = ROTATEspace_left = 500space_left_action = SYSLOGadmin_space_left = 200admin_space_left_action = SUSPEND
4.4.7 修复后验证
4.4.8 防再发建议
- 审计规则纳入容量评估:以“每秒事件数”“每日增量”作为上线门槛。
五、最佳实践和注意事项
5.1 最佳实践(可执行版)
- 变更前必须备份:先跑
backup-hardening-configs.sh,保证任何时候可回滚。 - 始终保留带外/控制台通道:涉及 SSH、sudo 的变更必须保证有控制台可用。
- 按主机角色分模板:跳板机、业务机、容器节点、网关节点的加固项不同。
- 安全项也要压测与灰度:sysctl 与挂载选项对网络/性能影响不可忽略。
- 最小暴露面优先:先做来源白名单与端口收敛,再做复杂审计。
- 审计要“可持续”:关键事件优先,容量阈值与轮转必须到位。
5.2 注意事项(高频踩坑点)
- 禁用口令前必须验证密钥登录链路(至少两人/两把密钥)。
AllowGroups/AllowUsers 配合 LDAP/SSSD 时要验证解析链路,否则会误封。- 防火墙规则要包含:业务端口、探活端口、监控端口、配置同步端口、必要出站。
rp_filter 与多网卡/策略路由冲突高,必须按角色模板。
5.3 常见错误清单(适合做变更门禁)
| | |
|---|
| | |
| | |
| | |
| | 命令级白名单 + use_pty + logfile |
六、故障排查和监控(安全事件监控、审计规则)
6.1 关键指标(建议纳入监控看板)
6.2 日志与审计的排障命令链
# SSH 失败与成功if [ -f /var/log/auth.log ]; then egrep -i 'Failed password|Accepted publickey|Accepted password' /var/log/auth.log | tail -n 200fiif [ -f /var/log/secure ]; then egrep -i 'Failed password|Accepted publickey|Accepted password|sudo:' /var/log/secure | tail -n 200fi# 审计关键 keyausearch -k identity -ts today | tail -n 50ausearch -k scope -ts today | tail -n 50ausearch -k privileged -ts today | tail -n 50# 最近 1 小时的 sudo 日志(如果启用)tail -n 200 /var/log/sudo.log 2>/dev/null || true
6.3 告警规则模板(Prometheus/Alertmanager 思路)
说明:主机侧需要把日志转指标(如 promtail + loki、或 node_exporter textfile、或 auditd exporter)。以下用“伪规则”表达核心口径。
# 规则名:HostSSHBurstFailures# 指标前提:将 SSH 失败日志聚合为计数指标 ssh_login_failed_totalalert: HostSSHBurstFailuresexpr: rate(ssh_login_failed_total[5m]) > 0.3for: 10mlabels: severity: warningannotations: summary: "SSH failures burst on {{ $labels.instance }}" description: "High rate of SSH failed logins,可能存在爆破或异常扫描"
# 规则名:AuditLogGrowthTooFast# 指标前提:采集 /var/log/audit/audit.log 文件大小为 audit_log_bytesalert: AuditLogGrowthTooFastexpr: (audit_log_bytes - audit_log_bytes offset 1h) / 1024 / 1024 > 500for: 30mlabels: severity: warningannotations: summary: "audit log growth too fast on {{ $labels.instance }}" description: "audit 日志 1 小时增长超过阈值,可能规则过量或异常行为"
6.4 修复后验证(回归动作清单)
# 1) SSH 配置校验sshd -tsystemctl reload sshd# 2) 从白名单来源登录验证(至少公钥 + sudo)# ssh user@host# sudo -l# 3) 防火墙规则校验command -v firewall-cmd >/dev/null && firewall-cmd --list-all# 4) 审计规则生效auditctl -sausearch -k sshd -ts recent | head -n 10# 5) 观察 30-60 分钟指标(失败次数、磁盘增长)# 结合监控平台确认曲线回落
七、总结
7.1 技术要点回顾(可执行)
- 主机加固必须是“可回滚”的工程实践,而不是一次性手工改配置。
- 账号安全的核心是:强口令/锁定/最小可登录账号 + sudo 最小权限。
- 防火墙要以“端口清单”为输入,包含探活与监控,避免误伤。
- sysctl 与挂载选项属于“高影响项”,必须按主机角色模板化。
- auditd 的价值在“关键事件可追溯”,不是“全量记录”。
- 任何加固项都需要明确验证命令链与监控指标,否则无法闭环。
7.2 进阶学习方向
- OpenSSH 证书登录与集中密钥管理:解决大规模密钥分发与撤销问题。
- 主机基线自动化:Ansible/OSQuery/SCAP 等实现持续合规。
- 审计到 SIEM:把 audit/journald 与告警联动,形成响应闭环。
- 零信任与访问代理:把 SSH 入口迁移到统一访问层,实现强审计与策略化。
7.3 参考资料
- CIS Benchmarks - 各发行版安全基线对照
- OpenSSH Manual Pages - sshd_config 官方参数说明
- Linux Audit Documentation - auditd 规则与实践
附录
A. 命令速查表(加固/验证常用)
sshd -t # 校验 sshd_config 语法sshd -T # 展开生效配置(含 include)ss -lntp # 查看监听端口firewall-cmd --list-all # 查看 firewalld zone 规则nft list ruleset # 查看 nftables 规则集sysctl --system # 加载 sysctl.d 配置stat -c '%a %U:%G %n' FILE # 查看权限visudo -c # 校验 sudoers 语法auditctl -s # 查看 audit 状态ausearch -k KEY -ts recent # 按 key 查询审计事件journalctl --disk-usage # 查看 journald 占用
B. 参数详解(挑关键的讲边界)
C. CIS 基线对照(示例映射表)
| | |
|---|
| | |
| | |
| | |
| | |
| | |
| sysctl 关闭 redirect/source_route | | |
| | |
| | |