HTTPS = HTTP + SSL/TLS,通过证书实现:
加密传输 - 防止数据被窃听 身份验证 - 证明服务器身份 数据完整性 - 防止数据被篡改# 创建私钥
openssl genrsa -out server.key 2048
# 创建证书签名请求(CSR)
openssl req -new -key server.key -out server.csr
# 生成自签名证书(有效期365天)
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
# 可选:生成pem格式(包含私钥和证书)
cat server.crt server.key > server.pem
server {
listen 443 ssl;
server_name example.com www.example.com;
# 证书路径
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
# SSL协议配置
ssl_protocols TLSv1.2 TLSv1.3;
# 加密套件
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
# 会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS(可选)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# 其他配置
location / {
root /usr/share/nginx/html;
index index.html;
}
}
# HTTP重定向到HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
# 安装Certbot
# Ubuntu/Debian
sudo apt update
sudo apt install certbot python3-certbot-nginx
# CentOS/RHEL
sudo yum install certbot python3-certbot-nginx
# 申请证书(自动配置Nginx)
sudo certbot --nginx -d example.com -d www.example.com
# 仅获取证书(手动配置)
sudo certbot certonly --nginx -d example.com
证书位置通常为:
/etc/letsencrypt/live/example.com/fullchain.pem/etc/letsencrypt/live/example.com/privkey.pemserver {
listen 443 ssl http2;
server_name example.com;
# Let's Encrypt证书
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# 启用SSL会话恢复
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# 现代SSL配置
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;
ssl_prefer_server_ciphers off;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
# 安全头
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
location / {
# 你的应用配置
}
}
# 使用DNS验证(需要配置DNS API)
sudo certbot certonly \
--manual \
--preferred-challenges=dns \
-d "*.example.com" \
-d example.com
# 主域名
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/wildcard.crt;
ssl_certificate_key /path/to/wildcard.key;
# ...其他配置
}
# 子域名1
server {
listen 443 ssl;
server_name api.example.com;
ssl_certificate /path/to/wildcard.crt;
ssl_certificate_key /path/to/wildcard.key;
# ...其他配置
}
# 子域名2
server {
listen 443 ssl;
server_name blog.example.com;
ssl_certificate /path/to/wildcard.crt;
ssl_certificate_key /path/to/wildcard.key;
# ...其他配置
}
# SSL优化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
ssl_ecdh_curve secp384r1;
# 性能优化
ssl_buffer_size 4k;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 24h;
ssl_session_tickets off;
# OCSP Stapling
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# DH参数(增强安全性)
ssl_dhparam /etc/nginx/dhparam.pem;
# 生成DH参数
# openssl dhparam -out /etc/nginx/dhparam.pem 2048
server {
listen 443 ssl http2;
http2_push_preload on;
# 启用Gzip压缩
gzip on;
gzip_vary on;
gzip_types text/plain text/css application/json application/javascript;
}
# 测试续期
sudo certbot renew --dry-run
# 创建自动续期任务
sudo crontab -e
# 添加以下内容(每天检查,每月执行)
0 0 */1 * * /usr/bin/certbot renew --quiet --renew-hook "systemctl reload nginx"
# 更新证书后重新加载Nginx
sudo certbot renew
sudo systemctl reload nginx
# 查看证书详情
openssl x509 -in server.crt -text -noout
# 测试SSL连接
openssl s_client -connect example.com:443 -servername example.com
# 在线检测
# https://www.ssllabs.com/ssltest/
# 检查配置文件语法
nginx -t
# 查看加载的配置
nginx -T | grep ssl
# 重新加载配置
nginx -s reload
# 错误1:证书路径错误
# 确保证书文件存在且Nginx有读取权限
# 错误2:证书不匹配域名
# 检查证书的SAN(Subject Alternative Names)
# 错误3:私钥不匹配
# 验证证书和私钥是否匹配
openssl x509 -noout -modulus -in server.crt | openssl md5
openssl rsa -noout -modulus -in server.key | openssl md5
# Dockerfile示例
FROM nginx:alpine
# 复制证书
COPY ssl/ /etc/nginx/ssl/
# 复制配置文件
COPY nginx.conf /etc/nginx/nginx.conf
COPY sites-enabled/ /etc/nginx/sites-enabled/
# 设置权限
RUN chmod 600 /etc/nginx/ssl/*.key
EXPOSE 80 443
| 方案 | 适用场景 | 有效期 | 自动续期 | 浏览器信任 |
|---|---|---|---|---|
| 自签名证书 | 内部测试、开发环境 | 自定义 | 手动 | 需要手动信任 |
| Let's Encrypt | 生产环境、公开服务 | 90天 | 支持自动 | 全平台信任 |
| 商业证书 | 企业级应用、特殊需求 | 1-2年 | 手动 | 全平台信任 |
根据实际需求选择合适的证书方案,生产环境推荐使用Let's Encrypt,配合自动续期脚本确保服务连续性。