如何在 Ubuntu 22.04 上設置支持 HTTP/2 的 Nginx

A previous version of this tutorial was written by Sergey Zhukaev.

介紹

Nginx是一個快速可靠的開源Web伺服器。它因其低內存佔用、高可擴展性、易於配置和對各種協議的支持而廣受歡迎。

HTTP/2是Hypertext傳輸協議的新版本,在Web上用於從伺服器傳遞頁面到瀏覽器。 HTTP/2是近二十年來的首次重大更新:當時網頁大小要小得多,公眾才開始使用HTTP1.1,那是在1999年。自那時以來,互聯網已經發生了巨大變化,我們現在面臨的是HTTP 1.1的限制。該協議對於大多數現代網站的潛在傳輸速度有所限制,因為它將頁面的各個部分按順序下載 – 前一部分必須完全下載才能開始下載下一部分 – 而一個平均的現代網頁下載數十個個別的CSS、javascript和圖像資源。

HTTP/2解決了這個問題,因為它帶來了一些根本性的改變:

  • 所有請求都是並行下載的,而不是在隊列中
  • HTTP標頭被壓縮
  • 頁面作為二進制傳輸,而不是作為文本文件,這更有效率
  • 伺服器可以在沒有用戶請求的情況下“推送”數據,這提高了高延遲用戶的速度

即使 HTTP/2 不要求加密,但 Google Chrome 和 Mozilla Firefox 两款最流行的浏览器的开发者表示,出于安全考虑,他们将仅支持 HTTPS 连接的 HTTP/2。因此,如果您决定设置支持 HTTP/2 的服务器,您还必须使用 HTTPS 对其进行保护。

本教程将帮助您设置一个快速且安全的 Nginx 服务器,并支持 HTTP/2。

先决条件

在开始之前,您需要准备一些东西:

步骤1 — 启用HTTP/2支持

如果您按照Nginx安装教程中的服务器块设置步骤进行了操作,则应该在/etc/nginx/sites-available/your_domain下拥有一个适用于您域的服务器块,并且server_name指令已经设置正确。我们将进行的第一个更改将是修改您域的服务器块以使用HTTP/2。

使用nano或您喜欢的编辑器打开您域的配置文件:

  1. sudo nano /etc/nginx/sites-enabled/your_domain

在文件中,找到与端口443关联的listen变量:

/etc/nginx/sites-enabled/your_domain
...
    listen [::]:443 ssl ipv6only=on; 
    listen 443 ssl; 
...

第一個是用於IPv6連接。第二個是用於所有IPv4連接。我們將為兩者啟用HTTP/2。

修改每個listen指令以包括http2

/etc/nginx/sites-enabled/your_domain
...
    listen [::]:443 ssl http2 ipv6only=on; 
    listen 443 ssl http2; 
...

這告訴Nginx在支持的瀏覽器中使用HTTP/2。

保存配置文件並退出文本編輯器。如果您正在使用nano,請按Ctrl+X,然後在提示時輸入Y,然後按Enter。

每當您對Nginx配置文件進行更改時,都應該使用-t標誌檢查配置文件中的錯誤,該標誌運行Nginx的內置語法檢查命令:

  1. sudo nginx -t

如果語法無誤,您將收到以下類似的輸出:

Output of sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

接下來,您將配置Nginx服務器以使用更嚴格的密碼列表以提高服務器的安全性。

第2步 – 刪除舊的和不安全的密碼套件

HTTP/2有一個封鎖列表,列出了應該避免使用的舊的和不安全的密碼套件。密碼套件是描述傳輸數據應如何加密的加密算法。

您將用於定義密碼的方法取決於您如何配置Nginx的TLS/SSL證書。

如果您使用 Certbot 获取证书,它还会创建文件 /etc/letsencrypt/options-ssl-nginx.conf,其中包含不足以保证安全性的密码。但是,修改此文件将阻止 Certbot 在将来应用更新,因此我们只需告诉 Nginx 不要使用此文件,然后我们将指定我们自己的密码列表。

打开您域的服务器块配置文件:

sudo nano /etc/nginx/sites-enabled/your_domain

找到包含 options-ssl-nginx.conf 文件的行,并通过在该行的开头添加 # 字符来将其注释掉:

