How to disable Django's invalid HTTP_HOST error?

浪尽此生 提交于 2019-11-27 00:03:38

问题


Ever since I deployed a site running Django 1.7 alpha (checked out from Git), I've been occasionally receiving error messages with titles like:

"Invalid HTTP_HOST header: 'xxx.xxx.com'"

I realize that this is due to the Host: HTTP header being set to a hostname not listed in ALLOWED_HOSTS. However, I have no control over when and how often someone sends a request to the server with a forged hostname. Therefore I do not need a bunch of error emails letting me know that someone else is attempting to do something fishy.

Is there any way to disable this error message? The logging settings for the project look like this:

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:


You shouldn't be ignoring this error. Instead you should be denying the request before it reaches your Django backend. To deny requests with no HOST set you can use

SetEnvIfNoCase Host .+ VALID_HOST
Order Deny,Allow
Deny from All
Allow from env=VALID_HOST

or force the match to a particular domain (example.com)

SetEnvIfNoCase Host example\.com VALID_HOST
Order Deny,Allow
Deny from All
Allow from env=VALID_HOST



回答2:


You can add this to the loggers section of your logging configuration:

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

This sets the logging threshold to above the ERROR level that Django uses when a SuspiciousOperation is detected.

Alternatively, you can use e.g. a FileHandler to log these events without emailing them to you. For example, to use a dedicated file just for these specific events, you could add this to the handlers section:

    'spoof_logfile': {
        'level': 'ERROR',
        'class': 'logging.FileHandler',
        'filename': '/path/to/spoofed_requests.log',
    },

and then use this in the loggers section:

    'django.security.DisallowedHost': {
        'handlers': ['spoof_logfile'],
        'level': 'ERROR',
        'propagate': False,
    },

Note that the suggestion made in the Django docs, to use

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

depends on you running Python 2.7 or later - on 2.6, logging doesn't have a NullHandler.




回答3:


Here's NGINX example that should prevent your django from receiving rubbish requests.

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:


you could silence that particular SuspiciousOperation with something like

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

see this for more reference https://docs.djangoproject.com/en/dev/topics/logging/#django-security

EDIT

you also need to add a 'null' handler:

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

probably you only need to add this and modify the level of error (replacing DEBUG with 'ERROR').

as always refer to the the documentation for the complete syntax and semantic.




回答5:


Using Apache 2.4, there's no need to use mod_setenvif. The HTTP_HOST is already a variable and can be evaluated directly:

WSGIScriptAlias / /path/to/wsgi.py

<Directory /path/to>
    <Files wsgi.py>
        Require expr %{HTTP_HOST} == "example.com"
    </Files>
</Directory>



回答6:


Another way to block requests with an invalid Host header before it reaches Django is to use a default Apache config with a <VirtualHost> that does nothing but return a 404.

<VirtualHost *:80>
</VirtualHost>

If you define this as your first virtual host (e.g. in 000-default.conf) and then follow it with your 'real' <VirtualHost>, complete with a <ServerName> and any <ServerAlias> entries that you want to match, Apache will return a 404 for any requests with a Host header that does not match <ServerName> or one of your <ServerAlias> entries. The key it to make sure that the default, 404 <VirtualHost> is defined first, either by filename ('000') or the first entry in your config file.

I like this better than the popular solution above because it is very explicit and easy to extend.




回答7:


I can't comment yet, but since Order Deny, Allow is deprecated, the way to do this in a virtual host with the current Require directive is:

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



回答8:


The other answers on this page are correct if you're simply looking to hide or disable the warning. If you're intentionally allowing every hostname the special value of * can be used as the ALLOWED_HOSTS setting.

To prevent hostname checking entirely, add the following line to your settings.py:

ALLOWED_HOSTS = ['*']

Source: 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



回答9:


for multiple valid hosts you can:

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



回答10:


In setting.py set:

ALLOWED_HOSTS = ['yourweb.com']


来源:https://stackoverflow.com/questions/18220519/how-to-disable-djangos-invalid-http-host-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!