Files
mc-proxy/CLAUDE.md
Kyle Isom ffc31f7d55 Add Prometheus metrics for connections, firewall, L7, and bytes transferred
Instrument mc-proxy with prometheus/client_golang. New internal/metrics/
package defines counters, gauges, and histograms for connection totals,
active connections, firewall blocks by reason, backend dial latency,
bytes transferred, L7 HTTP status codes, and L7 policy blocks. Optional
[metrics] config section starts a scrape endpoint. Firewall gains
BlockedWithReason() to report block cause. L7 handler wraps
ResponseWriter to record status codes per hostname.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 18:05:25 -07:00

3.9 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

mc-proxy is a TLS proxy and router for Metacircular Dynamics services. It operates in two per-route modes: L4 passthrough (reads SNI, proxies raw TCP without terminating TLS) and L7 terminating (terminates TLS, reverse proxies HTTP/2 and HTTP/1.1 traffic including gRPC). A global firewall (IP, CIDR, GeoIP, rate limiting) is evaluated before routing. PROXY protocol support enables multi-hop deployments preserving real client IPs. See ARCHITECTURE.md for full design.

Build Commands

make all          # vet → lint → test → build
make mc-proxy     # build the binary with version injection
make build        # compile all packages
make test         # run all tests
make vet          # go vet
make lint         # golangci-lint
make proto        # regenerate gRPC code from proto definitions
make devserver    # build and run locally with srv/mc-proxy.toml

Run a single test:

go test ./internal/sni -run TestExtract

Architecture

  • Module path: git.wntrmute.dev/kyle/mc-proxy
  • Go with CGO_ENABLED=0, statically linked, Alpine containers
  • Dual mode, per-route — L4 (passthrough) and L7 (TLS-terminating HTTP/2 reverse proxy) coexist on the same listener
  • PROXY protocol — listeners accept v1/v2; routes send v2. Enables edge→origin deployments over Tailscale
  • gRPC admin API — manages routes and firewall rules at runtime; Unix socket only; optional (disabled if [grpc] section omitted from config)
  • No auth on proxy listeners — this is pre-auth infrastructure; services behind it handle their own MCIAS auth
  • SQLite database — persists listeners, routes, and firewall rules; pure-Go driver (modernc.org/sqlite); seeded from TOML on first run, DB is source of truth thereafter
  • Write-through pattern — gRPC mutations write to DB first, then update in-memory state
  • Config: TOML via go-toml/v2, runtime data in /srv/mc-proxy/
  • Testing: stdlib testing only, t.TempDir() for isolation
  • Linting: golangci-lint v2 with .golangci.yaml

Package Structure

  • internal/config/ — TOML config loading and validation
  • internal/db/ — SQLite database: migrations, CRUD for listeners/routes/firewall rules, seeding, snapshots
  • internal/sni/ — TLS ClientHello parser; extracts SNI hostname without consuming bytes
  • internal/firewall/ — global blocklist evaluation (IP, CIDR, GeoIP via MaxMind GeoLite2); rate limiting; thread-safe mutations and GeoIP reload
  • internal/proxy/ — L4 bidirectional TCP relay with half-close propagation and idle timeout
  • internal/proxyproto/ — PROXY protocol v1/v2 parser and v2 writer
  • internal/l7/ — L7 TLS termination, prefixConn, HTTP/2 reverse proxy with h2c backend transport
  • internal/server/ — orchestrates listeners → PROXY protocol → firewall → SNI → route → L4/L7 dispatch; per-listener state with connection tracking
  • internal/grpcserver/ — gRPC admin API: route/firewall CRUD, status, write-through to DB
  • internal/metrics/ — Prometheus metric definitions and HTTP server; optional [metrics] config section
  • proto/mc_proxy/v1/ — protobuf definitions; gen/mc_proxy/v1/ has generated code

Signals

  • SIGINT/SIGTERM — graceful shutdown (drain in-flight connections up to shutdown_timeout)
  • SIGHUP — reload GeoIP database without restart

Critical Rules

  • L4 routes never terminate TLS and never modify the byte stream.
  • L7 routes terminate TLS at the proxy and reverse proxy HTTP/2 (including gRPC) to backends.
  • Firewall rules are always evaluated before any routing decision.
  • PROXY protocol is only parsed on explicitly enabled listeners.
  • SNI matching is exact and case-insensitive.
  • Blocked connections get a TCP RST — no error messages, no TLS alerts.
  • Database writes must succeed before in-memory state is updated (write-through).