14 KiB
Firewall Validation Log — Red Bear OS Phase 4
Created: 2026-07-26
Author: Red Bear OS networking systematic fix plan, Phase 4
Component: redbear-firewall-check + test-firewall-scenarios.sh
Requires: redbear-mini ISO, netfilter scheme (base netstack), UID 0 (root)
Overview
This document records the design, expected behavior, and validation procedure for
each of the six firewall validation scenarios. The scenarios exercise the
netfilter: scheme control plane in Red Bear OS — the packet-filter and NAT
subsystem in the base netstack daemon.
The validation harness has three parts:
| Part | Location | Purpose |
|---|---|---|
redbear-firewall-check |
local/recipes/system/redbear-hwutils/source/src/bin/redbear-firewall-check.rs |
In-guest binary that runs all 6 scenarios against /scheme/netfilter |
test-firewall-scenarios.sh |
local/scripts/test-firewall-scenarios.sh |
Host-side QEMU launcher for 3-VM topology |
FIREWALL-VALIDATION-LOG.md |
local/docs/FIREWALL-VALIDATION-LOG.md |
This document |
Netfilter Scheme Interface
The netfilter scheme (/scheme/netfilter/) exposes a filesystem-style API
authenticated by UID 0 (root). Operations:
| Path | Mode | Description |
|---|---|---|
rule/list |
Read | Text dump of all filter rules (mirrors iptables -L -n -v) |
rule/add |
Write | Append one rule (mirrors iptables -A) |
rule/del |
Write | Remove one rule by numeric id |
nat/list |
Read | Text dump of all NAT rules |
nat/add |
Write | Append one NAT rule |
nat/del |
Write | Remove one NAT rule by numeric id |
policy/<chain> |
Read/Write | Default policy for INPUT, OUTPUT, FORWARD, PREROUTING, POSTROUTING |
reset |
Write | Clear all rules, restore default ACCEPT policies, reset conntrack |
stats |
Read | Per-chain packet/byte counters, rule counts, NAT counts, conntrack summary |
conntrack/list |
Read | Per-connection entry dump with 5-tuple + packet/byte counters |
conntrack/stats |
Read | Per-protocol/state breakdown (TCP SYN/EST/FIN/TW/Close, UDP, ICMP) + over_limit + max_entries |
counters/reset |
Write | Zero per-chain and per-rule counters (preserves rules) |
log |
Read | Last 20 LOG verdict entries |
Rule Grammar
ACTION CHAIN [-i IFACE] [-o IFACE] [-p PROTO] [-s ADDR[/LEN]] [-d ADDR[/LEN]]
[--sport PORT] [--dport PORT] [state STATE|--ctstate STATE[,STATE...]]
Actions: ACCEPT, DROP, LOG, REJECT Chains: input, output, forward, prerouting, postrouting Protocols: tcp, udp, icmp, icmp6, or number States: new, established, related, invalid (comma-separated for --ctstate)
Examples:
ACCEPT input --ctstate ESTABLISHED,RELATEDDROP input -s 10.0.0.0/8ACCEPT input -p tcp --dport 22ACCEPT output -d 192.168.1.0/24 --sport 1024
NAT Rule Grammar
SNAT|DNAT hook to ADDR [port N] [match-src ADDR] [match-dst ADDR]
Examples:
SNAT postrouting to 10.0.2.15— masquerade outgoing trafficDNAT prerouting to 10.0.0.2 port 8080— port forward 80→8080SNAT postrouting to 10.0.2.15 match-src 10.0.0.1— source-specific SNAT
Scenario A: AcceptEstablished
Purpose
Verify that the default-deny INPUT + ACCEPT ESTABLISHED/RELATED pattern works. This is the most common iptables pattern: drop all incoming new connections, but allow responses to locally-initiated outbound traffic.
Prereq netcfg state
- Firewall reset to defaults (all policies ACCEPT, no rules).
- No network interfaces need to be configured at this level — the test validates the rule parser and scheme, not actual packet flow.
Exact ufw/netfilter commands
# Via scheme writes (equivalent to these netfilter scheme operations):
echo "DROP" > /scheme/netfilter/policy/input
echo "ACCEPT input --ctstate ESTABLISHED,RELATED" > /scheme/netfilter/rule/add
echo "1" > /scheme/netfilter/reset
What the test does
- Resets firewall.
- Sets INPUT policy to DROP.
- Verifies INPUT policy reads back as "DROP".
- Verifies OUTPUT policy remains "ACCEPT" (default).
- Adds
ACCEPT input --ctstate ESTABLISHED,RELATEDrule. - Verifies the rule appears in
rule/listwith a valid numeric id. - Verifies
statsendpoint returns chain counters for both input and output. - Resets firewall.
Expected output
Scenario A (AcceptEstablished) ... pass
SCENARIO_A=pass
Cleanup
- Firewall reset to defaults (all policies ACCEPT, empty rules).
Scenario B: SSHAllow
Purpose
Verify port-specific ACCEPT rules coexist correctly with the established-connections rule. This simulates opening a single service port (SSH on 22) while keeping the rest of INPUT denied.
Prereq netcfg state
- Firewall reset to defaults.
Exact ufw/netfilter commands
echo "DROP" > /scheme/netfilter/policy/input
echo "ACCEPT input -p tcp --dport 22" > /scheme/netfilter/rule/add
echo "ACCEPT input --ctstate ESTABLISHED,RELATED" > /scheme/netfilter/rule/add
echo "1" > /scheme/netfilter/reset
What the test does
- Resets firewall.
- Sets INPUT policy to DROP.
- Adds ACCEPT rule for tcp/22.
- Adds ACCEPT rule for ESTABLISHED,RELATED.
- Verifies both rules appear in
rule/list. - Verifies the SSH rule contains
dport=22but NOTdport=80(no rule leakage). - Resets firewall.
Expected output
Scenario B (SSHAllow) ... pass
SCENARIO_B=pass
Cleanup
- Firewall reset to defaults.
Scenario C: SNATMASQ
Purpose
Verify Source NAT (masquerade) rule configuration. This simulates a router with an internal subnet 10.0.0.0/24 whose outbound traffic is rewritten to use the router's external IP.
Prereq netcfg state
- Firewall reset to defaults.
- No actual routing needed — the test validates the NAT table control plane.
Exact ufw/netfilter commands
echo "SNAT postrouting to 10.0.2.15 match-src 10.0.0.1" > /scheme/netfilter/nat/add
echo "1" > /scheme/netfilter/reset
What the test does
- Resets firewall.
- Adds SNAT rule:
SNAT postrouting to 10.0.2.15 match-src 10.0.0.1. - Reads
nat/listand verifies the rule appears withSnattype and10.0.2.15target. - Verifies
nat/listheader (Nat table:) is present. - Reads
statsand verifies it includessnat=anddnat=counters. - Resets firewall.
Expected output
Scenario C (SNATMASQ) ... pass
SCENARIO_C=pass
Cleanup
- Firewall reset to defaults.
Scenario D: DNATPortFwd
Purpose
Verify Destination NAT (port forwarding) rule configuration. This simulates redirecting incoming traffic on the router's public IP port 80 to an internal server at 10.0.0.2:8080.
Prereq netcfg state
- Firewall reset to defaults.
Exact ufw/netfilter commands
echo "DNAT prerouting to 10.0.0.2 port 8080" > /scheme/netfilter/nat/add
echo "SNAT postrouting to 10.0.2.15" > /scheme/netfilter/nat/add
echo "1" > /scheme/netfilter/reset
What the test does
- Resets firewall.
- Adds DNAT rule:
DNAT prerouting to 10.0.0.2 port 8080. - Verifies the rule appears in
nat/listwithDnat,10.0.0.2, and8080. - Verifies port info (
8080) is present in the formatted output. - Adds a second NAT rule (SNAT) to verify coexistence.
- Verifies both SNAT and DNAT rules appear in the combined NAT table.
- Resets firewall.
Expected output
Scenario D (DNATPortFwd) ... pass
SCENARIO_D=pass
Cleanup
- Firewall reset to defaults.
Scenario E: ConntrackLifecycle
Purpose
Verify that the connection tracking (conntrack) module is initialized and reporting statistics. The conntrack table tracks TCP state transitions (SYN_SENT → SYN_RECV → ESTABLISHED → FIN_WAIT → TIME_WAIT), UDP streams, and ICMP echo exchanges.
Prereq netcfg state
- Firewall reset to defaults.
- Conntrack module auto-initialized (FilterTable::new creates ConntrackTable).
Exact ufw/netfilter commands
cat /scheme/netfilter/conntrack/stats
cat /scheme/netfilter/conntrack/list
What the test does
- Resets firewall.
- Reads
conntrack/statsand verifies all required fields:tcp_entries:(with state breakdown in parentheses)udp_entries:icmp_entries:over_limit:(parsed as u64)total_entries:(parsed as u64)max_entries:(must be > 0)
- Reads
conntrack/listand verifies the header (conntrack entries:) is present. - Verifies the
total_entriesvalue is a valid u64 number. - Resets firewall.
Expected output
Scenario E (ConntrackLifecycle) ... pass
SCENARIO_E=pass
Cleanup
- Firewall reset to defaults (also resets conntrack table).
Scenario F: SYNFlood
Purpose
Verify that the SYN rate-limiting infrastructure is wired into the conntrack
module. The conntrack table has a per-source-IP SYN counter (limit: 100 SYN/sec,
window: 1 second) that increments the over_limit counter when a source exceeds
the threshold.
Prereq netcfg state
- Firewall reset to defaults.
Exact ufw/netfilter commands
cat /scheme/netfilter/conntrack/stats
cat /scheme/netfilter/stats
What the test does
- Resets firewall.
- Reads
conntrack/statsand verifiesover_limitfield exists and parses as u64. - Logs the initial
over_limitvalue (expected 0; non-zero accepted as traffic residue). - Reads
max_entriesand verifies it is > 0 (table is enabled, not size-0). - Verifies
icmp_errorsfield exists (independent rate limit structure from SYN limit). - Reads
statsand verifiesrules:field exists. - Resets firewall.
Expected output
Scenario F (SYNFlood) ... pass
SCENARIO_F=pass
Cleanup
- Firewall reset to defaults.
3-VM QEMU Topology
The test-firewall-scenarios.sh script creates three VMs connected by
AF_UNIX socket pairs, simulating a routed network:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ VM-A │ │ Router-VM │ │ VM-B │
│ (internal) │◄───►│ 2 NICs │◄───►│ (external) │
│ 10.0.0.2/24 │ │ eth0: 10.0.0.1 │ │ 10.0.2.200/24│
└─────────────┘ │ eth1: 10.0.2.100│ └─────────────┘
└─────────────┘
Network configuration
| VM | NIC | MAC | Subnet | Role |
|---|---|---|---|---|
| Router-VM | eth0 | 52:54:00:12:34:01 | 10.0.0.0/24 | Internal gateway |
| Router-VM | eth1 | 52:54:00:12:34:02 | 10.0.2.0/24 | External NAT interface |
| VM-A | eth0 | 52:54:00:12:34:0A | 10.0.0.0/24 | Internal client |
| VM-B | eth0 | 52:54:00:12:34:0B | 10.0.2.0/24 | External peer |
Packet capture
Each NIC has a QEMU filter-dump object that writes a pcap file:
artifacts/firewall-<date>/router-eth0.pcap— Internal subnet trafficartifacts/firewall-<date>/router-eth1.pcap— External subnet trafficartifacts/firewall-<date>/vm-a-net0.pcap— Internal peer trafficartifacts/firewall-<date>/vm-b-net0.pcap— External peer traffic
Automated check mode
# Build the ISO first:
./local/scripts/build-redbear.sh redbear-mini
# Run the automated firewall check:
./local/scripts/test-firewall-scenarios.sh --check redbear-mini
This boots the Router-VM, logs in via expect, runs redbear-firewall-check,
captures all 6 scenario results, and exits with code 0 only if all pass.
Interactive mode
./local/scripts/test-firewall-scenarios.sh redbear-mini
All three VMs boot and wait. Log into Router-VM manually and run
redbear-firewall-check. Press Ctrl+C to stop all VMs.
Recipe Integration
The redbear-firewall-check binary is part of the redbear-hwutils crate.
It is built alongside other validation binaries (lspci, redbear-phase5-*, etc.)
via the [[bin]] entry in Cargo.toml and mapped to a /usr/bin path in
recipe.toml under [package.files].
Files modified
| File | Change |
|---|---|
local/recipes/system/redbear-hwutils/source/Cargo.toml |
Added [[bin]] entry |
local/recipes/system/redbear-hwutils/recipe.toml |
Added /usr/bin/redbear-firewall-check line |
local/recipes/system/redbear-hwutils/source/src/bin/redbear-firewall-check.rs |
New file — 6 scenarios |
local/scripts/test-firewall-scenarios.sh |
New file — 3-VM QEMU launcher |
local/docs/FIREWALL-VALIDATION-LOG.md |
New file — this document |
Limitations
-
Control-plane validation only. The
redbear-firewall-checkbinary validates the netfilter scheme control plane (rule add/del, NAT add/del, policy read/write, stats read, conntrack stats read). It does NOT generate actual network traffic through the netstack's filter evaluation path. End-to-end traffic validation requires the 3-VM QEMU topology with real packet flow and pcap capture. -
SYN flood detection. The test verifies the
over_limitcounter and rate-limit infrastructure exist. Actual SYN flood trigger requires100 SYN packets in <1 second from a single source through the netstack — this is validated by the pcap captures in the 3-VM topology, not by the in-guest binary alone.
-
NAT packet rewriting. The test verifies NAT rules are parsed and stored. Actual IP/port rewriting by
rewrite_src_ipv4/rewrite_dst_ipv4/rewrite_port_ipv4requires real packets routed through the netstack, which is validated by the 3-VM QEMU topology. -
No per-scenario network traffic generation. Each scenario resets the firewall, configures rules, and reads back the state. Generating and capturing meaningful test traffic across the 3-VM topology is a separate phase (manual or scripted from inside each guest VM).
Future Work
-
Phase 4.1: Add packet generation from inside each guest VM (e.g.,
nc/socat/curlwith the Red Bear netstack socket API) to generate actual test traffic through the filter. -
Phase 4.2: Add per-scenario pcap verification — the
filter-dumpcaptures can be analyzed by host-side scripts to verify that packets were/were not transmitted according to filter rules. -
Phase 4.3: Add
redbear-firewall-check --trafficmode that spawns real TCP/UDP/ICMP traffic inside the guest and measures conntrack state transitions and rule match counts. -
Phase 4.4: Integrate with the existing network test framework (
test-phase5-network-qemu.sh) for combined network+firewall validation.