Files
RedBear-OS/local/docs/FIREWALL-VALIDATION-LOG.md
T

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,RELATED
  • DROP input -s 10.0.0.0/8
  • ACCEPT input -p tcp --dport 22
  • ACCEPT 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 traffic
  • DNAT prerouting to 10.0.0.2 port 8080 — port forward 80→8080
  • SNAT 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

  1. Resets firewall.
  2. Sets INPUT policy to DROP.
  3. Verifies INPUT policy reads back as "DROP".
  4. Verifies OUTPUT policy remains "ACCEPT" (default).
  5. Adds ACCEPT input --ctstate ESTABLISHED,RELATED rule.
  6. Verifies the rule appears in rule/list with a valid numeric id.
  7. Verifies stats endpoint returns chain counters for both input and output.
  8. 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

  1. Resets firewall.
  2. Sets INPUT policy to DROP.
  3. Adds ACCEPT rule for tcp/22.
  4. Adds ACCEPT rule for ESTABLISHED,RELATED.
  5. Verifies both rules appear in rule/list.
  6. Verifies the SSH rule contains dport=22 but NOT dport=80 (no rule leakage).
  7. 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

  1. Resets firewall.
  2. Adds SNAT rule: SNAT postrouting to 10.0.2.15 match-src 10.0.0.1.
  3. Reads nat/list and verifies the rule appears with Snat type and 10.0.2.15 target.
  4. Verifies nat/list header (Nat table:) is present.
  5. Reads stats and verifies it includes snat= and dnat= counters.
  6. 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

  1. Resets firewall.
  2. Adds DNAT rule: DNAT prerouting to 10.0.0.2 port 8080.
  3. Verifies the rule appears in nat/list with Dnat, 10.0.0.2, and 8080.
  4. Verifies port info (8080) is present in the formatted output.
  5. Adds a second NAT rule (SNAT) to verify coexistence.
  6. Verifies both SNAT and DNAT rules appear in the combined NAT table.
  7. 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

  1. Resets firewall.
  2. Reads conntrack/stats and 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)
  3. Reads conntrack/list and verifies the header (conntrack entries:) is present.
  4. Verifies the total_entries value is a valid u64 number.
  5. 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

  1. Resets firewall.
  2. Reads conntrack/stats and verifies over_limit field exists and parses as u64.
  3. Logs the initial over_limit value (expected 0; non-zero accepted as traffic residue).
  4. Reads max_entries and verifies it is > 0 (table is enabled, not size-0).
  5. Verifies icmp_errors field exists (independent rate limit structure from SYN limit).
  6. Reads stats and verifies rules: field exists.
  7. 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 traffic
  • artifacts/firewall-<date>/router-eth1.pcap — External subnet traffic
  • artifacts/firewall-<date>/vm-a-net0.pcap — Internal peer traffic
  • artifacts/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

  1. Control-plane validation only. The redbear-firewall-check binary 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.

  2. SYN flood detection. The test verifies the over_limit counter and rate-limit infrastructure exist. Actual SYN flood trigger requires

    100 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.

  3. 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_ipv4 requires real packets routed through the netstack, which is validated by the 3-VM QEMU topology.

  4. 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 / curl with the Red Bear netstack socket API) to generate actual test traffic through the filter.

  • Phase 4.2: Add per-scenario pcap verification — the filter-dump captures 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 --traffic mode 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.