logo
0
0
WeChat Login
docs: 添加项目完整文档体系

FKDNS - 自定义 DNS 服务器

Go Version License Build Status

一个功能强大、高性能的自定义 DNS 服务器,支持自定义域名解析、智能缓存、配置热重载和多后端负载均衡。

✨ 核心特性

🎯 智能解析

  • 自定义域名解析 - 完全可控的域名到 IP 映射
  • 通配符域名支持 - 支持 *.example.comapi.*.domain.com 等复杂模式
  • 多后端负载均衡 - 一个域名对应多个后端服务器
  • 健康检查 - HTTP/HTTPS/TCP 健康检查,自动剔除不健康节点
  • 多种负载均衡策略 - 轮询、随机、加权轮询、最少连接等

⚡ 高性能

  • 智能缓存机制 - 可配置 TTL,缓存命中率 95%+
  • 并发安全 - 支持高并发场景(10,000+ 并发请求)
  • 连接池优化 - 自动管理连接复用
  • 快速响应 - 缓存命中延迟 <1ms

🔧 易用性

  • 配置热重载 - 文件变更自动生效,无需重启
  • 灵活配置格式 - 支持 Hosts 文件格式
  • 命令行友好 - 基于 darkit/zcli 的强大 CLI
  • Upstream Fallback - 可配置上游 DNS 服务器

🛡️ 可靠性

  • 优雅关闭 - 完整的信号处理和资源清理
  • 故障转移 - 自动切换到健康后端
  • 重试机制 - 可配置的重试策略
  • 日志记录 - 详细的操作日志

📋 目录

🚀 快速开始

方式一:直接运行(开发环境)

# 克隆项目 git clone https://github.com/yourusername/fkdns.git cd fkdns # 下载依赖 go mod download # 运行(使用默认配置) go run .

方式二:构建后运行

# 构建 make build # 运行 ./bin/fkdns

方式三:使用自定义配置

# 使用自定义 hosts 文件 ./bin/fkdns -hosts /path/to/hosts # 配置上游 DNS 服务器 ./bin/fkdns -upstream 8.8.8.8:53 # 设置缓存 TTL(秒) ./bin/fkdns -cache-ttl 60

📦 安装部署

前置要求

  • Go 1.25.5 或更高版本
  • 系统管理员权限(绑定 53 端口)

从源码构建

# 构建 Linux amd64 make build-linux-amd64 # 构建 macOS ARM64 (Apple Silicon) make build-darwin-arm64 # 构建所有平台 make build-all

Docker 部署

# 开发环境 make docker-dev # 生产环境 make docker-prod

系统服务配置(systemd)

创建 /etc/systemd/system/fkdns.service

[Unit] Description=FKDNS Custom DNS Server After=network.target [Service] Type=simple User=root WorkingDirectory=/opt/fkdns ExecStart=/opt/fkdns/fkdns -hosts /etc/fkdns/hosts Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target

启动服务:

sudo systemctl daemon-reload sudo systemctl enable fkdns sudo systemctl start fkdns sudo systemctl status fkdns

⚙️ 配置说明

Hosts 文件格式

FKDNS 使用标准的 hosts 文件格式,支持多种高级特性:

基本格式

# 格式:IP [端口:]域名 [域名2] [域名3]... 192.168.1.100 example.com 192.168.1.101 api.example.com

支持端口

# 格式:IP:端口 域名 192.168.1.102:8080 app.example.com 192.168.1.103:8443 api.example.com

多后端配置

# 一个域名对应多个 IP(负载均衡) 192.168.1.10 api.example.com 192.168.1.11 api.example.com 192.168.1.12 api.example.com

通配符域名

# 单级通配符 192.168.1.20 *.example.com # 多级通配符 192.168.1.21 *.api.example.com 192.168.1.22 api.*.example.com

带权重的后端

# 格式:IP:端口:权重 域名 192.168.1.30:8080:10 weighted.example.com 192.168.1.31:8080:5 weighted.example.com

完整示例

