{ "info": { "author": "Ferrix Hovi", "author_email": "ferrix@codetry.fi", "bugtrack_url": null, "classifiers": [ "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 1.8", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content" ], "description": "Django X-Forwarded-For Properly\n-------------------------------\n\nThe X-Forwarded-For header is used by many reverse proxies to pass the\nIP addresses of the whole chain of hosts between client and application\nserver. The header looks something like this::\n\n X-Forwarded-For: 54.12.13.14, 192.168.2.0, 192.168.3.1\n\nThis translates to::\n\n X-Forwarded-For: client, proxy1[, proxy2[...]]\n\nHowever it is just a header. Most default configurations simply append\nto the header. It is trivial for a malicious client to deliver a header\nin the initial request::\n\n X-Forwarded-For: phony, client\n\nWhat ``django-xff`` does\n========================\n\nThis library provides a decent and configurable middleware to rewrite\nthe ``request.META['HTTP_REMOTE_ADDR']`` to the correct client IP.\n\nThis is done by setting a depth of reverse proxies to be trusted alone.\nThe ``X-Forwarded-For`` header will additionally be sanitized from any\nextraneous entries.\n\nBy default, if the expected depth of proxies is 3, the ``client``\naddress will be used in all of these examples::\n\n X-Forwarded-For: phony, client, proxy1, proxy2\n X-Forwarded-For: client, proxy1, proxy2\n X-Forwarded-For: client, proxy\n\nNote:\n\n * Less proxies than expected is allowed by default, for varying lengths\n of proxy chains, the longest is the only one that can be trusted.\n * No header set is allowed by default and the library does nothing.\n\nWhat ``django-xff`` does not do\n===============================\n\nThis library does not check the IP addresses of any proxies along the\npath of the message.\n\nThis library is unable to detect compromised proxies or any incoming\nrequests that have the right number addresses in the correct header.\n\nTODO\n====\n\n * Separate middleware that checks CIDR for the trusted proxies\n * Separate middleware that checks exact IP addresses for proxies\n\nConfiguration\n=============\n\nAdd the following to your Django ``settings.py`` module to enable this\nmiddleware for two reverse proxies expected. The middlewares are\nprocessed order of appearance. This middleware should go somewhere\nnear the top to avoid giving a potentially malicious user chances to\nvalidate passwords with malformed requests::\n\n MIDDLEWARE_CLASSES = [\n \n 'xff.middleware.XForwardedForMiddleware',\n \n ]\n\n XFF_TRUSTED_PROXY_DEPTH = 2\n\nBy default, no attempts are denied. There are several settings to send\na ``400`` (Bad Request) response to failing requests. Strict mode will\nstop all failing requests::\n\n XFF_STRICT = True\n\nTo prevent only the clearly malicious requests, use the following\ninstead::\n\n XFF_NO_SPOOFING = True\n\nTo prevent requests that do not come through enough proxies, use the\nfollowing::\n\n XFF_ALWAYS_PROXY = True\n\nThe previous setting implies a Bad Request when there is no\n``X-Forwarded-For`` header present. The following setting follows the\n``XFF_ALWAYS_PROXY`` and ``XFF_STRICT`` by default but can be set\nindependently::\n\n XFF_HEADER_REQUIRED = False\n\nEven in ``XFF_LOOSE_UNSAFE`` mode this will require the header::\n\n XFF_LOOSE_UNSAFE = True\n\nFor an unsafe setting, in development possibly, you can trust that the\nfirst entry is always correct and still get the assumed client IP in\nthe right place, use::\n\n XFF_LOOSE_UNSAFE = True\n\nIf you want to keep the ``X-Forwarded-For`` header untouched even if\nthere are extra entries, use::\n\n XFF_CLEAN = False\n\nWhitelisting\n============\n\nIn some cases requests from alternate request paths are to be expected.\nThe Amazon Elastic Loadbalancer healthcheck or other administrative\ntasks need to be available even if they do not match the criteria.\n\nThis library accepts URIs as regular expressions to be exempt for\nchecking. These will be exempt for any validation including\n``XFF_STRICT`` and ``XFF_HEADER_REQUIRED``.\n\nTo define the whitelist::\n\n XFF_EXEMPT_URLS = [\n r'^healthcheck/$',\n r'^admin/',\n ]\n\nThis will allow calling ``/healthcheck/`` and ``/admin/*`` from anywhere.\nIt is a daft idea to allow everyone to access the admin site with less\nrequirements than the other parts of the site. For this reason it is\npossible to respond with ``404`` (Not Found) when the request arrives\nthrough the main entrance::\n\n XFF_EXEMPT_STEALTH = True\n\nThis will assume that anything below ``XFF_TRUSTED_PROXY_DEPTH`` is\ntrusted. The method is naive, but effective.\n\nLogging\n=======\n\nDropped requests will be logged. This means that there will be plenty of\nlogs when the library is misconfigured or malicious things are taking\nplace. It is recommended to keep the logs for tracing in case of a real\nattack. However they can be filtered from development by setting::\n\n LOGGING = {\n 'loggers': {\n 'xff.middleware': {\n 'handlers': ['null'],\n 'propagate': False,\n },\n },\n }\n\nSetting up\n==========\n\nIt is recommended to enable the middleware with the assumed number of\nproxies and investigating the logs. If the header is not present or the\nmiddleware is not configured, there will be no log entries. If the logs\nstate that the depth is incorrect, it should be reduced. If all\nrequests are considered as spoofing, the depth should probably be\nincreased::\n\n MIDDLEWARE_CLASSES = [\n 'xff.middleware.XForwardedForMiddleware',\n 'django.contrib.sessions.middleware.SessionMiddleware',\n 'django.middleware.common.CommonMiddleware',\n 'django.contrib.auth.middleware.AuthenticationMiddleware',\n ]\n\n XFF_TRUSTED_PROXY_DEPTH = 2\n\nWhen logs appear correct, control can be increased in increments::\n\n XFF_NO_SPOOFING = True\n\nThen::\n\n XFF_STRICT = True\n\nDefining exceptions is feasible with other flags set. The following\ncould be used behind an AWS Elastic Loadbalancer to prevent entry\nwithout the proper header set but allow healthcheck to return\ncorrectly. The stealth would also mask the same URI with a 404\nerror::\n\n XFF_TRUSTED_PROXY_DEPTH = 1\n XFF_EXEMPT_URLS = [r'^health/]\n XFF_REQUIRE_HEADER = True\n XFF_EXEMPT_STEALTH = True\n\nIn case there is a chain of reverse proxies, the healthcheck URI is\navailable for all layers except the last one.\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/ferrix/xff/", "keywords": "", "license": "MIT License", "maintainer": "", "maintainer_email": "", "name": "django-xff", "package_url": "https://pypi.org/project/django-xff/", "platform": "", "project_url": "https://pypi.org/project/django-xff/", "project_urls": { "Homepage": "https://github.com/ferrix/xff/" }, "release_url": "https://pypi.org/project/django-xff/1.3.0/", "requires_dist": [ "Django (>=1.8.2)" ], "requires_python": "", "summary": "Django X-Forwarded-For Properly", "version": "1.3.0" }, "last_serial": 4676153, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "fea6bca98e0d634cf3560656b7f1deb6", "sha256": "67fd6fdf1baa02e5ce3c5a041feae3fb214a6b37eb3d9dd1967c071f7a63c148" }, "downloads": -1, "filename": "django_xff-1.0.0-py2-none-any.whl", "has_sig": false, "md5_digest": "fea6bca98e0d634cf3560656b7f1deb6", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 12295, "upload_time": "2015-11-16T07:05:45", "url": "https://files.pythonhosted.org/packages/a7/7a/d0bf70904fc0d11b0deac250f1f720826f108ef1faf8a0dd32dd55ad04f6/django_xff-1.0.0-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "615595f4a2804a8fc329c74278b0235b", "sha256": "2e3194672a9e9ef0ccf935afda78e1d4ea1fbcccac500547056d424838579424" }, "downloads": -1, "filename": "django_xff-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "615595f4a2804a8fc329c74278b0235b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 12298, "upload_time": "2015-11-16T07:05:51", "url": "https://files.pythonhosted.org/packages/be/3a/614a06b9f4d0e96ad5ac206b4aca3a322572c889e108bcf542b37185414d/django_xff-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "6a285d8447f7e3282838c1331220b898", "sha256": "34d18b35116b3e737b524f53801186d72c4d00e1ed3d14298dd75e087d5c9e48" }, "downloads": -1, "filename": "django-xff-1.0.0.tar.gz", "has_sig": false, "md5_digest": "6a285d8447f7e3282838c1331220b898", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20671, "upload_time": "2015-11-16T07:05:40", "url": "https://files.pythonhosted.org/packages/61/bf/a3f5f74a7957a3c4465e83c6079db59f842a219e996cbc11f9f693af09d6/django-xff-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "d533d641def94f6baa00b5f55d54da87", "sha256": "90f3447ecc39fbef8a9f2b266b6153f06785dcc2a524686da2bb8ff9a455c875" }, "downloads": -1, "filename": "django_xff-1.0.1-py2-none-any.whl", "has_sig": false, "md5_digest": "d533d641def94f6baa00b5f55d54da87", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 13807, "upload_time": "2015-11-17T10:50:37", "url": "https://files.pythonhosted.org/packages/a9/8f/3004a8e4f9219f374681a580f3f5008e80e44af39a684601af12102e34cf/django_xff-1.0.1-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "e8b4ac7cb4ea492fc54296838d94783a", "sha256": "e1ac1b6d770315e0dde64d8847f923467826962784c3b928bf1dba1a4f87a248" }, "downloads": -1, "filename": "django_xff-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "e8b4ac7cb4ea492fc54296838d94783a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13806, "upload_time": "2015-11-17T10:50:46", "url": "https://files.pythonhosted.org/packages/fe/d7/72b7bfe92127392adc1af0ca19a2a4abf33064800c3b3307ca9c8ea86135/django_xff-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "477ef5d27b2a1796893afc28761ccfa7", "sha256": "99785ad5d128f69cddcd821127ac71d30426bf2f6b70ba3087f5d0182fadf70b" }, "downloads": -1, "filename": "django-xff-1.0.1.tar.gz", "has_sig": false, "md5_digest": "477ef5d27b2a1796893afc28761ccfa7", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21564, "upload_time": "2015-11-17T10:50:27", "url": "https://files.pythonhosted.org/packages/45/d1/192ab1e4c4e5ba6b6da71e2619c9209bb523dd1c70156a6baa6d812b3114/django-xff-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "294a8c5d1dd6ceb84db46e6df056ff28", "sha256": "9f9cc1d649f075336af0b8682c19913340918954e8235b018388ee7cbbec6c1b" }, "downloads": -1, "filename": "django-xff-1.0.2.macosx-10.10-x86_64.tar.gz", "has_sig": false, "md5_digest": "294a8c5d1dd6ceb84db46e6df056ff28", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 14822, "upload_time": "2015-11-17T11:47:37", "url": "https://files.pythonhosted.org/packages/04/2a/2c441e03e4801317ee6d0e6c0c677a57814143bd9a489ecc911993dc3e62/django-xff-1.0.2.macosx-10.10-x86_64.tar.gz" }, { "comment_text": "", "digests": { "md5": "f1a34e3ded37e0aa21fc9c9833ba1219", "sha256": "e0dc8bfa209f1a9d7b9055ee6d093b502cad12cbdc37b59f0765a03a1b95c66c" }, "downloads": -1, "filename": "django_xff-1.0.2-py2-none-any.whl", "has_sig": false, "md5_digest": "f1a34e3ded37e0aa21fc9c9833ba1219", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 13812, "upload_time": "2015-11-17T11:48:00", "url": "https://files.pythonhosted.org/packages/1b/c6/aeb449b8406f9c3ca9cb31ec5121cdc750ac7a027f0d8941b871ab9f7896/django_xff-1.0.2-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "326a8ec880d7fdfcc0546da78dd4b520", "sha256": "ad36c3343fd6c3a938df7156afb0cef60dd740b30e187549babe0e033e260286" }, "downloads": -1, "filename": "django-xff-1.0.2.tar.gz", "has_sig": false, "md5_digest": "326a8ec880d7fdfcc0546da78dd4b520", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21575, "upload_time": "2015-11-17T11:47:46", "url": "https://files.pythonhosted.org/packages/87/56/f860f8046e226df217b7ed2f1440ddf55127701432c067666d677e5f41f9/django-xff-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "f56994249f3fad24f080550fb535b109", "sha256": "33690ba5509041c7b695ca7c080d71aedc6c335d70aafdc1e4a3752b0c1b1e9d" }, "downloads": -1, "filename": "django_xff-1.0.3-py2-none-any.whl", "has_sig": false, "md5_digest": "f56994249f3fad24f080550fb535b109", "packagetype": "bdist_wheel", "python_version": "py2", "requires_python": null, "size": 13809, "upload_time": "2015-11-17T13:37:12", "url": "https://files.pythonhosted.org/packages/ca/71/8b770abd8431a92b86af315095e3785513b54da114e2dbcfd9326edcc7ca/django_xff-1.0.3-py2-none-any.whl" }, { "comment_text": "", "digests": { "md5": "3159d0cc9e092948b04608cd0050eadf", "sha256": "2b524b611c2126132b0d7114de821a5152284e2f99d84508745579937dbc12d2" }, "downloads": -1, "filename": "django_xff-1.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "3159d0cc9e092948b04608cd0050eadf", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 13808, "upload_time": "2015-11-17T13:37:17", "url": "https://files.pythonhosted.org/packages/75/58/abfca458d251eff84c0a69b5b6c7c802b23560c10ca1c87c73f80f423045/django_xff-1.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "79d2a1a1b714cd002448342412232cad", "sha256": "9b36219f31bd803823c72c8bdd2d6b393ffdfa672110a7d535ca1cb3378801c9" }, "downloads": -1, "filename": "django-xff-1.0.3.tar.gz", "has_sig": false, "md5_digest": "79d2a1a1b714cd002448342412232cad", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21569, "upload_time": "2015-11-17T13:37:00", "url": "https://files.pythonhosted.org/packages/21/66/3d9f4d84cdd0ce8616fb0e7b7d9029bdeb58e80cbab3f185a76b346379f7/django-xff-1.0.3.tar.gz" } ], "1.0.5": [ { "comment_text": "", "digests": { "md5": "630629753837bb1be5c7c1380ee341cf", "sha256": "6a788efe178ea9d6c5249bdf3fc642c8df44d825a387268db2781b736131e2cd" }, "downloads": -1, "filename": "django_xff-1.0.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "630629753837bb1be5c7c1380ee341cf", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13822, "upload_time": "2015-11-17T20:46:23", "url": "https://files.pythonhosted.org/packages/b4/03/b594aea599fea85679ceb415e493d655857c95392bbc7ad42cdc39ca85dd/django_xff-1.0.5-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1447e3c70b13499e80dce26ce7839468", "sha256": "3f8a0dade8c3093ec1205bb9dc3b418571bb56dbf01852abe975ce211c5ce669" }, "downloads": -1, "filename": "django-xff-1.0.5.tar.gz", "has_sig": false, "md5_digest": "1447e3c70b13499e80dce26ce7839468", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21668, "upload_time": "2015-11-17T20:46:17", "url": "https://files.pythonhosted.org/packages/1b/31/129963136ac552d77f5714c1ff8424e2921bf528595a0af2aed927f3e677/django-xff-1.0.5.tar.gz" } ], "1.0.6": [ { "comment_text": "", "digests": { "md5": "ce6fe059b52d016a5759f6fa047d9752", "sha256": "482a6b82f02e7f8c294a7b81c6bc990302043f42d70c57674cf608bc77fb5320" }, "downloads": -1, "filename": "django_xff-1.0.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "ce6fe059b52d016a5759f6fa047d9752", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13832, "upload_time": "2015-11-17T21:39:48", "url": "https://files.pythonhosted.org/packages/a3/45/e2de43c546c3f2b657acc359aa444672c93f951e73b573d8c19332bbfa16/django_xff-1.0.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0c7f552b42bfcedde10ee2b963de9f80", "sha256": "220c237ff73c691eadb0a6f55ecda0e4373d8525e8eb353e03e143dc453e75b1" }, "downloads": -1, "filename": "django-xff-1.0.6.tar.gz", "has_sig": false, "md5_digest": "0c7f552b42bfcedde10ee2b963de9f80", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 21671, "upload_time": "2015-11-17T21:39:42", "url": "https://files.pythonhosted.org/packages/e5/70/7ca1fba1aff69243e4e1c8adb0f95c6f99f52cafcefe0d7686370c3725f7/django-xff-1.0.6.tar.gz" } ], "1.2.0": [ { "comment_text": "", "digests": { "md5": "4f41e3cc28fde8eeab0b95542ac668f9", "sha256": "0279aaf67fd89c3e6fb72d1313d3f1103584499260f20f844e9afb610f7f5135" }, "downloads": -1, "filename": "django_xff-1.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "4f41e3cc28fde8eeab0b95542ac668f9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 13878, "upload_time": "2017-12-15T23:25:02", "url": "https://files.pythonhosted.org/packages/c9/6c/d1facf972ebc9289f8317544abb6a0d09cd54f32f64a65fbe5d6a40ef504/django_xff-1.2.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "12d2ea3451c66747ac01f7385d41c8bc", "sha256": "6bb74fabfea15e1d101cad353b4ab7fa50203ac0c52dfc79e0819361bc867b26" }, "downloads": -1, "filename": "django-xff-1.2.0.tar.gz", "has_sig": false, "md5_digest": "12d2ea3451c66747ac01f7385d41c8bc", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23593, "upload_time": "2017-12-15T23:25:15", "url": "https://files.pythonhosted.org/packages/e6/35/9f8e83e75f8cecf5df201ec0bd79d1fed8d707fc3f2c84181fb8994c0198/django-xff-1.2.0.tar.gz" } ], "1.3.0": [ { "comment_text": "", "digests": { "md5": "342ac56844525fa915dcc5086c20939f", "sha256": "46af595516c21966ce7d4233fe91f771c16285625566b49ac34e90737107111c" }, "downloads": -1, "filename": "django_xff-1.3.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "342ac56844525fa915dcc5086c20939f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11357, "upload_time": "2019-01-09T10:16:06", "url": "https://files.pythonhosted.org/packages/db/82/07fb73cefd6239a22bd2ccb268e10a6079ff32ef61b2593e9afed342ba49/django_xff-1.3.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f22c566312fba1eaf636d4e5aec42276", "sha256": "c352f06acc8e5be9c9ffb109635ddfcc952157aee86acf9064d2457c5f818803" }, "downloads": -1, "filename": "django-xff-1.3.0.tar.gz", "has_sig": false, "md5_digest": "f22c566312fba1eaf636d4e5aec42276", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23595, "upload_time": "2019-01-09T10:16:10", "url": "https://files.pythonhosted.org/packages/4e/0a/66485627f4250133d72e9af83affbe8a410591da6b474fbb7fc425d068d0/django-xff-1.3.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "342ac56844525fa915dcc5086c20939f", "sha256": "46af595516c21966ce7d4233fe91f771c16285625566b49ac34e90737107111c" }, "downloads": -1, "filename": "django_xff-1.3.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "342ac56844525fa915dcc5086c20939f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11357, "upload_time": "2019-01-09T10:16:06", "url": "https://files.pythonhosted.org/packages/db/82/07fb73cefd6239a22bd2ccb268e10a6079ff32ef61b2593e9afed342ba49/django_xff-1.3.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f22c566312fba1eaf636d4e5aec42276", "sha256": "c352f06acc8e5be9c9ffb109635ddfcc952157aee86acf9064d2457c5f818803" }, "downloads": -1, "filename": "django-xff-1.3.0.tar.gz", "has_sig": false, "md5_digest": "f22c566312fba1eaf636d4e5aec42276", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 23595, "upload_time": "2019-01-09T10:16:10", "url": "https://files.pythonhosted.org/packages/4e/0a/66485627f4250133d72e9af83affbe8a410591da6b474fbb7fc425d068d0/django-xff-1.3.0.tar.gz" } ] }