c127/mikrodoh

By c127

Updated 4 days ago

Light weight daemon DNS-over-HTTPs for Weak Devices.

Image
Networking
Security
Internet of things
0

621

c127/mikrodoh repository overview

MikroDoH

A small C++17 daemon that accepts plain UDP DNS queries and forwards them as DNS-over-HTTPS. It targets low-end routers - the reference device is a MikroTik RB4011iGS+ running the proxy in a RouterOS v7 container.

Repository: https://github.com/c127dev/mikrodoh/

Design

  • One HTTP/2 connection per event loop. Each worker drives a curl_multi handle with CURLPIPE_MULTIPLEX and CURLOPT_PIPEWAIT, so hundreds of queries share a single TLS connection and no TLS handshake is repeated.
  • No thread per query. A producer thread reads the UDP socket and shards queries to N workers. Concurrency is bounded by MAX_INFLIGHT, not by thread count.
  • Load shedding. Queries above the in-flight cap are dropped instead of queued, so accepted queries keep bounded latency under burst.
  • Cipher selection from CPU features. See below.

Cipher selection

TLS record crypto is the throughput ceiling on CPUs without an AES engine, because AES-GCM then runs in software. ChaCha20-Poly1305 is much faster in that case. CIPHER=auto probes the CPU at startup and picks accordingly:

CPUProbeSelected
x86 with AES-NICPUID.1:ECX[25]AES-GCM
x86 without AES-NICPUID.1:ECX[25]ChaCha20-Poly1305
ARMv8 with crypto extensionsgetauxval(AT_HWCAP) & HWCAP_AESAES-GCM
ARMv7 (Cortex-A15 and similar)getauxval(AT_HWCAP2) & HWCAP2_AESChaCha20-Poly1305
RISC-V, anything elsenoneChaCha20-Poly1305

CIPHER=chacha and CIPHER=aes override the probe. The selection is printed in the startup banner.

OpenSSL assembly

The record crypto belongs to OpenSSL, not to this daemon. OpenSSL carries hand-written assembly for both AEADs and dispatches on CPU features at runtime:

TargetChaCha20Poly1305
ARMv7chacha-armv4.pl, NEONpoly1305-armv4.pl, NEON
ARMv8chacha-armv8.plpoly1305-armv8.pl
x86_64chacha-x86_64.pl, SSSE3/AVX2poly1305-x86_64.pl

Two things have to hold for a ChaCha20 build to reach those paths:

  1. OpenSSL was not configured with no-asm. Some minimal or hardened builds are, and then ChaCha20 and Poly1305 fall back to portable C, which erases the reason to prefer them.
  2. The kernel reports NEON in AT_HWCAP. OpenSSL reads it into OPENSSL_armcap at startup and picks the NEON code paths from it.

scripts/crypto-bench.sh checks both and measures the two AEADs on the device:

./scripts/crypto-bench.sh
OPENSSL_armcap=0 ./scripts/crypto-bench.sh   # same run with ARM asm disabled

Its numbers are the ground truth for CIPHER; the CPU probe is only a prediction of them.

Configuration

Every key is read from the environment. boards/ holds ready-made sets, one per supported device, in --env-file format.

KeyDefaultMeaning
LISTEN_PORT53UDP port to bind
DOH_URLhttps://1.1.1.1/dns-queryUpstream DoH resolver
CIPHERautoauto, chacha or aes
WORKERSCPU coresEvent-loop threads; track cores, not query volume
MAX_INFLIGHT512In-flight cap before queries are shed
RCVBUF_KB4096UDP receive/send buffer, in kB
CHECK_CERTtrueVerify the resolver's certificate
TCP_KEEP_ALIVE0TCP keep-alive interval in seconds, 0 disables
CACHE0Response TTL in seconds, 0 disables the cache
Boards
FileDevice
boards/mikrotik-rb4011igs.confMikroTik RB4011iGS+ (AL21400, 4x Cortex-A15)
boards/generic-armv7.confAny ARMv7-A device
boards/generic-arm64.confAny ARMv8-A device
boards/generic-riscv64.confAny RV64GC device
boards/generic-x86_64.confAny x86_64 host

Board files also carry keys the daemon ignores: MIKRODOH_TUNE, the compiler flags scripts/build.sh passes to cmake, plus MIKRODOH_PLATFORM and MIKRODOH_VARIANT, which name the image a board gets built into.

Adding a device means copying the closest generic file, measuring, and pinning the values that differ.

Build

./scripts/build.sh                        # host defaults
./scripts/build.sh mikrotik-rb4011igs     # with that board's tuning flags

Needs cmake, a C++17 compiler and libcurl headers. The binary lands in build/mikrodoh.

Run

set -a; . ./boards/generic-x86_64.conf; set +a
./build/mikrodoh

End-to-end check, builds and resolves a name through the proxy on port 6353:

./scripts/test.sh

License

Apache License 2.0. See LICENSE.

Tag summary

Content type

Image

Digest

sha256:a44a67990

Size

7.1 MB

Last updated

4 days ago

docker pull c127/mikrodoh