http2 技術整理 nginx 搭建 http2 wireshark 抓包分析 server push 服務端推送


使用 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 。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM