HTTP/2探索第二篇——工具及應用

版權聲明:本文由張浩然原創文章,轉載請註明出處: 
文章原文連接:https://www.qcloud.com/community/article/88css

來源:騰雲閣 https://www.qcloud.com/communityhtml

 

因爲不一樣環境過於複雜,本文僅基於Mac OS和Linux來說解工具及應用。python

一.HTTP/2環境搭建所需軟件概覽

本文須要安裝的軟件爲(Mac用戶請使用homebrew來安裝,括號裏都是Mac的安裝方式)linux

  • curl (brew install nghttp2 —with-nghttp2)
    Linux安裝
    wget https://curl.haxx.se/download/curl-7.48.0.tar.gz
    tar xvf curl-7.48.0.tar.gz && cd curl-7.48.0
    而後輸入如下命令,exit一次再進入而後版本是7.48就成功了:nginx

    $ ./configure --with-nghttp2=/usr/local --with-ssl
    $ make
    $ sudo make install
    $ ldconfig
    $ usr/local/bin/curl -V
  • nghttp2 (brew install nghttp2)
    安裝網址git

    sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \
    zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \
    libjemalloc-dev cython python3-dev python-setuptools

    上面是安裝依賴,以後就能夠編譯了:github

    $ autoreconf -i
    $ automake
    $ autoconf
    $ ./configure
    $ make
    $ sudo make install
    nginx (brew install nginx —devel)
  • nginx (brew install nginx —devel)
    Linux安裝
    vim到/etc/apt/sources.list
    增長如下兩行,其中$codename自行去該網站查詢,好比Ubuntu 14.04 是 trusty;web

    deb http://nginx.org/packages/mainline/ubuntu/ $codename nginx
    deb-src http://nginx.org/packages/mainline/ubuntu/ $codename nginx

    而後sudo apt-get update && sudo apt-get install nginx就能夠裝最新支持HTTP2的nginx啦;算法

  • apache (brew install httpd24 —with-http2)[本文重點講解nginx]
    Linux安裝shell

    二.證書

    1.自簽發

    打開提供的Demo文件,terminal打開/keys路徑,輸入./ca.sh http2test.com,也能夠生成其餘域名或泛域名(.xx.com).注意:也能夠不用生成證書,直接使用keys文件下提供的http2test.com證書;
    Let’s Encrypt
    打開Let’s Encrypt的官網,這裏講解若是已經啓動nginx的狀況下,如何簽發證書。
    步驟:

  • 首先須要把代碼克隆下來:git clone https://github.com/letsencrypt/letsencrypt && cd letsencrypt
  • 而後./letsencrypt-auto --help會執行一些初始化工做,而且顯示支持的命令;
  • 好比個人web目錄在~/www下,此步驟須要已搭建好服務器,而且能夠經過example.com訪問~/www裏的內容,若是是動態網站,須要在nginx層設置一個映射,將/.well-known/acme-challenge映射到剛設置好的目錄,也就是~/www

    location /.well-known/acme-challenge {   
    root /home/$username/www;
    }
  • (須要nginx已經裝好,沒裝好的完成下面的nginx部分後再回來設置)那麼./letsencrypt-auto certonly --webroot -w ~/www -d example.com,example.com是你但願申請證書的域名,而後證書下發成功。

  • 而後在nginx中設置證書信息

    ssl_certificate      /etc/letsencrypt/live/$example.com/fullchain.pem;  
    ssl_certificate_key  /etc/letsencrypt/live/$example.com/privkey.pem;
  • 而後sudo nginx -t && sudo nginx -s reload就能夠看到啦

3、基本工具

  • curl
    curl的基本用法是:
    curl -v -o /dev/null --http2 http://nghttp2.org
    這裏輸入的是HTTP而不是HTTPS是由於,這裏會採用HTTP2的ClearText模式,使用101 改變協議協商升級爲HTTP2協議。
