diff mod_firewall/conditions.lib.lua @ 6502:b15601203d0d

mod_firewall: Support 'FROM IP' and 'FROM SUBNET' conditions
author Matthew Wild <mwild1@gmail.com>
date Thu, 26 Mar 2026 13:33:44 +0000
parents cc665f343690
children f61564e11d3b
line wrap: on
line diff
--- a/mod_firewall/conditions.lib.lua	Wed Mar 25 18:52:10 2026 +0000
+++ b/mod_firewall/conditions.lib.lua	Thu Mar 26 13:33:44 2026 +0000
@@ -2,6 +2,8 @@
 local condition_handlers = {};
 
 local jid = require "util.jid";
+local iplib = require "util.ip";
+local sha256 = require "util.hashes".sha256;
 local unpack = table.unpack or unpack;
 
 -- Helper to convert user-input strings (yes/true//no/false) to a bool
@@ -381,6 +383,28 @@
 	};
 end
 
+function condition_handlers.FROM_IP(ip_spec)
+	local parsed_ip, err = iplib.new_ip(ip_spec);
+	if not parsed_ip then
+		error("Cannot parse IP address: "..(err or "unknown error"));
+	end
+	local normal_ip = tostring(parsed_ip);
+	return ("session.ip == %q"):format(normal_ip);
+end
+
+function condition_handlers.FROM_SUBNET(subnet_spec)
+	local subnet, bits = iplib.parse_cidr(subnet_spec);
+	if not subnet then
+		error("Cannot parse subnet CIDR");
+	end
+	local spec_hash = sha256(subnet_spec, true):sub(1, 8);
+	return ("iplib.match(session_parsed_ip, parsed_ip_%s, %d)"):format(
+		spec_hash, bits
+	), {
+		"iplib", "session_parsed_ip", "parsed_ip:"..spec_hash..":"..tostring(subnet)
+	};
+end
+
 -- FROM COUNTRY: SE
 -- FROM COUNTRY: code=SE
 -- FROM COUNTRY: SWE