AWS、Nginx 和 Django:用于防止伪造主机字符串的默认服务器

AWS、Nginx 和 Django:用于防止伪造主机字符串的默认服务器

我们使用 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
}

相关内容