fix: use direct IP for DoH resolver to avoid DNS recursion
Browse files- dns-fix.js +32 -23
dns-fix.js
CHANGED
|
@@ -25,30 +25,39 @@ function dohResolve(hostname, callback) {
|
|
| 25 |
return callback(null, cached.ip);
|
| 26 |
}
|
| 27 |
|
| 28 |
-
|
| 29 |
-
const
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
callback(
|
| 46 |
-
} catch (e) {
|
| 47 |
-
callback(new Error(`DoH parse error: ${e.message}`));
|
| 48 |
}
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
req.on("error", (e) => callback(new Error(`DoH request failed: ${e.message}`)));
|
| 53 |
req.on("timeout", () => {
|
| 54 |
req.destroy();
|
|
|
|
| 25 |
return callback(null, cached.ip);
|
| 26 |
}
|
| 27 |
|
| 28 |
+
// Use Cloudflare DNS-over-HTTPS via direct IP to avoid DNS lookup for the resolver itself
|
| 29 |
+
const options = {
|
| 30 |
+
hostname: "1.1.1.1",
|
| 31 |
+
port: 443,
|
| 32 |
+
path: `/dns-query?name=${encodeURIComponent(hostname)}&type=A`,
|
| 33 |
+
method: "GET",
|
| 34 |
+
headers: { Accept: "application/dns-json" },
|
| 35 |
+
timeout: 10000,
|
| 36 |
+
servername: "cloudflare-dns.com", // Set SNI
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
+
const req = https.get(options, (res) => {
|
| 40 |
+
let body = "";
|
| 41 |
+
res.on("data", (c) => (body += c));
|
| 42 |
+
res.on("end", () => {
|
| 43 |
+
try {
|
| 44 |
+
if (res.statusCode !== 200) {
|
| 45 |
+
return callback(new Error(`DoH: server returned status ${res.statusCode}`));
|
|
|
|
|
|
|
| 46 |
}
|
| 47 |
+
const data = JSON.parse(body);
|
| 48 |
+
const aRecords = (data.Answer || []).filter((a) => a.type === 1);
|
| 49 |
+
if (aRecords.length === 0) {
|
| 50 |
+
return callback(new Error(`DoH: no A record for ${hostname}`));
|
| 51 |
+
}
|
| 52 |
+
const ip = aRecords[0].data;
|
| 53 |
+
const ttl = Math.max((aRecords[0].TTL || 300) * 1000, 60000);
|
| 54 |
+
runtimeCache.set(hostname, { ip, expiry: Date.now() + ttl });
|
| 55 |
+
callback(null, ip);
|
| 56 |
+
} catch (e) {
|
| 57 |
+
callback(new Error(`DoH parse error: ${e.message}`));
|
| 58 |
+
}
|
| 59 |
+
});
|
| 60 |
+
});
|
| 61 |
req.on("error", (e) => callback(new Error(`DoH request failed: ${e.message}`)));
|
| 62 |
req.on("timeout", () => {
|
| 63 |
req.destroy();
|