feat: clash/ss suport
This commit is contained in:
51
CLAUDE.md
51
CLAUDE.md
@@ -4,28 +4,31 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## Project Overview
|
||||
|
||||
Sub Router is a Surge proxy subscription management system. It aggregates nodes from upstream subscriptions, allows adding custom static nodes and rules, and generates a combined Surge configuration file served at `/surge`.
|
||||
Sub Router is a Surge proxy subscription management system. It aggregates nodes from upstream subscriptions, allows adding custom static nodes and rules, and generates a combined Surge configuration file served at `/surge/:token`.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Development (starts both server and web dev server concurrently)
|
||||
npm run dev
|
||||
pnpm dev
|
||||
|
||||
# Server only (port 3456, hot-reload via tsx watch)
|
||||
npm run dev:server
|
||||
pnpm dev:server
|
||||
|
||||
# Frontend only (port 5173, proxies /api and /surge to :3456)
|
||||
npm run dev:web
|
||||
pnpm dev:web
|
||||
|
||||
# Build frontend for production
|
||||
npm run build:web
|
||||
pnpm build:web
|
||||
|
||||
# Production start (serves built frontend + API on port 3456)
|
||||
npm run start
|
||||
pnpm start
|
||||
|
||||
# Type check frontend
|
||||
cd web && npx tsc --noEmit
|
||||
cd web && pnpm exec tsc --noEmit
|
||||
|
||||
# Type check server
|
||||
cd server && pnpm exec tsc --noEmit
|
||||
|
||||
# Docker
|
||||
docker compose up -d
|
||||
@@ -39,7 +42,7 @@ docker compose up -d
|
||||
|
||||
1. User adds upstream subscription URLs → backend fetches and parses nodes into `fetched_nodes` table
|
||||
2. User adds static nodes via URI (ss://, vmess://, trojan://) → parsed and stored in `static_nodes` table
|
||||
3. `GET /surge` → `generator.ts` rebuilds the Surge config:
|
||||
3. `GET /surge/:token` → `generator.ts` rebuilds the Surge config:
|
||||
- Takes first enabled subscription's `raw_config` as base template
|
||||
- **Replaces** `[Proxy]` section entirely with only enabled nodes (static first, then fetched)
|
||||
- **Rebuilds** `[Proxy Group]` select groups with only enabled node names
|
||||
@@ -48,11 +51,23 @@ docker compose up -d
|
||||
|
||||
### Auth model
|
||||
|
||||
`/surge` endpoint requires no auth (for Surge client access). All `/api/*` routes require Bearer token auth, except `/api/auth/login` and `/api/auth/status`. Password is stored in the `config` table. Token is the raw password sent via `Authorization: Bearer <password>`.
|
||||
Two separate credentials exist:
|
||||
|
||||
- **Admin password**: Protects all `/api/*` routes (except `/api/auth/login` and `/api/auth/status`). Sent as `Authorization: Bearer <password>`. On first login with no password set, the submitted password becomes the password.
|
||||
- **Surge token**: UUID stored in `config` table as `surge_token`. Embedded in the Surge subscription URL itself (`/surge/:token`). Returns 404 for wrong tokens. Regeneratable via `POST /api/config/surge-token`.
|
||||
|
||||
### API routes
|
||||
|
||||
- `POST /api/auth/login`, `GET /api/auth/status` — auth (no auth required)
|
||||
- `GET /api/stats` — node/rule counts summary
|
||||
- `/api/subscriptions` → `subscriptions.ts` (CRUD + `/:id/fetch`, `/:id/nodes`)
|
||||
- `/api/nodes` → `nodes.ts` (fetched node toggle, static node CRUD)
|
||||
- `/api/rules` → `rules.ts` (CRUD + `/reorder`)
|
||||
- `/api/config` → `surge.ts` (`/surge-token` GET/POST, `/preview` GET)
|
||||
|
||||
### Database
|
||||
|
||||
SQLite with WAL mode at `server/data/sub-router.db`. Five tables: `subscriptions`, `fetched_nodes` (FK to subscriptions, CASCADE delete), `static_nodes`, `rules`, `config` (KV store for password).
|
||||
SQLite with WAL mode at `server/data/sub-router.db`. Five tables: `subscriptions`, `fetched_nodes` (FK to subscriptions, CASCADE delete), `static_nodes`, `rules`, `config` (KV store for `password` and `surge_token`).
|
||||
|
||||
### Parsers (`server/src/parsers/`)
|
||||
|
||||
@@ -61,14 +76,28 @@ Convert protocol URIs to Surge proxy lines. Each parser returns `{ name, type, s
|
||||
- **SS**: No TLS wrapping (Surge doesn't support SS over TLS; SS 2022 has built-in encryption)
|
||||
- **VMess/Trojan**: `skip-cert-verify=false` (strict TLS verification)
|
||||
|
||||
On re-fetch, enabled state is preserved by node name: existing name→enabled mapping is saved before delete, then reapplied to new rows.
|
||||
|
||||
When renaming a static node (`PUT /api/nodes/static/:id`), the `surge_line` prefix is also updated to match the new name.
|
||||
|
||||
### Frontend
|
||||
|
||||
Five panels: Subscriptions (CRUD + fetch trigger), Static Nodes (paste URI, custom naming, double-click to rename), Node Selector (per-subscription toggle with regex batch operations), Rules (CRUD + drag reorder), Output (subscription URL + config preview). Dark cyberpunk theme with CSS variables, JetBrains Mono font.
|
||||
|
||||
### Generator limitation
|
||||
|
||||
`rebuildProxyGroup` in `generator.ts` only updates the **first** `= select,` group (due to `handled = true` flag). If a Surge template has multiple select groups, only the first gets its node list replaced.
|
||||
|
||||
## Route ordering matters
|
||||
|
||||
In `server/src/routes/`: specific paths like `/reorder` and `/fetched/batch` must be registered **before** parameterized `/:id` routes to avoid being captured by Express route matching.
|
||||
|
||||
## Legacy file
|
||||
|
||||
`index.js` at the repo root is a pre-rewrite single-file prototype. It is not used by the current system and can be ignored.
|
||||
|
||||
## Deployment
|
||||
|
||||
The `Content-Disposition` header on `/surge` controls the config profile name in Surge client (currently `IPLC.MAX.conf`). Docker mounts `./data` volume for SQLite persistence. Certificate renewal uses acme.sh with `dns_cf` (Cloudflare DNS API validation).
|
||||
Multi-stage Docker build: frontend built on `node:22-slim`, output copied into production image alongside the server. The `./data` volume maps to `server/data/` inside the container for SQLite persistence.
|
||||
|
||||
The `Content-Disposition` header on `/surge/:token` controls the config profile name in Surge client (currently `IPLC.MAX.conf`). Certificate renewal uses acme.sh with `dns_cf` (Cloudflare DNS API validation).
|
||||
|
||||
Reference in New Issue
Block a user