Skip to content

net: add --net-deny for default-allow egress with IP/CIDR/port denial#89

Open
congwang-mk wants to merge 13 commits into
mainfrom
net-deny
Open

net: add --net-deny for default-allow egress with IP/CIDR/port denial#89
congwang-mk wants to merge 13 commits into
mainfrom
net-deny

Conversation

@congwang-mk
Copy link
Copy Markdown
Contributor

Summary

Adds an L4 --net-deny option: allow all networking by default, block specific IPs, CIDR ranges, and ports. Addresses #75 (allow all internet, block certain destinations).

  • --net-deny <ip|cidr|:port|target:port|[ipv6]:port> plus a curated private token that expands to the full IPv4+IPv6 internal set (loopback, RFC1918, link-local incl. the 169.254.169.254 metadata endpoint, IPv6 ULA + link-local).
  • Mutually exclusive with --net-allow (clean error; forward-compatible: can later relax into deny-wins precedence).
  • Comma-delimited list support (--net-deny 127.0.0.1,10.0.0.0/8,...), matching the Deno --deny-net ergonomics the requester referenced.
  • TOML profile support via [network].deny, with --profile-file round-trip.
  • Rejected under --no-supervisor (network filtering needs the supervisor).

Design notes

  • Hostnames are rejected on the deny side. A startup-resolved hostname denylist fails open (the sandbox reaches other IPs for that name). IP/CIDR/port denial is enforced on the connect-time destination IP, so it is robust and DNS-rebinding-safe. Domain blocking stays at --http-deny (already exists, robust at the proxy).
  • Enforcement spans three layers: Landlock drops CONNECT_TCP from its handled set under --net-deny (default-allow), the seccomp on-behalf path becomes the sole filter via a new NetworkPolicy::DenyList, and SOCK_DGRAM is permitted so DNS-over-UDP still works.

Test plan

  • cargo test -p sandlock-core --lib (345 pass) and cargo test -p sandlock-cli (28 pass), zero warnings.
  • Unit coverage: IpCidr v4/v6 prefix match, parser (CIDR / bare-all-ports / private / hostname rejection / bracketed IPv6 / empty-icmp), DenyList.allows, resolve_net_deny, builder + exclusivity, notif_syscalls traps connect under deny, profile parse, --no-supervisor rejection, CLI exclusivity.
  • Live loopback matrix on a Landlock host: denied IP/CIDR/port -> ECONNREFUSED; non-denied destinations connect; --net-deny private blocks the metadata endpoint; default-allow lets unrelated traffic through.

🤖 Generated with Claude Code

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>
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>
Signed-off-by: Cong Wang <cwang@multikernel.io>
…ehalf, allow UDP)

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