前言

最近,我偶然发现了网站存在一个特殊 BUG—— 在特定条件下,通过 ESA 域名访问某些路径时,页面会直接跳转到源站。更令人意外的是,网站上大部分类似路径都存在相同问题……

问题描述

正常访问的完整流程

通常情况下,在通过ESA域名访问一个不存在的URL时,流程是这样的:

1、用户访问 ESA 域名

1
GET https://miraii.cn/abc

  • ESA(类似EdgeOne, Cloudflare)收到请求。
  • 在自己的边缘节点的缓存中查找 /abc 对应的资源。

2、ESA 缓存未命中 → 回源

  • ESA 没有 /abc 的缓存,就会把请求转发给源站:
1
GET https://original.aimiliy.top/abc

3、源站处理请求

  • 源站 Nginx(或其他 Web Server)收到请求后发现 /abc 不存在且对应的 /abc/ 不存在时:
    • 先走自身的 error_page 404 配置:
      1
      2
      3
      ...
      error_page 404 /404/;
      ...
    • 返回一个 HTTP 404 状态码 + /404/ 的内容

4、ESA 接收源站响应

  • ESA 收到来自源站的响应头:
    1
    2
    HTTP/1.1 404 Not Found
    Content-Type: text/html
  • 其中包含 /404/ 的页面内容。最终,用户浏览器会收到带有 /404/ 页面内容的 404 响应

异常情况的触发机制

问题出现在 第三步。当 Nginx 配置如下时:

1
2
3
4
5
...
location / {
try_files $uri $uri/ =404;
}
...

如果:

  • /abc 不存在
  • /abc/ 存在

那么 Nginx 会将 /abc 301 重定向到 /abc/。 对于普通静态网站,这没什么问题,但在阿里云 ESA 环境中却出现了问题:ESA 并没有在边缘节点完成这次 301 跳转,而是直接让浏览器请求跳转后的 URL。这直接导致用户访问的是源站地址,使得源站域名被暴露。

源站域名暴露啥的对我来说问题不大,我的源站走的是 443 端口且不能直接访问,没有太大的安全风险。但是对于有着强迫症的我来说,这么多类似的页面都有这种BUG,简直是一种折磨。

正常访问效果:

正常访问

异常访问效果https://miraii.cn/posts/6e0ce6ed:
直接从 ESA 跳转到源站:

异常访问

解决过程

阿里云ESA配置体验

说实话,这个阿里云 ESA 的配置页面真是让我头疼。和之前用的 DCDN、CDN 相比,复杂得不止一点半点。以前还能直接配置边缘脚本控站点,现在我连入口在哪都找不到,找了半天毫无结果。

提工单沟通

没办法,只能去提工单。本以为能直接解决问题,结果那个工程师(或者说只是个客服)好像对自己公司的产品也不够了解,一开始给的建议全是“升级到高级版”才能用的功能。
后来他大概理解我的意思了,才让我去开启 回源 301/302 跟随 配置。

根据配置描述,这个功能是这样的:

节点回源请求资源时,如果收到源站返回的 301/302 状态码,就会直接跳转到响应中的地址获取资源,而不会把 301/302 返回给用户。

我理解为:开启之后 ESA 会帮我去源站拿到重定向后的资源,应该就能解决我当前的问题。

回源301/302跟随

未达预期的实际效果

开启之后,网站确实不再直接跳转到源站,但 ESA 并没有去获取重定向后的资源,而是直接显示回源异常。我再次联系了客服询问原因,他们表示正在排查问题,却一直到下午都没有任何回复……

并没有获取源站301跳转后的地址

重定向规则配置

最后我还是自己找了个笨办法:
直接在阿里云 ESA 的重定向规则 中,把可能触发 301 的链接全都在 ESA 这一层提前重定向,比如访问:

1
https://miraii.cn/tags

直接跳到:
1
https://miraii.cn/tags/

通过这种方式,可以绕过 301 引发的问题。不过,这个方法并非完美,目前并不能覆盖所有出问题的 URL ,而且有可能会影响其他 URL 的访问。

重定向规则配置

结语

网站已经坚持运营将近两年,这个 BUG 却是在最近才被发现。或许是以往的访问路径较为单一,才一直未触发这一问题。上面那只是一个暂时性的解决方案,长期来看还是得找其他得解决方法。我觉得那个 301/302重定向跟随 应该可以解决我这个问题,但是就是不知道为什么在回源的时候报500相关的错误了。而 ESA 的日志并非实时更新,源站的日志又显示一切正常,完全找不到问题的来源。

折腾一天了,累了,暂且就这样吧!