1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/* globals require, __dirname, global, Buffer, process */
const fs = require("fs");
const options = {
key: fs.readFileSync(__dirname + "/http2-cert.key.pem"),
cert: fs.readFileSync(__dirname + "/http2-cert.pem"),
};
const http2 = require("http2");
const http = require("http");
const url = require("url");
const path = require("path");
let dnsPacket;
let libPath = path.join(__dirname, "../../xpcshell/dns-packet");
if (fs.existsSync(libPath)) {
// This is the path of dns-packet when running mochitest locally.
dnsPacket = require(libPath);
} else {
// This path is for running mochitest on try.
dnsPacket = require(path.join(__dirname, "./dns_packet"));
}
let serverPort = parseInt(process.argv[2].split("=")[1]);
let listeningPort = parseInt(process.argv[3].split("=")[1]);
let server = http2.createSecureServer(
options,
function handleRequest(req, res) {
let u = "";
if (req.url != undefined) {
u = url.parse(req.url, true);
}
if (u.pathname === "/dns-query") {
let payload = Buffer.from("");
req.on("data", function receiveData(chunk) {
payload = Buffer.concat([payload, chunk]);
});
req.on("end", function finishedData() {
let packet = dnsPacket.decode(payload);
let answers = [];
// Return the HTTPS RR to let Firefox connect to the HTTP/3 server
if (packet.questions[0].type === "HTTPS") {
answers.push({
name: packet.questions[0].name,
type: "HTTPS",
ttl: 55,
class: "IN",
flush: false,
data: {
priority: 1,
name: packet.questions[0].name,
values: [
{ key: "alpn", value: ["h3"] },
{ key: "port", value: serverPort },
],
},
});
} else if (packet.questions[0].type === "A") {
answers.push({
name: packet.questions[0].name,
type: "A",
ttl: 55,
flush: false,
data: "127.0.0.1",
});
}
let buf = dnsPacket.encode({
type: "response",
id: packet.id,
flags: dnsPacket.RECURSION_DESIRED,
questions: packet.questions,
answers,
});
res.setHeader("Content-Type", "application/dns-message");
res.setHeader("Content-Length", buf.length);
res.writeHead(200);
res.write(buf);
res.end("");
});
}
}
);
server.listen(listeningPort);
console.log(`DoH server listening on ports ${server.address().port}`);
|