net_allow: scheme-prefixed rules with per-protocol destination filtering#41
Merged
congwang-mk merged 4 commits intomainfrom May 6, 2026
Merged
net_allow: scheme-prefixed rules with per-protocol destination filtering#41congwang-mk merged 4 commits intomainfrom
congwang-mk merged 4 commits intomainfrom
Conversation
`--net-allow` (and the equivalent TOML/Rust/Python surfaces) now accepts an optional scheme prefix: bare host:port → tcp (unchanged) tcp://... → explicit tcp udp://... → udp; udp://*:* opts UDP socket creation in entirely icmp://host → kernel ping socket (SOCK_DGRAM + IPPROTO_ICMP) icmp://* → any ICMP echo destination Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
Signed-off-by: Cong Wang <cwang@multikernel.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three-commit rework of how
net_allowexpresses and enforces protocol gating. Pre-1.0, hard breaks — no compat shims for the oldallow_udp/allow_icmpflags.1. Scheme-prefixed rules (
042472b).--net-allow(and the equivalent TOML / Rust / Python surfaces) now accepts an optional scheme:host:port→ tcp (unchanged)tcp://.../udp://.../icmp://host/icmp://*Protocol gating falls out of rule presence per scheme — no separate boolean flag. The
allow_udpandallow_icmppolicy fields, builder methods, FFI setters, CLI flags, TOML keys, and Python dataclass fields are all dropped. Raw ICMP is no longer exposed at all (the BPF unconditionally denies SOCK_RAW); workloads that need ping should rely onnet.ipv4.ping_group_rangeand use the SOCK_DGRAM kernel ping socket viaicmp://....2. Per-protocol destination routing (
de1e55b). After commit 1 a UDP/ICMP rule's host parsed but had no runtime effect — the on-behalf handlers consulted a single globalNetworkPolicymixing all rules, so audp://1.1.1.1:53rule would also let TCP connect to that endpoint. This commit splits the resolved set intotcp/udp/icmpslices, givesNetworkStatethree protocol-keyed policies, and routes the on-behalf check viagetsockopt(SOL_SOCKET, SO_PROTOCOL)on the dup'd child fd. Onepidfd_getfdper network call serves both the protocol probe and the eventual on-behalf send. Unknown protocols (raw, SCTP, etc.) fail closed.3.
sendmmsgcoverage (549bab9). The most common UDP escape hatch — sendmmsg wasn't trapped, so an agent could batch sends to bypass per-message filtering. Factors outprescan_msghdrandsend_msghdr_on_behalffrom sendmsg, thensendmmsg_on_behalfpre-scans every entry (Continue if any has NULLmsg_nameor non-IP family), dups once, queries SO_PROTOCOL once, and loops with proper partial-failure semantics (returns N for "first N sent successfully," writes per-entrymsg_lenback). Capped at 256 entries per call. As a side effect the prescan close a TOCTOU window where the kernel re-reads child memory after our check on the Continue path.Test plan
498/498 cargo tests pass. New coverage on this branch:
NetAllow::parseunit tests covering bare-form default, all four schemes, host-scoped raw rejection, port-on-icmp rejection, unknown-scheme rejection.test_resolve_per_protocol_isolation(UDP rule doesn't leak into TCP set),test_resolve_icmp_no_ports,test_resolve_icmp_wildcard.test_udp_rule_scopes_destination_by_host(udp://127.0.0.1:53allows sendto(127.0.0.1:53), denies sendto(1.1.1.1:53) with errno 111),test_udp_wildcard_allows_any_destination,test_udp_rule_does_not_authorize_tcp(cross-protocol leak prevention).test_sendmmsg_partial_failure_on_blocked_destination(vlen=2, first allowed second blocked → ret=1, msg_len=1),test_sendmmsg_single_blocked_returns_econnrefused.test_seccomp_enforce::test_allow_icmp_*reworked to use rule-based opt-in;test_icmp_dgram_allowed_with_icmp_rulecovers the kernel ping socket path;test_raw_icmp_always_deniedproves SOCK_RAW stays denied even undericmp://*.