把 API key 校验上移到反向代理
上游升级把鉴权模块删了,才意识到门不该装在别人家里。
模型服务的推理引擎升级后,原来的 API key 鉴权直接被移除了——配置文件里的字段失效,服务裸奔在公网上。这类变更提醒我一件事:把安全边界建在应用层,就要接受它会随版本漂移。最后的解法是把鉴权上移到反向代理。
问题:升级即失守
自托管推理工具的大版本迭代常常伴随配置结构重构。这次是鉴权整体下线,理由是"应由上游网关负责"。如果没人盯 changelog,升级完成的瞬间服务就对所有来源开放了——而且功能一切正常,没有任何报错提示你这件事。
为什么选 nginx 做 key 白名单
不想引入额外组件,nginx 本来就在链路最前面,用它做一层 Bearer token 白名单足够:
map $http_authorization $auth_ok {
default 0;
"Bearer <你的密钥>" 1;
}
server {
listen 443 ssl;
location / {
if ($auth_ok = 0) { return 401; }
proxy_pass http://127.0.0.1:<后端端口>;
}
}
没有状态、没有外部依赖,改一行配置 reload 就生效。客户端只需要把请求地址指到这个入口,密钥放在 header 里,其余不变。
三个踩过的细节
一、map 块里含空格的 key 必须加引号。Bearer xxx 中间有空格,不加引号会让配置解析失败,而报错信息指向的行号未必是真正出错的那行。
二、容器里不能用 127.0.0.1。当调用方是跑在同一台机器上的容器时,它的 127.0.0.1 是容器自己的网络命名空间。要么走 Docker 网桥地址,要么用宿主机的内网地址,否则永远连不上——而这个错误的表现经常是"服务明明活着,容器就是超时"。
三、代理和后端抢端口。把某个端口从直连改成代理转发时,旧进程还占着端口,nginx 起不来(Address already in use)。正确顺序是:先让后端隧道切到新端口并释放,再写代理配置,最后 reload。另外回滚备份不要用"取最新文件"的策略——刚写坏的配置会正好成为那个"最新备份"。
更一般的原则
鉴权、限流、TLS 终止这类横切关注点,尽量放在自己完全掌控的一层,而不是依赖每个上游组件各自实现。上游可以随便重构,网关这层不动。多花十分钟配 nginx,换来的是以后每次升级都不用重新审一遍安全设置。
不要把门装在别人家的房子里——他会装修,你会忘记门已经没了。