[英]Django ALLOWED_HOSTS IPs range
Is there a way to set a range of ALLOWED_HOSTS IPs in django?有没有办法在 django 中设置一系列 ALLOWED_HOSTS IP?
Something like this:像这样的东西:
ALLOWED_HOSTS = ['172.17.*.*']
No, this is not currently possible.不,这目前是不可能的。 According to the docs , the following syntax is supported:
根据docs ,支持以下语法:
['www.example.com'] # Fully qualified domain
['.example.com'] # Subdomain wildcard, matches example.com and www.example.com
['*'] # Matches anything
If you look at the implementation of the validate_host
method, you can see that using '*'
by itself is allowed, but using *
as a wildcard as part of a string (eg '172.17.*.*'
) is not supported.如果您查看
validate_host
方法的实现,您会发现允许'172.17.*.*'
使用'*'
,但不支持将*
作为通配符用作字符串的一部分(例如'172.17.*.*'
)。
I posted a ticket on Django however I was shown this could be achieved by doing the following我在 Django 上发布了一张票,但是我看到这可以通过执行以下操作来实现
from socket import gethostname, gethostbyname
ALLOWED_HOSTS = [ gethostname(), gethostbyname(gethostname()), ]
https://code.djangoproject.com/ticket/27485 https://code.djangoproject.com/ticket/27485
Mozilla have released a Python package called django-allow-cidr which is designed to solve exactly this problem. Mozilla 发布了一个名为django-allow-cidr的 Python 包,旨在解决这个问题。
The announcement blog post explains that it's useful for things like health checks that don't have a Host
header and just use an IP address. 公告博客文章解释说,它对于没有
Host
标头而仅使用 IP 地址的健康检查之类的事情很有用。
You would have to change your IP address '172.17.*.*'
slightly to be a CIDR range like 172.17.0.0/16
您必须将 IP 地址
'172.17.*.*'
稍微更改为CIDR 范围,例如172.17.0.0/16
这是一个快速而肮脏的解决方案。
ALLOWED_HOSTS += ['172.17.{}.{}'.format(i,j) for i in range(256) for j in range(256)]
I've found such solution for filtering range of IPs:我找到了过滤 IP 范围的解决方案:
https://stackoverflow.com/a/36222755/3766751 https://stackoverflow.com/a/36222755/3766751
Using this approach we can filter IPs by any means (fe with regex).使用这种方法,我们可以通过任何方式过滤 IP(fe with regex)。
from django.http import HttpResponseForbidden
class FilterHostMiddleware(object):
def process_request(self, request):
allowed_hosts = ['127.0.0.1', 'localhost'] # specify complete host names here
host = request.META.get('HTTP_HOST')
if host[len(host)-10:] == 'dyndns.org': # if the host ends with dyndns.org then add to the allowed hosts
allowed_hosts.append(host)
elif host[:7] == '192.168': # if the host starts with 192.168 then add to the allowed hosts
allowed_hosts.append(host)
if host not in allowed_hosts:
raise HttpResponseForbidden
return None
Thanks for @Zorgmorduk感谢@Zorgmorduk
If we take a look into how Django validates hosts, we can gain insight into how we can make more flexible ALLOWED_HOSTS
entries:如果我们看看 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
)
Here is a RegexHost
utility which can make it through this validation.这是一个
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)
Which can be used like so:可以这样使用:
# this matches '172.17.*.*' and also many impossible IPs
host = RegexHost(r'172\.17\.[0-9]{1,3}\.[0-9]{1,3}')
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]
This solution works for me:这个解决方案对我有用:
django-allow-cidr==0.5.0
to your requirements.txtdjango-allow-cidr==0.5.0
添加到您的 requirements.txt MIDDLEWARE = [ 'allow_cidr.middleware.AllowCIDRMiddleware', ... ]
ALLOWED_CIDR_NETS = ['172.17.0.0/16']
Like this:像这样:
ALLOWED_HOSTS = ['127.0.0.1', 'localhost', '.domain.com']
ALLOWED_CIDR_NETS = ['172.17.0.0/16']
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
MIDDLEWARE = [
'allow_cidr.middleware.AllowCIDRMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.