从零构建Linux系统安全加固方案:账号权限、日志审计到入侵排查
发布时间:2026/10/18 10:44:52 锦皓数字建站

前段时间朋友的项目组出了一件事一台内网机器突然CPU飙到100%排查下来发现是个挖矿木马运行在/tmp目录下root权限启动方式很诡异。机器怎么被进的原因一点都不高级——某台Redis实例暴露在公网没有设置强密码还以root身份跑着。这事让我想聊一聊系统安全及应用这个老话题它不是什么高深的安全研究而是把一台操作系统和它上面跑的应用从默认的裸奔状态拧回受控状态并且在出事之后能快速定位、止血、复盘。这篇文章会围绕账号权限、系统加固、应用层防护、日志审计和入侵排查这几条主线展开适合需要自己扛服务器安全的运维、SRE以及想了解生产环境怎么防“被搞”的后端研发。文中所有命令和配置都是我在实际环境里验证过的你可以直接照着落进自己的巡检清单和加固手册里。1. 从“出事”倒推设计系统安全其实是在管状态1.1 “系统安全及应用”到底在解决什么问题你随便找一台刚装好的Linux服务器默认状态下通常存在这些“坑”开着的ssh允许root直接登录、用密码认证、防火墙规则形同虚设、一堆用不到的系统服务在监听端口、Web服务把版本号晒在响应头里、数据库管理员账号密码弱到离谱。等真出了问题日志没集中、审计没开、想查都不知道从哪查起。所以“系统安全及应用”不是一个孤立的工具也不是买一个所谓的安全软件装上就完事。它更像是一种状态管理你要清楚这台机器对外暴露了什么、谁有权登录、上面跑的服务在监听什么端口、关键目录里有没有出现不该出现的文件、日志有没有在持续记录。我见过太多项目安全投入花在买授权上结果最基础的账号权限、日志留存反而是空白等被拖库、被植入木马之后才发现连取证素材都没有。1.2 纵深防御与“成本先算”的落地思路聊安全很容易陷入“什么都想上”的焦虑又要WAF、又要堡垒机、还要HIDS、漏洞扫描、态势感知。但现实是很多业务团队的实际情况是两台服务器加一个应用你不可能按等保三级那一套把所有设备都拉满。我通常建议按“纵深防御”的思路把投入分到四个层次账号与权限层控制谁能进系统、进去之后能干什么。系统加固层把系统默认的不安全配置改掉收敛暴露面。服务与应用层把Web服务、数据库、中间件的外部接触面控制住。监控审计层确保日志完整、可检索出事后能追溯。这四个层级每个都不需要特别贵的商业方案很多靠系统自带能力和少量开源组件就能搭起来。做之前先做一次暴露面盘点通过ss -lntp看监听端口、通过firewall-cmd --list-all看放行规则、通过last看近期登录记录把这些信息整理成一张表你就知道自己最少该补哪些窟窿。有些项目一上来就堆设备连端口清单都没理清楚东西买了不会配反而是更大的风险。2. 账号与权限最朴素也最高危的防线2.1 用户账号清理与口令策略落地账号是进入系统的第一道门本身却是很多团队最不看重的配置。先做一遍“人口普查”用awk -F: $30{print $1} /etc/passwd找出所有UID为0的账号除了root之外任何多余UID 0的账号都是隐患。再看空口令账号awk -F: ($2){print $1} /etc/shadow生产环境一条都不该有。发现废弃账号或者孤儿账号先passwd -l锁定确认没用了再userdel -r删除不要把账号留在那里当后门。口令策略要落到系统配置里不能只靠口头要求。/etc/login.defs里的几个参数是基础PASS_MAX_DAYS 90控制密码最长有效期、PASS_MIN_DAYS 7防止改密后立刻又改回去、PASS_MIN_LEN 12虽然现在很多发行版用PAM接管了长度策略但设上没坏处。复杂度用/etc/pam.d/system-auth或/etc/security/pwquality.conf来配minlen12 dcredit-1 ucredit-1 lcredit-1 ocredit-1强制要求数字、大写、小写和特殊字符同时存在。注意这里dcredit-1表示至少一个数字如果参数为0表示该项不强制很多新手理解反了。口令历史也是常见漏项remember5可以让用户在改密码时不能直接改回最近用过的几个旧密码。放开shell的账号还要检查/etc/shells是否干净避免出现/bin/false之外的奇怪解析器。2.2 SSH远程管理的标准加固姿势SSH是运维的命脉也是最常被暴力破解的对象。我自己的标准做法是先备份/etc/ssh/sshd_config然后做以下几件事PermitRootLogin no禁止root直接登录管理员用普通账号登录后sudo提权。这个改完别忘了确认至少还有一个有sudo权限的普通账号否则你会把自己锁在门外。PasswordAuthentication no改用密钥认证。把公钥部署到~/.ssh/authorized_keys私钥本地保管并设好密码。AllowUsers ops alice在sshd层面直接限制可登录用户名单配合AllowGroups做白名单更省事。不要反过来用DenyUsers白名单的维护成本更低、语义更清晰。ClientAliveInterval 300、ClientAliveCountMax 0空闲5分钟自动断开避免遗留无人看的会话。修改端口这事见仁见智。反正我自己会改因为绕开默认22能少掉一大波扫描噪音但配合firewall-cmd和SELinux要一起改否则重启sshd之后服务起不来。口令暴力破解的兜底建议上fail2ban。它能在连续失败一定次数后封禁来源IP默认配置就能用再针对sshd单独写个jail封禁时间设置成1小时。注意不要盲目把封禁时间改成永久因为办公室出口IP往往是共享的一个误封可能让整个团队登不上服务器。注意改SSH配置前先用sshd -t验证语法再执行systemctl reload sshd最后另开一个会话测试能正常登录。别把正在用的连接断了才想起检查。2.3 sudo权限最小化与特权回收拿到服务器的人越多sudo权限就越要“抠门”。直接编辑/etc/sudoers不推荐多人协作时很容易语法错误导致sudo全部失效。更规范的做法是把授权拆分到/etc/sudoers.d/目录每个业务或每个角色一个文件。比如给某个需要重启Nginx的同事不要给他ALL权限而是/devops ALL(root) /usr/bin/systemctl restart nginx这样他只能执行这一条命令。网上很多教程图省事给NOPASSWD: ALL这在长期合作的团队里可以谈但对新人或者外包人员绝对是事故温床。开了NOPASSWD之后再想收权很难因为你不知道他在哪些场景依赖了这个便利。还有一种“特权回收”需要定期做每季度或者每次人员变动拉一次/etc/sudoers.d/下所有文件对照当前人员名单核对。privilege积累是蠕变的人走了、权限却留在了服务器上这种情况在现实中非常常见。另外umask也属于权限管理的一部分。生产环境的/etc/profile或/etc/bashrc里最好设成umask 027这样新建的文件默认权限就是640防止其他人随意读走业务文件。常见的错误是某些团队为了方便把umask改成022Web目录里源码和配置全都world-readable一旦被WebShell拿到进程权限可以读走的文件就太多了。3. 主机与应用加固实操把默认状态调成“受控状态”3.1 系统服务最小化少一个服务就少一条路每多装一个服务攻击面就多一分。用systemctl list-unit-files --typeservice --stateenabled拉一遍当前开机自启服务很多发行版自带的telnet-server、rsh之类老古董如果还在赶紧systemctl --now disable掉。装好即用完了的临时组件不要图省事留在系统里比如某个调试阶段用的python -m http.server跑起来就是一个无认证的文件下载点。判断一个服务该不该留看两点一是业务是否依赖它二是它监听的网络接口是不是必须对外。以常见的avahi-daemon、cups这类桌面/局域网发现服务为例纯服务器环境基本可以禁用。改完服务列表后重新扫描一次端口ss -lntup凡是没在监听清单里的进程确认后直接停掉。容器环境里要额外注意一条容器外的systemd服务列表看得见容器内那条链路经常被忽略。--privileged高权容器、把docker.sock挂载进容器这类操作等于在主机上开了一扇门。建议跑一个基础的合规检查比如扫描特权容器docker ps --format {{.Names}} {{.Privileged}}。特权容器本身就是安全隐患不用的时候别开着。3.2 内核参数与防火墙规则的“该调才调”内核参数是安全加固里最容易“调坏”的部分。很多文章喜欢让你把一大堆net.ipv4.*全部改掉搞得以为参数越多越安全。我的经验是只动和风险强相关的几项# /etc/sysctl.conf net.ipv4.tcp_syncookies 1 # 抵御SYN Flood 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.icmp_echo_ignore_broadcasts 1 # 忽略广播pingrp_filter开反向路径过滤的意义是防止源地址伪造的数据包进入这是DDoS和各类欺骗攻击常见的利用点。改完记得sysctl -p加载并且确认业务特殊场景没有依赖这些行为。千万别顺手把ip_forward关掉如果服务器本身要做转发这样操作会导致网络全断。防火墙规则按“最小放行”来配。以firewalld为例我一般先把默认zone设为drop再单独放行业务需要的端口firewall-cmd --set-default-zonedrop firewall-cmd --permanent --add-servicessh --zonedrop firewall-cmd --permanent --add-port443/tcp --zonedrop firewall-cmd --permanent --add-source10.0.0.0/8 --zonetrusted firewall-cmd --reload把内网管理网段加入trusted zone其他一切流量默认拒绝是最省心且效果最明显的收敛方式。云产品上的安全组规则同理突破口往往不是云厂商的防火墙而是安全组把0.0.0.0/0直接放给了数据库的3306或Redis的6379。SELinux和AppArmor这类强制访问控制不少人为了省事直接setenforce 0关掉。我理解一些场景下业务组件和SELinux确实有兼容问题但把它切成permissive模式只记录不拦截比彻底禁用要稳。至少将来出问题查日志时还有个方向。3.3 Web应用与数据库攻击者最喜欢碰的两块肉应用层安全是“系统安全及应用”里的关键一环。先说Web中间件Nginx默认会在响应头里暴露版本号把server_tokens off打开能减少针对性利用。PHP环境必查/etc/php.ini里的危险函数以下这组建议直接加入disable_functionsdisable_functions exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,show_source注意curl_exec在某些业务里确实要用来调用外部接口这种情况可以只禁掉curl_multi_exec按业务实际取舍。另外上传目录权限尤其重要很多站点把上传目录和代码混在一起攻击者传一个PHP后门就能直接解析。独立的上传目录建议设置成只写不执行比如Nginx里location ^~ /upload/ { root /data/www/site; expires 30d; }配合PHP配置里open_basedir限制到站点根目录攻击者就算传了文件也跑不到站点目录之外。数据库加固常被漏掉。PostgreSQL和MySQL都建议做到几点监听地址只能设内网IPbind_address127.0.0.1或内网网段业务账号按最小权限给能只读就只读而且要建独立的账号而不是团队共用全局管理员生产环境关闭local-infile这类可能读取服务器文件的特性。Redis那一块朋友项目组已经吃过亏我建议至少做到protected-mode yes、设置requirepass、禁用或者改名危险命令config、flushall等requirepass 强密码 rename-command CONFIG rename-command FLUSHALL protected-mode yes bind 127.0.0.1 内网IP3.4 配置文件和备份文件最容易无意间“递刀”的地方除了服务本身还有一类经常被攻击者利用的点是“残留文件”。比如项目目录下不小心提交的.git目录攻击者直接访问/.git/config就能把源码结构摸个半清再比如运维在站点根目录放了个bak.tar.gz或者/data/backup.sql这类文件一旦被扫到几乎等于把数据直接送出去。实操上的建议Web根目录严格只放当前版本需要对外访问的文件任何备份、压缩包、SQL dump放在Web根目录之外的路径并且用定时任务配合find定期清理临时产物。Nginx和Apache配置里对\..*这类请求直接返回403能挡掉一部分目录扫描location ~* \.(git|svn|sql|tar\.gz|bak)$ { deny all; }对图片、附件目录还要关掉解析执行权限这才是治本的做法。4. 日志审计与入侵排查出事后怎么定位和止血4.1 三类关键日志平时就要配好安全排查的成败一半取决于日志日志不全等于案发现场被提前破坏了。Linux下至少关注三类登录与认证日志/var/log/secureCentOS系或/var/log/auth.logDebian系记录ssh登录、sudo授权、用户切换等关键动作。Web访问日志Nginx的access.log记录每次HTTP请求的来源IP、路径、状态码和响应大小。审计日志auditd的/var/log/audit/audit.log可以精确记录“谁在什么时间对哪个文件做了什么操作”。日志要做轮转/etc/logrotate.conf和/etc/logrotate.d/里配置好按天切分、保留周期通常是30到90天。很多服务器日志爆盘之后主程序直接崩溃这不叫安全叫可用性事故。有了集中日志收集条件的话比如rsyslog向日志服务器转发建议尽早做出事的时候能结合多台主机的时间线看攻击路径。没有条件的话至少确保本机日志不会一天就覆盖掉。auditd的使用有一个很大的误区就是有人为了安全开了一堆监控规则导致系统卡顿。规则要小而准重点监控/etc/passwd、/etc/shadow、/etc/sudoers、Web站点目录里的文件改动比如auditctl -w /etc/passwd -p wa -k passwd_watch auditctl -w /data/www/site -p wa -k web_watch-p wa表示记录写和属性修改-k是给事件打标签排查时用ausearch -k web_watch就能快速把相关记录捞出来。4.2 一次模拟入侵排查流程实录用一次典型的WebShell植入场景串一遍排查思路。假设某天接到报警业务日志出现大量异常500错误安全运维介入。按下面的顺序走基本不会漏先看当前连接和进程。ss -lntp看监听的端口有没有新增ps aux --sort-%cpu把CPU占用最高的进程列出来。中了挖矿木马常常表现为/tmp下多了一个名字随机的进程占用率拉满。定位之后用ls -l /proc/[pid]/exe看这个进程的可执行文件路径不要急着杀掉先保留现场。再看文件系统变化。find /data/www/site -type f -mtime -1找最近一天被修改的文件更严格一点用find / -ctime -1 -name *.php全盘扫新生成的PHP文件。攻击者留下的WebShell常常伪装成正常命名的文件比如上传目录下的a.php或者打包在某个图片文件里的马。另外检查一下计划任务crontab -l、ls /etc/cron.d/ /etc/cron.daily/木马特别喜欢靠计划任务做持久化。接着看登录记录。lastb列出失败的登录记录last列出成功登录记录。重点关注凌晨时段的外部IP登录、以及登录之后的短时间有没有下载命令。顺手看一下history里有没有异常操作比如wget一个陌生域名的压缩包然后解压执行。最后是系统账号和文件权限校验。用passwd -aS查看所有账号的密码状态用rpm -VaDebian系用dpkg --verify校验系统关键命令的完整性因为攻击者可能会替换掉ps、ls等命令来做伪装。再把/etc/ld.so.preload文件翻一下很多rootkit会通过这个机制实现全局劫持。4.3 应急响应从定位到收敛的最小闭环发现入侵后最大的忌讳是手忙脚乱把证据全删了才想到要分析。我的建议是固定一个最小闭环流程隔离把受影响机器的外网连接断开或者只保留运维管理通道阻断木马外连C2。取证保留内存有条件就抓内存镜像、进程列表、网络连接、关键文件的时间戳全部记录下来。止血杀掉恶意进程删除恶意文件清理计划任务和自启动项。修复补上被利用的漏洞比如给Redis加密码、升级版本、修掉上传绕过。改口令所有系统账号、数据库、第三方平台密码全部改掉不止本次受影响的那台机器。恢复监控重新收拢日志持续观察是否有回连和反弹。这一步里前端脚本可以用一个排查样例快速收集现场数据date /tmp/investigate/data.txt ss -lntup /tmp/investigate/data.txt ps aux --sort-%cpu /tmp/investigate/data.txt find /data/www/site -type f -mtime -1 -name *.php /tmp/investigate/data.txt last /tmp/investigate/data.txt lastb /tmp/investigate/data.txt临时命令的输出留存在一个独立目录里后续整理到安全事件报告中。别用rm把可疑文件直接删掉最好mv到隔离目录加租约压缩这些文件是复盘攻击路径的第一手材料。等复盘完成确认没有其他后门再统一清理。5. 常见问题速查与避坑经验5.1 高频安全问题的定位对照表现象可能原因快速排查命令服务器CPU长时间100%挖矿木马、异常业务进程ps aux --sort-%cpuls -l /proc/[pid]/exe非业务端口发现可疑监听后门、未授权服务ss -lntupsystemctl list-units --typeservice --staterunningroot登录记录来自陌生IP弱口令被爆破lastbjournalctl -u sshd检查失败次数Web目录出现未知php/jsp文件WebShell上传find /data/www/site -type f -name *.php -mtime -1crontab中发现陌生任务持久化木马crontab -l 查看/var/spool/cron/配置莫名被改权限过宽、可疑命令注入auditctl -w /etc/sysconfig -p wa -k sysconf_watch文件删除后仍然存在rootkit隐藏进程用stat对比时间戳必要时挂载只读介质检查这张表是“从现象反推命令”的速查入口实际排查时建议把所有输出都存档因为排查过程同时也是取证过程。很多团队在出事之后反复重启了服务、改了配置等到安全同事入场时现场已经面目全非这种经验非常沉痛。5.2 几条被反复用到的避坑经验第一别只盯22端口。很多企业把SSH锁得很死结果Redis、MongoDB、ES这类服务暴露在了公网上一条未授权访问链就完蛋。做暴露面收敛时把数据库、消息队列、对象存储这些“数据面”服务看得比远程管理更重因为它们往往直接连着核心数据。第二修复漏洞要追到“源头包”。如果在运行环境里临时改了配置、打了补丁下一次重新发布又恢复原状——这种“修了个寂寞”的情况经常出现。镜像、初始化脚本、安装包里的默认配置同样要同步更新不然每次扩容上去都是新漏洞。加了安全基线的Dockerfile应该像业务代码一样走版本管理。第三最小权限要从人延伸到进程。平时提到权限大家条件反射想到给某个员工开sudo但运维里真正被攻击者利用的往往是进程权限Web服务以root跑、临时目录可写可执行、上传目录和代码目录不做隔离。进程的权限面决定了攻击者拿到能力后的活动范围这一层的投入比给一两个人收权收益更大。第四备份要可恢复不是备份了就完事。安全事件里有相当一部分最终是靠备份救命的但很多备份脚本只做“拷贝”没做“校验”等恢复的时候发现文件早就损坏了。真正靠谱的做法是定期做一次恢复演练把备份拉到一台干净机器上启动服务确认数据能读、应用能起再算数。结尾安全更像“做卫生”不是“买保险”我在实际处理过几次安全事件之后最大的感受是系统安全及应用的门槛并不在于会用多少安全设备而在于把最基本的状态管住账号干不干净、端口多没多、日志有没有在记、敏感文件有没有乱放。这几个点检查起来可能只需要半天但能挡住大部分初级但不低级的入侵方式。如果你现在接手了一台历史遗留的服务器我建议你第一周就把上面说的账号、端口、防火墙、日志这四个维度捋一遍列一张整改清单按优先级一条条消掉。安全这件事没有终点你会发现自己刚收敛完一轮业务又引入了新的服务、新的依赖、新的入口然后下一轮检查又开始了——但它带来的确定感是值得的你至少知道自己的系统处在什么状态出问题时手里有牌。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。