feat(dns): recommend multiple diverse servers for primary DoH, bootstrap, and fallback DNS

This commit is contained in:
Dushnilin
2026-09-02 18:38:30 +03:00
parent 5f4bfc7caf
commit fd629555c7
2 changed files with 101 additions and 42 deletions
+93 -35
View File
@@ -330,6 +330,51 @@ function test_candidate(server, domains, bootstrap_ips) {
return result; return result;
} }
function select_diverse_servers(candidates, max_count, max_latency, max_loss) {
max_count = int(max_count || 2);
max_latency = int(max_latency || 400);
max_loss = int(max_loss || 25);
let selected = [];
let seen_providers = {};
for (let c in candidates) {
if (c.latency < 0 || c.status == "failed" || c.lossPct > max_loss || c.latency > max_latency)
continue;
let prov = as_string(c.provider);
if (!seen_providers[prov]) {
seen_providers[prov] = true;
push(selected, c);
if (length(selected) >= max_count)
break;
}
}
if (length(selected) < max_count) {
for (let c in candidates) {
if (c.latency < 0 || c.status == "failed" || c.lossPct > max_loss || c.latency > max_latency)
continue;
let addr = as_string(c.address || c.ip);
let already = false;
for (let s in selected) {
if ((s.address || s.ip) == addr) {
already = true;
break;
}
}
if (!already) {
push(selected, c);
if (length(selected) >= max_count)
break;
}
}
}
return selected;
}
function compute_recommendation(results) { function compute_recommendation(results) {
results = array_or_empty(results); results = array_or_empty(results);
let working = []; let working = [];
@@ -342,10 +387,10 @@ function compute_recommendation(results) {
if (length(working) == 0) { if (length(working) == 0) {
return { return {
dns_type: "udp", dns_type: "udp",
dns_server: [ "77.88.8.8" ], dns_server: [ "77.88.8.8", "1.1.1.1" ],
bootstrap_dns_server: [ "77.88.8.8" ], bootstrap_dns_server: [ "77.88.8.8", "1.1.1.1" ],
dns_fallback_server: [ "1.1.1.1" ], dns_fallback_server: [ "1.0.0.1", "77.88.8.1" ],
dns_upstream_mode: "sequential", dns_upstream_mode: "parallel",
reason: "All probed DNS servers timed out or failed. Applied safe Yandex & Cloudflare defaults." reason: "All probed DNS servers timed out or failed. Applied safe Yandex & Cloudflare defaults."
}; };
} }
@@ -363,52 +408,65 @@ function compute_recommendation(results) {
working_udp = sort(working_udp, function(a, b) { return a.score - b.score; }); working_udp = sort(working_udp, function(a, b) { return a.score - b.score; });
working_doh = sort(working_doh, function(a, b) { return a.score - b.score; }); working_doh = sort(working_doh, function(a, b) { return a.score - b.score; });
let fastest_udp = length(working_udp) > 0 ? working_udp[0] : working[0]; // Select top 2 bootstrap UDP servers from distinct providers
let second_udp = null; let top_bootstrap = select_diverse_servers(working_udp, 2, 250, 25);
if (length(working_udp) > 1) { if (length(top_bootstrap) == 0) {
for (let u in working_udp) { top_bootstrap = [ { address: "77.88.8.8", ip: "77.88.8.8", provider: "Yandex", latency: 15 } ];
if (u.provider != fastest_udp.provider) { }
second_udp = u; let bootstrap_ips = [];
for (let b in top_bootstrap)
push(bootstrap_ips, b.ip || b.address);
// Select top 2 fallback UDP servers (prefer servers not in bootstrap or distinct)
let remaining_udp = [];
for (let u in working_udp) {
let in_boot = false;
for (let b in top_bootstrap) {
if (b.address == u.address || b.ip == u.ip) {
in_boot = true;
break; break;
} }
} }
if (second_udp == null) if (!in_boot)
second_udp = working_udp[1]; push(remaining_udp, u);
} }
if (second_udp == null) let top_fallback = select_diverse_servers(remaining_udp, 2, 350, 25);
second_udp = { address: "1.1.1.1", ip: "1.1.1.1", provider: "Cloudflare", latency: 50 }; if (length(top_fallback) == 0) {
top_fallback = select_diverse_servers(working_udp, 2, 350, 50);
let bootstrap_ip = fastest_udp.ip || fastest_udp.address || "77.88.8.8"; }
let fallback_ip = second_udp.ip || second_udp.address || "1.1.1.1"; let fallback_ips = [];
for (let f in top_fallback)
push(fallback_ips, f.ip || f.address);
if (length(fallback_ips) == 0)
fallback_ips = [ "1.0.0.1", "77.88.8.1" ];
let selected_type = "udp"; let selected_type = "udp";
let selected_dns_server = [ fastest_udp.address ]; let selected_dns_server = [];
let reason = "Selected fastest UDP server (" + fastest_udp.provider + " " + fastest_udp.latency + "ms) as fallback because encrypted DoH is unavailable"; let top_udp_primary = select_diverse_servers(working_udp, 2, 200, 25);
for (let u in top_udp_primary)
push(selected_dns_server, u.address || u.ip);
let reason = "Selected fast UDP servers (" + join(", ", selected_dns_server) + ") as fallback because encrypted DoH is unavailable";
// ALWAYS PRIORITIZE ENCRYPTED DoH AS PRIMARY DNS // ALWAYS PRIORITIZE ENCRYPTED DoH AS PRIMARY DNS
// Encrypted DNS prevents ISP interception, DNS hijacking, poisoning, and MITM. // Encrypted DNS prevents ISP interception, DNS hijacking, poisoning, and MITM.
// Bootstrap DNS resolves the DoH hostname, while DoH handles all encrypted user traffic. let top_doh = select_diverse_servers(working_doh, 2, 350, 25);
if (length(working_doh) > 0) { if (length(top_doh) > 0) {
let best_doh = working_doh[0]; selected_type = "doh";
if (best_doh.lossPct <= 25 && best_doh.latency < 350) { selected_dns_server = [];
selected_type = "doh"; let doh_names = [];
selected_dns_server = [ best_doh.address ]; for (let d in top_doh) {
reason = "Selected encrypted DoH (" + best_doh.provider + " " + best_doh.latency + "ms) for maximum privacy and anti-censorship, with " + fastest_udp.provider + " (" + bootstrap_ip + ") bootstrap DNS"; push(selected_dns_server, d.address);
push(doh_names, sprintf("%s (%dms)", d.provider, d.latency));
} }
reason = "Selected multiple encrypted DoH servers [" + join(", ", doh_names) + "] for maximum privacy and redundancy, with [" + join(", ", bootstrap_ips) + "] bootstrap DNS";
} }
let upstream_mode = "sequential";
if (length(working_doh) > 1 && working_doh[0].latency < 70 && working_doh[1].latency < 90)
upstream_mode = "parallel";
else if (fastest_udp.latency < 40 && second_udp.latency < 50)
upstream_mode = "parallel";
return { return {
dns_type: selected_type, dns_type: selected_type,
dns_server: selected_dns_server, dns_server: selected_dns_server,
bootstrap_dns_server: [ bootstrap_ip ], bootstrap_dns_server: bootstrap_ips,
dns_fallback_server: [ fallback_ip ], dns_fallback_server: fallback_ips,
dns_upstream_mode: upstream_mode, dns_upstream_mode: "parallel",
reason: reason reason: reason
}; };
} }
+8 -7
View File
@@ -64,11 +64,12 @@ ucode -L "$TACHYON_LIB" "$WORK_DIR/test_candidates.uc" | grep -q "OK" ||
cat >"$WORK_DIR/test_recommendation.uc" <<'UCODE' cat >"$WORK_DIR/test_recommendation.uc" <<'UCODE'
let benchmark = require("dns.benchmark"); let benchmark = require("dns.benchmark");
// Scenario A: Fast DoH (<85ms, close to UDP) -> Expect DoH recommended // Scenario A: Fast DoH -> Expect DoH recommended with multiple servers
let results_a = [ let results_a = [
{ id: "yandex_udp", provider: "Yandex", type: "udp", address: "77.88.8.8", ip: "77.88.8.8", latency: 15, lossPct: 0, status: "excellent", score: 15 }, { id: "yandex_udp", provider: "Yandex", type: "udp", address: "77.88.8.8", ip: "77.88.8.8", latency: 15, lossPct: 0, status: "excellent", score: 15 },
{ id: "cf_udp", provider: "Cloudflare", type: "udp", address: "1.1.1.1", ip: "1.1.1.1", latency: 20, lossPct: 0, status: "excellent", score: 20 }, { id: "cf_udp", provider: "Cloudflare", type: "udp", address: "1.1.1.1", ip: "1.1.1.1", latency: 20, lossPct: 0, status: "excellent", score: 20 },
{ id: "cf_doh", provider: "Cloudflare", type: "doh", address: "https://cloudflare-dns.com/dns-query", ip: "1.1.1.1", latency: 25, lossPct: 0, status: "excellent", score: 25 } { id: "cf_doh", provider: "Cloudflare", type: "doh", address: "https://cloudflare-dns.com/dns-query", ip: "1.1.1.1", latency: 25, lossPct: 0, status: "excellent", score: 25 },
{ id: "comss_doh", provider: "Comss.one", type: "doh", address: "https://dns.comss.one/dns-query", ip: "92.223.109.31", latency: 30, lossPct: 0, status: "excellent", score: 30 }
]; ];
let rec_a = benchmark.compute_recommendation(results_a); let rec_a = benchmark.compute_recommendation(results_a);
@@ -76,12 +77,12 @@ if (rec_a.dns_type != "doh") {
print("ERR: Scenario A should recommend DoH, got ", rec_a.dns_type, "\n"); print("ERR: Scenario A should recommend DoH, got ", rec_a.dns_type, "\n");
exit(1); exit(1);
} }
if (rec_a.bootstrap_dns_server[0] != "77.88.8.8") { if (length(rec_a.dns_server) < 2) {
print("ERR: Scenario A bootstrap DNS should be fastest UDP (77.88.8.8)\n"); print("ERR: Scenario A should recommend multiple DoH servers\n");
exit(2); exit(2);
} }
if (rec_a.dns_fallback_server[0] != "1.1.1.1") { if (rec_a.bootstrap_dns_server[0] != "77.88.8.8") {
print("ERR: Scenario A fallback DNS should be secondary provider (1.1.1.1)\n"); print("ERR: Scenario A bootstrap DNS should be fastest UDP (77.88.8.8)\n");
exit(3); exit(3);
} }
@@ -101,7 +102,7 @@ if (rec_b.dns_type != "udp" || rec_b.dns_server[0] != "77.88.8.8") {
// Scenario C: All failed -> Expect safe failsafe fallback // Scenario C: All failed -> Expect safe failsafe fallback
let results_c = []; let results_c = [];
let rec_c = benchmark.compute_recommendation(results_c); let rec_c = benchmark.compute_recommendation(results_c);
if (rec_c.dns_type != "udp" || rec_c.dns_server[0] != "77.88.8.8" || rec_c.dns_fallback_server[0] != "1.1.1.1") { if (rec_c.dns_type != "udp" || rec_c.dns_server[0] != "77.88.8.8" || length(rec_c.dns_server) < 2) {
print("ERR: Scenario C failsafe failed\n"); print("ERR: Scenario C failsafe failed\n");
exit(5); exit(5);
} }