news 2026/9/30 7:33:22

Linux安全加固六步全解:从账号口令到审计留痕一步不落

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux安全加固六步全解:从账号口令到审计留痕一步不落

简介:《LINUX安全加固手册》是一份面向Linux系统运维人员、安全工程师和初学者的实操型参考文档,核心聚焦用户账户安全与网络服务安全两大模块。内容从系统安装阶段的安全设置切入,系统梳理密码安全策略、密码强度检测、密码影子文件(Password Shadowing)与密码管理,再深入解释服务过滤、/etc/inetd.conf、R服务、Tcp_wrapper、/etc/hosts.equiv等关键配置文件,形成从入口部署到日常维护的加固主线。资源为单个PDF文件,大小仅40KB,轻量易保存,方便随时查询。目前已有1330人学习下载。手册后半部分还覆盖NFS文件共享、tftp简单文件传输、Sendmail邮件服务、finger查询、UUCP等常见服务的风险点,读者既可按照目录逐项对照检查,也能直接参考其中关于密码策略与服务访问控制的具体做法,快速落地为一套可执行的安全基线;对不熟悉Linux安全配置的新手,这份检查顺序也能帮助减少遗漏,适合作为团队内部培训或上线前自查的参考材料。

1. 加固不是装完系统就算完:一台服务器真正能上线前还差什么

一份 Linux 安全加固手册看起来厚,拆开其实就六层:账号口令、文件权限、服务暴露面、内核参数、审计留痕、基线核验。我见过太多团队装好系统、配完 IP 就丢上线,结果撑不过三天就被扫出弱口令,root 被人直接登进去。真正的问题不是内核漏洞,而是配置层面没人管。本文围绕 Linux 安全加固这条主线,按我自己交付服务器时习惯的顺序,把每一步的命令、参数和翻车点一次讲透。适合刚接手服务器的运维,也适合做基线核查交付的工程师,照着做能少踩一半的坑。

2. 账号与口令:先管住人和密码,再谈纵深防御

2.1 第一步不是装软件,而是清空无效账号

拿到一台机器,我不会先装 fail2ban 或杀毒,而是先看这台机器上有多少账号。绝大多数入侵都是从一个不该存在的账号开始的,尤其是 UID 为 0 的伪 root、无密码账号、离职员工的遗留账号。

先看 UID 0 的账号,正常情况应该只有 root 一个:

# 列出所有 UID 为 0 的账号 awk -F: '($3 == 0) {print $1}' /etc/passwd

逻辑说明:/etc/passwd每行按冒号分成七个字段,第三个字段是 UID。UID 为 0 意味着这个账号拥有与 root 相同的权限,哪怕它叫别的名字。这个命令应该只在输出里看到 root,多出来的任何一个名字都要盯死。

再看哪些账号没有密码,或者密码字段是异常状态:

# 找出没有口令的账号,$2 为空或为 ! 都算异常 awk -F: '($2 == "" || $2 == "!") {print $1}' /etc/shadow

逻辑说明:/etc/shadow只有 root 能读,第二个字段是口令散列。如果为空,说明这个账号不需要密码就能登录;如果是!或*,通常表示锁定,但也可能是创建后从没初始化过密码。把输出逐个人工核对,确认是服务账号还是人为创建的孤儿账号。

处理办法分两种:确定没用的直接删,暂时不敢删的先锁:

# 锁定账号(保留 home 目录和 uid) usermod -L 用户名 # 删除账号并清理 home 与邮件池 userdel -r 用户名

参数说明:usermod -L是在 shadow 密码字段前面加一个!,比直接删安全,适合“这个人可能还要回来”的场景。userdel -r会一并删掉家目录和/var/spool/mail下的文件,执行前务必确认没有该用户遗留的重要数据。

顺带处理 sudoers。很多团队把 sudo 权限给了所有人,或者把普通用户加进wheel组之后再也不审计。我一般先备份再编辑:

cp /etc/sudoers /etc/sudoers.bak.$(date +%F) visudo

参数说明:visudo会做语法校验,写错了不会让你保存,这比直接vim /etc/sudoers靠谱得多。备份文件名里带日期,出问题能快速回滚。sudoers 里要重点看两处:%wheel ALL=(ALL) ALL是否给了过大的组权限,以及有没有单独给某个用户NOPASSWD的裸授权。

2.2 密码策略与密码过期提醒:改 login.defs 要配 chage 才完整

口令策略是所有加固里投入产出比最高的一项。我见过不少服务器 root 密码是123456,还开了 SSH 密码登录,这种机器在公网活不过一天。改密码策略的核心在三个文件:/etc/login.defs、/etc/pam.d/system-auth(或password-auth)、以及存量用户要用chage单独刷。

先看/etc/login.defs里的几个关键项:

# /etc/login.defs 中需要确认的四项 PASS_MAX_DAYS 90 PASS_MIN_DAYS 7 PASS_MIN_LEN 12 PASS_WARN_AGE 14

参数说明:PASS_MAX_DAYS是密码最长使用天数,90 天是比较常规的节奏;PASS_MIN_DAYS是两次修改的最小间隔,设 7 天防止用户把密码立即改回原密码;PASS_WARN_AGE是过期前多少天开始提醒,这就是很多人搜的“linux密码过期提醒通知”的配置来源。需要特别注意:login.defs只对之后的密码修改生效,存量用户的过期时间不会自动变。

所以改完login.defs之后,必须对现有用户批量刷新:

# 对 UID >= 1000 的普通用户统一设置密码策略 for u in $(awk -F: '($3 >= 1000) {print $1}' /etc/passwd); do chage -M 90 -m 7 -W 14 "$u" done # 单独查看某个用户的当前策略 chage -l 用户名

逻辑说明:awk -F: '($3 >= 1000)'表示只挑 UID 不低于 1000 的普通用户,避免把系统账号也圈进去。chage -M 90对应最大天数,-m 7对应最小天数,-W 14对应提前提醒天数。chage -l是事后检查用的,能看到该用户密码过期时间、最小修改间隔、账号过期时间,排查问题时比直接读 shadow 更直观。

有些团队还会加一道 pam 强度校验,在 RHEL/CentOS 系上改/etc/pam.d/system-auth:

# 密码强度校验:长度 12 且包含大写、小写、数字、特殊字符 password requisite pam_pwquality.so try_first_pass retry=3 minlen=12 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1

参数说明:minlen=12是总长度下限;dcredit=-1、ucredit=-1、lcredit=-1、ocredit=-1分别要求至少包含一个数字、大写字母、小写字母、特殊字符。负号表示“至少多少个”,正数才是“最多扣多少分”。retry=3允许用户重试三次,不要设成 1,否则误伤率太高。

2.3 登录失败锁定:pam_faillock 的配置顺序别放错

暴力破解是公网服务器的日常,SSH 日志里每天都有来自各种 IP 的Failed password刷屏。与其只靠 fail2ban 事后封禁,更稳妥的是在 PAM 层做登录失败计数。RHEL 8 之前的系统常用pam_tally2,之后版本建议用pam_faillock替代。

在/etc/pam.d/system-auth的 auth 段和 account 段分别插入:

# auth 段开头 auth required pam_faillock.so preauth audit silent deny=5 unlock_time=900 # auth 段中间(放在 pam_unix.so 之后) auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=900 # account 段 account required pam_faillock.so

参数说明:deny=5表示连续失败 5 次锁定,unlock_time=900表示锁 15 分钟。silent参数让锁定前的提示不泄露过多账号信息。配置顺序非常关键——preauth必须在最前面,authfail必须在pam_unix.so后面,否则可能出现认证成功也被计数的怪现象。我见过有人把顺序放错,导致管理员自己输错一次密码就被锁,最后只能单用户模式进去改配置。

手动解锁用这个命令,不需要重启任何服务:

faillock --user 用户名 --reset

这条命令在排查“用户被锁了又不知道原因”的场景里是刚需。加完策略后一定要自己试一次连续错 5 次,确认行为符合预期再离开终端。

3. 文件系统与权限:把提权路径一条条焊死

3.1 SUID/SGID 排查:先看清你的系统里哪些文件带着 root 权限

Linux 提权攻击里最常见的一类,就是利用系统里残留的 SUID 文件。SUID 的意思是一个二进制文件运行时,进程的有效 UID 会变成文件属主的 UID。如果一个属主为 root 的普通命令带着 SUID 位,任何用户执行它都等于临时获得了 root 权限——这就是“linux提权”这条热词背后最常见的利用链。

先把自己系统里的 SUID/SGID 文件翻出来:

# 找出所有带 SUID(4000)的文件,不跨文件系统 find / -xdev -type f -perm -4000 -ls 2>/dev/null # 找出所有带 SGID(2000)的文件 find / -xdev -type f -perm -2000 -ls 2>/dev/null

参数说明:-xdev表示只在当前文件系统内搜索,不进入/proc、/sys、挂载的移动硬盘等,否则会产生大量噪音和权限报错。-perm -4000的写法是“只要包含 SUID 位就命中”,而不是“必须恰好是 4000”,这样能覆盖4755、4750等常见变体。2>/dev/null把无权限访问目录的报错丢掉,不然输出会淹没有效结果。

拿到清单后逐一核对是否属于系统包:

# RHEL/CentOS 系 rpm -qf /usr/bin/passwd # Debian/Ubuntu 系 dpkg -S /usr/bin/passwd

逻辑说明:这两条命令用来回答“这个文件是系统自带的还是后放的”。passwd、sudo、su本身就必须带 SUID,保留没问题;真正危险的是/usr/bin/vim、/usr/bin/find、/usr/bin/tar这类工具被人为加了 SUID。确认是非法残留的直接去位:

chmod u-s /tmp/可疑文件

如果你的系统里/usr/bin/find带着 SUID,任何用户都能通过find . -exec /bin/sh;直接拿到 shell,这种文件留着就是给攻击者送 root。除了清理,还要定期把命令结果落盘对比,我习惯每周跑一次并把输出存到/var/log/suid_audit.log,方便追溯变更。

3.2 挂载选项:/tmp、/dev/shm、/var/tmp 三个入口要封住

/tmp是另一个经典战场。攻击者的写入脚本、下载的恶意载荷、提权工具的临时落地路径,绝大多数都在/tmp和/dev/shm。对这两个目录追加noexec、nosuid、nodev挂载选项,能直接废掉一堆落盘执行的攻击脚本。

先看当前挂载情况:

findmnt /tmp findmnt /dev/shm

如果/tmp不是独立分区,而是在/根分区上,那没法单独改挂载选项,只能靠后续的目录权限和/etc/systemd/system层面的 tmpfs 规则来补。独立分区的情况下,编辑/etc/fstab给对应行加选项:

# /etc/fstab 中 /tmp 和 /dev/shm 的推荐配置 /dev/mapper/vg-tmp /tmp xfs defaults,noexec,nosuid,nodev 0 0 tmpfs /dev/shm tmpfs defaults,noexec,nosuid,nodev 0 0

参数说明:noexec禁止在该文件系统上直接执行任何二进制文件,nosuid忽略 SUID/SGID 位,nodev不识别设备文件。这三个是一套组合拳,单独只加noexec会被perl -e '...'或python -c '...'这类解释器绕过,但配合nosuid能堵住大部分落盘提权路径。

/dev/shm改完要立即生效就重新挂载:

mount -o remount,noexec,nosuid,nodev /dev/shm

注意:/dev/shm是 tmpfs,改 fstab 后重启也会保持;/tmp如果是 LVM 分区,remount 命令类似但要注意当前是否有进程把可执行文件留在/tmp上——比如 Java 的java.io.tmpdir默认就指向/tmp,你把它noexec了,JVM 启动可能直接报Failed to create temporary file。改之前用lsof +D /tmp看一眼有哪些进程在用,别在业务高峰期动手。

/var/tmp经常被人忽略,它和/tmp一样可写,但很多系统的清理机制不会扫它。如果它是独立分区,同样加上这三个选项;如果不是,那就确保它的权限不是 777:

chmod 1777 /var/tmp

权限 1777 里的1是粘滞位,意味着只有文件属主能删除自己的文件,防止我叫“你删我文件”的跨用户攻击。

3.3 不可变属性与 umask:关键文件要锁,但别锁到没退路

对极其敏感的系统文件,可以用chattr +i设置不可变属性。设置了之后,即使是 root 也不能修改、删除、重命名该文件。这个操作我一般只用在/etc/passwd、/etc/shadow、/etc/ssh/sshd_config这几个文件上,而不是整个目录。

# 查看当前不可变属性 lsattr /etc/shadow # 设置不可变,防止被篡改 chattr +i /etc/shadow

参数说明:+i是 immutable 的缩写,设置后lsattr会显示----i-----------。注意这招对 root 同样生效,所以你的“后悔药”就是自己改配置前先解除属性:

