【问题标题】:SSL proxy pass with NGINX leading to bad gateway through Docker使用 NGINX 的 SSL 代理通过 Docker 导致网关错误
【发布时间】:2019-10-18 13:40:51
【问题描述】:

背景

我的设置基于以下教程:

Dockerizing Django with Postgres, Gunicorn, and NGINX

TL;DR:(斜体:教程未涵盖;个人冒险
  • 3 Docker 服务用于:nginx -> django -> postgres(箭头表示依赖)
  • Nginx 代理将请求传递到 Django 服务中暴露的端口。
  • HTTP(非 SSL)请求工作
  • 通过重定向 http -> https
  • 需要 SSL 连接

详情

我已经生成了一个自签名证书来测试本地 NGINX 的 ssl 重定向,然后再尝试让它在生产中的 VPS 上工作。我对使用 NGINX 很陌生,所以我不完全确定出了什么问题或如何诊断问题。

这是我希望在下面提供的 NGINX 文件中发生的事情... (剧透:它不会)

  1. 转到http://localhost
  2. 被重定向到https://localhost
  3. 来自浏览器的关于自签名证书的警告;接受警告并继续
  4. 网站渲染良好,SSL 重定向工作正常!

但事实并非如此。我得到一个 502 Bad Gateway,NGINX 输出以下日志:

prod_1  | 192.168.144.1 - - [03/Jun/2019:00:01:44 +0000] "GET / HTTP/1.1" 502 158 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0" "-"
prod_1  | 2019/06/03 00:01:44 [error] 8#8: *1 peer closed connection in SSL handshake while SSL handshaking to upstream, client: 192.168.144.1, server: , request: "GET / HTTP/1.1", upstream: "https://192.168.144.3:8000/", host: "localhost"

谁能告诉我发生了什么或如何解决它?我觉得即使在 SSL 重定向之外,我的 conf 文件也可能存在一大堆问题,但我真的不知道如何识别任何问题。 conf文件在下面...

upstream mysite {
    server web:8000;
}

# redirect http traffic to https
server {
    listen 80;
    listen [::]:80;

    return 301 https://$host$request_uri;
}

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

    location / {
        proxy_pass https://mysite;
        proxy_ssl_server_name   on;

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

    location /assets/ {
        alias /usr/src/site/assets/;
    }

    location /media/ {
        alias /usr/src/site/media/;
    }

    ssl_certificate         /etc/ssl/certificates/site.crt;
    ssl_certificate_key     /etc/ssl/certificates/site.key;

    ssl_session_cache           builtin:1000 shared:SSL:10m;
    ssl_protocols               TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers                 HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers   on;

}

【问题讨论】:

  • 您的上游 (Django) 是否安全?我的猜测是 Django 是 http 的,但是你已经将 nginx 配置为通过 https 连接到它。
  • @chuex 我必须调查一下,我没有意识到我必须设置 Django 以确保安全。为此,我需要在 NGINX conf 文件方面做一些具体/额外的事情吗?除此之外,我将研究有关 SSL 连接的 Django 文档
  • 你不一定要让 Django 安全。我只需将 nginx 配置为通过 http 而不是 https 连接到它。
  • @chuex 你是说proxy_pass $http://mysite;吗?这不会撤消 SSL 连接吗?
  • 我的建议是匹配协议。如果 Django 是 http,那么你会希望 nginx 使用 http 与它对话。如果 Django 是 https,那么同样你需要 nginx 通过 https 与之对话。是的,http 在 nginx 和 Django 之间不太安全。关于 localhost 上的通信有两种思想流派——一种是使用 https 来保证安全,另一种是 localhost 已经是安全的。例如,您的 Django 实例是否使用 SSL 与本地数据库通信?如果不是,那么 Django 是否以明文方式与 nginx 对话是否重要?无论如何,这是另一个问题。

标签: docker ssl nginx


【解决方案1】:

根据您的错误

prod_1  | 2019/06/03 00:01:44 [error] 8#8: *1 peer closed connection in SSL handshake while SSL handshaking to upstream, client: 192.168.144.1, server: , request: "GET / HTTP/1.1", upstream: "https://192.168.144.3:8000/", host: "localhost"

我会说 Nginx 和 Django 之间可能存在某种协议不匹配。 Django 很可能期待非安全通信 (http)。您的 nginx 配置表明您已将其配置为通过 https 与 Django 通信:

proxy_pass https://mysite;

我的建议是确保 Nginx 和 Django 之间的通信使用相同的协议,无论是 http 还是 https。

您要使用 http 还是 https 取决于您。关于 http 是否安全,这里有两种不同的思想流派。

第一个观点是在这种情况下 http 是安全的,因为通信在同一台机器内。

第二种思路是保护所有通信,并使用 https。但是,如果您同意这种思路,则必须确保 Web 服务器和数据库之间的通信也使用安全协议。毕竟,只有最薄弱的环节才是安全的。

我倾向于倾向于第一流派。虽然这不一定适合你。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-04-09
  • 2023-04-01
  • 2013-08-11
  • 2014-08-18
  • 2017-02-03
  • 1970-01-01
  • 2018-07-02
  • 2021-05-28
相关资源
最近更新 更多