Skip to content

net: relay/firewall robustness and hosted service timeouts#72

Merged
JAORMX merged 3 commits intomainfrom
jaosorior/firewall-relay-robust
Apr 17, 2026
Merged

net: relay/firewall robustness and hosted service timeouts#72
JAORMX merged 3 commits intomainfrom
jaosorior/firewall-relay-robust

Conversation

@JAORMX
Copy link
Copy Markdown
Contributor

@JAORMX JAORMX commented Apr 17, 2026

Summary

Phase 4 of the hardening series. Three focused changes to the
network edge:

  • Cap relay frame length (net/firewall/relay.go). The length-
    prefix reader accepted any uint32 and then allocated /
    ReadFull'd that many bytes. A misbehaving peer could send
    0xFFFFFFFF and force a 4 GiB allocation. Cap at 65535 and
    treat overflow as a protocol violation that tears down the relay.
  • Drop non-IPv4 non-ARP frames under deny-default
    (net/firewall/relay.go). Previously the relay only dropped
    hdr == nil frames when a DNS hook was attached. Without one,
    IPv6 and other exotic EtherTypes slipped past even a deny-default
    filter. ARP (0x0806) continues to pass — required for VM
    bootstrap and harmless under deny.
  • Set HTTP timeouts on hosted services (net/hosted/service.go).
    http.Server previously ran with no Read/Write/Idle timeouts,
    giving a misbehaving guest a straightforward Slowloris vector
    against the host process. Defaults (10s/30s/30s/60s) applied,
    overridable per-Service via new fields. Construction extracted
    to an unexported helper so timeouts can be unit-tested without
    the full virtual-network stack.

Each commit is self-contained and includes its own tests. task verify green at every commit.

Test plan

  • task verify green at every commit
  • New unit tests:
    • TestRelay_RejectsOversizedLengthPrefix — oversized prefix
      tears down the relay within a short timeout without
      attempting the allocation.
    • TestRelay_DropsNonIPv4UnderDenyDefault — v6 frame dropped
      under deny-default without a DNS hook; ARP in the same
      session still passes.
    • TestNewHTTPServer_AppliesDefaults /
      TestNewHTTPServer_RespectsOverrides — timeouts default
      correctly and per-Service overrides take effect.
  • End-to-end via brood-box local replace:
    bbox rebuilds, VM boots, DNS egress works (api.anthropic.com
    resolves), HTTPS through the firewall returns a live response
    (api.github.com/zen 200).

🤖 Generated with Claude Code

JAORMX and others added 3 commits April 17, 2026 09:17
The length-prefix reader accepted any uint32 before allocating
and reading the declared frame payload. A misbehaving peer
(malicious guest on the VM side, or a corrupt network-side
stream) could send a 0xFFFFFFFF prefix and force a 4 GiB
make/ReadFull allocation. Ethernet frames at the topology MTU
never exceed a few KiB — cap at 65535 and treat overflow as a
protocol violation that tears down the relay.

Test writes an oversized length prefix without a payload and
asserts the relay's Run returns with "exceeds maximum" within a
short timeout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ParseHeaders returns nil for any EtherType other than IPv4
(0x0800). The relay previously only dropped hdr==nil frames
when a DNS hook was attached; without one, IPv6 and other
exotic EtherTypes slipped past even a deny-default filter.
Callers setting FirewallDefaultAction=Deny expect a closed
egress — honor that for v6 too. ARP (0x0806) continues to pass
(it is required for VM bootstrap and harmless under deny).

Test covers the new case: deny-default with no DNS hook, an
IPv6-tagged frame is dropped while an ARP frame in the same
session passes. The existing TestRelay_ARPPassthroughWithDenyAll
remains green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
http.Server previously ran with no Read/Write/Idle timeouts.
A guest that opened connections and stalled request headers
or bodies could tie up server goroutines and file descriptors
indefinitely — the classic Slowloris shape. Defaults are now
applied: 10s ReadHeader, 30s Read, 30s Write, 60s Idle.
Overridable per-Service for streaming handlers that legitimately
exceed the defaults.

Construction is extracted to an unexported newHTTPServer helper
so timeout handling can be unit-tested without spinning up the
full virtual-network stack.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JAORMX JAORMX merged commit b0eb92f into main Apr 17, 2026
7 checks passed
@JAORMX JAORMX deleted the jaosorior/firewall-relay-robust branch April 17, 2026 06:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant