对于Nginx来说,在编译时需要配置对于的SSL库,不管是HTTP3.0还是HTTP2.0,始终都要基于HTTPS,而加密算法这块主要有OpenSSL来提供,而BoringSSL是谷歌创建的OpenSSL分支,用于支持TLS1.3的UDP协议0-RTT数据传输的加密算法(可以理解成TLS 1.3是标准协议,BoringSSL是实现工具),BoringSSL的一些特性会在合适的时机同步给OpenSSl。Nginx从1.25.0开始支持QUIC和HTTP/3协议。此外,从1.25.0开始,Linux二进制包中提供了QUIC和HTTP/3支持
QUIC和HTTP/3支持是实验性的
安装BoringSSL证书
官方推荐了3种SSL库,参考文档https://nginx.org/en/docs/quic.html
我这里使用BoringSSL
- 使用 BoringSSL 编译 NGINX,需要满足以下要求:
gcc 版本大于6 - 编译BoringSSL 需要go环境支持
- cmake 3版本以上
升级cmake:
workon py_env
#yum install ninja-build
pip install -U cmake
升级gcc至8:
添加源:
1 2 3 4 5 6 7 8 |
vi /etc/yum.repos.d/CentOS-SCLo-scl.repo [centos-sclo-sclo] name=CentOS-7 - SCLo sclo baseurl=http://mirror.centos.org/centos/7/sclo/$basearch/rh/ #mirrorlist=http://mirrorlist.centos.org?arch=$basearch&release=7&repo=sclo-sclo gpgcheck=0 enabled=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-SIG-SCLo |
yum install devtoolset-8
激活:source /opt/rh/devtoolset-8/enable
此时通过gcc –version命令可以看到,gcc版本已经变成8.x.x,值得注意的是这仅仅在当前bash生效,如果需要永久生效,可以请自行添加环境变量。
golang安装:
wget https://golang.google.cn/dl/go1.21.4.linux-amd64.tar.gz
tar -C /usr/local/ -zxvf go1.21.4.linux-amd64.tar.gz
拉取BoringSSL源码
git clone https://github.com/google/boringssl.git
编译BoringSSL
1 2 3 4 5 6 |
cd boringssl # 建立一个专门用于编译的文件夹 mkdir build cd build cmake -GNinja .. ninja |
其中在执行cmake -GNinja .. 时,有如下报错:
cmake: Could NOT find Threads (missing: Threads_FOUND) 解决办法
在CMakeLists.txt最上面添加如下语句:
1 2 3 4 5 |
set(CMAKE_THREAD_LIBS_INIT "-lpthread") set(CMAKE_HAVE_THREADS_LIBRARY 1) set(CMAKE_USE_WIN32_THREADS_INIT 0) set(CMAKE_USE_PTHREADS_INIT 1) set(THREADS_PREFER_PTHREAD_FLAG ON) |
重新编译,即可编译通过。
参考链接: https://github.com/alicevision/geogram/issues/2
Brotli
Brotli是一种通用无损压缩算法,在Nginx模块中和Gzip都是压缩文件的一种方式,不同的是Brotli专为Web设计,对于Web数据压缩效率更高,甚至压缩效果比Gzip更小。Brotli配置和Gzip配置可以共存,无需删除原有的配置
1 2 3 4 5 |
git clone --recursive https://github.com/google/ngx_brotli.git cd ngx_brotli/deps/brotli/ mkdir out && cd out cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_FLAGS="-Ofast -m64 -march=native -mtune=native -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_CXX_FLAGS="-Ofast -m64 -march=native -mtune=native -flto -funroll-loops -ffunction-sections -fdata-sections -Wl,--gc-sections" -DCMAKE_INSTALL_PREFIX=./installed .. cmake --build . --config Release --target brotlienc |
编译安装
服务器使用LNMP作为Web管理后端,所以这里介绍如何修改LNMP的脚本达到一键升级的方法。
首先打开lnmp的主目录,修改如下脚本/path/to/lnmp2.0-full/include/upgrade_nginx.sh
安装依赖:yum install pcre-devel
修改:
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 |
./configure \ --user=www \ --group=www \ --prefix=/usr/local/nginx \ --with-http_stub_status_module \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_gzip_static_module \ --with-http_sub_module \ --with-stream \ --with-stream_ssl_module \ --with-http_realip_module \ \ --with-debug \ --add-module=../ngx_security_headers \ --add-module=../ngx_brotli \ --with-pcre \ --with-pcre-jit \ --with-http_mp4_module \ --with-ld-opt=-Wl,-E \ --with-cc-opt=-Wno-error \ --with-ld-opt=-ljemalloc \ --with-http_dav_module \ --with-http_v3_module \ --with-cc-opt=-I../boringssl/include \ --with-ld-opt='-L../boringssl/build/ssl -L../boringssl/build/crypto' |
注意:
从中间/下面开始是我添加的部分,注意要把脚本里原来带的–with-openssl 参数去掉,需要注意 BoringSSL 的路径,要指向上一步的使用的 boringSSL 路径,prefix修改为编译后nginx二进制链接到的位置,然后保存退出;
使用lnmp脚本运行./upgrade.sh nginx,选择nginx版本时填写1.25.3,等待编译完成。
nginx配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
server { listen 443 ssl; listen 443 quic reuseport; http3 on; http3_hq on; quic_retry on; ssl_early_data on; quic_gso on; charset utf-8; server_name xxx.com; # Quic或HTTP/3响应头 add_header Alt-Svc 'h3=":443"; ma=86400'; # HSTS add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"; #证书路径 ssl_certificate /you/path/fullchain.pem; #私钥路径 ssl_certificate_key /you/path/privkey.pem; #安全链接可选的加密协议 ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; |
参数解释
- listen 443 quic reuseport; #开启quic协议
- listen 443 ssl; #开启http2协议
- ssl_certificate ssl/apisix.frps.fun.crt; #证书上传路径
- ssl_certificate_key ssl/apisix.frps.fun.key;
- ssl_protocols TLSv1.3; # QUIC requires TLS 1.3 #支持tls协议1.3
- add_header Alt-Svc ‘h3=”:443″; ma=86400’; #请求头添加quic协议
注意:
- 关键配置2个,对于第二行listen 443 quic reuseport;,如果有多个server复用端口选项只需要在任意一个server里面填写就好了。对于第一行,其他的server也需要。
- 下面的选项为可选项,默认可以不加,具体可以参考官方文档。
http3 on;
http3_hq on;
quic_retry on;
ssl_early_data on;
quic_gso on;
nginx.conf:
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
user www www; #worker_processes auto; worker_processes 1; worker_cpu_affinity auto; error_log /data/logs/nginx/nginx_error.log crit; pid /usr/local/nginx/logs/nginx.pid; #Specifies the value for maximum file descriptors that can be opened by this process. worker_rlimit_nofile 51200; events { use epoll; worker_connections 1024; multi_accept off; accept_mutex off; } http { include 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; sendfile_max_chunk 512k; tcp_nopush on; keepalive_timeout 65; tcp_nodelay on; #为网站添加安全响应头并移除不安全响应,需编译 nginx 时添加 ngx_security_headers 模块 security_headers on; #如果缓存多站点则把下面四行放到nginx.conf中 fastcgi_cache_path /var/cache/nginx/fastcgi_cache levels=1:2:1 keys_zone=WORDPRESS:500m max_size=5g inactive=1d; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header http_500; #忽略一切nocache申明,避免不缓存伪静态等 fastcgi_ignore_headers Cache-Control Expires Set-Cookie; #Ps:如果是多个站点,以上内容不要重复添加,否则会冲突,可以考虑将以上内容添加到nginx.conf里面,避免加了多次 fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 256k; proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=http-cache:800m max_size=10g inactive=60m; proxy_redirect off; #proxy_set_header Host $http_host; #proxy_set_header X-Real-IP $remote_addr; #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffer_size 16k; proxy_buffers 4 16k; proxy_busy_buffers_size 16k; proxy_temp_file_write_size 128k; #use_temp_path off; gzip on; gzip_static on; gzip_min_length 1k; gzip_buffers 4 16k; #gzip_http_version 1.1; gzip_comp_level 6; gzip_types text/plain text/css application/javascript text/javascript application/x-javascript text/xml application/xml application/xml+rss application/json; gzip_vary on; gzip_proxied expired no-cache no-store private auth; gzip_disable "MSIE [1-6]\."; # 启用压缩 brotli on; #是否允许查找预处理好的以 .br 结尾的压缩文件。可选值为 on、off、always brotli_static always; # 压缩的文件类型 brotli_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript image/svg+xml; # 压缩质量 brotli_comp_level 6; # 允许压缩的最小大小 brotli_min_length 20; limit_conn_zone $binary_remote_addr zone=perip:10m; #If enable limit_conn_zone,add "limit_conn perip 10;" to server section. server_tokens off; #log_format main '$remote_addr|$http_x_real_ip|$remote_user|[$time_local]|"$request"' # '$status|$body_bytes_sent|"$http_referer"' # '"$http_user_agent"|"$http_x_forwarded_for"'; log_format main '$remote_addr|$remote_user|[$time_local]|"$request"' '$status|$body_bytes_sent|"$http_referer"|"$http_user_agent"|"$http3"'; access_log off; #所有访问跳转至 HTTPS server { listen 80 default_server; listen [::]:80 default_server; location / { return 301 https://$host$request_uri; } } include vhost/*.conf; } |
后续配置
检查相关端口号及服务
lsof -i:443
Nginx防火墙相关策略需要开启UDP/TCP协议:
-A INPUT -m state –state NEW -m tcp -p tcp –match multiport –dports 80,443 -j ACCEPT
-A INPUT -m state –state NEW -m udp -p udp –dport 443 -j ACCEPT
测试:
Chrome 浏览器可以访问 chrome://flags,搜索 quic 开启 QUIC 支持
浏览器启用后,可以通过这个 URL 进行测试,页面上会提示你的浏览器是否可以使用 QUIC
测试自建网站浏览器需要在没有缓存的情况下测试
验证是否开启Brotli
使用命令查看或者在浏览器用Network查看
运行命令:
curl -H ‘Accept-Encoding: br’ -I https://meaninglive.com
Content-Encoding:br 证明内容正确的被Brotli压缩
ETag:W/”63751040-124b” 前面的W代表是服务端压缩,没有就是前端打包压缩
下面是网站安全测试:https://www.ssllabs.com/ssltest/analyze.html
另:我的网站安全是A,不是A+, 需要dns配置CAA解析, 但是注册域名的网站不支持CAA,所以无法配置。具体配置方法可参考如下文章:
总结
现有网络环境错综复杂,网站如果使用 HTTP,访问的用户会存在很高的安全隐患,导致信息泄露、木马植入等情况出现。针对这一情况,为互联网提供安全服务而采用 HTTPS 已是大势所趋。HTTP 到 HTTPS 的转向可以帮助提升用户访问安全水平,所以推荐大家也加强个人网站的 SSL 安全等级。
参考:
https://winkkie.com/archives/%E9%87%8D%E6%96%B0%E7%BC%96%E8%AF%91nginx%E5%90%AF%E7%94%A8http3%E5%8D%8F%E8%AE%AE
https://blog.51cto.com/juestnow/4977550
配置 nginx.conf 实现 A+ 等级的 SSL 安全评级 : https://vickey.fun/2022/03/21/enable-https-to-get-A-rating-in-SSLLabs/
网速测试:https://cxlm.work/archives/nginxquictest
0 Comments