Skip to content

About

C++20 recursive DNS server — DoH upstream, LRU cache, rate limiting, Prometheus metrics, built from scratch to understand DNS

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

Repository files navigation

zazaki-dns

从零实现的 C++20 DNS 递归解析器——既能跑起来解析域名,又能在过程中真正理解 DNS 协议。

架构

客户端 (dig / 浏览器)
  │ UDP:53 / TCP:53
  ▼
┌─────────────────────────────────────┐
│  poll() 事件循环 (单线程收包)         │
│  ├─ UDP: recvfrom → 线程池          │
│  └─ TCP: accept → handle → close    │
└──────────────┬──────────────────────┘
               │ 分发到 N 个工作线程
               ▼
┌─────────────────────────────────────┐
│  Resolver (每线程独立 CURL handle)    │
│  ┌─ 1. 域名屏蔽 (BlockList)         │
│  ├─ 2. hosts 覆盖 (HostsFile)       │
│  ├─ 3. 缓存查询 (LRU + TTL)         │
│  ├─ 4. 负缓存检查                    │
│  ├─ 5. DoH 上游 (libcurl, HTTPS)    │
│  └─ 6. 迭代解析 (根→TLD→权威, 回落) │
└─────────────────────────────────────┘
               │
               ▼
┌─────────────────────────────────────┐
│  共享 DnsCache (shared_mutex)       │
│  Metrics HTTP :9191 (Prometheus)    │
│  RateLimiter (令牌桶, 每 IP)         │
│  SIGHUP 热加载配置                   │
└─────────────────────────────────────┘

快速开始

# 构建
cmake -S . -B build && cmake --build build

# 单元测试(54 个测试,185 个断言)
./build/test_message

# 启动服务器(端口 5300)
./build/dns_server dns_server.conf

# 测试查询
./scripts/dns_query.py example.com
./scripts/dns_query.py -a  # 预设域名列表

# 一键集成测试
./scripts/test_all.sh

配置文件

port 5300
hosts_file /etc/hosts
upstream_dot 8.8.8.8       # DNS-over-HTTPS 上游
upstream_dot 1.1.1.1
block *.doubleclick.net    # 域名屏蔽
rate_limit 100             # 限速 (qps/IP)
rate_burst 200             # 突发令牌

功能

功能 说明
DNS 报文编解码 Header/Question/RR 完整 encode/decode,含域名压缩指针
UDP + TCP 双栈 poll() 统一事件循环,TCP 带 2 字节长度前缀
DNS-over-HTTPS libcurl + 系统 CA 证书验证,绕过 DNS 劫持
迭代解析 13 个根服务器 → TLD → 权威,含 CNAME 追踪
LRU + TTL 缓存 惰性过期 + 双重淘汰,多线程安全 (shared_mutex)
负面缓存 NXDOMAIN 结果按 SOA MINIMUM 缓存
hosts 覆盖 标准 /etc/hosts 格式,IPv4 查询第一优先
域名屏蔽 精确匹配 + *.通配符,返回 0.0.0.0
线程池 可配置工作线程数,轮转分摊 CURL handle
限速 令牌桶算法,每 IP 独立桶,超限静默丢弃
Metrics Prometheus 格式,/metrics + /health,端口 9191
热加载 SIGHUP 重读配置,hosts/限速即时更新
优雅降级 DoH 全挂自动回落迭代解析
EDNS0 OPT 伪记录,声明 4096 字节 UDP 载荷
systemd dns_server.service,CAP_NET_BIND_SERVICE 免 root

查询示例

$ ./scripts/dns_query.py example.com github.com google.com
  example.com    NOERROR  A=104.20.23.154 (ttl=300s)
  github.com     NOERROR  A=20.205.243.166 (ttl=60s)
  google.com     NOERROR  A=142.250.204.46 (ttl=74s)

Metrics

$ curl http://127.0.0.1:9191/metrics
# HELP dns_udp_queries_total Total UDP queries received
# TYPE dns_udp_queries_total counter
dns_udp_queries_total 42

# HELP dns_cache_hits_total Cache hits
# TYPE dns_cache_hits_total counter
dns_cache_hits_total 28

# HELP dns_local_hit_rate Local hit rate (percent)
# TYPE dns_local_hit_rate gauge
dns_local_hit_rate 66.7

部署

sudo cp build/dns_server /usr/local/bin/
sudo cp dns_server.conf /etc/
sudo cp dns_server.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now dns_server

依赖

  • C++20 (GCC 16+ 或 Clang 19+)
  • CMake ≥ 3.20
  • libcurl ≥ 8.0
  • Linux, POSIX socket

项目结构

├── include/dns/          # 头文件
│   ├── message.hpp       # DNS 报文类型
│   ├── resolver.hpp      # 递归解析器
│   ├── cache.hpp         # LRU+TTL 缓存
│   ├── hosts.hpp         # hosts 文件 + 屏蔽
│   ├── dot_upstream.hpp  # DoH 上游
│   ├── config.hpp        # 配置解析
│   ├── stats.hpp         # 统计
│   ├── thread_pool.hpp   # 线程池
│   ├── rate_limiter.hpp  # 令牌桶限速
│   └── metrics_server.hpp # Prometheus metrics
├── src/dns/              # 实现
├── src/main.cpp          # 入口
├── tests/                # 54 个测试用例
├── scripts/              # 测试脚本
│   ├── test_all.sh       # 一键集成测试
│   ├── dns_query.py      # DNS 查询客户端
│   └── ...
└── dns_server.conf       # 默认配置

License

MIT

About

C++20 recursive DNS server — DoH upstream, LRU cache, rate limiting, Prometheus metrics, built from scratch to understand DNS

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages