
我接手过不少被入侵的Linux服务器事后复盘原因十有八九不是被什么高深的0day击穿而是栽在基础安全上——root密码是123456、SSH裸奔在公网、一个Tomcat跑在root权限下、防火墙规则形同虚设。这篇文章我会从权限模型、账户认证、文件系统、网络收敛、日志审计、加固落地六个方向把Linux系统基础安全这摊事从头到尾捋一遍。适合刚入行的运维、自己折腾云服务器的开发者也适合公司内部要做安全自查的同行。看完之后你至少能把一台新装的Linux服务器按标准流程加固到能拿出来见人的程度。1. 先搞清楚Linux安全到底在防什么1.1 一切皆文件权限就是命根子Linux的设计哲学是一切皆文件从普通文本、设备节点到网络套接字都被抽象成文件访问控制的统一入口就是文件权限。这意味着只要你理解了文件权限模型就掌握了Linux安全的一半这是个被说烂但确实管用的切入点。一个文件上有三组权限文件属主user、属主所在组group、其他人other每组分别是读r4、写w2、执行x1。数字表示法里755代表属主可读可写可执行、组和其他人只能读和执行。这个基础概念很多新手都懂但在实际分配权限时往往相当随意。我见过最常见的错误就是图省事给目录授权0777或者干脆把整个应用目录chmod -R 777。结果任何本地用户都能读取或篡改你的配置文件、日志文件一旦某个Web应用被上传了webshell攻击者就能以运行用户的身份横向读取系统里的敏感文件。正确的做法是遵循最小权限原则每个服务一个独立账户目录只给该账户所需的读写权限日志文件只允许写入配置文件只允许读取。这个原则贯穿整个加固过程后面每一步都在落实它。1.2 攻击者视角下的加固思路要加固系统先得站在攻击者角度想问题。一次典型的入侵路径通常是这样的先扫描目标开放的端口发现SSH、MySQL、Redis之类的外露服务然后尝试弱口令、未授权访问或已知漏洞一旦拿到一个低权限shell就开始查看sudo权限、SUID文件、内核版本寻找提权路径最后落地上马留后门、加计划任务、篡改日志保证持久化。对应到防御侧思路就很清晰了减小暴露面把不必要的端口和服务全部关掉强化认证弱口令和默认配置全部处理收紧权限让普通用户即使进来了也无法横向移动保留审计日志和文件完整性检查做到位。四个方向都不需要特别高深的技术但做好了能把90%以上的常见攻击挡在外面。这篇文章的骨架就是这四个方向后面每一章都是在落实其中一个环节。2. 账户与登录安全把大门先焊死2.1 账户清理与密码策略拿到一台新服务器第一件事不是装业务而是把系统里已有的账户理一遍。用下面命令看哪些用户具备root权限awk -F: $30{print $1} /etc/passwd正常情况下输出应该只有root自己。如果出现别的用户名就要警惕是不是被创建的后门账户立即锁定或删除。系统中很多默认账户如lp、sync、games等不需要登录能力可以在确认无依赖后锁定usermod -L lp密码策略是另一个重灾区。默认情况下很多发行版的密码可以设置得很随意改起来要同时看/etc/login.defs和PAM配置两个地方。前者控制密码有效期PASS_MAX_DAYS 90 PASS_MIN_DAYS 7 PASS_WARN_AGE 14这样设置之后用户密码最多90天必须更换最短使用7天到期前14天开始提醒。密码复杂度则由pam_pwquality.so这个模块控制。在/etc/pam.d/system-auth或/etc/pam.d/passwd中加入类似配置password required pam_pwquality.so retry3 minlen12 difok3 ucredit-1 lcredit-1 dcredit-1含义是允许重试3次、密码最小长度12位、新旧密码至少3处不同、必须包含大写字母、小写字母和数字。第一次配置时要注意密码策略太严格会引来业务部门的抱怨建议先定一个中等强度比如minlen10加两个复杂度要求运行一段时间后再逐步收紧。2.2 SSH远程登录的加固细节在所有远程管理方式里SSH是被攻击最多的入口。默认的22端口、root直接登录、密码认证这三个配置凑齐了基本就是给扫描器送人头。我的建议是不管服务器在不在公网都按下面的标准来加固。先切换到密钥认证生成密钥对ssh-keygen -t ed25519 -C your_commented25519比RSA密钥更短且安全性更高现在主流的OpenSSH版本都支持。然后把公钥追加到服务器的~/.ssh/authorized_keys接着修改/etc/ssh/sshd_configPermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes Port 2222 AllowUsers ops zhangsan修改之前先备份修改之后务必用sshd -t检查语法然后重启sshd。这里有个新手容易忽略的坑不要直接关掉当前SSH窗口先用另一个终端测试新端口和密钥登录是否成功确认没问题了再断开旧会话。否则配置文件一写错服务器锁在门外人就只能跑去机房或通过云厂商的VNC控制台救。PermitRootLogin no 是把root的直接登录关掉。日常运维用普通用户登录需要管理员权限时再执行sudo这样所有提权操作都会被记录到日志里出了问题知道是谁在什么时间做了什么。AllowUsers 配合白名单可以限定只有指定用户能通过SSH登录减少被爆破的账户面。如果公司有固定出口IP再用防火墙把来源IP白名单限定一下安全性还能更高。防爆破工具我最常用的是fail2ban它通过监控认证日志在短时间内多次登录失败的IP会被临时封禁。安装后默认配置一般够用改一下jail.local[sshd] enabled true maxretry 3 bantime 3600 findtime 300意思是5分钟内失败3次就封1小时。封禁时间不要设太短否则攻击者可以等时间过了继续爆也不要太长避免你把自家同事误封一整天。2.3 PAM认证的可插拔防线PAMPluggable Authentication Modules是Linux的认证框架它的好处是认证方式可以模块化配置密码、指纹、LDAP、双因子都能插进去。配置文件在/etc/pam.d/目录下每个服务一个文件。对于基础安全来说我比较关注两个用途一是控制谁能登录二是给关键服务加二次认证。前面说的密码复杂度配置其实就是通过PAM模块实现的。如果想限制只有特定用户能登录系统可以配置/etc/security/access.conf内容类似 : root : ALL : ops : 192.168.1.0/24 - : ALL : ALL然后在/etc/pam.d/login和/etc/pam.d/sshd中加入一行account required pam_access.so这样除了root和ops组来自内网的用户其他所有登录尝试都会被拒绝。PAM配置出错的后果比SSH配置出错更严重它可能直接导致所有人包括root都无法登录。所以每次改动前务必备份原文件改完之后新开一个终端测试登录不要动当前会话。3. 文件系统与权限控制3.1 特殊权限位SUID/SGID/Sticky Bit文件权限除了基础的rwx还有三个特殊位SUID、SGID、Sticky Bit。其中SUID是最需要警惕的。当一个二进制文件设置了SUID位普通用户执行它时会以文件属主的身份运行。系统里有/usr/bin/passwd这类程序必须依赖SUID才能让普通用户修改自己的密码。但攻击者拿到低权限shell后也会搜索系统里所有SUID文件如果发现某个有漏洞的SUID程序就能借它提权到root。检查系统里有哪些SUID文件一条命令find / -perm -4000 -type f 2/dev/null同样的方法还可以查SGID-perm -2000和Sticky Bit-perm -1000。定期跑一遍把结果保存下来作为基线以后比对多出来的文件就是重大嫌疑。确认无用的SUID权限可以去掉chmod u-s /path/to/file chmod g-s /path/to/dirSticky Bit主要用于共享目录最典型的就是/tmp。设置了粘滞位的目录里任何用户都能创建文件但只能删除自己创建的文件防止用户之间互相删文件。如果/tmp没有设置Sticky Bit任何本地用户都能进这个目录删别人的临时文件等于给了破坏者武器。3.2 chattr让关键文件动不了Linux还有一个容易被忽略的安全属性机制chattr。给文件加上i属性后文件变成不可变即使是root用户也不能修改、删除、重命名。想改内容必须先用chattr -i解除。这个特性对防篡改特别有用。系统里几个核心文件可以加上这个保护chattr i /etc/passwd chattr i /etc/shadow chattr i /etc/group chattr i /etc/gshadow加上之后攻击者就算拿到了root权限想往passwd里加一个后门账户也会失败。不过要注意这个保护是双向的日常如果要做用户管理工作比如useradd、passwd会报Permission denied得先解除属性再操作弄完再加回去。生产环境建议封装成脚本避免操作混乱。更高阶的做法是利用系统的扩展属性配合审计。比如对Web目录做防篡改监控先把文件全部加i然后通过eBPF或内核模块对关键路径做读写拦截审计。我看到有些安全产品就是基于file_operations层拦截read/write来实现文件防篡改和操作审计的这种做法颗粒度很细但需要较强的内核开发能力普通运维场景用chattr加AIDE定期比对就足够。3.3 SELinux与AppArmor要不要开强制访问控制MAC是Linux权限体系里最容易被跳过的部分。很多人装完系统第一件事就是setenforce 0理由是SELinux总是挡业务、报权限错误干脆关掉省心。从安全角度讲我不建议这么做。SELinux通过安全策略给进程、文件打标签精确控制哪个进程能访问哪个文件。它和传统的DAC自主访问控制是叠加关系即使DAC权限配置没错SELinux也能挡住越权访问。比如Web服务被攻破后如果SELinux策略限制Apache只能访问特定的Web目录攻击者想读取/etc/shadow就会被拒绝。如果确实需要调整正确做法是先用ausearch和audit2why查看被拒绝的审计记录确认是策略问题还是业务真的需要访问再针对性地生成或调整策略。比如grep AVC /var/log/audit/audit.log | audit2allow -M mypol semodule -i mypol.pp这是在确认安全的前提下放行特定行为而不是一棍子打死关闭整个机制。Debian/Ubuntu系列通常用AppArmor核心理念类似配置方式更简洁用aa-status查看状态aa-enforce、aa-complain切换模式。建议先把有业务影响的进程放到complain模式跑一轮确认无异常后再转enforce。4. 网络层收敛暴露面4.1 端口与服务排查网络层的攻击是所有入侵的第一步你不开端口攻击者连你的门都摸不到。装完系统后先做一次端口盘点ss -tlnp这条命令列出所有处于监听状态的TCP端口和对应进程。看到0.0.0.0:22、0.0.0.0:3306这类绑定在所有网卡上的监听要特别注意。MySQL这类数据库服务如果只给本机程序用应该只监听127.0.0.1而不是0.0.0.0否则等于把数据库暴露在网络上。排查当前启用了哪些服务systemctl list-unit-files --typeservice --stateenabled看到明显多余的服务比如装了图形环境带来的蓝牙、打印服务或者实验时装的FTP、Telnet直接禁用systemctl disable --now avahi-daemon systemctl disable --now cupsTelnet、rlogin、rsh这些明文协议服务只要存在就是隐患账号密码在网络上裸奔抓到包就等于拿到账户。任何版本的系统都不应该启用它们。除了系统服务还要检查计划任务里有没有可疑的下载脚本crontab -l ls /etc/cron.d/ /etc/cron.daily/有些挖矿木马就是通过定时任务在系统里反复下载并运行恶意程序的。4.2 firewalld与iptables的落地配置CentOS/RHEL系默认用firewalld底层还是iptables。安全加固时我喜欢把默认区域设为drop再按需放行firewall-cmd --permanent --default-zonedrop firewall-cmd --permanent --add-servicessh firewall-cmd --permanent --add-servicehttp firewall-cmd --reload默认区域设为drop意味着所有进站流量默认丢弃然后再显式放行SSH、HTTP这些必要服务。注意顺序先确保SSH放行成功再切换默认区域否则当前会话直接断连。如果是Ubuntu/Debian环境用ufw来操作更简单ufw default deny incoming ufw allow ssh ufw allow 80/tcp ufw allow 443/tcp ufw enable对高级一点的需求直接写iptables规则。一个典型的入站策略骨架是iptables -P INPUT DROP iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT iptables -A INPUT -i lo -j ACCEPT顺序很重要iptables规则从上到下匹配匹配后不再继续。所以允许已建立连接的规则必须放在默认丢弃之前否则正常访问的返回包都被丢了。我见过不少人写反了顺序然后来问我为什么SSH能连上但网页打不开其实就是这个原因。5. 日志审计与入侵排查5.1 日志体系中哪些值得盯很多服务器被入侵后管理员都拿不出任何线索原因就是日志没看。Linux的日志体系其实很清晰/var/log/messages系统整体运行日志/var/log/secure认证和安全相关日志SSH登录、sudo操作都在这里/var/log/wtmp所有成功登录的记录/var/log/btmp所有失败的登录尝试/var/log/dmesg内核日志其中/var/log/secure是最值得每天扫一眼的。我用过一条命令快速统计最近认证失败的IPgrep Failed password /var/log/secure | awk {print $(NF-3)} | sort | uniq -c | sort -nr | head -20如果看到某个IP尝试了几千次基本可以判定是在暴力破解直接加到防火墙黑名单。对于systemd管理的系统很多服务的日志用journalctl查journalctl -u sshd --since 1 hour ago日志量大的服务器要配置logrotate做轮转避免日志文件把磁盘撑爆。默认配置一般能用但建议把保留周期设为90天满足一般审计需求的同时不至于占太多空间。5.2 一条龙排查思路怀疑系统被入侵时按下面的顺序排查效率最高。第一步查登录痕迹last -20 lastb -20last看谁成功登录过lastb看哪些IP在尝试登录。如果发现不认识的主机名或IP进一步查/var/log/secure里这个IP的操作记录。第二步查当前进程ps aux --sort-%cpu | head -20CPU占用异常高的进程要仔细看启动路径和命令行。很多挖矿程序会伪装成类似[kworker]、[irqbalance]的进程名用ps -ef看完整参数再用ls -l /proc/PID/exe反查实际二进制路径。第三步查网络连接ss -antp如果服务器上有进程在向外网地址建立大量连接或者监听了一个不认识的端口赶紧定位进程并断网隔离。第四步查持久化ls -l /etc/rc.d/rc.local find /etc/systemd/system -type f -name *.service -newer /etc/passwd crontab -l ls -la /tmp /dev/shm攻击者要么把启动脚本塞进systemd服务要么写进crontab或rc.local要么利用/tmp、/dev/shm这种可写目录藏文件。这几处都看一眼基本能发现90%的后门痕迹。第五步验证系统文件完整性。CentOS/RHEL系自带的rpm可以快速校验核心文件有没有被动过rpm -Va输出里的S.5....T等标记分别代表文件大小、MD5校验、修改时间被改动过。重点看/bin、/sbin、/etc下的改动如果是自己没做过的操作基本可以确认被入侵了。5.3 文件完整性监控等被入侵了再排查属于事后补救。更主动的做法是提前建立文件完整性基线。最常用的工具是AIDEAdvanced Intrusion Detection Environment。先初始化数据库aide --init mv /var/lib/aide/aide.db.new.gz /var/lib/aide/aide.db.gz以后定期执行aide --check它会根据基线数据库比对文件是否被修改、新增、删除。推荐用cron每天跑一次0 0 * * * /usr/sbin/aide --check /var/log/aide.log 21AIDE适合监控配置文件、可执行文件这些不应该频繁变动的对象。配合前面的chattr i一个负责检测、一个负责防篡改双管齐下效果更好。对于Web目录这类频繁变动的文件则更适合用inotify做实时监控或者接入日志分析平台做关联分析。6. 加固落地清单与踩坑记录6.1 基础加固命令速查把前面几章的内容整理成一份可以直接执行的加固步骤适合拿到新服务器后按顺序操作。注意先做备份每执行一步都确认业务没有受影响再继续。# 1. 账户与密码 awk -F: $30{print $1} /etc/passwd passwd -l 不需要登录的账户 sed -i s/^PASS_MAX_DAYS.*/PASS_MAX_DAYS 90/ /etc/login.defs # 2. SSH加固先备份 cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak # 修改 PermitRootLogin no、PasswordAuthentication no 等 sshd -t systemctl reload sshd # 3. 文件权限 find / -perm -4000 -type f 2/dev/null /root/suid_baseline.log chown -R 应用用户:应用组 /app/data chmod -R 750 /app/data # 4. 防火墙 firewall-cmd --permanent --default-zonedrop firewall-cmd --permanent --add-servicessh firewall-cmd --reload # 5. 日志与审计 journalctl --vacuum-time90d systemctl start rsyslog systemctl enable rsyslog这份清单只是一个起点不用所有项都照搬。公司内部有合规要求比如等保的还要对应到具体的控制项比如身份鉴别、访问控制、安全审计、入侵防范、恶意代码防范这些大类逐项形成自查表。基础安全的核心是持续维护不是加完一次就高枕无忧。6.2 我踩过的几个坑坑一改SSH配置把自己锁在门外。我早期有一台外地机房的服务器改了sshd_config里的一处参数顺手reload然后当前会话断了新的密码认证又恰好被关掉最后只能联系IDC重装系统。从那以后我养成了两个习惯一是所有SSH改动前先cp备份二是改动后用sshd -t验证三是测试登录成功前绝不关当前窗口。坑二chattr i之后改密码报错。给/etc/passwd/etc/shadow加了不可变属性后执行useradd提示文件无法修改。当时排查了半天才想起来是自己加的属性。这个教训说明加固操作一定是业务的一部分要做成流程而不是临时起意。坑三防火墙默认drop导致服务全断。设置默认区域为drop时没有先把必要端口放行结果reload之后远程管理直接失效。正确的顺序永远是先放行后收口先把SSH放行了再考虑把默认策略收紧。坑四SELinux和业务互相打架。因为没搞懂SELinux的拒绝逻辑直接全局关闭。后来业务迁移到新环境安全审计要求必须开SELinux结果跑起来各种报错。其实SELinux调试并没有那么恐怖多看看audit日志用audit2why分析拒绝原因大多问题都能解决。坑五日志太多不看等于没日志。刚开始我把所有日志都保留磁盘满了才知道定期轮转而且当时从没主动看过/var/log/secure。直到有一次被入侵回溯日志才发现攻击者在爆破了一个月才拿到密码如果当时每天扫一眼失败登录记录早就该发现并封掉了。现在我会给关键服务器配置日志集中收集统一到日志平台做告警不用再一台台机器翻。最后说点个人体会。Linux基础安全这件事贵在坚持和制度化而不是装个安全软件就完事。我见过太多团队做完一轮加固就抛到脑后半年后代码上了新服务、防火墙放开了新端口之前的努力全部归零。我的习惯是把加固项写进服务器上线标准流程新机器一律先加固再上业务然后每季度用lynis这类工具做一次安全审计生成报告对照整改。安全这事没有终点但只要不断重复基础动作系统就会比大多数裸奔的服务器结实得多。希望这份从实战中沉淀下来的指南能帮你少走一些弯路拿到手的每一台Linux都能稳稳当当地跑上几年。