Connected to nghttp2.org (106.186.112.116) port 80 (#0)> GET / HTTP/1.1> Host: nghttp2.org
> User-Agent: curl/7.48.0> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAAQAAP__>
< HTTP/1.1 101 Switching Protocols
< Connection: Upgrade
< Upgrade: h2c
* Received 101* Using HTTP2, server supports multi-use* Connection state changed (HTTP/2 confirmed)
* TCP_NODELAY set
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=21* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2.0 200< date:Sun, 10 Apr 2016 16:52:43 GMT
< content-type:text/html
< content-length:6646< last-modified:Sun, 03 Apr 2016 06:53:14 GMT
< etag:"5700bdda-19f6"< link:</stylesheets/screen.css>; rel=preload; as=stylesheet
< accept-ranges:bytes
< x-backend-header-rtt:0.000625< server:nghttpx nghttp2/1.10.0-DEV
< via:2 nghttpx
< x-frame-options:SAMEORIGIN
< x-xss-protection:1; mode=block
< x-content-type-options:nosniff
<

如今的大多數網站,都是經過302跳轉到HTTPS網站來協商升級的,例如我廠的QQ郵箱;

Connected to mail.qq.com (183.60.15.162) port 80 (#0)
> GET / HTTP/1.1
> Host: mail.qq.com> User-Agent: curl/7.48.0
> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAAQAAP__>
< 
HTTP/1.1 302 Found
< Server: TWS
< Connection: close
< Date: Sun, 10 Apr 2016 16:58:48 GMT
< Content-Type: text/html; charset=GB18030
< Location: https://mail.qq.com/cgi-bin/loginpage
< Content-Length: 0
<
  • nghttp
    官方文檔,安裝nghttp2後有配套的nghttp 客戶端、nghttpd 服務器、nghttpx 反向代理、h2load 負載測試等工具。
    輸入命令nghttp -nv https://nghttp2.org(n表明不輸出,v表明詳細信息):
    結果列出了鏈接過程當中的HTTP2各個Stream信息,例如SETTINGS Frame,HEADER Frame等,也能夠帶上參數:
[  0.170] Connected
The negotiated protocol: h2
[  0.732] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.732] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.732] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.732] send HEADERS frame <length=36, flags=0x25, stream_id=13>
          ; END_STREAM | END_HEADERS | PRIORITY
          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)
          ; Open new stream
          :method: GET
          :path: /
          :scheme: https
          :authority: nghttp2.org
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.9.1
[  0.891] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.891] recv (stream_id=13) :method: GET
[  0.891] recv (stream_id=13) :scheme: https
[  0.892] recv (stream_id=13) :path: /stylesheets/screen.css
[  0.892] recv (stream_id=13) :authority: nghttp2.org
[  0.892] recv (stream_id=13) accept-encoding: gzip, deflate
[  0.892] recv (stream_id=13) user-agent: nghttp2/1.9.1
[  0.892] recv PUSH_PROMISE frame <length=47, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0, promised_stream_id=2)
[  0.892] recv (stream_id=13) :status: 200
[  0.892] recv (stream_id=13) date: Sun, 10 Apr 2016 17:00:25 GMT
[  0.892] recv (stream_id=13) content-type: text/html
[  0.892] recv (stream_id=13) content-length: 6646
[  0.892] recv (stream_id=13) last-modified: Sun, 03 Apr 2016 06:53:14 GMT
[  0.892] recv (stream_id=13) etag: "5700bdda-19f6"
[  0.892] recv (stream_id=13) link: </stylesheets/screen.css>; rel=preload; as=stylesheet
[  0.892] recv (stream_id=13) accept-ranges: bytes
[  0.892] recv (stream_id=13) x-backend-header-rtt: 0.000663
[  0.892] recv (stream_id=13) strict-transport-security: max-age=31536000
[  0.892] recv (stream_id=13) server: nghttpx nghttp2/1.10.0-DEV
[  0.892] recv (stream_id=13) via: 2 nghttpx
[  0.892] recv (stream_id=13) x-frame-options: SAMEORIGIN
[  0.892] recv (stream_id=13) x-xss-protection: 1; mode=block
[  0.892] recv (stream_id=13) x-content-type-options: nosniff
[  0.892] recv HEADERS frame <length=266, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0)
          ; First response header
