Как отключить недопустимую ошибку HTTP_HOST в Django?
С тех пор, как я развернул сайт под управлением Django 1.7 alpha (проверено в Git), я иногда получал сообщения об ошибках с заголовками вроде:
"Неверный заголовок HTTP_HOST:" xxx.xxx.com ""
Я понимаю, что это связано с Host:
Для заголовка HTTP установлено имя хоста, которого нет в списке ALLOWED_HOSTS
, Однако я не контролирую, когда и как часто кто-то отправляет запрос на сервер с поддельным именем хоста. Поэтому я не нуждаюсь в куче сообщений об ошибках, сообщающих мне, что кто-то еще пытается сделать что-то подозрительное.
Есть ли способ отключить это сообщение об ошибке? Настройки ведения журнала для проекта выглядят так:
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'filters': {
'require_debug_false': {
'()': 'django.utils.log.RequireDebugFalse'
}
},
'handlers': {
'mail_admins': {
'level': 'ERROR',
'filters': ['require_debug_false'],
'class': 'django.utils.log.AdminEmailHandler'
}
},
'loggers': {
'django.request': {
'handlers': ['mail_admins'],
'level': 'ERROR',
'propagate': True,
},
}
}
13 ответов
Вы не должны игнорировать эту ошибку. Вместо этого вы должны отклонить запрос, прежде чем он достигнет вашего бэкэнда Django. Отклонять запросы без HOST
установить вы можете использовать
SetEnvIfNoCase Host .+ VALID_HOST
Order Deny,Allow
Deny from All
Allow from env=VALID_HOST
или принудительное совпадение с конкретным доменом (example.com)
SetEnvIfNoCase Host example\.com VALID_HOST
Order Deny,Allow
Deny from All
Allow from env=VALID_HOST
Вы можете добавить это к loggers
раздел вашей конфигурации регистрации:
'django.security.DisallowedHost': {
'handlers': ['mail_admins'],
'level': 'CRITICAL',
'propagate': False,
},
Это устанавливает порог регистрации выше ERROR
уровень, который использует Django, когда SuspiciousOperation
обнаружен.
Кроме того, вы можете использовать, например, FileHandler
регистрировать эти события, не отправляя их вам по электронной почте. Например, чтобы использовать выделенный файл только для этих конкретных событий, вы можете добавить его в handlers
раздел:
'spoof_logfile': {
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': '/path/to/spoofed_requests.log',
},
а затем использовать это в loggers
раздел:
'django.security.DisallowedHost': {
'handlers': ['spoof_logfile'],
'level': 'ERROR',
'propagate': False,
},
Обратите внимание, что предложение, сделанное в Django Docs, использовать
'django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
зависит от того, используете ли вы Python 2.7 или новее - на 2.6, logging
не имеет NullHandler
,
Используя Apache 2.4, нет необходимости использовать mod_setenvif. HTTP_HOST уже является переменной и может оцениваться напрямую:
WSGIScriptAlias / /path/to/wsgi.py
<Directory /path/to>
<Files wsgi.py>
Require expr %{HTTP_HOST} == "example.com"
</Files>
</Directory>
Вот пример NGINX, который должен помешать вашему django получать мусорные запросы.
server {
listen 80 default_server;
server_name _;
return 418;
}
server {
listen 80;
# This will keep Django from receiving request with invalid host
server_name <SERVER_IP> your.domain.com;
...
Вы могли бы заставить замолчать эту конкретную SuspiciousOperation чем-то вроде
'loggers': {
'django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
см. это для получения дополнительной ссылки https://docs.djangoproject.com/en/dev/topics/logging/
РЕДАКТИРОВАТЬ
вам также нужно добавить обработчик 'null':
'handlers': {
'null': {
'level': 'DEBUG',
'class': 'logging.NullHandler',
},
}
вероятно, вам нужно только добавить это и изменить уровень ошибки (заменив DEBUG на "ERROR").
как всегда обратитесь к документации для полного синтаксиса и семантики.
Документы django обращаются к этому конкретно. Они рекомендуют указать это в настройках ведения журнала.
LOGGING = {
"handlers": {
# ...
"null": {
"class": "logging.NullHandler",
},
},
"loggers": {
# ...
"django.security.DisallowedHost": {
"handlers": ["null"],
"propagate": False,
},
},
}
Другой способ заблокировать запросы с недопустимым заголовком Host до того, как он достигнет Django, - это использовать конфигурацию Apache по умолчанию с <VirtualHost>
это ничего не делает, но возвращает 404.
<VirtualHost *:80>
</VirtualHost>
Если вы определили это как ваш первый виртуальный хост (например, в 000-default.conf), а затем следуйте за ним с вашим "реальным" <VirtualHost>
, в комплекте с <ServerName>
и любой ServerAlias>
записей, которые вы хотите сопоставить, Apache вернет 404 для любых запросов с Host
заголовок, который не совпадает <ServerName>
или один из ваших <ServerAlias>
записей. Ключ, чтобы убедиться, что по умолчанию, 404 <VirtualHost>
определяется первым, либо по имени файла ('000'), либо по первой записи в вашем файле конфигурации.
Мне это нравится больше, чем популярное решение выше, потому что оно очень простое и легко расширяемое.
Я пока не могу комментировать, но так как Order Deny, Allow устарела, способ сделать это на виртуальном хосте с текущей директивой Require:
<Directory /var/www/html/>
SetEnvIfNoCase Host example\.com VALID_HOST
Require env VALID_HOST
Options
</Directory>
Другие ответы на этой странице верны, если вы просто хотите скрыть или отключить предупреждение. Если вы намеренно разрешаете каждому имени хоста специальное значение *
может быть использован как ALLOWED_HOSTS
установка.
Чтобы полностью запретить проверку имени хоста, добавьте следующую строку в settings.py
:
ALLOWED_HOSTS = ['*']
Источник: https://github.com/django/django/blob/master/django/http/request.py
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 lower-cased and has
already had the port, if any, stripped off.
Return ``True`` for a valid host, ``False`` otherwise.
"""
for pattern in allowed_hosts:
if pattern == '*' or is_same_domain(host, pattern):
return True
return False
Также для обработки следующей ошибки через Apache:
- Недопустимый заголовок HTTP_HOST: « _my.domain.com». Предоставленное доменное имя недействительно в соответствии с RFC 1034/1035.
Мы можем использовать регулярное выражение,
^[^_]+
будет соответствовать строке из 1 или более символов, содержащей любой символ, кроме подчеркивания, в поддомене , как в приведенном ниже случае.
Мы можем применить его к файлу wsgi.py
<VirtualHost xxx.xxx.xxx.xxx:XX>
...
SetEnvIfNoCase Host "^[^_]+\.my-domain\.com" VALID_HOST
<Files wsgi.py>
<RequireAll>
Require all granted
Require env VALID_HOST
</RequireAll>
</Files>
...
</VirtualHost>
С Требовать expr :
<VirtualHost xxx.xxx.xxx.xxx:XX>
...
<Files wsgi.py>
Require expr %{HTTP_HOST} =~ m#^[^_]+\.my-domain\.com#
</Files>
...
</VirtualHost>
Или мы можем использовать, что является простым способом применения конфигурации ко всему серверу.
<VirtualHost xxx.xxx.xxx.xxx:XX>
...
SetEnvIfNoCase Host "^[^_]+\.my-domain\.com" VALID_HOST
<Location />
<RequireAll>
Require all granted
Require env VALID_HOST
</RequireAll>
</Location>
...
</VirtualHost>
Из документов Apache:
Когда использовать
<Location "/">
Используйте <Location> для применения директив к содержимому, находящемуся за пределами файловой системы. Для содержимого, находящегося в файловой системе, используйте и . Исключением является <Location "/"> , который является простым способом применения конфигурации ко всему серверу.
Ответ основан на модуле Apache mod_setenvif и на том, как блокировать постоянные запросы от конкретного робота .
Вот блок NGINX, необходимый для предотвращения получения таких запросов вашим django.
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl default_server;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; # managed by Certbot
return 444;
}
Для нескольких действительных хостов вы можете:
SetEnvIfNoCase Host example\.com VALID_HOST
SetEnvIfNoCase Host example2\.com VALID_HOST
SetEnvIfNoCase Host example3\.com VALID_HOST
Require env VALID_HOST