#630

allow to have deny/allow list of domains to ensure a deny-all policy

Openbenoitfopened 7mo ago

Problem

When running a container or VM, I want to be in full control of what domains and IPs can be reached. Specifically, I want an opt-in mode where, by default, there is no access to the outside world — only explicitly approved destinations are reachable.

Firewall rules defined inside the VM/container are not sufficient: if the user has sudo access (which is common), they can disable those rules and reach the internet anyway.

Why gvproxy is the right place for this

With podman machine, macadam, and other tools relying on gvproxy, all network traffic from the VM is routed through gvproxy on the host. This is a unique enforcement point:

  • Filtering happens on the host side, outside the VM — it cannot be bypassed from within the guest, even with root access
  • If gvproxy never forwards a packet to the internet, nothing inside the VM can reach it, period
  • There is some overhead compared to passthrough networking, but the trade-off is guaranteed control over outbound traffic

What I'd like

Static allow/deny policies

Define rules for what traffic is permitted, at two levels:

  • DNS-level: control which domains can be resolved (e.g. allow *.github.com, block everything else). This is the most natural way to express intent — users think in domains, not IPs.
  • IP/port-level: control which IP ranges and ports can be reached (e.g. allow TCP 80/443 to 0.0.0.0/0, deny all access to 10.0.0.0/8). This catches traffic that bypasses DNS or uses hardcoded IPs.

When a domain is approved via DNS, the resolved IPs should be automatically allowed at the network level — users shouldn't have to approve the same destination twice.

Interactive mode

While static deny/allow lists are useful, I'd also like an interactive mode where I can be notified in real-time and decide on the fly:

  • When a connection or DNS query is denied, hold it pending rather than silently dropping it
  • Notify me (via a socket, event stream, etc.) that something is waiting for approval
  • Let me approve or deny through an API, so I can build or use tools (CLI, TUI, desktop notification, web dashboard) to manage it
  • Cache my decisions so subsequent requests to the same destination don't block again
  • Auto-deny after a configurable timeout if I don't respond

This interactive mode is valuable for:

  • Discovery: run your workload and see exactly what it tries to reach, then build a static policy from the results
  • One-off approvals: allow a specific download without opening up the policy permanently

A simple "secure mode" shortcut

For the common case of "deny everything, ask me for each new destination", a single flag (e.g. --secure-mode) should set up deny-all with interactive approval for both DNS and network traffic — no config file needed.

Activity

8
cfergeau7mo ago

Regarding the interactive mode, my initial feeling was that we should be able to do with just notifications that the connection is pending, and instead of approving, we just allowlist the DNS/IP using the regular API. The problem is that this means we don’t have a clear way to deny the request. Unless we decide that adding the DNS/IP to the denylist means the connection request was rejected?

cfergeau7mo ago

Regarding the interactive mode, my initial feeling was that we should be able to do with just notifications that the connection is pending, and instead of approving, we just allowlist the DNS/IP using the regular API. The problem is that this means we don’t have a clear way to deny the request. Unless we decide that adding the DNS/IP to the denylist means the connection request was rejected?

benoitf7mo ago

at first I tried to do it as a separate task, but claude was encouraging me to hold the request and then I could approve the request and the request can continue (if timeout was enough) vs having the connection automatically denied and then I had to retry the connection

I played with both options and found it was a nicer experience when it was holding the response for a while (but I really think it depends on the use-case)

if you're sure to have interactive mode you want to hold and probably without the interactive mode you only want that it denies as soon as possible the request

Like authoring mode vs production mode.

benoitf7mo ago

at first I tried to do it as a separate task, but claude was encouraging me to hold the request and then I could approve the request and the request can continue (if timeout was enough) vs having the connection automatically denied and then I had to retry the connection

I played with both options and found it was a nicer experience when it was holding the response for a while (but I really think it depends on the use-case)

if you're sure to have interactive mode you want to hold and probably without the interactive mode you only want that it denies as soon as possible the request

Like authoring mode vs production mode.

cfergeau7mo ago

I’m not saying we don’t need interactive mode, just thinking out loud about the API. At the API level, do we want (very schematically)

gvproxy: notification: request to connect to redhat.com approve Y/N
application: approve
-> request goes through

or

gvproxy: notification: request to connect to redhat.com, holding it for 30s
application: whitelist accesses to redhat.com
-> request goes through

Both should be roughly equivalent, the latter might allow us to have the same api for interactive/non interactive.

But that’s really just some thoughts, needs to look at the PRs first.

cfergeau7mo ago

I’m not saying we don’t need interactive mode, just thinking out loud about the API. At the API level, do we want (very schematically)

gvproxy: notification: request to connect to redhat.com approve Y/N
application: approve
-> request goes through

or

gvproxy: notification: request to connect to redhat.com, holding it for 30s
application: whitelist accesses to redhat.com
-> request goes through

Both should be roughly equivalent, the latter might allow us to have the same api for interactive/non interactive.

But that’s really just some thoughts, needs to look at the PRs first.

benoitf7mo ago

latter is ok but there might still need a flag to say 'fail fast' where it's never holding if it's not approved

benoitf7mo ago

latter is ok but there might still need a flag to say 'fail fast' where it's never holding if it's not approved