Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

The RethinkDNS resolver that deploys to Cloudflare Workers, Deno Deploy, Fastly, and Fly.io

License

NotificationsYou must be signed in to change notification settings

serverless-dns/serverless-dns

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,261 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

serverless-dns is a Pi-Hole esquecontent-blocking, serverless, stub DNS-over-HTTPS (DoH) and DNS-over-TLS (DoT) resolver. Runs out-of-the-box onCloudflare Workers,Deno Deploy,Fastly Compute@Edge, andFly.io. Free tiers of all these services should be enough to cover 10 to 20 devices worth of DNS traffic per month.

The RethinkDNS resolver

RethinkDNS runsserverless-dns in production at these endpoints:

Cloud platformServer locationsProtocolDomainUsage
⛅ Cloudflare Workers280+ (ping)DoHsky.rethinkdns.comconfigure
🦕 Deno Deploy30+ (ping)DoHprivate beta
⏱️ Fastly Compute@Edge80+ (ping)DoHprivate beta
🪂 Fly.io30+ (ping)DoH and DoTmax.rethinkdns.comconfigure

Server-side processing takes from 0 milliseconds (ms) to 2ms (median), and end-to-end latency (varies across regions and networks) is between 10ms to 30ms (median).

FOSS UnitedFLOSS/fund badge

TheRethink DNS resolver on Fly.io is sponsored byFLOSS/fund and FOSS United.

Self-host

Cloudflare Workers is the easiest platform to setupserverless-dns:

Deploy to Cloudflare Workers

Deploy to Fastly

For step-by-step instructions, refer:

PlatformDifficultyRuntimeDoc
⛅ CloudflareEasyv8IsolatesHosting on Cloudflare Workers
🦕 Deno.comModerateDenoIsolatesHosting on Deno.com
⏱️ Fastly Compute@EdgeEasyFastly JSHosting on Fastly Compute@Edge
🪂 Fly.ioHardNodeMicroVMHosting on Fly.io

To setup blocklists, visithttps://<my-domain>.tld/configure from your browser (it should load something similar toRethinkDNS'configure page).

For help or assistance, feel free toopen an issue orsubmit a patch.


Development

OpenSSF ScorecardAsk DeepWiki

Setup

Code:

# navigate to work dircd /my/work/dir# clone this repositorygit clone https://github.com/serverless-dns/serverless-dns.git# navigate to serverless-dnscd ./serverless-dns

Node:

# install node v22+ via nvm, if required# https://github.com/nvm-sh/nvm#installing-and-updatingwget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh| bashnvm install --lts# download dependenciesnpm i# (optional) update dependenciesnpm update# run serverless-dns on node./run n# run a clinicjs.org profiler./run n [cpu|fn|mem]

Deno:

# install deno.land v2+# https://github.com/denoland/deno/#installcurl -fsSL https://deno.land/install.sh| sh# run serverless-dns on deno./run d

Fastly:

# install node v22+ via nvm, if required# install the Fastly CLI# https://developer.fastly.com/learning/tools/cli# run serverless-dns on Fastly Compute@Edge./run f

Wrangler:

# install Cloudflare Workers (cli) aka Wrangler# https://developers.cloudflare.com/workers/cli-wrangler/install-updatenpm i wrangler --save-dev# run serverless-dns on Cloudflare Workers (cli)# Make sure to setup Wrangler first:# https://developers.cloudflare.com/workers/cli-wrangler/authentication./run w# profile wrangler with Chrome DevTools# blog.cloudflare.com/profiling-your-workers-with-wrangler

Code style

Commits on this repository enforces the Google JavaScript style guide (ref:.eslintrc.cjs).A gitpre-commit hook that runs linter (eslint) and formatter (prettier) on.js files. Usegit commit --no-verifyto bypass this hook.

Pull requests are also checked for code style violations and fixed automatically where possible.

Env vars

