|
| 1 | +# lazydns v0.3 — Release Notes |
| 2 | + |
| 3 | +A high-performance DNS forwarder with a built-in web dashboard, written in Rust. |
| 4 | + |
| 5 | +This release covers v0.3.0 through v0.2. It adds a real-time WebUI, cache persistence, DNSSEC-safe caching, and simplifies the configuration experience. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Highlights |
| 10 | + |
| 11 | +### Web dashboard |
| 12 | + |
| 13 | +lazydns now ships with a built-in web dashboard (Svelte + axum). No external tools needed to see what your DNS server is doing. |
| 14 | + |
| 15 | +- **Live query logs**: every DNS query streams in real time via SSE, with client IP, domain, response time, and answers |
| 16 | +- **Security events**: rate-limit violations, blocked domains, upstream failures, and ACL denials appear instantly |
| 17 | +- **Upstream health**: per-upstream success rate, average latency, and failure counts |
| 18 | +- **Alert engine**: configurable rules with deduplication and webhook notifications |
| 19 | +- **Dark mode**, responsive layout, embedded assets (single binary with `web-embed`) |
| 20 | + |
| 21 | +Enable it in your config: |
| 22 | + |
| 23 | +```yaml |
| 24 | +web: |
| 25 | + enabled: true |
| 26 | + listen: "0.0.0.0:8002" |
| 27 | +``` |
| 28 | +
|
| 29 | +Build with `--features web-embed` to compile the dashboard into the binary. |
| 30 | + |
| 31 | +### Configuration viewer |
| 32 | + |
| 33 | +The Admin page now has a **Configuration** tab that shows your currently loaded plugins, sequences (as a visual step-by-step flow), and server settings. No more guessing what your server is actually running. Click any plugin to expand its full arguments. |
| 34 | + |
| 35 | +When a config reload fails, the error message from the validator is shown inline so you can fix the problem without digging through logs. |
| 36 | + |
| 37 | +### Cache persistence |
| 38 | + |
| 39 | +The cache can now survive server restarts. Set `dump_file` and lazydns saves cached responses to a binary file on shutdown, then restores them on startup (skipping any that have expired). |
| 40 | + |
| 41 | +```yaml |
| 42 | +- tag: cache |
| 43 | + type: cache |
| 44 | + args: |
| 45 | + size: 2048 |
| 46 | + enable_lazycache: true |
| 47 | + dump_file: /var/lib/lazydns/cache.dump |
| 48 | + dump_interval: 300 |
| 49 | +``` |
| 50 | + |
| 51 | +### Simpler configuration |
| 52 | + |
| 53 | +We removed confusing and dead config options across the board: |
| 54 | + |
| 55 | +- **`fallback`**: removed `threshold` and `always_standby` keys that were silently ignored (never implemented). |
| 56 | +- **`domain_validator`**: removed the `blacklist` option. Use `domain_set` + `black_hole` for domain blocking, which is more capable and supports file-based lists. |
| 57 | +- **`cache`**: removed 5 internal tuning knobs (`refresh_worker_count`, `refresh_queue_capacity`, `enable_cleanup`, `cleanup_interval_secs`, `cleanup_pressure_threshold`). These are now sensible built-in defaults. |
| 58 | +- **`priority`**: removed entirely. The sequence order in your config determines execution order; the `priority` field never did anything. |
| 59 | + |
| 60 | +--- |
| 61 | + |
| 62 | +## Bug fixes |
| 63 | + |
| 64 | +### Forwarding |
| 65 | + |
| 66 | +- UDP responses were cross-pollinated between concurrent queries on the shared socket. Now multiplexed by query ID with a dedicated demux loop. |
| 67 | +- A response arriving at the exact moment of a timeout could be dropped. Now uses a fair select so the response wins. |
| 68 | +- Average response time (used by the `fastest` load-balancing strategy) was updated non-atomically, losing samples under concurrency. Fixed with CAS. |
| 69 | +- Replaced `std::sync::Mutex` with `parking_lot::Mutex` to avoid lock poisoning on panics. |
| 70 | + |
| 71 | +### Cache |
| 72 | + |
| 73 | +- Cached responses were mutated in place when served, corrupting the cache for subsequent queries. Now deep-cloned. |
| 74 | +- The question section of cached responses was not synced to the current request, causing query/response mismatches on cache hits. |
| 75 | +- A cache key stayed marked "refreshing" forever after the first LazyCache background refresh, silently disabling prefetch for that key. Now cleared via a completion hook. |
| 76 | +- Cache keys did not include DNSSEC flags (DO/AD/CD), causing DNSSEC-enabled responses to be served to clients that did not request DNSSEC. Now included. |
| 77 | + |
| 78 | +### Servers |
| 79 | + |
| 80 | +- TCP/DoT responses larger than 65535 bytes silently truncated the length prefix, corrupting the stream. Now clamped with an error. |
| 81 | +- DoQ `local_addr()` would panic on failure. Now degrades gracefully. |
| 82 | + |
| 83 | +### Config |
| 84 | + |
| 85 | +- The `config-simple.yaml` example used an unimplemented sequence syntax that produced a no-op sequence. Fixed. |
| 86 | +- Upstream address formats were inconsistent across examples. Standardized to `addr:` mapping form. |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +## Protocol support |
| 91 | + |
| 92 | +All five DNS transport protocols are supported: |
| 93 | + |
| 94 | +| Protocol | Config type | Port example | |
| 95 | +|---|---|---| |
| 96 | +| UDP | `udp_server` | `:53` | |
| 97 | +| TCP | `tcp_server` | `:53` | |
| 98 | +| DoT | `dot_server` | `:853` | |
| 99 | +| DoH | `doh_server` | `:443` | |
| 100 | +| DoQ | `doq_server` | `:853` | |
| 101 | + |
| 102 | +DoT, DoH, and DoQ require TLS certificates (`cert_file` / `key_file`). |
| 103 | + |
| 104 | +--- |
| 105 | + |
| 106 | +## Feature flags |
| 107 | + |
| 108 | +```bash |
| 109 | +# Minimal (UDP/TCP only, no web) |
| 110 | +cargo build |
| 111 | +
|
| 112 | +# With WebUI dashboard |
| 113 | +cargo build --features web |
| 114 | +
|
| 115 | +# With embedded WebUI (single binary) |
| 116 | +cargo build --features web-embed |
| 117 | +
|
| 118 | +# Everything |
| 119 | +cargo build --features full |
| 120 | +``` |
| 121 | + |
| 122 | +--- |
| 123 | + |
| 124 | +## Getting started |
| 125 | + |
| 126 | +```bash |
| 127 | +# Build |
| 128 | +cargo build --features web-embed |
| 129 | +
|
| 130 | +# Run with the example config |
| 131 | +./target/debug/lazydns -c examples/etc/config.yaml -d examples/etc/ |
| 132 | +
|
| 133 | +# Open the dashboard |
| 134 | +open http://127.0.0.1:8002 |
| 135 | +``` |
| 136 | + |
| 137 | +Full documentation: https://lazywalker.github.io/lazydns/docs/ |
0 commit comments