# 升级或改密码前解除 chattr -i /etc/shadow # 完成后再加回去 chattr +i /etc/shadow

有很多人把/etc/passwd、/etc/shadow都加了+i,结果某次 yum update 时 rpm 事务脚本要替换这两个文件,直接报错中断,最后整个包管理器处于半坏状态。我的建议是:只在交付前、确认不会频繁变更用户和密码的阶段加锁,平时保持不加,靠审计规则盯着就够了。

默认的 umask 是 022,意味着新建文件权限为 644、目录为 755。对多用户服务器来说,这个值偏松,任何人都能读你 home 目录下的配置文件,而配置里往往带着数据库密码或者 API 密钥。收紧 umask 到 027:

# /etc/profile 末尾追加,对登录 shell 生效 echo 'umask 027' >> /etc/profile # 立即对当前会话生效 umask 027

参数说明:027表示新建文件的组权限去掉写权限,其他用户只有执行权。效果是新建文件 640、目录 750。对 web 服务这类需要其他用户读文件的场景,027可能太紧,可以折中用022保持读权限但不开放写。改完 umask 后,用umask命令验证当前值,并让业务方重启一下应用,确认临时文件和 Session 目录的权限没有异常。

4. 服务与 SSH:把系统的门面收窄到一扇门

4.1 SSH 加固:先从“留一条退路”开始

SSH 是服务器最重要的入口,也是被扫描爆破最频繁的端口。加固 SSH 的第一原则不是“改端口”,而是“先确保自己不会把唯一入口关掉”。我见过太多人上来就把PermitRootLogin no和PasswordAuthentication no一起打开,然后发现自己的公钥没装进去,人已经在机房千里之外——这种翻车一次就长记性。

正确的顺序是先放公钥、验证能登录,再关密码登录:

# 在服务器上创建 .ssh 目录并设置权限 mkdir -p ~/.ssh && chmod 700 ~/.ssh # 追加公钥(用 >> 而不是 >,别覆盖已有内容) cat id_rsa.pub >> ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys

参数说明:.ssh目录权限必须是 700,authorized_keys文件必须是 600。权限过松时 sshd 会直接忽略这个文件,而且不会给出明显报错。>>是追加如果服务器上已经有过期的公钥,覆盖写会直接把原管理员挤出系统。

公钥验证能登录之后,再改/etc/ssh/sshd_config:

# /etc/ssh/sshd_config 常用加固项 PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes MaxAuthTries 3 LoginGraceTime 30 ClientAliveInterval 300 ClientAliveCountMax 0 AllowUsers ops deploy

参数说明:PermitRootLogin no禁止 root 直连,管理员用普通用户登录后再 su 或 sudo,审计日志里能留下账号名;PasswordAuthentication no关闭密码认证,只允许密钥,这一步对防爆破效果立竿见影;MaxAuthTries 3限制单次连接最大尝试次数;LoginGraceTime 30限制登录超时时间,防止慢速爆破挂住连接;AllowUsers是白名单,只允许列出的用户从 SSH 登录,比在防火墙里封 IP 更硬核。

改完配置先做语法检查,再 reload,不要直接 restart:

# 语法检查 sshd -t # 语法通过后,保持当前连接不动,另开一个窗口验证新配置能连上 systemctl reload sshd

逻辑说明:sshd -t只检查配置合法性,不重启服务。确认语法无误后,用reload而不是restart,因为 reload 只重新读配置,不断开现有连接。就算新配置有问题,当前连接还在,你还有机会改回来。这是 SSH 加固里最重要的一个操作习惯。

4.2 服务暴露面:从 systemd 视角做最小化启动

Linux 默认安装会拉起一堆你根本用不到的服务:avahi-daemon、cups、postfix,还有一些发行版自带的远程管理代理。每个监听中的服务都是一个攻击面,你无法确定它们有没有隐藏漏洞。所以排查监听端口、关停无用服务,是每次加固的必修课。

先看当前所有正在监听的服务:

# 列出所有正在运行的 service 单元 systemctl list-units --type=service --state=running # 查看实际监听端口的进程 ss -lntup

参数说明:ss -lntup是现在推荐替代netstat的命令,-l只看监听中的,-n不做域名解析,-t只看 TCP,-u看 UDP,-p显示对应进程。输出里每一行都是一个潜在入口,对照业务需求逐个问“这个端口谁在用、能不能不监听”。

