proxy/

directory
v0.0.1-alpha83 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 12, 2026 License: Apache-2.0

README

Discobot Proxy

A multi-protocol proxy server with HTTP interception, header injection, and dynamic configuration.

Overview

The proxy provides:

  • HTTP/HTTPS proxy with MITM for traffic inspection, header injection, and WebSocket upgrades
  • HTTP recording for request/response handshakes plus binary upgraded-stream capture for WebSockets and other 101 Switching Protocols flows
  • SOCKS5 proxy for non-HTTP TCP tunneling
  • Protocol auto-detection on a single port
  • Domain-based header injection rules
  • Dynamic configuration via file watching and REST API
  • Request logging for all proxied traffic
  • Response caching with LRU eviction (perfect for Docker registry pulls)

Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                         Proxy Server                                 │
│                                                                      │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │                   Protocol Detector                             │ │
│  │              (first-byte sniffing on :17080)                     │ │
│  └────────────────────────────────────────────────────────────────┘ │
│                    │                          │                      │
│           HTTP (GET/POST/...)           SOCKS5 (0x05)               │
│                    │                          │                      │
│                    ▼                          ▼                      │
│  ┌─────────────────────────┐    ┌─────────────────────────────────┐ │
│  │     HTTP Proxy          │    │        SOCKS5 Proxy             │ │
│  │     (goproxy)           │    │     (things-go/go-socks5)       │ │
│  │                         │    │                                 │ │
│  │  ┌───────────────────┐  │    │  ┌───────────────────────────┐  │ │
│  │  │   MITM Handler    │  │    │  │   Rule-based Filtering    │  │ │
│  │  │  (TLS intercept)  │  │    │  │   (DNS/IP allowlist)      │  │ │
│  │  └───────────────────┘  │    │  └───────────────────────────┘  │ │
│  │           │             │    │               │                 │ │
│  │           ▼             │    │               ▼                 │ │
│  │  ┌───────────────────┐  │    │  ┌───────────────────────────┐  │ │
│  │  │  Header Injector  │  │    │  │   Connection Tunneling    │  │ │
│  │  │  (per-domain)     │  │    │  │   (TCP passthrough)       │  │ │
│  │  └───────────────────┘  │    │  └───────────────────────────┘  │ │
│  └─────────────────────────┘    └─────────────────────────────────┘ │
│                    │                          │                      │
│                    └──────────┬───────────────┘                      │
│                               ▼                                      │
│                    ┌───────────────────┐                            │
│                    │   Request Logger  │                            │
│                    └───────────────────┘                            │
└─────────────────────────────────────────────────────────────────────┘
                               │
         ┌─────────────────────┼─────────────────────┐
         ▼                     ▼                     ▼
┌─────────────────┐  ┌─────────────────┐  ┌─────────────────┐
│  Config Watcher │  │   REST API      │  │  Certificate    │
│  (YAML file)    │  │   (POST only)   │  │  Manager        │
└─────────────────┘  └─────────────────┘  └─────────────────┘

Documentation

Getting Started

Prerequisites
  • Go 1.23+
Development
# Run with auto-reload
cd proxy
air

# Or run directly
go run cmd/proxy/main.go

# Run tests
go test ./...

# Run linter
golangci-lint run
Recording

When recording.enabled is on, the proxy writes:

  • HTTP request/response handshakes to requests-YYYY-MM-DD.jsonl
  • upgraded bidirectional traffic (for example WebSockets after a 101 Switching Protocols response) to streams/stream-<session-id>.bin

The binary stream files use a compact framed format so each chunk keeps its direction (client -> server or server -> client) and observed ordering. Stream writes are queued to a background writer so recording does not block proxied traffic; if the recorder falls behind, chunks are dropped from the log rather than stalling the connection.

Environment Variables
Variable Default Description
PROXY_PORT 17080 Main proxy port (HTTP + SOCKS5)
API_PORT 17081 REST API port
CONFIG_FILE config.yaml Path to configuration file
CERT_DIR ./certs Directory for CA certificate
LOG_LEVEL info Log level (debug, info, warn, error)
LOG_FORMAT text Log format (text, json)
Building
go build -o discobot-proxy ./cmd/proxy
Configuration File
# config.yaml
proxy:
  port: 17080
  api_port: 17081

