Feature request: raw TCP/UDP RTT probe mode for urltest/priority groups (latency to non-HTTP targets — game servers, VoIP)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 38.1k
- Forks
- 4.6k
- Avg merge
- 19d 15h
- Merged PRs (30d)
- 1
Description
Problem
urltest currently has exactly one probe mode, and it is inherently HTTP(S)-only: a HEAD request against a URL, timed to response headers (common/urltest/urltest.go). The proposed throughput mode in #4397 changes what's measured (bandwidth vs. latency) but keeps the same HTTP(S) transport requirement — it solves a different problem and still can't probe a target that doesn't speak HTTP.
There's no way to auto-select an outbound by latency to a target that isn't an HTTP(S) endpoint — e.g. a game server (Battlefield-style titles use a bespoke UDP/TCP protocol with no TLS/HTTP handshake) or a VoIP endpoint. Pointing url at such a target doesn't work: the probe never gets a valid HTTP response, the group considers every outbound "dead", and the result is worse than not testing at all.
The current workaround is picking an HTTPS endpoint that's topologically close to the real target (same datacenter/ASN/region) and hoping its latency correlates. It's a guess, not a measurement, and it breaks whenever the real route to the game server diverges from the route to the HTTPS surrogate (different peering, different exchange points — common in practice).
Related issues
- #4397 proposes a
strategyfield on theurltestgroup (latency/throughput/throughput_with_latency_floor). This request would fit naturally as a furtherstrategyvalue rather than a separate mechanism. - #3604 is adjacent, same root constraint ("HTTP(S) only"): the Clash API
/delay?url=...silently rewrites a non-HTTPSurlparam back to the hardcoded gstatic target, so even ad-hoc probing of a non-HTTPS target through the API isn't possible today. - #3023 / #4110 (load balancing / weighted modes) are also about
strategychoices inside a group, but neither addresses measuring latency to a non-HTTP target.
Proposed solution
Add a raw_tcp (and optionally raw_udp) strategy value:
raw_tcp: instead of an HTTPHEAD, justDialContext(ctx, "tcp", host:port)through the outbound being probed, timing to a successful TCP handshake (SYN → SYN-ACK). No HTTP client, no URL/scheme — justhost:port.raw_udp(optional, harder to define "success" for without server cooperation): send a UDP packet and time to any response with a short timeout, or — simpler for a first pass — just time session establishment where the protocol allows it.
The metric (RTT) would land in the same URLTestHistory.Delay field used today — no change to the history/Clash API schema, just a different way of populating the existing field.
Example config
{
"type": "urltest",
"tag": "game-latency-out",
"outbounds": ["node-a", "node-b", "node-c"],
"strategy": "raw_tcp",
"test_target": "server.battlefield-provider.example:port",
"interval": "30s",
"tolerance": 20
}
test_target would be a new host:port field, relevant only when strategy != latency (for latency, the existing url field continues to be used).
Workaround
Writing a custom adapter to intercept traffic and swap in a fake test target — not something most users can do.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading common/urltest/urltest.go and trace how the current HTTP HEAD probe populates URLTestHistory.Delay. Define the scope of the proposed raw_tcp strategy and test_target configuration, including how successful TCP timing should be represented alongside existing latency results; raw_udp remains explicitly optional and unresolved in the issue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- networking
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100