changeset 1435:396d5606477f

server (proxy): add "Forwarded" and "X-Forwarded-xxx" headers to reverse proxy
author Goffi <goffi@goffi.org>
date Mon, 14 Jun 2021 15:27:33 +0200
parents 2f6dac783c8e
children d21fbdb33c1d
files libervia/server/constants.py libervia/server/proxy.py libervia/server/server.py
diffstat 3 files changed, 36 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/libervia/server/constants.py	Wed Jun 09 16:50:07 2021 +0200
+++ b/libervia/server/constants.py	Mon Jun 14 15:27:33 2021 +0200
@@ -119,6 +119,13 @@
     HTTP_PROXY_ERROR = 502
     HTTP_SERVICE_UNAVAILABLE = 503
 
+    ## HTTP HEADERS ##
+    H_FORWARDED = "Forwarded"
+    H_X_FORWARDED_FOR = "X-Forwarded-For"
+    H_X_FORWARDED_HOST = "X-Forwarded-Host"
+    H_X_FORWARDED_PROTO = "X-Forwarded-Proto"
+
+
     ## Cache ##
     CACHE_PUBSUB = 0
 
--- a/libervia/server/proxy.py	Wed Jun 09 16:50:07 2021 +0200
+++ b/libervia/server/proxy.py	Mon Jun 14 15:27:33 2021 +0200
@@ -17,7 +17,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 from twisted.web import proxy
 from twisted.python.compat import urlquote
+from twisted.internet import address
 from sat.core.log import getLogger
+from libervia.server.constants import Const as C
 
 log = getLogger(__name__)
 
@@ -48,3 +50,29 @@
             self.path + b'/' + urlquote(path, safe=b"").encode('utf-8'),
             self.reactor
         )
+
+    def render(self, request):
+        # Forwarded and X-Forwarded-xxx headers can be set if we have behin an other proxy
+        if ((not request.getHeader(C.H_FORWARDED)
+             and not request.getHeader(C.H_X_FORWARDED_HOST))):
+            forwarded_data = []
+            addr = request.getClientAddress()
+            if ((isinstance(addr, address.IPv4Address)
+                 or isinstance(addr, address.IPv6Address))):
+                request.requestHeaders.setRawHeaders(C.H_X_FORWARDED_FOR, [addr.host])
+                forwarded_data.append(f"for={addr.host}")
+            host = request.getHeader("host")
+            if host is None:
+                port = request.getHost().port
+                hostname = request.getRequestHostname()
+                host = hostname if port in (80, 443) else f"{hostname}:{port}"
+            request.requestHeaders.setRawHeaders(C.H_X_FORWARDED_HOST, [host])
+            forwarded_data.append(f"host={host}")
+            proto = "https" if request.isSecure() else "http"
+            request.requestHeaders.setRawHeaders(C.H_X_FORWARDED_PROTO, [proto])
+            forwarded_data.append(f"proto={proto}")
+            request.requestHeaders.setRawHeaders(
+                C.H_FORWARDED, [";".join(forwarded_data)]
+            )
+
+        return super().render(request)
--- a/libervia/server/server.py	Wed Jun 09 16:50:07 2021 +0200
+++ b/libervia/server/server.py	Mon Jun 14 15:27:33 2021 +0200
@@ -1628,7 +1628,7 @@
     def getExtBaseURLData(self, request):
         """Retrieve external base URL Data
 
-        this method tried to retrieve the base URL found by external user
+        this method try to retrieve the base URL found by external user
         It does by checking in this order:
             - base_url_ext option from configuration
             - proxy x-forwarder-host headers