high-performance HTTP/HTTPS forward proxy in pure Go. built on fasthttp, not net/http. handles plain HTTP forwarding and CONNECT tunneling with connection pooling, DNS caching, and Prometheus metrics out of the box.
./proxy -config config.yamlpoint your browser or HTTP_PROXY at :8080 and you're done.
- HTTP forwarding — receives
GET http://example.com/path, strips hop-by-hop headers, chainsX-Forwarded-For, forwards via pooled fasthttp client - HTTPS CONNECT tunneling — receives
CONNECT example.com:443, dials upstream, hijacks the connection, copies bytes bidirectionally. no TLS inspection, true opaque tunnel - connection pooling —
sync.Pooloffasthttp.Clientinstances with configurableMaxConnsPerHostand 5-min idle duration - DNS caching — 1-hour TTL via
fasthttp.TCPDialer, 4096 concurrent dials - Prometheus metrics — separate
net/httpserver so scraping never touches proxy traffic. request counters, latency histograms, active connections, byte accounting, tunnel gauges - structured logging —
zapwith console (colored) or JSON output, configurable level - graceful shutdown — catches
SIGINT/SIGTERM, 30-second drain deadline - no fingerprinting — no
Serverheader, noDateheader, header casing preserved as-is
git clone https://github.com/yigitkonur/proxy-http-forward.git
cd proxy-http-forward
make buildbinary lands in ./build/proxy.
make build-linux # ./dist/proxy-linux-amd64
make build-darwin # ./dist/proxy-darwin-arm64
make build-allmake docker-build && make docker-runmulti-stage alpine image, runs as non-root proxy user, exposes 8080 + 9090, built-in health check.
# with config file
./proxy -config config.yaml
# with defaults (searches ./config.yaml, /etc/proxy/config.yaml, ~/.proxy/config.yaml)
./proxy
# print version
./proxy -version
# override via env
PROXY_SERVER_ADDRESS=":3128" PROXY_LOGGING_LEVEL="debug" ./proxy# HTTP
curl -x http://localhost:8080 http://httpbin.org/ip
# HTTPS
curl -x http://localhost:8080 https://httpbin.org/ip
# metrics
curl http://localhost:9090/metricsYAML config file with env var overrides (PROXY_<SECTION>_<KEY>). env vars take priority.
server:
address: ":8080"
read_timeout: 30s
write_timeout: 30s
idle_timeout: 120s
max_conns_per_ip: 10000
max_requests_per_conn: 0
proxy:
dial_timeout: 10s
response_timeout: 60s
max_idle_conns: 1000
logging:
level: "info" # debug | info | warn | error | fatal
format: "console" # console | json
output: "stdout" # stdout | stderr | /path/to/file
metrics:
enabled: true
address: ":9090"
path: "/metrics"| env var | overrides |
|---|---|
PROXY_SERVER_ADDRESS |
server.address |
PROXY_PROXY_DIAL_TIMEOUT |
proxy.dial_timeout |
PROXY_LOGGING_LEVEL |
logging.level |
PROXY_METRICS_ENABLED |
metrics.enabled |
all under the proxy namespace:
| metric | type | labels |
|---|---|---|
proxy_requests_total |
counter | method, status, type |
proxy_request_duration_seconds |
histogram | method, type |
proxy_active_connections |
gauge | — |
proxy_bytes_sent_total |
counter | type |
proxy_bytes_received_total |
counter | type |
proxy_errors_total |
counter | type, reason |
proxy_tunnel_connections |
gauge | — |
cmd/proxy/
main.go — entry point, signal handling, graceful shutdown
pkg/
config/config.go — viper-based config with YAML + env var loading
handler/handler.go — HTTP forwarding, CONNECT tunneling, header stripping
log/log.go — zap logger construction
metrics/metrics.go — Prometheus metric definitions + separate HTTP server
pool/pool.go — sync.Pool of fasthttp.Client instances
proxy/proxy.go — server wiring, start/shutdown orchestration
test/
proxy_test.go — unit tests
no authentication, no ACLs, no URL filtering, no content inspection, no TLS on the listener itself. it's a fast, dumb pipe. if you need those things, put it behind something that does.
MIT