把 LibreNMS 放到 Cloudflare 后面:那个恼人的 419 页面过期

我们用 LibreNMS 监控自己的网络——AS37969 骨干上的设备、跨境线路的中转、各机房的服务器,靠它收 SNMP、出图、报警。这类后台本身就是攻击目标:它暴露了内网拓扑,又是一个 PHP/Laravel 应用,直接挂公网上既怕被扫、又怕吃 DDoS。所以我们把它放到 Cloudflare 后面,套一层 CDN、WAF 和 DDoS 防护,顺带让分布在各地的同事能就近快速访问。

把它放到 Cloudflare 后面本身没什么好写的,难点在套上之后冒出来的一个问题:登录页一提交就报 419 - page expired。

419 Page Expired

这个报错是 Laravel 的 CSRF / 会话状态校验没过——提交表单时带的 token 和服务端 session 里存的对不上,框架就判过期。直接挂在公网时一切正常,一套上 Cloudflare 就复现,所以问题出在"中间多了一层"引入的状态错位上。我们排下来,成因有两个。

成因一:框架自身的状态不一致

LibreNMS 这套 PHP + Laravel,偶尔会有依赖包或缓存状态不太对,表现之一就是会话/CSRF 相关的奇怪报错。LibreNMS 自带的 daily.sh 会做依赖更新、数据库迁移、缓存清理这类日常维护,先跑一遍把框架自身的状态摆正:

./daily.sh

如果 419 是框架侧缓存或依赖导致的,这一步往往就好了。这也是上 Cloudflare 之前就该确认的基线——先排除应用自己的问题,再去怀疑前面那层代理。

成因二:nginx 的缓存把动态内容缓存了

更常见的是 nginx 的缓存配置不对,尤其是存在多层 nginx 嵌套的情况——比如本机一个 nginx,前面机房再套一个反代,Cloudflare 又在最外层。只要中间任何一层把登录页或带 Set-Cookie 的响应缓存了,不同用户/不同请求就会拿到同一份过期的 CSRF token 和会话 cookie,419 就来了。

修的方向是:确保登录和其它动态页面不被任何一层缓存,Set-Cookie 原样透传,不要被中间缓存吞掉。 把多层 nginx 里对这类动态路径的缓存关掉,让它们真正回源,419 就消失了。

这里不贴具体某一行配置,是因为每个人的 nginx 嵌套层数和现有配置都不一样,照抄别人的 location 块反而容易引新问题。思路比具体指令重要:顺着请求链从外到内(Cloudflare → 机房反代 → 本机 nginx)逐层确认,哪一层缓存了本不该缓存的动态响应,就在哪一层关掉。

小结

Cloudflare 这层防护对一个暴露内网拓扑的监控后台是值得的,但它和 LibreNMS 这种带会话、带 CSRF 的 PHP 应用之间,冲突点几乎全在"缓存了不该缓存的东西"。遇到 419,先 daily.sh 排掉框架自身的问题,再顺着 nginx 的多层缓存往下查——这两步能解决我们碰到的绝大多数登录过期。放到 Cloudflare 后面前,先在没有 CDN 的情况下确认能正常登录,这样一旦套上出问题,你就知道是中间层而不是应用本身。

Published At (Updated At) Tagged with