6.8 KiB
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:
bestexit 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
bestswitching 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
bestoptimal-exit scoring; leaving it empty useswww.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 stringmapped toprobe_target_host,type:text, default''.ProbeTargetPort intmapped toprobe_target_port, default0.
Effective target resolution:
- If
ProbeTargetHostis non-empty andProbeTargetPortis 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
1to65535. - 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:
type tunnelProbeTarget struct {
Host string
Port int
}
Helpers:
defaultTunnelProbeTarget() tunnelProbeTargetreturnswww.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) tunnelProbeTargetreturns 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.
probeBestExitOwnersreceives 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.Portinstead ofbestExitPublicTargetHost: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:
{
"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:
{
"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?: stringprobeTargetPort?: 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
probeTargetHostandprobeTargetPortwith create/update payload.
Display:
- In the form helper, show default target behavior.
- In quality/best-exit display areas, avoid
Bingwording; prefer测试目标or the concretehost: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
probeTargetHostandprobeTargetPort. ListTunnelsreturns target fields.tunnelQualityProberuses configured target instead ofwww.bing.com:443.bestscoring uses configured target for exit-to-target probes.- Empty target preserves old default
www.bing.com:443behavior.
Frontend verification:
pnpm run buildpasses.- 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:443because empty target resolves to default. - SQLite/PostgreSQL schema changes are handled by existing auto-migration.
- Historical
TunnelQualityrows 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
bestscoring and tunnel quality monitoring. - Probe type remains TCP host/port.
- Empty target defaults to
www.bing.com:443.