# DNS/IP allowlist (empty = allow all)
allowlist:
  domains:
    - "*.github.com"
    - "api.anthropic.com"
    - "*.openai.com"
  ips:
    - "192.168.1.0/24"

# Header injection rules (domain -> header rules)
# Each rule has "set" (replace) and/or "append" sections
# Optional "conditions" restrict when headers are applied
headers:
  "api.anthropic.com":
    set:
      "X-Custom-Header": "value1"
  "*.openai.com":
    # Conditions: ALL must be true for headers to apply
    conditions:
      - header: "X-Environment"
        equals: "production"
    set:
      "X-Request-Source": "discobot-proxy"
    append:
      "X-Forwarded-For": "proxy.internal"

# Response caching (perfect for Docker registry pulls)
cache:
  enabled: true
  dir: ./cache
  max_size: 21474836480  # 20GB in bytes
  patterns:
    # Default patterns for Docker registry (if not specified):
    - "^/v2/.*/blobs/sha256:.*"      # Docker blob layers
    - "^/v2/.*/manifests/sha256:.*"  # Docker manifests by digest
    # Custom patterns can be added:
    # - "^/npm/@.*/-/.*\\.tgz$"       # npm packages

logging:
  level: info
  format: text
  file: ""  # Empty = stdout

API Endpoints

Method Path Description
POST /api/config Overwrite entire running config
PATCH /api/config Merge partial config into running config
GET /api/cache/stats Get cache statistics
DELETE /api/cache Clear all cached content
GET /health Health check
POST /api/config - Overwrite

Completely replaces the running configuration:

curl -X POST http://localhost:17081/api/config \
  -H "Content-Type: application/json" \
  -d '{
    "allowlist": {
      "enabled": true,
      "domains": ["*.github.com", "api.anthropic.com"],
      "ips": ["10.0.0.0/8"]
    },
    "headers": {
      "api.anthropic.com": {
        "set": {"Authorization": "Bearer sk-ant-xxx"}
      },
      "*.github.com": {
        "conditions": [
          {"header": "X-Auth-Type", "equals": "enterprise"}
        ],
        "set": {"Authorization": "token ghp_xxx"},
        "append": {"X-Forwarded-For": "proxy.internal"}
      }
    }
  }'
PATCH /api/config - Merge

Merges into existing config. Set a domain to null to delete:

# Add headers for a new domain (existing domains unchanged)
curl -X PATCH http://localhost:17081/api/config \
  -d '{"headers": {"api.openai.com": {"set": {"Authorization": "Bearer sk-xxx"}}}}'

# Add conditional headers (applied only when X-Environment equals "prod")
curl -X PATCH http://localhost:17081/api/config \
  -d '{"headers": {"api.example.com": {"conditions": [{"header": "X-Environment", "equals": "prod"}], "set": {"Authorization": "Bearer prod-token"}}}}'

# Add append-style headers
curl -X PATCH http://localhost:17081/api/config \
  -d '{"headers": {"*": {"append": {"Via": "1.1 discobot-proxy"}}}}'

# Delete a domain's headers
curl -X PATCH http://localhost:17081/api/config \
  -d '{"headers": {"api.openai.com": null}}'

Response:

{"status": "ok"}
GET /api/cache/stats - Cache Statistics

Returns current cache statistics:

curl http://localhost:17081/api/cache/stats

Response:

{
  "hits": 42,
  "misses": 8,
  "stores": 8,
  "evictions": 0,
  "errors": 0,
  "current_size": 5368709120,
  "hit_rate": 0.84
}
DELETE /api/cache - Clear Cache

Clears all cached content:

curl -X DELETE http://localhost:17081/api/cache

Response:

{"status": "ok"}

Project Structure

proxy/
├── cmd/proxy/
│   └── main.go              # Application entry point
├── internal/
│   ├── config/              # Configuration management
│   │   ├── config.go        # Config types and loading
│   │   └── watcher.go       # File watcher for hot reload
│   ├── proxy/               # Proxy implementations
│   │   ├── server.go        # Main server with protocol detection
│   │   ├── http.go          # HTTP/HTTPS proxy (goproxy)
│   │   ├── socks.go         # SOCKS5 proxy (go-socks5)
│   │   └── detector.go      # Protocol detection
│   ├── injector/            # Header injection
│   │   ├── injector.go      # Header injection logic
│   │   └── matcher.go       # Domain pattern matching
│   ├── cert/                # Certificate management
│   │   └── manager.go       # CA cert generation and storage
│   ├── api/                 # REST API
│   │   ├── server.go        # API server
│   │   └── handlers.go      # API handlers
│   ├── logger/              # Request logging
│   │   └── logger.go        # Structured logging
│   └── filter/              # Connection filtering
│       └── filter.go        # DNS/IP allowlist
├── docs/
│   ├── ARCHITECTURE.md
│   └── design/
│       ├── config.md
│       ├── proxy.md
│       ├── injector.md
│       └── api.md
├── go.mod
├── go.sum
└── config.yaml              # Example configuration

Dependencies

Package Purpose
github.com/elazarl/goproxy HTTP/HTTPS proxy with MITM
github.com/things-go/go-socks5 SOCKS5 server
github.com/fsnotify/fsnotify File watching for config
github.com/go-chi/chi/v5 HTTP routing for API
gopkg.in/yaml.v3 YAML configuration parsing
go.uber.org/zap Structured logging

Certificate Installation

For HTTPS interception, the proxy generates a CA certificate on first run. Install it in your system/browser trust store:

# Certificate is saved to:
# ./certs/ca.crt (public cert - install this)
# ./certs/ca.key (private key - keep secure)

# macOS
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ./certs/ca.crt

# Linux (Ubuntu/Debian)
sudo cp ./certs/ca.crt /usr/local/share/ca-certificates/discobot-proxy.crt
sudo update-ca-certificates

# Windows (PowerShell as Admin)
Import-Certificate -FilePath .\certs\ca.crt -CertStoreLocation Cert:\LocalMachine\Root

Usage

As HTTP Proxy
# Set environment variables
export HTTP_PROXY=http://localhost:17080
export HTTPS_PROXY=http://localhost:17080

# Or per-command
curl --proxy http://localhost:17080 https://api.anthropic.com/v1/messages
As SOCKS5 Proxy
# Set environment variable
export ALL_PROXY=socks5://localhost:17080

# Or per-command
curl --socks5 localhost:17080 https://example.com
Docker Registry Caching

The proxy automatically caches Docker registry pulls when caching is enabled. This dramatically speeds up repeated pulls of the same images:

# Configure Docker to use the proxy
export HTTP_PROXY=http://localhost:17080
export HTTPS_PROXY=http://localhost:17080

# Or configure in Docker daemon.json
{
  "proxies": {
    "default": {
      "httpProxy": "http://localhost:17080",
      "httpsProxy": "http://localhost:17080"
    }
  }
}

# First pull - downloads from registry and caches
docker pull ubuntu:22.04
# Subsequent pulls - served from cache (much faster!)
docker pull ubuntu:22.04

Cache benefits:

  • Content-addressable: Layers are cached by SHA256 digest (immutable)
  • Efficient storage: Only unique layers are stored
  • LRU eviction: Automatically manages cache size
  • Multi-image support: Shared layers between images are cached once
  • Streaming cache misses: First-time downloads are forwarded to the client immediately while they are written into the cache

Testing

# Run all tests
go test ./...

# Run with verbose output
go test -v ./...

# Run specific package
go test ./internal/injector/...

# Run with race detection
go test -race ./...

License

MIT

Directories

Path Synopsis
cmd
proxy command
Package main is the entry point for the proxy server.
Package main is the entry point for the proxy server.
internal
api
Package proxyapi provides the REST API for runtime configuration.
Package proxyapi provides the REST API for runtime configuration.
cache
Package cache provides HTTP response caching with LRU eviction.
Package cache provides HTTP response caching with LRU eviction.
cert
Package cert provides certificate management for MITM proxying.
Package cert provides certificate management for MITM proxying.
config
Package config provides configuration types, loading, and validation.
Package config provides configuration types, loading, and validation.
filter
Package filter provides connection filtering by domain and IP.
Package filter provides connection filtering by domain and IP.
injector
Package injector provides header injection with domain pattern matching.
Package injector provides header injection with domain pattern matching.
logger
Package logger provides structured logging for the proxy.
Package logger provides structured logging for the proxy.
proxy
Package proxy provides HTTP and SOCKS5 proxy implementations.
Package proxy provides HTTP and SOCKS5 proxy implementations.
recorder
Package recorder records full HTTP request/response information to disk.
Package recorder records full HTTP request/response information to disk.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL