在 VPN 服务器旁放一个缓存,听起来像是给隧道后面的所有人送上免费带宽。事实并非如此,因为经过那一点的字节仍受 TLS 会话保护,而该会话的两端是浏览器和网站。VPN 网关只去掉自己的外层加密,去不掉应用的加密。在增加硬件之前,先决定你要复用哪一种重复对象。

TLS 会话属于浏览器

在普通 HTTPS 中,浏览器与网站协商密钥,握手之后的每一条记录都为这对端点加密。VPN 网关解密自己建立的隧道,然后转发不透明的 TLS 记录。它能看到目的地、时间和流量,却看不到请求行或响应正文。这就是任何缓存都必须接受的边界。

任何打破这一点的设计都是 TLS 拦截设计,并带有证书信任与设备管理方面的自身后果。

CONNECT 是隧道,不是缓存

显式正向代理通常收到 HTTP CONNECT 请求,然后在两个方向上中继字节。关键在于中继:代理并不解析加密后的会话内容。

curl -sSI -x http://proxy.example:3128 https://example.com/

响应头来自代理对隧道的处理,而不是页面的缓存副本。CONNECT 成功只说明通路可用,并不说明有内容被存下来复用。 把 443 端口指向缓存 也不会让它学会说 TLS,因为缓存需要可读的消息。客户端配置必须使用受支持的显式代理设置,而不是没有解释的重定向。

缓存你运维的内容,而不是你浏览的内容

如果内容属于你,反向代理可以终止 TLS,并有意识地存储已获批准的响应。如果内容属于软件包仓库,就使用项目支持的镜像。

nginx -T | grep -n "proxy_cache"
curl -sSI https://mirror.example/pkg/index.json | grep -i -E "cache-control|age"

第一条命令显示是否配置了缓存区域以及它适用在哪里,第二条显示某个对象的源站自身缓存指令。共享缓存必须尊重新鲜度、缓存控制,以及区分不同表示形式的请求属性; private 和 no-store 含义不同,两者都不应为了抬高命中率而被去掉。HTTP 缓存规则还限制为已认证请求存储响应,而个性化页面恰恰在这里变成数据泄露。请把代理限制在获准的客户端,而不是暴露一个开放中继。

测量命中,而不是秒表

第二次请求变快,并不能证明新缓存起了作用,因为浏览器和操作系统本身就会积极地缓存。向代理索取命中与未命中计数器,并在受控重复期间观察源站流量。用同一个已知对象做一次重复下载,先启用缓存再绕过缓存,比较源站实际发出的字节,而不是耗时。然后检查授权边界:需要登录的资源不能提供给另一个客户端。

记录工作负载、缓存键以及允许复用的策略。缓存是一个披着优化外衣的数据共享决定。

相关文章