[  0.893] recv DATA frame <length=6646, flags=0x01, stream_id=13>
          ; END_STREAM
[  0.893] recv (stream_id=2) :status: 200
[  0.893] recv (stream_id=2) date: Sun, 10 Apr 2016 17:00:25 GMT
[  0.893] recv (stream_id=2) content-type: text/css
[  0.893] recv (stream_id=2) content-length: 39082
[  0.893] recv (stream_id=2) last-modified: Sun, 03 Apr 2016 06:53:14 GMT
[  0.893] recv (stream_id=2) etag: "5700bdda-98aa"
[  0.893] recv (stream_id=2) accept-ranges: bytes
[  0.893] recv (stream_id=2) x-backend-header-rtt: 0.000427
[  0.893] recv (stream_id=2) strict-transport-security: max-age=31536000
[  0.893] recv (stream_id=2) server: nghttpx nghttp2/1.10.0-DEV
[  0.893] recv (stream_id=2) via: 2 nghttpx
[  0.893] recv (stream_id=2) x-frame-options: SAMEORIGIN
[  0.893] recv (stream_id=2) x-xss-protection: 1; mode=block
[  0.893] recv (stream_id=2) x-content-type-options: nosniff
[  0.893] recv (stream_id=2) x-http2-push: 1
[  0.893] recv HEADERS frame <length=62, flags=0x04, stream_id=2>
          ; END_HEADERS
          (padlen=0)
          ; First push response header
[  1.407] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.563] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=33412)
[  1.740] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.741] recv DATA frame <length=6314, flags=0x01, stream_id=2>
          ; END_STREAM
[  1.741] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])

[  0.170] Connected
The negotiated protocol: h2
[  0.732] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.732] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.732] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.732] send HEADERS frame <length=36, flags=0x25, stream_id=13>
          ; END_STREAM | END_HEADERS | PRIORITY
          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)
          ; Open new stream
          :method: GET
          :path: /
          :scheme: https
          :authority: nghttp2.org
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.9.1
[  0.891] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.891] recv (stream_id=13) :method: GET
[  0.891] recv (stream_id=13) :scheme: https
[  0.892] recv (stream_id=13) :path: /stylesheets/screen.css
[  0.892] recv (stream_id=13) :authority: nghttp2.org
[  0.892] recv (stream_id=13) accept-encoding: gzip, deflate
[  0.892] recv (stream_id=13) user-agent: nghttp2/1.9.1
[  0.892] recv PUSH_PROMISE frame <length=47, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0, promised_stream_id=2)
[  0.892] recv (stream_id=13) :status: 200
[  0.892] recv (stream_id=13) date: Sun, 10 Apr 2016 17:00:25 GMT
[  0.892] recv (stream_id=13) content-type: text/html
[  0.892] recv (stream_id=13) content-length: 6646
[  0.892] recv (stream_id=13) last-modified: Sun, 03 Apr 2016 06:53:14 GMT
[  0.892] recv (stream_id=13) etag: "5700bdda-19f6"
[  0.892] recv (stream_id=13) link: </stylesheets/screen.css>; rel=preload; as=stylesheet
[  0.892] recv (stream_id=13) accept-ranges: bytes
[  0.892] recv (stream_id=13) x-backend-header-rtt: 0.000663
[  0.892] recv (stream_id=13) strict-transport-security: max-age=31536000
[  0.892] recv (stream_id=13) server: nghttpx nghttp2/1.10.0-DEV
[  0.892] recv (stream_id=13) via: 2 nghttpx
[  0.892] recv (stream_id=13) x-frame-options: SAMEORIGIN
[  0.892] recv (stream_id=13) x-xss-protection: 1; mode=block
[  0.892] recv (stream_id=13) x-content-type-options: nosniff
[  0.892] recv HEADERS frame <length=266, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0)
          ; First response header
[  0.893] recv DATA frame <length=6646, flags=0x01, stream_id=13>
          ; END_STREAM
[  0.893] recv (stream_id=2) :status: 200
[  0.893] recv (stream_id=2) date: Sun, 10 Apr 2016 17:00:25 GMT
[  0.893] recv (stream_id=2) content-type: text/css
[  0.893] recv (stream_id=2) content-length: 39082
[  0.893] recv (stream_id=2) last-modified: Sun, 03 Apr 2016 06:53:14 GMT
[  0.893] recv (stream_id=2) etag: "5700bdda-98aa"
[  0.893] recv (stream_id=2) accept-ranges: bytes
[  0.893] recv (stream_id=2) x-backend-header-rtt: 0.000427
[  0.893] recv (stream_id=2) strict-transport-security: max-age=31536000
[  0.893] recv (stream_id=2) server: nghttpx nghttp2/1.10.0-DEV
[  0.893] recv (stream_id=2) via: 2 nghttpx
[  0.893] recv (stream_id=2) x-frame-options: SAMEORIGIN
[  0.893] recv (stream_id=2) x-xss-protection: 1; mode=block
[  0.893] recv (stream_id=2) x-content-type-options: nosniff
[  0.893] recv (stream_id=2) x-http2-push: 1
[  0.893] recv HEADERS frame <length=62, flags=0x04, stream_id=2>
          ; END_HEADERS
          (padlen=0)
          ; First push response header
[  1.407] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.563] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=33412)
[  1.740] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.741] recv DATA frame <length=6314, flags=0x01, stream_id=2>
          ; END_STREAM
[  1.741] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])

還有這些參數:

-v : 顯示詳細信息
-n : 不輸出請求返回數據內容
-t : 請求超時設置
-w : 設置初始窗口大小
-a : 解析頁面獲取頁面上的資源
-H : 給請求增長特定頭部信息,例如: -H':method:PUT'-p: 設置請求權重 
--no-dep : 不發送依賴信息
  • nghttpd
    官方文檔,使用nghttpd,能夠架設一個簡易的支持HTTP2的服務器。打開附件中的示例文件,在路徑demos/nghttp/裏有一個run.sh(須要以管理員權限執行)
    $ cd demos/nghttp
    $ sudo ./run.sh [server-push]
    就能夠執行提供的shell腳本,第三個參數server-push是可選的,若是不須要server-push功能,直接sudo ./run.sh就能夠了,在本地設置好host 127.0.0.1 http2test.com後,就能夠在本地瀏覽器中訪問了,路徑是https://http2test.com/examples/dashboard/。因爲自籤的證書不被信任,須要安裝公鑰keys/*.crt文件並信任(Mac中須要打開keychain這個軟件,而後找到剛安裝的證書,改成老是信任),安裝信任後,打開Chrome就不會提示警告了;
    若是須要開啓server-push功能,輸入指令sudo ./run.sh server-push,shell腳本里設置了-p/examples/dashboard/=/examples/dashboard/d3.js,當請求路徑/examples/dashboard/時,就推送/examples/dashboard/d3.js文件。

