前言
暑假打了两个月工,非常累。开学的前三个星期开始康复训练,除了上课基本就是在玩游戏和看少女乐队,直到昨天晚上(9.22)总算电子阳痿了,想到不好好学习以后就得毕业即失业了,于是掏出了自顶向下来看。印象里学校的计网课程甚至传输层协议都是几笔带过,更别提应用层协议,大量时间都在网络底层上,一度让人怀疑自己是来到了通信工程专业的教室。果不其然,自顶向下很多也忘了,甚至套接字的概念都是模糊不清的,看了一会儿书打算做下lab 1复健一下,可惜时间太晚就上床了。后来和社团群友聊天,我在扯给UDP加上排序和重发不就是没有握手的TCP,然后群友提了一下QUIC,我顺势搜过去就看到了RFC 9000,也就是HTTP/3。打算睡醒了就给服务器配上HTTP/3。
升级&配置Nginx
升级Nginx服务器还有更新配置文件我就不多说了,看这篇文章就够:是时候为网站开启 HTTP/3 支持了吗 – atpX,我主要讲一下(自己造成的)踩过的坑。
我直到要配置的时候才想起来,高中的时候给这台香港轻量服务器留了不少坑,那时候因为还是一知半解的程度,这台机器主要都是用一键包配置的。(lnmp.org)现在用它也不敢了,因为很多面板/一键包都遭到了供应链投毒攻击,我自己也试过再用一键包的脚本编译安装更新,不出意料的失败了,还把nginx弄没了(还好拍了快照(要是以前的我肯定就滚回去打退堂鼓了)),想到之前上linux课的时候也教小白同学apt直接装NMP环境,没想到直接成功了(我也帮了点忙),于是打算换apt更一个试试,结果阿里源太旧压根没有官网的stable version。(我用的香港服务器为啥要用阿里源(但是看别人博客里说Debian源也很旧())),然后就老实添加nginx官网的pgp key巴拉巴拉装上了。后来花了大半天时间折腾的罪魁祸首如下图所示(我是洗完澡翻了下命令日志才看到的(虽然也通过这次折腾的又学到了很多(要是以前到这里绝对回滚不干了(还有一点应该就是不是重要的生产环境炸几个小时也无所谓,反正没人看)))))
由于自己的降智操作,我后面花费了一番功夫重写systemd下nginx.service以及nginx.conf的配置文件(主要是搞清楚他们怎么工作的)
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=false
[Install]
WantedBy=multi-user.target
可以看到,实际上systemctl就是个大号脚本,你在输入systemctl start nginx.service的时候实际上就对应着配置文件中ExecStart的/usr/sbin/nginx -c /usr/local/nginx/conf,和你在shell里执行是一样的。另外刚才写的时候还发现了一个配置文件的覆盖问题,/etc/systemd/system下的配置文件会覆盖/usr/lib/systemd/system下的,因此对另一个被覆盖的配置文件做修改实际上是不会生效的,可以参考以下文章
user www www;
worker_processes auto;
worker_cpu_affinity auto;
error_log /home/wwwlogs/nginx_error.log crit;
pid /var/run/nginx.pid;
#Specifies the value for maximum file descriptors that can be opened by this process.
worker_rlimit_nofile 51200;
lnmp.org的一键包会给pid目录配置成/usr/local/nginx/logs/nginx.pid,因为配置文件被重置的缘故,执行acme.sh会报错找不到Nginx的pid文件,认为在/var/run/nginx.pid下。实际上因为上面我把两处units文件混淆了之后,就一直在和三个应用程序指向的同一pid文件路径不同导致脑袋跟着服务器打架。例如/var/run路径下只有root用户拥有可写权限,我认为nginx的worker线程因为是www用户所以没有/var/run下的可写权限还在犹豫要不要赋予777权限,实际上是我一时脑抽了(
这里还有对pid文件修改造成影响的实验,可以看看(还挺好笑的):谁掳走了 nginx.pid 文件? – 活出自己范儿 – 博客园 (cnblogs.com)
server {
listen 443 ssl;
listen [::]:443 ssl;
listen 443 quic reuseport;
listen [::]:443 quic reuseport;
http2 on;
server_name atpx.com;
root /var/www/atpx.com;
index index.html;
ssl_certificate /path/to/ssl/atpx.com.pem;
ssl_certificate_key /path/to/ssl/atpx.com.key;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# Enabling 0-RTT.
# ssl_early_data on;
ssl_session_timeout 1h;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
# Informs the client that HTTP/3 is available.
add_header alt-svc 'h3=":443"; ma=86400';
}
等我终于重新更新完nginx服务器,就开始各个虚拟主机的配置了,在依照上面博客cv配置后发现端口被占用了,Stackoverflow上搜了下原来是因为这个原因,reuseport只用在一个虚拟主机的server中启用,随后会应用到所有host-port pair中,至于原理是什么我没看懂,我把文章丢给你们来看。
Enabling QUIC / http/3 on multiple domains with NGINX 1.25 – Stack Overflow
在我使用HTTP/3 Check网站检查博客是否支持的时候发现还支持0-RTT,但是我在vhost conf中并没有设置ssl_early_data on; 这也是我同样不理解的部分,不过在其他几个开启了http3的网站他也测不出来,不管了。
RFC 9460 SVCB&HTTPS DNS Record
等我总算搞定这些启动Nginx服务器,使用Edge F12工具观察网络请求发现协议中并没有走H3,仍然是H2,这是为什么呢?
QUIC为了兼容性,是基于UDP的应用层协议,而UDP因为众所周知的原因,可能会被国内运营商随机丢包等反而造成负优化,希望HTTP/3时代不要因此与我们无缘。顺带一提,二次元代理软件Hysteria 2协议就基于QUIC(HTTP/3)。在http header中的alt-svc ‘h3=”:443″; ma=86400’信息并不会在首次连接生效,等浏览器发现header中存在这行信息才会在后续的连接中尝试使用HTTP/3,但前提是H3速度比H2快,否则就是负优化了(
如果想要第一次连接就劝说浏览器使用HTTP/3该怎么做呢?这时候RFC 9460就隆重登场了,添加TYPE 64或TYPE 65 DNS记录(也就是SVCB/HTTPS)即可在发起DNS查询时就让浏览器知道站点支持H3协议。
此外,在添加SVCB/HTTPS记录的时候,有没有注意到在优先级非0时,填写的服务参数可以设置端口?例如填写port=”443″,即可告诉客户端直接使用DNS记录中提供服务的端口,那么这样还可以实现一些有趣的东西。可以阅读下文(但是运营商可以识别你的http流量,哪天一个红头文件下来我看还是都得完蛋,但是现在作为权宜之计还是不错的)
一种通过设置 DNS 记录解决家庭宽带提供 https 服务省去端口号的方法 – V2EX
折腾了这么多,那么,使用HTTP/3可以有多快呢?可以用一张图解释:
截止到本文发布作者仍未完成自顶向下的lab 1(
挺想用quic的,但是我用的是面板部署,强行升级怕出问题
可以做个快照再试试升级,我服务器用的也是类似于面板的东西,实际上主要注意的地方就在配置文件上
哎,不想折腾了,到时候炸了又要弄半天(无奈
只要拍了快照,rm -rf /也会好起来的)