Network Architecture & Firewall Configuration
This guide covers how to deploy TapPass in enterprise networks with firewalls, proxies, TLS inspection, and restricted egress.
Deployment Model
Section titled “Deployment Model”TapPass runs inside your corporate network as an internal service. It is not a SaaS. no inbound connections from the internet are required for the data plane.
┌──────────────────────────────────────────────────────────────────┐│ CORPORATE NETWORK ││ ││ ┌──────────┐ ┌──────────────┐ ┌────────────────────┐ ││ │ AI Agent │───▶│ TapPass │───▶│ Corporate Egress │─────┼──▶ LLM Providers│ │ │ │ (internal) │ │ Proxy (Zscaler / │ │ (api.openai.com,│ └──────────┘ │ │ │ Palo Alto / etc.) │ │ api.anthropic.com)│ ▲ └──────┬───────┘ └────────────────────┘ ││ │ │ ││ │ ┌──────┴───────┐ ││ │ │ OPA sidecar │ ││ │ └──────────────┘ ││ │ ││ Internal only. No inbound from internet. ││ Dashboard accessible via Cloudflare Tunnel or VPN. │└──────────────────────────────────────────────────────────────────┘Traffic Flows
Section titled “Traffic Flows”| # | Source | Destination | Port | Protocol | Direction | Purpose |
|---|---|---|---|---|---|---|
| 1 | AI Agent | TapPass | 9620/tcp | HTTPS (mTLS) | Internal | Governed LLM calls |
| 2 | TapPass | OPA | 8181/tcp | HTTP | localhost / sidecar | Policy decisions |
| 3 | TapPass | PostgreSQL | 5432/tcp | TCP+TLS | Internal | Audit trail, state |
| 4 | TapPass | Redis | 6379/tcp | TCP | localhost / sidecar | Rate limits, sessions |
| 5 | TapPass | LLM Provider | 443/tcp | HTTPS | Outbound (egress) | OpenAI, Anthropic, etc. |
| 6 | TapPass | SPIRE Server | 8081/tcp | gRPC+mTLS | Internal | Certificate issuance |
| 7 | SPIRE Agent | SPIRE Server | 8081/tcp | gRPC+mTLS | Internal | Attestation |
| 8 | Browser | TapPass | 443/tcp | HTTPS | Inbound (dashboard) | Admin UI (optional) |
Firewall Rules
Section titled “Firewall Rules”Minimal Rules (Internal Only: No Dashboard Exposure)
Section titled “Minimal Rules (Internal Only: No Dashboard Exposure)”Only outbound HTTPS to LLM providers is required. Everything else is internal.
# ── Inbound: NONE required ──────────────────────────────────────# TapPass is internal-only. Agents connect within the corporate network.
# ── Internal (agent → TapPass) ──────────────────────────────────ALLOW tcp/9620 FROM agent-subnet TO tappass-subnet # Governed calls
# ── Internal (TapPass → infrastructure) ─────────────────────────ALLOW tcp/5432 FROM tappass-subnet TO db-subnet # PostgreSQLALLOW tcp/6379 FROM tappass-subnet TO redis-subnet # Redis (if external)ALLOW tcp/8081 FROM tappass-subnet TO spire-subnet # SPIRE Server
# ── Outbound (TapPass → LLM providers via egress proxy) ─────────ALLOW tcp/443 FROM tappass-subnet TO proxy-subnet # Corporate proxy# OR direct egress (if no proxy):ALLOW tcp/443 FROM tappass-subnet TO 0.0.0.0/0 # LLM providersFirewall Rule Template (CSV. Palo Alto / Fortinet Import)
Section titled “Firewall Rule Template (CSV. Palo Alto / Fortinet Import)”Save as tappass-firewall-rules.csv and import into your firewall management console:
name,source_zone,source_address,destination_zone,destination_address,destination_port,protocol,action,descriptiontappass-agent-inbound,trust,agent-subnet,trust,tappass-subnet,9620,tcp,allow,AI agents to TapPass governancetappass-to-postgres,trust,tappass-subnet,trust,db-subnet,5432,tcp,allow,TapPass to PostgreSQLtappass-to-redis,trust,tappass-subnet,trust,redis-subnet,6379,tcp,allow,TapPass to Redistappass-to-spire,trust,tappass-subnet,trust,spire-subnet,8081,tcp,allow,TapPass to SPIRE Servertappass-llm-egress,trust,tappass-subnet,untrust,any,443,tcp,allow,TapPass to LLM providers (HTTPS)DNS Allowlist (for DNS-filtering proxies)
Section titled “DNS Allowlist (for DNS-filtering proxies)”If your proxy filters by domain, allowlist these endpoints:
# LLM Providers (enable only the ones you use)api.openai.comapi.anthropic.comgenerativelanguage.googleapis.comapi.mistral.aiapi.deepseek.comapi.groq.com
# TapPass infrastructure (if using managed services)*.supabase.co # Managed PostgreSQL (if Supabase backend)
# SPIFFE/SPIRE (internal only. should not need external access)# No external DNS entries requiredProxy Configuration
Section titled “Proxy Configuration”TapPass Server → LLM Providers (Outbound Proxy)
Section titled “TapPass Server → LLM Providers (Outbound Proxy)”If your corporate network routes outbound HTTPS through a proxy, configure TapPass:
# In .env.prod or docker-compose environment:HTTP_PROXY=http://proxy.corp.internal:8080HTTPS_PROXY=http://proxy.corp.internal:8080NO_PROXY=localhost,127.0.0.1,opa,redis,postgres,spire-server,.internal
# TapPass-specific (takes precedence over HTTP_PROXY for LLM calls):TAPPASS_PROXY_URL=http://proxy.corp.internal:8080TapPass uses httpx internally, which respects standard HTTP_PROXY / HTTPS_PROXY environment variables. The NO_PROXY setting is critical. internal sidecar traffic (OPA, Redis) must not go through the proxy.
SDK (Agent → TapPass) Through Proxy
Section titled “SDK (Agent → TapPass) Through Proxy”If agents run in a different network segment and need to reach TapPass through a proxy:
from tappass import Agentimport os
# Standard proxy env vars. httpx respects these automaticallyos.environ["HTTPS_PROXY"] = "http://proxy.corp.internal:8080"os.environ["NO_PROXY"] = "localhost,127.0.0.1"
agent = Agent("https://tappass.internal:9620")Or in the shell:
export HTTPS_PROXY=http://proxy.corp.internal:8080export NO_PROXY=localhost,127.0.0.1python my_agent.pyTLS Inspection Compatibility
Section titled “TLS Inspection Compatibility”The Problem
Section titled “The Problem”Many enterprises run TLS-inspecting proxies (Zscaler, Palo Alto, Fortinet) that perform man-in-the-middle (MITM) decryption of all HTTPS traffic. This breaks mTLS because the proxy replaces the client certificate.
Decision Tree
Section titled “Decision Tree”Does your network have a TLS-inspecting proxy? │ ├─ NO → Standard deployment. mTLS works. Done. │ └─ YES → Does it inspect ALL traffic, or can you exempt by SNI/IP? │ ├─ Can exempt → Add a TLS bypass rule for TapPass traffic. │ See "Bypass Rule" below. │ └─ Cannot exempt → Use Cloudflare Tunnel for the dashboard. Deploy TapPass in the same network segment as agents (no proxy between them). Use API key auth instead of mTLS for cross-segment agent traffic.TLS Bypass Rule (Proxy Exception)
Section titled “TLS Bypass Rule (Proxy Exception)”Add a TLS inspection bypass for agent-to-TapPass traffic:
Zscaler:
SSL Inspection Policy → Add Exception: Destination: tappass.internal (or IP range of TapPass subnet) Action: Bypass SSL Inspection Reason: mTLS required for agent governancePalo Alto:
Decryption Policy → Add No-Decrypt Rule: Source Zone: trust Destination: tappass-subnet Service: tcp/9620 Action: No DecryptFortinet:
SSL/SSH Inspection → Exemptions: Address: tappass-subnet Exempt from SSL Inspection: YesIf You Cannot Bypass TLS Inspection
Section titled “If You Cannot Bypass TLS Inspection”If your security policy does not allow TLS bypass for any traffic:
- Deploy TapPass in the same subnet as agents. no proxy needed for internal traffic.
- Use API key authentication instead of mTLS for agent identity. Set
TAPPASS_ADMIN_API_KEYand usetp_prefixed keys. - The proxy only applies to outbound TapPass → LLM provider traffic, which is standard HTTPS and works through TLS inspection.
Cloudflare Tunnel (Dashboard Access)
Section titled “Cloudflare Tunnel (Dashboard Access)”The production Docker Compose includes a Cloudflare Tunnel for exposing the dashboard without opening inbound firewall ports.
# In deploy/docker-compose.prod.ymltunnel: image: cloudflare/cloudflared:latest command: tunnel --protocol http2 run environment: - TUNNEL_TOKEN=${TUNNEL_TOKEN}Important: The Cloudflare Tunnel is for the dashboard/admin UI only. Agent traffic should stay internal and never traverse the tunnel. This separation is critical:
| Traffic | Path | Why |
|---|---|---|
| Agent → TapPass | Internal network (direct) | Low latency, no internet dependency |
| Admin → Dashboard | Cloudflare Tunnel | Zero inbound firewall rules, Zero Trust access |
| TapPass → LLM | Outbound HTTPS (via proxy) | Standard egress, auditable |
SPIRE / SPIFFE Network Requirements
Section titled “SPIRE / SPIFFE Network Requirements”SPIRE uses gRPC for all communication. Required flows:
| Source | Destination | Port | Protocol | Purpose |
|---|---|---|---|---|
| SPIRE Agent | SPIRE Server | 8081/tcp | gRPC + mTLS | Attestation, SVID issuance |
| TapPass | SPIRE Agent | Unix socket | Local | Workload API (cert retrieval) |
| spiffe-helper | SPIRE Agent | Unix socket | Local | Cert rotation signaling |
Key point: The SPIRE Agent runs as a sidecar or DaemonSet on the same node. Communication between TapPass and SPIRE Agent uses a Unix domain socket (/tmp/spire-agent/public/api.sock), not a network connection. No firewall rule is needed for this path.
SPIRE Server ↔ Agent communication (port 8081) is the only network flow. This is internal and uses mutual TLS with its own trust bundle.
Kubernetes Network Policies
Section titled “Kubernetes Network Policies”The Helm chart includes a NetworkPolicy resource (networkPolicy.enabled: true in values.yaml):
networkPolicy: enabled: true egressAllowCIDRs: - 10.0.0.0/8 # Internal services (DB, Redis, SPIRE) # Add LLM provider IPs or use proxy CIDR: - 192.168.1.0/24 # Corporate proxyFor strict egress control, use your cloud provider’s IP ranges for LLM providers:
# Example: OpenAI uses Cloudflare, so you need Cloudflare IP ranges# Alternatively, route through your corporate proxy (recommended)networkPolicy: enabled: true egressAllowCIDRs: - 10.0.0.0/8 # Internal - 172.16.0.0/12 # Internal - 192.168.0.0/16 # Internal # Proxy egress only: - 10.100.1.50/32 # Corporate proxy IPStreaming / Long-Lived Connections
Section titled “Streaming / Long-Lived Connections”TapPass supports SSE (Server-Sent Events) for streaming LLM responses. Some corporate proxies and load balancers kill connections that are idle or long-lived.
Proxy Timeout Requirements
Section titled “Proxy Timeout Requirements”| Component | Minimum Timeout | Reason |
|---|---|---|
| Load balancer → TapPass | 120s | LLM responses can take 60s+ for complex queries |
| Proxy (agent → TapPass) | 120s | Same: streaming SSE connections |
| TapPass → LLM provider | 120s | Provider-side timeout (configured in TapPass) |
Configuration Examples
Section titled “Configuration Examples”NGINX Ingress:
nginx.ingress.kubernetes.io/proxy-read-timeout: "120"nginx.ingress.kubernetes.io/proxy-send-timeout: "120"nginx.ingress.kubernetes.io/proxy-buffering: "off" # Required for SSEAWS ALB:
idle_timeout.timeout_seconds = 120Cloudflare Tunnel: Cloudflare Tunnel natively supports long-lived connections. No special configuration needed.
Air-Gapped / Disconnected Networks
Section titled “Air-Gapped / Disconnected Networks”For environments without internet access:
-
Container images: Export as tarballs and import into your private registry.
Terminal window docker save ghcr.io/cogniqor/tappass:0.2.0 -o tappass.tardocker save openpolicyagent/opa:0.71.0-static -o opa.tardocker save redis:7-alpine -o redis.tardocker save postgres:16-alpine -o postgres.tar# Transfer tarballs to air-gapped network, then:docker load -i tappass.tar -
LLM provider: Use a locally-hosted model (Ollama, vLLM) instead of cloud APIs.
Terminal window TAPPASS_LLM_JUDGE_MODEL=ollama/llama3.1TAPPASS_OLLAMA_API_BASE=http://ollama.internal:11434 -
Presidio NLP models: Pre-packaged in the Docker image. No runtime download needed.
-
OPA policies: Bundled in the ConfigMap. No external bundle server needed.
Troubleshooting
Section titled “Troubleshooting””Connection refused” from agent to TapPass
Section titled “”Connection refused” from agent to TapPass”# From the agent's host/pod:curl -v http://tappass:9620/health# Expected: {"status": "healthy", ...}
# If using mTLS:curl -v --cert /run/spire/certs/svid.pem \ --key /run/spire/certs/svid_key.pem \ --cacert /run/spire/certs/bundle.pem \ https://tappass:9620/healthTLS inspection breaking mTLS
Section titled “TLS inspection breaking mTLS”Symptom: ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED]
This means a TLS-inspecting proxy is replacing the TapPass certificate. See TLS Inspection Compatibility above.
Proxy blocking LLM calls
Section titled “Proxy blocking LLM calls”# From the TapPass pod:curl -v --proxy $HTTPS_PROXY https://api.openai.com/v1/models# Should return a JSON response (even if 401: that means connectivity works)SPIRE Agent not connecting to Server
Section titled “SPIRE Agent not connecting to Server”# Check SPIRE Agent health:docker compose exec spire-agent /opt/spire/bin/spire-agent healthcheck# Check logs:docker compose logs spire-agentSDK resilience in degraded mode
Section titled “SDK resilience in degraded mode”agent = Agent("http://tappass:9620")print(agent.resilience_status)# Returns circuit breaker state, cache size, buffered audit entries