欢迎光临散文网 会员登陆 & 注册

[HTTP3/QUIC] Debian 编译 NGINX_QUIC ,支持 HTTP3 QUIC

2023-02-20 04:49 作者:rua喵的小离  | 我要投稿

[HTTP3/QUIC] Debian 编译 NGINX_QUIC ,支持 HTTP3 QUIC

1. 准备 golang 环境(编译 BoringSSL 需要)

# 卸载旧环境 golang
apt-get remove golang
apt-get autoremove
# 环境准备 golang
cd /usr/local/src/
wget https://golang.google.cn/dl/go1.19.1.linux-amd64.tar.gz
tar -zxvf go1.19.1.linux-amd64.tar.gz
mv go /usr/local/
ln -s /usr/local/go/bin/go /usr/bin/go

2. 编译 BoringSSL (NGINX-QUIC/HTTP3 需要)

# BoringSSL
# Centos 编译不过,编译完从 Debian 复制过去也能用
cd /usr/local/src/
apt install git cmake gcc g++
git clone https://github.com/google/boringssl.git
mkdir /usr/local/src/boringssl/build
cd /usr/local/src/boringssl/build
cmake ..
gmake 
gmake install

3. 编译 NGINX

# 准备编译环境
cd /usr/local/src/
wget https://zlib.net/zlib-1.2.13.tar.gz
tar -zxvf zlib-1.2.13.tar.gz
apt install libpcre3 libpcre3-dev mercurial
hg clone -b quic https://hg.nginx.org/nginx-quic
cd /usr/local/src/nginx-quic
# 编译 HTTP3
./auto/configure \
--with-debug \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_quic_module \
--with-http_v2_module \
--with-http_v3_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_addition_module \
--with-http_sub_module \
--with-threads \
--with-openssl-opt='enable-tls1_3' \
--prefix=/usr/local/nginx \
--with-zlib=../zlib-1.2.13 \
--with-cc-opt="-I../boringssl/include" \
--with-ld-opt="-L../boringssl/build/ssl -L../boringssl/build/crypto"
make
make install
# HTTP2 (已经不使用)
./configure \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-http_v2_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_addition_module \
--with-http_sub_module \
--with-threads \
--with-openssl-opt='enable-tls1_3' \
--prefix=/usr/local/nginx \
--with-openssl=../openssl-1.1.1q \
--with-zlib=../zlib-1.2.13
make
make install

4. 配置使用 systemctl

vim /usr/lib/systemd/system/nginx.service