Configureenv.js if you need to tweak the defaults.For Cloudflare Workers, setup env vars inwrangler.toml, instead.For Fastly Compute@Edge, setup env vars infastly.toml, instead.

Request flow

  1. The request/response flow: client <->src/server-[node|workers|deno] <->doh.js <->plugin.js
  2. Theplugin.js flow:user-op.js ->cache-resolver.js ->cc.js ->resolver.js

Auth

serverless-dns supports authentication with analpha-numeric bearer token for both DoH and DoT. For a token,msg-key (secret), append the output ofhex(hmac-sha256(msg-key|domain.tld), msg) toACCESS_KEYS env var in csv format. Note:msg is currently fixed tosdns-public-auth-info.

  1. DoH: place themsg-key at the end of the blockstamp, like so:1:4AIggAABEGAgAA:<msg-key> (here,1 is the version,1:4AIggAABEGAgAAis the blockstamp,<msg-key> is the auth secret, and: is the delimiter).
  2. DoT: place themsg-key at the end of the SNI (domain-name) containing the blockstamp:1-4abcbaaaaeigaiaa-<msg-key> (here1 is the version,4abcbaaaaeigaiaais the blockstamp,<msg-key> is the auth secret, and- is the delimeter).

If the intention is to use auth with DoT too, keepmsg-key shorter (8 to 24 chars), since subdomains may only be 63 chars long in total.

You can generate the access keys for your fork frommax.rethinkdns.com, like so:

msgkey="ShortAlphanumericSecret"domain="my-serverless-dns-domain.tld"curl'https://max.rethinkdns.com/genaccesskey?key='"$msgkey"'&dom='"$domain"# output# {"accesskey":["my-serverless-dns-domain.tld|deadbeefd3adb33fa2bb33fd3eadf084beef3b152beefdead49bbb2b33fdead83d3adbeefdeadb33f"],"context":"sdns-public-auth-info"}

TLS PSK

serverless-dns also supports TLS PSK ciphersuites when env varTLS_PSK is set to hex or base64 of randomly generated 64 bytes. Works only on cloud deployments that terminate their own TLS (like on Fly.io).

The server-hint sent to the TLS 1.2 clients is fixed to888811119999.

Static PSK: TLS 1.2 clients must set client-hint (id) as hex string from790bb453...ffae2452. The static pre-shared key is then derived fromhkdf-sha256(key, id) wherekey is itselfhkdf-sha256(seed, sha512(ctx), salt):

  • seed is env varTLS_PSK converted to bytes from base64 or hex.
  • ctx isUTF-8 encoding of stringpskkeyfixedderivationcontext.
  • salt is fixed from44f402e7...91a6e3ce converted to bytes.
  • id is the static client-hint from above (790bb453...ffae2452) converted to bytes.

Dynamic PSK: For TLS 1.2 clients, to use a dynamically generated PSK identity and key (derived from env varTLS_PSK), invoke<my-domain.tld>/gentlspsk. The returned credentials are valid as long asTLS_PSK is unchanged:

