{"record":{"id":"d5c84fc7d2c94ded","repo":"jdx/mise","slug":"firewall-rule-uses-interface-matching-which","errorCode":null,"errorMessage":"firewall rule '{}' uses interface matching, which firewalld policies cannot express safely; select backend = \"nftables\" or \"ufw\"","messagePattern":"firewall rule '(.+?)' uses interface matching, which firewalld policies cannot express safely; select backend = \"nftables\" or \"ufw\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/firewall.rs","lineNumber":1059,"sourceCode":"    for rule in &request.rules {\n        if rule.action == FirewallAction::Limit {\n            if rule.direction != FirewallDirection::Incoming\n                || rule.protocol != Some(FirewallProtocol::Tcp)\n            {\n                bail!(\n                    \"firewall rule '{}' uses action = \\\"limit\\\", which requires direction = \\\"incoming\\\" and protocol = \\\"tcp\\\"\",\n                    rule.name\n                );\n            }\n            if backend == FirewallBackend::Firewalld {\n                bail!(\n                    \"firewall rule '{}' uses per-source connection limiting, which firewalld policies cannot express safely; select backend = \\\"nftables\\\" or \\\"ufw\\\"\",\n                    rule.name\n                );\n            }\n        }\n        if backend == FirewallBackend::Firewalld && rule.interface.is_some() {\n            bail!(\n                \"firewall rule '{}' uses interface matching, which firewalld policies cannot express safely; select backend = \\\"nftables\\\" or \\\"ufw\\\"\",\n                rule.name\n            );\n        }\n        if backend == FirewallBackend::Ufw\n            && matches!(\n                rule.protocol,\n                Some(FirewallProtocol::Sctp | FirewallProtocol::Dccp)\n            )\n        {\n            bail!(\n                \"firewall rule '{}' uses protocol {}, which UFW does not support; select backend = \\\"nftables\\\" or \\\"firewalld\\\"\",\n                rule.name,\n                rule.protocol.expect(\"matched protocol\").as_str()\n            );\n        }\n    }\n    Ok(())","sourceCodeStart":1041,"sourceCodeEnd":1077,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/firewall.rs#L1041-L1077","documentation":"Interface matching (binding a rule to a specific network interface, e.g. `interface = \"eth0\"`) cannot be expressed safely in firewalld policies as mise models them. Requests that combine the firewalld backend with a rule that sets `interface` are rejected up front to avoid rules that silently behave differently than declared.","triggerScenarios":"A firewall request with `backend = \"firewalld\"` containing any rule whose `interface` field is `Some(...)` (non-empty), validated in `validate_backend_request()` before apply.","commonSituations":"Rules authored for a ufw/nftables host (where per-interface binding works) applied to a firewalld-based machine; trying to scope SSH access to one NIC on a RHEL host; config templated with interface names across heterogeneous hosts.","solutions":["Switch to `backend = \"nftables\"` or `backend = \"ufw\"`, which support interface matching","Or remove the `interface` field and rely on source CIDR restrictions to scope the rule","Or model interface scoping via firewalld zones manually and keep that rule out of the mise-managed request"],"exampleFix":"// before\nbackend = \"firewalld\"\n[[rule]]\nname = \"ssh-internal\"\ninterface = \"eth0\"\n// after\nbackend = \"firewalld\"\n[[rule]]\nname = \"ssh-internal\"\nfrom = \"10.0.0.0/8\"  # scope by source instead of interface","handlingStrategy":"validation","validationCode":"// config lint\nfunction backendSupportsInterface(backend, rules) {\n  return backend !== \"firewalld\" || !rules.some(r => r.interface);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer source CIDR scoping over interface matching for portability","Only set `interface` on ufw/nftables backends","Use firewalld zones (managed outside mise) if interface scoping is required on RHEL hosts","Validate configs per backend in CI before rollout"],"tags":["firewall","firewalld","backend-compatibility","interface"],"backgroundTag":"unsupported-operation","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}