Extend the config, database schema, and server internals to support per-route L4/L7 mode selection and PROXY protocol fields. This is the foundation for L7 HTTP/2 reverse proxying and multi-hop PROXY protocol support described in the updated ARCHITECTURE.md. Config: Listener gains ProxyProtocol; Route gains Mode, TLSCert, TLSKey, BackendTLS, SendProxyProtocol. L7 routes validated at load time (cert/key pair must exist and parse). Mode defaults to "l4". DB: Migration v2 adds columns to listeners and routes tables. CRUD and seeding updated to persist all new fields. Server: RouteInfo replaces bare backend string in route lookup. handleConn dispatches on route.Mode (L7 path stubbed with error). ListenerState and ListenerData carry ProxyProtocol flag. All existing L4 tests pass unchanged. New tests cover migration v2, L7 field persistence, config validation for mode/cert/key, and proxy_protocol flag round-tripping. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68 lines
3.8 KiB
Markdown
68 lines
3.8 KiB
Markdown
# 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
|
|
|
|
```bash
|
|
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:
|
|
```bash
|
|
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
|
|
- `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).
|