Nginx SSL/TLS 配置
Nginx SSL/TLS 配置
什么是 SSL/TLS
SSL(Secure Sockets Layer)和 TLS(Transport Layer Security)是用于在互联网上提供安全通信的加密协议。HTTPS 是 HTTP 的加密版本,通过 SSL/TLS 协议保护数据传输安全。
获取 SSL 证书
使用 Let's Encrypt
# 安装 Certbot
sudo apt install certbot python3-certbot-nginx
# 获取证书
sudo certbot --nginx -d example.com -d www.example.com
# 自动续期
sudo certbot renew --dry-run
手动创建自签名证书(测试用)
# 创建私钥
openssl genrsa -out server.key 2048
# 创建证书签名请求
openssl req -new -key server.key -out server.csr
# 自签名证书
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
基本 HTTPS 配置
server {
listen 443 ssl http2;
server_name example.com;
# SSL 证书
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# SSL 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
# 其他配置
root /var/www/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
SSL 安全配置
现代 SSL 配置
server {
listen 443 ssl http2;
server_name example.com;
# SSL 证书
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# SSL 协议
ssl_protocols TLSv1.2 TLSv1.3;
# SSL 密码套件
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;
# SSL 会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
# OCSP Stapling
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 always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: ws: wss:" always;
}
多域名 SSL 配置
多域名证书
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
root /var/www/html;
index index.html;
}
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/ssl/certs/api.example.com.crt;
ssl_certificate_key /etc/ssl/private/api.example.com.key;
location / {
proxy_pass http://backend;
}
}
通配符证书
server {
listen 443 ssl http2;
server_name *.example.com;
ssl_certificate /etc/ssl/certs/*.example.com.crt;
ssl_certificate_key /etc/ssl/private/*.example.com.key;
root /var/www/html;
}
SSL 证书管理
证书文件权限
# 设置证书文件权限
sudo chmod 600 /etc/ssl/private/example.com.key
sudo chmod 644 /etc/ssl/certs/example.com.crt
# 设置目录权限
sudo chmod 700 /etc/ssl/private
证书备份
# 备份证书
sudo cp -r /etc/ssl/certs/example.com.crt /backup/
sudo cp -r /etc/ssl/private/example.com.key /backup/
# 设置备份权限
chmod 600 /backup/example.com.key
证书续期
# 手动续期
sudo certbot renew
# 自动续期(cron)
0 0 1 * * certbot renew --post-hook "systemctl reload nginx"
实践案例
部署带 SSL 的 Web 应用
# HTTP 重定向
server {
listen 80;
server_name app.example.com;
return 301 https://$server_name$request_uri;
}
# HTTPS 配置
server {
listen 443 ssl http2;
server_name app.example.com;
# SSL 证书
ssl_certificate /etc/ssl/certs/app.example.com.crt;
ssl_certificate_key /etc/ssl/private/app.example.com.key;
# SSL 配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# 安全头
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
# 应用配置
root /var/www/app;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
# API 代理
location /api/ {
proxy_pass http://backend;
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;
}
}
部署微服务 SSL
# 用户服务
server {
listen 443 ssl http2;
server_name user.example.com;
ssl_certificate /etc/ssl/certs/user.example.com.crt;
ssl_certificate_key /etc/ssl/private/user.example.com.key;
location / {
proxy_pass http://user-service:8080;
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;
}
}
# 订单服务
server {
listen 443 ssl http2;
server_name order.example.com;
ssl_certificate /etc/ssl/certs/order.example.com.crt;
ssl_certificate_key /etc/ssl/private/order.example.com.key;
location / {
proxy_pass http://order-service:8080;
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;
}
}
性能优化
server {
listen 443 ssl http2;
# SSL 会话缓存
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
# SSL 缓冲
ssl_buffer_size 4k;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
}
常见问题
证书不被信任
# 检查证书链
openssl s_client -connect example.com:443 -showcerts
# 检查证书有效期
openssl x509 -in /etc/ssl/certs/example.com.crt -noout -dates
SSL 配置测试
# 测试 Nginx 配置
sudo nginx -t
# 测试 SSL 配置
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
最佳实践
- 使用 Let's Encrypt 获取免费证书
- 配置 HTTP 到 HTTPS 重定向
- 启用 HSTS 和安全头
- 定期续期证书
- 使用强加密套件
总结
SSL/TLS 配置是保障 Web 应用安全的关键。通过合理配置 Nginx SSL,可以实现安全的 HTTPS 通信,保护用户数据和隐私。