4、服務器準備

  • nginx
    nginx的conf文件裏的設置,設置完後須要sudo nginx -s reload,因爲nginx的ngx_http_v2_module模塊是替代之前的ngx_http_spdy_module,故開啓HTTP2支持後,就沒法同時開啓SPDY支持:

    server {        
    listen       443 ssl http2;        
    server_name  http2test.com; 
    
    ssl_certificate      $證書地址;        
    ssl_certificate_key  $證書私鑰地址;  
    
    ssl_session_cache    shared:SSL:1m;        
    ssl_session_timeout  5m; 
    
    ssl_ciphers  HIGH:!aNULL:!MD5;        
    ssl_prefer_server_ciphers  on;   
    
    location / {            
    root   $靜態文件地址;            
    index  index.html index.htm;
        }
    }
  • h2o
    這裏引入下Server Push的概念,在上一篇概念篇有介紹道,Server Push就是,當請求時,服務器同時將其它文件也推送過來,HTTP2的說明中,並無規定Server Push具體的實現策略,這個可由服務器和客戶端自主決定:

  • Jetty:jetty經過referrer創建了一個依賴模型,該模型能夠應用在CDN裏,方便配置;
  • h2o:經過Cookie實現了cache aware server push——可感知緩存的服務器推送。第一次推送時,服務器端set-cookie,將要推送的路徑+etag存入一個集合,經過算法生產指紋編碼爲base64存入cookie,以後經過cookie來判斷是否須要推送該文件;
    這裏着重介紹h2o,爲何h2o要這麼作呢?由於流量就是錢啊。。。客戶端接收到服務器端發送的PUSHPROMISE Frame後,能夠經過是否發送RST Frame來拒絕掉服務器推送的文件,可是在這個過程當中,服務器推送的文件可能已經發送一部分過來了,若是客戶端決定不接收服務器推送的文件,那麼以前發送的部分就是浪費掉的流量,h2o就是爲了解決這個問題;在設置好h2o後,咱們來看看第一次訪問的結果:

    讓咱們來看看第二次訪問的結果:

    能夠看到,第二次訪問時,並無PUSHPROMISE Frame了,也就是說,服務器再也不推送文件了。

