解决OpenSSL创建的自签名证书在chrome端无法信任的问题

OpenSSL 创建自签名证书的方法在 chrome 上会遇到了证书无效的错误:

原因概述

Chrome浏览器要求证书中必须包含 “Subject Alternative Names” 这一参数。

解决方案

修改待用的openssl配置文件

1 拷贝openssl配置文件以备修改

1
sudo cp /etc/pki/tls/openssl.cnf  /etc/pki/tls/openssl_bak.cnf

2 修改 openssl.cnf 文件

1
sudo vim /etc/pki/tls/openssl.cnf

(1) 找到[ req ] 段落,添加如下配置:

1
req_extentions = v3_req

(2) 添加 v3_req 配置信息

1
2
3
4
5
[ v3_req ]
# Extensions to add to a certificate request
# basicConstraints = CA:FALSE
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

(3) 添加 alt_names 配置信息

1
2
[ alt_names ]
DNS.1 = linux111.esrichina.com

注:这里填入的即为 Subject Alternative Names 的域名名称

创建自签名SSL证书

创建自签名证书

创建存放证书的文件夹

打算把创建好的SSL证书放在 /etc/ssl/private 文件夹中,CentOS 7中没有这个文件夹,所以先创建好:

1
sudo mkdir /etc/ssl/private

在命令中使用 OpenSSL 创建自签名密钥和证书(此处有效期3650天):

1
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt  -extensions v3_req

在我们继续操作之前,让我们看看命令中发生了什么:

  • openssl:这是用于创建和管理 OpenSSL 证书、密钥和其他文件的基本命令工具。

  • req:此子命令指定我们要使用X.509证书签名请求管理。“X.509”是SSL和TLS为其密钥和证书管理所遵循的公钥基础结构标准。我们想要创建一个新的 X.509 证书,所以我们使用这个子命令。

  • -x509:这通过告诉实用程序我们要创建自签名证书而不是生成证书签名请求来进一步修改上一个子命令。

  • -nodes:这告诉 OpenSSL 跳过用密码保护我们的证书的选项。当服务器启动时,我们需要 Nginx 能够在没有用户干预的情况下读取文件。密码短语会阻止这种情况发生,因为我们必须在每次重启后输入密码。

  • -days 3650:此选项设置证书的有效时间长度。我们在这里设置了十年。

  • -newkey rsa:2048:这指定我们要同时生成新证书和新密钥。我们没有创建在上一步中签署证书所需的密钥,因此我们需要将其与证书一起创建。该rsa:2048部分告诉它制作一个2048位长的RSA密钥。

  • -keyout:这一行告诉 OpenSSL 在哪里放置我们正在创建的生成的私钥文件。

  • -out:这告诉 OpenSSL 在哪里放置我们正在创建的证书。

如上所述,这些选项将创建密钥文件和证书。我们将询问有关我们服务器的一些问题,以便将信息正确地填入到证书中。

最重要的一行是请求Common Name (e.g. server FQDN or YOUR name)。您需要输入与服务器关联的域名,或者是您服务器的公共IP地址。

整个提示将如下所示:

1
2
3
4
5
6
7
Country 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 组,用于与客户协商完整的保密。

通过输入以下内容来执行

1
sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

这可能需要几分钟,一旦完成,您将拥有一个强大的DH组。/etc/ssl/certs/dhparam.pem 可以在我们的配置中使用。

配置 Nginx 以使用 SSL

我们在/etc/ssl目录下创建了密钥和证书文件。现在我们只需要修改我们的Nginx配置就可以使用它们。

我们将对配置进行一些调整。

  1. 我们将创建一个包含 SSL 密钥和证书文件位置的配置代码。

  2. 我们将创建一个包含强 SSL 设置的配置代码,可以在将来与任何证书一起使用。

  3. 我们将调整我们的 Nginx 配置文件来处理 SSL 请求并使用上面的两个代码段。

这种配置 Nginx 的方法将允许将常见配置段放入可重用模块中。

创建指向SSL密钥和证书的配置代码

首先,让我们在 /etc/nginx/snippets目录中创建一个新的 Nginx 配置代码。

为了正确区分此文件,我们称之为 self-signed.conf

1
sudo vim /etc/nginx/snippets/self-signed.conf

在这个文件中,我们只需要将 ssl_certificate 设置为我们的证书文件和 ssl_certificate_key 相关的密钥。在我们的例子中,是这样的:

1
2
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

添加这些行后,保存并关闭该文件。

使用强加密设置创建配置代码

接下来,我们将创建另一个代码,用于定义一些SSL设置。这将使Nginx更加安全,并启用一些有助于保证我们的服务器安全的高级功能。

我们为了使设置的参数可以在将来的Nginx配置中重用,因此我们将为该文件指定一个通用名称:

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

对其进行修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now. You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

调整Nginx配置以使用SSL

打开 nginx 配置文件进行调整

1
sudo vim /etc/nginx/nginx.cnf

在里面,原来的nginx配置文件开始可能像这样:

1
2
3
4
5
6
7
8
9
10
server {
listen 80 default_server;
listen [::]:80 default_server;

# SSL configuration

# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;

. . .

修改此配置,以便将未加密的HTTP请求自动重定向到加密的HTTPS。这为我们的网站提供了最佳安全性。如果要同时允许HTTP和HTTPS流量,请使用后面的配置。
将把配置分成两个独立的块。在两个第一个listen指令之后,我们将添加一个server_name指令,设置为服务器的域名,或者是IP地址。然后,我们将设置重定向到我们将要创建的第二个Nginx配置文件。之后,我们将关闭这个短块:

注意:我们将使用302重定向,直到我们确认网站正常。我们可以将其更改为永久301重定向。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 302 https://192.168.0.100;
}

server {
ssl on;
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name _;
root /usr/share/nginx/html;
charset utf-8,gbk;
include /etc/nginx/snippets/self-singed.conf;
include /etc/nginx/snippets/ssl-params.conf;
# Load configuration files for the default server block
include /etc/nginx/default.d/*.conf;

location / {
}

error_page 404 /404.html;
location = /40x.html {
}

error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}

完成后保存并关闭文件。

启用Nginx中的更改

首先,我们应该检查以确保我们的文件中没有语法错误。我们可以通过输入以下内容来执

1
sudo nginx -t

如果一切顺利,您将得到如下结果:

1
2
3
nginx: [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

如果输出与上述内容匹配,则配置文件没有语法错误。我们可以安全地重启Nginx以实现我们的更改:

1
sudo systemctl restart nginx

我们的服务器现在可以通过HTTPS访问。

更改为永久重定向

如果您的重定向工作正常并且您确定只想允许加密流量,则应修改 Nginx 配置以使永久重定向。

再次打开 Nginx配置文件配置文件:

1
sudo vim /etc/nginx/nginx.conf

找到return 302并将其更改为return 301:

1
2
3
4
5
6
7
8
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name server_domain_or_IP;
return 301 https://$server_name$request_uri;
}

. . .

保存并关闭文件。

检查配置是否存在语法错误:

1
sudo nginx -t

准备好后,重新启动Nginx以使重定向永久化:

1
sudo systemctl restart nginx

您的站点现在应该在通过HTTP访问时永久重定向到HTTPS。

参考资料:

  1. OpenSSL创建的自签名证书在chrome端无法信任

  2. 如何为Nginx创建自签名SSL证书

  3. 给Nginx配置一个自签名的SSL证书

===END===