{// 64 hex chars; id is to be used as-is as the psk client identity."id":"43dc2df4...6d332545",// 128 hex chars; convert to 64-length byte array to use as psk shared secret."psk":"ebc9ab07...03629dd4"}

TLSearly data (0-RTT) for TLS 1.3 (via TLS PSK) is not supported by Node.(why?)

Logs and Analytics

serverless-dns can be setup to upload logs via CloudflareLogpush.

  1. Setup aLogpush job:
    CF_ACCOUNT_ID=<hex-cloudflare-account-id>CF_API_KEY=<api-key-with-logs-edit-permission-at-account-level>R2_BUCKET=<r2-bucket-name>R2_ACCESS_KEY=<r2-access-key-for-the-bucket>R2_SECRET_KEY=<r2-secret-key-with-read-write-permissions># optional, setup a filter such that only logs form this worker ends up being pushed; but if you# do not need a filter on Worker name (script-name), edit the "filter" field below accordingly.SCRIPT_NAME=<name-of-the-worker-as-in-wrangler-toml># for more options, ref: developers.cloudflare.com/logs/get-started/api-configuration# Logpush API with cURL: developers.cloudflare.com/logs/tutorials/examples/example-logpush-curl# Available Logpull fields: developers.cloudflare.com/logs/reference/log-fields/account/workers_trace_eventscurl -s -X POST"https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/logpush/jobs" \    -H"Authorization: Bearer${CF_API_KEY}" \    -H'Content-Type: application/json' \    -d'{        "name": "dns-logpush",        "logpull_options": "fields=EventTimestampMs,Outcome,Logs,ScriptName&timestamps=rfc3339",        "destination_conf": "r2://'"$R2_BUCKET"'/{DATE}?access-key-id='"${R2_ACCESS_KEY}"'&secret-access-key='"${R2_SECRET_KEY}"'&account-id='"{$CF_ACCOUNT_ID}"',        "dataset": "workers_trace_events",        "filter": "{\"where\":{\"and\":[{\"key\":\"ScriptName\",\"operator\":\"contains\",\"value\":\"'"${SCRIPT_NAME}"'\"},{\"key\":\"Outcome\",\"operator\":\"eq\",\"value\":\"ok\"}]}}",        "enabled": true,        "frequency": "low"    }'
  2. Setwrangler.toml propertylogpush = true, which enablesLogpush.
  3. (Optional) env varLOG_LEVEL = "logpush", which raises the log-level such that onlyrequest and error logs are emitted.
  4. (Optional) Set env varLOGPUSH_SRC = "csv,of,subdomains", which makeslog-pusher.js emitrequest logs only if Workershostname contains one of the subdomains.

Logs published to R2 can be retrieved either usingR2 Workers, theR2 API, or theLogpush API.

Workers Analytics, if enabled, is pushed against a log-key,lid, which if unspecified is set to hostname of the serverless deployment with periods,., replaced with underscores,_. Auth must be setup when querying for Analytics via the API which returns a json; ex:https://max.rethinkdns.com/1:<optional-stamp>:<msg-key>/analytics?t=<time-interval-in-mins>&f=<field-name>. Possiblefields areip (client ip),qname (dns query name),region (resolver region),qtype (dns query type),dom (top-level domains),ansip (dns answer ips), andcc (ans ip country codes).

Log capture and analytics isn't yet implemented for Fly and Deno Deploy.


A note about runtimes

Deno Deploy (cloud) and Deno (the runtime) do not expose the same API surface (for example, Deno Deploy onlysupports HTTP/S server-listeners; whereas, Deno suports raw TCP/UDP/TLS in addition to plain HTTP and HTTP/S).

Except on Node,serverless-dns uses DoH upstreams defined by env vars,CF_DNS_RESOLVER_URL /CF_DNS_RESOLVER_URL_2.On Node, the default DNS upstream is1.1.1.2 (ref) or the recursive DNS resolver atfdaa::3 when running on Fly.io.

The entrypoints for Node and Deno aresrc/server-node.js,src/server-deno.ts respectively,and both listen for TCP-over-TLS, HTTP/S connections; whereas, the entrypoint for Cloudflare Workers, which only listens over HTTP (cli) orover HTTP/S (prod), issrc/server-workers.js; and for Fastly itssrc/server-fastly.js.

Local (non-prod) setups on Node,key (private) andcert (public chain) files, by default, are read frompaths defined in env vars,TLS_KEY_PATH andTLS_CRT_PATH.

Whilst for prod setup on Node (on Fly.io), eitherTLS_OFFLOAD must be set totrue orkey andcertmust bebase64 encoded in env varTLS_CERTKEY (ref), like so:

# EITHER: offload tls to fly.io and set tls_offload to trueTLS_OFFLOAD="true"# OR: base64 representation of both key (private) and cert (public chain)TLS_CERTKEY="KEY=b64_key_content\nCRT=b64_cert_content"# OPTIONALLY: use TLS with PSK ciphers (also permits domain fronting)TLS_PSK="hex-or-base64(cryptographically-secure-random-64bytes)"# OPTIONALLY: set TLS_ALLOW_ANY_SNI to true to permit domain frontingTLS_ALLOW_ANY_SNI="true"

For Deno,key andcert files are read from paths defined in env vars,TLS_KEY_PATH andTLS_CRT_PATH (ref).

Process bringup is different for each of these runtimes: For Node,src/core/node/config.js governs thebringup;while for Deno, it issrc/core/deno/config.ts, and for Workers it issrc/core/workers/config.js.src/system.js pub-sub co-ordinates thebringup phase among various modules.

On Node and Deno, in-process DNS caching is backed by@serverless-dns/lfu-cache; Cloudflare Workers is backed by bothCache Web API andin-process lfu caches. To disable caching altogether on all three platfroms, set env var,PROFILE_DNS_RESOLVES=true.

Cloud

Cloudflare Workers, and Deno Deploy are ephemeral, as in, the "process" that serves client requests is not long-lived,and in fact, two back-to-back requests may be served by two differentisolates ("processes"). Fastly Compute@Edge is the also ephemeral but does not use isolates, instead Fastly creates and destroys awasmtime sandbox for each request. Resolver on Fly.io, running Node, is backed bypersistent VMs and is hence longer-lived,like traditional "serverfull" environments.

For Deno Deploy, the code-base is bundled up in a single javascript file withdeno bundle and then handed offto Deno.com.

Cloudflare Workers build-time and runtime configurations are defined inwrangler.toml.Webpack5 bundles the files in an ESM module which is then uploaded to Cloudflare byWrangler.

Fastly Compute@Edge build-time and runtime configurations are defined infastly.toml.Webpack5 bundles the files in an ESM module which is then compiled to WASM bynpx js-compute-runtimeand subsequently packaged and published to Fastly Compute@Edge with theFastly CLI.

For Fly.io, which runs Node, the runtime directives are defined infly.toml (used bydev andlive deployment-types),while deploy directives are innode.Dockerfile.flyctl accordingly setsupserverless-dns on Fly.io's infrastructure.

# build and deploy for cloudflare workers.devnpm run build# usually, env-name is prodnpx wrangler publish [-e<env-name>]# bundle, build, and deploy for fastly compute@edge# developer.fastly.com/reference/cli/compute/publishfastly compute publish# build and deploy to fly.ionpm run build:flyflyctl deploy --dockerfile node.Dockerfile --config<fly.toml> [-a<app-name>] [--image-label<some-uniq-label>]

For deploys offloading TLS termination to Fly.io (B1 deployment-type), the runtime directives are instead defined infly.tls.toml, which sets up HTTP2 Cleartext and HTTP/1.1 on port443, and DNS over TCP on port853.

Ref:github/workflows.

Blocklists

200+ blocklists are compressed in aSuccinct Radix Trie (based on Steve Hanov's impl) with modificationsto speed up string search (lookup) at the expense of "succintness". The blocklists are versionedwith unix timestamp (defined insrc/basicconfig.json downloaded bypre.sh), which is generated once every week, but we'd like to generate 'em daily / hourly,if possiblesee), and hosted on Cloudflare R2 (env var:CF_BLOCKLIST_URL).

serverless-dns downloadsblocklist filesrequired to setup the radix-trie during runtime bring-up or, downloads themlazily,when serving a DNS request.

serverless-dns compiles around ~17M entries (as of Nov 2025) from around 200+ blocklists. These are defined in theserverless-dns/blocklists repository.

Sponsor this project

  •  

Packages

No packages published

Contributors14


[8]ページ先頭

©2009-2026 Movatter.jp