Depuis que j'ai déployé un site utilisant Django 1.7 alpha (extrait de Git), je reçois parfois des messages d'erreur portant des titres tels que:
"En-tête HTTP_Host non valide: 'xxx.xxx.com'"
Je me rends compte que cela est dû au fait que l'en-tête HTTP Host:
est défini sur un nom d'hôte ne figurant pas dans ALLOWED_HOSTS
. Cependant, je ne contrôle pas 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 de plusieurs courriels d'erreur me laissant savoir que quelqu'un d'autre tente de faire quelque chose de louche.
Est-il possible de désactiver ce message d'erreur? Les paramètres de journalisation du projet se présentent comme suit:
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 demande avant qu’elle n’atteigne votre backend Django. Pour refuser des demandes sans ensemble Host
, vous pouvez utiliser
SetEnvIfNoCase Host .+ VALID_Host
Order Deny,Allow
Deny from All
Allow from env=VALID_Host
ou forcer la correspondance avec un domaine particulier (exemple.com)
SetEnvIfNoCase Host example\.com VALID_Host
Order Deny,Allow
Deny from All
Allow from env=VALID_Host
Vous pouvez ajouter ceci à la section loggers
de votre configuration de journalisation:
'Django.security.DisallowedHost': {
'handlers': ['mail_admins'],
'level': 'CRITICAL',
'propagate': False,
},
Ceci définit le seuil de journalisation au-dessus du niveau ERROR
utilisé par Django quand une SuspiciousOperation
est détectée.
Alternativement, vous pouvez utiliser par exemple FileHandler
pour consigner 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 ajouter ceci à la section handlers
:
'spoof_logfile': {
'level': 'ERROR',
'class': 'logging.FileHandler',
'filename': '/path/to/spoofed_requests.log',
},
puis utilisez ceci dans la section loggers
:
'Django.security.DisallowedHost': {
'handlers': ['spoof_logfile'],
'level': 'ERROR',
'propagate': False,
},
Notez que la suggestion faite dans Django docs , d’utiliser
'Django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
dépend de votre exécution de Python 2.7 ou version ultérieure - sur 2.6, logging
n'a pas 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 <SERVER_IP> your.domain.com;
...
vous pouvez faire taire cette opération suspecte avec quelque chose comme
'loggers': {
'Django.security.DisallowedHost': {
'handlers': ['null'],
'propagate': False,
},
voir ceci pour plus de référence https://docs.djangoproject.com/en/dev/topics/logging/#Django-security
MODIFIER
vous devez également ajouter un gestionnaire 'null':
'handlers': {
'null': {
'level': 'DEBUG',
'class': 'logging.NullHandler',
},
}
vous n'avez probablement besoin que d'ajouter ceci et de modifier le niveau d'erreur (en remplaçant DEBUG par 'ERROR').
comme toujours, consultez la documentation pour connaître la syntaxe complète et la sémantique.
Avec Apache 2.4, il n’est pas nécessaire d’utiliser mod_setenvif. HTTP_Host est déjà une variable et peut être évalué directement:
WSGIScriptAlias / /path/to/wsgi.py
<Directory /path/to>
<Files wsgi.py>
Require expr %{HTTP_Host} == "example.com"
</Files>
</Directory>
Une autre façon de bloquer les demandes avec un en-tête d’hôte non valide avant d’atteindre Django consiste à utiliser une configuration default Apache avec un <VirtualHost>
qui ne fait que renvoyer un 404.
<VirtualHost *:80>
</VirtualHost>
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' <VirtualHost>
, complété par un <ServerName>
et toutes les entrées <ServerAlias>
à faire correspondre, Apache retournera un toute demande avec un en-tête Host
qui ne correspond pas à <ServerName>
ou à l'une de vos entrées <ServerAlias>
. La clé permet de s'assurer que la valeur par défaut, 404 <VirtualHost>
, 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 cela 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 cherchez simplement à masquer ou à désactiver l’avertissement. Si vous autorisez intentionnellement chaque nom d'hôte, la valeur spéciale *
peut être utilisée comme paramètre ALLOWED_HOSTS
.
Pour empêcher entièrement la vérification du nom d’hôte, ajoutez la ligne suivante à votre 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
Je ne peux pas encore commenter, mais puisque Order Deny, Allow est obsolète, vous pouvez le faire dans un hôte virtuel avec la directive Require actuelle:
<Directory /var/www/html/>
SetEnvIfNoCase Host example\.com VALID_Host
Require env VALID_Host
Options
</Directory>
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