跳轉到內容

Nginx 反向代理與 SSL 證書配置完整教程 2026

Nginx 反向代理與 SSL 配置

Nginx 是當今最流行的 Web 服務器和反向代理服務器之一,以其高性能、高併發處理能力和低資源消耗著稱。本文將帶你從基礎配置到高級優化,全面掌握 Nginx 的核心技能。

本文涵蓋:

  • ✅ 反向代理基礎配置
  • ✅ Let's Encrypt SSL 證書自動配置與續期
  • ✅ HTTP/2 與 HTTPS 安全配置
  • ✅ 虛擬主機多域名配置
  • ✅ 負載均衡與健康檢查
  • ✅ WebSocket 代理支持
  • ✅ 安全頭部與性能優化

一、Nginx 基礎安裝與配置

1.1 安裝 Nginx

bash
# Debian / Ubuntu
sudo apt update && sudo apt install -y nginx

# CentOS / RHEL
sudo dnf install -y nginx

# 驗證安裝
nginx -v
# 輸出示例: nginx version: nginx/1.25.3

# 啟動並設置開機自啟
sudo systemctl enable --now nginx

# 檢查狀態
sudo systemctl status nginx

1.2 基礎配置文件結構

bash
# Nginx 配置文件結構
/etc/nginx/
├── nginx.conf          # 主配置文件
├── conf.d/             # 額外配置目錄
   └── *.conf          # 站點配置文件
├── sites-available/    # 可用站點配置
   └── example.com     # 站點配置文件
├── sites-enabled/      # 啟用的站點(軟鏈接)
   └── example.com -> ../sites-available/example.com
└── ssl/                # SSL 證書目錄
    ├── example.com.crt
    └── example.com.key

1.3 基礎反向代理配置

nginx
# /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com www.example.com;

    # 重定向到 HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # SSL 證書配置
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;

    # 反向代理到後端應用
    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;
        
        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # 靜態文件直接服務
    location /static/ {
        root /var/www/example.com;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}

1.4 啟用站點配置

bash
# 創建軟鏈接啟用站點
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/

# 測試配置文件語法
sudo nginx -t
# 輸出: nginx: configuration file /etc/nginx/nginx.conf test is successful

# 重新加載配置(不中斷服務)
sudo systemctl reload nginx

二、Let's Encrypt SSL 證書配置

2.1 安裝 Certbot

bash
# 安裝 Certbot 和 Nginx 插件
sudo apt update && sudo apt install -y certbot python3-certbot-nginx

# CentOS / RHEL
sudo dnf install -y certbot python3-certbot-nginx

# 驗證安裝
certbot --version

2.2 自動獲取 SSL 證書

bash
# 方法1: 自動配置(推薦)
sudo certbot --nginx -d example.com -d www.example.com

# 方法2: 僅獲取證書(手動配置)
sudo certbot certonly --nginx -d example.com -d www.example.com

# 方法3: 手動模式(無服務器)
sudo certbot certonly --manual -d example.com

# 證書文件位置
/etc/letsencrypt/live/example.com/
├── cert.pem          # 證書
├── chain.pem         # 證書鏈
├── fullchain.pem     # 完整證書鏈(包含證書和鏈)
└── privkey.pem       # 私鑰

2.3 自動續期配置

bash
# 檢查自動續期配置
sudo systemctl status certbot.timer

# 測試續期
sudo certbot renew --dry-run

# 如果需要手動續期
sudo certbot renew

# 強制續期(如果有問題)
sudo certbot renew --force-renewal

# 配置自動續期後重新加載 Nginx
echo "0 3 * * * certbot renew --quiet --deploy-hook 'systemctl reload nginx'" | sudo tee -a /etc/crontab

2.4 完整 SSL 配置示例

nginx
server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    # SSL 證書
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # SSL 優化配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_stapling on;
    ssl_stapling_verify on;
    
    # 安全頭部
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" 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 "strict-origin-when-cross-origin" always;

    # 反向代理配置
    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;
    }
}

三、HTTP/2 配置與性能優化

3.1 HTTP/2 配置

nginx
# 在 server 塊中啟用 HTTP/2
server {
    listen 443 ssl http2;
    
    # HTTP/2 優化
    http2_push_preload on;
    http2_max_concurrent_streams 100;
    http2_idle_timeout 60s;
}

3.2 性能優化配置

nginx
# /etc/nginx/nginx.conf

user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 1024;
    multi_accept on;
    use epoll;
}

