Giter Club home page Giter Club logo

serverless-dns's Introduction

It's a bird, it's a plane, it's... a self-hosted, pi-hole esque, DNS resolver

serverless-dns is a Pi-Hole esque content-blocking, serverless, stub DNS-over-HTTPS (DoH) and DNS-over-TLS (DoT) resolver. Runs out-of-the-box on Cloudflare Workers, Deno Deploy, Fastly Compute@Edge, and Fly.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 runs serverless-dns in production at these endpoints:

Cloud platform Server locations Protocol Domain Usage
โ›… Cloudflare Workers 280+ (ping) DoH sky.rethinkdns.com configure
๐Ÿฆ• Deno Deploy 30+ (ping) DoH private beta
โฑ๏ธ Fastly Compute@Edge 80+ (ping) DoH private beta
๐Ÿช‚ Fly.io 30+ (ping) DoH and DoT max.rethinkdns.com configure

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).

Self-host

Cloudflare Workers is the easiest platform to setup serverless-dns:

Deploy to Cloudflare Workers

Deploy to Fastly

For step-by-step instructions, refer:

Platform Difficulty Runtime Doc
โ›… Cloudflare Easy v8 Isolates Hosting on Cloudflare Workers
๐Ÿฆ• Deno.com Moderate Deno Isolates Hosting on Deno.com
โฑ๏ธ Fastly Compute@Edge Easy Fastly JS Hosting on Fastly Compute@Edge
๐Ÿช‚ Fly.io Hard Node MicroVM Hosting on Fly.io

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

For help or assistance, feel free to open an issue or submit a patch.


Development

OpenSSF Scorecard

Setup

Code:

# navigate to work dir
cd /my/work/dir

# clone this repository
git clone https://github.com/serverless-dns/serverless-dns.git

# navigate to serverless-dns
cd ./serverless-dns

Node:

# install node v19+ via nvm, if required
# https://github.com/nvm-sh/nvm#installing-and-updating
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
nvm install --lts

# download dependencies
npm i

# (optional) update dependencies
npm update

# run serverless-dns on node
./run n

# run a clinicjs.org profiler
./run n [cpu|fn|mem]

Deno:

# install deno.land v1.22+
# https://github.com/denoland/deno/#install
curl -fsSL https://deno.land/install.sh | sh

# run serverless-dns on deno
./run d

Fastly:

# install node v18+ 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-update
npm 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 git pre-commit hook that runs linter (eslint) and formatter (prettier) on .js files. Use git commit --no-verify to bypass this hook.

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

Env vars

Configure env.js if you need to tweak the defaults. For Cloudflare Workers, setup env vars in wrangler.toml, instead. For Fastly Compute@Edge, setup env vars in fastly.toml, instead.

Request flow

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

Auth

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

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

If the intention is to use auth with DoT too, keep msg-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 from max.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"}

Logs and Analytics

serverless-dns can be setup to upload logs via Cloudflare Logpush.

  1. Setup a Logpush 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_events
    curl -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. Set wrangler.toml property logpush = true, which enables Logpush.
  3. (Optional) env var LOG_LEVEL = "logpush", which raises the log-level such that only request and error logs are emitted.
  4. (Optional) Set env var LOGPUSH_SRC = "csv,of,subdomains", which makes log-pusher.js emit request logs only if Workers hostname contains one of the subdomains.

Logs published to R2 can be retrieved either using R2 Workers, the R2 API, or the Logpush 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>. Possible fields are ip (client ip), qname (dns query name), region (resolver region), qtype (dns query type), dom (top-level domains), ansip (dns answer ips), and cc (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 only supports 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 is 1.1.1.2 (ref) or the recursive DNS resolver at fdaa::3 when running on Fly.io.

The entrypoints for Node and Deno are src/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) or over HTTP/S (prod), is src/server-workers.js; and for Fastly its src/server-fastly.js.

Local (non-prod) setups on Node, key (private) and cert (public chain) files, by default, are read from paths defined in env vars, TLS_KEY_PATH and TLS_CRT_PATH.

Whilst for prod setup on Node (on Fly.io), either TLS_OFFLOAD must be set to true or key and cert must be base64 encoded in env var TLS_CERTKEY (ref), like so:

# EITHER: offload tls to fly.io and set tls_offload to true
TLS_OFFLOAD="true"
# OR: base64 representation of both key (private) and cert (public chain)
TLS_CERTKEY="KEY=b64_key_content\nCRT=b64_cert_content"

For Deno, key and cert files are read from paths defined in env vars, TLS_KEY_PATH and TLS_CRT_PATH (ref).

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

On Node and Deno, in-process DNS caching is backed by @serverless-dns/lfu-cache; Cloudflare Workers is backed by both Cache Web API and in-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 different isolates ("processes"). Fastly Compute@Edge is the also ephemeral but does not use isolates, instead Fastly creates and destroys a wasmtime sandbox for each request. Resolver on Fly.io, running Node, is backed by persistent VMs and is hence longer-lived, like traditional "serverfull" environments.

For Deno Deploy, the code-base is bundled up in a single javascript file with deno bundle and then handed off to Deno.com.

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

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

For Fly.io, which runs Node, the runtime directives are defined in fly.toml (used by dev and live deployment-types), while deploy directives are in node.Dockerfile. flyctl accordingly sets up serverless-dns on Fly.io's infrastructure.

# build and deploy for cloudflare workers.dev
npm run build
# usually, env-name is prod
npx wrangler publish [-e <env-name>]

# bundle, build, and deploy for fastly compute@edge
# developer.fastly.com/reference/cli/compute/publish
fastly compute publish

# build and deploy to fly.io
npm run build:fly
flyctl 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 in fly.tls.toml, which sets up HTTP2 Cleartext and HTTP/1.1 on port 443, and DNS over TCP on port 853.

Ref: github/workflows.

Blocklists

