如何对网站启动QUIC协议
最近在研究QUIC协议,如何让笔者的博客网站也支持QUIC呢?
背景
梳理下本网站的架构
1 | client -> nginx(https) -> hexo server(127.0.0.1:4000) |
- 负载均衡器: 使用nginx作为反向代理
- 博客服务: 使用hexo,并监听在127.0.0.1
- SSL证书: 使用acme.sh安装证书到对应的路径
实践
1. Nginx支持Quic
Nginx官方已在1.25.0以后支持Quic,需要手动编译和部署。
本物理机仍然是ubuntu16.04,综合考虑下,直接使用Docker的方式来运行,那么就需要考虑acme.sh如何将证书更新后reload docker中的nginx服务
acme.sh支持nginx docker
参考acme.sh的wiki部署相关acme.sh的docker和nginx docker
启动nginx docker
1
docker run --rm -it -d --label=sh.acme.autoload.domain=example.com nginx:latest
启动acme.sh docker
1
2
3
4
5
6docker run --rm -itd \
-v "$(pwd)/out":/acme.sh \
--net=host \
--name=acme.sh \
-v /var/run/docker.sock:/var/run/docker.sock \
neilpang/acme.sh daemon申请证书
1
2
3
4docker exec \
-e CF_Email=xxx@exmaple.com \
-e CF_Key=xxxxxxxxxx \
acme.sh --issue -d example.com --dns dns_cf发布证书并reload nginx
1
2
3
4
5
6
7
8docker exec \
-e DEPLOY_DOCKER_CONTAINER_LABEL=sh.acme.autoload.domain=example.com \
-e DEPLOY_DOCKER_CONTAINER_KEY_FILE=/etc/nginx/certs/example-com.key.pem \
-e DEPLOY_DOCKER_CONTAINER_CERT_FILE="/etc/nginx/certs/example-com.one.cert.pem" \
-e DEPLOY_DOCKER_CONTAINER_CA_FILE="/etc/nginx/certs/example-com.ca.pem" \
-e DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/etc/nginx/certs/example-com.cert.pem" \
-e DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload" \
acme.sh --deploy -d example.com --deploy-hook docker大家这里可以猜测下acme.sh的docker是如何将nginx docker中的服务reload的?
docker.sock是docker间通讯的关键
通过DEPLOY_DOCKER_CONTAINER_LABEL找到对应的nginx docker
发送DEPLOY_DOCKER_CONTAINER_RELOAD_CMD命令将nginx reload
整体的配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32version: "2.0"
services:
nginx:
image: nginx:1.25.2
container_name: docker_nginx
restart: unless-stopped
labels:
- "docker_nginx"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/conf.d:/etc/nginx/conf.d
ports:
- "80:80"
- "443:443"
- "443:443/udp"
extra_hosts:
- "host.docker.internal:xxx.xxx.xxx.xxx"
acme-blogs:
image: neilpang/acme.sh
container_name: acme-blogs
command: daemon
volumes:
- /data/acmeout:/acme.sh
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DEPLOY_DOCKER_CONTAINER_LABEL=docker_nginx
- DEPLOY_DOCKER_CONTAINER_KEY_FILE="/etc/nginx/certs/example-com.key.pem"
- DEPLOY_DOCKER_CONTAINER_CERT_FILE="/etc/nginx/certs/example-com.one.cert.pem"
- DEPLOY_DOCKER_CONTAINER_CA_FILE="/etc/nginx/certs/example-com.ca.pem"
- DEPLOY_DOCKER_CONTAINER_FULLCHAIN_FILE="/etc/nginx/certs/example-com.cert.pem"
- DEPLOY_DOCKER_CONTAINER_RELOAD_CMD="service nginx force-reload"
2. Nginx支持QUIC
参考nginx的文档配置server
1 | server { |
3. Nginx访问宿主机的hexo服务
方法一
一般docker是使用bridge
的方式来启动的,这时会在宿主机中启动一个docker0的网卡,将nginx中的upstream的server ip改为这里的172.17.0.1
即可实现docker访问宿主机网络
1 | $ ifconfig |
nginx upstream配置如下:
1 | upstream hexo-backend { |
方法二
docker v20.10+提供了一种支持方案,可通过指向 host.docker.internal
来指向宿主机的 IP。参见文档:从容器连接到主机上的服务
配置 docker-compose.yaml
1 | version: '2.0' |
在nginx docker中执行相关语句后,应该是可以联通到宿主机。由于笔者的docker环境是v20.4,无法实验,暂无法确定本方法是否可行
1 | $ curl http://host.docker.internal:4000 |
方法三
以host
方式启动nginx docker,这样nginx仍然在宿主机网络下
总结
笔者最后使用方法一来打通docker和宿主机的网络。至此,整体架构改为以下方式。
1 | client -> nginx docker(443:443, 443:443/udp) -> hexo(172.17.0.1:4000) |