安装boringSSL:
git clone https://boringssl.googlesource.com/boringssl
cd boringssl
mkdir build
cd build
cmake ..
碰到的问题是cmake版本过低
卸载旧版本的CMake
如果通过包管理器安装了CMake,可以先卸载旧版本:
sudo apt remove cmake
然后安装更新版本的CMake,从CMake官网安装
-
下载CMake最新版本: 打开CMake官网并下载适合您系统的二进制文件。例如:
wget https://github.com/Kitware/CMake/releases/download/v3.27.0/cmake-3.27.0-linux-x86_64.sh
-
安装CMake:
-
为安装文件添加执行权限:
chmod +x cmake-3.27.0-linux-x86_64.sh
-
运行安装脚本:
sudo ./cmake-3.27.0-linux-x86_64.sh --prefix=/usr/local --skip-license
-
然后更新环境变量
在~/.bashrc
中添加
export PATH=/usr/local/bin:$PATH
保存后重新加载配置文件
source ~/.bashrc # 如果使用 Bash
再次验证CMake 版本,cmake —version
接下来接着构建boringssl
cmake ..
make
碰到这个报错
/boringssl/ssl/internal.h:3549:39: error: ‘bssl::DTLS1_STATE::queued_key_update’ is too small to hold all values of ‘enum class bssl::QueuedKeyUpdate’ [-Werror]
QueuedKeyUpdate queued_key_update : 2;
^
查看枚举类型:
enum class QueuedKeyUpdate {
kNone,
kUpdateNotRequested,
kUpdateRequested,
};
最后boringssl安装参考这篇文章:
https://blog.csdn.net/liulilittle/article/details/141298738
不过这一步要在build中进行
cmake . && make
nginx-quic配置排查错误过程:
首先需要配置自签名证书:
- 生成 CA
openssl genrsa -out ca.key 2048 openssl req -x509 -new -nodes -key ca.key -subj "/CN=My CA" -days 3650 -out ca.crt
- 生成服务器密钥和 CSR
#video.local是本地域名
openssl genrsa -out server.key 2048 openssl req -new -key server.key -out server.csr -subj "/CN=video.local"
- 创建扩展文件:
echo "subjectAltName = DNS:video.local,IP:192.168.2.2" > server.ext
- 签署证书:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -extfile server.ext
- 生成证书链:
cat server.crt ca.crt > chain.crt
- 验证:
openssl x509 -in server.crt -text -noout
确认 Subject: CN=video.local, X509v3 Subject Alternative Name: DNS:video.local, IP Address:192.168.2.2.
cat chain.crt
确认包含两段 -----BEGIN CERTIFICATE-----
配置了自签名证书后更新nginx设置:
server {
listen 443 ssl;
listen 443 quic reuseport;
listen [::]:443 ssl;
listen [::]:443 quic reuseport;
http2 on;
http3 on;
server_name video.local;
add_header Alt-Svc 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000';
error_log /var/log/nginx/video.local.error.log debug; # 指定一个文件并设置级别为 info
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
add_header Alt-Svc 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000';
add_header Access-Control-Allow-Methods "GET,OPTIONS,POST,HEAD,PUT,DELETE";
add_header Accept-Ranges "bytes";
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Expose-Headers "Content-Lengrh,Content-Range,Date,Server,Transfer-Encoding,origin,range,x-goog-meta-foo1";
}
ssl_certificate path/key/chain.crt;
ssl_certificate_key path/key/server.key;
#error_page 404 /404.html;
ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers off;
# 添加QUIC特定配置
ssl_early_data on;
quic_retry on;
quic_gso on;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
重载 nginx:
sudo /usr/local/nginx/sbin/nginx -s stop
sudo /usr/local/nginx/sbin/nginx
复制证书到客户端(macos):
scp -P 22 cc@<ip addr>:path/ca.crt /Users/desktop
复制了后将ca.crt导入钥匙链中。
在配置好这些后,nginx-quic的基本配置就结束了,但是启动chrome或者firefox访问网页发现仍然是http2连接,下面是发现错误并步步排查错误并解决的过程:
启用http3连接
- 使用wireshark抓包:
查找条件:udp.port == 443
可以看到有quic尝试握手的报文
CONNECTION_CLOSE (Transport) Error code: CRYPTO_ERROR (Certificate Unknown)
主要到这提到了Certificate Unknown
- 使用 curl访问
#在docker中验证
cris@Cris % docker exec -u root -it <镜像id> sh -c 'echo "192.168.2.2 video.local" >> /etc/hosts'
curl -v --http3 https://video.local
可以看到:
SSL certificate problem: self signed certificate in certificate chain
* connect to 192.168.2.2 port 443 failed: SSL peer certificate or SSH remote key was not OK
curl: (60) SSL certificate problem: self signed certificate in certificate chain
This indicates that the certificate is either self-signed or signed by an untrusted Certificate Authority (CA), in this case, CN=My CA. The -k flag allows curl to ignore this issue, but other clients (like browsers) typically enforce stricter validation, leading to a CERTIFICATE_VERIFY_FAILED error during the QUIC handshake.也就是说证书是自签名证书,浏览器可能执行更严格的验证导致无法握手。
- 查看nginx错误日志
[info] 32575#0: *47 SSL_do_handshake() failed (SSL: error:10000418:SSL routines:OPENSSL_internal:TLSV1_ALERT_UNKNOWN_CA:SSL alert number 48) while SSL handshaking, client: 192.168.2.1, server: 0.0.0.0:443`
通过上述三点可以确问题:SSL/TLS 证书验证问题
解决问题方法
在寻找多种解决问题方法后,找到了最简单的解决方法:
google文档中说明了(Playing with QUIC):
Note that the server’s certificate must be trusted by a default CA for Chrome/Chromium to accept it for QUIC. If you are using a self-signed certificate or a certificate that is signed by a custom CA, you need to use the --ignore-certificate-errors-spki-list
command line flag to trust an individual certificate based on its SPKI. It is not possible to trust a custom CA using this flag. If you wish to deploy a MITM proxy that intercepts traffic, you need to block QUIC entirely and intercept TLS instead.
最后使用这行命令打开chrome成功完成了http3连接:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \ --user-data-dir=/tmp/chrome-profile \ --no-proxy-server \ --enable-quic \ --origin-to-force-quic-on=video.local:443 \ --ignore-certificate-errors-spki-list=<指纹id> \ <要打开的网页链接>
其中这个指纹id的获取方式是:
`openssl x509 -in /path/to/server.crt -pubkey -noout | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64`