Very low memory footprint dns resolver server on container

I’ve managed to set up a highly efficient MikroTik-friendly DNS resolver server with blacklist, DNSSEC, and many other new DNS features in an ARM64 container. It’s been working exceptionally well with very low memory usage and impressive speed. I’d like to share the details with the community for those who may benefit from it.

Note: This is not dns forwarder or proxy.

I’ve tested this setup on an RB5009 with an external disk connected to the USB port. I highly recommend using an external disk for containers.

The server I’m referring to is called sdns. It’s open-source, and the repository can be found at GitHub. You can either build the container from the source or pull it from Docker Hub (c1982/sdns). The Docker Hub version has over 10k pulls and is updated automatically through GitHub actions, which makes it quite reliable. Moreover, the container is incredibly lightweight at only 5MB, based on Alpine Linux. Upon startup, it utilizes only ~1MB of memory. :open_mouth: Additionally, the logging feature is very useful.

Here’s how I set it up:

/container/mounts/add name=sdns src=disk1/sdns-db dst=/db
/container/add remote-image=c1982/sdns:latest cmd="-c db/sdns.conf" hostname=sdns interface=veth1 mounts=sdns root-dir=disk1/sdns start-on-boot=yes logging=yes

After the first start, sdns generates sdns.conf under the disk1/sdns-db folder. You can fetch sdns.conf via SCP or SFTP, edit blacklists or other configurations, and restart the container.

Here are the logs from the first start:

/log/print
 12:05:43 container,info,debug importing remote image: c1982/sdns, tag: latest
 12:05:45 container,info,debug getting layer sha256:c7f4faa3cf6577680f0e22f85b6c93cc9a37f739545a2354553d6a976fc3b5eb
 12:05:47 container,info,debug layer sha256:c7f4faa3cf6577680f0e22f85b6c93cc9a37f739545a2354553d6a976fc3b5eb downloaded
 12:05:47 container,info,debug getting layer sha256:1f4de22d3c9c535608f0f3a0e32b7477b3d56ac970648537756a8febdfb939f5
 12:05:48 container,info,debug layer sha256:1f4de22d3c9c535608f0f3a0e32b7477b3d56ac970648537756a8febdfb939f5 downloaded
 12:05:48 container,info,debug import successful, container 006e0278-feac-4d01-a9b4-3afabf2dab64
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="Starting sdns..." version=1.3.6
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="Default config file generated" config=/db/sdns.conf
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="Loading config file..." path=db/sdns.conf
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="Working directory" path=db
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="Empty zones loaded" zones=99
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="API server listening..." addr=127.0.0.1:8080
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="DNS server listening..." net=tcp addr=:53
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="DNS server listening..." net=udp addr=:53
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=warn msg="No trust anchor state file found or the state corrupted! New one will be generate." path=db/trust-anchor.db
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="Trust anchor status" keytag=20326 state=VALID firstseen="Fri Feb 16 09:05:52 UTC 2024"
 12:05:52 container,info,debug t=2024-02-16T09:05:52+0000 lvl=info msg="Trust anchors refreshed" path=db/trust-anchor.db nextrefresh="Fri Feb 16 21:05:52 UTC 2024"
 12:05:53 container,info,debug t=2024-02-16T09:05:53+0000 lvl=info msg="Loading blocked domains..." path=db/blacklists
 12:05:53 container,info,debug t=2024-02-16T09:05:53+0000 lvl=info msg="Blocked domains loaded" total=0

SDNS also has an API, which can be docs found here. However, you’ll need to modify the API address in the configuration. Changed this line to:

api = ":8080"

I don’t recommend using heavy, extensive blacklists as they consume a significant amount of memory.

If you have any question ping me up.

How big is “heavy, extensive blacklists” can get before they cause problems?
For example, every ISP here in Poland is required by law (since 2017) to block gambling sites listed at https://hazard.mf.gov.pl/ - currently over 41k names and growing. All listed names are simple hosts (no wildcards or subdomains) - for each listed name the resolver has to return an A record pointing to 145.237.235.240 (which belongs to Ministry of Finances and shows a warning that it is illegal to use gambling sites that don’t pay taxes).
I’m currently using PowerDNS (pdns-recursor) in a Debian x86-64 VM under XCP-NG, with the list converted to /etc/hosts format. There are also scripts to convert the list to MT built-in static DNS. Would such list of 41k hosts be considered too heavy for this resolver?
(Don’t tell me it’s a stupid idea - it was made by politicians…)

I understand you very well. We have similar rules here in Turkey for ISPs. Don’t worry, a 41k blocklist is not too long. I think it uses an additional 10MB of memory. People are using 1M blocklists these days. :smiley: I’ve warned about the long lists. I have a RB5009, and my device has only 1GB of memory. The usage of blocklists depends on the memory capabilities of the device.

Also sdns support /etc/hosts style format too. You can set the list.

What does other blocklist formats that sdns support apart hosts style? I tries wildcard domains url but it not blocking. From the sdns.conf file, it does listed some other formats, but from what im experianced, it only block host style format.