跳转到内容

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 标记,请自行核实服务条款、价格和可用性,并遵守当地法律法规。