← First Pair Library

13 Security engineering in rgbdns

13.1 The packet is hostile

DNS combines nearly every parser hazard: nested lengths, compression pointers, variable counts, binary strings, recursive relationships, and network-facing availability requirements. “Written in Rust” removes broad classes of memory corruption, but it does not automatically prevent allocation bombs, infinite loops, CPU amplification, path races, policy errors, or accepting incoherent messages.

rgbdns therefore uses several layers:

Property tests in tests/packet_properties.rs feed arbitrary bytes to the decoder and exercise encode/decode invariants. Golden CDB fixtures compare compiled output with the expected djbdns layout. Network tests cross real UDP and TCP boundaries. Compatibility tests are valuable here because a parser can be safe yet subtly wrong, or compatible yet unsafe.

13.2 Least privilege and filesystem boundaries

The *-conf commands generate service directories whose run scripts execute the daemon under a selected account. rgbdns’s setuidgid resolves the user and group, initializes supplementary groups, drops GID and UID, verifies the result, and directly replaces itself with the target program. Direct replacement preserves signals and exit status and avoids an extra shell-owned process.

Generated paths are shell-quoted and support binaries by absolute path. Configuration writers reject unsafe existing file types and apply intentional modes. CDB and AXFR update workflows install only complete outputs.

Privilege dropping is not a substitute for a restricted service account, read-only data, network policy, or supervisor hardening. It is one layer in a deployment.