“系统安全及应用”这个题目,乍一看很像高校Linux课程里的一个章节,但真放到生产环境里,它几乎是每个运维、开发乃至个人站长都绕不开的生存技能。我见过太多“服务跑起来就行”的项目,结果上线没两周就被扫了端口、改了主页、成了矿机。这篇东西不聊虚的,就围绕账户安全、权限控制、日志审计、自动化巡检这几大块,把我在实际服务器上摸爬滚打出来的经验和能直接抄作业的方案,一次性讲透。
1. 系统安全的本质:先搞清楚你在防谁
1.1 安全不是一道锁,而是一整个流程
很多初学者对“系统安全”的理解就是设个复杂密码、装个杀毒软件,这个认知在个人电脑上凑合能用,但在服务器上完全不够。攻击者从来不会按套路出牌,他们可能通过你忘记关闭的测试端口进来,可能利用某个带SUID权限的旧版程序提权,也可能只是因为你把SSH暴露在公网且允许root直接登录,然后被暴力破解撞库撞开了门。
安全的核心思路是“纵深防御”:假设任何一层都可能被攻破,那么每一层都要有独立的防护手段。密码再复杂,如果服务本身有漏洞也没用;服务再安全,如果日志没人看,被入侵了也是事后诸葛亮。我自己的配置习惯是:把系统安全拆成四个维度来管理,分别是身份验证、权限收敛、行为审计、定期巡检。这四个维度相互独立又彼此补充,任何一环失效,其他环节还能兜底。
1.2 常见的攻击路径与对应的防御切入点
攻击者进服务器的路径其实就那么几条,摸清楚它们,你就知道该在哪儿使劲。
| 攻击路径 | 常见手法 | 对应防御手段 |
|---|---|---|
| 远程登录入口 | SSH暴力破解、弱口令、默认端口扫描 | 密钥登录、禁用root远程登录、修改端口、限制来源IP、fail2ban |
| 本地权限提升 | SUID滥用、sudo配置错误、内核漏洞提权 | 收紧SUID位、最小化sudo授权、及时打补丁 |
| 应用服务漏洞 | 中间件漏洞、上传漏洞、反序列化攻击 | 最小化安装、服务降权运行、Web层加固 |
| 敏感信息泄露 | 日志泄露、备份文件外泄、环境变量泄露 | 日志集中管理、备份权限收紧、配置项脱敏 |
| 供应链风险 | 恶意软件包、带后门的第三方工具 | 校验软件签名、控制安装来源、定期审计包列表 |
我特意把“供应链风险”列进来,是因为现在很多入侵事件不是从外部打进来的,而是开发者自己装了个带恶意代码的pip包或者npm包。这类问题传统的防火墙很难拦住,只能靠平时的安全意识去弥补。
2. 账户安全与身份认证:守住登录这扇门
2.1 账户体系规划:从源头控制人与权限的对应关系
生产环境最忌讳的就是“人手一个root”。我接手过一台服务器,里面居然有七个不同的账号,全部能sudo,password文件里的信息乱成一团,甚至有两个账号是上一个离职同事遗留的。这种账户管理方式,别说安全审计,真出了事你都查不出来是谁动的。
我的建议是把账号分成三类来管理:
- 超级管理员账户:仅限极少数人使用,主要用于系统初始化和紧急故障恢复。
- 日常运维账户:使用sudo授予临时权限,且sudo规则必须精确到具体命令。
- 服务运行账户:对应各种应用服务(例如nginx、mysql、redis),没有登录Shell,也不能sudo。
具体操作上,日常运维账户一定要用useradd创建时指定合理参数,我常用的命令模板是这样的:
useradd -m -s /bin/bash -U ops_user这里-U参数会自动创建同名用户组,后面配合sudo配置更容易管理。创建完立刻设置高强度初始密码,用chage强制用户在第一次登录时修改密码。
passwd ops_user chage -d 0 ops_user要注意的是,服务运行账户应该用-M选项禁止创建家目录,并且Shell设置为/sbin/nologin:
useradd -M -s /sbin/nologin -r webapp-r参数表示创建系统账户(UID通常小于1000),这类账户不会出现在登录界面上,也天然没有家目录和登录Shell,即使服务被攻破,攻击者想通过这个账户登录系统也是徒劳。
2.2 密码策略:别让密码成为最薄弱的环节
密码策略这件事,最反直觉的其实是“定期改密”未必比“设置复杂密码”更重要。因为人的习惯是,一旦要求三个月换一次密码,密码就会变成Spring2024!或者Autumn2024@这种带规律的模式。更好的策略是:密码要长,不要定期强制更换,配合多因素认证来兜底。
/etc/login.defs里几个关键参数我建议这样配:
PASS_MAX_DAYS 99999 PASS_MIN_DAYS 7 PASS_WARN_AGE 14PASS_MIN_DAYS 7是有讲究的,它防止用户改了密码之后立刻又改回原密码。真正有效的其实是密码复杂度本身,CentOS/RHEL系可以通过/etc/security/pwquality.conf来配置:
minlen = 14 dcredit = -1 ucredit = -1 lcredit = -1 ocredit = -1这四行分别要求:密码至少14位,必须包含数字、大写字母、小写字母、特殊符号。-1表示至少有一个这种字符,注意不是“最多”,和PAM模块里其他参数语义不一样,这个很容易搞混。
注意:配置密码策略之前,先用
authconfig或者pam-auth-update确保系统使用的是PAM认证,否则改了半天不生效。检查方式是cat /etc/pam.d/system-auth(RHEL系)或者cat /etc/pam.d/common-password(Debian系),确认存在pam_pwquality.so这一行。
2.3 SSH安全加固:密钥、端口、来源限制一个都不能少
SSH基本是所有远程服务器唯一的入口,这里必须重点照顾。第一件事就是关闭密码登录,全面切换到密钥认证。很多人不敢这么做,怕密钥丢了进不了系统,但正确的做法是配一个带密码保护的私钥,再用ssh-agent缓存,安全性和便利性兼得。
客户端生成密钥时:
ssh-keygen -t ed25519 -a 64 -f ~/.ssh/my_server_keyed25519是目前平衡安全性和性能的优选算法,-a 64把KDF迭代次数拉到64轮,暴力破解私钥密码的难度会大幅增加。生成后在服务器端执行:
mkdir -p ~/.ssh && chmod 700 ~/.ssh echo "公钥内容" >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys权限设置必须严格:.ssh目录700,authorized_keys文件600。很多SSH不生效的问题都是权限多了一点点导致的,这个坑我踩过不止一次。
然后是修改/etc/ssh/sshd_config里的关键选项:
Port 22022 PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes AllowUsers ops_user dev_user MaxAuthTries 3 LoginGraceTime 30 ClientAliveInterval 300 ClientAliveCountMax 2把端口从22改成高位端口能过滤掉绝大多数无差别扫描。AllowUsers是一个容易被忽略的好选项,它从账户维度限制谁能通过SSH登录,比单纯改端口更严格——即使某开发人员的密钥泄露了,只要他不是AllowUsers列表里的人,密钥也用不上。
这里要给一个实操提醒:修改sshd配置后,不要直接重启服务,先执行:
sshd -t这个命令只会做配置语法检查,不实际重启服务。确认无误后用systemctl restart sshd重启,并且不要关闭当前SSH会话,新开一个窗口测试能登录成功后再关老窗口。否则配置写错了,你把自己锁在外面就麻烦了。
2.4 sudo权限收敛:最小化授权的正确写法
sudo授权是日常运维效率和安全性的平衡点。我见过最糟糕的写法是直接给开发团队所有人sudo ALL=(ALL) ALL,这和直接把root密码发群里没区别。
合理的sudo授权应该精确到命令、精确到用户。以运维账户为例,在/etc/sudoers.d/下创建一个运维组专用的规则文件:
%ops_user ALL=(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx这表示ops_user用户组的成员只能执行nginx的restart和reload,做不了其他越权操作。如果还需要查看日志,再补一行:
%ops_user ALL=(ALL) /usr/bin/tail -f /var/log/nginx/access.log一个比较实际的做法是:允许运维组执行systemctl命令中的status和list-units子命令,但不允许start、stop、restart任意服务,除非你明确列出来。因为systemctl这个命令本身有太多子命令,如果授权得太宽,等于没限制。
注意:修改sudoers文件一定要用
visudo命令,它会做语法检查,避免语法错误导致sudo完全无法使用。如果是编辑/etc/sudoers.d/下的文件,依然要用visudo -f /etc/sudoers.d/xxx来检查,不要直接用vim或sed改。
3. 权限与文件系统安全:收窄攻击者的活动空间
3.1 找出并清理危险的SUID/SGID文件
SUID权限是Linux系统里最容易出问题的机制之一。简单说,带SUID位的可执行程序,运行时身份是文件所有者而不是执行者。经典案例就是/usr/bin/passwd,因为普通用户需要临时以root身份修改/etc/shadow,所以必须带SUID位。但这种机制如果落在不安全的自定义程序上,等于给攻击者留了提权后门。
排查方式很直接:
find / -perm -4000 -type f 2>/dev/null这个命令会找出全盘带SUID位的文件。正常情况下,系统自带的SUID文件就那么二十几个(例如ping、su、mount、umount、passwd等),出现任何陌生程序就要立刻查清楚。需要去掉SUID位时:
chmod -s /path/to/suspicious_file更细的维度还要检查SGID位(权限中是2000):
find / -perm -2000 -type f 2>/dev/nullSGID位在目录上还有特殊含义——在该目录下新建的文件会继承目录的属组。这个特性在某些协作场景有用,但也容易被利用,比如某个共享目录是组可写的,如果再带上SGID位,攻击者写进去的木马文件就会带着合法组身份运行。
3.2 umask与默认文件权限:别让新建文件“裸奔”
服务器的默认创建文件权限,由umask这个掩码决定。很多默认安装的Linux系统umask是022,这意味着新文件权限是644(rw-r--r--),新目录是755。问题在于,如果服务器上跑的是多租户应用,或者目录需要被多个服务访问,644权限可能让不该读的人也能读。
我建议根据业务场景设置umask。偏安全的环境可以改成027,这样同组用户能读写,但其他用户完全没有权限:
umask 027在/etc/profile或者/etc/bashrc里统一设置:
echo "umask 027" >> /etc/profile改了之后要注意应用服务的启动方式。很多服务是通过systemd拉起的,systemd会继承它自己那边的默认环境,不一定读/etc/profile。所以更靠谱的方式是在服务对应的systemd unit文件里写UMask=0027。这一步容易被忽略,但实际很重要——否则你在shell里设置了027,服务实际创建的文件还是022。
3.3 利用chattr和ACL做精细化控制
对某些非常关键的文件,比如/etc/ssh/sshd_config、/etc/shadow、/etc/sudoers,光是文件权限收紧还不够,我习惯加一层不可变属性:
chattr +i /etc/ssh/sshd_config chattr +a /var/log/messages+i表示文件不可修改、不可删除、不可重命名,即使是root也没用,除非先执行chattr -i解除。+a表示只能追加内容,不能覆盖和删除,非常适合日志文件。这个属性对攻击者来说是个巨大的障碍,因为就算他们拿到root权限,想把篡改后的sshd配置写进去,也会直接报错。
不过要提醒一句:chattr +i虽然好用,但也会妨碍正常的配置变更。改配置前要先chattr -i,改完再chattr +i。我就在自动化脚本里栽过跟头——某个配置管理脚本尝试修改被加锁的文件直接失败,排查了半天才意识到是chattr锁住了。
ACL(访问控制列表)也是一种很实用的权限工具,它能突破传统的属主/属组/其他人的三组权限模型。举个例子,某个目录需要让nginx用户只读,但传统权限模式下放给“其他人”读权限就等于所有系统用户都能读。用ACL可以精确指定:
setfacl -m u:nginx:r /var/www/html查看ACL权限用getfacl。如果未来要批量清除某个用户的ACL权限,用setfacl -x u:nginx而不是setfacl -b,-b是清空所有ACL,范围更广,容易误伤。
3.4 系统目录与挂载参数的安全自查
安全加固里有个冷门但有效的操作:对不需要执行文件的文件系统分区,挂载时加上noexec参数。比如/home、/tmp、/var/tmp这类用户可写目录,加noexec后攻击者即使上传了二进制木马,也无法在该分区执行。
修改/etc/fstab挂载参数:
/dev/mapper/vg_home /home xfs defaults,noexec,nosuid 0 0nosuid参数同时加上,防止在该分区上运行带SUID位的程序。需要注意的坑是:/tmp加noexec不是所有环境都能直接上的。有些软件安装包在解压时需要在/tmp执行临时脚本,加上noexec后安装会报错。所以生产环境我是建议先加nodev,nosuid,这两项比较安全,noexec需要根据实际跑的应用逐一验证后再启用。
4. 日志安全与审计:让每一次操作都有迹可循
4.1 日志取证关键:谁能在入侵后毫发无损
很多管理员把安全重心全放在防御上,日志几乎不看。等到服务器被入侵,想溯源时才发现:日志早被清空了,或者繁杂到根本找不到关键片段。其实日志的核心价值不在于记录了多少数据,而在于关键事件能不能被快速检索出来。
一个值得坚持的好习惯是:在每台服务器的/etc/rsyslog.conf里配置远程日志转发,把日志实时同步到独立的日志服务器上。这样做的好处有两点:一是本地日志被攻击者清空后,远程日志是唯一无法删改的证据来源;二是多台服务器日志统一入口,日常巡检不必一台一台登录去看。
Minimal配置示例:
# 在 /etc/rsyslog.conf 中追加 *.* @192.168.x.x:514远程端把rsyslog开启$ModLoad imudp和$IMUDP端口监听。注意UDP 514端口存在流量伪造的风险,有条件的话用TCP模式或部署日志接收代理,安全性更好。这个策略的短板是它依赖网络连通性,所以建议配合日志文件的本地加密备份一起做。
4.2 systemd-journald与logrotate的配合
现代Linux发行版统一使用systemd-journald管理日志,它把内核日志、系统服务日志集中存储成二进制journal文件。直接用journalctl查询很方便:
journalctl -u nginx --since "1 hour ago" journalctl -u sshd --since today | grep "Failed password"但journal文件本身不会无限增长,生产环境建议把/etc/systemd/journald.conf里的SystemMaxUse设置成合理的上限(比如500M),否则长时间不清理会占满/var分区。更合理的做法是让journald把日志转发给rsyslog,然后由logrotate按天滚动归档,这样既有二进制的时效性,又有文本日志的可读性。
在/etc/logrotate.d/可以配置什么日志、什么周期、保留多少份。我常用的一个模板:
/var/log/nginx/access.log /var/log/nginx/error.log { daily rotate 14 compress delaycompress missingok notifempty create 0640 nginx adm }daily表示按天滚动,rotate 14保留14份,compress压缩旧日志,delaycompress让最新一份刚滚出来的日志先不压缩(因为nginx还可能继续往里写)。实测下来这套配置绝大多数场景都够用。
4.3 审计工具的使用姿势:auditd与journalctl组合
如果需要精确跟踪“谁在什么时间执行了什么命令、改动了哪个文件”,单靠系统日志不够,这时候要引入auditd。它属于内核级审计框架,在红帽系发行版里通常预装但默认没启用:
systemctl enable auditd --now审计规则分两大类:文件监控和系统调用监控。比如我想跟踪/etc/passwd和/etc/sudoers的每一次访问修改行为,可以配置:
auditctl -w /etc/passwd -p wa -k identity_file auditctl -w /etc/sudoers -p wa -k sudo_changes-w指定监控文件,-p指定权限类型(r读、w写、x执行、a属性变更),-k是给这条规则打个便于检索的标签。查询审计记录用:
ausearch -k identity_file -ts recent注意:auditctl设置的规则重启后会失效,要持久化必须写到/etc/audit/rules.d/下对应规则文件中,或者使用augenrules --load重新加载全部规则。
实操心得:auditd规则不是越多越好。每条规则都会增加内核开销,生产环境监控
/etc目录里敏感文件就够了,不要全局监控/usr/bin目录,否则磁盘很快会被海量审计日志填满。
4.4 日志分析:发现异常的第一道信号
日志的价值最终要落到“发现异常”上。我给自己设了几个固定的检查项,你可以直接抄:
首先,登录失败记录。所有发行版都能查SSH日志中的Failed password条目,重点核查同一IP多次失败的情况。一条命令就能搞定:
grep "Failed password" /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -nr如果看到某个IP重试了几百上千次,基本可以断定有人在爆破。
其次是sudo提权行为的记录。在/var/log/secure里查询sudo相关的标记,定时确认有没有人在非工作时间执行过特权命令。
判断一个系统是不是被入侵,有个很实用的观察点:系统平均负载。如果一台应用负载常年很低,某天CPU飙高、网络连接暴涨,先不要急着重启机器,用top和ss -tnp观察进程和连接来源,多半能找到隐藏在系统目录下的挖矿木马。
5. 自动化安全巡检:不要让安全停留在配置完成那天
5.1 Shell脚本实现每日安全扫描
安全配置一旦配好,最怕的就是“配完就忘”。系统升级、开发人员临时改权限、新部署的服务端口没收敛……任何变动都可能让之前的安全工作付诸东流。我养成了一个习惯:每周跑一次巡检脚本,把关键指标扫一遍,结果落到文件里,偶尔翻出来看看。
一个轻量级巡检脚本的核心模块包括:
#!/bin/bash # 检查SUID异常文件 find / -perm -4000 -type f 2>/dev/null > /tmp/suid_files.txt # 检查可登录账户 awk -F: '$7 != "/sbin/nologin" && $7 != "/bin/false" {print $1}' /etc/passwd # 检查SSH配置关键项 grep -E "PermitRootLogin|PasswordAuthentication" /etc/ssh/sshd_config # 检查开放端口 ss -tulnp # 检查最近登录记录 last -10把这些模块跑出来的结果和上一次快照做对比,差异部分单独列出来重点分析。我在某次巡检中就是这样发现服务器上多了一个没见过的端口在监听,顺藤摸瓜找到一个被开发者偷偷部署的测试服务,它竟然带着一个全版本漏洞的web框架。这种服务要是放着不管,出是早晚的。
5.2 安全基线核查:对照基线找偏差
有条件的团队可以引入安全基线核查工具,没有条件的也能用手动方式制定基线。比如,基线里应该强制:
- /etc/shadow文件权限为000或600
- /etc/passwd文件权限为644
- /etc/ssh/sshd_config文件权限为600
- 不存在/etc/cron.allow和/etc/cron.deny之外的异常cron任务
把这些基线固化成一个checklist,每次巡检对照执行。不要觉得手动麻烦,在服务器数量不超过二十台的环境里,脚本加checklist的方式比引入大型平台工具要灵活得多,也不会给服务器带来多余agent负担。
5.3 服务端口与进程白名单
安全巡检的核心技术点之一是“先建立正常画像,再排查异常”。我的做法是,先把当前系统中的服务和端口全部列出来,挑出真正需要对外开放的,其他全部设为目标清单,后续巡检只关注清单之外的新增项。
ss -tlnp | awk 'NR>1 {print $4}' | cut -d: -f2 | sort -u这条命令会列出所有TCP监听端口。如果是数据库服务器,通常只该有3306(且绑定内网)、SSH端口、进程本身需要的端口。多出的端口必须能说清楚是谁、为什么、什么时候开的。这个“说不清楚”就是风险信号,应立即排查进程的行为和来源。
6. 关键防线实战:从配置到验证的完整闭环
6.1 验证一条加固策略是否有效的两种方式
从经验上讲,配置加完了,必须做验证:一是正常路径能通过,二是攻击路径被阻断。以禁用root SSH登录为例,验证方式就是用root账号尝试通过SSH登录,如果配置正确,连接会被拒绝并返回Permission denied。而正常运维账号用密钥可以顺利登录。
同理,修改SSH端口后,用nc -vz IP 新端口验证端口通不通,再用旧端口探测应该超时。一些管理员改完端口后只测了新端口,忘了确认旧端口是否真的失效,结果旧端口仍然响应,等于白改。
验证方式不应该只是“看一眼配置文件”,而是实打实从外部模拟真实访问。没有条件的团队,可以直接在服务器本机执行ssh -p 端口 root@localhost试试看,效果完全一样。
6.2 结合软件包更新降低已知漏洞风险
系统安全有一个绕不开的环节:打补丁。很多入侵事件里,攻击者利用的漏洞其实早在几个月前就有官方修复版本了,只是管理员一直没更新。服务器上长期不更新软件包,等于把已知漏洞挂着招摇过市。
更新策略有一个度的问题。完全禁止更新不可取,每天自动更新也可能引入兼容性问题。我建议的节奏是:
- 安全更新(如内核、OpenSSL、OpenSSH):每两周检查一次,测试环境验证后推向生产。
- 功能版本升级:不主动更新,等业务有需要时再评估。
命令层面,apt/yum都有安全更新接口:
# RHEL系 yum update-minimal --security # Debian系 apt update && apt list --upgradable | grep -i security生产环境强推在凌晨低峰期执行,并且更新前做快照或备份。更新后至少观察十分钟服务状态,确保没有因依赖变更导致服务异常。
6.3 攻击面最小化:删除不需要的组件和服务
最小化安装是系统安全里性价比最高的一条。一台干净的服务器,默认只开SSH就足够跑业务了,但很多发行版默认会附带一堆你根本用不上的服务:打印服务(cups)、蓝牙栈(bluetooth)、邮件传输代理(postfix/sendmail)等。这些服务不仅白白占资源,还额外引入攻击面。
查看和管理开机启动:
systemctl list-unit-files --type=service --state=enabled对不需要的服务直接禁用并停止:
systemctl disable --now cups systemctl disable --now bluetooth还有一类容易忽略的:自动挂载服务(autofs)、远程桌面协议端口(RDP)、Telnet等明文远程控制协议。这些老协议如果还开着,就属于高危项,必须彻底关闭。
6.4 利用入侵检测思维:fail2ban与异常连接的发现
虽然防火墙能限制端口,但对企业网络里“合法端口上的持续暴力尝试”,防火墙是挡不住的。SSH的暴力破解是公网服务器最常见的安全事件,百试不爽的解决方案是fail2ban。
fail2ban的原理很朴素:监控日志,发现同一来源多次失败尝试,就动态调用防火墙规则封禁该IP一段时间。安装后配置一个jail(以Debian系路径为例):
[sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 findtime = 600 bantime = 3600maxretry 3表示10分钟内失败3次就触发封禁,bantime 3600表示封禁1小时。如果你把SSH端口改成了22022,这里port也要同步修改,否则fail2ban解析的还是22端口。
实测下来,fail2ban能挡住几乎所有无差别扫描式爆破,但它不能完全替代密钥认证和AllowUsers限制——攻击者如果拿到合法密钥或者合法用户名,fail2ban就失效了。所以fail2ban属于“水桶拼图中比较靠下的那一块”,不能因为装了它就觉得万事大吉。
7. 常见问题速查与排查技巧
7.1 问题场景表
我整理了一张高频排查表,非常适合放在手边参照:
| 典型问题 | 可能原因 | 排查命令 | 解决方式 |
|---|---|---|---|
| SSH密码登录被拒绝 | PasswordAuthentication设置为no,但客户端未配置密钥 | grep PasswordAuthentication /etc/ssh/sshd_config | 客户端生成密钥并加入authorized_keys |
| 修改端口后无法连接 | 防火墙/selinux未放行新端口 | ss -tlnp、getenforce | firewalld添加端口规则或调整SELinux布尔值 |
| 普通用户执行sudo报错 | 用户不在sudo组或sudoers规则配置错误 | groups 用户名、visudo -c | 修改/etc/sudoers.d/添加精准规则 |
| 文件明明给了777还是无法访问 | SELinux策略限制 | ls -Z、ausearch -m avc | 调整SELinux布尔值或写上正确的上下文 |
| 系统日志增长过快 | auditd规则过宽或journald无上限 | journalctl --disk-usage、auditctl -l | 缩小审计范围,设置journald上限 |
| 开放端口里多出未知端口 | 服务被植入后门或自带端口 | ss -tnp、lsof -i:端口 | 定位进程,终止并排查启动项 |
关于SELinux,这里展开多说一句。很多管理员为了省事实质上是把SELinux直接关掉了,这个做法在安全要求不高的个人服务器上勉强能接受,但生产环境最好不要关。SELinux的坑在于默认策略会让原本正常的服务访问报错,而且报错不一定直接提示“SELinux denied”,而是显示权限不足。遇到这类问题,先用ausearch -m avc -ts recent查一下最近的拒绝记录,再针对性地调整布尔值或文件上下文,比直接setenforce 0要科学得多。
7.2 配置审核流程
每次做安全配置变更,我建议严格走“备份、测试、验证、记录”四步。任何配置文件的修改,第一步永远是备份:
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)然后在小范围或测试机验证,确认正常后再批量推送。推送完成后记录下变更内容和时间,这样以后出问题能快速回滚,也能回答“这台机器上到底改过什么”这个灵魂拷问。
7.3 说一个我踩过的真实心态坑
有段时间我觉得自己把服务器安全做得非常完善:密钥登录、fail2ban、防火墙、日志转发都上了。然后某天凌晨两点,监控告警说数据库CPU跑满,登录上去一看,rsyslog的日志转发配置因为磁盘写满挂了,而挂载/var的分区正好因为日志膨胀被撑到100%。复盘时发现,我忽略了logrotate对转发日志目录的轮转,导致日志文件无限增长。这类安全问题不是被攻击者攻破,而是自己配置不当产生的不可用。
从此我养成了一个习惯:安全配置的每一项都要问自己一句“如果这项配置失效,会不会引发系统不可用”。平衡安全性和可用性才是做系统安全真正难的地方。太激进的最小化可能会让运维寸步难行,太保守的配置又等于把门敞开。关键在于持续巡检、持续验证,把安全当成一个不断优化的过程,而不是某一天一顿操作就一劳永逸的工程。