runbound 0.3.2

RFC-compliant DNS resolver — drop-in Unbound with REST API, ACME auto-TLS, HMAC audit log, and master/slave HA
[package]
name = "runbound"
version = "0.3.2"
edition = "2021"
authors = ["redlemonbe <https://github.com/redlemonbe>"]
license = "PolyForm-Noncommercial-1.0.0"
description = "RFC-compliant DNS resolver — drop-in Unbound with REST API, ACME auto-TLS, HMAC audit log, and master/slave HA"
readme = "README.md"
repository = "https://github.com/redlemonbe/Runbound"
homepage = "https://github.com/redlemonbe/Runbound"
keywords = ["dns", "unbound", "resolver", "dnssec", "acme"]
categories = ["network-programming", "command-line-utilities"]

[dependencies]
# Async runtime
tokio = { version = "1", features = ["full"] }

# DNS engine — DoT / DoH / DoQ / DNSSEC
hickory-server   = { version = "0.24", features = [
    "dnssec-ring",
    "dns-over-rustls",
    "dns-over-https-rustls",
    "dns-over-quic",
] }
hickory-resolver = { version = "0.24", features = [
    "dnssec-ring",
    "tokio-runtime",
    "dns-over-rustls",
    "dns-over-https-rustls",
] }
hickory-proto    = { version = "0.24", features = [
    "dnssec-ring",
    "dns-over-rustls",
    "dns-over-https-rustls",
    "dns-over-quic",
] }

# TLS certificate loading — must match hickory-server 0.24's rustls 0.21
rustls           = { version = "0.21", features = ["dangerous_configuration"] }
rustls-pemfile   = "1"

# REST API
axum       = { version = "0.7", features = ["json"] }
axum-extra = { version = "0.9", features = ["typed-header"] }
tower      = { version = "0.5", features = ["limit"] }
tower-http = { version = "0.6", features = ["limit", "trace"] }

# Serialization
serde       = { version = "1", features = ["derive"] }
serde_json  = "1"
toml        = "0.8"
serde_with  = "3"

# Error handling
thiserror = "2"
anyhow    = "1"

# Logging
tracing            = "0.1"
tracing-subscriber = { version = "0.3", features = ["json", "env-filter"] }
tracing-appender   = "0.2"

# Utils
uuid            = { version = "1", features = ["v4", "serde"] }
sha2            = "0.10"
hmac            = "0.12"
getrandom       = "0.3"
hex             = "0.4"
subtle          = "2"
tempfile        = "3"
regex           = "1"
humantime       = "2"
humantime-serde = "1"

# HTTP client (feeds fetch + ACME HTTP-01 bridge)
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }

# ACME (Let's Encrypt) — ring backend only; HTTP done via reqwest bridge
instant-acme = { version = "0.8", default-features = false, features = ["ring"] }

# Zero-copy byte buffers — used in ACME HttpClient bridge
bytes = "1"

# HTTP types shared across hyper / axum / instant-acme
http = "1"

# Stream utilities — SSE streaming for /stats/stream endpoint
futures-util = "0.3"

# Async trait (required by RequestHandler impl)
async-trait = "0.1"

# Jemalloc (Linux only)
tikv-jemallocator = "0.6"

# Concurrent HashMap — replaces Mutex<HashMap> in rate limiter (lock-free reads)
dashmap = "6"

# Fast non-cryptographic hasher — RandomState seeded by OS CSPRNG at startup,
# HashDoS resistant (v0.8+). Used for rate-limiter DashMaps (IpAddr keys).
# Zone-lookup HashMaps keep SipHash: DNS name keys come from untrusted network.
ahash = "0.8"

# Raw socket control — SO_REUSEPORT per-CPU UDP socket binding
socket2 = { version = "0.6", features = ["all"] }

# Low-level OS syscalls used by AF_XDP implementation
libc = "0.2"

# Lock-free atomic Arc swap — read path for LocalZoneSet with zero contention
arc-swap = "1"

# Self-signed TLS certificate generation (--gen-cert)
rcgen = "0.13"

# Slave/master sync: HTTPS server (TLS termination) + HTTPS client (cert pinning)
tokio-rustls   = "0.24"
hyper          = { version = "1", features = ["http1"] }
hyper-util     = { version = "0.1", features = ["tokio", "server-auto"] }
http-body-util = "0.1"

[dev-dependencies]

[features]
# Kernel-bypass DNS fast path via AF_XDP / eBPF.
# Requires: clang + libbpf-dev at build time (apt install clang libbpf-dev).
# No runtime C libraries needed — aya is pure Rust.
xdp = ["dep:aya"]

[dependencies.aya]
version  = "0.13"
optional = true

[profile.release]
opt-level     = 3
lto           = true
strip         = true
codegen-units = 1