Rename proto/gen directories from mc-proxy to mc_proxy for valid protobuf package naming. Add CLI status subcommand for querying running instance health via gRPC. Add systemd backup service/timer and backup pruning script. Add buf.yaml and proto-lint Makefile target. Add shutdown_timeout config field. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
3.1 KiB
3.1 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 Layer 4 TLS SNI proxy and router for Metacircular Dynamics services. It reads the SNI hostname from incoming TLS ClientHello messages and proxies the raw TCP stream to the matched backend. It does not terminate TLS. A global firewall (IP, CIDR, GeoIP country blocking) is evaluated before routing. 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
- gRPC admin API — manages routes and firewall rules at runtime; TLS with optional mTLS; 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
testingonly,t.TempDir()for isolation - Linting: golangci-lint v2 with
.golangci.yaml
Package Structure
internal/config/— TOML config loading and validationinternal/db/— SQLite database: migrations, CRUD for listeners/routes/firewall rules, seeding, snapshotsinternal/sni/— TLS ClientHello parser; extracts SNI hostname without consuming bytesinternal/firewall/— global blocklist evaluation (IP, CIDR, GeoIP via MaxMind GeoLite2); thread-safe mutations and GeoIP reloadinternal/proxy/— bidirectional TCP relay with half-close propagation and idle timeoutinternal/server/— orchestrates listeners → firewall → SNI → route → proxy pipeline; per-listener state with connection trackinginternal/grpcserver/— gRPC admin API: route/firewall CRUD, status, write-through to DBproto/mc_proxy/v1/— protobuf definitions;gen/mc_proxy/v1/has generated code
Signals
SIGINT/SIGTERM— graceful shutdown (drain in-flight connections up toshutdown_timeout)SIGHUP— reload GeoIP database without restart
Critical Rules
- mc-proxy never terminates TLS and never modifies the byte stream.
- Firewall rules are always evaluated before any routing decision.
- 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).