Skip to content

Add support for ODoH (RFC9230)#31

Merged
jaromil merged 7 commits into
masterfrom
ODoH
Apr 14, 2026
Merged

Add support for ODoH (RFC9230)#31
jaromil merged 7 commits into
masterfrom
ODoH

Conversation

@danielinux

Copy link
Copy Markdown
Collaborator

• Added RFC9230 ODoH support:

  • dohd -O acts as Target (accepts application/oblivious-dns-message)
  • ns2dohd -O acts as Client
  • dohproxyd is Proxy (ODoH + legacy DoH).

Includes proxy auth allowlist, key/config tooling, docs/manpages, install targets, and self-test scripts.

Copilot AI review requested due to automatic review settings February 15, 2026 14:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds RFC9230 Oblivious DoH (ODoH) support across the project, including a target mode in dohd, a new standalone proxy (dohproxyd), and an ODoH-capable client gateway (ns2dohd), plus accompanying tooling, tests, docs, and CI/install targets.

Changes:

  • Implement ODoH message/config handling, key generation tooling, and proxy authorization allowlisting.
  • Refactor event loop to epoll and introduce fixed-size memory pools + O(1) client lookup in dohd.
  • Add unit/integration/stress test harnesses, manpages, install targets, and CI self-test workflow.

Reviewed changes

Copilot reviewed 44 out of 45 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tools/odoh-keygen.c New key/config generator producing dohd-compatible ODoH materials
tools/Makefile Build targets for odoh-keygen (release/debug/asan/clean)
test/valgrind_test.sh Valgrind-based leak detection runner for dohd
test/test_url64_extended.c Additional url64 decoder edge-case unit tests
test/test_request_leaks.sh Integration script to exercise request lifecycle/memory behavior
test/test_mempool.c Unit tests for the new fixed-size memory pool
test/test_heap.c Unit tests for heap timer scheduling behavior
test/test_dns_parser.c Unit tests for DNS parsing/TTL extraction logic
test/test_concurrent.sh Concurrent request stress test script
test/test_client_lifecycle.sh Client connect/disconnect lifecycle stress test
test/stress_test.sh Multi-worker stress runner that builds/launches dohd
test/stress_flood.sh Connection flood stress runner for resource exhaustion behavior
test/stress_escalate.sh Escalating load test to find failure thresholds
test/stress_chaos.sh Chaos-style randomized request pattern stress runner
test/run_asan_test.sh ASAN runner script for dohd
test/gen_test_certs.sh Helper to generate self-signed TLS certs for tests
test/README.md Documentation for unit/integration/stress/leak tests
test/Makefile Expanded test build + check/integration/stress/valgrind targets
src/proxy_auth.h API for proxy certificate public-key hash allowlist
src/proxy_auth.c Loads allowlist from directory + checks peer certificate key hash
src/odoh.h Public ODoH config/message APIs and context structs
src/odoh.c HPKE-based ODoH query/response encryption/decryption implementation
src/mempool.h Fixed-size pool API and stats struct
src/mempool.c Pool implementation with freelist + bitmap double-free detection
src/libevquick.c Switch event multiplexing from poll-style to epoll + deferred frees
src/dohd.c ODoH target mode, proxy auth gate, request timeouts, mempool + client hash table integration
src/Makefile Link in new modules (mempool/odoh/proxy_auth) for dohd
proxy/Makefile Build rules for new dohproxyd binary
ns2dohd/README.md Docs for ns2dohd including ODoH mode usage
ns2dohd/Makefile Build rules for new ns2dohd binary (including odoh.o)
man/odoh-keygen.1 Manpage for ODoH key/config generator
man/ns2dohd.8 Manpage for the DNS-to-DoH gateway daemon
man/dohproxyd.8 Manpage for the DoH/ODoH proxy daemon
man/dohd.8 Manpage updates documenting ODoH target mode and proxy allowlist
examples/odoh/selftest-proxy-target-curl.sh Local proxy+target self-test script using curl
examples/odoh/dodh_targets Example legacy target list file for proxy
examples/odoh/deploy-target-example.sh Example target deployment script/flags
examples/odoh/deploy-proxy-example.sh Example proxy deployment script/flags
README.md Top-level docs for ns2dohd/dohproxyd + ODoH guidance and examples
Makefile Top-level build/test/stress/install/uninstall targets + subdir builds
.gitignore Ignore additional built artifacts and test outputs
.github/workflows/pr-build-install-selftest.yml CI: build+install to staging prefix + run ODoH self-test
Comments suppressed due to low confidence (1)

src/dohd.c:680

  • dns_send_request_h2() returns -1 for several error cases (e.g., ODoH decrypt failure, non-query DNS header) without destroying the req_slot or sending an HTTP/2 error response. Since the caller ignores the return value, this leaves the stream/user_data and request resources hanging until client disconnect. Ensure these error paths submit an appropriate HTTP error (e.g., 400/415/500) and call dohd_destroy_request(req).
    if (oblivion_mode) {
        if (!req->is_odoh)
            return -1;
        if (odoh_target_decrypt_query(&odoh_target,
                req->h2_request_buffer, (uint16_t)req->h2_request_len,
                plain_dns, &plain_len, &req->odoh_ctx) != 0) {
            return -1;
        }
        if (plain_len > sizeof(req->h2_request_buffer))
            return -1;
        memcpy(req->h2_request_buffer, plain_dns, plain_len);
        req->h2_request_len = plain_len;
    }
    /* Parse DNS header: only check the qr flag. */
    hdr = (struct dns_header *)req->h2_request_buffer;
    if (hdr->qr != 0) {
        return -1;
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/dohd.c
Comment thread src/libevquick.c
Comment thread tools/Makefile Outdated
Comment thread tools/odoh-keygen.c
h2_cb_on_header: Instead of passing value + 6 (unbounded) directly to dohd_url64_check/dohd_url64_decode, the code now copies exactly valuelen - strlen(GETDNS) bytes into a stack-local
  b64tmp buffer and NUL-terminates it before calling the helpers.

h2_cb_on_frame_recv: Added an is_h2_get field to req_slot, set to 1 when a GET :path payload is successfully decoded. The content-type check now reads (!req->content_type_seen &&
  !req->is_h2_get), so valid GET requests aren't rejected with 415.

dohd_new_connection: evquick_addevent's return value is now checked; on failure, the wolfSSL object is freed, the socket closed, and the pool slot returned — preventing socket/memory leaks.

heap_insert: realloc now uses a temporary pointer _tmp; the original heap->top is only overwritten on success, preventing the pointer loss that left the heap in a corrupted state.
@jaromil jaromil merged commit cb4e784 into master Apr 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants