Django ALLOWED_HOSTS IPs范围

Ale*_*x T 23 django django-settings

有没有办法在django中设置ALLOWED_HOSTS IP的范围?

像这样的东西:

ALLOWED_HOSTS = ['172.17.*.*']
Run Code Online (Sandbox Code Playgroud)

Ala*_*air 24

不,这目前不可行.根据文档,支持以下语法:

['www.example.com']  # Fully qualified domain
['.example.com']  # Subdomain wildcard, matches example.com and www.example.com 
['*']  # Matches anything
Run Code Online (Sandbox Code Playgroud)

如果查看validate_host方法的实现,可以看到*不支持使用通配符.


Tho*_*ner 24

我在Django上发了一张票但是我看到这可以通过以下方式实现

from socket import gethostname, gethostbyname 
ALLOWED_HOSTS = [ gethostname(), gethostbyname(gethostname()), ] 
Run Code Online (Sandbox Code Playgroud)

https://code.djangoproject.com/ticket/27485

  • 因为它将像[“ *”]一样工作 (2认同)
  • 不幸的是,这只允许添加机器的 IP 和主机名,而不是我们信任的任何其他服务器,但不知道其静态 IP 地址,例如 Amazon 负载均衡器。如果可以添加通配符,我可以允许子网范围,但现在我必须使用 nginx 重写主机来解决该问题。 (2认同)

小智 13

这是一个快速而肮脏的解决方案.

ALLOWED_HOSTS += ['172.17.{}.{}'.format(i,j) for i in range(256) for j in range(256)]
Run Code Online (Sandbox Code Playgroud)

  • `['172.17.{}.{}'.format(i,j) for i in range(256) for j in range(256)]` 与上面使用格式相同。喜欢它。 (2认同)

ale*_*ler 13

Mozilla发布了一个名为django-allow-cidr的Python软件包,旨在解决这个问题.

公告博客文章解释说,它对于没有Host标题且仅使用IP地址的健康检查等内容非常有用.

你将不得不改变你的IP地址'172.17.*.*'略是一个CIDR范围内172.17.0.0/16

  • 请注意,这将允许诸如“172.17.malicious.host.com”之类的恶意内容 (3认同)
  • @科尔不会。查看源代码https://github.com/mozmeao/django-allow-cidr/blob/master/allow_cidr/middleware.py 你可以看到它只会匹配特定的IP。`self.allowed_cidr_nets = [IPNetwork(net) for net in allowed_cidr_nets]` `for net in self.allowed_cidr_nets:` 您可以查看有关 IPNetwork 的更多信息 https://netaddr.readthedocs.io/en/latest/tutorial_01.html#slicing “使用生成器可确保高效地处理大型 IP 子网。” (2认同)

Dra*_*obZ 6

如果我们研究一下 Django 如何验证主机,我们可以深入了解如何制作更灵活的ALLOWED_HOSTS条目:

def validate_host(host, allowed_hosts):
    """
    Validate the given host for this site.

    Check that the host looks valid and matches a host or host pattern in the
    given list of ``allowed_hosts``. Any pattern beginning with a period
    matches a domain and all its subdomains (e.g. ``.example.com`` matches
    ``example.com`` and any subdomain), ``*`` matches anything, and anything
    else must match exactly.

    Note: This function assumes that the given host is lowercased and has
    already had the port, if any, stripped off.

    Return ``True`` for a valid host, ``False`` otherwise.
    """
    return any(pattern == '*' or is_same_domain(host, pattern) for pattern in allowed_hosts)

. . .

def is_same_domain(host, pattern):
    """
    Return ``True`` if the host is either an exact match or a match
    to the wildcard pattern.

    Any pattern beginning with a period matches a domain and all of its
    subdomains. (e.g. ``.example.com`` matches ``example.com`` and
    ``foo.example.com``). Anything else is an exact string match.
    """
    if not pattern:
        return False

    pattern = pattern.lower()
    return (
        pattern[0] == '.' and (host.endswith(pattern) or host == pattern[1:]) or
        pattern == host
    )
Run Code Online (Sandbox Code Playgroud)

这是一个RegexHost可以通过此验证的实用程序。

class RegexHost(str):
    def lower(self):
        return self

    def __init__(self, pattern):
        super().__init__()
        self.regex = re.compile(pattern)

    def __eq__(self, other):
        # override the equality operation to use regex matching
        # instead of str.__eq__(self, other) 
        return self.regex.match(other)
Run Code Online (Sandbox Code Playgroud)

可以像这样使用:

# this matches '172.17.*.*' and also many impossible IPs
host = RegexHost(r'172\.17\.[0-9]{1,3}\.[0-9]{1,3}')

# Un-comment the below assertions to prove to yourself that this host
# validation works. Do not leave these assertions active in 
# production code for startup performance considerations.

# assert all(host == f'172.17.{i}.{j}' for i in range(256) for j in range(256))
# assert not any(host == f'172.18.{i}.{j}' for i in range(256) for j in range(256))
ALLOWED_HOSTS = [host]
Run Code Online (Sandbox Code Playgroud)

  • 请记住,这只会在服务器启动时运行,因此即使他们确实将其保留在设置文件中,应用程序的性能也不会受到影响。我会将它们注释掉,以防有人对此感到困惑。 (3认同)