Skip to main content

HTTP and QUIC Encrypted Ingress

Encrypted DNS ingress over HTTP and QUIC, including DoH, HTTP/2, optional HTTP/3, and DoQ.

http_server

Purpose

Provides DNS over HTTPS and can serve HTTP/1.1, HTTP/2, and optional HTTP/3.

Example Configuration

- tag: doh_in
type: http_server
args:
# HTTPS / DoH bind address
listen: ":443"
# Certificate required for HTTPS and HTTP/3
cert: "/etc/oxidns/server.crt"
# Private key required for HTTPS and HTTP/3
key: "/etc/oxidns/server.key"
# Also enable DoH over HTTP/3 when TLS is present
enable_http3: true
# Restore the real client IP from a reverse-proxy header
src_ip_header: "X-Forwarded-For"
# Idle timeout for HTTP/1.1, HTTP/2, and HTTP/3 connections
idle_timeout: 30
entries:
# Standard RFC 8484 endpoint
- path: "/dns-query"
exec: "seq_main"
# Enable the JSON DNS API for this entry
json_api: true
# Alternate path for a different policy chain
- path: "/dns-alt"
exec: "seq_alt"

Configuration Details

entries

  • Type: array; Required: yes; Default: none
  • Purpose: Maps HTTP request paths to executors.
  • Examples:
    • path: "/dns-query", exec: "seq_main"
    • path: "/dns-alt", exec: "seq_alt"
  • Each item contains:
    • path
      • Type: string
      • Required: yes
      • Purpose: DoH request path.
      • Constraint: must start with /.
    • exec
      • Type: string
      • Required: yes
      • Purpose: Executor for requests hitting that path.
      • Constraint: must reference an existing executor plugin.
    • json_api
      • Type: boolean
      • Required: no
      • Default: false
      • Purpose: Enables or disables the JSON DNS API for this path.
  • Runtime impact:
    • Different paths can enter different policy chains.

listen

  • Type: string; Required: yes; Default: none
  • Purpose: Defines the HTTP or HTTPS bind address.
  • Examples:
    • listen: ":80"
    • listen: ":443"
  • Supported forms:
    • ip:port
    • [ipv6]:port
    • :port
  • Runtime impact:
    • :port means dual-stack [::]:port; use 0.0.0.0:port for IPv4-only.

src_ip_header

  • Type: string; Required: no; Default: none
  • Purpose: Header name used to read the original client address.
  • Example: src_ip_header: "X-Forwarded-For"
  • Runtime impact:
    • Allows a reverse proxy to pass through the real source address.

cert

  • Type: string; Required: no; Default: none
  • Purpose: HTTPS certificate file path.
  • Example: cert: "/etc/oxidns/server.crt"
  • Runtime impact:
    • HTTPS is enabled only when cert and key are both present.

key

  • Type: string; Required: no; Default: none
  • Purpose: HTTPS private key file path.
  • Example: key: "/etc/oxidns/server.key"
  • Runtime impact:
    • HTTPS is enabled only when cert and key are both present.

idle_timeout

  • Type: integer; Required: no; Default: 30
  • Unit: seconds
  • Purpose: Controls idle HTTP connection lifetime.
  • Example: idle_timeout: 30
  • Runtime impact:
    • Affects HTTP/1.1 / HTTP/2 long-lived connection behavior.

enable_http3

  • Type: boolean; Required: no; Default: false
  • Purpose: Enables HTTP/3 in addition to HTTP/2.
  • Example: enable_http3: true
  • Requirements:
    • cert and key must both be configured.
  • Runtime impact:
    • Starts an additional QUIC-based DoH listener task.
    • HTTP/1.1 / HTTP/2 responses include Alt-Svc: h3=":<listen-port>"; ma=86400 so clients can discover HTTP/3 on the same port.

Behavior

  • Each path can route to a different exec, which is useful for multi-entry policies.
  • Registers both GET and POST DoH access methods commonly used for RFC 8484.
  • With json_api enabled, GET requests can use JSON API parameters: name (required), type (optional, defaults to 1, numeric or text RR type), cd, do, edns_client_subnet, and random_padding (accepted and ignored).
  • If a GET request includes both dns= and name/type, RFC 8484 dns= takes precedence.
  • ct=application/dns-message returns DNS wire format; otherwise the JSON API returns application/dns-json.
  • HTTP/1.1 and HTTP/2 are negotiated automatically on the same listener with no extra configuration.
  • When HTTP/3 is enabled, an extra QUIC listener is started.
  • When HTTP/3 is enabled, HTTP/1.1 / HTTP/2 responses advertise the same listen port through the Alt-Svc header.

Good Fits

  • Standard DoH exposure.
  • Multiple DNS policy entry points on one listener.
  • Deployments behind a reverse proxy that preserve the original client IP with src_ip_header.
Notes
  • enable_http3: true requires both cert and key.
  • If a reverse proxy is involved, define a trusted boundary for src_ip_header to avoid spoofed source IPs.

quic_server

Purpose

Provides DNS over QUIC.

Example Configuration

- tag: doq_in
type: quic_server
args:
# Policy chain used by DoQ requests
entry: "seq_main"
# Common DoQ port
listen: ":853"
# TLS certificate is mandatory for DoQ
cert: "/etc/oxidns/server.crt"
# TLS private key is mandatory for DoQ
key: "/etc/oxidns/server.key"
# QUIC transport idle timeout in seconds
idle_timeout: 30

Configuration Details

entry

  • Type: string; Required: yes; Default: none
  • Purpose: Selects the executor used by DoQ requests.
  • Example: entry: "seq_main"
  • Requirements:
    • Must reference an existing executor plugin.

listen

  • Type: string; Required: yes; Default: none
  • Purpose: Defines the QUIC bind address.
  • Example: listen: ":853"
  • Runtime impact:
    • Occupies a UDP port.
    • :port means dual-stack [::]:port; use 0.0.0.0:port for IPv4-only.

cert

  • Type: string; Required: yes; Default: none
  • Purpose: Path to the TLS certificate required by DoQ.
  • Example: cert: "/etc/oxidns/server.crt"
  • Runtime impact:
    • The listener cannot start if the certificate is invalid.

key

  • Type: string; Required: yes; Default: none
  • Purpose: Path to the TLS private key required by DoQ.
  • Example: key: "/etc/oxidns/server.key"
  • Runtime impact:
    • The listener cannot start if the private key is invalid.

idle_timeout

  • Type: integer; Required: no; Default: none
  • Unit: seconds
  • Purpose: Controls QUIC transport idle timeout.
  • Example: idle_timeout: 30
  • Runtime impact:
    • Affects when idle QUIC connections are reclaimed.

Behavior

  • DoQ always requires TLS, so cert and key are mandatory.
  • ALPN is fixed to doq.
  • Each bidirectional stream represents one independent DNS exchange.

Good Fits

  • Encrypted DNS ingress with low latency.
  • Modern clients that benefit from QUIC transport behavior.
Notes
  • The listener still consumes a UDP port underneath.
  • Do not bind the same address and port as udp_server.