Service Online

DNS-over-HTTPS Proxy

Cloudflare Workers ยท Single File ยท RESTful DoH Gateway

How It Works

The proxy is triggered by a domain suffix in the request path. The first segment is the access password; everything after it is the upstream DoH server you define.

  • 1
    Password first Request /doh.<pwd>/... — the first segment after /doh. must equal your access token.
  • 2
    Verify before proxy Wrong / missing password → a random UUID is returned and the request is never forwarded.
  • 3
    Path-based routing After <pwd>/, the rest <domain>/<path> is rewritten to https://<domain>/<path>.
  • 4
    Protocol passthrough GET uses application/dns-json; POST uses application/dns-message (wire format). CORS enabled.

Endpoints

MethodPath PatternDescription
ANY /doh.<pwd>/<domain>/<path> Verify <pwd>, then proxy to https://<domain>/<path>
ANY /proxy/<domain>/<path> Explicit proxy prefix (supports IP addresses, no password)
GET /api/docs This documentation page (no password needed)
GET /health Health check โ†’ { status: "ok" }

Request Examples

Replace https://glm5.331319.xyz with your worker URL.

The password is the first segment after /doh., before your custom DoH address. Wrong password → random UUID, no proxy.

๐Ÿ”’
Password protection is ONSet the ACCESS_PWD secret via wrangler secret put or the Cloudflare dashboard. The token is never shown in this UI.

GET JSON API (dns-json)

curl "https://glm5.331319.xyz/doh.<pwd>/alidns.com/dns-query?name=example.com&type=A"

POST Wire Format (dns-message)

# Resolve example.com AAAA
dog --type AAAA example.com --dns "https://glm5.331319.xyz/doh.<pwd>/alidns.com/dns-query"

# Or with curl + binary body
curl -X POST "https://glm5.331319.xyz/doh.<pwd>/alidns.com/dns-query" \
     -H "Content-Type: application/dns-message" \
     --data-binary @dns_request.bin

ANY Wrong / Missing Password

# Any path that does NOT start with /doh.<correct-pwd>/ returns a UUID
curl "https://glm5.331319.xyz/doh.wrong-pwd/alidns.com/dns-query?name=example.com"
# -> 200  "f47ac10b-58cc-4372-a567-0e02b2c3d479"

curl "https://glm5.331319.xyz/doh.<pwd>/alidns.com/dns-query"
# -> 200  (proxied)  {"Status":0, ...}

Path Mapping Rules

Request PathUpstream URL
/doh.<pwd>/alidns.com/dns-queryhttps://alidns.com/dns-query
/doh.<pwd>/dns.alidns.com/resolvehttps://dns.alidns.com/resolve
/doh.<pwd>/cloudflare-dns.com/dns-queryhttps://cloudflare-dns.com/dns-query
/doh.wrong/dns.alidns.com/resolve200 "uuid" (not proxied)
/proxy/9.9.9.9/dns-queryhttps://9.9.9.9/dns-query

Response

Responses are streamed directly from the upstream server with CORS and caching headers added.

HeaderValue
Access-Control-Allow-Origin*
Access-Control-Allow-MethodsGET, POST, OPTIONS
Cache-Controlpublic, max-age=60
Content-TypeOriginal upstream type

Try It

๐Ÿ”’ Password is set (from Secret). Leave as-is or update below.