mesh.firewall
The host firewall, as the mesh needs it
What it is
What inbound traffic the declaration implies this machine must admit — the multicast group's port, the broadcast port when it is a permitted fallback, every declared hub port whose address is this machine's, and the server's own port when it listens beyond loopback — from the private networks the declaration names; which firewall front this host runs (ufw, nftables, the macOS application firewall); the commands that admit the plan there; what the firewall itself says about the plan now (present, missing, inactive, or unobservable without root); and what the kernel logged it dropping toward those ports in the last five minutes. Fails when a rule is observed missing or a drop was logged. Reads the host; changes nothing.
Descriptor
- Canonical id
mesh.firewall- Module
mesh- Kind
- query
- Stability
- experimental
- Provenance
- declared
- Source
apps/majordomus-cli/src/capability/builtin/mesh.rs- Cache
disabled- Benchmark
waived: external_dependency- Tags
- meshdiagnosticsfirewall
Run
queryProjections
| Interface | As | Where |
|---|---|---|
| MCP tool | majordomus_mesh_firewall | - |
| MCP resource | not exposed | - |
| HTTP | GET /api/v1/mesh/firewall | Swagger |
| Command line | majordomus mesh firewall | - |
Schemas
Input · FirewallInput
{
"type": "object",
"additionalProperties": false,
"properties": {
"port": {
"type": [
"integer",
"null"
],
"format": "uint16",
"minimum": 0,
"maximum": 65535,
"description": "The port this checkout's server listens on beyond loopback, when it does: a peer\ndials it there on the link protocol, so it needs admitting too. Omitted, the plan\nholds the discovery ports and the hub ports the declaration gives this machine."
}
},
"description": "The input of `mesh.firewall` and `mesh.firewall.apply`.",
"title": "FirewallInput"
}Output · FirewallReport
{
"type": "object",
"properties": {
"ok": {
"type": "boolean",
"description": "Whether the host admits the mesh as far as it can be observed: nothing missing, and\nnothing logged as dropped."
},
"platform": {
"type": "string",
"description": "The platform (`linux`, `macos`, …)."
},
"backend": {
"$ref": "#/$defs/Backend",
"description": "The firewall front found."
},
"executable": {
"type": [
"string",
"null"
],
"description": "The executable the server runs as, which is what the macOS firewall admits."
},
"plan": {
"$ref": "#/$defs/FirewallPlan",
"description": "What the declaration implies this host must admit."
},
"commands": {
"type": "array",
"items": {
"$ref": "#/$defs/AdmitCommand"
},
"description": "The commands that admit it on this backend; what `apply` runs."
},
"observation": {
"$ref": "#/$defs/FirewallObservation",
"description": "The firewall's own word about the plan."
},
"window_seconds": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"description": "The window `blocked_recently` covers, in seconds."
},
"blocked_recently": {
"type": [
"object",
"null"
],
"additionalProperties": {
"type": "integer",
"format": "uint64",
"minimum": 0
},
"description": "Drops the kernel logged toward the plan's ports within the window, per port;\nabsent when the log could not be read."
},
"verdict": {
"type": "string",
"description": "The sentence a person reads."
}
},
"required": [
"ok",
"platform",
"backend",
"plan",
"commands",
"observation",
"window_seconds",
"verdict"
],
"description": "The whole report: the plan, the backend, the commands, the firewall's word and the\nkernel's, with one verdict sentence and one `ok`. What `mesh.firewall` answers and\nwhat the doctor's `firewall` check reads.\n\n```\nuse majordomus_cli::mesh::firewall::{report, FirewallReport, BLOCK_WINDOW_SECONDS};\n\nlet r: FirewallReport = report(None, &[], None);\nassert!(r.ok && r.commands.is_empty());\nassert_eq!(r.window_seconds, BLOCK_WINDOW_SECONDS);\nassert_eq!(r.platform, std::env::consts::OS);\n```",
"title": "FirewallReport",
"$defs": {
"Backend": {
"oneOf": [
{
"type": "string",
"const": "ufw",
"description": "Uncomplicated Firewall, the Debian and Ubuntu front: `ufw` is on the path."
},
{
"type": "string",
"const": "nftables",
"description": "nftables without ufw in front: `nft` is on the path."
},
{
"type": "string",
"const": "application_firewall",
"description": "macOS: the application firewall (`socketfilterfw`), which admits executables, not ports."
},
{
"type": "string",
"const": "none",
"description": "No firewall front this executable knows; nothing is observed and nothing is applied."
}
],
"description": "The firewall front this host runs, as far as the executable can tell without privilege:\ndecided by `detect` from the platform and the path, and the thing `render`,\n`observe` and `apply` are specific to.\n\n```\nuse majordomus_cli::mesh::firewall::Backend;\n\nassert_eq!(serde_json::to_value(Backend::ApplicationFirewall).unwrap(), \"application_firewall\");\nassert_eq!(Backend::None.as_str(), \"none\");\n```"
},
"FirewallPlan": {
"type": "object",
"properties": {
"local_addresses": {
"type": "array",
"items": {
"type": "string"
},
"description": "This machine's addresses, as the plan saw them."
},
"networks": {
"type": "array",
"items": {
"type": "string"
},
"description": "The private networks peers come from: the enclosing ranges of every address the\ndeclaration names, or of this machine's own when it names none."
},
"hub_ports": {
"type": "array",
"items": {
"type": "integer",
"format": "uint16",
"minimum": 0,
"maximum": 65535
},
"description": "The ports of the declared hubs this machine is."
},
"rules": {
"type": "array",
"items": {
"$ref": "#/$defs/FirewallRule"
},
"description": "The admissions, in a fixed order."
}
},
"required": [
"local_addresses",
"networks",
"hub_ports",
"rules"
],
"description": "What the declaration implies this host must admit: the rules, the networks they admit\nfrom, the hub ports this machine is listed for, and the addresses the plan saw. The\nanswer of `plan`; an empty `rules` is \"nothing is needed\", which is the answer for no\ndeclaration and for a disabled one.\n\n```\nuse majordomus_cli::mesh::firewall::{plan, FirewallPlan};\n\nlet nothing: FirewallPlan = plan(None, &[], None);\nassert!(nothing.rules.is_empty() && nothing.hub_ports.is_empty() && nothing.networks.is_empty());\n```"
},
"FirewallRule": {
"type": "object",
"properties": {
"role": {
"$ref": "#/$defs/Role",
"description": "Why."
},
"protocol": {
"$ref": "#/$defs/Protocol",
"description": "The transport protocol."
},
"port": {
"type": "integer",
"format": "uint16",
"minimum": 0,
"maximum": 65535,
"description": "The destination port."
},
"destination": {
"type": [
"string",
"null"
],
"description": "The destination address when it is a multicast group; `None` for this host's own."
},
"sources": {
"type": "array",
"items": {
"type": "string"
},
"description": "The networks the traffic may come from, as CIDR; empty admits any source, which is\nonly ever the case for the multicast group, whose TTL keeps it on the segment."
},
"reason": {
"type": "string",
"description": "The sentence a person reads beside the rule."
}
},
"required": [
"role",
"protocol",
"port",
"sources",
"reason"
],
"description": "One inbound admission the mesh needs on this host: a protocol and a port, the group it is\naddressed to when it is multicast, the networks it may come from, and the sentence that\nsays why. A rule is derived, never written by hand; `FirewallRule::label` is how a\nverdict names it.\n\n```\nuse majordomus_cli::mesh::firewall::{FirewallRule, Protocol, Role};\n\nlet rule = FirewallRule {\n role: Role::Hub,\n protocol: Protocol::Tcp,\n port: 8791,\n destination: None,\n sources: vec![\"192.168.7.0/24\".into()],\n reason: \"this machine is a declared rendezvous hub\".into(),\n};\nassert_eq!(rule.label(), \"tcp/8791 from 192.168.7.0/24\");\n```"
},
"Role": {
"oneOf": [
{
"type": "string",
"const": "multicast",
"description": "The declared multicast group: every runtime of the segment advertises to it."
},
{
"type": "string",
"const": "broadcast",
"description": "The declared broadcast port, when broadcast is a permitted fallback."
},
{
"type": "string",
"const": "hub",
"description": "This machine is a declared rendezvous hub: the fleet registers here."
},
{
"type": "string",
"const": "link",
"description": "This machine's server is dialed by peers on the link protocol."
}
],
"description": "Why a rule exists: which part of the declaration implied it. The role is what a person\nreads beside the rule and what a verdict names, and it is serialised in snake case.\n\n```\nuse majordomus_cli::mesh::firewall::Role;\n\nassert_eq!(serde_json::to_value(Role::Hub).unwrap(), \"hub\");\nlet back: Role = serde_json::from_value(serde_json::json!(\"multicast\")).unwrap();\nassert_eq!(back, Role::Multicast);\n```"
},
"Protocol": {
"oneOf": [
{
"type": "string",
"const": "udp",
"description": "Datagrams: discovery."
},
{
"type": "string",
"const": "tcp",
"description": "Connections: the hub's registrations and the link protocol."
}
],
"description": "The transport protocol of a rule: discovery is datagrams, registration and the link\nprotocol are connections. Serialised as the word a firewall front takes.\n\n```\nuse majordomus_cli::mesh::firewall::Protocol;\n\nassert_eq!(serde_json::to_value(Protocol::Udp).unwrap(), \"udp\");\nassert_eq!(serde_json::to_value(Protocol::Tcp).unwrap(), \"tcp\");\n```"
},
"AdmitCommand": {
"type": "object",
"properties": {
"rule": {
"type": "string",
"description": "The rule it admits."
},
"argv": {
"type": "array",
"items": {
"type": "string"
},
"description": "The program and its arguments, as executed."
},
"line": {
"type": "string",
"description": "The same, quoted for a shell."
}
},
"required": [
"rule",
"argv",
"line"
],
"description": "One command that admits a rule: the rule's label, its argument vector exactly as\n`apply` executes it, and the same quoted as one line a person pastes into a root\nshell. The two are projections of one vector, so what the report shows is what runs.\n\n```\nuse std::net::Ipv4Addr;\nuse majordomus_cli::mesh::firewall::{plan, render, AdmitCommand, Backend};\nuse majordomus_cli::mesh::MeshConfig;\n\nlet config: MeshConfig = serde_json::from_value(serde_json::json!({\n \"schema\": \"mesh/v1\", \"kind\": \"mesh-declaration\", \"id\": \"doc\", \"enabled\": true,\n})).unwrap();\nlet p = plan(Some(&config), &[Ipv4Addr::new(10, 0, 0, 2)], None);\nlet commands: Vec<AdmitCommand> = render(Backend::Ufw, &p, None);\nassert_eq!(commands[0].argv[0], \"ufw\");\nassert_eq!(commands[0].rule, \"udp/7741 to 239.255.77.77 from any\");\nassert_eq!(commands[0].line, \"ufw allow in proto udp to 239.255.77.77 port 7741 comment 'majordomus mesh: multicast discovery'\");\n```"
},
"FirewallObservation": {
"type": "object",
"properties": {
"state": {
"$ref": "#/$defs/FirewallObservationState",
"description": "The verdict."
},
"detail": {
"type": "string",
"description": "The evidence: the status line, the rules found, or the refusal."
},
"missing": {
"type": "array",
"items": {
"type": "string"
},
"description": "The rules not admitted, by label, when `state` is `missing`."
}
},
"required": [
"state",
"detail"
],
"description": "The firewall's own word, judged against the plan: the state, the evidence behind it,\nand the labels of the rules not admitted when the state is `missing`.\n\n```\nuse majordomus_cli::mesh::firewall::{judge_ufw, plan, FirewallObservation, FirewallObservationState};\n\nlet o: FirewallObservation = judge_ufw(\"Status: inactive\\n\", &plan(None, &[], None));\nassert_eq!(o.state, FirewallObservationState::Inactive);\nassert!(o.missing.is_empty() && o.detail.contains(\"inactive\"));\n```"
},
"FirewallObservationState": {
"oneOf": [
{
"type": "string",
"const": "no_backend",
"description": "No backend to ask."
},
{
"type": "string",
"const": "inactive",
"description": "The firewall is off: nothing filters, nothing is needed."
},
{
"type": "string",
"const": "present",
"description": "Every rule of the plan is admitted."
},
{
"type": "string",
"const": "missing",
"description": "At least one rule of the plan is not admitted."
},
{
"type": "string",
"const": "unobservable",
"description": "The firewall could not be asked from this process — it needs root."
}
],
"description": "What the host's firewall says about the plan, as one word. Only `missing` is a failure\non its own; `unobservable` is an absence that the kernel log may still turn into one.\n\n```\nuse majordomus_cli::mesh::firewall::FirewallObservationState;\n\nassert_eq!(serde_json::to_value(FirewallObservationState::Unobservable).unwrap(), \"unobservable\");\n```"
}
}
}Examples
These are the capability's own benchmark cases: the same inputs the benchmark runs and the OpenAPI document shows.
declared
{}