- 基本 HTTPS 配置
- 使用 Let's Encrypt
- SSL 配置說明
- 安全標頭
- 多網域配置
- 反向代理配置
- 效能優化
- 測試與驗證
- 常見問題
- 總結
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
root /var/www/html;
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
server_name example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
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 off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
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 "SAMEORIGIN" 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;
ssl_dhparam /etc/nginx/dhparam.pem;
root /var/www/html;
index index.html index.htm index.php;
location / {
try_files $uri $uri/ =404;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
}
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
}
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$server_name$request_uri;
}
}
sudo apt update
sudo apt install certbot python3-certbot-nginx
sudo yum install certbot python3-certbot-nginx
brew install certbot
sudo certbot --nginx -d example.com -d www.example.com
sudo certbot certonly --nginx -d example.com -d www.example.com
sudo certbot certonly --webroot -w /var/www/html \
-d example.com -d www.example.com
Let's Encrypt 憑證預設位置:
/etc/letsencrypt/live/example.com/
├── fullchain.pem # 完整憑證鏈(用於 ssl_certificate)
├── privkey.pem # 私鑰(用於 ssl_certificate_key)
├── chain.pem # 中繼憑證
└── cert.pem # 網站憑證
sudo certbot renew --dry-run
sudo certbot renew
sudo crontab -e
0 2 * * * certbot renew --quiet --post-hook "systemctl reload nginx"
sudo systemctl status certbot.timer
sudo openssl dhparam -out /etc/nginx/dhparam.pem 2048
sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096
| 協定 |
狀態 |
建議 |
| SSLv2 |
已廢棄 |
禁用 |
| SSLv3 |
已廢棄 |
禁用 |
| TLS 1.0 |
已過時 |
禁用 |
| TLS 1.1 |
已過時 |
禁用 |
| TLS 1.2 |
安全 |
啟用 |
| TLS 1.3 |
最安全 |
啟用 |
ssl_protocols TLSv1.2 TLSv1.3;
ssl_protocols SSLv2 SSLv3 TLSv1 TLSv1.1;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
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_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
| 標頭 |
用途 |
建議值 |
| Strict-Transport-Security |
強制 HTTPS |
max-age=63072000; includeSubDomains; preload |
| X-Frame-Options |
防止點擊劫持 |
SAMEORIGIN |
| X-Content-Type-Options |
防止 MIME 嗅探 |
nosniff |
| X-XSS-Protection |
XSS 防護(舊瀏覽器) |
1; mode=block |
| Referrer-Policy |
控制 Referer 標頭 |
no-referrer-when-downgrade |
| Content-Security-Policy |
內容安全策略 |
依需求設定 |
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
HSTS Preload 清單:
add_header X-Frame-Options "SAMEORIGIN" 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'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
server {
listen 443 ssl http2;
server_name example.com www.example.com blog.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
if ($host = blog.example.com) {
root /var/www/blog;
}
if ($host ~* ^(www\.)?example\.com$) {
root /var/www/main;
}
}
sudo certbot certonly --manual --preferred-challenges dns \
-d example.com -d *.example.com
server {
listen 443 ssl http2;
server_name *.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
set $subdomain "";
if ($host ~* ^([^.]+)\.example\.com$) {
set $subdomain $1;
}
root /var/www/$subdomain;
}
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_pass http://localhost:3000;
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;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
upstream backend {
least_conn;
server 192.168.1.101:3000 weight=3;
server 192.168.1.102:3000 weight=2;
server 192.168.1.103:3000 backup;
}
server {
listen 443 ssl http2;
server_name app.example.com;
ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
location / {
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;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
location / {
http2_push /static/style.css;
http2_push /static/script.js;
}
}
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
gzip_disable "msie6";
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
sudo nginx -t
sudo nginx -s reload
sudo systemctl restart nginx
sudo systemctl status nginx
openssl s_client -connect example.com:443 -servername example.com
echo | openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -text
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3
錯誤:NET::ERR_CERT_AUTHORITY_INVALID
解決:確保使用 fullchain.pem
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate /etc/letsencrypt/live/example.com/cert.pem;
問題:HTTPS 頁面載入 HTTP 資源
解決:設定 CSP 標頭升級不安全請求
add_header Content-Security-Policy "upgrade-insecure-requests" always;
sudo certbot certificates
sudo certbot renew
sudo certbot renew --force-renewal
sudo tail -f /var/log/nginx/error.log
sudo ufw allow 443/tcp
sudo setenforce 0
sudo tail -f /var/log/nginx/error.log
| 項目 |
狀態 |
| 使用 Let's Encrypt 或商業憑證 |
✅ |
| 啟用 TLS 1.2 和 1.3 |
✅ |
| 禁用 SSL 2.0/3.0 和 TLS 1.0/1.1 |
✅ |
| 使用強加密套件 |
✅ |
| 啟用 HTTP/2 |
✅ |
| 設定 HSTS 標頭 |
✅ |
| 啟用 OCSP Stapling |
✅ |
| HTTP 自動重定向到 HTTPS |
✅ |
| 設定自動續期 |
✅ |
| 配置完整憑證鏈 |
✅ |
| SSL Labs 測試達到 A 或 A+ |
✅ |
| 設定安全標頭 |
✅ |
| 操作 |
指令 |
| 取得憑證 |
sudo certbot --nginx -d example.com |
| 測試續期 |
sudo certbot renew --dry-run |
| 檢查配置 |
sudo nginx -t |
| 重載配置 |
sudo nginx -s reload |
| 查看憑證 |
sudo certbot certificates |
| SSL 測試 |
openssl s_client -connect example.com:443 |
建立日期:2025-10-28
最後更新:2025-12-04