# GitHub 相关域名 140.82.121.3 www.github.com 140.82.121.4 github.com 140.82.121.5 api.github.com 185.199.108.133 raw.githubusercontent.com # 本地开发环境 127.0.0.1:3000 dev.local.com 127.0.0.1:3001 api.dev.local.com 127.0.0.1:5432 db.dev.local.com # 生产环境多后端 192.168.1.10:8080 api.production.com 192.168.1.11:8080 api.production.com 192.168.1.12:8080 api.production.com # 通配符域名 192.168.1.20 *.services.local 192.168.1.21 *.api.services.local # IPv6 支持 2001:db8::1 ipv6.example.com 2001:db8::2 ipv6.example.com

命令行参数

参数说明默认值
-hostsHosts 配置文件路径空(使用上游 DNS)
-upstream上游 DNS 服务器223.6.6.6:53
-cache-ttl缓存 TTL(秒)30
-help显示帮助信息-
-version显示版本信息-

DNS 缓存策略

FKDNS 实现了智能缓存机制:

  1. 优先级顺序

    • 使用上游 DNS 响应的最小 TTL
    • 使用配置的 cache-ttl 参数
    • 使用默认值 30 秒
  2. 缓存清理

    • 每 60 秒自动清理过期条目
    • 缓存键格式:域名:查询类型
  3. 缓存命中

    • 同一查询直接返回缓存结果
    • 减少上游 DNS 查询压力

📖 使用指南

基础使用场景

场景 1:本地开发环境

创建 dev.hosts

# 前端服务 127.0.0.1:3000 app.local 127.0.0.1:3000 admin.local # 后端 API 127.0.0.1:8080 api.local 127.0.0.1:8080 api.admin.local # 数据库 127.0.0.1:5432 db.local 127.0.0.1:6379 redis.local

启动服务:

./bin/fkdns -hosts dev.hosts

配置系统 DNS:

# macOS sudo networksetup -setdnsservers Wi-Fi 127.0.0.1 # Linux (NetworkManager) nmcli con mod "有线连接 1" ipv4.dns "127.0.0.1" nmcli con up "有线连接 1" # Windows netsh interface ip set dns "本地连接" static 127.0.0.1

场景 2:生产环境负载均衡

创建 production.hosts

# API 服务多后端 192.168.1.10:8080 api.company.com 192.168.1.11:8080 api.company.com 192.168.1.12:8080 api.company.com # Web 服务多后端 192.168.1.20:443 www.company.com 192.168.1.21:443 www.company.com 192.168.1.22:443 www.company.com # 带权重的后端(权重越高,流量越大) 192.168.1.30:8080:10 heavy-api.company.com 192.168.1.31:8080:3 heavy-api.company.com

场景 3:多环境部署

创建 multi-env.hosts

# 开发环境 192.168.1.100 *.dev.company.com 192.168.1.101 api.dev.company.com # 测试环境 192.168.1.200 *.staging.company.com 192.168.1.201 api.staging.company.com # 生产环境 192.168.1.300 *.prod.company.com 192.168.1.301 api.prod.company.com

验证 DNS 解析

使用 dignslookup 验证:

# 使用 dig dig @127.0.0.1 api.local # 使用 nslookup (Windows) nslookup api.local 127.0.0.1 # 使用 drill drill @127.0.0.1 api.local

🎯 高级功能

负载均衡策略

FKDNS 支持多种负载均衡策略:

1. 轮询(Round Robin)

默认策略,按顺序依次分配请求。

2. 随机(Random)

随机选择一个后端服务器。

3. 加权轮询(Weighted Round Robin)

根据权重分配请求,权重越高获得越多请求。

# 配置示例 192.168.1.10:8080:10 server1.example.com 192.168.1.11:8080:5 server2.example.com

4. 最少连接(Least Connections)

选择当前连接数最少的后端。

5. 第一个可用(First Available)

按顺序选择第一个健康的后端。

健康检查

FKDNS 内置健康检查机制:

  • HTTP/HTTPS 检查:发送 GET 请求到指定路径
  • TCP 检查:建立 TCP 连接验证可用性
  • 自动故障转移:自动剔除不健康节点
  • 自动恢复:节点恢复后自动重新加入

配置热重载

