原文:How To Set Up Nginx with HTTP/2 Support on Ubuntu 16.04 | DigitalOcean
作者:Sergey Zhukaev
介绍
NGINX 是一个快速可靠的开源Web服务器。由于其内存占用空间小,可扩展性高,易于配置,并支持绝大多数协议,因此受到欢迎。
本教程将帮助您部署一个支持HTTP / 2 的快速,安全的 Nginx 服务器。
前提
在开始之前,我们需要几件事情:
- Ubuntu 16.04 Droplet
- 具有sudo权限的非root用户(有关详细信息,请查看Ubuntu 16.04初始服务器设置。)
- 完全注册域名 您可以在 Namecheap
上购买一张或在 Freenom 上免费获得一张。 - 确保您的域名配置为指向您的Droplet。如果需要帮助,请参阅本教程。
- SSL证书。生成自签名证书,从“我们加密”获取一个免费的证书,或从另一个提供商处购买一个。
就这些。如果您有上面列出的所有内容,您随时可以去。
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不需要加密,但两款最受欢迎的浏览器(Chrome浏览器和Mozilla Firefox)的开发人员表示,为了安全起见,他们将仅为HTTPS 连接提供HTTP / 2支持。因此,如果您决定在服务器支持HTTP / 2,则必须使用HTTPS。
步骤1 - 安装最新版本的Nginx
在Nginx 1.9.5中加入了HTTP / 2协议的支持。幸运的是,Ubuntu 16.04中的默认镜像源包含的nginx版本高于此版本,因此我们不必添加第三方镜像源。
首先,在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连接。我们将为两者启用加密。
修改监听端口为HTTPS协议使用的443:
// 在/etc/nginx/sites-available/default中
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
注意,除 ssl
之外,我们还加入 http2
。该变量告诉Nginx对支持HTTP2
协议的浏览器启用HTTP / 2。
步骤3 - 更改服务器名称
我们使用server_name
条目来指定哪个域名与配置文件相关联。找到server_name
配置文件中的条目。
默认情况下,server_name
设置为 _
(下划线),这意味着配置文件负责所有传入的请求。更改 _
为你的实际域名,如下所示:
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证书,或者目前没有SSL证书,请按照本文“前提”部分中的其中一个教程进行操作。
创建一个目录以将您的SSL证书存储在Nginx配置目录中:
$ 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(短暂的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请求应该做什么。
在我们的文件底部,我们将创建一个新的server
块,用于将所有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)并重新加载页面(View - > Reload This Page)。然后导航到 Network
选项卡,指向从Name
开始的表头所在行,右键单击它,然后选择 Protocol
选项。
现在您应该看到h2
(代表HTTP / 2)的新列,表示您的网站提供HTTP / 2服务。
在这一点上,我们的服务器已经准备好通过HTTP / 2协议提供内容了,但是我们仍然需要为生产环境的服务器做一些准备。
步骤10 - 优化Nginx以获得最佳性能
首先,我们 nginx.conf
通过在控制台中键入以下内容来打开它们:
在此步骤中,我们将调整主Nginx配置文件,以获得最佳性能和安全性。
$ sudo nano /etc/nginx/nginx.conf
启用连接凭据缓存
与HTTP相比,HTTPS需要相对较长的时间来建立服务器和用户之间的初始连接。为了最小化页面加载速度的差异,我们将启用连接凭据的缓存。这意味着,不是在所请求的每个页面上创建一个新的会话,服务器将使用缓存版本的凭据。
要启用会话缓存,http
请在 nginx.conf
文件块的末尾添加这些行:
// 在/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)
即使我们已经将所有常规HTTP请求重定向到我们的Nginx配置文件中的HTTPS,我们还应该启用HSTS,以避免这些重定向操作。
如果浏览器找到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实验室,并针对您的服务器运行测试。如果一切配置正确,您应该获得一个A +标记的安全。