changeset 8886:3d7ba590f6f5

auth: only use X- headers instead of REMOTE_ADDR if explicitly told so in remote_addr_header Before, X-Forwarded-For (and others) headers would *always* be trusted blindly, also in setups without a proxy server. It would thus in some cases be possible for users to fake their IP, and thus potentially be possible to bypass IP restrictions configured in Kallithea. Fixed by making it configurable which WSGI environment variable to use for the remote address. Users can configure remote_addr_header to for example HTTP_X_FORWARDED_FOR instead of using the default REMOTE_ADDR. This change is a bit similar to what is going on in the https_fixup middleware, but is doing a bit more of what for example is happening in similar code in werkzeug/middleware/proxy_fix.py .
author Mads Kiilerich <mads@kiilerich.com>
date Sun, 09 May 2021 22:34:02 +0200
parents f08fbf424898
children 070b8c39736f
files development.ini docs/setup.rst kallithea/controllers/base.py kallithea/templates/ini/template.ini.mako
diffstat 4 files changed, 18 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/development.ini	Sun May 09 22:32:51 2021 +0200
+++ b/development.ini	Sun May 09 22:34:02 2021 +0200
@@ -111,6 +111,9 @@
 ## cut off limit for large diffs (size in bytes)
 cut_off_limit = 256000
 
+## WSGI environment variable to get the IP address of the client (default REMOTE_ADDR)
+#remote_addr_variable = HTTP_X_FORWARDED_FOR
+
 ## always pretend the client connected using HTTPS (default false)
 #force_https = true
 
--- a/docs/setup.rst	Sun May 09 22:32:51 2021 +0200
+++ b/docs/setup.rst	Sun May 09 22:34:02 2021 +0200
@@ -423,8 +423,12 @@
 configured to pick that information up and trust it.
 
 Kallithea will by default rely on its WSGI server to provide the IP of the
-client in the WSGI environment as ``REMOTE_ADDR``, but it can also
-get it from the ``X-Real-IP`` or ``X-Forwarded-For`` HTTP headers.
+client in the WSGI environment as ``REMOTE_ADDR``, but it can be configured to
+get it from an HTTP header that has been set by the proxy server. For
+example, if the proxy server puts the client IP in the ``X-Forwarded-For``
+HTTP header, set::
+
+    remote_addr_variable = HTTP_X_FORWARDED_FOR
 
 Kallithea will by default rely on finding the protocol (``http`` or ``https``)
 in the WSGI environment as ``wsgi.url_scheme``. If the proxy server puts
--- a/kallithea/controllers/base.py	Sun May 09 22:32:51 2021 +0200
+++ b/kallithea/controllers/base.py	Sun May 09 22:34:02 2021 +0200
@@ -81,20 +81,12 @@
 
 
 def get_ip_addr(environ):
-    proxy_key = 'HTTP_X_REAL_IP'
-    proxy_key2 = 'HTTP_X_FORWARDED_FOR'
-    def_key = 'REMOTE_ADDR'
-
-    ip = environ.get(proxy_key)
-    if ip:
-        return _filter_proxy(ip)
-
-    ip = environ.get(proxy_key2)
-    if ip:
-        return _filter_proxy(ip)
-
-    ip = environ.get(def_key, '0.0.0.0')
-    return _filter_proxy(ip)
+    """The web server will set REMOTE_ADDR to the unfakeable IP layer client IP address.
+    If using a proxy server, make it possible to use another value, such as
+    the X-Forwarded-For header, by setting `remote_addr_variable = HTTP_X_FORWARDED_FOR`.
+    """
+    remote_addr_variable = kallithea.CONFIG.get('remote_addr_variable', 'REMOTE_ADDR')
+    return _filter_proxy(environ.get(remote_addr_variable, '0.0.0.0'))
 
 
 def get_path_info(environ):
--- a/kallithea/templates/ini/template.ini.mako	Sun May 09 22:32:51 2021 +0200
+++ b/kallithea/templates/ini/template.ini.mako	Sun May 09 22:34:02 2021 +0200
@@ -174,6 +174,9 @@
 <%text>##</%text> cut off limit for large diffs (size in bytes)
 cut_off_limit = 256000
 
+<%text>##</%text> WSGI environment variable to get the IP address of the client (default REMOTE_ADDR)
+#remote_addr_variable = HTTP_X_FORWARDED_FOR
+
 <%text>##</%text> always pretend the client connected using HTTPS (default false)
 #force_https = true