Summary
POC for outbound network and DNS filtering in gvisor-tap-vsock, built entirely via vibe coding with Claude Code AI.
https://github.com/user-attachments/assets/00101988-0458-4ce4-a412-b21d36f20a8e
related to https://github.com/containers/gvisor-tap-vsock/issues/630
What was done
- Network filtering (
pkg/services/forwarder/filter.go): ACL-based filtering for outbound TCP/UDP connections with CIDR, port, and protocol matching. First-match-wins rule evaluation. - DNS filtering (
pkg/services/dns/filter.go): Domain-level filtering with allow/block lists and wildcard support (*.example.com). Denied domains are tracked. - Interactive approval mode (
--secure-mode): When enabled, all outbound traffic is denied by default. Blocked connections are held pending (up to 30s timeout) while waiting for user approval via the HTTP API. Approved DNS domains automatically whitelist the resolved IPs for TCP/UDP. - SSE real-time events: The
/network/eventsendpoint streams connection events (pending, approved, denied) and DNS events to subscribers. - Svelte approval UI (
approval/): A web frontend that connects to the SSE stream and lets users approve/deny pending connections and DNS queries in real-time. - Configuration model (
pkg/types/configuration.go):NetworkPolicyandDNSPolicytypes supporting YAML config files or the--secure-mode/--network-policyCLI flags.
Architecture
VM → gvisor-tap-vsock → DNS Filter → upstream DNS → Network Filter (TCP/UDP) → internet ↕ HTTP API + SSE ← Approval UI (Svelte)
How to quickly test
1. Secure mode (deny-all + interactive approval)
# Build gvproxy
make
# Run with secure mode + services endpoint
./bin/gvproxy --listen unix:///tmp/gvproxy.sock \
--listen-vfkit unixgram:///tmp/vfkit.sock \
--secure-mode \
--services "unix:///tmp/gvproxy-services.sock"
All outbound connections from the VM will be blocked and held pending for 30 seconds.
2. Policy file mode (static ACL rules)
Create a policy.yaml:
defaultAction: deny
rules:
- action: allow
cidr: "0.0.0.0/0"
ports: [443, 80]
protocol: tcp
- action: deny
cidr: "10.0.0.0/8"
dns:
defaultAction: deny
allowedDomains:
- "*.github.com"
- "*.googleapis.com"
- "registry.fedoraproject.org"
blockedDomains:
- "*.malware.example"
./bin/gvproxy --listen unix:///tmp/gvproxy.sock \
--listen-vfkit unixgram:///tmp/vfkit.sock \
--network-policy policy.yaml \
--services "unix:///tmp/gvproxy-services.sock"
3. Query the HTTP API
# List pending/denied connections
curl --unix-socket /tmp/gvproxy-services.sock http://localhost/network/pending
# List denied DNS queries
curl --unix-socket /tmp/gvproxy-services.sock http://localhost/dns/denied
# Approve a connection (interactive mode)
curl --unix-socket /tmp/gvproxy-services.sock -X POST http://localhost/network/allow \
-d '{"protocol":"tcp","ip":"142.250.80.46","port":443}'
# Allow a DNS domain dynamically
curl --unix-socket /tmp/gvproxy-services.sock -X POST http://localhost/dns/allow \
-d '{"domain":"example.com"}'
# Stream events (SSE)
curl --unix-socket /tmp/gvproxy-services.sock http://localhost/network/events
4. Run the approval UI
cd approval
npm install
npm run dev
The Svelte UI connects to the SSE event stream and shows pending connections/DNS queries with approve/deny buttons.
5. Run unit tests
go test ./pkg/services/forwarder/ -run TestFilter -v
go test ./pkg/services/dns/ -run TestFilter -v
Limitations (POC)
- No persistence — approved rules are lost on restart
- No authentication on the HTTP API
- The approval UI assumes the services socket is reachable (needs proxy for unix sockets)
- Interactive approval timeout is fixed at 30s (configurable via approvalTimeout in policy YAML)Activity
10[APPROVALNOTIFIER] This PR is NOT APPROVED
This pull-request has been approved by: benoitf Once this PR has been reviewed and has the lgtm label, please assign evidolob for approval. For more information see the Code Review Process.
The full list of commands accepted by this bot can be found here.
Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment
Fwiw, I’m not sure about adding the svelte UI to the gvisor-tap-vsock repo, but that’s not central to this feature
Fwiw, I’m not sure about adding the svelte UI to the gvisor-tap-vsock repo, but that’s not central to this feature
sure, I don't think it should be there, I only provided it as a convenient way rather than using curl/rest commands
sure, I don't think it should be there, I only provided it as a convenient way rather than using curl/rest commands
https://github.com/containers/gvisor-tap-vsock/pull/609 attempts to solve a very similar usecase, though I don’t think it has the "request" feature.
https://github.com/containers/gvisor-tap-vsock/pull/609 attempts to solve a very similar usecase, though I don’t think it has the "request" feature.
PR needs rebase.
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.
This pull request is a draft
Merging is unavailable until it is marked ready for review.
[APPROVALNOTIFIER] This PR is NOT APPROVED
This pull-request has been approved by: benoitf Once this PR has been reviewed and has the lgtm label, please assign evidolob for approval. For more information see the Code Review Process.
The full list of commands accepted by this bot can be found here.
Approvers can indicate their approval by writing
/approvein a comment Approvers can cancel approval by writing/approve cancelin a comment