NGINX 指令 ssl_password_file 配置详解

ssl_password_file 是 NGINX 中的一个指令,用于指定一个包含密码的文件,这个文件用于提供 SSL/TLS 私钥的密码。该指令在 NGINX 启动时会读取该文件,并用于加载私钥文件时解锁加密的私钥。如果私钥是加密的,那么 NGINX 需要密码才能使用它,密码错误会导致nginx启动或者重新加载失败。

语法

Syntax: ssl_password_file file;
Default: —
Context: http, server
This directive appeared in version 1.7.3.

  • “:指定包含密码的文件路径。这个文件应该包含一个用于解锁 SSL 私钥的密码。
  • 指定一个包含密钥密码的文件,每个密码都位于单独的一行。在加载密钥时,密码将按顺序尝试。

默认值

  • 默认情况下,ssl_password_file 指令不被启用,即没有设置密码文件。

使用场景

该指令通常在以下情况下使用:
1. 私钥加密:当生成 SSL/TLS 私钥时,如果你为私钥设置了密码保护,那么每次 NGINX 启动时,都需要提供密码才能加载私钥。

配置示例

生成四组自签名证书及私钥, 其中RSA算法两个, ECC算法两个,两组证书中一个带密码,一个不带密码。使用脚本生成

#!/bin/bash

# Set directory variables
CERTS_DIR="/etc/nginx/ssl"

# Create the certificate directory if it doesn't exist
mkdir -p $CERTS_DIR

# Set passwords for different key types
PASSWORD_RSA_WITH="password123"
PASSWORD_ECC_WITH="password789"

# Create password files for multiple certificates
echo $PASSWORD_RSA_WITH > "$CERTS_DIR/rsa_password.txt"
chmod 600 "$CERTS_DIR/rsa_password.txt"
echo $PASSWORD_ECC_WITH > "$CERTS_DIR/ecc_password.txt"
chmod 600 "$CERTS_DIR/ecc_password.txt"
cat "$CERTS_DIR/rsa_password.txt" "$CERTS_DIR/ecc_password.txt" > "$CERTS_DIR/password_file.txt"

# Set certificate information
COUNTRY="CN"
STATE="BEIJING"
LOCALITY="BEIJING"
ORG="test"
ORG_UNIT="test-unit"
EMAIL="email@example.com"

# Generate RSA private key with password
openssl genpkey -algorithm RSA -aes256 -out "$CERTS_DIR/rsa_private_key_with_password.pem" -pass pass:$PASSWORD_RSA_WITH
echo "Generated RSA private key with password: rsa_private_key_with_password.pem"

# Generate RSA private key without password
openssl genpkey -algorithm RSA -out "$CERTS_DIR/rsa_private_key_without_password.pem"
echo "Generated RSA private key without password: rsa_private_key_without_password.pem"

# Generate RSA Certificate Signing Request (CSR) with password, avoiding interactive input
COMMON_NAME="example1.com"
openssl req -new -key "$CERTS_DIR/rsa_private_key_with_password.pem" -out "$CERTS_DIR/rsa_csr_with_password.pem" \
-passin pass:$PASSWORD_RSA_WITH \
-subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORG/OU=$ORG_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"
echo "Generated RSA CSR with password: rsa_csr_with_password.pem"

# Generate RSA CSR without password, avoiding interactive input
COMMON_NAME="example2.com"
openssl req -new -key "$CERTS_DIR/rsa_private_key_without_password.pem" -out "$CERTS_DIR/rsa_csr_without_password.pem" \
-subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORG/OU=$ORG_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"
echo "Generated RSA CSR without password: rsa_csr_without_password.pem"

# Use the RSA private key to sign the certificate
openssl x509 -req -in "$CERTS_DIR/rsa_csr_with_password.pem" -signkey "$CERTS_DIR/rsa_private_key_with_password.pem" -out "$CERTS_DIR/rsa_certificate_with_password.pem" -days 365 -passin pass:$PASSWORD_RSA_WITH
openssl x509 -req -in "$CERTS_DIR/rsa_csr_without_password.pem" -signkey "$CERTS_DIR/rsa_private_key_without_password.pem" -out "$CERTS_DIR/rsa_certificate_without_password.pem" -days 365
echo "Generated RSA certificates"

# Generate ECC private key with password
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -aes256 -out "$CERTS_DIR/ecc_private_key_with_password.pem" -pass pass:$PASSWORD_ECC_WITH
echo "Generated ECC private key with password: ecc_private_key_with_password.pem"

# Generate ECC private key without password
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out "$CERTS_DIR/ecc_private_key_without_password.pem"
echo "Generated ECC private key without password: ecc_private_key_without_password.pem"

# Generate ECC CSR with password, avoiding interactive input
COMMON_NAME="example3.com"
openssl req -new -key "$CERTS_DIR/ecc_private_key_with_password.pem" -out "$CERTS_DIR/ecc_csr_with_password.pem" \
-passin pass:$PASSWORD_ECC_WITH \
-subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORG/OU=$ORG_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"
echo "Generated ECC CSR with password: ecc_csr_with_password.pem"