确认无用的服务直接停掉并禁用,有些还要 mask:

# 停止并禁止开机自启 systemctl disable avahi-daemon --now # mask 掉,防止被其他服务依赖而拉起来 systemctl mask cups.socket

参数说明:disable --now是“停止当前 + 禁止开机自启”的组合操作。mask比disable更狠,它会把这个单元链接到/dev/null,任何显式或隐式的启动请求都会失败,即使另一个服务在依赖列表里写了它也拉不起来。对cups.socket这类基于 socket 激活的服务,直接 disable 是不够的,因为打印任务一来它会被唤醒,mask 才能彻底关死。

4.3 端口与防火墙:默认拒绝而不是默认放行

公网服务器上防火墙策略的核心是“默认拒绝,白名单放行”,不是“默认放行,黑名单封禁”。大多数发行版默认的 zone 是public,策略是放行大量常见端口,这个对服务器来说太宽松了。

我习惯把默认 zone 直接切到drop,然后精确放行需要对外提供的服务:

# 默认 zone 切为 drop,未匹配规则的全部丢弃 firewall-cmd --permanent --set-default-zone=drop # 放行 SSH(如果用密钥登录且改了端口,换成自己的端口) firewall-cmd --permanent --add-service=ssh # 只放行业务端口,比如 80/443 firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https # 重新加载使配置生效 firewall-cmd --reload

参数说明:--permanent表示写入持久化配置,不加的话重启后丢失。dropzone 会对未放行的流量直接丢弃而不是返回拒绝包,从攻击者的扫描视角看,这些端口像是不存在,能显著减少被进一步探测的概率。切 zone 时务必确认 SSH 服务已经在放行列表里,否则防火墙 reload 的瞬间你就会被踢出服务器——这是个非常经典的翻车点。

如果系统用的是iptables而非 firewalld,最稳妥的收尾策略是把默认策略改为 DROP:

# 先把当前规则备份,别在前面的规则验证完之前清空 iptables-save > /root/iptables.rules.bak # 设置默认策略为 DROP iptables -P INPUT DROP iptables -P FORWARD DROP

注意:直接改默认策略之前,一定确保自己能通过其他方式回到机器,比如带外管理卡或云控制台的 VNC。我见过有人执行完iptables -P INPUT DROP才发现 22 端口的放行规则写在了后面,当前连接没断但新连接全部超时,那叫一个后悔药都没得吃。

5. 常见问题排查:加固后系统“飞了”,先查这五件事

5.1 密码过期策略误伤自动化任务

  • 现象:某天开始,cron 脚本和定时备份任务大面积失败,日志里出现认证失败或“password expired”的错误;部分服务间调用也开始报 401。
  • 原因:批量执行chage -M 90时把服务账号也圈进去了。服务账号不需要人工登录,密码过期后没有机制自动续期,依赖密码认证的定时任务全部失效。这类账号的密码过期时间往往还是“从未设置”状态,一旦策略落地就立刻出问题。
  • 解决:服务账号单独管理,不参与普通用户的密码周期。恢复操作用chage取消过期时间并检查状态:
# 对服务账号取消密码过期 chage -E -1 服务账号 # 检查所有账号的过期状态,找出遗漏 chage -l 服务账号 | grep -E 'Password expires|Account expires'

参数说明:-E -1表示取消账号过期时间,-1对 chage 来说就是“无限期”。排查时用chage -l看输出里的Password expires字段,一旦发现password must be changed之类的标记,就该知道问题出在密码周期上。

5.2 sshd 配置改坏后连不上的排查

  • 现象:执行systemctl reload sshd后,新连接全部被拒绝,要么提示Permission denied,要么直接超时;当前连接还活着,但不敢断,断了就回不去了。
  • 原因:PermitRootLogin no和PasswordAuthentication no同时启用,而自己的公钥并没有真正生效(可能是.ssh目录权限不对,或者 authorized_keys 内容被覆盖);也可能是AllowUsers名单里写错了用户名,把自己漏掉了。
  • 解决:先别慌,检查当前会话还在,然后做三件事:
# 1. 确认目标端口还在监听 ss -lntp | grep :22 # 2. 用 verbose 模式测试密钥认证是否正常 ssh -v -i 自己的私钥 用户名@目标IP # 3. 检查 authorized_keys 的权限和内容 ls -la ~/.ssh/ cat ~/.ssh/authorized_keys

