在一台新 VPS 上第一次运行 Lynis,通常会得到 60 上下的分数和一长串建议,而且看不出该先抓哪一条。好消息是:80 到 85 是一个晚上的工作量,而且大多数步骤不是装饰性的,是真正值得做的。坏消息是:最后那十五分在一台租来的虚拟机上够不着,去追它是个错误。
这个 index 说明什么,又不说明什么
hardening index 是通过的检测项占总数的比例,并带有权重——而不是安全性的百分比。Lynis 会跑大约三百项检测,给出两份彼此分开的清单:warnings,看起来像是真问题的;以及 suggestions,是可以改进的地方。永远先从警告开始;它们通常只有寥寥几条。
一百分是不会有的:有些建议要求的是安装系统时做出的决定(为 /home、/tmp 和 /var 分独立分区),有些需要 VPS 上没有的引导器访问权限,还有些彼此矛盾。而拿自己的 index 跟别人比毫无意义:Lynis 是按机器上跑着什么来扣分的。每多一个运行中的服务,就多一个开放端口、多一份自己的配置和十来条新建议,正因如此高分更多出现在除了 SSH 什么都不跑的地方。对一台带站点、数据库和邮件的生产服务器来说,85 是个好成绩。
请以 root 身份运行
sudo lynis audit system
没有 sudo,Lynis 会跳过所有需要系统文件的检测,并报出一个偏低的 index——不是因为服务器差,而是因为那些检查根本看不见。报告写入 /var/log/lynis-report.dat,可读的日志在 /var/log/lynis.log。
输出的每一行都以检测项标识符开头,比如 SSH-7408 或 KRNL-6000。正是靠这个标识符去查找说明,也靠它来关掉某项检测——记住它的样子,下面的一切都围绕着它。
真正能拉动分数的是什么
SSH(SSH-7408)。最重的一块:一项检测同时查十来个参数。不要改动整个 sshd_config;放一个独立文件进去,好让包更新抹不掉你的成果:
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
MaxAuthTries 3
MaxSessions 2
X11Forwarding no
AllowTcpForwarding no
ClientAliveInterval 300
ClientAliveCountMax 2
LogLevel VERBOSE
TCPKeepAlive no
EOF
sudo sshd -t && sudo systemctl reload ssh
重载服务之前的 sshd -t 是强制性的:在你的会话还开着的时候,配置里的一处错误会把你留在门外。而在设置 PasswordAuthentication no 之前,请从第二个打开的终端确认密钥确实可用。
内核参数(KRNL-6000)。这项检测会查大约两打 sysctl 值。给它们准备一个文件:
sudo tee /etc/sysctl.d/99-hardening.conf <<'EOF'
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
kernel.sysrq = 0
fs.protected_hardlinks = 1
fs.protected_symlinks = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.all.log_martians = 1
EOF
sudo sysctl --system
缺失的工具。相当一部分建议只是「把没有的装上」:auditd(系统事件记录)、aide(文件完整性)、debsums(软件包完整性)、unattended-upgrades(自动安全更新)、sysstat 和 acct(进程记账)、恶意软件扫描器。每一个都能关掉一两条建议,但别为了分数去装:没有它们,事后你什么也复原不了。
投入产出比不错的小事。/etc/login.defs 里的 umask 027;同一文件里的口令有效期;/etc/issue 和 /etc/issue.net 里的横幅;只有 root 可读的编译器(chmod 700 /usr/bin/gcc)。关于横幅说句实话:它们对安全毫无作用,那是法律形式——但分数确实是给的。
login.defs 里的一个陷阱
用 sed 替换行的方式去改 umask,常常会让文件里同时留下好几行 UMASK。这时 Lynis 干脆不计这个值,检测项 AUTH-9328 依然是红的,尽管设置看上去已经做好了。改完之后请检查:
grep -c '^UMASK' /etc/login.defs
应当恰好只有一行。那个文件里的其他每个参数同理。
误报,以及把它们正确地噤声
有些警告对你的服务器根本不适用。一个活生生的例子:在某大服务商的 VPS 上,检测项 PKGS-7388 报称找不到安全仓库——仅仅因为仓库是以 deb822 格式描述并引用了一个镜像文件,而 Lynis 在找它熟悉的那种写法。安全更新其实来得好好的。
把它噤声要用 profile,而不是从报告里删行。profile 文件用 .prf 扩展名(不是 .prof——在这里丢掉半小时很容易),而你自己的规则放进 /etc/lynis/custom.prf:
skip-test=PKGS-7388
skip-test=KRNL-5788
只有一条规则:每一行旁边都需要一句注释,说明为什么跳过这项检测。半年后你不会记得它是因为不适用而被关掉,还是因为修起来太麻烦——而这两种情形之间的区别,正是全部意义所在。
不该做什么
别追着数字跑。关掉那些碍事的检测就能轻易把 index 吹上去,而且过了某个水平之后那是唯一的路——只不过服务器并不因此更安全。有用的是另一件事:记下自己的数值,然后观察它的变化。在一次更新之后或者别人改过配置之后掉下来的 index,是比它的绝对大小有价值得多的信号。
正因如此,Lynis 值得按计划运行而不是只跑一次,并把报告保存下来,好有东西可比。汇总在一个页面上是什么样子,见下面的演示:index、带检测项标识符的警告清单,以及自上一次运行以来有什么变化。