#!/usr/bin/env ucode let fs = require("fs"); let common = require("core.common"); let uci_core = require("core.uci"); let as_string = common.as_string; let read_json_file = common.read_json_file; 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 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; const CONFIG_NAME = getenv("TACHYON_CONFIG_NAME") || "tachyon"; const LIB_DIR = getenv("TACHYON_LIB") || "/usr/lib/tachyon"; const STATE_DIR = getenv("TACHYON_UI_STATE_DIR") || "/var/run/tachyon"; const BENCHMARK_STATE_FILE = STATE_DIR + "/dns-benchmark-state.json"; const BENCHMARK_PID_FILE = STATE_DIR + "/dns-benchmark.pid"; const SERVICE_INIT = getenv("TACHYON_SERVICE_INIT") || "/etc/init.d/tachyon"; 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" }, // --- Cloudflare DNS --- { id: "cloudflare_udp", provider: "Cloudflare", type: "udp", address: "1.1.1.1", ip: "1.1.1.1", tag: "Primary" }, { id: "cloudflare_udp2", provider: "Cloudflare", type: "udp", address: "1.0.0.1", ip: "1.0.0.1", tag: "Secondary" }, { id: "cloudflare_doh", provider: "Cloudflare", type: "doh", address: "https://cloudflare-dns.com/dns-query", ip: "1.1.1.1", tag: "DoH Encrypted" }, // --- Google Public DNS --- { id: "google_udp", provider: "Google", type: "udp", address: "8.8.8.8", ip: "8.8.8.8", tag: "Primary" }, { id: "google_udp2", provider: "Google", type: "udp", address: "8.8.4.4", ip: "8.8.4.4", tag: "Secondary" }, { id: "google_doh", provider: "Google", type: "doh", address: "https://dns.google/dns-query", ip: "8.8.8.8", tag: "DoH Encrypted" }, // --- AdGuard DNS --- { id: "adguard_udp", provider: "AdGuard", type: "udp", address: "94.140.14.14", ip: "94.140.14.14", tag: "Default" }, { id: "adguard_doh", provider: "AdGuard", type: "doh", address: "https://dns.adguard-dns.com/dns-query", ip: "94.140.14.14", tag: "DoH Encrypted" }, // --- Comss.one DNS --- { id: "comss_udp", provider: "Comss.one", type: "udp", address: "92.223.109.31", ip: "92.223.109.31", tag: "Anti-Censorship" }, { id: "comss_doh", provider: "Comss.one", type: "doh", address: "https://dns.comss.one/dns-query", ip: "92.223.109.31", tag: "DoH Anti-Censorship" }, // --- Control D --- { id: "controld_udp", provider: "Control D", type: "udp", address: "76.76.2.0", ip: "76.76.2.0", tag: "Unfiltered" }, { id: "controld_doh", provider: "Control D", type: "doh", address: "https://freedns.controld.com/p0", ip: "76.76.2.0", tag: "DoH Encrypted" }, // --- Quad9 --- { id: "quad9_udp", provider: "Quad9", type: "udp", address: "9.9.9.9", ip: "9.9.9.9", tag: "Primary" }, // --- Mullvad DNS --- { id: "mullvad_udp", provider: "Mullvad", type: "udp", address: "194.242.2.2", ip: "194.242.2.2", tag: "Privacy" } ]; const TEST_DOMAINS = [ "google.com", "yandex.ru", "cloudflare.com", "wikipedia.org" ]; function now_seconds() { let stamp = clock(); return stamp ? stamp[0] : 0; } function has_tool(name) { let out = command_output_from_args([ "which", as_string(name) ]); return length(out) > 0; } function url_host(url) { let m = match(as_string(url), /^https?:\/\/([^\/:]+)/); return m ? m[1] : ""; } function domain_to_doh_b64(domain) { domain = trim(as_string(domain)); if (domain == "google.com") return "AAABAAABAAAAAAAABmdvb2dsZQNjb20AAAEAAQ"; if (domain == "cloudflare.com") return "AAABAAABAAAAAAAACmNsb3VkZmxhcmUDY29tAAABAAE"; if (domain == "wikipedia.org") return "AAABAAABAAAAAAAACXdpa2lwZWRpYQNvcmcAAAEAAQ"; if (domain == "yandex.ru") return "AAABAAABAAAAAAAABnlhbmRleAJydQAAAQAB"; if (domain == "example.com") return "AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE"; let labels = split(replace(domain, /^\.+|\.+$/, ""), "."); let bytes = [ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 ]; for (let label in labels) { if (label == "") continue; push(bytes, length(label)); for (let i = 0; i < length(label); i++) push(bytes, ord(label, i)); } push(bytes, 0, 0, 1, 0, 1); let b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; let res = ""; let i = 0; while (i < length(bytes)) { let b0 = bytes[i]; let b1 = i + 1 < length(bytes) ? bytes[i + 1] : 0; let b2 = i + 2 < length(bytes) ? bytes[i + 2] : 0; let c0 = (b0 >> 2) & 0x3f; let c1 = (((b0 & 0x03) << 4) | ((b1 >> 4) & 0x0f)) & 0x3f; let c2 = (((b1 & 0x0f) << 2) | ((b2 >> 6) & 0x03)) & 0x3f; let c3 = b2 & 0x3f; res += substr(b64chars, c0, 1); res += substr(b64chars, c1, 1); if (i + 1 < length(bytes)) res += substr(b64chars, c2, 1); if (i + 2 < length(bytes)) res += substr(b64chars, c3, 1); i += 3; } return res; } // Probes a UDP DNS server with `dig` (primary) or `nslookup` (fallback). // Returns latency in milliseconds, or -1 on failure. function probe_udp(server_ip, domain) { server_ip = as_string(server_ip); domain = as_string(domain); if (has_tool("dig")) { let output = command_output_from_args([ "dig", "@" + server_ip, domain, "A", "+time=2", "+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) { let ms = int(m[1]); return ms >= 0 ? ms : 0; } } } } // Fallback using nslookup & timestamp let t0 = clock(); let status = command_status_from_args([ "nslookup", domain, server_ip ]); let t1 = clock(); if (status == 0 && t0 && t1) { let elapsed_ms = (t1[0] - t0[0]) * 1000 + int((t1[1] - t0[1]) / 1000000); return elapsed_ms >= 0 ? elapsed_ms : 0; } return -1; } // Probes a DoH DNS server using `curl` with standard RFC 8484 DNS wireformat and direct IP resolving. // Returns latency in milliseconds, or -1 on failure. function probe_doh(server, domain) { let doh_url = as_string(type(server) == "object" ? server.address : server); domain = as_string(domain); let ip = as_string(type(server) == "object" ? (server.ip || "") : ""); let host = url_host(doh_url); 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}", "-H", "accept: application/dns-message, application/dns-json" ]; // Directly resolve host to the provider IP to test DoH over direct UDP bootstrap without local DNS dependency if (host != "" && ip != "") { push(args, "--resolve", host + ":443:" + ip); push(args, "--resolve", host + ":80:" + ip); } push(args, query_url); let output = command_output_from_args(args); if (length(output) > 0) { let lines = split(output, "\n"); let last_line = length(lines) > 0 ? lines[length(lines) - 1] : ""; if (last_line == "" && length(lines) > 1) last_line = lines[length(lines) - 2]; let m = match(last_line, /^([0-9]{3})[ \t]+([0-9.]+)/); if (m && m[1] == "200" && m[2] != null) { let total_sec = double(m[2]); let ms = int(total_sec * 1000); return ms >= 0 ? ms : 0; } } return -1; } function probe_server(server, domain) { if (server.type == "doh") return probe_doh(server, domain); return probe_udp(server.ip || server.address, domain); } function test_candidate(server, domains) { domains = array_or_empty(domains); let total_ms = 0; let success_count = 0; let total_rounds = length(domains); for (let domain in domains) { let ms = probe_server(server, domain); if (ms >= 0) { total_ms += ms; success_count++; } } let result = { id: server.id, provider: server.provider, type: server.type, address: server.address, ip: server.ip, tag: server.tag, latency: -1, lossPct: 100, status: "failed", score: 99999 }; if (success_count > 0) { let avg_latency = int(total_ms / success_count); let loss_pct = int(((total_rounds - success_count) * 100) / total_rounds); let score = avg_latency + (loss_pct * 5); result.latency = avg_latency; result.lossPct = loss_pct; result.score = score; if (avg_latency < 35 && loss_pct == 0) result.status = "excellent"; else if (avg_latency < 75 && loss_pct <= 25) result.status = "good"; else if (avg_latency < 150 && loss_pct <= 50) result.status = "fair"; else if (loss_pct < 100) result.status = "slow"; else result.status = "failed"; } return result; } function compute_recommendation(results) { results = array_or_empty(results); let working = []; for (let r in results) { if (r.latency >= 0 && r.status != "failed") push(working, r); } // Default failsafe recommendation if (length(working) == 0) { return { dns_type: "udp", dns_server: [ "77.88.8.8" ], bootstrap_dns_server: [ "77.88.8.8" ], dns_fallback_server: [ "1.1.1.1" ], dns_upstream_mode: "sequential", reason: "All probed DNS servers timed out or failed. Applied safe Yandex & Cloudflare defaults." }; } // Find fastest UDP and fastest DoH let fastest_udp = null; let second_udp = null; let fastest_doh = null; for (let r in working) { if (r.type == "udp") { if (fastest_udp == null) fastest_udp = r; else if (second_udp == null && r.provider != fastest_udp.provider) second_udp = r; } else if (r.type == "doh") { if (fastest_doh == null) fastest_doh = r; } } if (fastest_udp == null && length(working) > 0) fastest_udp = working[0]; if (second_udp == null) { for (let r in working) { if (r.type == "udp" && r.id != fastest_udp.id) { second_udp = r; break; } } } if (second_udp == null) second_udp = { address: "1.1.1.1", ip: "1.1.1.1", provider: "Cloudflare" }; // Choose Primary DNS: // Prefer DoH if latency is good (< 85ms and <= 1.6x of fastest UDP) for security & anti-hijacking let selected_type = "udp"; let selected_dns_server = [ fastest_udp.address ]; let reason = "Selected fastest UDP server (" + fastest_udp.provider + " " + fastest_udp.latency + "ms)"; if (fastest_doh != null && fastest_doh.latency <= 85) { let udp_lat = fastest_udp ? fastest_udp.latency : 100; if (fastest_doh.latency <= (udp_lat * 1.6) + 15) { selected_type = "doh"; selected_dns_server = [ fastest_doh.address ]; reason = "Selected fast encrypted DoH (" + fastest_doh.provider + " " + fastest_doh.latency + "ms) for maximum privacy and anti-censorship"; } } 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 upstream_mode = "sequential"; if (fastest_udp.latency < 50 && second_udp.latency < 60) upstream_mode = "parallel"; return { dns_type: selected_type, dns_server: selected_dns_server, bootstrap_dns_server: [ bootstrap_ip ], dns_fallback_server: [ fallback_ip ], dns_upstream_mode: upstream_mode, reason: reason }; } function run_benchmark(on_progress) { let results = []; let total = length(CANDIDATE_SERVERS); for (let i = 0; i < total; i++) { let server = CANDIDATE_SERVERS[i]; if (on_progress) on_progress(i, total, server.provider + " (" + server.type + ")", null); let res = test_candidate(server, TEST_DOMAINS); push(results, res); if (on_progress) on_progress(i + 1, total, server.provider + " (" + server.type + ")", res); } // Sort by score ascending (lowest score is best) results = sort(results, function(a, b) { return a.score - b.score; }); let recommendation = compute_recommendation(results); return { results: results, recommendation: recommendation }; } function apply_recommendation(rec) { if (!rec || type(rec) != "object") return false; let cursor = uci_core.cursor(); if (!cursor) return false; if (rec.dns_type) cursor.set(CONFIG_NAME, "settings", "dns_type", as_string(rec.dns_type)); if (rec.dns_server) cursor.set(CONFIG_NAME, "settings", "dns_server", rec.dns_server); if (rec.bootstrap_dns_server) cursor.set(CONFIG_NAME, "settings", "bootstrap_dns_server", rec.bootstrap_dns_server); if (rec.dns_fallback_server) cursor.set(CONFIG_NAME, "settings", "dns_fallback_server", rec.dns_fallback_server); if (rec.dns_upstream_mode) cursor.set(CONFIG_NAME, "settings", "dns_upstream_mode", as_string(rec.dns_upstream_mode)); cursor.commit(CONFIG_NAME); // Restart tachyon service to apply immediately command_success_from_args([ SERVICE_INIT, "restart" ]); return true; } // --- CLI Output Helpers --- function print_cli_table(benchmark_data) { let results = benchmark_data.results; let rec = benchmark_data.recommendation; print("\n========================================================================================\n"); print(" TACHYON DNS BENCHMARK RESULTS \n"); print("========================================================================================\n"); printf("%-14s | %-6s | %-42s | %-8s | %-6s | %-10s\n", "Provider", "Type", "Address", "Latency", "Loss", "Rating"); print("----------------------------------------------------------------------------------------\n"); for (let r in results) { let lat_str = r.latency >= 0 ? sprintf("%d ms", r.latency) : "TIMEOUT"; let loss_str = sprintf("%d%%", r.lossPct); let rating = r.status == "excellent" ? "EXCELLENT" : r.status == "good" ? "GOOD" : r.status == "fair" ? "FAIR" : r.status == "slow" ? "SLOW" : "FAILED"; printf("%-14s | %-6s | %-42s | %-8s | %-6s | %-10s\n", substr(r.provider, 0, 14), r.type, substr(r.address, 0, 42), lat_str, loss_str, rating ); } print("========================================================================================\n\n"); print("⚡ RECOMMENDED TACHYON DNS CONFIGURATION:\n"); print(" • DNS Type: ", rec.dns_type, "\n"); print(" • Primary DNS: ", join(", ", rec.dns_server), "\n"); print(" • Bootstrap DNS: ", join(", ", rec.bootstrap_dns_server), "\n"); print(" • Fallback DNS: ", join(", ", rec.dns_fallback_server), "\n"); print(" • Upstream Mode: ", rec.dns_upstream_mode, "\n"); print(" • Analysis: ", rec.reason, "\n\n"); } // --- Background / UI Async Engine --- function write_state(state) { command_success_from_args([ "mkdir", "-p", STATE_DIR ]); return write_json_file(BENCHMARK_STATE_FILE, state); } function read_state() { let data = read_json_file(BENCHMARK_STATE_FILE); return type(data) == "object" ? data : null; } function start_async() { let existing = read_state(); if (existing && existing.running === true) { let age = now_seconds() - (existing.started_at || 0); if (age < 90) { print(sprintf("%J\n", { success: true, message: "DNS benchmark is already running", state: existing })); return 0; } } let initial_state = { running: true, progress: 0, current_server: "Starting benchmark...", results: [], recommendation: null, error: null, started_at: now_seconds(), finished_at: null }; write_state(initial_state); // Fork async background worker let worker_cmd = sprintf("TACHYON_LIB=%s ucode -L %s %s/dns/benchmark.uc worker >/dev/null 2>&1 & echo $!", shell_quote(LIB_DIR), shell_quote(LIB_DIR), LIB_DIR); let pipe = fs.popen(worker_cmd, "r"); if (pipe) { let pid = trim(as_string(pipe.read("all"))); pipe.close(); if (pid != "") fs.writefile(BENCHMARK_PID_FILE, pid); } print(sprintf("%J\n", { success: true, message: "DNS benchmark started", running: true })); return 0; } function run_worker() { let state = { running: true, progress: 0, current_server: "Initializing...", results: [], recommendation: null, error: null, started_at: now_seconds(), finished_at: null }; write_state(state); let benchmark_data = run_benchmark(function(completed, total, current_name, latest_result) { state.progress = int((completed * 100) / total); state.current_server = current_name; if (latest_result) push(state.results, latest_result); write_state(state); }); state.running = false; state.progress = 100; state.current_server = "Completed"; state.results = benchmark_data.results; state.recommendation = benchmark_data.recommendation; state.finished_at = now_seconds(); write_state(state); try { fs.unlink(BENCHMARK_PID_FILE); } catch(e) {} return 0; } function stop_benchmark() { let pid_str = fs.readfile(BENCHMARK_PID_FILE); if (pid_str) { let pid = int(trim(as_string(pid_str))); if (pid > 0) command_status_from_args([ "kill", "-9", as_string(pid) ]); try { fs.unlink(BENCHMARK_PID_FILE); } catch(e) {} } let state = read_state() || {}; state.running = false; state.error = "Benchmark stopped by user"; state.finished_at = now_seconds(); write_state(state); print(sprintf("%J\n", { success: true, message: "Benchmark stopped" })); return 0; } function get_status() { let state = read_state(); if (!state) { state = { running: false, progress: 0, current_server: "", results: [], recommendation: null, error: null, started_at: 0, finished_at: null }; } print(sprintf("%J\n", state)); return 0; } function apply_from_state() { let state = read_state(); if (!state || !state.recommendation) { print(sprintf("%J\n", { success: false, error: "No benchmark recommendation available to apply" })); return 1; } let ok = apply_recommendation(state.recommendation); if (ok) print(sprintf("%J\n", { success: true, message: "Recommended DNS configuration applied and service restarted", recommendation: state.recommendation })); else print(sprintf("%J\n", { success: false, error: "Failed to apply DNS configuration to UCI" })); return ok ? 0 : 1; } // --- CLI Dispatcher --- let mode = ARGV[0] || ""; if (mode == "benchmark") { let json_mode = (ARGV[1] == "--json"); let data = run_benchmark(null); if (json_mode) print(sprintf("%J\n", data)); else print_cli_table(data); exit(0); } else if (mode == "autotune") { let apply_flag = (ARGV[1] == "--apply" || ARGV[1] == "-a"); let data = run_benchmark(null); print_cli_table(data); if (apply_flag) { print("Applying recommended DNS configuration...\n"); if (apply_recommendation(data.recommendation)) print("✓ Settings saved to /etc/config/tachyon and service restarted successfully.\n"); else print("✗ Failed to apply settings.\n"); } else { print("Tip: Run `tachyon dns_autotune --apply` to automatically save and activate these settings.\n"); } exit(0); } else if (mode == "benchmark_async" || mode == "benchmark-async") { exit(start_async()); } else if (mode == "worker") { exit(run_worker()); } else if (mode == "benchmark_status" || mode == "benchmark-status") { exit(get_status()); } else if (mode == "benchmark_stop" || mode == "benchmark-stop") { exit(stop_benchmark()); } else if (mode == "benchmark_apply" || mode == "benchmark-apply") { exit(apply_from_state()); } return { CANDIDATE_SERVERS, TEST_DOMAINS, probe_udp, probe_doh, test_candidate, compute_recommendation, run_benchmark, apply_recommendation };