Как отключить Django неверную ошибку HTTP_HOST?

С тех пор как я развернул сайт под управлением 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,
        },
    }
}

Ответ 1

Вы не должны игнорировать эту ошибку. Вместо этого вы должны отклонять запрос до того, как он достигнет вашего бэкэнда 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

Ответ 2

Вы можете добавить это в раздел loggers своей конфигурации ведения журнала:

    'django.security.DisallowedHost': {
        'handlers': ['mail_admins'],
        'level': 'CRITICAL',
        'propagate': False,
    },

Это устанавливает порог регистрации выше уровня ERROR, который использует Django, когда обнаружен SuspiciousOperation.

В качестве альтернативы вы можете использовать, например. a 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.

Ответ 3

Здесь пример NGINX, который должен помешать вашему джанго получать запросы на мусор.

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;
    ...

Ответ 4

вы можете отключить эту особую SuspiciousOperation с чем-то вроде

'loggers': {
    'django.security.DisallowedHost': {
        'handlers': ['null'],
        'propagate': False,
   },

см. это для дополнительной справки https://docs.djangoproject.com/en/dev/topics/logging/#django-security

ИЗМЕНИТЬ

вам также нужно добавить обработчик 'null':

'handlers': {
    'null': {
        'level': 'DEBUG',
        'class': 'logging.NullHandler',
    },
}

возможно, вам нужно только добавить это и изменить уровень ошибки (заменив DEBUG на "ERROR" ).

как всегда, ссылаются на документацию для полного синтаксиса и семантики.

Ответ 5

Используя 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>

Ответ 6

Другой способ блокировать запросы с недопустимым заголовком Host до того, как он достигнет Django, - это использовать конфигурацию Apache по умолчанию с <VirtualHost>, которая ничего не возвращает, а возвращает 404.

<VirtualHost *:80>
</VirtualHost>

Если вы определяете это как свой первый виртуальный хост (например, в 000-default.conf), а затем следуйте за ним с помощью своего "реального" <VirtualHost>, в который входят записи <ServerName> и any < ServerAlias>, которые вы хотите совместить, Apache вернет 404 для любых запросов с заголовком Host, который не соответствует <ServerName> или одной из ваших записей <ServerAlias>. Прежде всего, убедитесь, что значение по умолчанию - 404 <VirtualHost> - либо имя файла ('000'), либо первая запись в вашем файле конфигурации.

Мне нравится это лучше, чем популярное решение выше, потому что оно очень явное и легко расширяемое.

Ответ 7

Другие ответы на этой странице верны, если вы просто хотите скрыть или отключить предупреждение. Если вы намеренно разрешаете каждому имени хоста, специальное значение * может использоваться как параметр ALLOWED_HOSTS.

Чтобы полностью исключить проверку имени хоста, добавьте следующую строку в settings.py:

ALLOWED_HOSTS = ['*']

Источник: https://github.com/django/django/blob/master/django/http/request.py#L544-L563

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

Ответ 8

Я не могу комментировать, но поскольку Order Deny, Allow устарел, способ сделать это на виртуальном хосте с текущей директивой Require:

<Directory /var/www/html/>
    SetEnvIfNoCase Host example\.com VALID_HOST
    Require env VALID_HOST
    Options
</Directory>

Ответ 9

В параметре setting.py:

ALLOWED_HOSTS = ['yourweb.com']

Ответ 10

для нескольких допустимых хостов вы можете:

SetEnvIfNoCase Host example\.com VALID_HOST
SetEnvIfNoCase Host example2\.com VALID_HOST
SetEnvIfNoCase Host example3\.com VALID_HOST
Require env VALID_HOST