公钥文件权限必须是 600,目录必须是 700,authorized_keys 里不能有多余换行或格式错误的 key。如果确认配置有问题,就在当前已连接的会话里改回去并 reload,保命要紧。以后再改 sshd_config 时,养成“先sshd -t,再另开连接验证,最后才 reload”的习惯,就不会再把自己关在门外。

5.3 /tmp 加 noexec 后安装包失败的排查

  • 现象:给/tmp加了noexec挂载选项后,某天安装新软件时报Permission denied或者段错误,尤其是安装包是二进制形式的、需要用/tmp做临时解压目录的软件。
  • 原因:安装程序把临时文件写到/tmp再执行,noexec直接拒绝执行任何位于该文件系统上的二进制,安装当然失败。类似情况也会发生在/dev/shm上——一些 Java 应用和数据库会用它做共享内存映射。
  • 解决:给这些程序单独指定可执行的临时目录,而不是取消 noexec:
# 创建专用临时目录,1777 保持粘滞位 mkdir -p /opt/tmp && chmod 1777 /opt/tmp # 对安装过程单独指定 TMPDIR TMPDIR=/opt/tmp ./installer.sh # 对 Java 应用,在启动参数里指定 java -Djava.io.tmpdir=/opt/tmp -jar app.jar

参数说明:TMPDIR是大多数程序都会尊重的环境变量,用它覆盖默认的/tmp即可绕过 noexec。/opt/tmp的权限用 1777,粘滞位保证多用户环境下不能互相删文件。如果程序是 systemd 启动的,在 unit 文件里加Environment=TMPDIR=/opt/tmp,改完记得systemctl daemon-reload。

5.4 chattr +i 之后升级失败的排查

  • 现象:在某次yum update或apt upgrade时报错,提示无法删除或替换/etc/shadow、/etc/passwd,包管理器直接中断,重启后系统处于半更新状态。
  • 原因:之前执行过chattr +i /etc/shadow,不可变属性对 root 一样生效。rpm 事务脚本在更新时要替换这些文件,发现属性不可变就直接失败。
  • 解决:升级前统一解除,升级后重新加回:
# 查看当前哪些关键文件带 immutable 属性 lsattr /etc/passwd /etc/shadow /etc/ssh/sshd_config # 升级前批量解除 chattr -i /etc/passwd /etc/shadow /etc/ssh/sshd_config # 升级完成后重新锁定 chattr +i /etc/shadow /etc/ssh/sshd_config

我的习惯是/etc/passwd不加锁,因为用户管理操作太频繁,加了反而制造麻烦;/etc/shadow和sshd_config可以加,但每次系统升级前都要走一遍“先解后锁”的流程。如果不放心,可以在升级脚本里把chattr -i和chattr +i写成一对,放在升级命令前后。

5.5 锁定策略把自己锁在门外的排查

  • 现象:管理员输错两三次密码后,整个账号被锁死,faillock --user 用户名 --status显示多个失败记录;有时甚至内网跳板机的固定 IP 也被连坐。
  • 原因:pam_faillock的deny阈值设得太低,比如 3 次;或者是自动化脚本、监控采集器用了错误的凭据反复探测,把失败计数刷上去了。
  • 解决:先解锁当前用户,再调策略:
# 解锁指定用户 faillock --user 用户名 --reset # 查看当前所有失败记录 faillock --user 用户名 --status

如果要彻底避免误伤,可以把运维跳板机的 IP 加进pam_faillock.so的ignore列表,或者把deny调高到 5 次、unlock_time保留 900 秒。记住一点:任何锁定策略都必须留一个不经过 PAM 的应急入口,比如带外管理卡或者本地 console,否则人不在机房时只能干瞪眼。

6. 内核参数与基线验证:从加固到能证明加固

6.1 几个必须动但别乱动的 sysctl 参数

sysctl 是内核运行时参数,改对了能挡住一批低水平攻击,改错了可能直接让网络行为异常。我只设置以下几个经过验证的参数,其余尽量不动:

# /etc/sysctl.d/99-hardening.conf net.ipv4.tcp_syncookies = 1 net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.icmp_echo_ignore_broadcasts = 1

