كيفية تعطيل خطأ HTTP_HOST غير صحيح في Django؟




logging http-host (7)

منذ أن قمت بنشر موقع يشغل 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,
        },
    }
}

الإجابات الأخرى في هذه الصفحة صحيحة إذا كنت تبحث فقط عن إخفاء التحذير أو تعطيله. إذا كنت تسمح عمداً لكل اسم مضيف ، يمكن استخدام القيمة الخاصة * كإعداد 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

باستخدام 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>

في ما يلي مثال NGINX الذي يجب أن يمنع جهاز django من استلام طلبات القمامة.

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

لا يمكنني التعليق حتى الآن ، ولكن نظرًا لرفض الطلب ، تم إيقاف العمل بالسماح ، فإن طريقة القيام بذلك في مضيف ظاهري باستخدام الأمر Require الحالي هو:

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

هناك طريقة أخرى لحظر الطلبات باستخدام رأس مضيف غير صالح قبل وصولها إلى Django وهي استخدام توصيف Apache افتراضي مع <VirtualHost> لا يفعل سوى إرجاع 404.

<VirtualHost *:80>
</VirtualHost>

إذا قمت بتعريف هذا على أنه مضيف ظاهري لأول مرة (على سبيل المثال في 000-default.conf) ثم اتبع ذلك مع 'الحقيقي' الخاص بك <VirtualHost> ، مع إدخالات <ServerName> و < ServerAlias> التي تريد مطابقتها ، Apache سيعود 404 لأي طلبات مع رأس Host لا يطابق <ServerName> أو أحد إدخالات <ServerAlias> الخاصة بك. المفتاح هو التأكد من أن الافتراضي ، 404 <VirtualHost> يتم تعريفه أولاً ، إما عن طريق اسم الملف ('000') أو الإدخال الأول في ملف التكوين الخاص بك.

أنا أحب هذا أفضل من الحل الشعبي أعلاه لأنه صريح جدا وسهل للتمديد.


يجب ألا تتجاهل هذا الخطأ. بدلاً من ذلك ، يجب أن تنكر الطلب قبل وصوله إلى الواجهة الخلفية لـ 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

يمكنك إضافة هذا إلى قسم loggers في تكوين تسجيل الدخول الخاص بك:

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

يقوم هذا بتعيين عتبة تسجيل الدخول إلى أعلى مستوى ERROR الذي يستخدمه Django عند اكتشاف وجود SuspiciousOperation .

بدلاً من ذلك ، يمكنك استخدام 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 ، لاستخدام

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

يعتمد على تشغيل Python 2.7 أو أحدث - على 2.6 ، لا يحتوي logging على NullHandler .





http-host