CompactDNS (CDNS) is a minimalistic yet powerful DNS server designed for simplicity and speed, offering local caching, as well as authoritative, recursive, and forwarding capabilities.
In 2025, Google Chrome will remove adblockers with the impending Manifest V3 update. This change threaten the existance of software like UBlock Origin. Rather than abandoning Chrome, I explored alternative ways to block ads. This DNS server, CompactDns, was the result: it's lightweight, blazing fast, and can block ads. It also caches all requests on device, leading to a latency as low as 0 ms.
- ninjamar
Install CDNS
pip install cdnsCDNS can also be installed from source
git clone https://github.com/ninjamar/compactdns
cd compactdns
pip install .For development,
pip install -e .After installation, CDNS can be used by running:
cdns [command] [options]The server can be run as a daemon, or as a standalone program.
To start the server:
cdns run [options]Configuration is stored in a toml or json file. See config.toml for an example configuration.
cdns run --config config.tomlThe DNS protocol is typically run over port 53 for TCP and 853 for TLS.
When TLS is used, a key and certificate file are required.
Generate a pair:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodesAn example configuration file is available in config.toml.
CDNS can be set up to run in the background as a service:
sudo cdns install -c /path/to/config
This command will output instructions for starting and stopping the server.
Startup logs are written to /tmp/cdns-startup.log and cdns-startup-err.log .
Note
MacOS seems to occasionally be killing the server when the device wakes from sleep.
A program called sleepwatcher is required to fix this.
Ensure that all paths in the configuration file are relative to the path of the configuration file.
CDNS can be configured as the system DNS server. Replace A.B.C.D with the address of the server.
On MacOS:
networksetup -setdnsservers Wi-Fi A.B.C.DZones can be stored in 3 formats:
- Single zone Json file (e.g.,
*.json) - Multiple zones JSOn file (e.g.,
*.all.json) - Traditional zone file (e.g.,
*.zone)
See the example-zones/ directory for examples.
To convert a host file to a JSON list:
cdns tools h2j /path/to/host.txt /path/to/output.all.jsonexample-zones/lowe.all.json was generated from Peter Lowe's adservers list using this script
A preload file is a plain text list of hosts to be loaded into the cache before server startup.
# These sites will all be preloaded
google.com
github.com
example.com
The cache (and also the zones) can be written to a file upon server shutdown and reloaded on startup.
When in recursive mode, the server can achieve latency as low as 0 ms. Initially, cache misses will result in higher latency, but once requests are resolved, responses are cached for the future.
graph TD;
send["Send the request"]
done["Response sent back"]
send --> recv["Server receives the request"]
recv --> is_cache["Is the request in the cache?"]
is_cache --> |"Yes"| cache["The request is in the cache"] --> done
is_cache --> |"No"| recursive["Recursively fulfill the request"]
recursive --> |"Add response to cache"| done
CDNS includes an interactive debugging shell.
Warning
This feature exists for debbuging. Use at your own risk
Note
Incoming requests are blocked when in use
Run the shell:
cdns shell [options]Options:
--host,-h: The host address for the shell server ina.b.c.d:portformat
The shell opens a Python REPL connected to the main server process.
List the available commands:
>>> help(self.command)Some outdated tests exist in tests/ directory
Instead, send test queries using dig.
dig @A.B.C.D -p PORT example.comThis project is licensed under the MIT License. See the LICENSE file for details.
Make sure the following tools have been applied:
- black
- isort
Make sure all code passes:
- mypy
- darglint
- ruff
pytest tests