[WIP] feat(net): optional allow_net filtering for UDP#778
Conversation
allow_net only constrained TCP — UDP went through gvproxy's default NAT forwarder, so a restricted box could exfiltrate to any host over UDP/QUIC (DNS-over-UDP to an attacker on :53, HTTP/3 on :443, custom channels). The DNS sinkhole only governs name resolution, not datagram destinations. Add a filtered UDP forwarder that drops datagrams whose destination IP is not permitted by the AllowNet filter. The decision (udpAllowed) reuses TCPFilter.MatchesIP, so the gateway/internal IPs (incl. the embedded DNS resolver) and allowlisted hosts pass while everything else is dropped. With no allow_net, all UDP is allowed (unchanged). [WIP] gated behind BOXLITE_UDP_FILTER=true, OFF by default — the live forwarder path is NOT integration-verified. In particular, whether overriding the UDP protocol handler bypasses gvproxy's embedded DNS resolver endpoint (DNS-break risk) and the datagram relay/idle-timeout behavior must be validated against a running network stack; the repo has no such harness (forked_network_test only reflit-checks the stack field). Wiring it on by default needs that verification. Two-sided test: TestUDPAllowed confirms attacker :53/:443 and unlisted hosts are blocked while allowlisted + gateway DNS pass; reverting udpAllowed to its pre-fix "always allow" makes the blocked cases pass through and the test fails. Audit finding #2 (high). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
boxlite security fixes seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
1 similar comment
|
boxlite security fixes seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
…tion) Adds TestUDPFilter_BoundDNSEndpointNotBypassed: builds a gvisor stack, binds a UDP endpoint on gateway:53 (as gvproxy's DNS resolver does via gonet.DialUDP), installs a filtering UDP forwarder, and injects real IPv4/UDP datagrams. It confirms the load-bearing property behind OverrideUDPHandler: the transport demuxer delivers :53 to the bound resolver endpoint (DNS keeps working) while non-DNS UDP reaches the filtering forwarder (where allow_net drops it). This disproves the DNS-break concern flagged in the original WIP commit — overriding the UDP protocol handler does not bypass the bound DNS endpoint. Remaining caveat (still BOXLITE_UDP_FILTER-gated, off by default): end-to-end relay of allow-listed flows under real guest traffic is not yet load-tested. Audit finding #2 (high). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Problem
allow_netonly filtered TCP. UDP used gvproxy's default NAT forwarder, so arestricted box could exfiltrate to any host over UDP/QUIC (DNS-over-UDP to an
attacker on :53, HTTP/3 on :443, custom UDP channels). The DNS sinkhole governs
only name resolution, not datagram destinations.
Change
udpAllowed(destIP, destPort, filter)— drops UDP to destinations not permittedby the AllowNet filter; reuses
TCPFilter.MatchesIP, so gateway/internal IPs(incl. the DNS resolver) and allowlisted hosts pass. No filter → all UDP allowed.
OverrideUDPHandlerinstalls a filteredudp.NewForwarder(mirrors the TCPoverride). Wired in
main.gobehindBOXLITE_UDP_FILTER=true, OFF bydefault so the live path is unchanged.
Test (two-sided) — policy, runs locally
TestUDPAllowed: attacker:53/:443and unlisted hosts blocked; allowlisted +gateway DNS pass. Reverting
udpAllowedto "always allow" (pre-fix) makes theblocked cases pass and the test fails. Full bridge suite +
go vetgreen.What needs a resource to verify (before enabling by default)
forked_network_testonly reflect-checks the
stackfield) to drive real UDP/DNS packets and confirm:(a) non-allowlisted UDP is dropped end to end, (b) DNS still resolves (i.e.
overriding the UDP handler does not bypass the embedded resolver endpoint), and
(c) the datagram relay/idle-timeout works for allowed flows.
Audit finding #2 (high).
🤖 Generated with Claude Code