summaryrefslogtreecommitdiff
path: root/docs/research/public-defaults.md
diff options
context:
space:
mode:
authorAndrew Guschin <guschin@altlinux.org>2026-10-30 01:59:28 +0400
committerAndrew Guschin <guschin@altlinux.org>2026-10-30 01:59:28 +0400
commitda2e0eef42d5d611b0125de17e467dbddf3d8d71 (patch)
treebdbbf6b7190157fc2325ccb7dd42cf6bb62cdcd1 /docs/research/public-defaults.md
parent170f05697812b2f8b29226b4aa07b1b8db38873e (diff)
Document subscription formats and ALT runtime integrationresearch
- Add the Roentgen domain glossary - Record research on 3x-ui subscriptions, runtime integration, and defaults
Diffstat (limited to 'docs/research/public-defaults.md')
-rw-r--r--docs/research/public-defaults.md95
1 files changed, 95 insertions, 0 deletions
diff --git a/docs/research/public-defaults.md b/docs/research/public-defaults.md
new file mode 100644
index 0000000..dd6dbba
--- /dev/null
+++ b/docs/research/public-defaults.md
@@ -0,0 +1,95 @@
+# Public resolver and diagnostic defaults
+
+Researched 2026-10-29 for ticket 13, "Which public resolver and diagnostic endpoints can be defaults?" Planning only. These provider values are proposals pending final human review. This report changes no specification, ticket, networking, service or policy.
+
+## Proposed values
+
+Use Cloudflare's standard public DNS resolver and its speedtest download API. The current official client documents both the download URL and zero-byte latency requests. That supplies a coherent minimal set without a vendor comparison. [Official client README, pinned revision](https://github.com/cloudflare/speedtest/blob/7183e970bda21c900e7f4bcf9c5416aa08257e27/README.md#measurement-config).
+
+| Setting | Proposed value | Expected behavior |
+| --- | --- | --- |
+| Remote DNS | `1.1.1.1:53`, reached through the selected Trojan outbound | Standard DNS; no content filtering |
+| Optional second resolver | `1.0.0.1:53`, also through that outbound | Same provider, alternate address; no provider diversity |
+| HTTPS Ping URL | `https://speed.cloudflare.com/__down?bytes=0` | GET; expect HTTP `200` and an empty response body |
+| Manual Speed URL | `https://speed.cloudflare.com/__down?bytes=10485760` | GET; expect HTTP `200` and 10,485,760 response body bytes if completed |
+| Speed byte limit | `10485760` bytes, exactly 10 MiB | Client stops consuming at the limit |
+| Speed duration limit | `10` seconds | One deadline includes setup and body consumption; first reached limit stops the test |
+| Automatic Ping | Selected configuration only, every `30` seconds; `5` second total deadline | Always through the selected proxy, including while host proxying is disabled |
+| Automatic Speed | Never | An explicit manual action starts one bounded download |
+
+The scheduler and limits above are already approved product requirements. Status and body expectations are source-backed proposals, not observations from a live test. The evidence boundary below matters for the exact `200` expectation.
+
+## Resolver evidence and routing
+
+Cloudflare lists `1.1.1.1` and `1.0.0.1` as its standard unfiltered resolver addresses. Its IPv6 alternatives are `2606:4700:4700::1111` and `2606:4700:4700::1001`. Choose one IPv4 resolver for the existing singular Settings field; publish the second as an alternate rather than adding a new list setting. The official documentation describes the address pair as redundancy. [IP addresses](https://developers.cloudflare.com/1.1.1.1/ip-addresses/).
+
+Port 53 with ordinary DNS is the minimal transport proposal. It does not imply DNS encryption from the Trojan exit to Cloudflare. Cloudflare explicitly distinguishes plaintext DNS from DoT, which it supports on port 853 at these same addresses, with hostname `one.one.one.one`. Adding DoT would be a separate transport decision. [DNS over TLS](https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-tls/).
+
+Roentgen must direct DNS exchanges, including TCP fallback, through the selected Trojan outbound. Resolver address selection must never permit direct DNS fallback. Resolve the diagnostic hostname through that protected path too. This is an implementation requirement from the approved product scope, not proof that the installed Xray adapter already implements it. The use of a numeric resolver avoids needing DNS to discover that resolver. Resolving the Trojan server's own hostname is a separate bootstrap concern for the runtime design.
+
+An IPv4 resolver destination does not prevent querying AAAA records. Reaching an IPv6 resolver address requires suitable connectivity from the proxy exit. IPv6 default selection and the installed Xray DNS transport behavior require later implementation validation; this research sent no DNS queries.
+
+## What the speedtest sources establish
+
+The official `cloudflare/speedtest` client was inspected at `7183e970bda21c900e7f4bcf9c5416aa08257e27`, the `main` revision returned by GitHub during this research, committed 2026-10-29. Its README names `https://speed.cloudflare.com/__down` as the default GET download API. It explicitly specifies `bytes=0` for latency and defines `bytes` as the download file size. Thus zero-byte GET is an intended latency operation, not an invented convention. [Pinned README](https://github.com/cloudflare/speedtest/blob/7183e970bda21c900e7f4bcf9c5416aa08257e27/README.md#instantiation).
+
+The client constructs the URL with `URL.searchParams.set`, sets `bytes`, checks `response.ok`, consumes the body, and handles HTTP 429 as a rate-limit failure with retries. Roentgen should use its own bounded reader rather than copy the client's whole-body `text()` read or retry policy. [Pinned BandwidthEngine, lines 437 to 515 and 677 to 699](https://github.com/cloudflare/speedtest/blob/7183e970bda21c900e7f4bcf9c5416aa08257e27/src/engines/BandwidthEngine/BandwidthEngine.ts#L437).
+
+Cloudflare's launch article links its official Worker template as the benchmark source. The template remains available at `d9b0c5535594a9527d456e2e8c43198dc78569da`, committed 2024-09-20. Its README defines `bytes` as response body size, default zero. Its download handler generates ASCII `0` repeated the requested number of times, clamps at 100,000,000, constructs `new Response(body)` and sets `Content-Type: application/octet-stream` and `Cache-Control: no-store`. Zero produces an empty string. [Launch article](https://blog.cloudflare.com/test-your-home-network-performance/), [pinned template README](https://github.com/cloudflare/worker-speedtest-template/blob/d9b0c5535594a9527d456e2e8c43198dc78569da/README.md#download), [pinned download handler](https://github.com/cloudflare/worker-speedtest-template/blob/d9b0c5535594a9527d456e2e8c43198dc78569da/src/down.js#L24).
+
+The Fetch standard defines `200` as the default Response status. Consequently the published template returns `200`, an empty body at zero, and N ASCII zero bytes at positive integer N below its clamp. [Fetch ResponseInit](https://fetch.spec.whatwg.org/#responseinit), [Workers Response constructor](https://developers.cloudflare.com/workers/runtime-apis/response/#constructor).
+
+There is a specific limitation. The template routes GET requests at `/down`; the current client targets `/__down`. The template README also warns that the official service has different internal server timing behavior. These sources support expecting `200` and a zero-length Ping body, but do not establish that today's deployed `/__down` is byte-for-byte the template or has a permanent status/header contract. Do not require ASCII zeros, the template's maximum size, a specific `Content-Length`, or its diagnostic headers from production. No live request was made to either diagnostic URL. [Pinned routes](https://github.com/cloudflare/worker-speedtest-template/blob/d9b0c5535594a9527d456e2e8c43198dc78569da/src/index.js#L9), [template caveat](https://github.com/cloudflare/worker-speedtest-template/blob/d9b0c5535594a9527d456e2e8c43198dc78569da/README.md#installation).
+
+## Proposed request and check policy
+
+The following is a Roentgen policy proposal unless a source is explicitly cited.
+
+Both HTTP settings must parse as absolute `https` URLs with a hostname. Reject userinfo and fragments. Preserve valid paths and queries. Use certificate and hostname verification, with no insecure override. Use GET rather than HEAD. Disable redirects and treat every 3xx as endpoint failure; the user can configure the final HTTPS URL. This keeps one observable destination and avoids measuring redirect chains. HTTPS remains mandatory even inside Trojan. Certificate validation follows [HTTP semantics, section 4.3.4](https://www.rfc-editor.org/rfc/rfc9110.html#section-4.3.4).
+
+Use an identifiable Roentgen user agent. Send no cookies, referrer, authentication tokens or result-logging requests. Request `Accept-Encoding: identity`, disable automatic decompression and reject other content codings. Disable application response caching and request `Cache-Control: no-cache, no-store`. Use a fresh diagnostic connection for reproducible inclusion of connection establishment. Do not inherit an environment proxy that can bypass the selected outbound. Bound response headers, buffers and every read under the operation's deadline.
+
+For the default Ping URL, require exactly `200`. Reject a declared nonzero content length. Require end-of-body with zero bytes under the five-second deadline; any delivered body byte is an unexpected-response failure, and the client must abort without draining it. Missing `Content-Length` is acceptable if framing establishes empty completion. A verified TLS handshake or a fast HTTP error alone is not successful Ping.
+
+Measure Ping with a monotonic clock from the start of the proxied operation to final response headers, then publish success only after empty-body validation. Include proxy connection, DNS if needed, TCP/TLS setup and server response delay. Show milliseconds as HTTPS delay. This differs from the official browser client's `requestStart` to `responseStart` timing and must not be presented as ICMP RTT or an equivalent Cloudflare score. Cloudflare describes Ping in terms of response-start timing. [Speed Test methodology](https://speed.cloudflare.com/about#faqs).
+
+For an edited Ping URL, URL-only configuration cannot specify arbitrary expected bodies. The minimal generic policy should accept `200` or `204`, discard at most 4 KiB, and require clean completion within the same deadline. Keep the strict `200`/empty rule for the exact default URL. Larger pages fail with an explanation to choose a small endpoint. This generic check confirms bounded HTTPS success, not a body signature. Supporting configurable expected statuses or body matches would require a separate specification decision.
+
+For the default Speed URL, require `200`, no content coding, and a binary response, expected as `application/octet-stream`. Do not compare payload bytes to zeros. Reject HTML/error responses and HTTP errors rather than report their transfer rate. A completed default response is expected to contain 10,485,760 bytes. If a supplied `Content-Length` contradicts that size, report an unexpected endpoint response. A clean EOF shorter than expected is incomplete, not a completed default test.
+
+For custom Speed URLs, accept `200` with a nonempty body under the same client limits; flag HTML as an endpoint error. Record any known size and whether EOF, the byte limit or the time limit ended the transfer. An early EOF on a genuinely smaller custom resource is valid but may make the sample too short to represent useful throughput.
+
+Treat `Content-Length` as metadata, never as the client cap. A larger declared custom resource can still supply a bounded prefix. An absent length is acceptable with valid streaming framing. A truncated declared body before a deliberate cap or clean completion is a transport failure. Do not send Range by default: a server can ignore it, and `206` has separate partial-response semantics. Reject unsolicited `206` and `Content-Range`; adding range support requires validating the returned range. [HTTP content length](https://www.rfc-editor.org/rfc/rfc9110.html#section-8.6), [Range](https://www.rfc-editor.org/rfc/rfc9110.html#section-14.2), [206](https://www.rfc-editor.org/rfc/rfc9110.html#section-15.3.7).
+
+Stream into a fixed-size scratch buffer. Limit each application read to the remaining byte budget. At the byte limit, deadline or cancellation, abort the response and its transport without draining the remainder or retrying. HTTP libraries, TLS and kernel buffers can read ahead, and packets can already be in flight. The cap therefore bounds consumed response-body bytes, not total link traffic or a billing ceiling. Headers, TLS/Trojan overhead and DNS also consume bytes.
+
+Start the ten-second deadline before connection setup and keep it active throughout body reads. For nonempty successful data, report download rate as `8 * consumed_body_bytes / elapsed_body_seconds`, using a monotonic clock from final headers to the last counted byte or deadline. Also record total duration, bytes and stop reason. A deliberate byte/time stop can yield a bounded sample; zero-byte timeouts, HTTP/protocol errors and user cancellation must not become successful speeds. Results describe this proxy path to this endpoint with one short transfer. No claim of maximum link capacity follows.
+
+## Static URL and editable caps
+
+Save the full Speed URL, including `bytes=10485760`, independently of the two client limits. Do not infer parameter semantics for arbitrary URLs or silently append/replace `bytes`. If the user reduces the cap to 2 MiB, consume at most 2 MiB of the requested 10 MiB body and cancel. If they raise the cap to 20 MiB, the unchanged default URL still finishes at 10 MiB; the cap is a maximum, not a target or promise of a ten-second transfer. Explain that increasing requested payload size requires editing the URL too.
+
+A provider-aware URL template could instead set `bytes` from the configured cap, but it adds a setting/protocol decision and needs size validation. The fixed URL plus independent limits fits the approved Settings fields and is the recommended minimum.
+
+Automatic Ping must never scan every configuration, fall back to direct traffic, or activate host TUN merely to probe while disabled. Prevent overlapping runs and bind each result to its configuration generation. Speed remains manual only. No automatic retry should exceed a probe deadline or Speed budget. Report 429 and honor a valid `Retry-After` as a minimum pause for subsequent scheduled requests, without replacing the nominal 30-second cadence with rapid retries.
+
+## Availability, privacy and use limitations
+
+Cloudflare explicitly provides no SLA for public 1.1.1.1 and limits dedicated support. Its resolver terms incorporate its Website and Online Services Terms and specify attribution for integrating ISPs or network equipment providers. Name Cloudflare as the selected provider; whether Roentgen falls within those attribution categories is not decided here. [Resolver support](https://developers.cloudflare.com/1.1.1.1/infrastructure/sla-and-support/), [resolver terms](https://developers.cloudflare.com/1.1.1.1/terms-of-use/).
+
+The Speed Test footer links the same Website Terms. Those terms allow modification, discontinuation and termination, prohibit overburdening services and circumventing limits, and disclaim reliability warranties. The reviewed sources contain no numeric allowance or express guarantee for perpetual third-party Ping every 30 seconds. Public source code and documented client defaults establish technical suitability; they do not confer an SLA or unrestricted hosted-service permission. Accept provider errors and keep URLs editable. [Speed Test footer](https://speed.cloudflare.com/about), [Website Terms, sections 4, 7 and 10](https://www.cloudflare.com/website-terms/).
+
+The resolver policy allows limited query/debug logs for up to 25 hours, limited APNIC access, retained aggregations, and sampled packet capture of at most 0.05% for troubleshooting and attack mitigation. Do not describe it as "no logging." [Public resolver privacy commitments](https://developers.cloudflare.com/1.1.1.1/privacy/public-dns-resolver/).
+
+Speed Test's privacy notice says Cloudflare receives the connecting IP, derives location and ASN, truncates IP addresses, and shares anonymized measurement information with partners. This is a separate policy from resolver privacy. [Speed Test privacy notice](https://speed.cloudflare.com/). The official client separately posts final measurements to its logging API; Roentgen need not implement that workflow. A raw download request still reaches the provider and is not guaranteed to avoid server-side logging. [Pinned logging implementation](https://github.com/cloudflare/speedtest/blob/7183e970bda21c900e7f4bcf9c5416aa08257e27/src/logging/logFinalResults.ts#L106).
+
+Inference from the required proxy path: Cloudflare normally sees the Trojan exit's source IP, and that exit's route determines the Cloudflare edge reached. DNS names remain visible to the resolver; plaintext DNS beyond the exit is visible on that segment. One provider for both diagnostics creates correlated failure. A failed Ping establishes failure of that check, not failure of every Internet destination.
+
+## Remaining decisions and validation
+
+1. Human approval of Cloudflare as the specific default provider, including acceptance of the public service's availability and use limits.
+2. Accept the fixed Speed URL policy and the generic custom-Ping `200`/`204`, 4 KiB policy, or specify another editable-URL contract before implementation.
+3. Keep the single DNS field at `1.1.1.1`, or explicitly add support for a resolver list. Confirm DNS transport through the installed Xray separately; do not introduce direct fallback.
+4. Later authorized integration work must verify actual production status/body/headers, HTTP cancellation and proxy routing, including disabled mode. Source inspection cannot establish live availability or compatibility with the installed Xray release. No such tests were run here.
+
+Research fetched official documentation, GitHub metadata and source only. It made no resolver query, latency request, speed payload download or live proxy test. Root glossary and ADR directory were absent in this checkout. No implementation or tracker edits were made.