在Nginx中支持HTTP3.0/QUIC
HTTP3.0,也稱做HTTP over QUIC。核心是QUIC(讀音quick)協議,由Google在2015年提出的SPDY v3演化而來的新協議,傳統的HTTP協議是基於傳輸層TCP的協議,而QUIC是基於傳輸層UDP上的協議,能夠定義成:HTTP3.0基於UDP的安全可靠的HTTP2.0協議,主要有如下特性:linux
-
基於UDP減小了TCP三次握手及TLS握手時間 -
解決多路複用丟包時的線頭阻塞問題 -
優化重傳策略 -
流量控制 -
鏈接遷移
本文主要講解一下如何在Nginx中開啓HTTP3.0的支持。nginx
方案選擇
對於HTTP3.0,因爲整個協議仍是處於草案階段,目前來講沒有一個完整的標準,因此各大瀏覽器廠商還只是在開發者版本中才會支持,例如Chrome的金絲雀版本Chrome Canary[1],而且各個服務器廠商也是在持續跟進中,對於Nginx來講,支持HTTP3.0目前有兩種方案能夠選擇:c++
-
基於Cloudflare的分支版本Nginx:對於HTTP3.0/QUIC,Cloudflare始終走在了前列,藉助於自家維護的開源項目 quic [2],從Nginx中拉出了一個分支來開發,並編譯出了對HTTP3.0支持的Nginx服務器。 -
Nginx官方Nginx-quic項目:今年6月10日,Nginx 官博 [3]發佈公告稱已經在研發支持HTTP3.0/QUIC協議的工做,目前項目維護在 nginx-quic [4],該項目和基於Cloudflare基於Nginx的分支並沒有關係,算是相對於正統的方案。
基於此,本文將會以部署nginx-quic的方式來讓Nginx支持HTTP3.0/QUIC。git
改造過程
咱們最終的目的是獲得nginx-quic版本的nginx可執行文件,須要通過一系列的安裝和編譯,期間可能會遇到不少問題,若是各位讀者不想實際操做,能夠直接用我編譯好的版本nginx-quic.linux-x86_64.zip 傳送門[5]。github
準備工做:
以centos7爲例,下載nginx-quic源碼傳送門[6],下載完成以後,須要進行編譯安裝,因爲nginx-quic依賴boringSSL,因此還需下載boringSSL源碼傳送門[7],而後一樣須要編譯安裝boringSSL,執行這些操做以前,須要在linux上安裝一些前置模塊,經過yum來安裝,執行如下命令:golang
sudo yum install build-essential mercurial psmisc lsb-release cmake golang libunwind-dev git libpcre3-dev zlib1g-dev
什麼是boringSSL:
對於Nginx來講,在編譯時須要配置對於的SSL庫,不論是HTTP3.0仍是HTTP2.0,始終都要基於HTTPS,而加密算法這塊主要有OpenSSL來提供,而BoringSSL是谷歌建立的OpenSSL分支,用於支持TLS1.3的UDP協議0-RTT數據傳輸的加密算法(能夠理解成TLS1.3是標準協議,BoringSSL是實現工具),BoringSSL的一些特性會在合適的時機同步給OpenSSl。web
編譯安裝boringSSL:
cd boringssl-master/
mkdir build
cd build
cmake ../
make
執行以後,能夠在build/crypto
,和build/ssl
下得到對應的文件,以下圖: 算法
注意編譯安裝boringSSL須要使用cmake3以上的版本。chrome
編譯安裝nginx-quic:
cd nginx-quic/
./auto/configure --prefix=/root/nginx --with-http_ssl_module --with-http_v2_module --with-http_v3_module --with-cc-opt="-I../boringssl-master/include" --with-ld-opt="-L../boringssl-master/build/ssl -L../boringssl-master/build/crypto"
make
make install
執行命令以後,會在/root/nginx
目錄下生成對應的nginx可執行文件,以下圖:centos
其中,配置文件在conf/
下,nginx命令在sbin/
目錄下。
修改配置文件,啓動nginx:
vi /root/nginx/conf/nginx.conf
添加http3配置:
server {
listen 443 ssl http2; # TCP listener for HTTP/2
listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3
ssl_protocols TLSv1.3; # QUIC requires TLS 1.3
ssl_certificate ssl/www.example.com.crt;
ssl_certificate_key ssl/www.example.com.key;
add_header Alt-Svc 'quic=":443"; h3-27=":443";h3-25=":443"; h3-T050=":443"; h3-Q050=":443";h3-Q049=":443";h3-Q048=":443"; h3-Q046=":443"; h3-Q043=":443"'; # Advertise that QUIC is available
}
其中,要求使用TLSv1.3版本,而且當瀏覽器不支持http3時,能夠選擇http2。另外,add_header Alt-Svc
添加這個返回頭不可缺乏。
-
Alt-Svc 全稱爲「Alternative-Service」,直譯爲「備選服務」。該頭部列舉了當前站點備選的訪問方式列表,讓服務器能夠告訴客戶端 「看,我在這個主機的這個端口用這個協議提供相同的服務」。通常用於在提供 「QUIC」 等新興協議支持的同時,實現向下兼容。參考 MDN [8]。
驗證HTTP3生效:
因爲目前瀏覽器對HTTP3.0/QUIC的支持性有限,能夠經過http3check.net/[9]來驗證站點啓用HTTP3是否成功,以個人站點爲例:
坑點總結
整個過程看似很簡單,可是真正配置過程當中遇到了很多坑,前先後後加上搜索問題花了一天半的時間才真正解決,把這些問題記錄下來,分享給你們。
開啓UDP的443端口:
因爲quic協議使用的是UDP的443端口,這個端口對於centos7來講是默認關閉的,能夠採用下面命令開啓:
firewall-cmd --zone=public --add-port=443/udp --permanent
若是項目託管在阿里雲上,須要更新ECS的安全組策略來對外開啓對應的協議和端口,以下圖:
TLS版本向下兼容:
因爲使用了TLS 1.3,因此會修改對應加密算法,可是對於一些瀏覽器而言還不支持這麼高的版本,尤爲是對於蘋果的Safari,因此,在配置nginx配置文件時,要多配置幾個版本向下兼容,代碼以下:
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
-Werror錯誤問題:
在編譯nginx-quic時,有時會遇到以下錯誤:
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
-o objs/src/os/unix/ngx_linux_sendfile_chain.o \
src/os/unix/ngx_linux_sendfile_chain.c
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
-o objs/src/event/ngx_event_openssl.o \
src/event/ngx_event_openssl.c
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
-o objs/src/event/ngx_event_openssl_stapling.o \
src/event/ngx_event_openssl_stapling.c
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
-o objs/src/event/ngx_event_quic.o \
src/event/ngx_event_quic.c
cc -c -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
-o objs/src/event/ngx_event_quic_transport.o \
src/event/ngx_event_quic_transport.c
src/event/ngx_event_quic_transport.c: In function ‘ngx_quic_create_stream’:
src/event/ngx_event_quic_transport.c:54:9: error: comparison is always true due to limited range of data type [-Werror=type-limits]
: ((uint32_t) value) <= 16383 ? 2 \
^
src/event/ngx_event_quic_transport.c:1299:15: note: in expansion of macro ‘ngx_quic_varint_len’
len = ngx_quic_varint_len(sf->type);
^
cc1: all warnings being treated as errors
make[1]: *** [objs/src/event/ngx_event_quic_transport.o] Error 1
make[1]: Leaving directory `/root/nginx-quic'
make: *** [build] Error 2
[root@iz2zehmi1ztqtx8tg6ca7gz nginx-quic]#
解決辦法是:
cd nginx-quic\objs
vi Makefile
找到 CFLAGS = -pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -I../boringssl-master/include
將-Werror參數去掉。
reuseport只需配置一次:
假若有多個域名須要開啓http3,則reuseport建議只在根域名上配置,若是一個配置文件中出現多個reuseport,會報錯,配置以下:
server {
listen 443 ssl http2; # TCP listener for HTTP/2
listen 443 http3 reuseport; # UDP listener for QUIC+HTTP/3
server_name www.nihaoshijie.com.cn default_server;
}
server {
listen 443 ssl http2; # TCP listener for HTTP/2
listen 443 http3; # UDP listener for QUIC+HTTP/3
server_name app.nihaoshijie.com.cn;
}
編譯安裝時的性能問題:
若是編譯安裝時報相似下面的錯誤,多是主機的內容不足,須要關閉一些運行的程序來往下進行。
...
c++: internal compiler error: Killed (program cc1plus)
快開啓你的HTTP3之旅吧!
參考資料
Chrome Canary: https://www.google.cn/chrome/canary/
[2]cloudflare-quic: https://cloudflare-quic.com/
[3]introducing-technology-preview-nginx-support-for-quic-http-3: https://www.nginx.com/blog/introducing-technology-preview-nginx-support-for-quic-http-3/
[4]nginx-quic: https://hg.nginx.org/nginx-quic
[5]nginx-quic.linux-x86_64.zip: https://www.nihaoshijie.com.cn/mypro/nginx-quic.linux-x86_64.zip
[6]nginx-quic-source-code: https://hg.nginx.org/nginx-quic
[7]boringssl-code: https://github.com/google/boringssl
[8]MDN: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Alt-Svc
[9]http3check: https://http3check.net/?host=www.nihaoshijie.com.cn
原鏈:https://juejin.cn/post/6850418105462571021
本文分享自微信公衆號 - 雲原生生態圈(CloudNativeEcoSystem)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。