Skip to content

Commit b480ea0

Browse files
yasithdevclaude
andcommitted
docs: add CLAUDE.md for Claude Code project context
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1b8d330 commit b480ea0

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

CLAUDE.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# FRP-Server
2+
3+
Go-based relay control plane for FRP tunneling. Manages tunnel provisioning, API key auth, JWT tokens, and coordinates with the FRP relay engine for P2P connections.
4+
5+
## Commands
6+
7+
```bash
8+
go build -o frp-server . # Build
9+
go test ./... # Run tests
10+
```
11+
12+
## Running
13+
14+
```bash
15+
./frp-server \
16+
--relay-addr "0.0.0.0:7000" \
17+
--api-addr "0.0.0.0:7500" \
18+
--master-secret "your-secret" \
19+
--db-path "./frp-server.db" \
20+
--jwt-secret "optional-persist-across-restarts"
21+
```
22+
23+
`--master-secret` is required (fatal if missing). `--jwt-secret` auto-generates if omitted (logged warning).
24+
25+
## Architecture (~850 LoC)
26+
27+
```
28+
main.go # CLI flags, startup, graceful shutdown (SIGTERM/SIGINT, 5s timeout)
29+
internal/
30+
config/config.go # Config struct (5 fields)
31+
auth/jwt.go # JWT generation/validation, scopes (host/connect)
32+
db/
33+
db.go # SQLite store (WAL mode, FK constraints)
34+
models.go # APIKey, Tunnel, TunnelPort
35+
api/
36+
server.go # HTTP server, route registration
37+
handlers.go # 8 REST handlers
38+
middleware.go # Master secret + API key auth middleware
39+
relay/relay.go # FRP server.Service wrapper
40+
```
41+
42+
## Auth Model (3 tiers)
43+
44+
1. **Master Secret** — Admin-only, for `/api/v1/auth/*`. Constant-time comparison.
45+
2. **API Keys** — Created via master secret. Stored as SHA256 hash. Prefix: `ak-`. Used for tunnel CRUD.
46+
3. **JWT Tokens** — Per-tunnel, scoped (`host`/`connect`). 24h TTL. Also used as FRP relay auth token.
47+
48+
## API (`/api/v1/`)
49+
50+
| Endpoint | Auth | Description |
51+
|----------|------|-------------|
52+
| `POST /auth/keys` | Master | Create API key |
53+
| `DELETE /auth/keys/{id}` | Master | Revoke API key |
54+
| `POST /tunnels` | API key | Create tunnel (returns hostToken + connectToken) |
55+
| `GET /tunnels` | API key | List owner's tunnels |
56+
| `GET /tunnels/{id}` | API key | Get tunnel + ports |
57+
| `DELETE /tunnels/{id}` | API key | Delete tunnel |
58+
| `POST /tunnels/{id}/ports` | API key | Add port (1-65535) |
59+
| `DELETE /tunnels/{id}/ports/{port}` | API key | Remove port |
60+
| `POST /tunnels/{id}/tokens` | API key | Generate new JWT (scope required) |
61+
| `GET /health` | None | Health check |
62+
63+
## Database (SQLite3, WAL mode)
64+
65+
- `api_keys`: id (`ak-*`), key_hash (SHA256), created_at, revoked_at
66+
- `tunnels`: id (`row-*`), tunnel_id (`tun-*`), owner_key_id (FK), created_at, expires_at
67+
- `tunnel_ports`: id (`tp-*`), tunnel_id (FK CASCADE), port, protocol
68+
69+
ID pattern: `prefix-` + 12 hex chars (6 random bytes).
70+
71+
## Gotchas
72+
73+
- Tunnel `expires_at` is stored but never enforced — no background cleanup job
74+
- JWT secret is shared with FRP relay auth token (`cfg.Auth.Token = jwtSecret`)
75+
- Port deletion is a silent no-op if port doesn't exist
76+
- Lists return empty `[]` not `null` (explicit nil-slice handling)
77+
- Master secret stored as plain string in memory (compared via `subtle.ConstantTimeCompare`)
78+
- Ownership check: tunnel operations return 403 if `OwnerKeyID != keyID` from context

0 commit comments

Comments
 (0)