ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux安全加固实战:从账户到内核的完整加固手册

Linux安全加固实战:从账户到内核的完整加固手册 简介面向Linux系统运维与安全管理人员的加固实践手册内容同时适合初学者建立安全基线认知。手册从安装环节的root密码与网络接口配置讲起延伸到用户帐号安全中的密码策略、Password Shadowing、密码检查与管理再细化到网络服务安全中的服务过滤、Tcp_wrapper、/etc/inetd.conf、/etc/hosts.equiv 等关键项能够直接用于服务器上线前的自检与日常运维排错。资源为单份PDF文件压缩包大小仅40KB精炼便携可离线阅读或打印对照。目前已有1332人学习/下载在同类安全运维资料中具有不错的参考价值。手册共16页各章节以清单式条目呈现便于快速定位问题结合描述可见其覆盖NFS、tftp、Sendmail、finger、UUCP等常见服务加固适合作为系统加固操作的速查手册。1. LINUX安全加固手册到底在治什么先看懂加固的边界很多Linux服务器被攻破往往不是被多高级的0day打的而是被扫描器撞上弱口令、开着没用的端口、跑了没人维护的旧服务最终被脚本小子顺手拿走。LINUX安全加固手册这类资料在运维和开发圈流传很广新手喜欢照着一条条抄老手把它当基线清单来对。它真正解决的是一个问题让一台默认配置的Linux机器在暴露到公网后能撑得更久并在出事之后能快速定位是谁干的。加固不是装个杀软就完事它是一套从账户、SSH、文件权限、系统服务到内核网络参数的收敛动作。适合的对象很明确刚接手服务器不知道从哪里下手的初级运维被安全巡检逼着交整改报告的中级工程师以及想给团队定一份可复用基线的小团队负责人。这篇文章按我实际做加固的顺序来讲把每个步骤的命令、参数和翻车点都摊开照着手敲就能在测试机上跑通再上生产。2. 账户与口令加固先管好能进系统的人和登录口令2.1 清理系统里的僵尸账户并把新建用户的默认策略收紧加固的第一步不是改服务而是看这台机器上有多少能登录的账户。很多厂商预装系统里会留一些不常用的账号还有离职同事没删干净的系统用户这些都可能成为被爆破的入口。我一般会先跑这么几条命令# 查看所有能登录shell的账户排除正常的root和业务账户 awk -F: $7 ! /sbin/nologin $7 ! /bin/false {print $1, $6, $7} /etc/passwd # 查看最近修改过口令的账户核对是否有异常 ls -l /etc/shadow # 查看当前系统上所有用户的最近登录记录 last -20第一条命令把passwd文件里第七列不是nologin或false的用户列出来这些是真正能登录Shell的账户。如果里面冒出不认识的用户名比如test、ftpuser、oracle这种不明确的账号就要查一下它的创建时间和对应用途。第二条命令看shadow文件的修改时间如果一台新机器上shadow文件的修改时间异常早通常是镜像里就带了可疑账户。第三条命令用last翻登录记录重点看有没有在凌晨来自陌生IP的登录成功记录。对确认无用的账户用userdel -r彻底删除连home目录一起清掉。对还需要保留但暂时不准登录的账户可以用usermod -s /sbin/nologin把它的登录Shell改成不能登录这样即使口令被撞出来也没法直接拿Shell。这一步尽量不要用passwd -l锁账户因为锁账户只是锁了口令登录SSH Key登录依然可能进得来处理不彻底。2.2 口令复杂度与老化策略让弱口令和万能密码成为过去式清理完账户接着要堵住弱口令和口令长期不变的问题。默认的CentOS和Ubuntu对密码强度的要求都很低甚至允许用户把自己名字当密码。我在生产机上一般会同时改两处一处是/etc/login.defs里的全局老化策略另一处是PAM的密码质量模块。# 编辑 /etc/login.defs调整以下参数 # PASS_MAX_DAYS 90 强制90天更换 # PASS_MIN_DAYS 7 修改后至少7天才能再改防反复改回去 # PASS_MIN_LEN 12 最小长度12位 # PASS_WARN_AGE 14 到期前14天提醒 # 编辑 /etc/pam.d/system-authCentOS系加组件 password requisite pam_pwquality.so retry3 minlen12 dcredit-1 ucredit-1 lcredit-1 ocredit-1 # 对存量用户立即生效 chage --maxdays 90 --mindays 7 --warndays 14 root修改login.defs只会影响之后新建的用户存量用户必须用chage单独拉齐。我在实际项目里经常遇到只改了login.defs、老用户仍然万年不换密码的半吊子加固审计一查就露馅。PAM那行参数里minlen是总长度dcredit、ucredit、lcredit、ocredit分别是数字、大写、小写、特殊字符的必须数量负号表示至少要有几个。这样组合下来密码必须同时包含数字、大小写和特殊字符且总长度不低于12位。注意如果系统里跑着老旧的业务有些程序用密码做接口认证口令策略收紧后会导致功能报错比如FTP脚本自动上传、数据库定时任务。遇到这种情况我的做法是对这种服务单独设置专用的认证账户不走系统口令策略那条路而不是为了妥协把全局策略放宽。否则审计是过了安全性又回到原样等于白做。2.3 sudo权限收敛不随便给All权限少一个root就少一条路账户清理完另一个常被忽略的点是sudo权限。很多团队图省事给所有开发同事的账户都加了wheel组等于人手一个root入口。加固的顺序里我建议单独花十分钟过一遍sudo配置# 查看哪些用户或组拥有sudo权限 grep -E ^[a-Z].*\(ALL /etc/sudoers /etc/sudoers.d/* 2/dev/null # 正确示范给运维组仅保留执行特定命令的权限 visudo -f /etc/sudoers.d/ops ops ALL(ALL) /usr/bin/systemctl restart nginx, /usr/bin/systemctl reload nginx用visudo而不是直接vim是因为visudo会做语法校验改坏了能撤销不会把sudoers文件改崩导致整个机器的提权通道报废。给权限的原则是最小化能指定命令就不要给ALL能指定服务名就不要给全部服务。如果业务方确实需要临时root建议配一个带时效的sudo规则或者让他们按流程申请一次性权限而不是长期挂着。3. SSH远程登录加固把运维的大门从密码锁换成指纹锁3.1 sshd_config里的6个必调参数SSH是Linux服务器的管理通道也是爆破最猛烈的入口。默认配置下SSH开着密码登录和root直接登录扫描器撞上正确用户名后就是无限次试密码。我每次装完系统第一件事就是改/etc/ssh/sshd_config改完重启sshd前会用sshd -t先验一遍语法。下面是生产环境常用的配置段# /etc/ssh/sshd_config 关键配置 Port 22333 # 改掉默认22端口降低被批量扫描命中的概率 PermitRootLogin no # 禁止root直接用SSH登录 MaxAuthTries 3 # 每个连接最多尝试3次认证 PubkeyAuthentication yes # 开启公钥认证 PasswordAuthentication no # 关闭密码认证只保留密钥方式 ClientAliveInterval 300 # 每300秒发一次心跳 ClientAliveCountMax 2 # 连续2次心跳无响应就断开 AllowUsers opsadmin deploy # 白名单只允许指定用户登录Port改22333的意图是避开自动化扫描工具默认盯防的22端口但它对定向攻击没用所以同时还要配DenyUsers或者AllowUsers做登录账户白名单。PermitRootLogin设为no之后root只能先登录普通用户再su切换审计日志会留下痕迹这是很多等保巡检要被查的项目。PasswordAuthentication关闭前必须确保至少有一个已导入公钥的普通用户能登录否则关了密码认证又没配好密钥机器就会变成谁也进不去的状态那就只能上管理卡或者去机房了。改完配置一定先跑sshd -t再systemctl restart sshd同时不要关掉当前连接。很多运维手滑配置写错直接重启旧会话也断了新会话又连不上最后只能靠带外管理救场。这类教训在运维圈真的不少。3.2 密钥登录的正确部署方式权限错了照样被拒绝关闭密码认证只是手段前提是公钥登录已经能正常用。很多第一次做加固的人会在这一步卡住把公钥放进authorized_keys后发现登录依然要密码或者提示server refused our key。90%的原因出在权限上。SSH守护进程对密钥相关文件的权限要求非常严格权限过松会直接拒绝加载公钥。# 在本地生成密钥对如果已有密钥可跳过 ssh-keygen -t ed25519 -a 100 -f ~/.ssh/prod_key # 把公钥推到服务器上手动创建目录避免权限被umask污染 ssh -p 22333 opsadminserver mkdir -p ~/.ssh chmod 700 ~/.ssh # 推送公钥并设置正确权限 scp -P 22333 ~/.ssh/prod_key.pub opsadminserver:~/.ssh/authorized_keys ssh -p 22333 opsadminserver chmod 600 ~/.ssh/authorized_keys chmod 700 ~/.ssh # 本地测试密钥登录 ssh -i ~/.ssh/prod_key -p 22333 opsadminserver密钥类型我一般选ed25519它比RSA短且安全度高加-a 100的意思是做100轮KDF即使私钥泄露被暴力破解的成本也更高。部署完成后先不要急着删密码认证保持当前的SSH连接在新终端里用密钥登录一次确认成功后再去关闭PasswordAuthentication。authorized_keys的权限必须是600.ssh目录必须是700owner必须是登录用户自己这个顺序错了任何一步登录都会被拒。另外如果服务器上启用了SELinux密钥文件还需要检查上下文类型。CentOS系可以用restorecon -R -v ~/.ssh修复否则即使权限全对SELinux也会在后台静默拦截密钥读写。这个问题我遇到过不止三次每次都是看审计日志才发现的。3.3 必开的登录警报让爆破者无所遁形密钥登录配置好后还需要让系统在有人登录时留下声音。光靠系统自带的last日志不够我习惯配一个简单的登录通知脚本在ssh登录触发pam_exec时执行把登录IP和账号实时发到运维群。这样一旦有人爆破成功能第一时间发现并处理而不是等到业务受损才发现。# /etc/pam.d/sshd 增加一行在session阶段触发 session optional pam_exec.so /usr/local/bin/login-notify.sh # /usr/local/bin/login-notify.sh 内容 #!/bin/bash IP$(echo $PAM_RHOST | sed s/::ffff://) USER$PAM_USER TIME$(date %Y-%m-%d %H:%M:%S) if [ -n $IP ]; then echo SSH登录通知$USER 从 $IP 在 $TIME 登入 /var/log/login_notify.log fi这个脚本不阻断登录只能旁路记录并输出日志但配置前提是PAM的sshd文件里已经启用了pam_exec模块且sshd本身开启了UsePAM yes默认就是yes如果之前有人为了省事关过它记得开回来。脚本里过滤了IPv6映射IPv4的::ffff:前缀避免看到一堆看不懂的地址。日志可以再接rsyslog远程汇聚这个在后面验证章节细讲。4. 文件权限、系统服务与内核参数把隐形后门逐个上锁4.1 高危SUID文件排查与关键目录脱敏系统里的SUID文件就像一个不讲道理的万能钥匙任何用户执行它就能以文件属主的身份运行。正常情况下系统需要少数几个SUID程序比如sudo、passwd、mount但攻击者偶尔会在系统上留下被植入的SUID后门。我每次加固都会做一个全盘排查# 找出所有带SUID位的文件重点关注非系统路径 find / -perm -4000 -type f 2/dev/null | grep -vE ^(/usr/bin|/bin|/sbin|/usr/sbin) # 找出带SGID位的文件 find / -perm -2000 -type f 2/dev/null # 检查最近7天内被修改过的系统二进制 find /usr/bin /usr/sbin /bin /sbin -mtime -7 -type f -exec ls -l {} \;把find的结果和系统原始SUID列表做对比新增的、路径奇特的、文件名带空格或特殊符号的都要重点核查。如果确认是异常文件先看有没有进程在用的痕迹再用chmod -s去掉特殊位并归档。不要一上来就删除万一它跟某个老业务的加密狗驱动挂钩删了会造成连锁故障。除了SUID还有/tmp和/var/tmp这两个目录的权限问题。生产机上如果/tmp被其它用户写执行权限放开攻击者可以把脚本丢进去诱导root执行。我的做法是给/tmp单独挂载noexec、nosuid、nodev参数这要在/etc/fstab里加并重挂载生效# /etc/fstab 里把/tmp所在行改为 tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev,mode1777 0 0 # 重新挂载生效 mount -o remount /tmp改成tmpfs之后/tmp会变成内存盘重启清空对需要临时大文件的程序可能有问题。如果业务有依赖/tmp存大文件就看情况改成普通分区加挂载参数不强制用tmpfs。这里踩过坑的朋友应该懂很多java程序默认把临时文件写在/tmp内存盘满了整个服务就hang住。4.2 服务裁剪与开机自启项少一个服务就少一个攻击面加固手册里经常写“关闭不需要的服务”但很多新手不知道哪些服务该关。我的判断办法很简单先看这台机器的业务是什么然后反向推理需要哪些端口。比如一台纯Web服务器需要的可能只有80/443和SSH其它的一律不应该跑。# 列出所有监听中的端口和对应进程 ss -tlnp # 列出所有正在运行的服务 systemctl list-units --typeservice --staterunning # 停掉并禁用明显无关的服务常见如 cups、avahi-daemon、bluetooth systemctl disable --now cups avahi-daemon bluetooth这里的判断逻辑不是把所有不认识的都禁掉而是先搞清楚它是什么、依赖什么。比如postfix默认在CentOS上启用很多业务根本没用到它但它会监听25端口并可能被spam机器人利用这种情况disable掉是合理的。再比如chronyd时间同步看着好像没用但Kerberos和日志审计都依赖它这类不能乱关。另外开机自启项里还藏着不少安装软件时自动写入的rc.local残留看一眼/etc/rc.local和/etc/rc.d/rc.local里的内容也是加固必做项。4.3 内核网络参数防SYN Flood、防IP欺骗、防源路由绕过服务层收紧后再到内核层把网络协议栈的“脾气”调稳。很多DDoS和扫描能得手跟内核默认参数太宽松有直接关系。下面这组sysctl参数是我在接入公网的机器上必调的# /etc/sysctl.d/99-security.conf # 开启SYN Cookie防止半连接攻击拖垮系统 net.ipv4.tcp_syncookies 1 # 忽略ICMP重定向和广播ping减少被用于放大攻击 net.ipv4.conf.all.accept_redirects 0 net.ipv4.conf.all.accept_source_route 0 net.ipv4.icmp_echo_ignore_broadcasts 1 # 开启反向路径过滤防止IP欺骗 net.ipv4.conf.all.rp_filter 1 net.ipv4.conf.default.rp_filter 1 # 禁ping按需开。对公网机器建议开内网YUM和监控例外 net.ipv4.icmp_echo_ignore_all 1 # 调大连接跟踪表避免高并发下被丢包 net.netfilter.nf_conntrack_max 65536 # 生效 sysctl --system注意accept_source_route这类参数在CentOS 6时代经常被单独设置到了systemd时代必须写在/etc/sysctl.d下并执行sysctl --system否则重启后失效。rp_filter开启后如果服务器有多块网卡做流量转发某些入站流量源地址和路由不匹配可能被丢弃这点在多运营商BGP接入的场景里要谨慎。我一般先在非生产环境开一周观察连通性确认没有误杀才推到生产。icmp_echo_ignore_all设1之后别人ping不通你的机器但自己的出站ping不受影响只是外部健康检查可能报异常WAF或负载均衡的探活如果依赖ICMP记得不要开这一条。5. 加固后的避坑与常见问题排??查为什么一改就翻车5.1 现象调整sshd配置后所有远程连接全部被拒连密码都不让输原因配置了PermitRootLogin no且关闭了PasswordAuthentication但公钥没有正确导入。最常见的是authorized_keys的owner是root或者目录权限是755sshd直接拒绝读取公钥。解决通过带外管理或云厂商的VNC登录把/root/.ssh/authorized_keys的owner改成对应用户权限收敛为600如果公钥内容本身有问题重新追加并验证是否换行正确。修复后再用sshd -t和sshd -T检查实际生效参数。5.2 现象加固后某个老业务访问另一个内网服务超时repair之后发现是防火墙规则拦了原因安全加固时用firewalld或iptables做了端口收敛只放行了本机服务端口忘了业务之间的互相访问。比如应用要连数据库的3306但数据库服务器的防火墙只放了SSH。解决做端口收敛前先对业务流量做一次清单梳理用tcpdump或ss -tlnp记录一段周期内的实际连接。梳理清楚的规则先放到一个独立zone里测试观察一周再挪到生产出错时能快速回滚。5.3 现象sysctl调整rp_filter后按地域DNS解析出现间歇性失败原因多网卡主机开启了严格反向路径过滤回程路由不对称导致部分UDP查询包被内核丢弃。解决先确认是不是rp_filter引起的看dmesg有没有martian source日志如果有就把rp_filter调整为0或改为loose模式。生产我通常用1多网卡问题域单独调但必须在变更记录里写清原因避免后续维护者一头雾水。5.4 现象关掉了来路不明的服务后开机自检多了一个失败单位系统也变卡了原因盲目disable了依赖关系核心的服务。比如关了dbus或polkit很多桌面组件和部分GUI程序起不来关了systemd-journald整个系统的日志会静默丢失。解决如果不是明确已知用不到先mask不用的服务而不是disable关服务前用systemctl list-dependencies查一下影响范围。5.5 现象修改SELinux上下文后业务服务报权限错误原因对密钥文件或业务目录执行了chmod或restorecon但业务二进制期望的类型上下文不是默认值。解决用ausearch -m avc -ts recent查看被拒绝的AVC记录然后用semanage fcontext添加对应规则再restorecon。如果实在排查不出上下文类型临时将SELinux设为permissive观察日志但不建议长期关闭。6. 验证与审计加固落地之后怎么确认它真的有效加固做完不是拍屁股走人最后一步是拿数据说话。我习惯在交付前跑一遍手动基线检查把系统当前状态固定成文字存档并开启审计守护进程。# 检查关键加固项是否已生效 sshd -T | grep -E permitrootlogin|passwordauthentication|port sysctl net.ipv4.tcp_syncookies systemctl is-enabled cups 2/dev/null || echo cups已禁用 awk -F: $7 ! /sbin/nologin $7 ! /bin/false {print $1} /etc/passwd # 开启审计守护进程监控关键文件变更 systemctl enable --now auditd auditctl -w /etc/ssh/sshd_config -p wa -k sshd_config_change auditctl -w /etc/passwd /etc/shadow -p wa -k account_change第一组命令的输出要和加固前的记录做对比确认参数没有回弹。第二组auditctl用内核审计框架对关键文件设置写监控一旦有人改动sshd_config或口令文件审计日志里会记下操作者和时间。这份日志再配合rsyslog远程投递到日志机即使入侵者清理本机日志远端照样有备份。这是整个加固动作里最划得来的一笔投入。这些年做下来我有一个习惯每次执行完加固变更都在变更单里记录改了什么参数、为什么要改、影响面是什么而不只记“已加固”三个字。有同事问我为什么这么较真我说遇到过一次因为没有记录三个月后系统出问题要回滚却不知道要回滚什么配置最后只能对照备份重装。这里面的教训就是加固本身不难难的是让加固状态可追溯、可回滚、可持续验证。希望这篇手册式的笔记能帮你在自己的机器上少踩几个坑把Linux安全加固从玄学变成一套可重复的执行流程。本文还有配套的精品资源点击获取
返回列表