Mercurial > prosody-modules
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 6537:9bc83fba89ac | 6538:de1f17ed4dac |
|---|---|
| 326 new_long_id = { | 326 new_long_id = { |
| 327 global_code = [[local new_long_id = require "util.id".long;]]; | 327 global_code = [[local new_long_id = require "util.id".long;]]; |
| 328 }; | 328 }; |
| 329 | 329 |
| 330 trace = { | 330 trace = { |
| 331 global_code = [[local trace_init = module:require("trace").init;]]; | 331 global_code = [[local trace_init = module.environment.trace.init;]]; |
| 332 }; | 332 }; |
| 333 }; | 333 }; |
| 334 | 334 |
| 335 local function include_dep(dependency, code) | 335 local function include_dep(dependency, code) |
| 336 local dep, dep_param = dependency:match("^([^:]+):?(.*)$"); | 336 local dep, dep_param = dependency:match("^([^:]+):?(.*)$"); |
| 379 end | 379 end |
| 380 | 380 |
| 381 local definition_handlers = module:require("definitions"); | 381 local definition_handlers = module:require("definitions"); |
| 382 local condition_handlers = module:require("conditions"); | 382 local condition_handlers = module:require("conditions"); |
| 383 local action_handlers = module:require("actions"); | 383 local action_handlers = module:require("actions"); |
| 384 | |
| 385 module.environment.trace = module:require("trace"); | |
| 386 | |
| 387 local metadata_field_handlers = { | |
| 388 trace = function (v) | |
| 389 v = v:lower(); | |
| 390 return v == "on" or v == "true"; | |
| 391 end; | |
| 392 }; | |
| 384 | 393 |
| 385 if module:get_option_boolean("firewall_experimental_user_marks", true) then | 394 if module:get_option_boolean("firewall_experimental_user_marks", true) then |
| 386 module:require"marks"; | 395 module:require"marks"; |
| 387 end | 396 end |
| 388 | 397 |
| 447 ruleset[chain] = ruleset[chain] or {}; | 456 ruleset[chain] = ruleset[chain] or {}; |
| 448 elseif not(state) and line:sub(1, 2) == "@@" then | 457 elseif not(state) and line:sub(1, 2) == "@@" then |
| 449 local k, v = line:match("^@@%s*([^%s=]+)%s*=%s*(.+)$"); | 458 local k, v = line:match("^@@%s*([^%s=]+)%s*=%s*(.+)$"); |
| 450 if not k then | 459 if not k then |
| 451 return nil, errmsg("Unable to parse metadata assignment (expected '@@ key = value')"); | 460 return nil, errmsg("Unable to parse metadata assignment (expected '@@ key = value')"); |
| 461 end | |
| 462 local handler = metadata_field_handlers[k]; | |
| 463 if handler then | |
| 464 v = handler(v); | |
| 452 end | 465 end |
| 453 metadata[k] = v; | 466 metadata[k] = v; |
| 454 elseif not(state) and line:sub(1,1) == "%" then -- Definition (zone, limit, etc.) | 467 elseif not(state) and line:sub(1,1) == "%" then -- Definition (zone, limit, etc.) |
| 455 local what, name = line:match("^%%%s*([%w_]+) +([^ :]+)"); | 468 local what, name = line:match("^%%%s*([%w_]+) +([^ :]+)"); |
| 456 if not definition_handlers[what] then | 469 if not definition_handlers[what] then |
| 564 end | 577 end |
| 565 end | 578 end |
| 566 | 579 |
| 567 if metadata.trace then | 580 if metadata.trace then |
| 568 include_dep("trace", code); | 581 include_dep("trace", code); |
| 569 table.insert(code, ("local trace = trace_init(%q, %q);"):format(metadata.filename, chain_name)) | 582 table.insert(code, ("local trace_record <close>, trace = trace_init(%q, %q, stanza, event.firewall_trace_tag, source_rules);"):format(metadata.filename, chain_name)) |
| 570 end | 583 end |
| 571 | 584 |
| 572 local condition_cache, n_conditions = {}, 0; | 585 local condition_cache, n_conditions = {}, 0; |
| 573 for rule_n, rule in ipairs(rules) do | 586 for rule_n, rule in ipairs(rules) do |
| 574 for _, dep in ipairs(rule.deps) do | 587 for _, dep in ipairs(rule.deps) do |
| 609 | 622 |
| 610 rule_code = "if "..table.concat(rule.conditions, " and ").." then\n\t\t\t" | 623 rule_code = "if "..table.concat(rule.conditions, " and ").." then\n\t\t\t" |
| 611 ..table.concat(rule.actions, "\n\t\t\t") | 624 ..table.concat(rule.actions, "\n\t\t\t") |
| 612 .."\n\t\tend\n"; | 625 .."\n\t\tend\n"; |
| 613 else | 626 else |
| 627 if metadata.trace then | |
| 628 table.insert(rule.actions, 2, ("trace(%d, nil, true)"):format(rule_n)); | |
| 629 end | |
| 614 rule_code = table.concat(rule.actions, "\n\t\t"); | 630 rule_code = table.concat(rule.actions, "\n\t\t"); |
| 615 end | 631 end |
| 616 table.insert(code, rule_code); | 632 table.insert(code, rule_code); |
| 617 end | 633 end |
| 618 | 634 |
| 674 -- [filename] = { last_modified = ..., events_hooked = { [name] = handler } } | 690 -- [filename] = { last_modified = ..., events_hooked = { [name] = handler } } |
| 675 local loaded_scripts = {}; | 691 local loaded_scripts = {}; |
| 676 | 692 |
| 677 function load_script(script) | 693 function load_script(script) |
| 678 script = resolve_script_path(script); | 694 script = resolve_script_path(script); |
| 695 local base_name = script:match("[^/]+$"); | |
| 696 | |
| 679 local last_modified = (lfs.attributes(script) or {}).modification or os.time(); | 697 local last_modified = (lfs.attributes(script) or {}).modification or os.time(); |
| 680 if loaded_scripts[script] then | 698 if loaded_scripts[script] then |
| 681 if loaded_scripts[script].last_modified == last_modified then | 699 if loaded_scripts[script].last_modified == last_modified then |
| 682 return; -- Already loaded, and source file hasn't changed | 700 return; -- Already loaded, and source file hasn't changed |
| 683 end | 701 end |
