changeset 6348:9d3e6d2f25c7

mod_net_proxy: Add support for `proxy_out` and `proxy_secure`
author moparisthebest <admin@moparisthebest.com>
date Fri, 14 Nov 2025 02:06:22 -0400
parents 7ed4627ba65d
children 2d256ea0c157
files mod_net_proxy/README.md mod_net_proxy/mod_net_proxy.lua
diffstat 2 files changed, 69 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/mod_net_proxy/README.md	Thu Nov 06 15:25:19 2025 +0100
+++ b/mod_net_proxy/README.md	Fri Nov 14 02:06:22 2025 -0400
@@ -24,6 +24,7 @@
 or within
 [the official protocol specifications.](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)
 
+It also allows to set an outgoing (s2s) proxy, and optionally mark any of these connections secure.
 
 Usage
 =====
@@ -64,6 +65,29 @@
 
   Example: proxy_ports = { 15222, 15269 }
 ]]--
+
+-- make all outgoing s2s connections directly to here instead
+proxy_out = { "192.168.10.1", 15270 }
+
+--[[
+  Mark incoming/outgoing connections from/to proxy as secure.
+  This is just shorthand to override `proxy_secure_in` and `proxy_secure_out` below.
+]]--
+proxy_secure = true
+
+--[[
+  Mark incoming connections from proxy as secure.
+  The proxy must guarantee this by requiring encryption and properly validating
+  incoming s2s certs.
+]]--
+proxy_secure_in = true
+
+--[[
+  Mark outgoing connections to proxy as secure.
+  The proxy must guarantee this by requiring encryption, and sending client cert
+  for s2s connections.
+]]--
+proxy_secure_out = true
 ```
 
 The above example configuration, which needs to be placed in the global section,
@@ -173,6 +197,7 @@
 
   ----- -----
   trunk Works
+  13    Works
   0.12  Works
   0.11  Works
   0.10  Works
--- a/mod_net_proxy/mod_net_proxy.lua	Thu Nov 06 15:25:19 2025 +0100
+++ b/mod_net_proxy/mod_net_proxy.lua	Fri Nov 14 02:06:22 2025 -0400
@@ -15,6 +15,7 @@
 local set = require "util.set";
 local portmanager = require "core.portmanager";
 local fmt = require "util.format".format;
+local basic_resolver = require "net.resolvers.basic";
 
 -- Backwards Compatibility
 local function net_ntop_bc(input)
@@ -466,3 +467,46 @@
 	listener = listener;
 	default_ports = mapped_ports;
 });
+
+function module.add_host(module)
+    local proxy_out = module:get_option("proxy_out", "");
+
+    local proxy_secure = module:get_option("proxy_secure", false);
+    local proxy_secure_in = proxy_secure or module:get_option("proxy_secure_in", false);
+    local proxy_secure_out = proxy_secure or module:get_option("proxy_secure_out", false);
+
+    if proxy_out ~= "" then
+        -- this redirects outgoing s2s connections to a static host:port
+        local host, port = proxy_out[1] or proxy_out, tonumber(proxy_out[2]) or 15270;
+        module:log("debug", "proxy_out: '%s:%d' proxy_secure_out: %s proxy_secure_in: %s", host, port, proxy_secure_out, proxy_secure_in);
+        module:hook("s2sout-pre-connect", function (event)
+            local session = event.session;
+
+            module:log("debug", "proxy_out redirect for '%s'", session.to_host);
+
+            if proxy_secure_out then
+                -- mark it secure so we will offer SASL EXTERNAL auth
+                session.secure = true;
+            end
+
+            event.resolver = basic_resolver.new(host, port, "tcp");
+        end);
+    else
+        module:log("debug", "proxy_secure_in: %s", proxy_secure_in);
+    end
+
+    if proxy_secure_in then
+        -- this hook marks incoming s2s as secure so we offer SASL EXTERNAL auth
+        module:hook("s2s-stream-features", function(event)
+            local session = event.origin;
+            -- check that proxyip isn't nil to make sure the connection was handled by this module
+            if session.conn.proxyip and session.type == "s2sin_unauthed" then
+                module:log("debug", "proxy_in for '%s' marked secure with validated cert", session.from_host);
+                session.secure = true;
+                session.cert_chain_status = "valid";
+                session.cert_identity_status = "valid";
+            end
+        end, 9000);
+    end
+
+end