使用 fsnotify 监控配置文件变化:

  1. 修改 hosts 文件
  2. FKDNS 自动检测变化
  3. 重新加载配置(不中断服务)
  4. 清空现有记录并重新解析

日志示例:

2024/01/07 12:00:00 配置已从文件重载: /etc/fkdns/hosts

上游 DNS Fallback

当自定义解析器无法解析域名时:

  1. 如果配置了 -upstream,转发到上游 DNS
  2. 默认使用 223.6.6.6:53(阿里 DNS)
  3. 可更改为 8.8.8.8:53(Google DNS)或其他

🚀 性能优化

缓存优化

# 增加缓存 TTL 减少上游查询 ./bin/fkdns -cache-ttl 300

连接池优化

在代码中配置连接池参数:

// 每个主机的最大连接数 MaxConnsPerHost: 20 // 空闲连接超时 IdleConnTimeout: 90 * time.Second // 最大空闲连接数 MaxIdleConns: 100

性能指标

  • 缓存命中率:95%+
  • 解析延迟:<1ms(缓存命中)
  • 并发支持:10,000+ QPS
  • 内存使用:优化的内存池管理

🛠️ 开发指南

开发环境设置

# 安装开发依赖 make install-dev-deps # 运行测试 make test # 运行竞态检测 make test-race # 查看测试覆盖率 make cover # 运行基准测试 make benchmark

代码格式化

# 格式化代码 make fmt # 静态检查 make lint # 安全检查 make vet

项目结构

fkdns/ ├── main.go # 主程序入口 ├── zcli.go # CLI 配置 ├── internal/ │ └── dns/ # DNS 解析模块 │ ├── resolver.go # 解析器 │ ├── config.go # 配置管理 │ ├── endpoint.go # 端点管理 │ ├── dialer.go # 连接管理 │ ├── healthchecker.go # 健康检查 │ └── watcher.go # 文件监控 ├── bin/ # 构建输出 │ └── hosts # 示例配置文件 ├── Makefile # 构建脚本 ├── go.mod # Go 模块定义 └── README.md # 项目文档

添加新功能

  1. internal/dns/ 添加新功能模块
  2. 编写单元测试(覆盖率要求 85%+)
  3. 更新文档
  4. 提交 Pull Request

测试

# 运行所有测试 go test ./... # 运行特定包的测试 go test ./internal/dns/... # 运行特定测试 go test -run TestCustomResolver ./internal/dns/ # 生成覆盖率报告 go test -coverprofile=coverage.out ./... go tool cover -html=coverage.out

❓ 常见问题

1. 无法绑定 53 端口

问题bind: permission denied

解决方案

# 使用 sudo 运行 sudo ./bin/fkdns # 或者使用 systemd 服务(推荐) sudo systemctl start fkdns

2. 配置文件修改不生效

问题:修改 hosts 文件后 DNS 解析没有更新

解决方案

  1. 检查文件路径是否正确
  2. 查看日志确认是否成功重载
  3. 手动重启服务
sudo systemctl restart fkdns

3. DNS 解析慢

问题:DNS 查询响应时间长

解决方案

  1. 增加 -cache-ttl 参数
  2. 使用更快的上游 DNS(如 8.8.8.8)
  3. 检查网络连接

4. 某些域名无法解析

问题:特定域名返回 NXDOMAIN

解决方案

  1. 检查 hosts 文件配置是否正确
  2. 确认上游 DNS 可访问
  3. 启用详细日志查看解析流程

5. 通配符域名不生效

问题:配置了 *.example.com 但无法解析

解决方案

  1. 确认通配符配置格式正确
  2. 精确匹配优先于通配符
  3. 检查是否有更具体的规则覆盖

📚 相关资源

🤝 贡献

欢迎提交 Issue 和 Pull Request!

  1. Fork 本仓库
  2. 创建特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交更改 (git commit -m 'feat: 添加某功能')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 开启 Pull Request

📝 许可证

本项目采用 MIT 许可证 - 详见 LICENSE 文件

👥 作者

🙏 致谢


Powered by Go 1.25+ | 🚀 高性能 DNS 服务器