輕鬆讓你的nginx伺服器支援HTTP2協議

簡介

nginx是一個高效的web伺服器,因為其獨特的響應處理機制和低記憶體消耗,深得大家的喜愛,並且nginx可和多種協議配合使用,而HTTP2協議又是一個非常優秀的協議,如果將兩者結合起來會產生意想不到的效果,今天我們將會講解如何在nginx中配置HTTP2協議。

HTTP1.1和HTTP2

HTTP的全稱是Hypertext Transfer Protocol,是在1989年World Wide Web發展起來之後出現的標準協議,用來在WWW上傳輸數據。HTTP/1.1是1997年在原始的HTTP協議基礎上進行的補充和優化。

到了2015年,為了適應快速發送的web應用和現代瀏覽器的需求,發展出了新的HTTP/2協議,主要在手機瀏覽器、延時處理、影像處理和影片處理方面進行了優化。

相對於HTTP1.1來說,HTTP2有如下幾個優點:

  1. 使用多路復用技術,在同一個連接中可以並行處理多個請求。
  2. 可以壓縮HTTP頭,減少請求的大小。
  3. 數據傳輸格式是以二進位進行的,所以傳輸更加有效。
  4. 伺服器可以向客戶端推送數據,從而讓應用程式可以處理更加複雜的功能。

儘管HTTP2並不要求使用加密,但是對於現代瀏覽器來說如Google Chrome 和 Mozilla Firefox默認HTTP2和HTTPS是一起使用的,所以如果你想配置HTTP2的話,還是需要同時配置SSL。

安裝最新的nginx

在寫本文的時候,nginx最新的版本是1.21.1。我們可以從nginx官網上下載對應的編譯好的文件,直接解壓即可運行。或者可以下載它的源文件,手動進行編譯安裝。

如果你是在mac環境,可以直接使用brew命令來進行安裝:

brew install nginx

安裝完畢之後會告訴我們一些有用的資訊:

Docroot is: /usr/local/var/www

The default port has been set in /usr/local/etc/nginx/nginx.conf to 8080 so that
nginx can run without sudo.

nginx will load all files in /usr/local/etc/nginx/servers/.

To have launchd start nginx now and restart at login:
  brew services start nginx
Or, if you don't want/need a background service you can just run:
  nginx

這裡就不一一詳細講解了,感興趣的朋友可以自行探索。

開啟HTTP2支援

從上面可以知道,nginx默認的配置文件是/usr/local/etc/nginx/nginx.conf,打開該文件可以看到最後一行:

