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>
62 lines
3.1 KiB
Markdown
62 lines
3.1 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 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
|
|
|
|
```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
|
|
- **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 `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); thread-safe mutations and GeoIP reload
|
|
- `internal/proxy/` — bidirectional TCP relay with half-close propagation and idle timeout
|
|
- `internal/server/` — orchestrates listeners → firewall → SNI → route → proxy pipeline; 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
|
|
|
|
- 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).
|