[Django]-Suppress admin email on django ALLOWED_HOSTS exception

39👍

For completeness you can override parts of the logging: (tested on django 1.6):

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'null': {
            'level': 'DEBUG',
            'class': 'logging.NullHandler',
        },
    },
    'loggers': {
        'django.security.DisallowedHost': {
            'handlers': ['null'],
            'propagate': False,
        },
    },
}

Also see Django security docs.

6👍

To suppress the admin email, define a logging filter:

def skip_suspicious_operations(record):
    if record.name == 'django.security.DisallowedHost':
        return False
    return True

Then in settings.py add it to the LOGGING dict as a filter:

'filters': {
    'skip_suspicious_operations': { 
        '()': 'django.utils.log.CallbackFilter',
        'callback': skip_suspicious_operations,
    }
}

and add the filter to the mail_admins handler:

'handlers': {
    'mail_admins': {
        'level': 'ERROR',
        'filters': ['skip_suspicious_operations'],
        'include_html' : True,
    }
}

This works in Django 1.6 as is. In Django-1.5 I think the RHS of the comparison with record.name is a little different, but otherwise it should work.

👤Nils

4👍

Apache

If you’re using Apache you can filter out the traffic to different hosts from the httpd.conf — this is a much simpler solution than writing any code. Something like

WSGIPythonPath [your Python path]
ServerSignature Off
ServerTokens Prod

<VirtualHost *:80>
    DocumentRoot /var/www
</VirtualHost>

<VirtualHost *:80>
    ServerName www.myrealhost.com
    rest of apache configuration ....
</VirtualHost>

The first setting will grab everything that doesn’t match your server name (e.g. www.myrealhost.com )

Nginx

You can use the same approach in nginx to filter out the traffic to different hosts in your configuration file using the server_name directive like

server {
    # the port your site will be served on
    listen      80;

    # the domain name it will serve for
    server_name www.myrealhost.com;  # optionally include localhost here for local testing

    ...the rest of your nginx config for Django
}
server {
     # You need to provide a default server for all other traffic
    listen 80 default_server;
    server_name  _;

    # If you need a healthcheck route that works with any hostname, unncomment
    # the next three lines
l   #location = /healthcheck {
    #    return 200;
    #}
    location / {
        return 444;
    }
 }

1👍

A bit of googling would have revealed that there’s already a bug in Django’s bug tracker for this:

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

Until there is a fix in (hopefully) Django 1.5.1, there’s a workaround involving a log filter.

👤Simon

0👍

But wait, there’s an app for that!

https://github.com/litchfield/django-safelogging

👤s29

0👍

So I typically prefer to just redirect all unmatched vhosts to a single vhost. this is done with a simple addition to the apache.conf file…

<VirtualHost *:80>
    RedirectMatch ^/?(.*) http://www.example.com/$1
</VirtualHost>

The example above would result in a request to any unmatched vhost to redirect to http://www.example.com, while retaining the path component properly.

This also has the added advantage of correcting the case where a user is following an invalid request or some such thing.

Leave a comment