# SmartDNS: a local resolver that returns the fastest IP, not just the first one

> SmartDNS is a local DNS server written in C that queries several upstream resolvers at once, measures which returned address is fastest from your network, and answers with that one. It fits routers and home labs; it is not a privacy VPN.

**pymumu/smartdns** — A local DNS server to obtain the fastest website IP for the best Internet experience, support DoT, DoH, DoQ. 一个本地DNS服务器，获取最快的网站IP，获得最佳上网体验，支持DoH，DoT，DoQ。

- Repository: https://github.com/pymumu/smartdns
- Website: https://pymumu.github.io/smartdns/
- Stars: 11,319 · Forks: 1,253
- Language: C
- License: GPL-3.0
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/pymumu-smartdns

## The problem SmartDNS solves, and who ends up running it

A normal resolver hands back whatever address the upstream returns first, or whatever the upstream decides to put at the top of the answer. That address is chosen from the resolver's point of view, not yours. If a CDN returns two addresses and the slower one is listed first, your client connects to the slower one. SmartDNS takes the opposite approach: it asks several upstream servers at once, collects the address list, measures reachability and speed from the local network, and returns the fastest result to the client. The README states this directly, and contrasts the behaviour with DNSmasq's all-servers mode, which returns every answer rather than picking the quickest.

The intended audience is visible in the platform list: Raspberry Pi, OpenWrt firmware, Asus router stock firmware, and WSL on Windows. This is software for people who own the network path, typically someone running a router they can install packages on. The README also lists per-client control by MAC or IP address, which points at households that want different rules for different devices, and domain-to-IP mapping, which the README describes as a way to filter ads and block malicious sites. If you rent a hosted smart DNS service to unlock a streaming catalogue, that is a different product with a similar name, and SmartDNS will not do it.

## The query path: multiple upstreams, a speed test, one answer

The architecture section of the README describes four steps. SmartDNS receives DNS queries from local devices such as PCs and phones. It forwards those queries to multiple upstream DNS servers, over UDP on standard or non-standard ports, or over TCP. The upstreams return the list of IP addresses for the name. SmartDNS then tests which of those addresses is fastest to reach from the local network, and returns that address to the client.

Around that core loop sit several mechanisms worth knowing before you configure anything. Virtual DNS servers let one SmartDNS instance expose different ports, rule sets and client groups. Upstreams can be reached over UDP, TCP, DoT, DoH, DoQ and DoH3, through SOCKS5 or an HTTP proxy, and on non-53 ports. Domain suffix matching is used for filtering; the README claims matching against 200,000 records takes under 1 ms. Domain splitting sends different categories of names to different upstreams, and the README notes integration with iptables and nftables, including placing results into ipset and nftset sets when the speed test fails. The codebase is C with a threaded asynchronous I/O model and a query cache, per the feature list. The repository also carries a plugin directory, and the Makefile exposes WITH_UI=1 to build a smartdns-ui plugin, which is the dashboard shown in the README screenshots.

## Installing SmartDNS and making a first query

The README points at the project site at https://pymumu.github.io/smartdns for usage guidance, and states that mainstream router systems ship SmartDNS in their official package sources, so on those systems you install from the router's package manager rather than building. For source builds, the repository provides package/build-pkg.sh, which the README says builds LuCI, Debian, OpenWrt and Optware packages. A Dockerfile is present at the repository root for container builds.

A plain source build uses the top-level Makefile. The default prefix is /usr, the binary directory is /usr/sbin, and configuration lives under /etc:

```bash
make
sudo make install
```

The Makefile also accepts WITH_UI=1 to include the smartdns-ui plugin, and it copies systemd/smartdns.service into place from systemd/smartdns.service.in, substituting the binary, config and runtime directories. On a systemd host the service file is therefore installed by the same make install step.

Configuration is read from a file, and the README's feature list is the guide to what goes in it: upstream server entries, per-client rules, domain-specific IP mappings, and domain splitting rules. The project documentation site is where the exact keys are documented; the README itself does not enumerate them, so read the site before writing a config rather than guessing key names. After starting the service, the verification step the README itself uses is a lookup against the local resolver followed by a ping of the returned address:

```bash
nslookup www.baidu.com
ping 14.215.177.39 -c 2
```

In the README's example the local server answers on 192.168.1.1 and returns 14.215.177.39, which pings at roughly 6 ms, against 24 to 31 ms for the addresses returned by 223.5.5.5. Treat that as the shape of the check, not as a number you should expect: your result depends on your upstreams and your route.

## Where SmartDNS is the wrong tool

The speed measurement is the whole point, and it is also the part with the least documentation in the README. The README says SmartDNS detects the fastest server IP from the local network, and separately mentions a setting for what happens when the speed test fails: results go into the configured ipset and nftset sets. What the README does not describe is how the probe works, how long it waits, or what it does with addresses it cannot reach at all. If you run a network where probing arbitrary addresses is undesirable, or where outbound ICMP or TCP to unknown hosts is filtered, you need to read the project documentation before trusting the selection. This is a real gap in the README, not a hidden feature.

Second, this is a resolver, not a tunnel. It changes which IP your client connects to and which upstream answers your queries. It does not change your apparent location, and the README's privacy claim is limited to DoT, DoH, DoQ and DoH3 protecting the query in transit. Anyone who needs a hosted smart DNS proxy for region-locked content is looking at a different category of product, and installing SmartDNS will not produce that result.

Third, the code is C, GPL-3.0, and the build path is not trivial. The Dockerfile fetches and compiles a trimmed OpenSSL 3.5.4, installs Node.js 20.x and Rust, and then builds SmartDNS. That is a lot of moving parts for a resolver. On OpenWrt and similar systems the packaged route avoids it, but if you are building from source on a small device you should expect to spend time on the toolchain before you spend time on DNS.

## How it differs from DNSmasq and from a hosted smart DNS service

DNSmasq is the natural comparison because the README makes it. In all-servers mode, DNSmasq forwards a query to all configured upstreams and returns the answers it receives; the client or the operating system then decides which address to use, usually by trying them in order. SmartDNS inserts a measurement step between the upstream answer and the client, so the client receives one address that was selected for speed from that network. The trade-off is that SmartDNS does more work per query and depends on its own probe logic being right; DNSmasq is simpler and its behaviour is easier to predict from its documentation.

A hosted smart DNS proxy is a different thing again. Those services exist so that a device can appear to resolve names from another region, and the vendor operates the resolvers. SmartDNS runs on your hardware and uses upstreams you choose. It can send queries over DoH or DoT to a provider, and it can split domains across providers, but the selection logic and the speed test stay local. If your requirement is regional access, SmartDNS is not a substitute. If your requirement is picking the faster of two CDN addresses that your ISP's resolver keeps getting wrong, that is exactly the case it was built for.

## Maintenance, releases and the GPL-3.0 licence

The repository is not archived, and the last push was on 2026-08-30. Releases are frequent: Release48.4 on 2026-08-05 and Release48.3 on 2026-07-27, with a nightly build published alongside them. Upgrades on packaged systems follow the distribution's package manager, which is the low-effort path. Upgrades from source mean rebuilding, and because the Dockerfile pins OpenSSL 3.5.4 and Node.js 20.x, a source build carries its own dependency maintenance burden separate from SmartDNS itself. The Makefile also generates the systemd unit at build time from systemd/smartdns.service.in, so a rebuild refreshes the unit file along with the binary.

SmartDNS is GPL-3.0. If you install it on your own router and configure it, the licence is not something you need to think about. If you intend to redistribute it inside a firmware image or a product, the GPL-3.0 obligations apply to that distribution, and the plugin directory and the smartdns-ui plugin are part of the same tree. That is a question for your own legal review, not something to settle from a README.

## Conclusion

Adopt SmartDNS if you run a router or home network where DNS latency and upstream choice matter, and you are willing to read the config before pointing clients at it. Skip it if what you actually want is a hosted smart DNS proxy for streaming regions, or if you need a resolver that is trivial to audit line by line. Before switching, verify two things on your own hardware: that the speed measurement picks a better address than your current upstream for a domain you use daily, and that your fallback path behaves the way you expect when every upstream fails.

## FAQ

### What does SmartDNS do?

It runs as a local DNS server, forwards queries to multiple upstream resolvers, measures which returned IP address is fastest to reach from the local network, and returns that address to the client. The README states it supports UDP, TCP, DoT, DoH, DoQ and DoH3.

### What are the disadvantages of SmartDNS?

The README does not document how the speed probe works, how long it waits, or how unreachable addresses are handled; it only says that when the speed test fails, results can be placed into ipset and nftset sets. It is also a resolver rather than a tunnel, so it does not change your apparent location.

### How do I install SmartDNS?

The README says mainstream router systems provide SmartDNS in their official package sources, so those systems install it from the package manager. For source builds, the README points at package/build-pkg.sh, which it says builds LuCI, Debian, OpenWrt and Optware packages.

### How do I set up SmartDNS on my device?

The README directs users to the project site at https://pymumu.github.io/smartdns for usage guidance, and says mainstream router systems ship SmartDNS in their official package sources. The README itself does not enumerate the configuration keys, so the project site is where setup is documented.

### How do I use SmartDNS?

You point your clients at the local SmartDNS instance and it forwards their queries to the upstream servers you configure, then returns the fastest address it measured. The README's own verification example is nslookup against the local server followed by a ping of the returned address.

## Sources

- [License: GPL-3.0](https://github.com/pymumu/smartdns/blob/master/LICENSE)
- [Project website](https://pymumu.github.io/smartdns/)
- [pymumu/smartdns on GitHub](https://github.com/pymumu/smartdns)
- [README](https://github.com/pymumu/smartdns/blob/master/README.md)
- [Releases](https://github.com/pymumu/smartdns/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pymumu-smartdns