/etc/nginx/sites-enabled/your_domain

# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot

在该行下面,添加以下行以定义允许的密码:

/etc/nginx/sites-enabled/your_domain

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

保存文件并退出编辑器。

如果您使用自签名证书或使用第三方证书并根据先决条件进行了配置,请在文本编辑器中打开文件 /etc/nginx/snippets/ssl-params.conf

  1. sudo nano /etc/nginx/snippets/ssl-params.conf

找到以下行:

/etc/nginx/snippets/ssl-params.conf
...
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
...

修改为使用以下密码列表:

/etc/nginx/snippets/ssl-params.conf

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

保存文件并退出编辑器。

再次使用 nginx -t 命令检查语法错误:

  1. sudo nginx -t

如果遇到任何错误,请解决它们并再次测试。

一旦您的配置通过了语法检查,请使用 systemctl 命令重新启动 Nginx:

  1. sudo systemctl reload nginx.service

服务器重新启动后,让我们验证它是否正常工作。

步驟三 — 驗證是否已啟用 HTTP/2

讓我們確保伺服器正在運行並使用 HTTP/2。

使用 curl 命令向您的網站發出請求並查看標頭:

  1. curl -I -L --http2 https://your_domain

您將收到如下輸出:

HTTP/2 200
**Server**: nginx/1.18.0 (Ubuntu)
**Date**: Tue, 21 Jun 2022 22:19:09 GMT
**Content-Type**: text/html
**Content-Length**: 612
**Last-Modified**: Tue, 21 Jun 2022 22:17:56 GMT
**Connection**: keep-alive
**ETag**: "62b24394-264"
**Accept-Ranges**: bytes

您還可以驗證 Google Chrome 是否正在使用 HTTP/2。打開 Chrome 並導航至 https://your_domain。打開 Chrome 開發人員工具(檢視 -> 開發人員 -> 開發人員工具)並重新加載頁面(檢視 -> 重新載入此頁面)。導航至 網絡 標籤,右鍵點擊以 名稱 開頭的表頭行,並從彈出菜單中選擇 協議 選項。

您將得到一個新的 協議 列,其中包含 h2(代表 HTTP/2),表示 HTTP/2 正在運行。

在此時,您已準備通過 HTTP/2 協議提供內容。讓我們通過啟用 HSTS 來提高安全性和性能。

步驟4 — 啟用HTTP嚴格傳輸安全性(HSTS)

即使您的HTTP請求重定向到HTTPS,您也可以啟用HTTP嚴格傳輸安全性(HSTS)以避免進行這些重定向。如果瀏覽器發現HSTS標頭,它將不會再嘗試以常規HTTP連接到服務器,一段時間內,無論如何,它將僅使用加密的HTTPS連接進行數據交換。此標頭還可保護我們免受協議降級攻擊的影響。

再次打開您域的服務器塊配置文件:

sudo nano /etc/nginx/your_domain

將此行添加到包含SSL密碼的文件中的同一塊中,以啟用HSTS:

/etc/nginx/your_domain
server {
...
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    add_header Strict-Transport-Security "max-age=15768000" always;
}
...

max-age以秒為單位。值15768000等於6個月。

默認情況下,此標頭不會添加到子域請求中。如果您有子域並且希望HSTS應用於所有子域,您應在行末添加includeSubDomains變量,如下所示:

/etc/nginx/your_domain
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;

保存文件,並退出編輯器。

再次檢查語法錯誤的配置:

  1. sudo nginx -t

最後,重新啟動Nginx服務器以應用更改。

  1. sudo systemctl reload nginx.service

結論

您的 Nginx 伺服器現在正在提供 HTTP/2 頁面。如果您想測試 SSL 連線的強度,請訪問 Qualys SSL 實驗室 並對您的伺服器進行測試。如果一切都配置正確,您應該會獲得安全性的 A+ 等級。

要了解有關 Nginx 如何解析和實現伺服器塊規則的更多信息,請閱讀 理解 Nginx 伺服器和位置塊選擇算法

Source:
https://www.digitalocean.com/community/tutorials/how-to-set-up-nginx-with-http-2-support-on-ubuntu-22-04