使用 Nginx 反向代理的时候和上游服务器也使用 SSL 连接

Jun 09, 2024 • 预计阅读时间 2 分钟

当 Nginx 反向代理和上游服务器部署在不同位置的时候,如果 Nginx 和上游服务器通过 HTTP 通讯,就会存在中间人攻击的安全隐患。

比较安全的方式是反向代理服务器和上游服务器之间也通过 SSL 加密通讯来保证数据安全。

[客户端] <- SSL -> [Nginx 反向代理] <- SSL -> [上游服务器]

其中客户端和 Nginx 反向代理之间,使用的是正常的 SSL 证书。

Nginx 反向代理和上游服务器之间,可以使用同样的证书,也可以使用自签名证书。

上游服务器证书配置

没啥特别的地方,按正常方式配置就行,例子里面使用的是 CloudFlare 生成的有效期 15 年的自签名证书,好处就是不需要经常更新证书。

http {
    server {
        listen 127.0.0.1:10443 ssl http2;
        listen [::1]:10443 ssl http2;

        ssl_certificate /opt/certs/lvv.me/cloudflare/fullchain.pem;
        ssl_certificate_key /opt/certs/lvv.me/cloudflare/privkey.pem;
        ssl_trusted_certificate /opt/certs/lvv.me/cloudflare/fullchain.pem;

        ssl_protocols TLSv1.3 TLSv1.2;
        ssl_ecdh_curve prime256v1:secp384r1;
        ssl_conf_command Options PrioritizeChaCha;
        ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384;
        ssl_prefer_server_ciphers on;
        ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

        ssl_session_timeout 1d;
        ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
        ssl_session_tickets off;
    }
}

stream {
    upstream backend {
        server 127.0.0.1:10443;
    }

    server {
        listen 443;
        listen [::]:443;

        proxy_pass backend;
    }
}

以上配置用了 stream 进行转发,这个操作不是必须的,仅供参考。

Nginx 反向代理服务器配置

反向代理服务器需要配置两个证书:客户端连接用的证书和上游服务器的证书。

反向代理需要配置在 stream 模块里:

stream {
  upstream backend {
    hash $remote_addr consistent;
    server 1.2.3.4:443;
    server 2.3.4.5:443;
  }

  server {
    listen 443 ssl;
    listen [::]:443 ssl;

    ssl_certificate /usr/local/etc/letsencrypt/live/lvv.me/fullchain.pem;
    ssl_certificate_key /usr/local/etc/letsencrypt/live/lvv.me/privkey.pem;
    ssl_trusted_certificate /usr/local/etc/letsencrypt/live/lvv.me/fullchain.pem;

    ssl_protocols TLSv1.3 TLSv1.2;
    ssl_ecdh_curve prime256v1:secp384r1;
    ssl_conf_command Options PrioritizeChaCha;
    ssl_conf_command Ciphersuites TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384;
    ssl_prefer_server_ciphers on;
    ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;

    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;  # about 40000 sessions
    ssl_session_tickets off;

    proxy_ssl on;
    proxy_ssl_certificate /opt/certs/lvv.me/cloudflare/fullchain.pem;
    proxy_ssl_certificate_key /opt/certs/lvv.me/cloudflare/privkey.pem;
    proxy_ssl_trusted_certificate /opt/certs/lvv.me/cloudflare/fullchain.pem;

    proxy_ssl_protocols TLSv1.3 TLSv1.2;
    proxy_ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305;
    proxy_ssl_session_reuse on;

    proxy_connect_timeout 15s;
    proxy_timeout 30s;
    proxy_pass backend;
  }
}

其中的 proxy_ssl 需要和上游服务器使用一样的 SSL 证书, 当用户访问 Nginx 反向代理的时候,数据先在反向代理这解密,然后使用上游服务器的证书加密通讯,整个通讯的链路都是经过 SSL 加密的,保证了安全性。

添加的 ssl_trusted_certificate 可以避免把完整的证书链发给客户端。

Nginx
版权声明:如果转发请带上本文链接和注明来源。

lvv.me

iOS/macOS Developer

OpenSSL 创建自签名证书

Nginx 负载均衡解决同 IP 连接漂移的问题