Skip to content

FR: Support outbound HTTP/SOCKS5 proxy for server-side egress #363

Description

@YewFence

Use case

I run Agent Vault on my own development machine to avoid the latency of a remote deployment. However, my network environment cannot reach several target services directly — GitHub, for example, is unreachable without going through a local proxy. In this situation the Agent Vault server itself cannot dial any upstream, so the broker is unusable even though the client side (vault run) works fine.

I imagine this also applies to corporate networks that mandate an egress proxy.

Current behavior

Server-side outbound connections are always direct dials, with no way to configure an upstream proxy:

  • The MITM proxy's upstream transport (internal/mitm/proxy.go) builds an http.Transport with DialContext: netguard.SafeDialContext(...) and no Proxy field, so HTTPS_PROXY-style env vars are ignored entirely.
  • The OAuth token client (internal/server/server.go) goes further and explicitly sets oauthTransport.Proxy = nil.
  • No env var or CLI flag exists to change this (checked .env.example and the env-var reference docs).

I understand this is deliberate: netguard resolves hostnames locally, validates the IPs against the SSRF blocklist, and dials the validated IP to prevent DNS rebinding. Forwarding to an upstream proxy re-delegates resolution to the proxy and weakens that guarantee.

Workarounds I've considered

None of these are great for my situation, which is why I'm opening this issue:

  • Host-level transparent proxy (iptables/nftables REDIRECT of outbound traffic): too complex to set up and maintain just for one application, and invisible to Agent Vault when debugging.
  • Docker Compose sidecar doing transparent proxying (e.g. a sidecar container with its own iptables rules forcing egress through my proxy): avoids touching host network config, and Agent Vault already has a Docker deployment story, but it's still a fair amount of moving parts for a single-user dev setup.
  • Running the server on a remote host with good connectivity: what I'm trying to avoid due to latency.

Proposal

Add an opt-in upstream proxy for server egress, e.g. AGENT_VAULT_UPSTREAM_PROXY=http://127.0.0.1:7890 (supporting http:///https:// via CONNECT and ideally socks5:// via golang.org/x/net/proxy), with NO_PROXY-style bypass for internal targets.

On the SSRF trade-off, one possible framing is an explicit, operator-configured "unsafe" mode — there's precedent in the codebase with AGENT_VAULT_ALLOW_PRIVATE_RANGES=true, which weakens the same protection when the operator knows their deployment calls for it. Concretely:

  • Off by default; the default security posture is unchanged.
  • When set, netguard validates the proxy address instead of the final target.
  • A prominent warning is logged at startup, e.g. upstream proxy configured: target SSRF validation delegated to proxy.
  • Optionally keep local checks for literal-IP targets (including 169.254.169.254, which is how IMDS is reached in practice), so the most dangerous SSRF target stays blocked even in this mode.

That said, I fully understand if the maintainers feel any weakening of netguard isn't a good fit for the project — in that case feel free to close this and I'll make do with one of the workarounds above. If the direction is acceptable, I'm happy to attempt a PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions