Skip to content

Commit

Permalink
node: rmv hand-rolled doh2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
ignoramous committed Sep 8, 2023
1 parent d2f25c2 commit 78ce42b
Show file tree
Hide file tree
Showing 3 changed files with 2 additions and 100 deletions.
10 changes: 0 additions & 10 deletions src/commons/envutil.js
Original file line number Diff line number Diff line change
Expand Up @@ -308,16 +308,6 @@ export function forceDoh() {
return envManager.get("NODE_DOH_ONLY") || false;
}

export function avoidFetch() {
if (!envManager) return false;

// on other runtimes, continue using fetch
if (!isNode()) return false;

// on node, default to avoiding fetch
return envManager.get("NODE_AVOID_FETCH") || false;
}

export function disableDnsCache() {
// disable when profiling dns resolutions
return profileDnsResolves();
Expand Down
5 changes: 0 additions & 5 deletions src/core/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,6 @@ const defaults = new Map(
// default: "localhost|1e84b3c687,rethinkdns.localhost|c9de656fd9",
default: "", // no auth when empty
},
// avoid using the (slow) fetch polyfill if on nodejs
NODE_AVOID_FETCH: {
type: "boolean",
default: false,
},
// use only doh upstream on nodejs (udp/tcp is the default on nodejs)
NODE_DOH_ONLY: {
type: "boolean",
Expand Down
87 changes: 2 additions & 85 deletions src/plugins/dns-op/resolver.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export default class DNSResolver {
this.blocker = new DnsBlocker();
/** @type {import("../rethinkdns/main.js").BlocklistWrapper} */
this.bw = blocklistWrapper;
this.http2 = null;
this.nodeutil = null;
this.transport = null;
this.log = log.withTags("DnsResolver");
Expand All @@ -35,7 +34,6 @@ export default class DNSResolver {
this.profileResolve = envutil.profileDnsResolves();
// only valid on nodejs
this.forceDoh = envutil.forceDoh();
this.avoidFetch = envutil.avoidFetch();

// only valid on workers
// bg-bw-init results in higher io-wait, not lower
Expand All @@ -51,19 +49,14 @@ export default class DNSResolver {

if (this.profileResolve) {
this.log.w("profiling", this.determineDohResolvers());
this.log.w("doh?", this.forceDoh, "fetch?", this.avoidFetch);
this.log.w("doh?", this.forceDoh);
}
}

async lazyInit() {
if (!envutil.hasDynamicImports()) return;

const isnode = envutil.isNode();
const plainOldDnsIp = dnsutil.dnsaddr();
if (isnode && !this.http2) {
this.http2 = await import("node:http2");
this.log.i("imported custom http2 client");
}
if (isnode && !this.nodeutil) {
this.nodeutil = await import("../../core/node/util.js");
this.log.i("imported node-util");
Expand Down Expand Up @@ -441,9 +434,7 @@ DNSResolver.prototype.resolveDnsUpstream = async function (
throw new Error("get/post only");
}
this.log.d(rxid, "upstream doh2/fetch", u.href);
promisedPromises.push(
this.avoidFetch ? this.doh2(rxid, dnsreq) : fetch(dnsreq)
);
promisedPromises.push(fetch(dnsreq));
}
} catch (e) {
this.log.e(rxid, "err doh2/fetch upstream", e.stack);
Expand Down Expand Up @@ -475,77 +466,3 @@ DNSResolver.prototype.resolveDnsFromCache = async function (rxid, packet) {

return Promise.resolve(r);
};

/**
* Resolve DNS request using HTTP/2 API of Node.js
* @param {String} rxid - request id
* @param {Request} request - Request object
* @returns {Promise<Response>}
*/
DNSResolver.prototype.doh2 = async function (rxid, request) {
if (!this.http2 || !this.nodeutil) {
throw new Error("h2 / node-util not setup, bailing");
}

this.log.d(rxid, "upstream with doh2");
const http2 = this.http2;

const u = new URL(request.url); // doh.tld/dns-query/?dns=b64
const verb = request.method; // GET or POST
const path = util.isGetRequest(request)
? u.pathname + u.search // /dns-query/?dns=b64
: u.pathname; // /dns-query
const qab = await request.arrayBuffer(); // empty for GET
const upstreamQuery = bufutil.bufferOf(qab);
const headers = util.copyHeaders(request);

return new Promise((resolve, reject) => {
// TODO: h2 conn re-use: archive.is/XXKwn
// TODO: h2 conn pool
if (!util.isGetRequest(request) && !util.isPostRequest(request)) {
reject(new Error("Only GET/POST requests allowed"));
}

const c = http2.connect(u.origin);

c.on("error", (err) => {
this.log.e(rxid, "conn fail", err.message);
reject(err.message);
});

const req = c.request({
[http2.constants.HTTP2_HEADER_METHOD]: verb,
[http2.constants.HTTP2_HEADER_PATH]: path,
...headers,
});

req.on("response", (headers) => {
const b = [];
req.on("data", (chunk) => {
b.push(chunk);
});
req.on("end", () => {
const rb = bufutil.concatBuf(b);
const h = this.nodeutil.transformPseudoHeaders(headers);
c.close();
resolve(new Response(rb, h));
});
});
// nodejs' async err events go unhandled when the handler
// is not registered, which ends up killing the process
req.on("error", (err) => {
this.log.e(rxid, "send/recv fail", err.message);
reject(err.message);
});

// req.end writes query to upstream over http2.
// do this only after the event-handlers (response,
// on, end, error etc) have been registered (above),
// and not before. Those events aren't resent by
// nodejs; while they may in fact happen immediately
// post a req.write / req.end (for ex: an error if it
// happens pronto, before an event-handler could be
// registered, then the err would simply go unhandled)
req.end(upstreamQuery);
});
};

0 comments on commit 78ce42b

Please sign in to comment.