Apache2 and HTTP/2
最近 Apache HTTPD 2.4.17 出了,內建 HTTP/2 的支援,不免俗的要來測試一下,在 Ubuntu 14.04 LTS 下安裝其實也是蠻辛苦的,最主要的問題是 OpenSSL 內建的是 1.0.1,但是要完整支援 HTTP/2 ,還需要 TLS 的 ALPN ,然後就會需要 OpenSSL 1.0.2,因此第一件事情就是下載編譯安裝 OpenSSL,目前最新的是 1.0.2d,如果是 15.10 就是內建 1.0.2 的,問題會少很多,總之先自己下載解壓縮然後編譯:
./config
make
sudo make install
會把檔案裝到/usr/local/ssl
這個位置,大概是因為 OpenSSL 影響比較大所以預設沒有裝到平常的/usr/local
下面,不過也因此造就後續比較麻煩的地方。
Apache 的部分比較麻煩,要分兩個部分,第一個部分是先把 APR 部分的程式碼和 HTTPD 的部分拉下來放一起,這邊參考 あすのかぜ 上的指令:
wget http://ftp.jaist.ac.jp/pub/apache//httpd/httpd-2.4.17.tar.gz
tar zxvf ./httpd-2.4.17.tar.gz
wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache//apr/apr-1.5.2.tar.gz
tar zxvf ./apr-util-1.5.4.tar.gz
mv ./apr-1.5.2 ./httpd-2.4.17/srclib/apr
wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache//apr/apr-util-1.5.4.tar.gz
ar zxvf ./apr-util-1.5.4.tar.gz
mv ./apr-util-1.5.4 ./httpd-2.4.17/srclib/apr-util
然後進去httpd-2.4.17
目錄下指令編譯安裝:
env PKG_CONFIG_PATH=/usr/local/ssl/lib/pkgconfig ./configure --enable-http2
make
sudo make install
執行的時候也需要注意,需要帶個環境變數,不然他找不到/usr/local/ssl/
下的 Library:
env LD_LIBRARY_PATH=/usr/local/ssl/lib /usr/local/apache2/bin/httpd
或是:
env LD_LIBRARY_PATH=/usr/local/ssl/lib /usr/local/apache2/bin/apachectl start
不過其實執行前還需要先修改一下設定,我是加在 VirtualHost 裡面:
<VirtualHost *:80>
Protocols h2c http/1.1
ServerName blog.othree.net
ServerAdmin othree@gmail.com
還有
<VirtualHost *:443>
Protocols h2 http/1.1
ServerName blog.othree.net
ServerAdmin othree@gmail.com
重點是Protocols
那行,h2
指的是 HTTPS(TLS) 下的 HTTP/2 連線,h2c
則是 HTTP 下的,在其他地方還會看到h-15
、h-17
之類的,那些其實是之前草稿的版本,無視就好,另外還有一個地方需要設定的是加密用的 CipherSuite 和溝通協定,可以參考 How to h2 in apache 提供的設定:
SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
SSLProtocol All -SSLv2 -SSLv3
不確定 CipherSuite 的選擇影響多大,不過我猜主要是要把 SSL 全部關掉吧,然後其實這組設定就是 Mozilla 推薦的 SSL 設定的 Modern 那組,等於是要放棄很多舊瀏覽器了,支援的瀏覽器最低版本如下:
- Firefox 27
- Chrome 22
- IE 11
- Opera 14
- Safari 7
- Android 4.4
- Java 8
都弄好開啟 Apache 就可以了,不過記得如果之前是用 apt 裝的 Apache 的話,設定要自己搬過來。
驗證工具可以用 Curl 或是 nghttp,我是在 OSX 上用 brew 裝的,Curl 比較麻煩,不過可以看到一開始溝通的部分:
brew install curl --with-nghttp2
brew link curl
/usr/local/bin/curl -v --http2 https://othree.net
然後就會出現最上面那張圖那樣的資訊,可以看到有 ALPN 的選項出現,另外一個工具是 nghttp,其實 Curl 的 http2 支援就是用這套 library:
brew install nghttp2
nghttp -uv https://othree.net
可以看到上色整理得很漂亮的資訊,另外用瀏覽器也可以判斷,Firefox 的話會寫上 HTTP 版本號,Chrome 我測試是要 Canary 才支援,然後我網站連線的 SSL 握手那段花的時間反而更多,不過還是比較快全部下載完,只是 render 畫面影響的還有其他檔案,雖然大部分檔案都提早開始下載,不過也同時開始下載重要度比較低的圖形檔案,結果反而 DOM ready 的時間點更晚~~~,下圖是 HTTP/1.1 的時候:
然後是 2.0:
最後就是還不支援 Server Push,這個東西其實技術上不難,可是和 Cache 搞在一起就變很複雜了,目前好像還沒有比較好的解法出現,也只有一些非開源的系統支援的樣子。