mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-28 07:36:38 +08:00
docs: add custom best exit probe target design
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
# Custom Best-Exit Probe Target Design
|
||||
|
||||
Date: 2026-05-01
|
||||
Status: Approved design
|
||||
|
||||
## Goal
|
||||
|
||||
Allow each tunnel to define the TCP target used for exit-side quality probing instead of always probing `www.bing.com:443`.
|
||||
|
||||
The custom target must be used consistently by:
|
||||
|
||||
- `best` exit scoring: each exit probes the configured target to measure exit-to-public quality.
|
||||
- Tunnel quality monitoring: the existing exit-side quality check probes the same configured target.
|
||||
|
||||
If a tunnel does not configure a target, behavior remains compatible with today: `www.bing.com:443`.
|
||||
|
||||
## Non-Goals
|
||||
|
||||
- Do not add HTTP/HTTPS request probing in this phase. The probe remains TCP host/port measurement.
|
||||
- Do not add a global default target setting in this phase.
|
||||
- Do not require existing tunnels to be edited or migrated manually.
|
||||
- Do not change the `best` switching thresholds, confirmation rounds, cooldowns, or runtime chain ordering semantics.
|
||||
- Do not add frontend test infrastructure.
|
||||
|
||||
## User-Facing Behavior
|
||||
|
||||
Each tunnel form gets a compact quality target section:
|
||||
|
||||
- Host input, placeholder `www.bing.com`.
|
||||
- Port input, placeholder `443`.
|
||||
- Helper text: this target is used for tunnel quality detection and `best` optimal-exit scoring; leaving it empty uses `www.bing.com:443`.
|
||||
|
||||
Tunnel list/get responses include the configured target so edit forms can round-trip it. The UI displays the effective target near quality/best-exit information as `测试目标:host:port`.
|
||||
|
||||
## Data Model
|
||||
|
||||
Add nullable/default-compatible fields to `model.Tunnel`:
|
||||
|
||||
- `ProbeTargetHost string` mapped to `probe_target_host`, `type:text`, default `''`.
|
||||
- `ProbeTargetPort int` mapped to `probe_target_port`, default `0`.
|
||||
|
||||
Effective target resolution:
|
||||
|
||||
- If `ProbeTargetHost` is non-empty and `ProbeTargetPort` is valid, use it.
|
||||
- Otherwise use `www.bing.com:443`.
|
||||
|
||||
The existing `TunnelQuality` persisted fields `exit_to_bing_latency` and `exit_to_bing_loss` remain unchanged for compatibility. They will semantically mean exit-to-configured-test-target after this change. API/UI labels should avoid saying `Bing` for new displays.
|
||||
|
||||
## Validation
|
||||
|
||||
On create/update:
|
||||
|
||||
- Empty host and empty/zero port are allowed and mean default target.
|
||||
- If either host or port is set, validate both as a pair.
|
||||
- Host is trimmed and must not contain URL scheme, path, query, or whitespace.
|
||||
- Host can be a domain, IPv4, or IPv6 literal. Bracketed IPv6 input should be normalized by removing surrounding brackets.
|
||||
- Port must be an integer from `1` to `65535`.
|
||||
- Do not perform network probing during save; external network failures must not block configuration changes.
|
||||
|
||||
Errors should be specific, for example:
|
||||
|
||||
- `测试目标 Host 不能为空`
|
||||
- `测试目标端口必须是 1-65535`
|
||||
- `测试目标 Host 不能包含协议或路径`
|
||||
|
||||
## Backend Flow
|
||||
|
||||
Introduce a small value/helper near the tunnel quality and best-exit code:
|
||||
|
||||
```go
|
||||
type tunnelProbeTarget struct {
|
||||
Host string
|
||||
Port int
|
||||
}
|
||||
```
|
||||
|
||||
Helpers:
|
||||
|
||||
- `defaultTunnelProbeTarget() tunnelProbeTarget` returns `www.bing.com:443`.
|
||||
- `normalizeTunnelProbeTarget(host string, port int) (tunnelProbeTarget, bool, error)` validates user input; the boolean indicates whether the user explicitly configured a target.
|
||||
- `effectiveTunnelProbeTarget(tunnel *model.Tunnel) tunnelProbeTarget` returns configured target or default.
|
||||
|
||||
Use the effective target in `tunnelQualityProber.probeTunnel`:
|
||||
|
||||
- Type 1 and unknown tunnel fallback probes entry node to effective target instead of hardcoded Bing.
|
||||
- Type 2 probes the selected/current exit node to effective target instead of hardcoded Bing.
|
||||
- `probeBestExitOwners` receives the effective target and passes it into best-exit owner scoring.
|
||||
|
||||
Use the effective target in `evaluateBestExitOwner`:
|
||||
|
||||
- Owner-to-exit measurement stays unchanged.
|
||||
- Exit-to-public measurement probes `target.Host:target.Port` instead of `bestExitPublicTargetHost:bestExitPublicTargetPort`.
|
||||
- The per-round public probe cache key must include node ID plus target host and port so future extensions cannot reuse measurements across different targets.
|
||||
|
||||
## API Shape
|
||||
|
||||
Tunnel list/get data includes:
|
||||
|
||||
```json
|
||||
{
|
||||
"probeTargetHost": "example.com",
|
||||
"probeTargetPort": 443
|
||||
}
|
||||
```
|
||||
|
||||
For old/default tunnels, return empty host and `0` to represent `use default`. The edit form must preserve default-as-empty unless the user explicitly saves a custom target.
|
||||
|
||||
Quality monitoring response includes effective target display metadata:
|
||||
|
||||
```json
|
||||
{
|
||||
"probeTargetHost": "www.bing.com",
|
||||
"probeTargetPort": 443
|
||||
}
|
||||
```
|
||||
|
||||
Existing `exitToBingLatency` and `exitToBingLoss` keys stay to avoid breaking frontend and external consumers.
|
||||
|
||||
## Frontend Flow
|
||||
|
||||
Extend `ChainTunnel` only if needed for node-level data; the target belongs to the tunnel, so `Tunnel` and `TunnelForm` get:
|
||||
|
||||
- `probeTargetHost?: string`
|
||||
- `probeTargetPort?: number`
|
||||
|
||||
On edit:
|
||||
|
||||
- Populate form fields from tunnel response.
|
||||
- Empty or zero means default target.
|
||||
|
||||
On submit:
|
||||
|
||||
- Trim host.
|
||||
- Convert blank port to `0`.
|
||||
- Send `probeTargetHost` and `probeTargetPort` with create/update payload.
|
||||
|
||||
Display:
|
||||
|
||||
- In the form helper, show default target behavior.
|
||||
- In quality/best-exit display areas, avoid `Bing` wording; prefer `测试目标` or the concrete `host:port`.
|
||||
|
||||
## Error Handling
|
||||
|
||||
- Invalid target input returns a normal API error envelope with a specific message.
|
||||
- Probe failures use existing quality error paths and best-exit scoring failure entries.
|
||||
- If all exit-to-target probes fail, best-exit behavior remains the same as today when all Bing probes fail: no valid best decision is applied from that round.
|
||||
|
||||
## Testing
|
||||
|
||||
Backend tests:
|
||||
|
||||
- Normalize default target when host/port are empty.
|
||||
- Reject partial host/port configuration and invalid port ranges.
|
||||
- Reject host values with URL scheme/path/whitespace.
|
||||
- Create/update tunnel persists `probeTargetHost` and `probeTargetPort`.
|
||||
- `ListTunnels` returns target fields.
|
||||
- `tunnelQualityProber` uses configured target instead of `www.bing.com:443`.
|
||||
- `best` scoring uses configured target for exit-to-target probes.
|
||||
- Empty target preserves old default `www.bing.com:443` behavior.
|
||||
|
||||
Frontend verification:
|
||||
|
||||
- `pnpm run build` passes.
|
||||
- Manual UI check: create/edit tunnel with blank target and custom target, confirm payload and round-trip display.
|
||||
|
||||
## Rollout And Compatibility
|
||||
|
||||
- Existing tunnels continue using `www.bing.com:443` because empty target resolves to default.
|
||||
- SQLite/PostgreSQL schema changes are handled by existing auto-migration.
|
||||
- Historical `TunnelQuality` rows keep existing columns and are not rewritten.
|
||||
- No runtime agent change is required; the panel already performs these quality probes through existing node ping APIs.
|
||||
|
||||
## Open Decisions
|
||||
|
||||
None. User-approved decisions:
|
||||
|
||||
- Per-tunnel fields are `host + port`.
|
||||
- The target applies to both `best` scoring and tunnel quality monitoring.
|
||||
- Probe type remains TCP host/port.
|
||||
- Empty target defaults to `www.bing.com:443`.
|
||||
Reference in New Issue
Block a user