五.開發準備

  • wireshark
    這裏講解基本的wireshark使用,因爲大多數的HTTP2都是基於Over TLS版,也就是須要解密才能看到正確的HTTP2包內容;wireshark提供了兩個方式:
    使用SSLKEYLOGFILE,使得wireshark可使用Firefox/Chrome的解密信息
    首先在wireshark的Preferences -> Protocol -> SSL配置一個可讀的文件地址,而後在環境變量,例如Mac是~/.bashprofile

    export SSLKEYLOGFILE=$剛配置的地址
    source     ~/.bashprofile

    經過Terminal打開Firefox或Chrome,這樣才能使用環境變量SSLKEYLOGFILE
    open -a Google\ Chrome
    該方法的侷限是,只能在電腦上抓包使用,而且只能使用Chrome和Firefox;
    還有一個方法是配置RSA私鑰,不過這種辦法的侷限是多種加密方式不支持,而且該方法必須紀錄完整的TLS握手過程,因此建議打開瀏覽器訪問前就已經開始監聽;
    配置好解密方式後,使用瀏覽器打開剛跑起來的HTTP2 Demo,https://http2test.com/examples/dashboard/,而後再篩選出輸入http2並回車,就能夠看到篩選的HTTP2包。

  • fiddler
    fiddler解密HTTPS採用的是中間人攻擊的方法,客戶端訪問到fiddler代理服務器,而後fiddler代理服務器再模擬客戶端訪問到網站。那麼,須要安裝Fiddler的根認證證書,同時啓用HTTPS解密功能。

    對於Fiddler來講,對於每一個機器其實下發的實際上是不一樣的根證書,因此,必定要經過Fiddler的配置網頁來安裝證書(配置代理後,打開網站http://ipv4.fiddler:8888,而後點擊圖中的FiddlerRoot Certificate來下載安裝)

    針對iOS及部分高版本的Android,證書中的部分信息是必要的,有兩個辦法。
    (1) 採用如圖所示的設置(iOS 9親測可用),
    (2) 安裝使用Fiddler CertMaker插件
    而後須要介紹的一個點是FiddlerScript,這是一個很強大的功能。若是須要將之前調試HTTP的方法在HTTPS一樣適用,須要有這些設置。,而後以後我也會繼續更新Fiddler調試部分的內容,請收藏哦。在Willow的rule裏設置HTTPS -> HTTP; HTTPS -> File; 都是能夠生效的。
    若是須要HTTPS -> HTTPS 或者 HTTPS -> HTTP,能夠採用上面連接的方法,也能夠設置oSession["x-replywithtunnel"] = "FakeTunnel"。

    if (oSession.HostnameIs("app.yourdomain.com"))
    {    // Handle CONNECT Tunnels
    if (oSession.HTTPMethodIs("CONNECT"))
    {
        oSession["x-replywithtunnel"] = "FakeTunnel";        return;
    }
    
    oSession.fullUrl = "http://somedomain:someport" + oSession.PathAndQuery;
    }

六.SSL/TLS部分小貼士

1.活用證書,提升性能

首先來看本地搭建的HTTPS服務:

第一個狀況是,同一個IP,可是域名不一樣,同時,使用的證書也不一樣:第一張圖顯示的域名是http2test.com,第二張圖顯示的域名是http2.icese7en.com,他們使用的證書也是不一樣的,能夠看到TCP Stream這一列,具備不一樣的序號(相同序號代表他們使用的是同一個TCP鏈接)

第二個狀況是,同一個IP,域名不一樣,可是使用的證書是相同的:第一張圖的域名是cdn1.http2test.com,第二張圖的域名是cdn2.http2test.com,他們使用的證書(第三張圖)是泛域名*.http2test.com,他們的TCP Stream序號都是30,複用同一條TCP鏈接



那麼,若是域名不一樣,甚至都不是子域名的方式,也能夠經過這一個點去優化嗎?是能夠的,經過證書裏的subjectAltName,咱們能夠在證書裏管理多個不一樣域名,例如google的證書:

不過這樣證書很貴就是了 - -

2.SSL/TLS提升安全

HSTS——HTTP嚴格傳輸協議
HSTS主要是爲了改善如下幾個問題:

  • 沒辦法知道一個網站是否支持TLS:例如第一次鏈接時,若是沒有指定協議名,會優先採用http協議,有安全隱患。而開啓HSTS後,第一次(以前訪問過該域名)以後的訪問瀏覽器會自動強制使用HTTPS訪問;
  • 對證書問題的寬容:未開啓HSTS時,若是證書有問題,客戶端只會提示警告,而不是禁止訪問,開啓HSTS後,會被禁止訪問;
  • mixed-content問題:開啓HSTS後,一個HTTPS頁面上的同域名下的非HTTPS資源會自動升級爲HTTPS訪問;

要開啓HSTS,只須要服務器端在返回頭中返回(不支持IP)

Strict-Transport-Security: max-age=31536000 [; includeSubDomains] [; preload]
# includeSubDomains 能夠開啓子域名的HSTS功能# 不過須要評估這麼作的是否會有負面影響

在max-age指定的時間內,瀏覽器都自動以HTTPS訪問。若是須要關閉HSTS,返回max-age=0就能夠了。

注意

  • HSTS的第一次訪問仍然具備被挾持的危險,可經過HSTS preload來減輕影響(須要申請加入各瀏覽器的preload-list);
  • HSTS時間是基於本地時間計算的,若是客戶端時間被篡改,可能會形成HSTS策略被失效繞過。
  • 引用自關於啓用 HTTPS 的一些經驗分享(一)

    只要你不能確保永遠提供 HTTPS 服務,就不要啓用。由於一旦 HSTS 生效,你再想把網站重定向爲 HTTP,以前的老用戶會被無限重定向,惟一的辦法是換新域名

CSP——內容安全政策
CSP是一個聲明式的安全機制,本來的目的是防止XSS跨站腳本攻擊。例如,CSP能夠徹底禁止內聯的Javascript代碼的執行,控制哪些外聯的Javascript文件能夠被執行。

Content-Security-Policy: default-src 'self'; img-src *; script-src scripts.example.com
上面的CSP策略是,默認容許本源的資源的訪問,容許全部URL的圖片顯示,外鏈腳本只容許來自於scripts.example.com的文件執行;

Content-Security-Policy: default-src https: 'unsafe-inline' 'unsafe-eval'; connect-src https:
上面的CSP策略是,默認容許來自於任何URL的資源,只要它是安全的HTTPS,同時開啓了內聯JS和eval的執行(默認是被CSP禁止的),connect-src設定了Ajax請求只能請求HTTPS;(部分開啓內聯JS的執行可參考Content Security Policy Level 2 介紹)

CSP上報
使用report-uri指令,違反CSP策略的行爲都會被上報到該CGI

文章來源於公衆號:小時光茶社(Tech Teahouse)

相關文章
相關標籤/搜索