使用 nginx 搭建一個 http2 的站點,准備所需:
1,域名 .com .net 均可(國內域名需要 icp 備案)
2,雲主機一個,可以自由的安裝配置軟件的服務器
3,https 證書
http2 基於 https ,所以先配置好 https 訪問
本文以 CentOS 6.5 (以下教程針對有 linux 使用基礎的人,本文不會介紹 ,安裝 編譯環境,yum 軟件包,這種基礎的東西)
購買 https 證書,淘寶上就可以買,價格幾十到幾千不等。
使用源碼編譯安裝 nginx http://nginx.org/en/download.html
使用目前的最新版 nginx-1.14.2.tar.gz
nginx http2 模塊支持,需要用到 >= openssl 1.0.2 http://nginx.org/en/docs/http/ngx_http_v2_module.html
先下載一個 openssl-1.0.2j.tar.gz 解壓
開始編譯 nginx 並啟用 ssl http2 模塊
./configure --with-debug --with-http_ssl_module --with-http_v2_module --prefix=/usr/local/nginx/ --with-openssl=/home/openssl-1.0.2j
make && make install
運行 nginx -V 查看版本及支持
/usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.14.2
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
built with OpenSSL 1.0.2j 26 Sep 2016
TLS SNI support enabled
配置 ssl http2
/usr/local/nginx/conf/ssl
將購買的證書放到這里
xxx.com.key xxx.com.pem
nginx.conf
listen 443 ssl http2; # 1.1版本后這樣寫 server_name www.xxx.com; #填寫綁定證書的域名 ssl_certificate /usr/local/nginx/conf/ssl/xxx.com.pem; # 指定證書的位置,絕對路徑 ssl_certificate_key /usr/local/nginx/conf/ssl/xxx.com.key; # 絕對路徑,同上 ssl_session_timeout 5m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; #按照這個協議配置 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;#按照這個套件配置 ssl_prefer_server_ciphers on;
使用 火狐瀏覽器訪問(火狐可以更好的顯示出來頭信息)
添加 php7 fpm 支持
apache2.4 http2 支持
./configure 時添加參數 --enable-http2 --with-ssl=/usr/local/openssl1.0.2
修改 httpd.conf
LoadModule http2_module modules/mod_http2.so
在已經配置好 https 的基礎上添加
<VirtualHost _default_:443>
Protocols h2 http/1.1
使用 wireshark 抓包分析
有2種方法
1,使用 瀏覽器導出 TLS 信息,即可解碼,比較簡單不做介紹
2,使用服務器私鑰解密,優點是不依賴瀏覽器,普通程序也可以解密,如使用 libcurl okhttp 加密TLS流量
先配置 RSA keys list ,添加上服務器私鑰。
IIS .pfx 格式證書需要填寫密碼
Nginx Apache .key 格式證書不需要密碼
Tomcat .jks 格式證書不支持,需要轉換為 .key
然后打開瀏覽器訪問站點,查看分析數據包,已解密
使用 tcpdump 抓包 tcp 並保存為文件
tcpdump tcp -s 0 -c 1000 -w http2.cap
運行 curl 測試程序 后使用 wireshark 進行分析
linux 上面的 curl 不支持 http2 ,ubuntu 18 已經支持了。如果不支持,需要先編譯安裝 ngnttp2 這個庫以后,在編譯安裝新版的 curl 即可支持。
win 方便的 curl 測試工具非常方便,其實就是大名鼎鼎的 git windows 客戶端 https://git-scm.com/download/win 安裝后,打開 Git Bash 輸入 curl -V
$ curl -V curl 7.61.1 (i686-w64-mingw32) libcurl/7.61.1 OpenSSL/1.0.2p (WinSSL) zlib/1.2.11 libidn2/2.0.5 nghttp2/1.33.0 Release-Date: 2018-09-05 Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp Features: AsynchDNS IDN IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz TLS-SRP HTTP2 HTTPS-proxy MultiSSL Metalink
curl 發送 post :
curl https://www.xxx.com/test_post.php -X POST -d "title=comewords&content=articleContent"
curl 發送 json post:
https://www.xxx.com/test_post.php -H "Content-Type:application/json" -X POST -d '{"title":"comewords","content":"articleContent"}'
curl 上傳文件:
curl http://www.xxx.com/test_post.php -F "file1=@1.txt" -F "file2=@2.txt"
HTTP2 協議詳解
使用 window git bash 中的 curl 進行測試 使用不同的 --http1.1 --http2 協議
頭信息
Header: :method: GET Header: :path: / Header: :scheme: https Header: :authority: www.xxx.com Header: user-agent: curl/7.61.1 Header: accept: */*
頭信息多了幾個,同時也少了一些東西,對比 HTTP1.1
GET / HTTP/1.1\r\n Host: www.xxx.com\r\n User-Agent: curl/7.61.1\r\n Accept: */*\r\n
服務器推送 server push
使用 nginx 配置服務器推送
#server push location /push/index.html { http2_push /push/1.css http2_push /push/2.css }
當訪問 /push/index.html 時推送2個 css 。
使用 chrome 訪問。
使用 nghttp 進行測試
先安裝 sudo apt-get install nghttp2-client
nghttp -ans https://www.xxx.com/push/index.html
id responseEnd requestStart process code size request path 13 +6.17ms +166us 6.00ms 200 251 /push/index.html 2 +6.53ms * +5.58ms 946us 200 60 /push/1.css 4 +6.63ms * +5.79ms 840us 200 12 /push/2.css
重點 http2 連接復用
利用 http2 連接可以復用的支持,可以實現 HTTP 長連接,類似於 HTML5 WebSocket ,服務端可以向客戶端推送消息,不必每次建立連接。
服務端如何實現:
和PHP實現文件限速下載,比較類似,每次只讀一定的長度,在做 sleep ,就實現了限速下載,下載一個文件可能要一天時間。
實現好了,效果如下,每3秒鍾,輸出當前時間
http2 ping
ALPN 在 SSL hello 時發送
Server Hello
openssl 支持 ALPN 的方法,較簡單,版本要求 >= 1.0.2
const unsigned char *alpn = NULL; unsigned int alpnlen = 0; SSL_get0_next_proto_negotiated(ssl, &alpn, &alpnlen); SSL_get0_alpn_selected(ssl, &alpn, &alpnlen);
http2 流量控制
首次服務器發送 window_update 有幾個設置。
frame size 16k / windows size 64k
當客戶端從服務器接收一個流時,服務器會檢查協商的 window 大小,當大小不足時,就不在發送數據,這時客戶端需要更新 window 大小。如上圖所示,初始值是 64K 當客戶端接收的數據達到這個值時,則需要更新 window 。
window 更新為 32768 則 32k 。服務器收到后,更新 window 大小,又可以繼續下發流了。這里有2次更新,對應2個 stream id 。