Cloudflare Workers ยท Single File ยท RESTful DoH Gateway
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.
/doh.<pwd>/... — the first segment after /doh. must equal your access token.
<pwd>/, the rest <domain>/<path> is rewritten to https://<domain>/<path>.
application/dns-json; POST uses application/dns-message (wire format). CORS enabled.
| Method | Path Pattern | Description |
|---|---|---|
| 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" } |
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.
ACCESS_PWD secret via wrangler secret put or the Cloudflare dashboard. The token is never shown in this UI.curl "https://glm5.331319.xyz/doh.<pwd>/alidns.com/dns-query?name=example.com&type=A"
# 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 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, ...}
| Request Path | Upstream URL |
|---|---|
/doh.<pwd>/alidns.com/dns-query | https://alidns.com/dns-query |
/doh.<pwd>/dns.alidns.com/resolve | https://dns.alidns.com/resolve |
/doh.<pwd>/cloudflare-dns.com/dns-query | https://cloudflare-dns.com/dns-query |
/doh.wrong/dns.alidns.com/resolve | 200 "uuid" (not proxied) |
/proxy/9.9.9.9/dns-query | https://9.9.9.9/dns-query |
Responses are streamed directly from the upstream server with CORS and caching headers added.
| Header | Value |
|---|---|
Access-Control-Allow-Origin | * |
Access-Control-Allow-Methods | GET, POST, OPTIONS |
Cache-Control | public, max-age=60 |
Content-Type | Original upstream type |