http {
    # 基礎優化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    
    # Gzip 壓縮
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    
    # Brotli 壓縮(需要編譯支持)
    # brotli on;
    # brotli_types text/plain text/css application/json application/javascript text/xml application/xml+rss text/javascript;
    
    # 緩存控制
    expires 1y;
    add_header Cache-Control "public, immutable";
    
    # 日誌優化
    access_log /var/log/nginx/access.log combined buffer=16k;
    error_log /var/log/nginx/error.log warn;
    
    # 包含站點配置
    include /etc/nginx/sites-enabled/*;
}

3.3 客戶端緩存配置

nginx
server {
    # 靜態資源緩存
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        add_header ETag "";
        
        # 禁止緩存敏感文件
        if ($request_uri ~* "(\.php|\.py|\.sh)$") {
            expires off;
            add_header Cache-Control "no-cache, no-store, must-revalidate";
        }
    }
    
    # HTML 文件不緩存
    location ~* \.(html|htm)$ {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
    }
}

四、虛擬主機配置

4.1 多域名配置

nginx
# /etc/nginx/sites-available/example.com
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    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;
    
    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

# /etc/nginx/sites-available/api.example.com
server {
    listen 80;
    server_name api.example.com;
    return 301 https://$server_name$request_uri;
}

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:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

4.2 泛域名配置

nginx
# 泛域名配置(需要通配符證書)
server {
    listen 80;
    server_name *.example.com;
    return 301 https://$host$request_uri;
}

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;
    
    # 根據子域名路由到不同後端
    location / {
        if ($host = "api.example.com") {
            proxy_pass http://localhost:8000;
            break;
        }
        
        if ($host = "app.example.com") {
            proxy_pass http://localhost:3000;
            break;
        }
        
        # 默認後端
        proxy_pass http://localhost:8080;
    }
}

4.3 獲取泛域名證書

bash
# 使用 DNS 驗證獲取泛域名證書
sudo certbot certonly \
  --manual \
  --preferred-challenges=dns \
  -d example.com \
  -d *.example.com

五、負載均衡配置

5.1 基礎負載均衡

nginx
# /etc/nginx/conf.d/upstream.conf
upstream backend {
    server backend1.example.com:8080;
    server backend2.example.com:8080;
    server backend3.example.com:8080;
}

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;
    
    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;
    }
}

5.2 負載均衡策略

nginx
# 輪詢(默認)
upstream backend {
    server backend1.example.com;
    server backend2.example.com;
}

# 最小連接數
upstream backend {
    least_conn;
    server backend1.example.com;
    server backend2.example.com;
}

# IP 哈希(同一 IP 始終路由到同一服務器)
upstream backend {
    ip_hash;
    server backend1.example.com;
    server backend2.example.com;
}

# 加權輪詢
upstream backend {
    server backend1.example.com weight=3;  # 30% 的流量
    server backend2.example.com weight=7;  # 70% 的流量
}

# 健康檢查(需要 nginx-plus 或第三方模塊)
upstream backend {
    server backend1.example.com max_fails=3 fail_timeout=30s;
    server backend2.example.com max_fails=3 fail_timeout=30s;
    
    # nginx-plus 健康檢查
    # zone backend 64k;
    # health_check;
}

5.3 備用服務器配置

nginx
upstream backend {
    server backend1.example.com;
    server backend2.example.com;
    
    # 備用服務器(主服務器都不可用時使用)
    server backup.example.com backup;
}

六、WebSocket 代理配置

6.1 基礎 WebSocket 代理

nginx
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;
    
    # WebSocket 代理
    location /ws/ {
        proxy_pass http://localhost:8080;
        
        # WebSocket 必需的頭信息
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # 超時設置
        proxy_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;
        
        # 客戶端 IP 傳遞
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }
}

6.2 Socket.IO 代理

nginx
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;
    
    # Socket.IO 代理
    location /socket.io/ {
        proxy_pass http://localhost:3000;
        
        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        # 長輪詢支持
        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_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;
        
        # 緩衝區設置
        proxy_buffers 8 32k;
        proxy_buffer_size 64k;
    }
}

七、安全配置與防護

7.1 安全頭部配置

nginx
server {
    # HSTS(強制 HTTPS)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    
    # 防止點擊劫持
    add_header X-Frame-Options DENY always;
    
    # MIME 類型嗅探防護
    add_header X-Content-Type-Options nosniff always;
    
    # XSS 保護
    add_header X-XSS-Protection "1; mode=block" always;
    
    # 內容安全策略(根據需要調整)
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline'" always;
    
    # 權限策略
    add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
    
    # 引薦來源策略
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    
    # 跨域資源共享
    add_header Access-Control-Allow-Origin "*" always;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
    add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
}

7.2 限制請求速率

nginx
# 限制單 IP 請求速率
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

server {
    location /api/ {
        # 限制每秒 10 個請求,最多延遲處理 50 個請求
        limit_req zone=api burst=50 nodelay;
        
        proxy_pass http://localhost:8000;
    }
}

# 限制連接數
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

server {
    location / {
        # 限制單 IP 最多 10 個併發連接
        limit_conn conn_limit 10;
        
        proxy_pass http://localhost:3000;
    }
}

7.3 禁止訪問敏感文件

nginx
server {
    # 禁止訪問隱藏文件
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # 禁止訪問配置文件
    location ~* (config\.json|config\.yml|\.env|\.git) {
        deny all;
        access_log off;
        log_not_found off;
    }
    
    # 禁止訪問日誌文件
    location ~* \.(log|sql|bak)$ {
        deny all;
        access_log off;
        log_not_found off;
    }
}

7.4 允許特定 IP 訪問

nginx
server {
    # 僅允許特定 IP 訪問管理後臺
    location /admin/ {
        allow 192.168.1.0/24;
        allow 10.0.0.0/8;
        deny all;
        
        proxy_pass http://localhost:3000;
    }
}

八、日誌配置與分析

8.1 日誌格式配置

nginx
# /etc/nginx/nginx.conf
http {
    # 自定義日誌格式
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for" '
                    '$request_time $upstream_response_time';
    
    log_format json '{ "time": "$time_local", '
                    '"remote_addr": "$remote_addr", '
                    '"remote_user": "$remote_user", '
                    '"request": "$request", '
                    '"status": "$status", '
                    '"body_bytes_sent": "$body_bytes_sent", '
                    '"http_referer": "$http_referer", '
                    '"http_user_agent": "$http_user_agent", '
                    '"request_time": "$request_time" }';
    
    # 訪問日誌
    access_log /var/log/nginx/access.log main;
    
    # 錯誤日誌
    error_log /var/log/nginx/error.log warn;
}

8.2 日誌分析示例

bash
# 統計訪問最多的頁面
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10

# 統計狀態碼分佈
awk '{print $9}' /var/log/nginx/access.log | sort | uniq -c | sort -nr

# 統計訪問最多的 IP
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10

# 查找 4xx 和 5xx 錯誤
awk '$9 >= 400' /var/log/nginx/access.log | head -20

# 計算平均響應時間
awk '{sum+=$14} END {print "Average response time: " sum/NR "ms"}' /var/log/nginx/access.log

九、常見問題與解決方案

Q1:SSL 證書過期怎麼辦?

bash
# 檢查證書過期時間
openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem

# 手動續期
sudo certbot renew

# 如果續期失敗,嘗試強制續期
sudo certbot renew --force-renewal

# 檢查自動續期定時器
sudo systemctl status certbot.timer

Q2:Nginx 啟動失敗怎麼辦?

bash
# 檢查配置語法
sudo nginx -t

# 查看錯誤日誌
tail -f /var/log/nginx/error.log

# 檢查端口是否被佔用
sudo ss -tlnp | grep :80
sudo ss -tlnp | grep :443

# 檢查權限問題
ls -la /etc/nginx/ssl/
ls -la /etc/letsencrypt/live/example.com/

Q3:反向代理後獲取不到真實客戶端 IP?

nginx
# 確保配置了以下頭信息
location / {
    proxy_pass http://localhost:3000;
    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;
}

在後端應用中讀取 X-Forwarded-ForX-Real-IP 頭來獲取真實客戶端 IP。

Q4:WebSocket 連接失敗?

nginx
# 確保配置了正確的頭信息
location /ws/ {
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}

Q5:如何配置 HTTP/3?

bash
# HTTP/3 需要特殊配置(需要編譯支持或使用 nginx-plus)
# 檢查是否支持 HTTP/3
nginx -V 2>&1 | grep quic

# 如果支持,配置示例
server {
    listen 443 ssl http2 http3;
    listen [::]:443 ssl http2 http3;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # QUIC 配置
    ssl_quic on;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1.3;
}

十、完整配置示例

10.1 生產環境完整配置

nginx
# /etc/nginx/sites-available/example.com

# HTTP -> HTTPS 重定向
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    
    # ACME 挑戰(用於 Let's Encrypt 驗證)
    location /.well-known/acme-challenge/ {
        root /var/www/html;
        allow all;
    }
    
    # 其他請求重定向到 HTTPS
    return 301 https://$server_name$request_uri;
}

# HTTPS 主站點
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    # SSL 配置
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # SSL 優化
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_stapling on;
    ssl_stapling_verify on;
    
    # 安全頭部
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" 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 "strict-origin-when-cross-origin" always;
    
    # 靜態文件緩存
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp|css|js|woff|woff2|ttf|eot)$ {
        root /var/www/example.com;
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    # WebSocket 代理
    location /ws/ {
        proxy_pass http://localhost:8080;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        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_connect_timeout 7d;
        proxy_send_timeout 7d;
        proxy_read_timeout 7d;
    }
    
    # 主應用代理
    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;
        
        # 緩存控制
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
    }
    
    # 錯誤頁面
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

結語

Nginx 是一個功能強大的工具,掌握好它可以為你的網站提供高性能、高安全性的服務。本文涵蓋了從基礎配置到高級優化的大部分內容,但 Nginx 的能力遠不止這些。

推薦學習路徑:

  1. 掌握基礎配置和反向代理
  2. 配置 SSL 證書和安全頭部
  3. 學習負載均衡和健康檢查
  4. 深入瞭解性能優化和日誌分析

推薦閱讀:


🚀 提示: 定期更新 Nginx 和 Certbot,保持你的服務器安全和性能處於最佳狀態。


延伸阅读

免责声明

本文仅供技术交流和学习参考。涉及第三方服务的链接可能包含 sponsored 标记,请自行核实服务条款、价格和可用性,并遵守当地法律法规。

最後更新於: