tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

doh_server.js (3338B)


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