本教程的先前版本由Justin Ellingwood编写
介绍
TLS或传输层安全性及其前身SSL (代表安全套接字层)是用于将正常流量包装在受保护的加密包装中的Web协议。
使用这种技术,服务器可以在服务器和客户端之间安全地发送流量,而不会被外部各方拦截。 证书系统还可以帮助用户验证他们正在连接的站点的身份。
在本指南中,我们将向您展示如何设置自签名SSL证书,以便与Ubuntu 18.04服务器上的Nginx Web服务器一起使用。
注意:自签名证书将加密服务器与任何客户端之间的通信。 但是,由于Web浏览器不包含任何受信任的证书颁发机构的签名,因此用户无法使用该证书自动验证服务器的身份。
如果您没有与服务器关联的域名以及加密Web界面不面向用户的实例,则可能需要使用自签名证书。 如果您有域名,在许多情况下最好使用CA签名的证书。 您可以在此处了解如何使用Let's Encrypt项目设置免费的可信证书。
先决条件
在开始之前,您应该有一个配置了sudo
权限的非root用户。 您可以按照Ubuntu 18.04的初始服务器设置了解如何设置此类用户帐户。
您还需要安装Nginx Web服务器。 如果您想在服务器上安装整个LEMP(Linux,Nginx,MySQL,PHP),可以按照我们在Ubuntu 18.04上设置LEMP的指南进行操作。
如果您只是想要Nginx Web服务器,您可以按照我们的指南在Ubuntu 18.04上安装Nginx 。
完成先决条件后,请继续以下操作。
第1步 - 创建SSL证书
TLS / SSL通过使用公共证书和私钥的组合来工作。 SSL密钥在服务器上保密。 它用于加密发送给客户端的内容。 SSL证书与请求内容的任何人公开共享。 它可用于解密由关联的SSL密钥签名的内容。
我们可以在一个命令中使用OpenSSL创建自签名密钥和证书对:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
您将被问到一系列问题。 在我们讨论之前,让我们看看我们发出的命令中发生了什么:
- openssl :这是用于创建和管理OpenSSL证书,密钥和其他文件的基本命令行工具。
- req :此子命令指定我们要使用X.509证书签名请求(CSR)管理。 “X.509”是SSL和TLS为其密钥和证书管理所遵循的公钥基础结构标准。 我们想要创建一个新的X.509证书,所以我们使用这个子命令。
- -x509 :这通过告诉实用程序我们要创建自签名证书而不是生成证书签名请求(通常会发生)来进一步修改上一个子命令。
- -nodes :这告诉OpenSSL跳过用密码保护我们的证书的选项。 当服务器启动时,我们需要Nginx能够在没有用户干预的情况下读取文件。 密码短语会阻止这种情况发生,因为我们必须在每次重启后输入密码。
- -days 365 :此选项设置证书被视为有效的时间长度。 我们在这里设置了一年。
- -newkey rsa:2048 :这指定我们要同时生成新证书和新密钥。 我们没有创建在上一步中签署证书所需的密钥,因此我们需要将其与证书一起创建。
rsa:2048
部分告诉它生成一个2048位长的RSA密钥。 - -keyout :这一行告诉OpenSSL在哪里放置我们正在创建的生成的私钥文件。
- -out :这告诉OpenSSL在哪里放置我们正在创建的证书。
如上所述,这些选项将创建密钥文件和证书。 我们将询问有关我们服务器的一些问题,以便将信息正确地嵌入到证书中。
适当填写提示。 最重要的一行是请求Common Name (eg server FQDN or YOUR name)
。 您需要输入与服务器关联的域名,或者更可能是您服务器的公共IP地址。
整个提示将如下所示:
OutputCountry Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:New York
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc.
Organizational Unit Name (eg, section) []:Ministry of Water Slides
Common Name (e.g. server FQDN or YOUR name) []:server_IP_address
Email Address []:admin@your_domain.com
您创建的两个文件都将放在/etc/ssl
目录的相应子目录中。
在我们使用OpenSSL的同时,我们还应该创建一个强大的Diffie-Hellman组,用于与客户协商Perfect Forward Secrecy 。
我们可以通过键入以下内容来执
sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096
这需要一段时间,但一旦完成,您将在/etc/nginx/dhparam.pem
上有一个强大的DH小组,我们可以在我们的配置中使用它。
第2步 - 配置Nginx以使用SSL
我们在/etc/ssl
目录下创建了密钥和证书文件。 现在我们只需要修改我们的Nginx配置就可以利用它们。
我们将对配置进行一些调整。
- 我们将创建一个包含SSL密钥和证书文件位置的配置代码段。
- 我们将创建一个包含强SSL设置的配置代码段,可以在将来与任何证书一起使用。
- 我们将调整我们的Nginx服务器块来处理SSL请求并使用上面的两个片段。
这种配置Nginx的方法将允许我们保持干净的服务器块并将常见配置段放入可重用模块中。
创建指向SSL密钥和证书的配置代码段
首先,让我们在/etc/nginx/snippets
目录中创建一个新的Nginx配置代码/etc/nginx/snippets
。
为了正确区分此文件的目的,我们将其称为self-signed.conf
:
sudo nano /etc/nginx/snippets/self-signed.conf
在此文件中,我们需要将ssl_certificate
指令设置为我们的证书文件,将ssl_certificate_key
设置为关联的密钥。 在我们的例子中,这将是这样的:
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
添加这些行后,保存并关闭该文件。
使用强加密设置创建配置代码段
接下来,我们将创建另一个片段,用于定义一些SSL设置。 这将使Nginx具有强大的SSL密码套件,并启用一些有助于保证我们的服务器安全的高级功能。
我们将设置的参数可以在将来的Nginx配置中重用,因此我们将为该文件指定一个通用名称:
sudo nano /etc/nginx/snippets/ssl-params.conf
要安全地设置Nginx SSL,我们将使用Remy van Elst在Cipherli.st网站上的推荐 。 此站点旨在为流行软件提供易于使用的加密设置。
链接到上述网站的建议设置提供了强大的安全性。 有时,这是以更高的客户端兼容性为代价的。 如果您需要支持较旧的客户端,可以通过单击标记为“是的,给我一个与旧版/旧版软件一起使用的密码套件”的页面上的链接来访问该列表。 该列表可以替换下面复制的项目。
您使用哪种配置的选择在很大程度上取决于您需要支持的内容。 它们都将提供很大的安全性。
出于我们的目的,我们可以完整地复制提供的设置。 我们只需要进行一些小的修改。
首先,我们将为上游请求添加我们首选的DNS解析器。 我们将使用Google作为本指南。
其次,我们将注释掉设置严格传输安全头的行。 在取消注释此行之前,您应花点时间阅读HTTP严格传输安全性或HSTS ,特别是有关“预加载”功能的信息 。 预加载HSTS可提高安全性,但如果意外启用或启用错误,可能会产生深远的影响。
将以下内容复制到ssl-params.conf
片段文件中:
ssl_protocols TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparam.pem;
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;
ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off; # Requires nginx >= 1.5.9
ssl_stapling on; # Requires nginx >= 1.3.7
ssl_stapling_verify on; # Requires nginx => 1.3.7
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable strict transport security for now. You can uncomment the following
# line if you understand the implications.
# add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
由于我们使用的是自签名证书,因此不会使用SSLStapling。 Nginx将输出警告,为我们的自签名证书禁用Stapling,并继续正常运行。
完成后保存并关闭文件。
调整Nginx配置以使用SSL
现在我们已经有了我们的代码片段,我们可以调整我们的Nginx配置来启用SSL。
我们将在本指南中假设您在/etc/nginx/sites-available
目录中使用自定义服务器块配置文件。 我们将在此示例中使用/etc/nginx/sites-available/example.com
。 根据需要替换配置文件名。
在我们继续之前,让我们备份当前的配置文件:
sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.com.bak
现在,打开配置文件进行调整:
sudo nano /etc/nginx/sites-available/example.com
在里面,你的服务器块可能开始类似于:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
. . .
}
您的文件可能采用不同的顺序,而不是root
和index
指令,您可能有一些location
, proxy_pass
或其他自定义配置语句。 这没关系,因为我们只需更新listen
指令并包含我们的SSL代码段。 我们将修改此现有服务器块以在端口443上提供SSL流量,然后创建新的服务器块以在端口80上进行响应并自动将流量重定向到端口443。
注意:我们将使用302重定向,直到我们确认一切正常。 之后,我们可以将其更改为永久301重定向。
在现有配置文件中,更新两个listen
语句以使用端口443和ssl,然后包含我们在前面步骤中创建的两个片段文件:
server {
listen 443 ssl;
listen [::]:443 ssl;
include snippets/self-signed.conf;
include snippets/ssl-params.conf;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.htm index.nginx-debian.html;
. . .
}
接下来,在第一个块的右括号( }
)之后,将第二个服务器块粘贴到配置文件中:
. . .
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 302 https://$server_name$request_uri;
}
这是一个简单的配置,可以监听端口80并执行重定向到HTTPS。 完成编辑后保存并关闭文件。
第3步 - 调整防火墙
如果启用了ufw
防火墙,则必须按照先决条件指南的建议,调整设置以允许SSL流量。 幸运的是,Nginx在安装时会注册一些ufw
配置文件。
我们可以通过键入来查看可用的配置文件
sudo ufw app list
您应该看到如下列表:
OutputAvailable applications:
Nginx Full
Nginx HTTP
Nginx HTTPS
OpenSSH
您可以键入以下内容来查看当前设置:
sudo ufw status
它可能看起来像这样,这意味着只允许HTTP流量进入Web服务器:
OutputStatus: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx HTTP ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx HTTP (v6) ALLOW Anywhere (v6)
为了进一步允许HTTPS流量,我们可以允许“Nginx Full”配置文件,然后删除冗余的“Nginx HTTP”配置文件限额:
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
您的状态现在应该如下所示:
sudo ufw status
OutputStatus: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
Nginx Full ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Nginx Full (v6) ALLOW Anywhere (v6)
第4步 - 启用Nginx中的更改
现在我们已经进行了更改并调整了防火墙,我们可以重新启动Nginx以实现我们的新更改。
首先,我们应该检查以确保我们的文件中没有语法错误。 我们可以通过键入以下内容来执
sudo nginx -t
如果一切顺利,您将得到如下结果:
Outputnginx: [warn] "ssl_stapling" ignored, issuer certificate not found
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
在开头注意警告。 如前所述,由于我们的自签名证书无法使用SSLStapling,因此此特定设置会发出警告。 这是预期的,我们的服务器仍然可以正确加密连接。
如果输出与上述内容匹配,则配置文件没有语法错误。 我们可以安全地重启Nginx以实现我们的更改:
sudo systemctl restart nginx
第5步 - 测试加密
现在,我们已准备好测试我们的SSL服务器。
打开Web浏览器,在地址栏中输入https://
然后输入服务器的域名或IP:
https://server_domain_or_IP
由于我们创建的证书未由您的某个浏览器的受信任证书颁发机构签名,因此您可能会看到一个可怕的警告,如下所示:
这是预期和正常的。 我们只对证书的加密方面感兴趣,而不是对主机真实性的第三方验证感兴趣。 单击“高级”,然后提供链接以继续进入您的主机:
你应该被带到你的网站。 如果你在浏览器地址栏中查看,你会看到一个带有“x”的锁。 在这种情况下,这只意味着无法验证证书。 它仍在加密您的连接。
如果您使用两个服务器块配置Nginx,自动将HTTP内容重定向到HTTPS,您还可以检查重定向是否正常运行:
http://server_domain_or_IP
如果这导致相同的图标,这意味着您的重定向工作正常。
第6步 - 更改为永久重定向
如果您的重定向工作正常并且您确定只想允许加密流量,则应修改Nginx配置以使重定向永久化。
再次打开服务器块配置文件:
sudo nano /etc/nginx/sites-available/example.com
找到return 302
并将其更改为return 301
:
return 301 https://$server_name$request_uri;
保存并关闭文件。
检查配置是否存在语法错误:
sudo nginx -t
准备好后,重新启动Nginx以使重定向永久化:
sudo systemctl restart nginx
结论
您已将Nginx服务器配置为对客户端连接使用强加密。 这样您就可以安全地处理请求,并阻止外部人员阅读您的流量。