aboutsummaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2023-06-03 17:10:04 +0200
committerKim Alvefur <zash@zash.se>2023-06-03 17:10:04 +0200
commit8c92b32b7aa5b1457663bf39c4891fcc11fce8e5 (patch)
tree69ff19018414a17326b47e9b2b33c03acb387319 /plugins
parent3fbd92e26d9bad1e2e14c7b2d2fe4999fcf53f8a (diff)
downloadprosody-8c92b32b7aa5b1457663bf39c4891fcc11fce8e5.tar.gz
prosody-8c92b32b7aa5b1457663bf39c4891fcc11fce8e5.zip
mod_http: Use RFC 7239 Forwarded header to find original client IP
Prefer over X-Forwarded-* since it has an actual specification. Main practical difference is that Forwarded may carry more properties than only the IP address since it is a structured header. Since we parse it into an array, it is easier to do the logical thing and iterate backwards trough proxies until an untrusted one is encountered. Compare the handling of X-Forwarded-For. The 'secure' field now accounts for the full chain of proxies, which must be secure all the way to be considered secure.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/mod_http.lua21
1 files changed, 20 insertions, 1 deletions
diff --git a/plugins/mod_http.lua b/plugins/mod_http.lua
index b7912019..edf220a8 100644
--- a/plugins/mod_http.lua
+++ b/plugins/mod_http.lua
@@ -15,7 +15,8 @@ local portmanager = require "prosody.core.portmanager";
local moduleapi = require "prosody.core.moduleapi";
local url_parse = require "socket.url".parse;
local url_build = require "socket.url".build;
-local normalize_path = require "prosody.util.http".normalize_path;
+local http_util = require "prosody.util.http";
+local normalize_path = http_util.normalize_path;
local set = require "prosody.util.set";
local array = require "util.array";
@@ -319,6 +320,24 @@ end
local function get_forwarded_connection_info(request) --> ip:string, secure:boolean
local ip = request.ip;
local secure = request.secure; -- set by net.http.server
+
+ local forwarded = http_util.parse_forwarded(request.headers.forwarded);
+ if forwarded then
+ request.forwarded = forwarded;
+ for i = #forwarded, 1, -1 do
+ local proxy = forwarded[i]
+ if is_trusted_proxy(ip) then
+ ip = normal_ip(proxy["for"]);
+ secure = secure and proxy.proto == "https";
+ else
+ break
+ end
+ end
+
+ -- Ignore legacy X-Forwarded-For and X-Forwarded-Proto, handling both seems unfeasible.
+ return ip, secure;
+ end
+
local forwarded_for = request.headers.x_forwarded_for;
if forwarded_for then
-- luacheck: ignore 631