[英]Django behind NGINX reverse proxy and AWS Application Load Balancer doesn't get HTTPS forwarded from client in HTTP_X_FORWARDED_PROTO
I'm running Django on Gunicorn behind a NGINX reverse proxy, and an AWS Application Load Balancer.我在 NGINX 反向代理和 AWS 应用程序负载均衡器后面的 Gunicorn 上运行 Django。 The ALB has 2 listeners.
ALB 有 2 个侦听器。 The HTTPS listener forwards to a Target Group in port 80, and the HTTP listener redirects to HTTPS.
HTTPS 侦听器转发到端口 80 中的目标组,HTTP 侦听器重定向到 HTTPS。
The ALB thus connects with an AWS ECS Cluster, which runs a task with 2 containers: one for the Django app, and another for the NGINX that acts as a reverse proxy for the Django app.因此,ALB 与 AWS ECS 集群连接,该集群使用 2 个容器运行任务:一个用于 Django 应用程序,另一个用于 NGINX,充当 Django 应用程序的反向代理。 Here's the configuration for the NGINX reverse proxy:
这是 NGINX 反向代理的配置:
upstream django {
server web:8000;
}
server {
listen 80;
listen [::]:80;
location / {
proxy_pass http://django;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_ssl_server_name on;
proxy_redirect off;
}
}
This configuration ensures that whenever the client tries to hit the website app using an HTTP request, he gets redirected to HTTPS. And everything works fine with one exception.此配置确保每当客户端尝试使用 HTTP 请求访问网站应用程序时,他都会被重定向到 HTTPS。除了一个例外,一切正常。 In Django, when I run
request.is_secure()
I'm getting False
instead of True
as expected.在 Django 中,当我运行
request.is_secure()
时,我得到的是False
而不是预期的True
。 If I run request.build_absolute_uri()
, I get http://mywebsite.com
and not https://mywebsite.com
as expected.如果我运行
request.build_absolute_uri()
,我得到http://mywebsite.com
而不是预期的https://mywebsite.com
。
I already tried adding the following lines to settings.py
:我已经尝试将以下行添加到
settings.py
:
USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
as explained in the documentation, but it doesn't work.如文档中所述,但它不起作用。 Whenever I inspect
request.META
(or the raw request.headers
), I'm seeing 'HTTP_X_FORWARDED_PROTO': 'http'
(and the equivalent raw 'X-Forwarded-Proto': 'http'
) instead of https
as expected.每当我检查
request.META
(或原始request.headers
)时,我都会看到'HTTP_X_FORWARDED_PROTO': 'http'
(以及等效的原始'X-Forwarded-Proto': 'http'
)而不是预期的https
。 The stack is correctly forwarding 'HTTP_X_FORWARDED_HOST': 'mywebsite.com'
from the client, but the scheme is being ignored.堆栈从客户端正确转发
'HTTP_X_FORWARDED_HOST': 'mywebsite.com'
,但方案被忽略。
Can anyone help me identify what I'm doing wrong and how to fix it?谁能帮我确定我做错了什么以及如何解决? Thanks
谢谢
With a Classic ELB you specify the "instance port" (see the listeners tab) and that controls the protocol that you send downstream to nginx. In that scenario it is common to attach an SSL cert to the 443 port but send HTTP
down port 80 to nginx. the port 80 listener also sends HTTP
.使用经典 ELB,您可以指定“实例端口”(请参阅侦听器选项卡)并控制您向下游发送到 nginx 的协议。在这种情况下,通常将 SSL 证书附加到 443 端口,但将
HTTP
发送到端口 80到 nginx。端口 80 侦听器还发送HTTP
。 In that setup, where only HTTP
is coming in from the load balancer it is your job to inspect the X-Forwarded-Proto
header and perform a permanent redirect to HTTPS
.在该设置中,只有
HTTP
来自负载均衡器,您的工作是检查X-Forwarded-Proto
header 并执行永久重定向到HTTPS
。 That's because the classic ELB could not redirect HTTP
to HTTPS
.那是因为经典的 ELB 无法将
HTTP
重定向到HTTPS
。 With the Application Load Balancer (ALB) I believe you can redirect HTTP to HTTPS if you want to speak 443 to nginx.使用应用程序负载均衡器 (ALB),如果您想将 443 转至 nginx,我相信您可以将 HTTP 重定向至 HTTPS。
In your specific case it seems like you were only listening on Port 80 so you were probably only sending HTTP from the load balancer.在您的特定情况下,您似乎只在端口 80 上监听,因此您可能只从负载均衡器发送 HTTP。 Check you Instance Port and protocol.
检查您的实例端口和协议。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.