Skip to content

Instantly share code, notes, and snippets.

@prajaybasu
Created April 25, 2025 00:17
Show Gist options
  • Save prajaybasu/3a92b382d444ce0c2ab1fbaa8a6de821 to your computer and use it in GitHub Desktop.
Save prajaybasu/3a92b382d444ce0c2ab1fbaa8a6de821 to your computer and use it in GitHub Desktop.
DoH proxy for OpenWRT and uhttpd-mod-ucode
#!/usr/bin/env ucode
import { fdopen } from "fs";
import { create, AF_INET6, SOCK_DGRAM, SOL_SOCKET, SO_RCVTIMEO } from "socket";
const MAXLEN = 4096;
const TIMEOUT = 10000;
function b64url_decode(s) {
if (!s) return null;
s = replace(s, "-", "+");
s = replace(s, "_", "/");
const pad = length(s) % 4;
if (pad == 2) s += "==";
else if (pad == 3) s += "=";
else if (pad == 1) return null;
return b64dec(s);
}
function read_body(len) {
return len ? fdopen(0, "r").read(len) : "";
}
const method = getenv("REQUEST_METHOD") ?? "";
const qs = getenv("QUERY_STRING") ?? "";
const accept = lc(getenv("HTTP_ACCEPT") ?? "");
const clen = int(getenv("CONTENT_LENGTH") ?? 0);
let wire_query = null;
if (method == "GET") {
let b64 = null;
let parts = split(qs, "&");
for (let i = 0; i < length(parts); i++)
if (substr(parts[i], 0, 4) == "dns=") {
b64 = substr(parts[i], 4);
break;
}
wire_query = b64url_decode(b64);
} else if (method == "POST") {
wire_query = read_body(clen);
} else {
print("Status: 405 Method Not Allowed\r\n\r\n");
exit(0);
}
if (!wire_query || length(wire_query) == 0 || length(wire_query) > MAXLEN) {
print("Status: 400 Bad Request\r\n\r\n");
exit(0);
}
const sock = create(AF_INET6, SOCK_DGRAM);
sock.setopt(SOL_SOCKET, SO_RCVTIMEO, {
tv_sec: TIMEOUT / 1000,
tv_usec: (TIMEOUT % 1000) * 1000,
});
sock.send(wire_query, 0, { address: "::1", port: 53 });
const reply = sock.recv(MAXLEN);
sock.close();
if (!reply || length(reply) == 0) {
print("Status: 504 Gateway Timeout\r\n\r\n");
exit(0);
}
print("Content-Type: application/dns-message\r\n");
print("Cache-Control: no-store\r\n");
print("Content-Length: ", length(reply), "\r\n\r\n");
print(reply);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment