我们使用 AWS 设置服务器,该服务器必须满足以下要求:
1:必须允许来自负载均衡器的传入请求(具体来说,健康检查和延迟检查)到达 Web 服务器。
2:Host
必须允许包含正确字符串的有效请求到达 Web 服务器。
3:所有其他请求必须使用非标准 Nginx“444”拒绝,这意味着它们将被忽略。
此外,我们的网站有多个子域名,每个子域名都为不同的客户端运行基本相同的代码。我们已设置 Nginx,将所有到这些子域名的 http 流量重定向到 https。我将这些子域名称为“a.example.com”、“b.example.com”和“c.example.com”。
我们在日志中注意到,由于伪造的“Host”字符串绕过了 Nginx,我们的 Django 代码返回了大量 500 错误。我们看到的每个请求的主机字符串都是“*.example.com”,它与我们的任何一个子域匹配,因此进入了 Django 代码。由于该主机字符串无法识别,Django 返回了 500 错误。
以下是我们 Nginx 站点可用文件的近似值:
# Repeat this for each subdomain:
server {
server_name a.example.com;
listen 80;
return 301 https://a.example.com$request_uri;
}
server {
server_name a.example.com;
listen 443;
location / {
set $my_host $host;
if ($host ~ "\d+\.\d+\.\d+\.\d+") {
set $my_host "elb.example.com";
}
}
}
我们尝试使用 Nginx 中的以下“黑洞”服务器定义来捕获这个错误的主机字符串:
server {
server_name *.example.com;
listen 80 default_server;
listen 443 default_server;
return 444
}
但是,“*.example.com”主机字符串与其中一个 https 服务器定义匹配,并被转发到 Django 代码。
我错过了什么?
答案1
在您尝试的配置中,您需要改变的只是将server_name
变量更改为与任何其他服务器块不匹配但有效的变量,例如localhost
,并且如果请求与任何其他主机名不匹配,它应该是请求回退的服务器(因为您将其标记为default_server
- 使用通配符主机名只会使事情复杂化)。
server {
server_name localhost;
listen 80 default_server;
listen 443 default_server;
return 444
}