Native modules (developers)
Normal use does not require modules. This guide is for developers and administrators extending the Windows or Linux service with native libraries. Modules run inside the service with its privileges, so install only trusted code and keep module files, dependencies, and configuration administrator-owned.
Load a module
The service reads *.conf files from a modules.d directory beside its config
file. Default locations are:
| Platform | Module configuration | Library type |
|---|---|---|
| Linux | /etc/mudfish-dns/modules.d/ | .so |
| Windows | %ProgramData%\Mudfish DNS\modules.d\ | .dll |
Each file contains one absolute library path per line. For example,
/etc/mudfish-dns/modules.d/10-policy.conf could contain:
/usr/lib/mudfish-dns/modules/policy.so
Files are read in filename order, then line order. Blank lines and lines starting
with # are ignored. Do not quote paths or use environment variables or inline
comments: those are not expanded. On Windows, write the full absolute path
inside the file, including for paths with spaces.
Restart the service after adding, changing, or removing a module. On Linux:
sudo systemctl restart mudfish-dns.service
On Windows, restart the Mudfish DNS service from Services. The app's Start DNS, Stop DNS, and Apply settings actions do not reload modules. An unreadable configuration, invalid path, or load/initialization error prevents the service from starting. An absent or empty module directory is allowed.
For development, repeated --module arguments specify libraries in call order
and replace automatic modules.d loading. --config FILE changes the adjacent
module directory. --restore-dns performs recovery without loading modules.
Implement hooks
Read the mudfish_dns_module.h header or
download mudfish_dns_module.h.
It defines the structures, hooks, actions, and lifetime rules used by modules.
This guide uses C ABI v2. Export mudfish_dns_module_init_v2() and check
MUDFISH_DNS_MODULE_ABI_V2 and the supplied structure size before filling in
hooks. Return zero on successful initialization.
| Hook | Called when |
|---|---|
on_dns_query | A parsed query is accepted, before cache lookup or forwarding. |
on_dns_response | A response is selected, before caching or returning it to the client. Cached responses also pass through this hook. |
on_web_hello | Initial HTTP Host/TLS SNI inspection finishes, before connecting or processing the initial data. |
on_web_data | Subsequent client data or server data is read, before forwarding it. |
DNS actions
For v2 DNS hooks, return 0 for success and set result->action:
| Action | Effect |
|---|---|
MUDFISH_DNS_CONTINUE | Continue to the next module and normal processing. |
MUDFISH_DNS_ALLOW | End the current hook chain and continue normal resolution or return the selected response. |
MUDFISH_DNS_BLOCK | Return REFUSED. |
MUDFISH_DNS_DROP | Discard without sending a DNS response. |
MUDFISH_DNS_ANSWER | Synthesize an answer using the supplied IPv4/IPv6 address and TTL. |
MUDFISH_DNS_REPLACE | Use a complete DNS wire response supplied by the module. |
Do not return the action directly from a v2 DNS hook. A nonzero function return
or invalid result produces SERVFAIL. ALLOW ends only the current hook chain;
it does not bypass domain rules, transport permissions, or certificate checks.
Query results other than DROP still pass through the response hooks.
Web hooks return MUDFISH_DNS_CONTINUE or MUDFISH_DNS_REJECT directly.
Web rejection closes the connection. Web hooks
require enabled web protection and do not expose decrypted HTTPS content.
Buffers, threading, and caching
Input events and buffers are read-only and valid only during the callback. A replacement response must use module-owned memory valid until that module's next callback or destruction; do not return stack memory or a borrowed event pointer. Its DNS ID, opcode, and question must match the original query. Callbacks for one instance are serialized but can run on different threads; keep them short and do not unwind across the ABI.
Synthetic, replaced, blocked, or dropped results are not stored in the host cache. Replacing a cached response does not alter the original cached entry. The host clears the AD flag on replacement responses and does not validate or re-sign DNSSEC; modules modifying signed data must handle invalidated signatures.
Example and header
The following pages include the complete example source and required header. You do not need a checkout of the Mudfish DNS source tree.
| File | Contents |
|---|---|
| policy.c — DNS policy example | Allow, block, or drop DNS queries; synthesize an IP answer; rewrite an answer's address and TTL. Includes Linux build and test commands. |
| mudfish_dns_module.h — module header | ABI declarations, hook signatures, action constants, and buffer ownership rules. |
Download policy.c and mudfish_dns_module.h into the same directory before
building. The example's build command produces a Linux .so library.