[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s quit
PrivateTmp=true

[Install]
WantedBy=multi-user.target

5. 提供一个简化的NGINX 配置

## 缺少某些目录或者文件导致无法写入,导致启动报错的
mkdir -p /etc/nginx/conf/logs/
## 自行解决: dhparam.pem ssl_certificate、ssl_certificate_key 等文件
## 这个文件主要是写一些通用的配置,通过 include 来统一引入。看起来简洁一些
vim /etc/nginx/public.conf
## 重要: 必须要在 include vim /usr/local/nginx/conf/nginx.conf 才能生效
include /etc/nginx/*.conf;

vim /etc/nginx/zhuihoude.cn.conf

server {  #if ($host !~* "(zhuihoude)") { return 444;}
  listen 80;
  return 302 https://$host$request_uri?http;
}

################ zhiuhoude.cn ################
server {
include                                     /etc/nginx/conf/public.conf;
  ssl_trusted_certificate                   /etc/nginx/conf/certificate/cn.crt;
  ssl_certificate                           /etc/nginx/conf/certificate/cn.crt;
  ssl_certificate_key                       /etc/nginx/conf/certificate/cn.key;

  server_name                               zhuihoude.cn;
  listen                                    443 http2 reuseport fastopen=3 ssl;
  listen                                    443 http3 reuseport;

location / {
  if (
  $host !~* "(zhuihoude)")                  { return 302 http://zhuihoude.cn; }
  proxy_pass                                https://127.0.0.1:8080/;
  proxy_redirect                            default;
# proxy_set_header 写在 server 下似乎会失效
  proxy_set_header                          Host $host;
  proxy_set_header                          X-Real-IP $remote_addr;
  proxy_set_header                          X-Forwarded-For $proxy_add_x_forwarded_for;
  access_log                                /etc/nginx/conf/logs/today_zhdcn.json log_json;
}

vim /etc/nginx/public.conf

## SSL Config
  ssl_dhparam                               /etc/nginx/conf/certificate/dhparam.pem;
  ssl_protocols                             TLSv1.2 TLSv1.3; # SSLv2 SSLv3 TLSv1 TLSv1.1 
  ssl_session_cache                         shared:SSL:10m;  #缓存大小
  ssl_session_tickets                       on;              #浏览器缓存
  ssl_session_timeout                       10m;             #缓存超时
  ssl_prefer_server_ciphers                 on;              #使用服务器密码
  ssl_ciphers                               ECDHE:!CBC:!NULL:!aNULL:!eNULL:!MD5:!ADH:!RC4:!DH:!DHE;
  ssl_early_data                            on;              #开启 1.3 o-RTT
  keepalive_timeout                         120s;            #TCP 保持
  keepalive_requests                        1000;

 #ssl_stapling                              on; ## OCSP Stapling 用于在线查询证书吊销情况 BoringSLL 暂不支持
  ssl_stapling_verify                       on;
# ssl_stapling_file                         /etc/nginx/conf/certificate/stapling_file.ocsp;
  resolver                                  114.114.114.114 8.8.8.8 valid=240s;
  resolver_timeout                          5s;

## HTTP3
  quic_retry                                on;
  quic_gso                                  on;
  quic_mtu                                  1350;

## 升级站内 HTTP 为 HTTPS 连接
  proxy_hide_header                         Content-Security-Policy;
  add_header                                Content-Security-Policy upgrade-insecure-requests;
## HTTP3 开启常用端口
  proxy_hide_header                         Alt-Svc;
  add_header                                Alt-Svc 'h3=":443"; ma=86400';
  add_header                                Alt-Svc 'h3=":1443"; ma=86400';

## Hsts
  proxy_hide_header                         Strict-Transport-Security;
  add_header                                Strict-Transport-Security "max-age=31536000; includeSubdomains; preload";
## DENY:不能iframe;SAMEORIGIN:本站iframe;ALLOW-FROM:允许frame
  proxy_hide_header                         X-Frame-Options;
  add_header                                X-Frame-Options SAMEORIGIN;
## 防止 MIME 类型混淆攻击
  proxy_hide_header                         X-Content-Type-Options;
  add_header                                X-Content-Type-Options nosniff;
## 跨域
  proxy_hide_header                         Access-Control-Allow-Origin;
  add_header                                Access-Control-Allow-Origin *;
  proxy_hide_header                         Access-Control-Allow-Credentials;
  add_header                                Access-Control-Allow-Credentials true;
  proxy_hide_header                         Access-Control-Allow-Methods;
  add_header                                Access-Control-Allow-Methods *; #'GET, POST, OPTIONS';
  proxy_hide_header                         Access-Control-Allow-Headers;
  add_header                                Access-Control-Allow-Headers *; #'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';

## Error Page
  error_page 400                            /page/400.html;
  error_page 401                            /page/401.html;
  error_page 403                            /page/403.html;
  error_page 404                            /page/404.html;
  error_page 502                            /page/502.html;
  error_page 504                            /page/504.html;
  error_page 506                            /page/506.html;
  error_page 497                            https://$host:$Server_port$request_uri?error=$host:$Server_port;

vim /usr/local/nginx/conf/nginx.conf

worker_processes                            2;
worker_cpu_affinity                         01 10;
worker_rlimit_nofile                        65535;

events{
  use                                       epoll;
  multi_accept                              on;
  accept_mutex                              on;
  worker_connections                        512;
}
http{
include                                     /etc/nginx/conf/page/mime.types;
default_type                                application/octet-stream;
server_names_hash_bucket_size               128;
client_header_buffer_size                   32k;
large_client_header_buffers                 4 32k;
client_max_body_size                        50m;
sendfile                                    on;
tcp_nopush                                  on;
tcp_nodelay                                 on;
index                                       index.html;
charset                                     utf-8;

proxy_connect_timeout                       3s;
proxy_read_timeout                          10s;
proxy_send_timeout                          30s;

keepalive_timeout                           60;
keepalive_requests                          1000;
fastcgi_connect_timeout                     300;
fastcgi_send_timeout                        300;
fastcgi_read_timeout                        300;
fastcgi_buffer_size                         64k;
fastcgi_buffers 64                          64k;
fastcgi_busy_buffers_size                   128k;
fastcgi_temp_file_write_size                256k;
fastcgi_intercept_errors                    on;

gzip                                        on;
gzip_comp_level                             6;
gzip_min_length                             1k;
gzip_types                                  text/plain text/css text/xml text/javascript text/x-component application/json application/javascript application/x-javascript application/xml application/xhtml+xml application/rss+xml application/atom+xml application/x-font-ttf application/vnd.ms-fontobject image/svg+xml image/x-icon font/opentype;
gzip_disable                                "MSIE [1-6].(?!.*SV1)";
gzip_vary                                   on;
gzip_proxied                                any;

log_format log_json
  '{"timestamp":"$time_iso8601",\n'
  '"response_time": "$upstream_response_time",\n'
  '"remote_addr":"$remote_addr",\n'
  '"http_x_forwarded_for":"$http_x_forwarded_for",\n'
  '"request_status":"$request_method-$status-$http3",\n'
  '"request_url":"$scheme://$host:$Server_port$request_uri",\n'
  '"referer":"$http_referer",\n'
  '"user_agent":"$http_user_agent",\n'
  '"request_body":"$request_body"\n'
  '},';
# log_format log_quic '$remote_addr - $remote_user [$time_local] '
#   '"$request" $status $body_bytes_sent '
#   '"$http_referer" "$http_user_agent" "$http3"';

access_log /etc/nginx/conf/logs/today_nginx.json log_json;
include /etc/nginx/*.conf;
}

其他: 在编译之前可以修改自定义服务器名称

  1. 修改Nginx 内部名称 vim src/core/nginx.h

#define nginx_version      20447
#define NGINX_VERSION      "16.3 (20D74)"
#define NGINX_VER          "iOS " NGINX_VERSION

  1. 修改 HTTP Response Header vim src/http/ngx_http_header_filter_module.c

static u_char ngx_http_server_string[] = "Server: iOS" CRLF;

  1. 修改错误页的底部 Footer vim src/http/ngx_http_special_response.c

static u_char ngx_http_error_tail[] =
"<hr><center>iOS 16.3 (20D47)</center>" CRLF
"</body>" CRLF
"</html>" CRLF
;

其他: 每日自动日志分割

vim /etc/nginx/conf/shell/cutlog.sh

#!/bin/sh
# 使用 /etc/crontab 每天零点切割日志并重启
# 0 0 * * * root /etc/nginx/conf/shell/cutlog.sh
systemctl stop nginx

touch "/usr/local/nginx/logs/error.log"
touch "/etc/nginx/conf/logs/today_nginx.json"
touch "/etc/nginx/conf/logs/today_zhuihoude.json"

mv "/usr/local/nginx/logs/error.log"           "/etc/nginx/conf/logs/$(date -d "yesterday" +%G.%m.%d)_error.log"
mv "/etc/nginx/conf/logs/today_nginx.json"     "/etc/nginx/conf/logs/$(date -d "yesterday" +%G.%m.%d)_nginx.json"
mv "/etc/nginx/conf/logs/today_zhuihoude.json" "/etc/nginx/conf/logs/$(date -d "yesterday" +%G.%m.%d)_zhuihoude.json"

systemctl start nginx

其他: acme.sh 申请证书 (腾讯云 DNSPOD)

# Git安装 #其他方法参阅 https://github.com/acmesh-official/acme.sh 

git clone https://github.com/acmesh-official/acme.sh.git
cd ~/.acme.sh/
./acme.sh --install -m justroylau@gmail.com

#
# #DNSPOD 颁发证书
## 设定密钥 获取方法(头像 - 我的账号 - 账号中心 - API密钥 - DNSPod Token - 创建密钥)
export DP_Id="123456"
export DP_Key="自己去查看吧"
## 其他 DNS 供应商查询 https://github.com/acmesh-official/acme.sh/wiki/dnsapi

#
# 可以申请泛域名(*)证书哦
./acme.sh --issue --dns dns_dp -d zhuihoude.cn -d zhuihoude.com -d *.zhuihoude.cn -d *.zhuihoude.com

#
# 等待大约两分钟后…
cd ~/.acme.sh/zhuihoude.cn/
## 两个文件就到手啦~ 建议直接使用 fullchain.cer 包含了完整的证书链
~/.acme.sh/zhuihoude.cn/fullchain.cer
~/.acme.sh/zhuihoude.cn/zhuihoude.cn.key

其他: 群晖动态 DDNS

群晖自带 DDNS 支持泛域名
但是前端限制了 * 符号的无法提交,可以直接 POST 到后台 (GET好像也行)。

Post 接口 https://zhuihoude.synology.me:5001/webapi/entry.cgi

## 首先获取浏览器 F12 的 Request Headers 三个就够
x-requested-with:XMLHttpRequest
x-syno-hash:GrkQhxoP31TF4g-1ii_6Qzz-oYc2_g.MTY0
x-syno-token:xYlNn9NhDQgtA

#### Post 的 Form Data,(具体参数可以直接浏览器 F12 去复制 只需要改域名就行)
#### 可以用 Chrome 插件 Postwoman 来发送请求 
stop_when_error:true
mode:"sequential"
compound:[{"api":"SYNO.Core.DDNS.Record","method":"set","version":1,"id":"DNSPod.cn","enable":true,"provider":"DNSPod.cn","hostname":"这个是域名*.zhuihoude.com","username":"这个也是 腾讯云 DNS POD的","net":"DEFAULT","ip":"124.227.92.77","ipv6":"0:0:0:0:0:0:0:0","heartbeat":false,"passwd":"这个是腾讯云DNS POD 的"},{"api":"SYNO.Core.DDNS.Record","method":"update_ip_address","version":1,"id":"DNSPod.cn"}]
api:SYNO.Entry.Request
method:request
version:1


[HTTP3/QUIC] Debian 编译 NGINX_QUIC ,支持 HTTP3 QUIC的评论 (共 条)

分享到微博请遵守国家法律