190+ blocklists are compressed in a Succinct Radix Trie (based on Steve Hanov's impl) with modifications to speed up string search (lookup) at the expense of "succintness". The blocklists are versioned with unix timestamp (defined in src/basicconfig.json downloaded by pre.sh), which is generated once every week, but we'd like to generate 'em daily / hourly, if possible see), and hosted on Cloudflare R2 (env var: CF_BLOCKLIST_URL).

serverless-dns downloads 3 blocklist files required to setup the radix-trie during runtime bring-up or, downloads them lazily, when serving a DNS request.

serverless-dns compiles around ~13M entries (as of Jan 2023) from around 190+ blocklists. These are defined in the serverless-dns/blocklists repository.

serverless-dns's People

Contributors

amithm7 avatar dns-deploy avatar georgyo avatar github-actions[bot] avatar harish-narayan avatar ignoramous avatar jakechampion avatar markiannucci avatar neneeen avatar peterdavehello avatar santhosh-ponnusamy avatar shruuub avatar spencerisgiddy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

serverless-dns's Issues

Migrate the codebase to Typescript

The refactor has been painful due to the wild west nature of this javascript codebase. Let's try to static-type it esp since absence of tests are exaggerating the pain, at this moment.

On device wakeup, DoH queries fail

It appears that RethinkDNS app's (golang-based) http client has trouble getting answers (more than 50+ queries) from max.rethinkdns.com upon device wake-up.

12-24 16:53:18.382 17127 12410 I GoLog   : Trying confirmed IP 213.188.218.85 for addr max.rethinkdns.com:443
12-24 16:53:18.423 17127 15151 I GoLog   : Confirmed IP 213.188.218.85 worked
12-24 16:53:18.465 17127 10198 I GoLog   : new udp proxy (mode: %!s(bool=false)) conn to target: 10.111.222.3:53
12-24 16:53:18.465 17127 10198 I GoLog   : skipping local block for  with err play.googleapis.com name not in blocklist 1:4AIAgABAAHAhAA== [%!s(bool=false)]
12-24 16:53:18.466 17127 10198 I GoLog   : Dialing max.rethinkdns.com:443
12-24 16:53:18.466 17127 10198 I GoLog   : Trying confirmed IP 213.188.218.85 for addr max.rethinkdns.com:443
12-24 16:53:18.382 17127 12410 I GoLog   : 56522 Sending query
12-24 16:53:18.382 17127 12410 I GoLog   : 56522 GetConn(max.rethinkdns.com:443)
12-24 16:53:18.382 17127 12410 I GoLog   : 56522 GetConn(max.rethinkdns.com:443)
12-24 16:53:18.423 17127 15151 I GoLog   : 56522 TLSHandshakeStart()
12-24 16:53:18.468 17127 15151 I GoLog   : 56522 TLSHandshakeDone({772 true false 4866 h2 true max.rethinkdns.com <hex>, <nil>)
12-24 16:53:18.469 17127 15151 I GoLog   : 56522 GetConn(max.rethinkdns.com:443)
12-24 16:53:18.469 17127 15151 I GoLog   : 56522 GotConn({0x400015ca80 reused=true wasIdle=false idleTime=0s})
12-24 16:53:18.469 17127 15151 I GoLog   : 56522 WroteHeaders()
12-24 16:53:18.469 17127 15151 I GoLog   : 56522 WroteRequest({<nil>})
12-24 16:53:18.501 17127 12410 I GoLog   : 56522 Query failed: Post "https://max.rethinkdns.com/1:IAAgAA==": unexpected EOF
12-24 16:53:18.501 17127 12410 I GoLog   : 56522 Disconfirming 213.188.218.85
12-24 16:53:18.501 17127 12410 I GoLog   : 56522 Closing failing DoH socket
12-24 16:53:18.504 17127 15151 I GoLog   : DoH query failed: connection closed
12-24 16:53:18.466 17127 10198 I GoLog   : 62575 Sending query
12-24 16:53:18.466 17127 10198 I GoLog   : 62575 GetConn(max.rethinkdns.com:443)
12-24 16:53:18.468 17127 15151 I GoLog   : 62575 GotConn({0x400015ca80 reuse=false idle=false idleTime=0s})
12-24 16:53:18.468 17127 15151 I GoLog   : 62575 WroteHeaders()
12-24 16:53:18.469 17127 15151 I GoLog   : 62575 WroteRequest({<nil>})
12-24 16:53:18.497 17127 11237 I GoLog   : 62575 TLSHandshakeStart()
12-24 16:53:18.499 17127 12410 I GoLog   : 62575 GotFirstResponseByte()
12-24 16:53:18.500 17127 12410 I GoLog   : 62575 Got response
12-24 16:53:18.500 17127 11237 I GoLog   : 62575 Closed response
12-24 16:53:18.501 17127 11237 I GoLog   : 62575 Query failed: Nonzero response ID
12-24 16:53:18.501 17127 11237 I GoLog   : 62575 Disconfirming 213.188.218.85
12-24 16:53:18.501 17127 11237 I GoLog   : 62575 Closing failing DoH socket
12-24 16:53:18.548 17127 10198 I GoLog   : 62575 TLSHandshakeDone({772 true false 4866 h2 true max.rethinkdns.com <hex>}, <nil>)

Each query creates a new download / blocklist construction

Observed on both node & deno.

Maybe related: A deno-deploy user has reported increase in latency, the past week:

i checked the latency recently after the updates, there is an increase lantency of about 800ms repeatedly for various request log for 1week. I also check the (upstream dns) lantency derectly but it has latency of about 50ms.

Logs for repeated requests:

downloading https://dist.rethinkdns.com/blocklists/1636965620445/filetag.json
makeTd from tdParts 2
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td00.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td01.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td02.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/rd.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/filetag.json
makeTd from tdParts 2
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td00.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td01.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td02.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/rd.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/filetag.json
makeTd from tdParts 2
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td00.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td01.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td02.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/rd.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/filetag.json
makeTd from tdParts 2
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td00.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td01.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td02.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/rd.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/filetag.json
makeTd from tdParts 2
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td00.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td01.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td02.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/rd.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/filetag.json
makeTd from tdParts 2
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td00.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td01.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td02.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/rd.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/filetag.json
makeTd from tdParts 2
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td00.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td01.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td02.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/rd.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/filetag.json
makeTd from tdParts 2
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td00.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td01.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/td02.txt
downloading https://dist.rethinkdns.com/blocklists/1636965620445/rd.txt

cached blocklists__/ probably hid this behavior.

Can't deploy to cloudflare

On deploying (why the link on the readme lead to non-existent repo?), I got

Creating the secret for script name serverless-dns
Worker serverless-dns doesn't exist in the API yet. Creating a draft Worker so we can create new secret.
Error: No such file or directory (os error 2)

Fix NPM deps warnings

querystring, chokidar, resolve-url, urix, and fsevents.

npm WARN deprecated [email protected]: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
npm WARN deprecated [email protected]: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
npm WARN deprecated [email protected]: https://github.com/lydell/resolve-url#deprecated
npm WARN deprecated [email protected]: Please see https://github.com/lydell/urix#deprecated
npm WARN deprecated [email protected]: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.

from: https://github.com/serverless-dns/serverless-dns/runs/4536113441?check_suite_focus=true

Optionally disable blocklist downloads

A user says,

Hi. I would like to give feedback on the index.bundle.js

For the code, the latency over few days remains consistent avarage of 500ms from 800ms(in the past before fixing/updates) using deno-deploy.

Can i suggest for index.bundle.js code to have off switch for blocklist url, since most users have their personal CF-DNS-RESOLVER-URL, that means they have include its blocklist(like Nextdns/controld, or even rethinkdns link)in sever side.

I maybe right or wrong. This will maybe reduce significant for our deno deploy errors or latency or other factors that affect its performance).

Sorry for the Huge feedback.


Msg forward permission by amithm7

User:
So can i get like an off switch or disable for Blocklist url in deno deploy code?

amithm7:
there is a bug currently, Mz may fix it in a few days.

For the off switch, can you forward this feedback in the group? Mz can take a better decision. thanks.

Support GET requests

GET requests are broken when stamps are used.

Tested at dohjs.org

With URLs

https://basic.bravedns.com/dns-query/1:AMD_PwDw

https://basic.bravedns.com/1:AMD_PwDw

DoT with Deno

DoT with Deno isn't on this repo. yet.

Also, Deno code uses another env. variable TERMINATE_TLS="true" to determine if to start tls -server termination or not.

Originally posted by @amithm7 in #43 (comment)

enhanced privacy

vars = { CF_CACHE_EXPIRY_DAYS = 1, CF_CONFIG_CMS_KEY = "", CF_INFO_CMS_KEY = "", CF_USER_CMS_CACHE_TIME = 0, CF_USER_CMS_TOSS_TIME = 0, CF_LOG_FIREHOSE_STREAM = "", CF_DEBUG_FIREHOSE_STREAM = "", CF_DNSCOUNT_FIREHOSE_STREAM = "", CF_DNSLOG_WAIT_TIME = 10000, CF_DNSCOUNT_WAIT_TIME = 15000, CF_LIVELOG_END_POINT = "", CF_USER_CONFIG_CACHE_TIME = 300000, CF_BLOCKLIST_URL = "https://bravepublic.s3.us-east-2.amazonaws.com/completeblocklist/", CF_LATEST_BLOCKLIST_TIMESTAMP = "1627901743446", CF_PROCESS_DNS_ON_DNSPARSER_EXCEPTION = false, CF_PROCESS_DNS_ON_SERVER_EXCEPTION = false, CF_ON_INVALID_FLAG_STOPPROCESSING = true, CF_DNS_RESOLVER_URL = "https://cloudflare-dns.com/dns-query"}

https://cloudflare-dns.com/dns-queryโ†’https://mozilla.cloudflare-dns.com/dns-query

Deno Deploy Promise.all within Promise.any quirk

dnsResolver.js:resolveDns await on two async functions. One returns a Array<Promise> of which resolution of any one is enough to proceed. The other returns a single Promise, which has to resolve. And so, it is handled like so:

  const outerPromises = await Promise.all(promiseOfArrayOfPromises(), singlePromise())
  const unwrappedArrayOfPromises = outerPromises[0]
  const anyOnePromise = await Promise.any(arrayOfPromises)

The current code setup works on Workers but not on Deno Deploy, for reasons unknown.

0 | 2022-02-01 10:27:44 | Error: resolver: cache miss
     at DNSResolver.resolveDnsFromCache (file:///src/index.bundle.js:7416:31)

const promisedTasks = await Promise.all([
this.resolveDnsUpstream(

Include configure webpage with workers

Users should be able to configure the blocklists through serverless-dns deployment rather than rely on rethinkdns.com/configure. Figure out a way to share code between the RethinkDNS website and serverless-dns deployment.

The domain name for the endpoint must be picked up automatically, if possible (should be, from within workers?).

Deno DoT (local certs) fails

Process bring up is all good, but DoT doesn't work since apparently reads fail to decrypt:

โžœ deno run --unstable --allow-net --allow-env --allow-read --import-map=import_map.json src/server-deno.ts
โžœ kdig -d @127.0.0.1:10000 +tls-ca=../serverless-dns/test/data/tls/dns.rethinkdns.localhost.crt +tls-host=1-AABABAA.dns.rethinkdns.localhost +tls-sni=1-AABABAA.dns.rethinkdns.localhost aws.com
2022-01-23T14:03:10.517Z D Deno DoT conn: { transport: "tcp", hostname: "127.0.0.1", port: 53256 }
2022-01-23T14:03:10.520Z W Deno err tcp query read InvalidData: cannot decrypt peer's message
    at deno:core/01_core.js:101:46
    at unwrapOpResult (deno:core/01_core.js:121:13)
    at async read (deno:ext/net/01_net.js:21:19)
    at async serveTcp (file:///home/murtaza/bravehub/serverless-dns/src/server-deno.ts:133:11)

TLS cert/key picked up from:

{ certFile: "test/data/tls/dns.rethinkdns.localhost.crt",
  keyFile: "test/data/tls/dns.rethinkdns.localhost.key" }

DNS Logs with Workers KV free-tier

Prototype DNS logs storage & retrieval from Workers KV free-tier (1K writes, deletes, lists / day; 100K reads / day; 1G storage in total).

We'd need some gating mechanism (may be via Workers secrets or env-variable)?

Hmm, is it possible for users to open a specific page for a config, then while browsing in another tab, that page will list the recently blocked queries? Sorta poor-man short-term logging. I'm thinking if the config is say abc123, and the user normally use /abc123 for DoH address, they can use /abc123/def456 temporarily as DoH address while opening /abc123/def456/logs

nodejs `req` object vs fetch's `Request` instance

Regression introduced in a850e52

Error stack:

  const ua = req.headers.get("User-Agent")
                         ^
TypeError: req.headers.get is not a function
    at fromBrowser (file:///node-dir/src/helpers/util.js:42:26)
    at Module.corsHeadersIfNeeded (file:///node-dir/src/helpers/util.js:68:11)
    at Http2SecureServer.serveHTTPS (file:///node-dir/src/server.js:393:50)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

const ua = req.headers.get("User-Agent")

This is being called with NodeJS http req passed. From here:

res.writeHead(dnsutil.dohStatusCode(b), util.corsHeadersIfNeeded(req));

Unlike fetch's Request instance, this an object and ua can be got like this:

const ua = req.headers["user-agent"];

This requires 2 diff. functions ? and maybe JSDoc for type Http2ServerRequest (nodejs: h2) vs Request (fetch). Like this:

/**
* Services a DNS over HTTPS connection
* @param {Http2ServerRequest} req
* @param {Http2ServerResponse} res
*/
async function serveHTTPS(req, res) {

Revisit blocklist stamps

Today, the blocklists metadata is stored in a dictionary-encoded bitmap as leaf node of domains compacted into a radix trie.

This encoded bitmap is then represented in a URL (like the one rethinkdns/configure generates in response to user's selection) as a url-safe base64.

The bitmap encoding is such that, up to a maximum of 256 -- 16 (blocklist groups) x 16 (blocklists per group) -- unique dictionary values (blocklist index) can be represented. Of course, this can be increased by increasing size of bytes used to represent the blocklist group (currently 2 bytes) and/or blocklists themselves (also at 2 bytes).

Ideally, the encoded representation must optimize for the data being encoded. Analysis tells us that there are likely over 80% domains that are present only either in one or two blocklists. So, there's a potential to rethink the current strategy of encoding the blocklist metadata the way we are while also increasing number of blocklists that RethinkDNS, the resolver, can support.

Total domain entries: 5814457
Unique domains: 2550019
// count is the total number of domains present in #{entry} number of blocklists
// that is, the first line below means, 1412059 domains (55%) exist in just 1 blocklist.
Entry: 1 : count: 1412059 : %: 55.37445015115574
Entry: 2 : count: 554896 : %: 21.76046531418001
Entry: 3 : count: 214961 : %: 8.429780327126975
Entry: 4 : count: 85965 : %: 3.371151352205611
Entry: 5 : count: 44341 : %: 1.7388497889623569
Entry: 6 : count: 62576 : %: 2.4539425000362742
Entry: 7 : count: 26620 : %: 1.0439137904462672
Entry: 8 : count: 49785 : %: 1.9523383943413755
Entry: 9 : count: 27338 : %: 1.0720704433966963
Entry: 10 : count: 17297 : %: 0.6783086714255855
Entry: 11 : count: 13686 : %: 0.5367018833977315
Entry: 12 : count: 17039 : %: 0.6681910997525901
Entry: 13 : count: 9138 : %: 0.358350271115627
Entry: 14 : count: 5380 : %: 0.21097882015781058
Entry: 15 : count: 3046 : %: 0.11945009037187565
Entry: 16 : count: 1807 : %: 0.07086221710504902
Entry: 17 : count: 1139 : %: 0.0446663338586889
Entry: 18 : count: 763 : %: 0.029921345684090984
Entry: 19 : count: 688 : %: 0.02698019112798767
Entry: 20 : count: 413 : %: 0.016195957755608878
Entry: 21 : count: 328 : %: 0.0128626492586918
Entry: 22 : count: 244 : %: 0.009568556155856094
Entry: 23 : count: 179 : %: 0.0070195555405665605
Entry: 24 : count: 109 : %: 0.00427447795487014
Entry: 25 : count: 70 : %: 0.00274507758569642
Entry: 26 : count: 54 : %: 0.0021176312803943814
Entry: 27 : count: 42 : %: 0.0016470465514178522
Entry: 28 : count: 24 : %: 0.0009411694579530583
Entry: 29 : count: 14 : %: 0.0005490155171392841
Entry: 30 : count: 10 : %: 0.00039215394081377434
Entry: 31 : count: 4 : %: 0.00015686157632550972
Entry: 32 : count: 2 : %: 0.00007843078816275486
Entry: 33 : count: 1 : %: 0.00003921539408137743
Entry: 34 : count: 0 : %: 0
Entry: 35 : count: 1 : %: 0.00003921539408137743

from: celzero/serverless-dns/issues/4.

CF_BLOCKLIST_URL Get 403 on Deno

Hello
I have a problem with Deno deploy and get 403 on logs.
I have set env with https://cf.rethinkdns.com/blocklists/ but there is space on logs make cant fetch blocklist, i see on blocklistWrapper.js#L163 and blocklistWrapper.js#L165 is fine but on deno there is have a space.

https://cf.rethinkdns.com/blocklists/ /filetag.json Response {
  body: ReadableStream { locked: false },
  bodyUsed: false,
  headers: Headers {
  "content-type": "application/xml",
  date: "Mon, 27 Dec 2021 08:10:51 GMT",
  server: "AmazonS3",
  via: "1.1 03bb2a9a7a53ca49b9a36c5ecd83fbae.cloudfront.net (CloudFront)",
  "x-amz-cf-id": "Q-WNfbUO7fAdAwPBoNRsnq1xlF4IimcTIj9fsNLphK_gLXNEYT9ArQ==",
  "x-amz-cf-pop": "SIN5-C1",
  "x-cache": "Error from cloudfront"
},
  ok: false,
  redirected: false,
  status: 403,
  statusText: "Forbidden",
  url: "https://cf.rethinkdns.com/blocklists/%20/filetag.json"
}

Blocklists metadata repo

I think we may have to maintain our own blocklists like nextdns does.

1Hosts maintainer has reported that we track 1Hosts (complete) which is a defunct blocklist...

Using filterlists is an option, but it may be an overkill. Let's setup a repository similar to that of nextdns/metadata.

DNS packet encode / decode unhandled exceptions

After adding a caching layer, reliance on dns-packet encoding / decoding has gone up. In our tests, these unhandled exceptions have cropped up in the meanwhile:

  "exceptions": [
    {
      "name": "TypeError",
      "message": "Failed to execute function: parameter 1 is not of type 'Response'.",
    }
  ],
  "logs": [
    {
      "message": [
        "Error At : DNSParserWrap -> Encode"
      ],
      "level": "error",
    },
    {
      "message": [
        "TypeError: e.copy is not a function\n    at Object.encode (worker.js:10:13483)\n    at Object.encode (worker.js:10:33416)\n    at ce (worker.js:10:35934)\n    at ne (worker.js:10:35051)\n    at de.Encode (worker.js:10:36285)\n    at Ue.dnsBlockResponse (worker.js:10:44687)\n    at vt.Rt (worker.js:10:82128)\n    at vt.executePlugin (worker.js:10:80457)\n    at async worker.js:10:82801"
      ],
      "level": "error",
    }
  ],
 "outcome": "exception",
  "scriptName": null,
  "exceptions": [
    {
      "name": "TypeError",
      "message": "Failed to execute function: parameter 1 is not of type 'Response'.",
    }
  ],
  "logs": [
    {
      "message": [
        "Error At : DNSParserWrap -> Encode"
      ],
      "level": "error",
    },
    {
      "message": [
        "TypeError: e.copy is not a function\n    at Object.encode (worker.js:10:13483)\n    at Object.encode (worker.js:10:33416)\n    at ce (worker.js:10:35934)\n    at ne (worker.js:10:35051)\n    at de.Encode (worker.js:10:36285)\n    at Ue.dnsBlockResponse (worker.js:10:44687)\n    at vt.Rt (worker.js:10:82128)\n    at vt.executePlugin (worker.js:10:80457)\n    at async worker.js:10:82801"
      ],
      "level": "error",
    }
  ],

Configure Blocklist using Deno-Deploy

image
Summary:

  1. No issues for latency (25-50ms. Great)
  2. No issues for error in deno-deploy (Great)
  3. Config blocklist issues (syntax error- on website)
  4. No issues on blocklist on deno-deploy (Great)

NodeJS process crash in MAA

2021-12-24T05:22:18.469 app[a6e3f003] maa [info] Main child exited with signal (with signal 'SIGINT', core dumped? false)
2021-12-24T05:22:18.470 app[a6e3f003] maa [info] Starting clean up.
2021-12-24T05:22:18.482 proxy[a6e3f003] maa [error] error.code=2000 error.message="problem connecting to app instance" 
2021-12-24T05:22:19.311 proxy[a6e3f003] maa [error] error.code=2 error.message="Internal problem" 
2021-12-24T05:22:20.222 proxy[a6e3f003] maa [error] error.code=2 error.message="Internal problem" 
2021-12-24T05:22:20.247 proxy[a6e3f003] maa [error] error.code=2 error.message="Internal problem"

Nothing more.

WiFi connection problem

First of all, I searched for "wifi", and couldn't find any similar issue.
That said, I created a WiFi hotspot using a mobile device. After connecting to it, I get no dns queries. The same happens with public WiFi. It connects, but no dns response.
If I create a Bluetooth hotspot, then it works well.
I tried to add dns ips into wifi settings, but didn't help.

Thanks

Multiple upstream DoHs

Provide a way for user to select multiple DoH upstream.

The upstream DoHs could be in their configs in a fixed ordered list.

The DoH user wants used could be optionally encoded in the URL.

Otherwise, the resolver is free to round-robin among the upstream DoHs from the config.

Cancel upstream requests when clients go away

Sometimes, clients close connections even before a response could be sent. In those cases, it may be better to close upstream connections as there's no one to send an answer to, but then again if the client comes back again with the same query, we could possibly respond faster since the response would have been cached from previous request...

Eitherways, any behaviour, one way or the other, needs to be codified (documented or implemented).

Cloudflare Workers 'memory exceeded exception'

  1. Default env vars in production.
  2. Memory limit exceeded upon downloading blocklists.
 | [Info] Loading env. from runtime: worker 
 | [Debug] Added runTime worker 
 | [Debug] Added runTimeEnv production 
 | [Warn] cloudPlatform env[key] default value: fly 
 | [Debug] Added cloudPlatform fly 
 | [Debug] Added logLevel info 
 | [Warn] blocklistUrl env[key] default value: https://dist.rethinkdns.com/blocklists/ 
 | [Debug] Added blocklistUrl https://dist.rethinkdns.com/blocklists/ 
 | [Warn] latestTimestamp env[key] default value: 1638959365361 
 | [Debug] Added latestTimestamp 1638959365361 
 | [Warn] dnsResolverUrl env[key] default value: https://cloudflare-dns.com/dns-query 
 | [Debug] Added dnsResolverUrl https://cloudflare-dns.com/dns-query 
 | [Warn] secondaryDohResolver env[key] default value: https://dns.google/dns-query 
 | [Debug] Added secondaryDohResolver https://dns.google/dns-query 
 | [Warn] onInvalidFlagStopProcessing env[key] default value: false 
 | [Debug] Added onInvalidFlagStopProcessing false 
 | [Warn] workerTimeout env[key] default value: 10000 
 | [Debug] Added workerTimeout 10000 
 | [Warn] fetchTimeout env[key] default value: 5000 
 | [Debug] Added fetchTimeout 5000 
 | [Warn] tdNodecount env[key] default value: 42112224 
 | [Debug] Added tdNodecount 42112224 
 | [Warn] tdParts env[key] default value: 2 
 | [Debug] Added tdParts 2 
 | [Info] Console level set:  info 
 | [Info] svc: systemReady 
 | [Info] 2022-01-22T17:52:19.651Z I BlocklistWrapper [rx.moomxa5hqw.diqfxcepmj] download blocklists 1642873939651 0 
 | [Info] downloading https://dist.rethinkdns.com/blocklists/1638959365361/filetag.json json 
 | [Info] makeTd from tdParts 2 
 | [Info] downloading https://dist.rethinkdns.com/blocklists/1638959365361/td00.txt buffer 
 | [Info] downloading https://dist.rethinkdns.com/blocklists/1638959365361/td01.txt buffer 
 | [Info] downloading https://dist.rethinkdns.com/blocklists/1638959365361/td02.txt buffer 
 | [Info] downloading https://dist.rethinkdns.com/blocklists/1638959365361/rd.txt buffer 
 | [Info] tds downloaded 
 ! [Error] Worker exceeded memory limit.

Redirection to website fails on deno

Try: https://rdns.deno.dev. or locally:

curl -vk -X GET \
  'https://dns.rethinkdns.localhost:8080/' \
  -H 'User-Agent: Mozilla/5.0 something'\
  --output -

Resolver works fine.

Corresponding logs:

E RethinkPlugin [rx.otzjofgg9h.wvgcyt6u5v] exception {"isException":true,"exceptionStack":"Error: [rx.otzjofgg9h.wvgcyt6u5v]mk-res no upstream result\n    at DNSResolver.makeRdnsResponse (file:///src/index.bundle.js:7282:25)\n    at DNSResolver.resolveDns (file:///src/index.bundle.js:7259:30)\n    at DNSResolver.RethinkModule (file:///src/index.bundle.js:7232:40)\n    at async RethinkPlugin.executePlugin (file:///src/index.bundle.js:7606:25)","exceptionFrom":"dnsResolver","data":{}}
E DnsResolver [rx.otzjofgg9h.wvgcyt6u5v] main Error: [rx.otzjofgg9h.wvgcyt6u5v]mk-res no upstream result
  at DNSResolver.makeRdnsResponse (file:///src/index.bundle.js:7282:25)
  at DNSResolver.resolveDns (file:///src/index.bundle.js:7259:30)
  at DNSResolver.RethinkModule (file:///src/index.bundle.js:7232:40)
  at async RethinkPlugin.executePlugin (file:///src/index.bundle.js:7606:25)
I RethinkPlugin [rx.otzjofgg9h.wvgcyt6u5v] user-op is a no-op, possibly a command-control req
W UserOp [rx.otzjofgg9h.wvgcyt6u5v] not a dns-msg, ignore

Plain old DNS on Deno

Tokio powered IO is likely way faster under load than Node's?

For reference, Node's plain old DNS perf doing 6600 DNS reqs at the rate of 110 per sec:

-------------------------------
runs: 6600
p10/50/75/90/95     17   18   19   20   21
p99/99.9/99.99/100  25   34   89  131 
-------------------------------

node/h2 (dns-resolver): Uncaught error

DNSResolver.prototype.doh2 = async function (request) {

  • Probably check if http2Session (c) is not destroyed before calling c.close() ?
  • Error handlers on c and req aren't closing the http2Session either, but just rejecting promise. destroy the socket on error?

Type 1:

2021-12-20T10:35 app [info] node:internal/errors:464
2021-12-20T10:35 app [info]     ErrorCaptureStackTrace(err);
2021-12-20T10:35 app [info]     ^
2021-12-20T10:35 app [info] Error [ERR_STREAM_PREMATURE_CLOSE]: Premature close
2021-12-20T10:35 app [info]     at new NodeError (node:internal/errors:371:5)
2021-12-20T10:35 app [info]     at Http2ServerRequest.onclose (node:internal/streams/end-of-stream:122:30)
2021-12-20T10:35 app [info]     at Http2ServerRequest.emit (node:events:390:28)
2021-12-20T10:35 app [info]     at ServerHttp2Stream.onStreamAbortedRequest (node:internal/http2/compat:191:13)
2021-12-20T10:35 app [info]     at ServerHttp2Stream.emit (node:events:402:35)
2021-12-20T10:35 app [info]     at closeStream (node:internal/http2/core:1896:14)
2021-12-20T10:35 app [info]     at ServerHttp2Stream.close (node:internal/http2/core:2268:5)
2021-12-20T10:35 app [info]     at node:internal/http2/core:3218:46
2021-12-20T10:35 app [info]     at Map.forEach (<anonymous>)
2021-12-20T10:35 app [info]     at TLSSocket.socketOnClose (node:internal/http2/core:3218:19) {
2021-12-20T10:35 app [info]   code: 'ERR_STREAM_PREMATURE_CLOSE'
2021-12-20T10:35 app [info] }
2021-12-20T10:35 app [info] Node.js v17.2.0
2021-12-20T10:35 app [info] Main child exited normally with code: 1
2021-12-20T10:35 app [info] Starting clean up.
2021-12-20T10:35 proxy [error] Error 2: Internal problem
2021-12-20T10:35 proxy [error] Error 2: Internal problem
2021-12-20T10:35 proxy [error] Error 2: Internal problem
2021-12-20T10:35 proxy [error] Error 2: Internal problem

Type 2:

2021-12-19T05:06:16.851 node:events:368
2021-12-19T05:06:16.851       throw er; // Unhandled 'error' event
2021-12-19T05:06:16.851       ^
2021-12-19T05:06:16.851 Error [ERR_HTTP2_STREAM_CANCEL]: The pending stream has been canceled (caused by: connect ECONNREFUSED 2620:fe::10:443)
2021-12-19T05:06:16.851     at new NodeError (node:internal/errors:371:5)
2021-12-19T05:06:16.851     at closeSession (node:internal/http2/core:1138:20)
2021-12-19T05:06:16.851     at ClientHttp2Session.destroy (node:internal/http2/core:1517:5)
2021-12-19T05:06:16.851     at TLSSocket.socketOnError (node:internal/http2/core:2968:13)
2021-12-19T05:06:16.851     at TLSSocket.emit (node:events:390:28)
2021-12-19T05:06:16.851     at emitErrorNT (node:internal/streams/destroy:164:8)
2021-12-19T05:06:16.851     at emitErrorCloseNT (node:internal/streams/destroy:129:3)
2021-12-19T05:06:16.851     at processTicksAndRejections (node:internal/process/task_queues:83:21)
2021-12-19T05:06:16.851 Emitted 'error' event on ClientHttp2Stream instance at:
2021-12-19T05:06:16.851     at emitErrorNT (node:internal/streams/destroy:164:8)
2021-12-19T05:06:16.851     at emitErrorCloseNT (node:internal/streams/destroy:129:3)
2021-12-19T05:06:16.851     at processTicksAndRejections (node:internal/process/task_queues:83:21) {
2021-12-19T05:06:16.851   cause: Error: connect ECONNREFUSED 2620:fe::10:443
2021-12-19T05:06:16.851       at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1157:16) {
2021-12-19T05:06:16.851     errno: -111,
2021-12-19T05:06:16.851     code: 'ECONNREFUSED',
2021-12-19T05:06:16.851     syscall: 'connect',
2021-12-19T05:06:16.851     address: '2620:fe::10',
2021-12-19T05:06:16.852     port: 443
2021-12-19T05:06:16.852   },
2021-12-19T05:06:16.852   code: 'ERR_HTTP2_STREAM_CANCEL'
2021-12-19T05:06:16.852

Custom allowlist / denylist with Workers KV

A user wrote:

If someone asks for a customized blocking server, they usually need more than just enabling and disabling lists. They would also want to whitelist and blacklist specific domains directly, or remotely check the log to see what they've been missing or inadvertently block.

Make sense.

This would need us to build:

  1. A front-end to let users enter these, may be up to 1000 each?
  2. Store these against a single key, as a json {"allowlist" : ["domain1", "domain2", ...], "denylist": ["domain1", "domain2", ...]}?
  3. A simple password-based auth needed, because otherwise, anyone may be able to add/remove from the KV.

Unsure Failed Deployments on deno-deploy.

image

After linking to the repo, there is an error as stated above. (1st pic)
Status on https://______.deno.dev/ is currently online and working but the latest changes currently does not push/follow.

Time-based rules

Allow users to set time ranges in increments of 30m against each blocklist.

Example:

Blocklist BL1 form 10:30 11:00
Blocklist BL2 from 12:00 23:00
Blocklist BL3 from 22:00 06:00
Blocklist BL7 from 10:30 11:00
and so on...

The stamp generated would be :stamp(map-of-time-ranges-to-blocklists) where map is {time-range -> set-of-blocklists}. For the example above, this would be:

(10:30-11:00) -> [BL1, BL7]
(12:00-23:00) -> [BL2]
(22:00-06:00) -> [BL3]

stamp(map) => stamp(time-slice) + stamp(blocklists)
stamp(blocklists) => existing implementation


stamp(time-slice) => base64(dictionary-encoding(time-slice))
dictionary-encoding(time-slice) => {(0, 00:00), (1, 00:30), (2, 01:00), (3, 01: 30), (4, 02:00), (5, 02:30), (6, 03:00),...}

Deno Deploy Upstream Error

45 [Error] 2022-01-22T15:47:49.753Z E RethinkPlugin [rx.o6wcl2xi55.k9ufww4cca] exception {"isException":true,"exceptionStack":"Error: [rx.o6wcl2xi55.k9ufww4cca]no upstream result\n at DNSResolver.makeRdnsResponse (file:///src/index.bundle.js:7274:25)\n at DNSResolver.resolveDns (file:///src/index.bundle.js:7251:30)\n at DNSResolver.RethinkModule (file:///src/index.bundle.js:7226:40)\n at async RethinkPlugin.executePlugin (file:///src/index.bundle.js:7597:25)","exceptionFrom":"dnsResolver","data":{}}
46 [Warn] 2022-01-22T15:52:53.263Z W DnsBlocker [rx.47n5vyse9a.sz3pl3y4nd] q: no stamp
47 [Error] 2022-01-22T15:52:53.265Z E DnsResolver [rx.47n5vyse9a.sz3pl3y4nd] main TypeError: Invalid URL at Object.opSync (deno:core/01_core.js:149:12) at opUrlParse (deno:ext/url/00_url.js:47:27) at new URL (deno:ext/url/00_url.js:320:20) at DNSResolver.resolveDnsUpstream (file:///src/index.bundle.js:7311:26) at DNSResolver.resolveDns (file:///src/index.bundle.js:7259:32) at async DNSResolver.RethinkModule (file:///src/index.bundle.js:7226:29) at async RethinkPlugin.executePlugin (file:///src/index.bundle.js:7597:25)
48 [Error] 2022-01-22T15:52:53.265Z E RethinkPlugin [rx.47n5vyse9a.sz3pl3y4nd] exception {"isException":true,"exceptionStack":"TypeError: Invalid URL\n at Object.opSync (deno:core/01_core.js:149:12)\n at opUrlParse (deno:ext/url/00_url.js:47:27)\n at new URL (deno:ext/url/00_url.js:320:20)\n at DNSResolver.resolveDnsUpstream (file:///src/index.bundle.js:7311:26)\n at DNSResolver.resolveDns (file:///src/index.bundle.js:7259:32)\n at async DNSResolver.RethinkModule (file:///src/index.bundle.js:7226:29)\n at async RethinkPlugin.executePlugin (file:///src/index.bundle.js:7597:25)","exceptionFrom":"dnsResolver","data":{}}
49 [Error] Error: no upstream at DNSResolver.resolveDnsUpstream (file:///src/index.bundle.js:7303:24) at DNSResolver.resolveDns (file:///src/index.bundle.js:7259:32) at async DNSResolver.RethinkModule (file:///src/index.bundle.js:7226:29) at async RethinkPlugin.executePlugin (file:///src/index.bundle.js:7597:25)

Deploy DoH to Fly.io and Deno Deploy

Fly.io free-tier supports both raw UDP/TCP and HTTP/S. We've already done the test runs behind a Nginx/Lua proxy to confirm this is do-able, but the right idea would be to serve requests on Fly.io via Deno.

Probably a new request-handler, a build, and a deploy script away from getting this done.

The Deno Runtime APIs also differ from what's available on Cloudflare Workers, so that's something to keep an eye on.

Deno Deploy Runtime is compatible with Cloudflare Workers, as both of them are adaptions of Service Worker API.

Deno Deploy is different from Deno (CLI).

This issue tracks impl DoH only. Support for DoT and DoQ can be added to in later iterations, and probably require a non-Deno (?) setup and so a bigger task.

Caching changes for Workers causing issues on Fly

Missing event.waitUntil on Fly/NodeJS in DNSResponseBlock.

2021-12-28T15:09:51.110 app[552489aa] maa [info] Adding to local cache
2021-12-28T15:09:51.111 app[552489aa] maa [info] Error At : DNSResponseBlock -> RethinkModule
2021-12-28T15:09:51.111 app[552489aa] maa [info] TypeError: event.waitUntil is not a function
2021-12-28T15:09:51.111 app[552489aa] maa [info]     at putCache (file:///node-dir/src/dns-operation/dnsResponseBlock.js:99:9)
2021-12-28T15:09:51.111 app[552489aa] maa [info]     at DNSResponseBlock.RethinkModule (file:///node-dir/src/dns-operation/dnsResponseBlock.js:41:7)
2021-12-28T15:09:51.111 app[552489aa] maa [info]     at RethinkPlugin.executePlugin (file:///node-dir/src/helpers/plugin.js:171:34)
2021-12-28T15:09:51.111 app[552489aa] maa [info]     at runMicrotasks (<anonymous>)
2021-12-28T15:09:51.111 app[552489aa] maa [info]     at processTicksAndRejections (node:internal/process/task_queues:96:5)
2021-12-28T15:09:51.111 app[552489aa] maa [info]     at async proxyRequest (file:///node-dir/src/index.js:62:5)
2021-12-28T15:09:51.111 app[552489aa] maa [info]     at async handleHTTPRequest (file:///node-dir/src/server.js:429:18)
2021-12-28T15:09:51.111 app[552489aa] maa [info] exec-plugin.bj5cf4b8hu: 36.81ms DNSResponseBlock got-res
2021-12-28T15:09:51.111 app[552489aa] maa [info] In dnsResponseBlockCallBack {"isBlocked":false,"blockedB64Flag":"1:UAAACIAA","blockedTag":[]}
2021-12-28T15:09:51.112 app[552489aa] maa [info] {"isException":true,"exceptionStack":"TypeError: event.waitUntil is not a function\n    at putCache (file:///node-dir/src/dns-operation/dnsResponseBlock.js:99:9)\n    at DNSResponseBlock.RethinkModule (file:///node-dir/src/dns-operation/dnsResponseBlock.js:41:7)\n    at RethinkPlugin.executePlugin (file:///node-dir/src/helpers/plugin.js:171:34)\n    at runMicrotasks (<anonymous>)\n    at processTicksAndRejections (node:internal/process/task_queues:96:5)\n    at async proxyRequest (file:///node-dir/src/index.js:62:5)\n    at async handleHTTPRequest (file:///node-dir/src/server.js:429:18)","exceptionFrom":"DNSResponseBlock RethinkModule","data":{"isBlocked":false,"blockedB64Flag":"1:UAAACIAA","blockedTag":[]}}

fail when deploy to fly

how to fix health test in fly io i was try to deploy in fly but always fail in health check ? y can see eror in my action log

Unhandled exceptions in currentRequest.js and dnsBlock.js

dnsBlock.js:

2021-12-24T12:34:16.878 app[4ce977ae] cdg [info] Error At : DNSBlock -> RethinkModule
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info] TypeError: Cannot read properties of undefined (reading 'length')
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at DNSBlock.RethinkModule (file:///node-dir/src/dns-operation/dnsBlock.js:37:57)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at RethinkPlugin.executePlugin (file:///node-dir/src/helpers/plugin.js:158:34)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at runMicrotasks (<anonymous>)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at processTicksAndRejections (node:internal/process/task_queues:96:5)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at async proxyRequest (file:///node-dir/src/index.js:60:5)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at async handleHTTPRequest (file:///node-dir/src/server.js:427:18)

currentRequest.js:

2021-12-24T12:34:16.878 app[4ce977ae] cdg [info] TypeError: Cannot read properties of undefined (reading 'id')
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at CurrentRequest.dnsExceptionResponse (file:///node-dir/src/helpers/currentRequest.js:29:39)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at loadException (file:///node-dir/src/helpers/plugin.js:346:18)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at RethinkPlugin.dnsBlockCallBack (file:///node-dir/src/helpers/plugin.js:282:5)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at RethinkPlugin.executePlugin (file:///node-dir/src/helpers/plugin.js:163:26)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at runMicrotasks (<anonymous>)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at processTicksAndRejections (node:internal/process/task_queues:96:5)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at async proxyRequest (file:///node-dir/src/index.js:60:5)
2021-12-24T12:34:16.878 app[4ce977ae] cdg [info]     at async handleHTTPRequest (file:///node-dir/src/server.js:427:18)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.