如何在Django ALLOWED_HOSTS配置下通过AWS ELB健康检查
解决AWS ELB健康检查被Nginx 444拦截的方案
针对你的场景,核心矛盾是既要用Nginx拦截非法Host的请求以减少Django错误邮件,又要让ELB健康检查请求正常到达Django的健康检查页面,以下是几种可行的解决方案:
方案1:调整Nginx配置,优先处理健康检查请求
通过分层的Nginx server块,让健康检查请求绕过444拦截规则,同时强制设置合法Host避免Django的DisallowedHost错误:
# 1. 处理主域名的正常请求 server { listen 80; server_name my-site.com; # 正常业务请求转发到gunicorn location / { proxy_pass http://gunicorn; 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; } # 主域名下的健康检查路径(确保主域名的健康检查也能正常工作) location = /health/ { proxy_pass http://gunicorn; proxy_set_header Host my-site.com; } } # 2. 处理所有非主域名的请求,仅放行健康检查路径 server { listen 80; server_name _; # 匹配所有未被上述server块覆盖的Host # 仅允许健康检查请求转发到gunicorn,强制设置合法Host location = /health/ { proxy_pass http://gunicorn; proxy_set_header Host my-site.com; proxy_set_header X-Real-IP $remote_addr; } # 其他非法请求直接返回444,不转发到Django location / { return 444; } } # 3. 处理无Host头的请求,直接返回444 server { listen 80; server_name ""; return 444; }
配置说明:
- Nginx会按server块的顺序匹配请求,主域名请求优先进入第一个server块;
- ELB健康检查的请求(通常Host为容器内网IP或ELB内部地址)会进入第二个server块,仅
/health/路径被转发到gunicorn,且通过proxy_set_header Host my-site.com强制设置合法Host,避免Django拦截; - 所有非法Host或无Host的请求,除健康检查外,都会被返回444,不会触发Django的错误日志和邮件。
方案2:自定义ALB健康检查的Host头(仅适用于Application Load Balancer)
如果使用的是AWS ALB,可以直接在健康检查配置中添加合法的Host头,让请求匹配主Nginx server块:
- 进入AWS控制台的ECS集群对应的ALB配置页面;
- 找到目标组的健康检查设置;
- 在HTTP头中添加
Host: my-site.com; - 保存配置后,ELB的健康检查请求会携带合法Host,被Nginx的主server块处理,正常转发到Django的健康检查页面。
这种方案无需修改Nginx配置,更简洁,但仅支持ALB(经典ELB无法自定义健康检查头)。
方案3:补充ALLOWED_HOSTS(不推荐,仅作为临时补充)
如果上述方案暂时无法实施,可以在Django的ALLOWED_HOSTS中添加ELB健康检查的来源IP或容器内网IP段,让健康检查请求能通过Django的Host验证:
# settings.py ALLOWED_HOSTS = [ "my-site.com", "10.0.0.0/24", # 替换为你的ECS容器所在的内网IP段 "ELB-健康检查-IP", # 替换为ELB健康检查的来源IP ]
注意:
这种方案只是让健康检查请求通过,但无法阻止其他非法Host的请求到达Django,仍会产生DisallowedHost错误邮件,因此仅作为临时过渡方案,优先推荐方案1或2。
内容的提问来源于stack exchange,提问作者PLR06157
相关产品推荐
相关产品推荐

