Linux系统安全加固实战:从SSH到日志审计的完整防护体系

发布时间:2026/10/18 8:17:43
Linux系统安全加固实战:从SSH到日志审计的完整防护体系
做了这么多年Linux运维我处理过的服务器故障里真正被“高级黑客”精准打击的案例极少绝大多数问题都出在基础防护没做到位SSH密码被爆破、某个漏洞补丁没跟上、权限放得太宽、关键日志没人看。这篇文章我想把Linux系统安全这块完整梳理一遍从登录入口加固、账号权限管控、防火墙和SELinux配置到日志审计和应急响应全部基于我在真实环境里反复验证过的操作方案。内容偏实战适合刚接手服务器的新手也适合想系统性排查安全短板的运维老手。1. 先搞清楚Linux服务器到底怕什么1.1 常见攻击路径与威胁模型在动手加固之前得先想清楚一个核心问题——你的服务器最可能从哪个环节被打穿。Linux的威胁模型其实比大多数人想象的更集中攻击者不会漫无目的地撒网他们走的路子基本就那几条。第一条是暴力破解。我见过太多服务器直接开着默认的22端口root允许密码登录密码还是常见的弱口令这种机器在网上挂着基本活不过三天。攻击者用字典配合自动化工具一天能试几万次密码只要密码稍微有规律被撞开只是时间问题。第二条是漏洞利用。系统内核、Web服务、中间件、数据库任何一个组件存在公开漏洞而没有及时修复都可能成为突破口。尤其是跑着公网Web服务的机器攻击者会先扫描中间件版本匹配已知漏洞库然后直接打EXP一套流程自动化程度很高。第三条是提权和横向移动。攻击者先进来拿个普通用户权限然后通过内核漏洞提权到root或者挖出配置不当的SUID程序、sudo规则漏洞往上爬。拿到一台机器之后再以内网为跳板横向扩散扫描同网段的其他主机复用密码和密钥扩散速度非常快。第四条是供应链和第三方风险。这个经常被忽视——装了一个来路不明的软件源、下载了被投毒的安装包、引入了有后门的开源组件等于自己把门打开了。还有一种是离职人员的账号没及时回收、测试用的临时账号还挂在系统里这些都是潜在的暗门。做安全加固本质上就是把这几个路径全部堵住。不用追求所谓的“绝对安全”那是伪命题只要把攻击成本抬到足够高让攻击者觉得不划算大部分威胁就自动绕开了。所以我的思路是入口收紧、权限最小化、行为可审计、出事能响应。1.2 安全基线的建立思路很多刚入行的人喜欢一上来就装各种安全软件什么主机入侵检测、Web应用防火墙、漏洞扫描器堆了一堆东西结果告警刷屏没人看系统反而被拖慢真正出事的时候连日志都找不到。我更推荐“基线先行”的做法。所谓基线就是一套你愿意对每一台服务器强制执行的最小安全配置集合。先不急着上工具把系统本身的攻击面收拾干净。基线一般分几层系统层要选稳定的发行版并持续跟进安全更新关闭不需要的服务和端口账号层要强制密钥认证、禁用root远程登录、收回多余账号权限应用层要按最小权限运行服务每个服务用独立的低权限账号网络层要按业务需要开放端口默认拒绝最后是审计层确保关键日志落盘并且有告警通道。每一台新服务器上线之前我都会照着这套基线过一遍。刚开始觉得繁琐多走几遍就成了肌肉记忆。关键是基线不能只写在文档里要落到具体的配置文件和命令操作上让团队任何人来执行都能得到一致的结果。下面几个章节我就按这套基线一层层往下拆每一步都可以直接抄作业。2. 账号与远程登录这块是最值得花时间的2.1 SSH加固从默认配置开始改SSH是绝大多数Linux服务器唯一的远程管理入口也是最容易被攻击的窗口。我接手每台机器的第一件事就是重写sshd_config的核心参数。先看端口。默认的22端口建议改掉改成几千以上的高位端口。防不住真正的定向攻击但能避开全网自动扫描器的大规模撞库——那些扫描脚本默认就扫22改了之后日志瞬间清净一大半。改端口的时候注意要同步更新防火墙放行规则和SELinux端口标签不然改完直接连不上。然后是认证方式。PermitRootLogin设置成noroot只允许通过控制台登录远程一律用普通用户加sudo。PasswordAuthentication改成no只保留密钥认证。这一步做完暴力破解基本就断了路因为没有密码可破了。有位数的也不要怕密钥使用的是非对称加密只要私钥保管好安全级别远高于任何密码。配置完别忘了几件事PubkeyAuthentication yes明确打开AuthorizedKeysFile指向.ssh/authorized_keysLoginGraceTime设成30秒MaxAuthTries设成3次ClientAliveInterval和ClientAliveCountMax配合用来断开僵死连接。这些参数都是为了减少占用连接、防止低效试探。改完配置记得先做个语法检查sshd -t systemctl reload sshdreload不会断开现有连接这点很关键。我见过有人直接restart的正在跑的任务被掐断不说如果新配置有语法错误服务起不来就只能跑机房了。还有两步值得做。第一步有条件就装fail2ban配置好sshd的jail规则连续失败超过设定次数直接拉黑IP给自动化爆破一个“硬反馈”。第二步给密钥本身加个口令配合ssh-agent使用这样即使密钥文件丢了没有口令也起不了作用。2.2 sudo与用户权限的精细管控登录这块收紧了内部权限也不能松。Linux安全里有个铁律叫最小权限——每个用户只拥有完成自身工作所需的最小权限集不多给一分。实际做法是日常操作全用普通账号需要管理员权限时通过sudo提权。sudo的配置文件在/etc/sudoers编辑时一定用visudo命令打开这个工具自带语法检查改错了不会让你保存能避免因为配置文件错误导致sudo彻底瘫痪的尴尬。sudo权限分配上不建议给用户开放的ALL ALL(ALL) ALL这种全量权限。更合理的写法是精确到命令。比如让运维同事可以管理Nginx但不给他随便改用户密码的权限opsuser ALL(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx能用这种颗粒度管控的就不要开大口子。另一个容易被忽视的点是sudo su这个后门。给了sudo权限用户sudo su就直接切到root了前面做的精细授权全白搭。可以在sudoers里加上这么一条禁用掉Defaults !authenticate等等这条不是干这个用的。正确的做法是限制sudo su的执行比如不把/usr/bin/su纳入授权范围同时在securetty和PAM层面对su命令做限制。更简单粗暴一点的方案是在sudoers里定义Cmnd_Alias把高风险命令集中管理Cmnd_Alias HIGH_RISK /usr/bin/passwd, /usr/bin/su, /usr/bin/sudo, /bin/mount, /bin/umount opsuser ALL(ALL) ALL, !HIGH_RISK这样的好处是用户可以正常使用sudo完成日常管理但没法通过su切换到root也没法改别人的密码。权限管控做到这个程度内部人员的操作风险就基本可控了。2.3 密码策略与PAM认证即便用了密钥认证系统里仍然存在各种密码场景控制台登录、用户自己的账户、服务之间的认证。密码策略这一关不能省靠的就是PAM可插拔认证模块这套机制。在主流发行版上密码复杂度规则在/etc/security/pwquality.conf里配置。我常用的配置是这样的minlen 12 dcredit -1 ucredit -1 lcredit -1 ocredit -1 minclass 4解释一下minlen是密码最小长度12位起步dcredit、ucredit、lcredit、ocredit分别代表数字、大写字母、小写字母、特殊字符的必需数量设为负数表示“至少包含”加起来四类字符都要求出现minclass代表字符类别最小值。这样配出来的密码暴力破解的成本直接翻几个数量级。锁定策略用pam_faillock模块在/etc/pam.d/system-auth和/etc/pam.d/password-auth里配置。连续错误5次锁定用户15分钟这个参数要把握好——太严了容易把自己人锁在外面太松了起不到防爆破的作用。我在生产环境用的是fail_interval90015分钟内累计、deny5、unlock_time900。另外还有一个细节root账号的锁定策略要单独对待。root被锁了会导致本地也无法登录处理起来很麻烦。我的做法是root账号不参与faillock锁定而是通过控制台访问限制和sudo审计来管控。PAM这块配置完了记得用pam-auth-update之类的工具确认模块加载顺序没问题或者直接重启一次登录会话做验证。改PAM配置最怕改坏改完老老实实开个新终端测试一遍登录确认没问题再离开。3. 系统层防护防火墙、强制访问控制和文件保护3.1 firewalld实战配置系统层面的第一道防线是防火墙。现在主流发行版都用firewalld管理netfilter规则相比老式的iptables它的zon概念更接近实际网络拓扑用起来也更直观。我的配置原则很简单默认拒绝按需放行。服务器上只开放业务必需的端口其余全部不对外。以一台Web服务器为例通常只对外开放80和443管理端口走内网或跳板机其余端口一律关闭。先看当前默认区域firewall-cmd --get-default-zone大多数服务器默认区域是public把默认区域改成只允许SSH然后把其他端口按业务加进来firewall-cmd --set-default-zonepublic firewall-cmd --permanent --add-servicessh firewall-cmd --permanent --add-servicehttp firewall-cmd --permanent --add-servicehttps firewall-cmd --reload这里有个核心观念所有临时生效的规则只用于测试确认无误后一定要加--permanent参数持久化最后统一reload。不然防火墙一重启或者reload一次规则全没了服务直接裸奔。更精细的话可以把管理网段单独划一个zone。比如内网运维网段允许访问22和数据库端口公网zone只开放Web端口。这样即使某个服务被攻击了横向移动的路径也会被防火墙切断。firewalld还支持富规则rich rules可以做基于来源IP或端口的更复杂限制。比如只允许特定IP访问mysql端口firewall-cmd --permanent --zonepublic --add-rich-rulerule familyipv4 source address192.168.10.0/24 port port3306 protocoltcp accept最后提醒一个坑改防火墙规则前永远确保有一条通往外部的备用连接通道。最稳妥的做法是先加一个放行规则再reload不要先reload再放行。我见过太多同事改防火墙把自己锁在外面的情况了这后面专门有一节讲怎么自救。3.2 SELinux与AppArmor别急着关掉新装的Linux系统不少教程上来就教人关SELinux理由是“太麻烦、影响服务启动”。这个做法我非常不认同。SELinux是内核级的强制访问控制机制在系统被攻破后它可能是最后一道拦截提权操作的防线。SELinux的工作机制可以通俗理解成传统权限DAC管的是“谁有权限访问文件”SELinuxMAC管的是“进程能不能访问这个文件”。即使攻击者拿到了某个服务的控制权在SELinux的约束下他能触碰的文件范围依然被严格限制在服务域内。看SELinux状态的命令getenforce输出Enforcing就是强制开启状态。永久配置在/etc/selinux/config里把SELINUXenforcing改掉即可切换。生产环境的建议是保持Enforcing至少也要Permissive只记录不拦截跑一段时间收集告警再逐步收紧。遇到服务因为SELinux起不来的情况不要直接关SELinux而是去查AVC告警ausearch -m avc -ts recent根据告警内容要么调整文件上下文要么开启对应的布尔值。比如Nginx要访问非标准目录下的文件需要把目录上下文设为httpd_sys_content_tsemanage fcontext -a -t httpd_sys_content_t /data/web(/.*)? restorecon -Rv /data/web常用的布尔值操作比如允许httpd访问网络setsebool -P httpd_can_network_connect on-P参数表示持久化不加的话重启就失效了。SELinux这套东西上手有一定成本但真的值得花时间。系统被入侵后SELinux往往能帮你把损失控制在极小范围内这个价值在平时看不出来出事的时候就是天壤之别。AppArmor是另一类强制访问控制方案常见于Ubuntu系。用法和SELinux不同但思路类似建议同样保持开启按需为服务配置profile。3.3 文件权限与关键目录保护强制访问控制之外传统文件权限也不能放松。Linux默认的umask是022新建文件其他用户只有读权限这还算可以。但如果有人把umask改成000或者服务运行账号本身就是root情况就比较危险了。权限配置上我坚持几个原则所有的配置文件和数据文件属主明确服务运行账号使用独立低权限用户严禁以root身份运行常驻服务进程。滥用SUID是提权攻击的重灾区。所谓SUID就是文件所有者权限中s那个标志它会允许普通用户以文件所有者的身份执行该程序。系统里大部分程序其实不需要SUID。定期扫描是一个必要操作find / -perm -4000 -type f 2/dev/null排查输出里每个SUID文件的必要性比如passwd、sudo、mount这些系统自带的可以保留出现非系统路径下的SUID文件就要高度警惕基本可以当成入侵信号处理。另外对关键文件和配置做加固可以用chattr命令给文件加不可变属性chattr i /etc/passwd /etc/shadow /etc/sudoers加了i属性的文件即使是root也无法直接修改、删除想改回来用chattr -i就行。这个手段能有效抑制篡改类攻击但运维时要记得自己加了锁配合脚本批量部署的时候注意先解锁。/tmp目录安全也容易被人忽略。临时目录是全系统所有用户都能写的攻击者爱往这里放恶意脚本。有条件的建议把/tmp单独分区并以noexec、nosuid、nodev方式挂载这样临时目录里的文件就算被上传了也无法执行mount -o remount,noexec,nosuid,nodev /tmp别忘了检查/var/tmp它跟/tmp是类似的临时目录攻击者也会利用同样按这个标准处理。4. 看得见才防得住日志、审计与告警4.1 日志体系搭建安全工作的前提是“可审计”。假如事后连日志都查不到那前面做的所有防护都等于没有。先把日志体系搭好这步不能省。现代Linux发行版的日志系统是journald加rsyslog的组合。journald负责采集内核和系统服务的结构化日志rsyslog负责把约定的日志写入文本文件。两者配合使用。先看journald日志journalctl -u sshd --since 24 hours ago journalctl -p err --since 24 hours ago排查某个服务的问题时先按服务名过滤再按时间范围缩小效率最高。journald的日志默认存在内存和/var/log/journal目录如果想长期保留需要确保目录存在并把Storage改成persistentmkdir -p /var/log/journal systemctl restart systemd-journald再看rsyslog这边的关键文件。不同发行版日志位置稍有差别CentOS系看/var/log/secureUbuntu系看/var/log/auth.log这两个是认证日志登录成功失败都有记录是排查爆破和入侵的主要依据。系统整体运行信息在/var/log/messagesCentOS或/var/log/syslogUbuntu。日志轮转用logrotate管理配置在/etc/logrotate.d/目录下。我的习惯是保留90天日志每天轮转并对压缩后的日志做权限收敛/var/log/secure { daily rotate 90 compress missingok notifempty create 0600 root root }这样日志不会无限占满磁盘也能保证历史追溯能力。日志文件权限要注意认证日志里涉及敏感信息最好按上面这个配置把新建文件的权限设成600只能root读。还有一个容易被忽视的细节系统时间同步。日志如果没有准确的时间戳事后追溯各个事件的先后顺序会很困难。确保chrony或ntp服务正常运行是日志体系正常工作的前提。4.2 必看的审计点日志这么多不可能每天逐行看。我认为最值得关注的审计点就几个盯住它们就抓住了安全监控的大头。第一个认证日志里的失败登录记录。搜索Failed password统计来源IP和用户名这是判断是否遭到爆破的最直观指标grep Failed password /var/log/secure | awk {print $(NF-3)} | sort | uniq -c | sort -nr | head -20看到某个IP尝试了几百上千次基本可以确定是扫描或爆破行为直接加入防火墙黑名单。第二个sudo的提权记录。认证日志里凡是涉及sudo的行都值得看因为sudo操作对应着管理员权限的使用。正常用户不会频繁执行sudo出现大量提权行为要么是操作习惯有问题要么账号已被入侵。第三个用户登录状态的变化。last命令查看正常登录记录lastb查看失败登录记录。重点是检查是否存在来源异常的登录、非工作时间登录、以及长期未清理的僵死会话。第四个系统账户变化。/etc/passwd和/etc/shadow被修改是严重信号要么有人创建了隐藏账户要么有人改了密码。可以配置auditd对这些关键文件做实时监控auditctl -w /etc/passwd -p wa -k passwd_watch auditctl -w /etc/shadow -p wa -k shadow_watch-w指定监听的路径-p wa表示监控写入和属性修改操作-k是给规则打的标签方便检索。这是审计中一个成本低但防护效果显著的做法能第一时间知道系统关键权限文件被谁动过。查看审计结果ausearch -k passwd_watch -ts today第五个就是计划任务和开机自启项。攻击者喜欢把后门藏在crontab或systemd服务里定期拉取恶意脚本执行。所以/etc/crontab、/etc/cron.d/、用户的crontab是重点检查对象systemctl list-unit-files | grep enabled也要过一遍。4.3 日志告警自动化日志光存着不行得让“异常”主动浮出来。纯人工盯着既不现实也容易漏上告警系统才是正途。最轻量的方式是用脚本配合crontab定期扫描日志。比如每5分钟检查一次认证日志发现失败次数超过阈值就触发通知。脚本逻辑不复杂我贴一个简单版本#!/bin/bash AUTH_LOG/var/log/secure THRESHOLD10 FAIL_COUNT$(grep Failed password $AUTH_LOG | awk {print $(NF-3)} | sort | uniq -c | awk -v t$THRESHOLD $1 t {print $2} | wc -l) if [ $FAIL_COUNT -gt 0 ]; then echo $(date) 检测到疑似暴力破解来源IP超过阈值 | mail -s SSH爆破告警 adminexample.com fi生产环境建议直接使用成熟的日志分析平台比如把rsyslog的日志转发到集中式日志系统配合告警规则引擎。不过对于中小规模环境上面的脚本方案已经能解决90%的需求先把“有人爆破”这个高频问题接住。还要提一个进阶细节把日志同时复制一份到远端日志服务器。攻击者即使拿到了服务器权限并清掉了本地日志也抹不掉远端副本。很多入侵案例最终是靠远端日志还原攻击路径的。rsyslog远程转发配置很简单server端开514端口接收client端加一行转发规则即可。安全体系的完整闭环是“防护、检测、响应、恢复”日志告警就是这个闭环里的检测引擎。没有它前面做的所有加固都是沉默的堡垒能不能防住攻击全凭运气。5. 应急响应真出事的时候怎么做5.1 忘记root密码的抢救流程先说个不涉及攻击但也很常见的事故root密码忘了远程登录又只有root账号这种情况我遇到不少次多半是接手前任环境时碰上。怎么办如果是物理机或虚拟机有控制台权限可以通过单用户模式重置密码。重启机器在GRUB引导菜单界面按e进入编辑模式找到linux开头新版本可能是linux16或linuxefi的那一行在行尾加上single或者rd.breaksingle直接进入单用户模式rd.break是在切换根文件系统前中断需要额外执行mount -o remount,rw /sysroot和chroot /sysroot才能操作文件系统。两者目的都是绕过登录验证拿一个root shell。进入单用户模式后就可以直接重置密码passwd root exec /sbin/init重启后新密码生效。这个流程要注意单用户模式能进入的前提是引导加载程序没被密码保护且机器有物理访问能力。这也是我在前面强调要开启SELinux和加固引导器的原因——物理接触等于最高权限。如果是云服务器一般通过控制台提供的VNC或管理终端也能进入单用户模式具体入口各家控制台略有差异但原理一样。换密码之后记得确认SSH相关配置允许root在控制台内登录否则新密码也只是本地可用了。5.2 服务器疑似被入侵的排查思路接到应用响应异常的告警或者收到安全通报说某IP在攻击你们怎么判断服务器是不是真的被拿下了我提供一个标准的排查流程按这个顺序走基本不会漏掉关键痕迹。第一步看进程和资源占用。异常的高CPU或者高内存进程是首要怀疑对象top -c ps -ef --forestps的树状视图能直观看到进程的父子关系恶意程序通常会启动子进程来执行命令。看到名字古怪的进程随机字符串、系统命令的拼写变体先记下PID再用ls -l /proc/PID/exe查看它的真实可执行文件路径。第二步查网络连接。恶意程序与C2服务器通信必然建立外连看监听和连接状态netstat -antp ss -antp lsof -i重点检查进程名与实际端口不相符的情况以及连向异常IP地址的ESTABLISHED连接。第三步查认证日志。看有没有来源不明的成功登录记录last -20 grep Accepted /var/log/secure | tail -20如果发现正常业务时间之外、来源IP又不合理的成功登录基本可以断定账号已经失守要立刻改密码、踢会话。第四步查持久化后门。攻击者进来后会想方设法让恶意程序在下次重启后还能存活。检查几个地方/etc/crontab和用户crontab、/etc/rc.local、systemctl list-unit-files | grep enabled、以及每个用户家目录下的.ssh/authorized_keys文件。后门排查没有捷径就是逐个确认。第五步查被篡改的系统命令。有些高水平的攻击者会替换ps、ls、netstat等系统命令来隐藏自己。用rpm -V或对比命令文件的时间戳可以发现问题rpm -V procps-ng输出异常说明对应命令包的文件被改过了。此时不要在原系统上继续操作正确的做法是离线挂载磁盘在干净环境中做分析。整个排查过程建议只读操作不要修复、不要删文件、不要重启。保留现场是取证的基础修复动作应该在分析结论明确之后再做。5.3 防火墙配置失误后的自救这个场景太常见了改防火墙规则加错了网段、顺序不对或者reload完发现把SSH端口挡了远程连接直接断掉。这个时候最怕慌手头没有备用通道的话只能走带外通道。物理机和内网虚拟机可以通过IPMI/iDRAC这类带外管理卡提供的远程控制台登录前提是带外管理网和生产网是分开的而且你有带外口的管理账号。登录控制台后相当于直接坐在机器前面可以执行本机命令修正规则。云服务器的话主流控制台都提供VNC/网页终端等带外登录方式相当于虚拟的物理控制台。进去之后如果机器还能响应直接执行systemctl stop firewalld或者更精确的诊断步骤iptables -L -n -v查看当前生效规则确认是哪条把SSH挡了然后修正或删除规则。千万别在没备份的情况下盲目执行iptables -F清空所有规则——生产环境遗留的NAT规则和防规则可能依赖这个链清空后会造成更大范围故障。如果firewalld服务本身启动失败导致网络异常可以进入救援模式把根文件系统挂载出来后修改规则文件再重启。手动修改/etc/firewalld/zones/下的XML文件删除有问题的规则后重新加载配置。防止这类事故的根本办法是所有防火墙操作都带上“先备份、再改动、后验证”的流程。改规则前可以执行iptables-save /root/iptables.bak同理firewalld可以复制一份/etc/firewalld/目录。多花一分钟备份能避免几个小时甚至一天的上不了线的痛苦。6. 一些长期维护的心得6.1 安全更新与补丁管理文章最后这部分我想聊聊比任何安全软件都重要的一件事及时打补丁。我接过的服务器里有被入侵后排查发现漏洞早已公开好几个月、厂商补丁也发布了就是因为运维担心重启影响业务一直没打结果被人利用漏洞直接提权成功。补丁管理最关键的是计划性。业务窗口能接受的重启时间提前规划好每月固定一个维护窗口来做安全更新优先处理公开漏洞和高危公告涉及的组件。主流发行版都有自动安全更新的选项比如CentOS的yum-cron、Ubuntu的unattended-upgrades可以先在配置文件里限定只自动更新安全公告类补丁减少依赖冲突。对于不能轻易重启的数据库和核心服务至少要做到数据库和核心组件的补丁跟着厂商公告走应用层的代码漏洞定期审查和升级依赖。安全更新本质上是一场与时间的赛跑漏洞公开到被利用的平均时间越来越短补丁越晚打风险敞口就越久。6.2 备份与恢复演练安全不只是防“进得来”还包括“坏了能回来”。中了勒索病毒、磁盘损坏、误删数据这些都是安全事件的范畴。备份是最后一道保底防线没有备份的系统谈安全等于空中楼阁。备份策略我的经验是三层本地定时备份、异地冷备、定期恢复演练。本地备份方便快速恢复异地副本防止机房级故障和数据中心故障恢复演练则是验证备份到底能不能用。很多团队的备份时间表配置得很好但从来没真正恢复测试过真出事才发现备份文件是坏的那就真是欲哭无泪了。恢复演练不必做得太频繁每季度针对核心系统做一次“完整拉起来”的演练就够。重点验证三件事备份数据的完整性、恢复流程的可操作性、恢复耗时是否在业务可接受的范围内。这个过程还能顺便检验操作文档有没有过期一举多得。最后说一个心态上的体会。我做了这些年最大的感受是安全不是一个需要“搞定”的项目也不是装了一套高级的系统就万事大吉了。它是持续性的维护动作——每周看一次认证日志每个月做一轮补丁更新每季度做一次恢复演练这些不起眼的习惯长期坚持下来远比任何花哨的安全产品更可靠。把基础动作做扎实把循环跑起来Linux系统安全这件事完全可以做到心里有底。