资讯动态

Linux系统安全加固实战:从弱口令爆破到挖矿木马应急的完整防御链

发布时间:2026/10/18 13:07:55 来源:尧图企业网站定制
开篇一次事故让我决定重新审视 Linux 系统安全前阵子帮朋友排查一台服务器的“卡顿问题”登录上去看了一眼负载直接吓一跳——load average飙到 20 多top里一个陌生进程占着 300% 的 CPU。再细查网络连接发现这台机器正疯狂向外发包标准的挖矿木马特征。问了下情况服务器部署了一个很老的应用开放了 22 端口密码设置还是“Admin123”这种级别。从日志里看对方用国外 IP 爆破了整整两天最后成功登录然后下木马、提权、清理痕迹一套流程行云流水。这台设备最终拆掉重装但留下的教训很深刻Linux 系统安全不是某一个单独的动作而是从账号、权限、网络、日志到应急响应的一整条防御链。任何一环的疏漏都可能让前面的努力全部白费。这篇文章我想从一线运维的视角把 Linux 系统安全这件事完整地拆一遍。内容覆盖威胁模型、账号加固、最小权限、网络防线、日志审计、应急响应和日常运维适合三种人看刚接触 Linux 运维的新人、被安全问题困扰过的开发者、以及准备给现有服务器做一遍安全体检的同行。每一段都是实操经验命令直接能给思路讲透你也好判断哪些方案真正适合自己的环境。1. 先想清楚对手是谁安全加固的优先级排序1.1 常见的攻击路径与威胁模型很多人一提安全就紧张恨不得把所有加固手段全怼上去。但实际做安全的第一步不是装各种工具而是先想清楚一个问题我的机器正面临哪些威胁从实际入侵案例来看Linux 服务器被攻破的路径绝大多数绕不开这几类。第一类是弱口令爆破。这占了所有入侵事件的很大比例尤其是开放 SSH 端口、root 密码简单、或者用了常见弱密码的机器。攻击者用自动化工具对常用用户名加字典密码做批量尝试24 小时不间断。一台防御空白的主机被爆破成功只是时间问题。第二类是未修复的已知漏洞。比如老版本的服务程序存在远程代码执行漏洞攻击者扫描到开放端口后用公开的 PoC概念验证代码直接打进来甚至不需要任何凭据。这类攻击对老旧环境杀伤力最大因为补丁更新往往是最容易被忽略的环节。第三类是配置不当导致的暴露。比如把数据库端口裸奔到公网Redis 服务未设密码且以 root 权限运行Web 目录被写入权限放得太宽——这些都不是“入侵”而是大门自己敞开着被扫描器像是逛街一样看见顺手就进来了。第四类是供应链与第三方风险。上游镜像被污染、安装包被篡改或者随便从不明渠道拉了一个二进制脚本扔到服务器上执行都可能直接给攻击者铺好了路。1.2 按成本收益给加固动作排个序理清威胁模型之后加固的优先级就很清晰了。我给自己的原则是八个字先堵口子再补细节。最高优先级是阻断常见攻击入口禁用 SSH 密码登录、关闭不必要的端口、修复高危漏洞、收敛对外开放的服务面。这些动作成本低、见效快能挡住 90% 以上的自动化攻击。第二优先级是做好权限控制和隔离非 root 运行服务、分权管理、最小化授权文件系统访问。即使攻击者拿到了某个账户也走不远、提不了权。第三优先级才是日志、审计、入侵检测这些“看得见”的能力。它们是纵深防御的下一层用于发现已经绕过外层防护的入侵者并及时止损。有人一上来就研究内核加固、容器逃逸防护但自己的 SSH 还是密码登录这等于先把后门焊死却把前门敞开。安全建设讲究性价比先把基础工作做完再往深处走。2. 账户与认证堵住最容易被攻破的大门2.1 密码策略的硬性配置SSH 的弱口令爆破是我见过最频繁的攻击方式。很多机器被拿下的第一步就是 root 或某个普通用户的密码被猜中。密码策略虽然看似老生常谈但落地时依然有很多机器漏配。先看密码老化策略核心配置文件是/etc/login.defs。几个关键参数需要确认PASS_MAX_DAYS 90 PASS_MIN_DAYS 10 PASS_WARN_AGE 7PASS_MAX_DAYS控制密码最长使用天数PASS_MIN_DAYS限制最短修改间隔防止用户改了立刻改回原密码PASS_WARN_AGE是到期前提醒天数。修改文件只对后续新建用户生效老用户需要再执行一次chage -M 90 用户名单独调整。再配合密码复杂度可以用 PAM 的pwquality模块。在/etc/pam.d/system-authCentOS/RHEL 系或/etc/pam.d/common-passwordDebian/Ubuntu 系中加入password requisite pam_pwquality.so try_first_pass local_users_only retry3 minlen12 dcredit-1 ucredit-1 lcredit-1 ocredit-1这段配置要求密码最短 12 位并且必须同时包含数字、大写字母、小写字母和特殊字符。这里的dcredit、ucredit、lcredit、ocredit是负值意思是“至少需要多少个对应类型字符”负号表示强制要求正号则相反。2.2 SSH 服务加固的完整清单对公网服务器来说SSH 配置加固是安全投入产出比最高的一项工作。下面是/etc/ssh/sshd_config里我实际在用的关键配置项每一条都能讲出原因# 禁用 root 直接登录日常运维用普通用户 sudo 提权 PermitRootLogin no # 只允许密钥认证关闭密码认证 PasswordAuthentication no PubkeyAuthentication yes # 修改默认端口能过滤掉大部分扫描噪音 Port 22222 # 严格限制允许登录的用户 AllowUsers admin ops # 控制连接尝试次数和登录超时 MaxAuthTries 3 LoginGraceTime 30禁用 root 登录切换到普通用户加 sudo这是我最推荐的做法。这样即便某个用户密码泄露攻击者拿到的也不是最高权限后续 sudo 的密码验证还能再拦一道。修改 SSH 端口的效果我实测下来很明显——扫描日志里针对 22 端的随机爆破瞬间少了九成属于“低成本、降噪音”的神器。生成密钥对时我习惯用ed25519算法代替rsassh-keygen -t ed25519 -a 100 -f ~/.ssh/id_ed25519这个密钥更短、更快安全性也足够。把公钥放到服务器的~/.ssh/authorized_keys注意这个文件的权限必须严格控制chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys如果权限设置过宽sshd 会直接拒绝使用这个密钥文件这是很多人配置密钥登录失败的原因。改完sshd_config之后务必先用一条测试命令确认配置正确再重载服务sshd -t systemctl reload sshd2.3 用 Fail2ban 做自动化防线即使关闭了密码登录只要服务器有对外开放的服务依然会收到无脑爆破请求。Fail2ban 的作用是监控日志中的失败尝试达到阈值后直接封锁来源 IP。我用它来防护 SSH 和 Web 服务效果非常稳定。以 Ubuntu 下阻止 SSH 爆破为例在/etc/fail2ban/jail.local里配置[sshd] enabled true port ssh filter sshd logpath /var/log/auth.log maxretry 5 bantime 3600maxretry 5表示半小时内 5 次失败即触发bantime 3600表示封禁一小时。如果你改了 SSH 端口port那里要填实际的端口号logpath也要根据系统日志路径调整RHEL 系是/var/log/secure。一个值得注意的坑Fail2ban 的封禁默认走 iptables如果服务器本身用的防火墙规则管理工具是 nftables两者可能冲突导致封禁规则不生效。建议在部署前确认防火墙体系统一用同一套规则管理方案别让 Fail2ban 和自己的防火墙打架。3. 最小权限原则账号、文件和 sudo 的控制之道3.1 文件权限与特殊位的基础检查Linux 系统安全里有一条铁律给每个主体最小够用的权限。这个原则落到文件系统层就是权限位和特殊位的合理配置。我接手一台新服务器通常会先用两条命令探查权限异常。第一条是找出所有 SUID 程序find / -perm -4000 -type f 2/dev/nullSUID 位意味着普通用户执行这个文件时能以文件属主的身份运行。如果某个不知名程序带上了 SUID一旦存在漏洞就可能被用来提权。系统自带的sudo、passwd这类程序带 SUID 是正常的但凡是出现在奇奇怪怪路径下的就要立刻查清来源。第二条是检查全局可写的目录和文件find / -perm -0002 -type d 2/dev/null find / -perm -0002 -type f 2/dev/null全局可写目录配合sticky bit才是安全的组合。/tmp目录默认带 Sticky Bit目录权限显示为drwxrwxrwt意味着每个用户只能删除自己的文件。但其他目录如果也全局可写且没有 sticky bit就相当于允许任何人删别人的文件必须引起重视。3.2 sudo颗粒化授权比给 root 密码更靠谱团队协作时我不建议共享 root 密码。更可控的方式是给运维人员分配普通账号把需要的管理命令放进 sudo 白名单。用visudo打开/etc/sudoers配置一段规则ops ALL(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx这条规则赋予ops用户重启和重载 nginx 的权限其他管理命令一概没有。对需要完整管理权限的同事也不要直接给NOPASSWD选项。我见过一个生产事故某员工配置了 sudo NOPASSWD结果脚本里一个命令写错直接把错误的运行参数传给了服务进程因为免密没有任何二次确认的环节误操作在几秒内就完成了。这类风险防不胜防所以我的习惯是要求 sudo 必须带密码验证哪怕麻烦点也值得。visudo本身也是保命工具——它在保存时会校验语法写错了不会让你存进去避免搞坏 sudoers 导致所有提权失效的尴尬处境。3.3 用系统能力和服务隔离收窄权限边界现代 Linux 还提供了一个比普通文件权限更细的权限控制层Capabilities。它能把 root 的超级权限拆分成几十个小能力按需赋予进程。举个实际例子nginx 的master进程如果需要监听 80 端口完全不需要整个 root 身份只需要CAP_NET_BIND_SERVICE这一项能力。可以通过配置systemd单元文件的AmbientCapabilities参数来赋予或者在容器场景的配置文件中设置。对于常驻服务我更推荐用 systemd 的沙箱参数做一层防护[Service] NoNewPrivilegestrue PrivateTmptrue ProtectSystemstrict ProtectHometrue ReadOnlyPaths/NoNewPrivilegestrue是关键——它禁止该服务进程及其子进程通过exec获得任何新的特权即使二进制文件设置了 SUID 位也没用。这能有效阻断一部分提权攻击链。加这些参数前要仔细测试比如ProtectSystemstrict下服务无法写/usr和/etc如果应用需要写这些目录服务会直接启动失败。4. 网络与服务把暴露面收敛到最小4.1 服务的精简与端口收敛攻击者想打进来必须先找到一个通向你服务的网络入口。所以服务越少、开放端口越少攻击面就越小。我从多年前就养成了一个习惯新服务器安装系统时选择最小化安装不装图形界面、不装用不到的软件包。系统跑起来后再查一遍当前监听的端口ss -tulnp看到的结果里只保留业务必需的服务。任何不清楚是什么、谁在用、为什么监听的端口一律查清楚然后停掉。有些应用安装时自动开启额外服务这是最常见的“隐形暴露面”来源。对于必须在公网提供服务的应用也要细化访问控制。比如 MySQL 这类数据库通常只需要内网访问直接在监听地址上做限制让它只绑内网 IP 就足够bind-address 192.168.1.10把服务绑定到内网 IP 而不是0.0.0.0这一步很多人会忽略但它往往是防住数据库被拖走的最后一道锁。4.2 防火墙策略从默认放行到默认拒绝防火墙的原则可以浓缩成一句话默认拒绝显式放行。我见过不少配置防火墙开着但规则是开放 1-65535 端口这等同于没开。以 nftables 为例一套简洁的策略框架可以这么搭nft add table inet filter nft add chain inet filter input { type filter hook input priority 0 ; policy drop ; } nft add chain inet filter forward { type filter hook forward priority 0 ; policy drop ; } nft add rule inet filter input ct state established,related accept nft add rule inet filter input iif lo accept nft add rule inet filter input tcp dport 22222 accept nft add rule inet filter input tcp dport 80 accept nft add rule inet filter input tcp dport 443 accept这段规则的含义是默认丢弃所有入站和转发流量只放行进站口的回程连接、本机回环、SSH22222 端口、HTTP80和 HTTPS443。established,related这条很重要否则服务器主动访问外网时回包会被拦截业务直接受影响。Debian/Ubuntu 用户用ufw会更简单直观ufw default deny incoming ufw default allow outgoing ufw allow 22222/tcp ufw allow 80/tcp ufw allow 443/tcp ufw enable在修改生产环境防火墙规则前我会给自己留一条后路设置一个临时 cron 任务5 分钟后关掉防火墙或者打印当前规则保存好。万一写错规则把自己锁在外面还有一个补救窗口。这个习惯救过我两次强烈推荐。4.3 内核级防护SELinux 与 AppArmorSELinux 和 AppArmor 是 Linux 的强制访问控制机制它们是文件权限之上的另一层防护即使进程以 root 运行也只能访问预定义的系统资源和文件。很多运维朋友对 SELinux 的第一反应是“关了它”因为开启后经常遇到权限莫名其妙的报错。但我要说SELinux 并不是洪水猛兽它的报错恰恰是在提示你某个进程的行为异常了或是上下文配置错了。对于标准服务用对了上下文或者设置合适的布尔值运行毫无问题。以 nginx 为例在 RHEL 系系统上如果 SELinux 处于 enforcing 模式可能会阻止 nginx 访问自定义的日志目录或非标准目录。这类问题多数可以通过设置布尔值或修改上下文解决setsebool -P httpd_can_network_connect 1 semanage fcontext -a -t httpd_sys_content_t /var/www/html(/.*)? restorecon -Rv /var/www/htmlUbuntu 等 Debian 系默认用 AppArmor配置侧重点略有差异但思路一致让每个服务跑在受限的 profile 里。从安全收益角度说强制访问控制拦截的是“即使被攻破也拿不到关键数据”的第二层防线。我倾向于在条件允许时开启不要嫌麻烦。刚开始切换时可以先放宽松模式SELinux 的 permissive观察日志确认无误后再切到 enforcing这样既安全又平滑。5. 日志、审计与文件完整性看得见的防护才可靠5.1 日志的集中收集与日常阅读没有日志的安全是无从谈起的。Linux 系统的认证和权限日志在 RHEL/CentOS 系存于/var/log/secureDebian/Ubuntu 系存于/var/log/auth.log。后者记录了所有 SSH 登录尝试包括成功和失败的 IP、用户、时间。每天花两分钟扫一眼认证日志是成本最低的安全巡检方式。比如用一条命令统计今天被尝试爆破的次数grep Failed password /var/log/secure | awk {print $(NF-3)} | sort | uniq -c | sort -nr | head多台服务器的情况下逐个登录查看不现实建议搭建集中日志服务。用 rsyslog 把各主机的认证日志推送到一台日志收集机上配合简单的grep脚本就能做到异常告警。日志集中之后还要注意两点一是收集机的日志目录权限必须收紧二是日志要定期归档别让日志文件无限膨胀。5.2 logrotate防止日志撑爆磁盘这个问题太常见了默认配置下系统日志会不断增长如果没人管某天一个晚上就能把磁盘写满。而磁盘满在 Linux 上带来的后果比想象中严重得多——服务可能挂掉而且你能看到的报错信息少得可怜。好在主流发行版默认带 logrotate。关键是要检查配置文件里的保留周期和压缩选项。以 RHEL 系/etc/logrotate.conf为例weekly rotate 4 create dateext compress include /etc/logrotate.d含义是每周轮转一次、保留四周、轮转后压缩。如果你有日志增长速度特别快的服务比如 nginx 访问日志在/etc/logrotate.d/nginx里单独设置/var/log/nginx/*.log { daily rotate 14 compress missingok notifempty sharedscripts postrotate /bin/kill -USR1 cat /var/run/nginx.pid 2/dev/null 2/dev/null || true endscript }daily和rotate 14表示按天轮转、保留两周。轮转后向 nginx 发信号让重新打开日志文件否则 nginx 还会往已删掉的文件里写内容。5.3 auditd关键操作不留死角如果想对文件访问、系统调用做更细致的审计可以用 auditd。它能在谁、什么时间、访问了哪个文件这些层面留下记录。在安全事件追溯时这是决定性的证据。常用的审计规则配置示例auditctl -w /etc/passwd -p wa -k user-file auditctl -w /etc/sudoers -p wa -k sudoers-change auditctl -a always,exit -F archb64 -S execve -k command-log前两条监控/etc/passwd和/etc/sudoers的写入和属性变更第三条记录所有命令执行。执行后日志在/var/log/audit/audit.log可以通过ausearch -k user-file按规则标识查询。注意写审计规则要控制范围别把execve全量记录开在繁忙的生产机器上日志增长速度会让你怀疑人生。最好只针对敏感可执行目录和安全关键操作做审计。5.4 文件完整性校验AIDE攻击者在拿下系统后通常会篡改系统二进制文件植入后门。靠人工很难发现这类异常这时需要一个文件完整性校验工具最常用的是 AIDE。安装后先初始化数据库aide --init mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz之后每次做基线检查对比当前状态和数据库是否有变化aide --check有变更会输出差异报告正常合理更新产生的差异我们确认后重新初始化数据库即可。部署 AIDE 要注意一点数据库本身要存储在安全位置最好只读挂载或者定时备份到异机。否则攻击者改了文件之后也改数据库完整性校验就形同虚设。我建议把 AIDE 检查放到 cron 里每周跑一次输出结果定时发到日志中心。虽然有些繁琐但一旦服务器被篡改这是第一个能提醒你的设备。6. 应急响应发现问题后的黄金半小时6.1 先判断系统到底有没有被入侵事前防护做得再好也不能保证 100% 不出事。应急响应是安全体系里兜底的部分它的启动时机是“发现可疑迹象”。最常见的迹象包括负载突然飙升top里出现名字古怪的进程CPU 占用极高外联连接异常增多尤其高频连接境外或可疑 IP系统出现未授权的新用户或 root 用户被克隆登录日志显示大量失败尝试之后出现成功的记录定时任务cron出现看不懂的条目关键文件被修改比如/.ssh/authorized_keys中出现陌生公钥发现可疑迹象第一反应不要慌着重启或者杀进程。先保现场命令一条条查。6.2 常用的排查命令与检查清单我建议按下面这个顺序开展排查每一条命令都有明确的意图先看用户和登录记录# 列出所有用户及最近登录 awk -F: $30{print $1} /etc/passwd last | head -20rootuid 0账户如果出现多个说明被做了手脚。last看谁的登录记录异常比如凌晨三点来自陌生 IP。看进程和网络# 按 CPU 排序找陌生进程 top -b -n 1 | head -30 # 查看所有外连连接 ss -tunap | grep ESTABLISHED重点排查ESTABLISHED状态且目标端口非业务端口的外连比如主动连接 443、常见的挖矿矿池端口等。查定时任务和自启动项crontab -l cat /etc/crontab ls -la /etc/cron.d/ systemctl list-unit-files --typeservice --stateenabled木马常驻的方式通常是定时任务或 systemd 服务。把所有可疑条目列出来一行一行核对是否是自己部署过的任务。检查 LD_PRELOAD 和后门文件echo $LD_PRELOAD find / -name *.so -newer /boot 2/dev/null偷懒又有效的做法是用chkrootkit和rkhunter自动扫描一遍已知的后门特征。虽然这类工具不能发现所有新型后门但对常见样本检出率很高应急开局用它快速筛查是合理的。在处理方式上有几个原则要遵守。如果确认被入侵先从网络层面把机器隔离——拔掉公网网卡或直接更新防火墙规则丢弃所有入站流量。这个动作比在机器上杀毒更优先可以阻止攻击者继续外传数据或横向渗透。然后保存好当前系统状态包括内存镜像、进程列表、网络连接等证据再考虑重装或恢复。6.3 一个实用的紧急封禁命令应急时最常用的动作是封掉攻击来源 IP。用 firewalld 的话firewall-cmd --permanent --add-rich-rulerule familyipv4 source address1.2.3.4 reject firewall-cmd --reloadnftables 的话nft add rule inet filter input ip saddr 1.2.3.4 drop这类规则需要持久化保存否则重启后失效。nftables 执行nft list ruleset /etc/nftables.conf保存规则集即可。7. 常见问题速查表与避坑心得做安全加固时踩过的坑我整理成了一张速查表基本覆盖了常见生产事故的起点问题现象可能原因解决方案修改 SSH 配置后无法登录sshd_config 语法错误或密钥权限不对本地执行sshd -t验证确认 authorized_keys 为 600 权限开启 SELinux 后服务报权限错误文件上下文或布尔值设置不当先用ausearch查拒绝记录再setsebool或semanage调整Fail2ban 封禁不生效与系统防火墙体系冲突或日志路径错误确认使用同套防火墙ls 检查 logpath 是否正确服务日志增长过快撑爆磁盘未配置 logrotate 或轮转周期过长为服务单独配置 logrotate缩短轮转周期并开启压缩改完 sudoers 后 sudo 全部失效sudoers 语法错误用 root 的另一个登录会话执行pkexec visudo修复登录日志显示大量爆破但未成功密码策略已生效但攻击仍在尝试启用 Fail2ban 封禁来源 IP或考虑改用密钥认证服务器被植入挖矿木马进程杀掉后反复出现存在守护进程或定时任务在拉取按 6.2 清单排查 cron、systemd、LD_PRELOAD 后彻底清理治本的建议仍然是加固前做好备份加固后做完整功能回归测试。安全配置改动引发可用性问题这在生产环境并不少见。我自己比较喜欢的一套节奏是先在测试环境验证配置再在生产环境分批灰度每个改动都能回滚。另外听说有些公司会在安全加固后直接跑一轮压测和故障演练专门验证“加固是否影响业务、应急脚本是否可用”。这种思路我非常认同——安全配置不该是写在那里的摆设它必须被验证过才算真正生效。8. 安全加固的最后一公里持续维护才是关键有人说 Linux 安全是“一锤子买卖”配好了就能一劳永逸。这个想法非常危险。安全加固是持续过程资产的更新、业务的变化、新漏洞的公开都会打破之前好不容易建立的平衡。我的日常做法是三类动作并行每周检查系统更新并评估是否需要打补丁每月做一次日志和文件完整性检查每季度对全部开放端口、账号权限、sudo 规则做一遍整体审计。同时关注主流发行版的漏洞公告邮件让安全信息保持新鲜。在最后分享一个我从实战中坚持下来的小习惯每天早晨到工位后花一分钟快速翻一下认证日志和关键服务日志用固定的脚本输出前一天的异常摘要。看得久了你会对这台服务器的“正常”画像形成直觉而直觉在安全运维里往往是最开始发现异常的信号。Linux 系统安全没有终点更多的是“防御、发现、响应、恢复”循环里不断变强。希望这篇从实战里长出来的文章能帮你把这个循环跑起来让每一台机器都少一点裸奔的风险。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