From ed77a13c851e8a112837dcddf610c885c3ec1e58 Mon Sep 17 00:00:00 2001 From: hacklab Date: Sat, 10 Oct 2026 15:54:42 +0200 Subject: [PATCH] dns: primero el resolutor del sistema, los publicos de respaldo main.js preguntaba siempre a 8.8.8.8/1.1.1.1. Las VPN que evitan fugas de DNS (Mullvad) y las redes que bloquean DNS externos los rechazan, y entonces no se encontraba ningun pub por nombre: unirse a uno no hacia nada y no decia nada. Ahora va primero getaddrinfo, que respeta la VPN y el DNS privado de Android; a los 5 s, o si falla, tambien los publicos. Probado en Android 15 detras de Mullvad: antes no resolvia hacklab.laenre.net y ahora si. --- main.js | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/main.js b/main.js index e2d4675..c174b81 100644 --- a/main.js +++ b/main.js @@ -26,6 +26,8 @@ try { const dns = require('dns'); const net = require('net'); const servers = ['8.8.8.8', '1.1.1.1', '8.8.4.4']; + const systemLookup = dns.lookup; + const SYSTEM_LOOKUP_MS = 5000; try { dns.setServers(servers); } catch (e) {} try { if (dns.promises && dns.promises.setServers) dns.promises.setServers(servers); } catch (e) {} @@ -48,11 +50,43 @@ try { ? callback(null, [direct]) : callback(null, direct.address, direct.family)); } - const resolver = family === 6 ? dns.resolve6 : dns.resolve4; - resolver.call(dns, hostname, (err, addrs) => { - if (err || !addrs || !addrs.length) return callback(err || new Error('ENOTFOUND ' + hostname)); - if (options.all) return callback(null, addrs.map((a) => ({ address: a, family }))); - return callback(null, addrs[0], family); + // rama movil: primero el resolutor del sistema (getaddrinfo), que es el que + // respeta la VPN y el DNS privado de Android. Upstream iba siempre a + // 8.8.8.8/1.1.1.1, y las VPN que evitan fugas de DNS (Mullvad, por ejemplo) + // o las redes que bloquean DNS externos los rechazan: no se encontraba + // ningun pub por nombre y unirse a uno "no hacia nada". Los publicos quedan + // de respaldo, para los moviles donde getaddrinfo no contesta. + // Los dos caminos compiten: el del sistema sale ya y, si en SYSTEM_LOOKUP_MS + // no ha contestado o falla, se pregunta tambien a los publicos. Gana la primera + // respuesta buena; si fallan los dos, se devuelve el error del sistema, que + // dice mas ("no existe") que el de unos servidores quiza bloqueados. + let done = false, sysErr = null, pubErr = null, sysDone = false, pubDone = false, pubStarted = false; + const finish = (err, address, fam) => { + if (done) return; + done = true; + clearTimeout(timer); + if (err) return callback(err); + if (options.all) return callback(null, Array.isArray(address) ? address : [{ address, family: fam }]); + if (Array.isArray(address)) return callback(null, address[0].address, address[0].family); + return callback(null, address, fam); + }; + const bothFailed = () => { if (sysDone && pubDone) finish(sysErr || pubErr || new Error('ENOTFOUND ' + hostname)); }; + const viaPublic = () => { + if (pubStarted) return; + pubStarted = true; + const resolver = family === 6 ? dns.resolve6 : dns.resolve4; + resolver.call(dns, hostname, (err, addrs) => { + pubDone = true; + if (err || !addrs || !addrs.length) { pubErr = err || new Error('ENOTFOUND ' + hostname); return bothFailed(); } + finish(null, options.all ? addrs.map((x) => ({ address: x, family })) : addrs[0], family); + }); + }; + const timer = setTimeout(viaPublic, SYSTEM_LOOKUP_MS); + systemLookup.call(dns, hostname, { family, all: !!options.all }, (err, address, fam) => { + sysDone = true; + if (!err) return finish(null, address, fam); + sysErr = err; + if (pubStarted) bothFailed(); else viaPublic(); }); };