include servers/*;

所以我們可以在servers中新建一個www.flydean.com.conf的文件作為今天要開啟HTTP2支援的域名。

默認情況下,nginx監聽的埠是80,如下所示:

listen 80 default_server;
listen [::]:80 default_server;

為什麼會有兩個listen呢?第一個listen指的是所有的IPv4連接,第二個listen指的是IPv6連接。

因為HTTP2需要開啟SSL支援,所以我們這裡將其修改為443,並且加上http2支援如下所示:

        listen       443 ssl http2;
        server_name  www.flydean.com;

上面的配置中我們還指定了server_name,這就是要訪問的域名地址,這裡我們使用www.flydean.com。

添加SSL支援

要想添加SSL支援就需要添加證書,一種方式是購買或者在網上有一些免費的SSL證書可用,如果只是在測試環境中的話,還可以生成自簽名證書。

這裡我們介紹一下如何生的自簽名證書。這裡我們使用openssl命令來完成這個工作。

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout selfsigned.key -out selfsigned.crt
Generating a RSA private key

執行完成上面的命令,會要求你輸入一些證書的資訊如下:

Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:SH
Locality Name (eg, city) []:SH
Organization Name (eg, company) [Internet Widgits Pty Ltd]:flydean
Organizational Unit Name (eg, section) []:flydean
Common Name (e.g. server FQDN or YOUR name) []:127.0.0.1
Email Address []:[email protected]

然後就生成了兩個文件:selfsigned.crt和selfsigned.key。

這裡稍微講解一下自簽名證書生成的命令。

openssl是一個非常強大的密鑰生成工具,可以完成絕大多數的密鑰生成工作。

req表示的是這是一個X.509 certificate signing request (CSR)。

-x509表示我們希望生成的是一個自簽名的證書。

-nodes表示我們不需要對生成的密鑰進行密碼加密。

-days 365表示證書的有效期。

-newkey rsa:2048表示使用RSA演算法同時生成證書和key,key的長度是2048。

-keyout:指定key的生成路徑。

-out:指定證書的生成路徑。

這裡即使是使用了SSL,為了保證安全,我們還可以使用一項叫做完美的向前保密的技術,這裡需要生成Diffie-Hellman group:

openssl dhparam -out dhparam.pem 2048

這個命令會需要一些時間,生成之後,我們就可以開始nginx的SSL配置了。

        ssl_certificate      ssl/selfsigned.crt;
        ssl_certificate_key  ssl/selfsigned.key;

修改加密演算法

我們知道已經存在很多加密演算法,隨著密碼學技術的發展,很多演算法已經被證明是不安全的。所以這裡我們需要對默認的加密演算法進行修改。

默認的演算法是:

        ssl_ciphers  HIGH:!aNULL:!MD5;

我們將其修改為:

ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

Diffie–Hellman對消息進行加密

雖然我們使用private key配置了客戶端和伺服器端的加密連接,在建立連接之後,在ServerKeyExchange這一步,雙方還會詢問對資訊的加密方式來用來構建加密通道。

ServerKeyExchange的內容可能包含兩種形式:

  • 如果選擇的是RSA協議,那麼傳遞的就是RSA構建公鑰密碼的參數(E,N)。我們回想一下RSA中構建公鑰的公式:\(密文=明文^E\ mod\ N\), 只要知道了E和N,那麼就知道了RSA的公鑰,這裡傳遞的就是E,N兩個數字。具體內容可以參考RSA演算法詳解

  • 如果選擇的是Diff-Hellman密鑰交換協議,那麼傳遞的就是密鑰交換的參數,具體內容可以參考更加安全的密鑰生成方法Diffie-Hellman

這裡我們選擇使用Diffie–Hellman,還記得上一小節,我們創建的Diffie–Hellman文件嗎?這裡直接使用即可。

默認情況下Nginx使用的是1028-bit DHE (Ephemeral Diffie-Hellman) key,這個比較容易被破解,所以需要使用我們自己生成的文件。

       ssl_dhparam  ssl/dhparam.pem;

重定向所有的HTTP請求到HTTPS

默認情況下我們訪問網站都是HTTP的,所以需要將HTTP請求重定向到HTTPS:

server {
       listen         80;
       listen    [::]:80;
       server_name    www.flydean.com;
       return         301 //$server_name$request_uri;
}

啟動nginx並測試

好了,到此為止所有的nginx配置都完成了,我們使用下面的命令測試nginx文件和啟動:

nginx -t
nginx: the configuration file /usr/local/etc/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/etc/nginx/nginx.conf test is successful

nginx

要訪問網站,還需要配置一下host將 www.flydean.com 指到你的nginx server上。

然後就可以訪問www.flydean.com了。

這裡可能會出現一個問題,如果你是自簽名的證書,在chrome默認的安全環境中會認為這個證書是無效的,還需要將該證書加入證書的信任鏈中。

怎麼看出這個網站到底使用的那種協議呢?

打開瀏覽器的調試開關,到網路的tab,點擊訪問的頁面,可以看到下面的內容:

可以看到版本是HTTP/2並且響應頭帶有X-Firefox-Spdy h2。

總結

好了,你已經可以配置一個完美的HTTPS並且支援HTTP2協議的網站了。恭喜!

本文已收錄於 //www.flydean.com/01-nginx-http2/

最通俗的解讀,最深刻的乾貨,最簡潔的教程,眾多你不知道的小技巧等你來發現!

歡迎關注我的公眾號:「程式那些事」,懂技術,更懂你!