如何在Ubuntu16.04上设置支持HTTP/2的Nginx
介绍
NGINX 是一个快速可靠的开源 Web 服务器。 它因其低内存占用、高可扩展性、易于配置和支持绝大多数不同协议而广受欢迎。
支持的协议之一是 2015 年 5 月发布的相对较新的 HTTP/2。 HTTP/2 的主要优势是它对于内容丰富的网站的高传输速度。
本教程将帮助您设置一个快速安全的支持 HTTP/2 的 Nginx 服务器。
先决条件
在开始之前,我们需要做一些事情:
- Ubuntu 16.04 液滴
- 具有 sudo 权限的非 root 用户(查看 Initial Server Setup with Ubuntu 16.04 了解详情。)
- 完全注册的域。 您可以在 Namecheap 上购买一个或在 Freenom 上免费获得一个。
- 确保您的域名配置为指向您的 Droplet。 如果您需要帮助,请查看 本教程 。
- SSL 证书。 生成自签名证书,从 Let's Encrypt 获取免费证书,或 从其他提供商处购买 。
就这些。 如果您拥有上面列出的所有内容,那么您就可以开始了。
HTTP 1.1 和 HTTP/2 的区别
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 保护它们。
第 1 步 — 安装最新版本的 Nginx
Nginx 1.9.5 中引入了对 HTTP/2 协议的支持。 幸运的是,Ubuntu 16.04 中的默认存储库包含比此更高的版本,因此我们不必添加第三方存储库。
首先,更新 apt 打包系统中的可用包列表:
sudo apt-get update
然后,安装 Nginx:
sudo apt-get install nginx
安装过程完成后,您可以通过键入以下命令检查 Nginx 的版本:
sudo nginx -v
输出应类似于以下内容:
sudo nginx -v 的输出
nginx version: nginx/1.10.0 (Ubuntu)
在接下来的几个步骤中,我们将修改 Nginx 配置文件。 每一步都会改变一个 Nginx 配置选项。 我们将一路测试配置文件的语法。 最后,我们将验证 Nginx 是否支持 HTTP/2 并进行一些更改以优化性能。
第 2 步 — 更改侦听端口并启用 HTTP/2
我们要做的第一个更改是将监听端口从 80
更改为 443
。
让我们打开配置文件:
sudo nano /etc/nginx/sites-available/default
默认情况下,Nginx 设置为监听 80 端口,这是标准的 HTTP 端口:
/etc/nginx/sites-available/default
listen 80 default_server; listen [::]:80 default_server;
如您所见,我们有两个不同的 listen
变量。 第一个适用于所有 IPv4 连接。 第二个用于 IPv6 连接。 我们将为两者启用加密。
修改监听端口为443
,HTTPS协议使用:
/etc/nginx/sites-available/default
listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server;
请注意,除了 ssl
之外,我们还在该行中添加了 http2
。 这个变量告诉 Nginx 在支持的浏览器上使用 HTTP/2。
第 3 步 — 更改服务器名称
我们使用 server_name
条目来指定应该与配置文件关联的域。 在配置文件中找到 server_name
条目。
默认情况下,server_name
设置为 _
(下划线),这意味着配置文件负责所有传入的请求。 将 _
更改为您的实际域,如下所示:
/etc/nginx/sites-available/default
server_name example.com;
保存配置文件并编辑文本编辑器。
每当您更改 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
第 4 步 — 添加 SSL 证书
接下来,您需要配置 Nginx 以使用您的 SSL 证书。 如果您不知道 SSL 证书是什么或目前没有,请遵循本文先决条件部分中的教程之一。
在 Nginx 配置目录中创建一个目录来存储 SSL 证书:
sudo mkdir /etc/nginx/ssl
将您的证书和私钥复制到此位置。 我们还将重命名文件以显示它们关联的域。 当您有多个域与此服务器关联时,这将在未来派上用场。 将 example.com
替换为您的实际主机名:
sudo cp /path/to/your/certificate.crt /etc/nginx/ssl/example.com.crt sudo cp /path/to/your/private.key /etc/nginx/ssl/example.com.key
现在,让我们再次打开我们的配置文件并配置 SSL。
sudo nano /etc/nginx/sites-available/default
在 server
块内的新行上,定义证书的位置:
/etc/nginx/sites-available/default
ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key;
保存文件,然后退出文本编辑器。
第 5 步 — 避免使用旧密码套件
HTTP/2 有一个 巨大的黑名单 旧的和不安全的密码,所以我们必须避免它们。 密码套件是一组加密算法,描述了应如何加密传输数据。
我们将使用一个非常流行的密码集,其安全性得到了 CloudFlare 等互联网巨头的认可。 它不允许使用 MD5 加密(自 1996 年以来就被称为不安全,但尽管如此,它的使用直到今天仍然很普遍)。
打开以下配置文件:
sudo nano /etc/nginx/nginx.conf
在 ssl_prefer_server_ciphers on;
之后添加这一行。
/etc/nginx/nginx.conf
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
保存文件,然后退出文本编辑器。
再次检查配置是否有语法错误:
sudo nginx -t
第 6 步 — 提高密钥交换安全性
建立安全连接的第一步是在服务器和客户端之间交换私钥。 问题是,到目前为止,它们之间的连接没有加密——这意味着任何第三方都可以看到数据的传输。 这就是为什么我们需要 Diffie-Hellman-Merkle 算法。 关于它如何工作的技术细节是一个复杂的事情,不能一概而论,但如果你真的对细节感兴趣,你可以观看这个YouTube视频。
默认情况下,Nginx 使用 1028 位 DHE(Ephemeral Diffie-Hellman)密钥,解密相对容易。 为了提供最大的安全性,我们应该构建自己的、更安全的 DHE 密钥。
为此,请发出以下命令:
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
请记住,我们应该在与 SSL 证书相同的文件夹中生成 DH 参数。 在本教程中,证书位于 /etc/nginx/ssl/
。 这样做的原因是 Nginx 总是在证书文件夹中查找用户提供的 DHE 密钥并在存在时使用它。
文件路径后面的变量(在我们的例子中是 2048
)指定密钥的长度。 具有 2048 位长度的密钥足够安全,并且 由 Mozilla 基金会 推荐,但如果您正在寻找更多加密,您可以将其更改为 4096
。
生成过程大约需要 5 分钟。
完成后,再次打开默认的 Nginx 配置文件:
sudo nano /etc/nginx/sites-available/default
在 server
块内的新行上,定义自定义 DHE 键的位置:
/etc/nginx/sites-available/default
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
第 7 步 — 将所有 HTTP 请求重定向到 HTTPS
由于我们只对通过 HTTPS 提供内容感兴趣,我们应该告诉 Nginx 如果服务器收到 HTTP 请求它应该做什么。
在我们文件的底部,我们将创建一个新的服务器块,用于将所有 HTTP 请求重定向到 HTTPS(确保将服务器名称替换为您的实际域名):
/etc/nginx/sites-available/default
server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; }
保存文件,退出配置文件。
检查配置是否有语法错误:
sudo nginx -t
第 8 步 - 重新加载 Nginx
这就是所有 Nginx 配置更改的内容。 由于我们检查了每次更改的语法错误,您应该准备好重新启动 Nginx 并测试您的更改。
总而言之,忽略注释掉的行,您的配置文件现在应该类似于以下内容:
/etc/nginx/sites-available/default
server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name example.com; location / { try_files $uri $uri/ =404; } ssl_certificate /etc/nginx/ssl/example.com.crt; ssl_certificate_key /etc/nginx/ssl/example.com.key; ssl_dhparam /etc/nginx/ssl/dhparam.pem; } server { listen 80; listen [::]:80; server_name example.com; return 301 https://$server_name$request_uri; }
要应用更改,请重新启动 Nginx 服务器。
sudo systemctl restart nginx
第 9 步 - 验证更改
让我们检查一下我们的服务器是否已启动并正在运行。 打开您的网络浏览器并导航到您的域(将 example.com
替换为您的实际域名):
example.com
如果一切配置正确,您应该会自动重定向到 HTTPS。 现在,让我们检查 HTTP/2 是否正常工作:打开 Chrome 开发者工具(View -> Developer -> Developer Tools)并重新加载页面([ X160X]查看 -> 重新加载此页面)。 然后导航到 Network 选项卡,单击以 Name 开头的表头行,右键单击它,然后选择 Protocol 选项。
现在您应该在您的网站提供 HTTP/2 内容的新列中看到 h2
(代表 HTTP/2)。
至此,我们的服务器已经准备好通过 HTTP/2 协议提供内容,但是我们还需要做一些事情来准备服务器以用于生产。
第 10 步 — 优化 Nginx 以获得最佳性能
在这一步中,我们将调整主要的 Nginx 配置文件以获得最佳性能和安全性。
首先,让我们通过在控制台中键入以下内容来打开 nginx.conf
:
sudo nano /etc/nginx/nginx.conf
启用连接凭据缓存
与 HTTP 相比,HTTPS 在服务器和用户之间建立初始连接所需的时间相对较长。 为了最大限度地减少页面加载速度的差异,我们将启用连接凭据的缓存。 这意味着服务器不会在每个请求的页面上创建新会话,而是使用缓存版本的凭据。
要启用会话缓存,请在 nginx.conf
文件的 http
块的末尾添加以下行:
/etc/nginx/nginx.conf
ssl_session_cache shared:SSL:5m; ssl_session_timeout 1h;
ssl_session_cache
指定将包含会话信息的缓存大小。 其中 1 MB 可以存储大约 4000 个会话的信息。 5 MB 的默认值对于大多数用户来说已经绰绰有余,但如果您预计流量非常大,您可以相应地增加此值。
ssl_session_timeout
限制特定会话存储在缓存中的时间。 这个值不应该太大(超过一个小时),但是将值设置得太低也是没有意义的。
启用 HTTP 严格传输安全 (HSTS)
即使我们已经在 Nginx 配置文件中将所有常规 HTTP 请求重定向到 HTTPS,我们也应该启用 HTTP Strict Transport Security 以避免首先进行这些重定向。
如果浏览器找到一个 HSTS 标头,它将不会在给定的时间段内再次尝试通过常规 HTTP 连接到服务器。 无论如何,它将仅使用加密的 HTTPS 连接交换数据。 这个标头还应该保护我们免受协议降级攻击。
在 nginx.conf
中添加这一行:
/etc/nginx/nginx.conf
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 restart nginx
结论
你的 Nginx 服务器现在提供 HTTP/2 页面。 如果您想测试 SSL 连接的强度,请访问 Qualys SSL Lab 并针对您的服务器运行测试。 如果一切配置正确,您应该获得 A+ 安全标记。