fix(dns): optimize benchmark probing with host caching and strict timeouts

This commit is contained in:
Dushnilin
2026-09-02 18:19:37 +03:00
parent de691c61ab
commit 5f4bfc7caf
+64 -45
View File
@@ -10,11 +10,13 @@ let write_json_file = common.write_json_file;
let command_output_from_args = common.command_output_from_args;
let command_status_from_args = common.command_status_from_args;
let command_success_from_args = common.command_success_from_args;
let command_from_args = common.command_from_args;
let shell_quote = common.shell_quote;
let object_or_empty = common.object_or_empty;
let array_or_empty = common.array_or_empty;
let option = common.option;
let list_option = common.list_option;
let normalize_status = common.normalize_status;
const CONFIG_NAME = getenv("TACHYON_CONFIG_NAME") || "tachyon";
const LIB_DIR = getenv("TACHYON_LIB") || "/usr/lib/tachyon";
@@ -27,7 +29,6 @@ const CANDIDATE_SERVERS = [
// --- Yandex DNS ---
{ id: "yandex_udp", provider: "Yandex", type: "udp", address: "77.88.8.8", ip: "77.88.8.8", tag: "Primary" },
{ id: "yandex_udp2", provider: "Yandex", type: "udp", address: "77.88.8.1", ip: "77.88.8.1", tag: "Secondary" },
{ id: "yandex_doh", provider: "Yandex", type: "doh", address: "https://common.dot.yandex.net/dns-query", ip: "77.88.8.8", tag: "DoH Basic" },
// --- Cloudflare DNS ---
{ id: "cloudflare_udp", provider: "Cloudflare", type: "udp", address: "1.1.1.1", ip: "1.1.1.1", tag: "Primary" },
@@ -66,9 +67,7 @@ const CANDIDATE_SERVERS = [
const TEST_DOMAINS = [
"google.com",
"yandex.ru",
"cloudflare.com",
"wikipedia.org"
"yandex.ru"
];
function now_seconds() {
@@ -128,39 +127,59 @@ function domain_to_doh_b64(domain) {
return res;
}
// Resolves a hostname via a specific bootstrap UDP server.
function resolve_host_via_bootstrap(host, bootstrap_ip) {
let resolved_hosts_cache = {};
// Resolves a hostname via a specific bootstrap UDP server with cache and fast fallback.
function resolve_host_via_bootstrap(host, bootstrap_ip, fallback_ip) {
host = as_string(host);
bootstrap_ip = as_string(bootstrap_ip);
fallback_ip = as_string(fallback_ip);
if (match(host, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/))
return host;
let cache_key = host + "@" + bootstrap_ip;
if (resolved_hosts_cache[cache_key])
return resolved_hosts_cache[cache_key];
if (has_tool("dig")) {
let output = command_output_from_args([
"dig", "@" + bootstrap_ip, host, "A", "+short", "+time=2", "+tries=1"
"dig", "@" + bootstrap_ip, host, "A", "+short", "+time=1", "+tries=1"
]);
if (length(output) > 0) {
let lines = split(output, "\n");
for (let line in lines) {
line = trim(line);
if (match(line, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/))
if (match(line, /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/)) {
resolved_hosts_cache[cache_key] = line;
return line;
}
}
}
}
let output = command_output_from_args([ "nslookup", host, bootstrap_ip ]);
if (length(output) > 0) {
let lines = split(output, "\n");
for (let line in lines) {
let m = match(line, /Address(?:es)?:[ \t]+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/);
if (m && m[1] != null && m[1] != bootstrap_ip)
return m[1];
if (has_tool("nslookup")) {
let output = command_output_from_args([ "nslookup", host, bootstrap_ip ]);
if (length(output) > 0) {
let lines = split(output, "\n");
for (let line in lines) {
let m = match(line, /Address(?:es)?(?:[ \t]+[0-9]+)?:[ \t]+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/);
if (m && m[1] != null && m[1] != bootstrap_ip) {
resolved_hosts_cache[cache_key] = m[1];
return m[1];
}
}
let m2 = match(output, /Name:[ \t]+[^\n]+\nAddress(?:[ \t]+[0-9]+)?:[ \t]+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/);
if (m2 && m2[1] != null && m2[1] != bootstrap_ip) {
resolved_hosts_cache[cache_key] = m2[1];
return m2[1];
}
}
let m2 = match(output, /Name:[ \t]+[^\n]+\nAddress:[ \t]+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)/);
if (m2 && m2[1] != null)
return m2[1];
}
if (fallback_ip != "") {
resolved_hosts_cache[cache_key] = fallback_ip;
return fallback_ip;
}
return null;
@@ -174,10 +193,9 @@ function probe_udp(server_ip, domain) {
if (has_tool("dig")) {
let output = command_output_from_args([
"dig", "@" + server_ip, domain, "A", "+time=2", "+tries=1", "+stats"
"dig", "@" + server_ip, domain, "A", "+time=1", "+tries=1", "+stats"
]);
if (length(output) > 0) {
// Check for valid response status
if (index(output, "status: NOERROR") >= 0 || index(output, "status: NXDOMAIN") >= 0) {
let m = match(output, /;; Query time:[ \t]+([0-9]+)[ \t]+msec/);
if (m && m[1] != null) {
@@ -200,33 +218,19 @@ function probe_udp(server_ip, domain) {
return -1;
}
// Probes a DoH DNS server using `curl` with standard RFC 8484 DNS wireformat and bootstrap IP resolving.
// Probes a DoH DNS server using `curl` with standard RFC 8484 DNS wireformat.
// Returns latency in milliseconds, or -1 on failure.
function probe_doh(server, domain, bootstrap_ips) {
function probe_doh(server, domain, resolved_ip) {
let doh_url = as_string(type(server) == "object" ? server.address : server);
domain = as_string(domain);
let fallback_ip = as_string(type(server) == "object" ? (server.ip || "") : "");
let host = url_host(doh_url);
// Resolve DoH host using verified bootstrap DNS servers (cascade)
let resolved_ip = null;
bootstrap_ips = array_or_empty(bootstrap_ips);
for (let b_ip in bootstrap_ips) {
b_ip = as_string(b_ip);
if (b_ip != "") {
resolved_ip = resolve_host_via_bootstrap(host, b_ip);
if (resolved_ip != null)
break;
}
}
if (resolved_ip == null)
resolved_ip = fallback_ip;
resolved_ip = as_string(resolved_ip);
let b64 = domain_to_doh_b64(domain);
let query_url = doh_url + (index(doh_url, "?") >= 0 ? "&" : "?") + "dns=" + b64;
let args = [
"curl", "-s", "-k", "-m", "3", "-w", "\n%{http_code} %{time_total}",
"curl", "-s", "-k", "-m", "2", "--connect-timeout", "2", "-w", "\n%{http_code} %{time_total}",
"-H", "accept: application/dns-message, application/dns-json"
];
@@ -254,20 +258,35 @@ function probe_doh(server, domain, bootstrap_ips) {
return -1;
}
function probe_server(server, domain, bootstrap_ips) {
if (server.type == "doh")
return probe_doh(server, domain, bootstrap_ips);
return probe_udp(server.ip || server.address, domain);
}
function test_candidate(server, domains, bootstrap_ips) {
domains = array_or_empty(domains);
let total_ms = 0;
let success_count = 0;
let total_rounds = length(domains);
let resolved_ip = "";
if (server.type == "doh") {
let host = url_host(server.address);
bootstrap_ips = array_or_empty(bootstrap_ips);
for (let b_ip in bootstrap_ips) {
b_ip = as_string(b_ip);
if (b_ip != "") {
resolved_ip = resolve_host_via_bootstrap(host, b_ip, server.ip || "");
if (resolved_ip != null && resolved_ip != "")
break;
}
}
if (resolved_ip == "" || resolved_ip == null)
resolved_ip = as_string(server.ip || "");
}
for (let domain in domains) {
let ms = probe_server(server, domain, bootstrap_ips);
let ms = -1;
if (server.type == "doh")
ms = probe_doh(server, domain, resolved_ip);
else
ms = probe_udp(server.ip || server.address, domain);
if (ms >= 0) {
total_ms += ms;
success_count++;