nono-proxy 0.6.1

Network filtering proxy for the nono sandbox
Documentation

nono-proxy

Network filtering proxy for the nono sandbox.

Overview

nono-proxy provides host-level network filtering and credential injection for sandboxed processes. It runs unsandboxed in the supervisor process while the child is restricted to connecting only to the proxy's localhost port via NetworkMode::ProxyOnly.

Proxy Modes

Mode Module Description
CONNECT tunnel connect Host-filtered HTTPS tunnelling. Validates the target host against an allowlist and CIDR deny ranges, then establishes a raw TCP tunnel. TLS is end-to-end.
Reverse proxy reverse Credential injection for API calls. Requests to http://127.0.0.1:<port>/<service>/... are forwarded upstream with the real API key injected as an HTTP header.
External proxy external Enterprise proxy passthrough. CONNECT requests are chained through a corporate proxy with the default deny list enforced as a floor.

Security Properties

  • Default deny list is hardcoded -- Cloud metadata endpoints (169.254.169.254), RFC1918 private networks, link-local, and loopback ranges are always blocked regardless of allowlist configuration.
  • DNS rebinding protection -- The proxy resolves DNS and checks all resolved IPs against deny CIDRs before connecting. Callers connect to resolved addresses, not re-resolved hostnames.
  • Session token authentication -- Each session generates a 256-bit random token. CONNECT requests use Proxy-Authorization (Basic or Bearer); reverse proxy requests use X-Nono-Token.
  • Credential isolation -- API keys are loaded from the OS keyring, stored in Zeroizing<String>, injected at the HTTP header level, and never exposed to the sandboxed process.
  • Constant-time token comparison -- Prevents timing side-channel attacks on session token validation.

Usage

use nono_proxy::{ProxyConfig, start, ProxyHandle};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = ProxyConfig {
        allowed_hosts: vec![
            "api.openai.com".into(),
            "api.anthropic.com".into(),
        ],
        ..Default::default()
    };

    let handle: ProxyHandle = start(config).await?;

    // Set these in the child process environment
    let env_vars = handle.env_vars();
    // HTTP_PROXY, HTTPS_PROXY, NONO_PROXY_TOKEN, etc.

    // Shutdown when done
    handle.shutdown();
    Ok(())
}

Module Structure

Module Purpose
server TCP listener, connection dispatch, lifecycle
filter Async host filtering with DNS resolution
connect CONNECT tunnel handler
reverse Reverse proxy with credential injection
external External proxy passthrough
credential Keyring-backed credential store
token Session token generation and validation
config Configuration types
audit Connection audit logging
error Error types

License

Apache-2.0