简介
对这个概念感到陌生的读者,可以先行查看这些文档:
RFC 7838 - HTTP Alternative Services
HTTP Alternative Services 介绍 | JerryQu 的小站
Alternative Services,直译过来即为“HTTP 替代服务”。发布于 2016 年的它不是一个新标准;如果要做个对比的话,HTTP/2发布于 2015 年。但如今它在 Web 服务中运用并不是很广泛。
其实它带来的特性挺实用的。简单地来说,它可以使用户在访问 example.com 时,让浏览器实际上向 "custom-proxy.example.com" 发送请求,而前端应用不会觉察到任何更改,甚至连 Host 标头都不会有任何变化。当然,这都是原站点控制的,该有 TLS 的还是走 TLS ,安全可靠不会被劫持,不易被中间人攻击。
免备案在国内主机上建站?
稍微深入想想,对国内站长来说,它有着很重要的意义。
由于严格的管控,大部分国内云主机或是内网穿透节点的 HTTP(S) 端口都是封死的,只有经过各种复杂的备案之类的才能放行,不备案的站长无法在国内主机常规端口部署 Web 服务。部署在除了 80 和 443 之外的非标准端口呢?记住网址对很多用户已经是难事了,还要记端口号的话估计是过滤大部分访客了... 这就意味着,不备案的网站与国内用户之间,只能隔着国际线路的大延迟和丢包。
但是,Alternative Services为我们提供了另一种可能。在墙外主机上部署一个站点,这将是用户首次访问到的站点,通过响应一个Alt-Svc标头让用户之后的请求都发送到国内主机的非标准端口上。这样便间接实现了免备案在国内主机上部署 Web 服务。
想多了
当然我们需要实践一下,恰好本站就是这么一个典型的例子。之前我解决这个问题的方法是,对于静态资源,当用户请求原站资源时,服务器返回一个302 Found状态码,将用户重定向到国内节点的非标准端口上。勉强有用,不过打开开发者工具的时候看到一堆重定向 ,弄得我很难受,虽然用户看不到。另外,这一堆请求一开始还是要经过源站,优化效果有限。于是我打算在自己的站点上配置 Alternative Services。
我首先在 Nginx 配置中增加了这样一个响应头:
Alt-Svc: h2="blog-proxy.icyu.me:41259"
测试后,发现它在 Firefox 上生效,但是Chrome并没有理会这个标头。一顿查找资料,看到这篇文章:使用HTTP Alternative Services实现免备案 | 灰灰 の blog,然后才知道Chrome不支持使用 HTTP/2 作为替代服务(想不明白为什么)。
好好,那么部署HTTP/3总可以了吧。我的树莓派上貌似无法用 apt 源更新 Nginx到支持 HTTP/3 的版本,于是安装了 Caddy 作为提供 HTTP/3 的反向代理。折腾这个又搞了很久,不过终于是跑起来了。然后把标头改成这样:
Alt-Svc: h3-29="blog-proxy.icyu.me:41259", h3="blog-proxy.icyu.me:41259"
在Chrome上还是不行,而且这次没有加上HTTP/2的替代服务连Firefox上也不生效了。又一顿搜索,发现好像目前HTTP/3的替代服务(基于 UDP)和老版本 Web 服务(基于 TCP)得运行在同一个主机,同一个端口。这就有问题了,那我还怎么用国内节点加速啊?另外我还是想不通这种限制的意义何在,这样的话还不如把Alt-Svc和Upgrade合并一下算了,毕竟(在Chrome上)前者也就是用来升级协议。
用在线工具测试了一下,是正常的,大概它的客户端没有这样莫名的限制。虽然原来的设想已经落空了,不过还是往下探索了一下。改成这样,类似于大部分成功启用 HTTP/3 的站点:
Alt-Svc: h3-29=":41259", h3=":41259"
然后我直接在浏览器输入协议加地址加端口号,直接访问国内的站点 。还是无法成功握手 HTTP/3,这回我真没有办法了。用 Wireshark 能抓到从浏览器发出的 QUIC 请求,不过没有回复。可能和我自己的网络环境有关吧,总之一时半会儿解决不了。
总结
给我整累了,写这篇警示一下后来的探索者不要掉我已经走过的坑,浪费了我很多时间。Web 标准的各家不同的实现或者是非标准的实现真的很让 Web 开发者头痛啊...
目前“免备案在国内节点建站”的需求大概只有用户使用Firefox才可实现。但考虑到它的用户群体实在有限,这也只能作为一个额外的手段,而非主要方式。
至于HTTP/3,我还没发现哪个中文技术博客成功启用了这个功能。除非站点通过 Cloudflare 代理,那倒是可以的。测试使用的浏览器是 Chrome 99 (Windows 平台,32位版本)。
忘记说了,最后提醒一下在浏览器配置了代理的情况下 Alt-Svc 标头不生效,也就是说此时无法启用 HTTP/3。
其他参考
HTTP/3:HTTP Alternative Services 作为协商方式 | Sukka's Blog
Alt-Svc - HTTP | MDN
全站已经启用HTTP3 + QUIC + Brotli - GKSEC - ATD SECURITY TEAM
小试HTTP3 | kn007的个人博客