本教程的先前版本由 Sergey Zhukaev 编写。
介绍
Nginx 是一个快速可靠的开源 Web 服务器。 它因其低内存占用、高可扩展性、易于配置和支持多种协议而广受欢迎。
HTTP/2 是超文本传输协议的新版本,用于在 Web 上将页面从服务器传送到浏览器。 HTTP/2 是近二十年来 HTTP 的第一次重大更新:HTTP1.1 早在 1999 年就被引入公众,当时网页通常只是一个带有内联 CSS 样式表的 HTML 文件。 从那时起,互联网发生了巨大的变化,现在我们面临着 HTTP 1.1 的限制——该协议限制了大多数现代网站的潜在传输速度,因为它会在队列中下载页面的一部分(前一部分必须在下载之前完全下载下一部分开始),一个现代网页平均需要大约 100 个请求才能下载(每个请求是图片、js 文件、css 文件等)。
HTTP/2 解决了这个问题,因为它带来了一些根本性的变化:
- 所有请求都是并行下载的,而不是在队列中
- HTTP 标头被压缩
- 页面以二进制而不是文本文件的形式传输,效率更高
- 即使没有用户的请求,服务器也可以“推送”数据,从而提高高延迟用户的速度
尽管 HTTP/2 不需要加密,但两种最流行的浏览器 Google Chrome 和 Mozilla Firefox 的开发人员表示,出于安全原因,他们将仅支持 HTTP/2 用于 HTTPS 连接。 因此,如果您决定设置支持 HTTP/2 的服务器,则还必须使用 HTTPS 保护它们。
本教程将帮助您设置一个快速安全的支持 HTTP/2 的 Nginx 服务器。
先决条件
在开始之前,我们需要做一些事情:
- 按照Ubuntu 18.04初始服务器设置指南设置一台Ubuntu 18.04服务器,包括sudo非root用户和防火墙。
- Nginx 安装在您的服务器上,您可以按照 How To Install Nginx on Ubuntu 18.04 进行操作。
- 配置为指向您的服务器的域名。 您可以在 Namecheap 上购买一个或在 Freenom 上免费获得一个。 您可以按照 如何使用 DigitalOcean 管理您的域的文档来学习如何将域指向 DigitalOcean Droplets。
- 为您的服务器配置的 TLS/SSL 证书。 你有三个选择: 您可以按照如何在 Ubuntu 18.04 上使用 Let's Encrypt 保护 Nginx 来从 Let's Encrypt 获得免费证书。 您还可以按照如何在 Ubuntu 18.04 中为 Nginx 创建自签名 SSL 证书来生成和配置自签名证书。 您可以从其他提供商处购买并配置 Nginx 以使用它,方法是按照如何在 Ubuntu 18.04 中为 Nginx 创建自签名 SSL 证书的步骤 2 到 6。
- Nginx 配置为将流量从端口
80
重定向到端口443
,这应该包含在前面的先决条件中。 - Nginx 配置为使用 2048 位或更高的 Ephemeral Diffie-Hellman (DHE) 密钥,前面的先决条件也应涵盖这一点。
第 1 步 — 启用 HTTP/2 支持
如果您按照 Nginx 安装教程 中的 服务器块设置步骤进行操作,您应该在 /etc/nginx/sites-available/your_domain
处为您的域设置一个服务器块,并且已经正确设置了 server_name
指令。 我们将进行的第一个更改是修改您域的服务器块以使用 HTTP/2。
打开您的域的配置文件:
sudo nano /etc/nginx/sites-available/your_domain
在文件中,找到与端口 443
关联的 listen
变量:
/etc/nginx/sites-available/<^>your_domain<^>
... listen [::]:443 ssl ipv6only=on; listen 443 ssl; ...
第一个用于 IPv6 连接。 第二个用于所有 IPv4 连接。 我们将为两者启用 HTTP/2。
修改每个 listen
指令以包含 http2
:
/etc/nginx/sites-available/<^>your_domain<^>
... listen [::]:443 ssl http2 ipv6only=on; listen 443 ssl http2; ...
这告诉 Nginx 在支持的浏览器上使用 HTTP/2。
保存配置文件并退出文本编辑器。
每当您更改 Nginx 配置文件时,您应该检查配置是否存在语法错误,如下所示:
sudo nginx -t
如果语法没有错误,您将看到以下输出:
sudo nginx -t 的输出
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
接下来,我们将配置我们的服务器以使用更严格的密码列表。
第 2 步 — 删除旧的和不安全的密码套件
HTTP/2 有一个 blacklist 旧且不安全的密码,因此我们必须避免使用它们。 密码套件是描述应如何加密传输的数据的加密算法。
您将用于定义密码的方法取决于您为 Nginx 配置 TLS/SSL 证书的方式。
如果您使用 Certbot 来获取您的证书,它还会创建文件 /etc/letsencrypt/options-ssl-nginx.conf
,其中包含对 HTTP/2 来说不够强大的密码。 不幸的是,修改这个文件会阻止 Certbot 将来应用更新,所以我们只会告诉 Nginx 不要使用这个文件,我们将指定我们自己的密码列表。
打开您的域的服务器块配置文件:
sudo nano /etc/nginx/sites-available/your_domain
找到包含 options-ssl-nginx.conf
文件的行并将其注释掉:
/etc/nginx/sites-available/<^>your_domain<^>
# include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot<^>
在该行下方,添加此行以定义允许的密码:
/etc/nginx/sites-available/<^>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
:
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;
保存文件并退出编辑器。
再次检查配置是否有语法错误:
sudo nginx -t
如果您发现任何错误,请解决它们并再次测试。
一旦你没有看到语法错误,重启 Nginx:
sudo systemctl reload nginx
重新启动服务器后,让我们验证它是否正常工作。
第 3 步 — 验证 HTTP/2 是否已启用
让我们确保服务器正在运行并使用 HTTP/2。
使用 curl
命令向您的站点发出请求并查看标头:
curl -I -L https://your_domain
您将看到以下输出:
OutputHTTP/1.1 301 Moved Permanently Server: nginx/1.14.0 (Ubuntu) Date: Fri, 06 Jul 2018 19:07:12 GMT Content-Type: text/html Content-Length: 194 Connection: keep-alive Location: https://your_domain/ HTTP/2 200 server: nginx/1.14.0 (Ubuntu) date: Fri, 06 Jul 2018 19:07:12 GMT content-type: text/html content-length: 16 last-modified: Fri, 06 Jul 2018 16:55:37 GMT etag: "5b3f9f09-10" accept-ranges: bytes
您还可以验证 HTTP/2 是否在 Google Chrome 中使用。 打开 Chrome 并导航到 http://your_domain
。 打开 Chrome 开发者工具 (View -> Developer -> Developer Tools) 并重新加载页面 (View -> 重新加载此页面)。 导航到 Network 选项卡,右键单击以 Name 开头的表头行,然后从弹出菜单中选择 Protocol 选项。
您将在新的 Protocol 列中看到 h2
(代表 HTTP/2),表明 HTTP/2 正在工作。
此时,您已准备好通过 HTTP/2 协议提供内容。 让我们通过启用 HSTS 来提高安全性和性能。
第 4 步 — 启用 HTTP 严格传输安全 (HSTS)
即使您的 HTTP 请求重定向到 HTTPS,您也可以启用 HTTP Strict Transport Security (HSTS) 以避免进行这些重定向。 如果浏览器找到 HSTS 标头,它不会在给定的时间段内再次尝试通过常规 HTTP 连接到服务器。 无论如何,它将仅使用加密的 HTTPS 连接交换数据。 此标头还保护我们免受协议 降级攻击 。
在编辑器中打开 Nginx 配置文件:
sudo nano /etc/nginx/nginx.conf
将此行添加到文件以启用 HSTS:
/etc/nginx/nginx.conf
http { ... ## # Virtual Host Configs ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; add_header Strict-Transport-Security "max-age=15768000" always; } ...
max-age
以秒为单位设置。 15768000
的值相当于 6 个月。
默认情况下,此标头不会添加到子域请求中。 如果您有子域并希望 HSTS 应用于所有子域,则应在行尾添加 includeSubDomains
变量,如下所示:
/etc/nginx/nginx.conf
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains" always;
保存文件,然后退出编辑器。
再次检查配置是否有语法错误:
sudo nginx -t
最后,重新启动 Nginx 服务器以应用更改。
sudo systemctl reload nginx
结论
你的 Nginx 服务器现在提供 HTTP/2 页面。 如果您想测试 SSL 连接的强度,请访问 Qualys SSL Lab 并针对您的服务器运行测试。 如果一切配置正确,您应该获得 A+ 安全标记。