# Generate ECC CSR without password, avoiding interactive input
COMMON_NAME="example4.com"
openssl req -new -key "$CERTS_DIR/ecc_private_key_without_password.pem" -out "$CERTS_DIR/ecc_csr_without_password.pem" \
-subj "/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORG/OU=$ORG_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"
echo "Generated ECC CSR without password: ecc_csr_without_password.pem"

# Use the ECC private key to sign the certificate
openssl x509 -req -in "$CERTS_DIR/ecc_csr_with_password.pem" -signkey "$CERTS_DIR/ecc_private_key_with_password.pem" -out "$CERTS_DIR/ecc_certificate_with_password.pem" -days 365 -passin pass:$PASSWORD_ECC_WITH
openssl x509 -req -in "$CERTS_DIR/ecc_csr_without_password.pem" -signkey "$CERTS_DIR/ecc_private_key_without_password.pem" -out "$CERTS_DIR/ecc_certificate_without_password.pem" -days 365
echo "Generated ECC certificates"

# Print the generated file paths
echo "RSA Certificate (with password): $CERTS_DIR/rsa_certificate_with_password.pem"
echo "RSA Private Key (with password): $CERTS_DIR/rsa_private_key_with_password.pem"
echo "RSA Certificate (without password): $CERTS_DIR/rsa_certificate_without_password.pem"
echo "RSA Private Key (without password): $CERTS_DIR/rsa_private_key_without_password.pem"
echo "ECC Certificate (with password): $CERTS_DIR/ecc_certificate_with_password.pem"
echo "ECC Private Key (with password): $CERTS_DIR/ecc_private_key_with_password.pem"
echo "ECC Certificate (without password): $CERTS_DIR/ecc_certificate_without_password.pem"
echo "ECC Private Key (without password): $CERTS_DIR/ecc_private_key_without_password.pem"

ssl_password_file 来指定该文件:

user root;
worker_processes 1;

error_log logs/error.log debug;

#pid logs/nginx.pid;

events {
worker_connections 1024;
}

http {
#large_client_header_buffers 4 16k;

# Global settings for SSL password file
ssl_password_file /etc/nginx/ssl/password_file.txt;

# Default SSL settings for all server blocks
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;

# Server block for example1.com using RSA certificate with password
server {
listen 443 ssl;
server_name example1.com;

ssl_certificate /etc/nginx/ssl/rsa_certificate_with_password.pem;
ssl_certificate_key /etc/nginx/ssl/rsa_private_key_with_password.pem;

# Other SSL-related settings
#ssl_password_file /etc/nginx/ssl/rsa_password.txt;

location / {
# Custom location settings for example1.com
#root /var/www/html;
#index index.html;
return 200 "This is the response for example3.com\n";
}
}

# Server block for example2.com using RSA certificate without password
server {
listen 443 ssl;
server_name example2.com;

ssl_certificate /etc/nginx/ssl/rsa_certificate_without_password.pem;
ssl_certificate_key /etc/nginx/ssl/rsa_private_key_without_password.pem;

# Other SSL-related settings
#ssl_password_file /etc/nginx/ssl/rsa_password_without.txt;

location / {
# Custom location settings for example2.com
#root /var/www/html;
#index index.html;
return 200 "This is the response for example3.com\n";
}
}

# Server block for example3.com using ECC certificate with password
server {
listen 443 ssl;
server_name example3.com;

ssl_certificate /etc/nginx/ssl/ecc_certificate_with_password.pem;
ssl_certificate_key /etc/nginx/ssl/ecc_private_key_with_password.pem;

# Other SSL-related settings
#ssl_password_file /etc/nginx/ssl/ecc_password.txt;

location / {
# Custom location settings for example3.com
#root /var/www/html;
#index index.html;
return 200 "This is the response for example3.com\n";
}
}

# Server block for example4.com using ECC certificate without password
server {
listen 443 ssl;
server_name example4.com;

ssl_certificate /etc/nginx/ssl/ecc_certificate_without_password.pem;
ssl_certificate_key /etc/nginx/ssl/ecc_private_key_without_password.pem;

# Other SSL-related settings
#ssl_password_file /etc/nginx/ssl/ecc_password_without.txt;

location / {
# Custom location settings for example4.com
#root /var/www/html;
#index index.html;
return 200 "This is the response for example4.com\n";
}
}

}

在这个配置中,NGINX 会在启动时自动读取 /etc/nginx/ssl_password.txt 文件,提取其中的密码,并使用它解锁 server.key 文件,以便加载和使用 SSL 私钥。

安全性注意事项

  • 确保 ssl_password_file 文件的权限设置非常严格,因为它包含私钥的密码。如果设置启动用户为 nginx, 可以设置用户限制只有 nginx 用户才能读取该文件。例如,你可以使用以下命令来限制文件权限:
chmod 600 /etc/nginx/ssl_password.txt
chown nginx:nginx /etc/nginx/ssl_password.txt

小结

  • ssl_password_file 是加载加密私钥的有效工具,可提高自动化部署效率。
  • 确保密码文件权限设置正确,以免泄露私钥密码。
  • 在部署中建议结合密码管理工具,进一步提升安全性。

图片from Mike Lin

Comments are closed.