Comment désactiver l’erreur HTTP_HOST invalide de Django?

Depuis que j’ai déployé un site exécutant Django 1.7 alpha (extrait de Git), je reçois parfois des messages d’erreur avec des titres tels que:

“En-tête HTTP_HOST invalide: ‘xxx.xxx.com'”

Je me rends compte que cela est dû à l’en-tête Host: HTTP défini sur un nom d’hôte non répertorié dans ALLOWED_HOSTS . Cependant, je n’ai aucun contrôle sur quand et à quelle fréquence quelqu’un envoie une demande au serveur avec un nom d’hôte falsifié. Par conséquent, je n’ai pas besoin d’un tas d’emails d’erreur pour me faire savoir que quelqu’un d’autre tente de faire quelque chose de louche.

Est-il possible de désactiver ce message d’erreur? Les parameters de journalisation du projet ressemblent à ceci:

 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, }, } } 

Vous ne devriez pas ignorer cette erreur. Au lieu de cela, vous devriez refuser la requête avant qu’elle n’atteigne votre backend Django. Pour refuser des demandes sans HOST , vous pouvez utiliser

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

ou forcer la correspondance à un domaine particulier (example.com)

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

Vous pouvez l’append à la section des loggers de votre configuration de journalisation:

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

Cela définit le seuil de journalisation au-dessus du niveau ERROR utilisé par Django lorsqu’une opération SuspiciousOperation est détectée.

Vous pouvez également, par exemple, utiliser un FileHandler pour enregistrer ces événements sans vous les envoyer par courrier électronique. Par exemple, pour utiliser un fichier dédié uniquement pour ces événements spécifiques, vous pouvez l’append à la section handlers :

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

puis utilisez ceci dans la section des loggers :

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

Notez que la suggestion faite dans les documents de Django , à utiliser

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

dépend de l’exécution de Python 2.7 ou version ultérieure – sur 2.6, la logging ne possède pas de NullHandler .

Voici un exemple NGINX qui devrait empêcher votre django de recevoir des demandes d’ordures.

 server { listen 80 default_server; server_name _; return 418; } server { listen 80; # This will keep Django from receiving request with invalid host server_name  your.domain.com; ... 

vous pourriez faire taire cette SuspiciousOperation particulière avec quelque chose comme

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

voir ceci pour plus de références https://docs.djangoproject.com/en/dev/topics/logging/#django-security

MODIFIER

vous devez également append un gestionnaire ‘null’:

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

il suffit probablement de l’append et de modifier le niveau d’erreur (en remplaçant DEBUG par ‘ERROR’).

comme toujours se référer à la documentation pour la syntaxe complète et la sémantique.

En utilisant Apache 2.4, il n’y a pas besoin d’utiliser mod_setenvif. Le HTTP_HOST est déjà une variable et peut être évalué directement:

 WSGIScriptAlias / /path/to/wsgi.py   Require expr %{HTTP_HOST} == "example.com"   

Une autre façon de bloquer les requêtes avec un en-tête Host invalide avant d’atteindre Django consiste à utiliser une configuration Apache par défaut avec un qui ne fait que renvoyer un 404.

   

Si vous définissez ceci comme votre premier hôte virtuel (par exemple dans 000-default.conf) et que vous le suivez ensuite avec votre “vrai” , avec un et toutes les entrées < ServerAlias> que vous voulez faire correspondre, Apache renverra un 404 pour toute demande avec un en-tête Host qui ne correspond pas à ou à l’une de vos entrées . La clé pour s’assurer que la valeur par défaut 404 est définie en premier, soit par nom de fichier (‘000’), soit par la première entrée de votre fichier de configuration.

J’aime mieux que la solution populaire ci-dessus car elle est très explicite et facile à étendre.

Les autres réponses sur cette page sont correctes si vous souhaitez simplement masquer ou désactiver l’avertissement. Si vous autorisez intentionnellement chaque nom d’hôte, la valeur spéciale de * peut être utilisée comme paramètre ALLOWED_HOSTS .

Pour empêcher toute vérification du nom d’hôte, ajoutez la ligne suivante à vos 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 (eg ``.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, ssortingpped 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 

Je ne peux pas encore commenter, mais depuis que Order Deny, Allow est obsolète, la manière de le faire dans un hôte virtuel avec la directive Require actuelle est la suivante:

  SetEnvIfNoCase Host example\.com VALID_HOST Require env VALID_HOST Options  

Dans setting.py set:

 ALLOWED_HOSTS = ['yourweb.com'] 

pour plusieurs hôtes valides, vous pouvez:

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