diff mod_firewall/mod_firewall.lua @ 6538:de1f17ed4dac

mod_firewall: Add support for tracing rule evaluation in real-time
author Matthew Wild <mwild1@gmail.com>
date Mon, 11 May 2026 13:37:19 +0100
parents 9bc83fba89ac
children 430584888704
line wrap: on
line diff
--- a/mod_firewall/mod_firewall.lua	Mon May 11 13:18:45 2026 +0100
+++ b/mod_firewall/mod_firewall.lua	Mon May 11 13:37:19 2026 +0100
@@ -328,7 +328,7 @@
 	};
 
 	trace = {
-		global_code = [[local trace_init = module:require("trace").init;]];
+		global_code = [[local trace_init = module.environment.trace.init;]];
 	};
 };
 
@@ -382,6 +382,15 @@
 local condition_handlers = module:require("conditions");
 local action_handlers = module:require("actions");
 
+module.environment.trace = module:require("trace");
+
+local metadata_field_handlers = {
+	trace = function (v)
+		v = v:lower();
+		return v == "on" or v == "true";
+	end;
+};
+
 if module:get_option_boolean("firewall_experimental_user_marks", true) then
 	module:require"marks";
 end
@@ -450,6 +459,10 @@
 			if not k then
 				return nil, errmsg("Unable to parse metadata assignment (expected '@@ key = value')");
 			end
+			local handler = metadata_field_handlers[k];
+			if handler then
+				v = handler(v);
+			end
 			metadata[k] = v;
 		elseif not(state) and line:sub(1,1) == "%" then -- Definition (zone, limit, etc.)
 			local what, name = line:match("^%%%s*([%w_]+) +([^ :]+)");
@@ -566,7 +579,7 @@
 
 		if metadata.trace then
 			include_dep("trace", code);
-			table.insert(code, ("local trace = trace_init(%q, %q);"):format(metadata.filename, chain_name))
+			table.insert(code, ("local trace_record <close>, trace = trace_init(%q, %q, stanza, event.firewall_trace_tag, source_rules);"):format(metadata.filename, chain_name))
 		end
 
 		local condition_cache, n_conditions = {}, 0;
@@ -611,6 +624,9 @@
 					..table.concat(rule.actions, "\n\t\t\t")
 					.."\n\t\tend\n";
 			else
+				if metadata.trace then
+					table.insert(rule.actions, 2, ("trace(%d, nil, true)"):format(rule_n));
+				end
 				rule_code = table.concat(rule.actions, "\n\t\t");
 			end
 			table.insert(code, rule_code);
@@ -676,6 +692,8 @@
 
 function load_script(script)
 	script = resolve_script_path(script);
+	local base_name = script:match("[^/]+$");
+
 	local last_modified = (lfs.attributes(script) or {}).modification or os.time();
 	if loaded_scripts[script] then
 		if loaded_scripts[script].last_modified == last_modified then