参数说明:tcp_syncookies是 SYN Flood 的基础防护,半开连接队列耗尽时启用 cookie 机制;rp_filter开启反向路径过滤,丢弃源地址伪造的包;accept_redirects=0不接受 ICMP 重定向,防止中间人劫持路由;accept_source_route=0禁用源路由选项;icmp_echo_ignore_broadcasts忽略广播 ping,减少被用作反射放大攻击的风险。不要碰tcp_tw_recycle,它在 NAT 环境下会引发连接超时问题,4.12 之后的内核已经把它移除了。

生效并验证:

sysctl -p /etc/sysctl.d/99-hardening.conf sysctl net.ipv4.tcp_syncookies

6.2 用审计规则证明加固还在生效

配置改完只是开始,关键是三个月后还能证明这些配置还在。auditd 是 Linux 自带的审计框架,对关键文件的读写执行操作留痕:

# 为关键文件添加审计规则 auditctl -w /etc/ssh/sshd_config -p wa -k sshd_config auditctl -w /etc/passwd -p wa -k userdb auditctl -w /etc/shadow -p wa -k userdb # 查看最近所有关于 sshd_config 的变更 ausearch -k sshd_config -ts recent

参数说明:-w指定监控文件,-p wa表示记录写入和属性变更,-k是给规则打标签,方便后续检索。ausearch -ts recent查看最近时间段的记录,能用一条命令回答“这周有没有人改过 sshd 配置”。为了配合日常巡检,写一个加固基线自检脚本是一个很值得投入的收尾动作:

#!/bin/bash # 加固基线自检脚本:输出当前状态,人工对比差异 echo "== SUID 文件,正常只有 passwd/ sudo 等系统命令 ==" find / -xdev -type f -perm -4000 2>/dev/null echo "== SSH 允许密码登录状态,应为 no ==" grep -E '^PasswordAuthentication' /etc/ssh/sshd_config echo "== 空密码账号 ==" awk -F: '($2 == "") {print $1}' /etc/shadow echo "== 监听端口 ==" ss -lntup

这个脚本不追求自动判定,它的价值是把分散的检查项汇总到一次输出里,拿到结果后与上一次的基线做 diff,任何新增的 SUID 文件、端口或密码状态都是需要警惕的信号。我自己的习惯是每个月跑一次,输出重定向到文件里再对比,配合 auditd 的日志,任何异常变更都有迹可循。第一次做完整加固时也翻过车,把 SSH 密码登录关了才发现公钥没生效,还好当时的连接没断,从那以后每次改配置都先留退路再动手。这套流程走下来,服务器的安全状态不只看上去稳,出了问题还能追,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/30 7:33:04

IntelliJ IDEA构建RESTful API模板:Maven+Jersey+Servlet完整流程

简介:PDF电子教程以IntelliJ IDEA 2018.1.4为操作环境,全程演示从零创建一个基于Maven与Jersey的Java Web后端RESTful API模板。教程先从Maven archetype选择maven-archetype-webapp开始,讲解GroupId、ArtifactId的含义,随后在pom…

作者头像 李华
网站建设 2026/9/30 7:31:44

Django 导出 Excel 实战:内存优化与异步下载避坑指南

简介:面向Django开发者的实用技术文档,聚焦在项目中导出数据至Excel并实现浏览器下载的常见需求,适合初中级后端工程师快速掌握实现路径。资料包仅含1个PDF文档,大小77KB,内容精炼,便于快速阅读与按需查阅。…

作者头像 李华
网站建设 2026/9/30 7:30:49

PyTorch猫狗图像分类实战:从环境配置到模型训练完整指南

简介:这是一份面向深度学习初学者与有一定基础的开发者的PyTorch猫狗图像分类实战教程,提供从项目背景、数据增强、轻量级CNN搭建到训练评估与部署的完整流程。内容以中文讲解配合可直接复制运行的Python代码,覆盖随机裁剪、水平翻转、归一化…

作者头像 李华
网站建设 2026/9/30 7:29:54

微信小程序+Spring Boot+MySQL 4S店管理系统实战

简介:本资源是一份面向计算机专业本科生的毕业设计完整文档,聚焦汽车4S店信息化服务升级需求,基于微信小程序前端与JavaMySQL技术栈构建轻量化管理系统。文档详细阐述了小程序功能设计(车辆展示、试驾预约、保养预约)、…

作者头像 李华