SSL证书制作及nginx中部署
本文主要介绍了SSL证书的制作及如何将证书部署在nginx中,并简要说明在制作及部署过程中可能遇到的问题。
SSL证书制作
-
推荐在Linux环境上制作SSL证书,本文使用的是CentOS。
-
安装openssl:
#更新系统中的软件包,以确保你安装的是最新的版本 sudo yum update#安装 OpenSSL sudo yum install openssl#查看版本信息,确认安装成功 openssl version
-
接下来是制作SSL证书
生成 SSL 证书的步骤
# 生成私钥 (Private Key) openssl genpkey -algorithm RSA -out private.key -aes256
private.key
是生成的私钥文件。-aes256
参数表示使用 AES 256 加密私钥文件。
# 生成证书签名请求 (CSR - Certificate Signing Request) openssl req -new -key private.key -out certificate.csr
-
certificate.csr
是生成的 CSR 文件。 -
在执行此命令时,系统会提示输入一些信息,如国家代码、州、省、市、组织名、单位名、域名 (Common Name),以及邮箱地址。这些信息将包含在证书中。
# 生成自签名证书 (Self-signed Certificate) openssl x509 -req -days 365 -in certificate.csr -signkey private.key -out certificate.crt
-
certificate.crt
是生成的自签名证书文件。 -
-days 365
参数表示证书的有效期为 365 天,可以根据需要调整。
# 合并私钥和证书到一个文件 (按需) cat private.key certificate.crt > combined.pem
生成过程中可能用到的命令选项
-newkey rsa:2048
:生成一个新的 RSA 密钥对,密钥长度为 2048 位。-nodes
:如果不想加密私钥文件,可以添加此参数。-sha256
:使用 SHA-256 算法生成 CSR。
验证生成的证书
可以使用以下命令验证生成的证书:
bash复制代码# 查看证书内容 openssl x509 -in certificate.crt -text -noout# 查看私钥内容 openssl rsa -in private.key -check# 查看 CSR 内容 openssl req -text -noout -verify -in certificate.csr
生成的各文件的作用
- .key 文件 (私钥文件):
- 作用: 这是一个私钥文件,包含了生成 SSL 证书的私钥。私钥应当保密,不应泄露。
- 位置: 服务器上安全的地方,例如
/etc/nginx/ssl/private.key
。 - 用途: 私钥用于解密 SSL/TLS 会话。
- .csr 文件 (证书签名请求文件):
- 作用: 这是一个证书签名请求文件,包含公钥以及组织信息。这是提交给证书颁发机构 (CA) 的文件,用于申请 SSL 证书。
- 位置: 用于申请证书过程中,申请完后可以保留以备未来使用。
- 用途: 用于向 CA 提交申请以获得 SSL 证书。
- .crt 文件 (证书文件):
- 作用: 这是由 CA 签发的公钥证书文件,包含了你的公钥以及 CA 的签名。
- 位置: 服务器上配置到 Nginx 或其他服务的地方,例如
/etc/nginx/ssl/certificate.crt
。 - 用途: 这是公开的证书,用于客户端验证服务器的真实性。
- .pem 文件 (合成文件):
- 作用: PEM 文件通常是包含私钥和公钥证书的合成文件,方便一些软件和服务读取所有需要的信息。
- 位置: 服务器上需要读取私钥和公钥证书的地方,例如
/etc/nginx/ssl/combined.pem
。 - 用途: 提供了私钥和证书的综合访问,可以用于许多支持 PEM 格式的服务。
-
上述生成的SSL证书在部署在nginx后,在启动nginx时可能会报错:
cannot load certificate key "C:\AnGongYuan\nginx-1.23.0/conf/private.key": PEM_read_bio_PrivateKey() failed (SSL: error:2807106B:UI routines:UI_process:processing error:while reading strings error:0906406D:PEM routines:PEM_def_callback:problems getting password error:0907B068:PEM routines:PEM_read_bio_PrivateKey:bad password read)
这个错误消息表明,Nginx 在尝试读取你的私钥文件时遇到了问题,具体来说是因为私钥文件受密码保护而 Nginx 无法正确处理密码。
解决方案是: 生成不受密码保护的私钥文件,配置到nginx中
openssl rsa -in private.key -out private_no_passphrase.key
-
综合上述过程,可以将整个过程整合到shell脚本中,如下:
#!/bin/bash# 用户输入的信息(根据需要修改) COUNTRY="CN" STATE="Beijing" LOCALITY="Beijing" ORGANIZATION="MyCompany" ORG_UNIT="IT" COMMON_NAME="192.168.1.1" # 可以是域名或IP地址 EMAIL="admin@example.com" DAYS=365 # 证书有效期# 生成私钥 openssl genpkey -algorithm RSA -out private.key -aes256# 生成证书签名请求 (CSR) openssl req -new -key private.key -out certificate.csr -subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORGANIZATION/OU=$ORG_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"# 生成自签名证书 openssl x509 -req -days $DAYS -in certificate.csr -signkey private.key -out certificate.crt# 生成不带密码保护的私钥 openssl rsa -in private.key -out private_no_passphrase.key# 验证生成的证书 echo "验证证书内容:" openssl x509 -in certificate.crt -text -nooutecho "验证私钥内容:" openssl rsa -in private.key -checkecho "验证CSR内容:" openssl req -text -noout -verify -in certificate.csrecho "SSL 证书生成完毕!"
使用上述脚本生成SSL证书过程中,会出现若干次让输入密码的情况,根据自己需要进行输入,也可以使用下面调整后的脚本,将密码提前存入脚本中
#!/bin/bash# 用户输入的信息(根据需要修改) COUNTRY="CN" STATE="Beijing" LOCALITY="Beijing" ORGANIZATION="MyCompany" ORG_UNIT="IT" COMMON_NAME="192.168.1.1" # 可以是域名或IP地址 EMAIL="admin@example.com" DAYS=365 # 证书有效期 PASSPHRASE="your_secure_password" # 私钥密码# 生成加密的私钥 openssl genpkey -algorithm RSA -out private.key -aes256 -pass pass:$PASSPHRASE# 生成证书签名请求 (CSR) openssl req -new -key private.key -out certificate.csr -passin pass:$PASSPHRASE -subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORGANIZATION/OU=$ORG_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"# 生成自签名证书 openssl x509 -req -days $DAYS -in certificate.csr -signkey private.key -passin pass:$PASSPHRASE -out certificate.crt# 生成不带密码保护的私钥 openssl rsa -in private.key -passin pass:$PASSPHRASE -out private_no_passphrase.key# 验证生成的证书 echo "验证证书内容:" openssl x509 -in certificate.crt -text -nooutecho "验证私钥内容:" openssl rsa -in private_no_passphrase.key -checkecho "验证CSR内容:" openssl req -text -noout -verify -in certificate.csrecho "SSL 证书生成完毕!"
nginx中部署SSL证书
下面是在nginx中部署上面生成的证书,给出的是nginx.conf
的部分配置,此配置支持从http的80端口跳转到https的443端口:
# HTTPS serverserver {listen 443 ssl;server_name 192.168.14.17;ssl_certificate certificate.crt;ssl_certificate_key private_no_passphrase.key;ssl_session_cache shared:SSL:10m;ssl_session_timeout 10m;ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';ssl_prefer_server_ciphers on;ssl_stapling on;ssl_stapling_verify on;resolver 8.8.8.8 8.8.4.4 valid=300s;resolver_timeout 5s;add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload" always;add_header X-Frame-Options DENY;add_header X-Content-Type-Options nosniff;add_header X-XSS-Protection "1; mode=block";add_header Referrer-Policy no-referrer-when-downgrade;# Proxy pass for other requestslocation / {proxy_pass http://127.0.0.1:13000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}}server {listen 80;server_name 192.168.14.17;location / {return 301 https://$host$request_uri;}}