薇尔薇

Back

所有代码都由claude编写 未提供产物,需要自行从源码构建 不开源,感兴趣请邮件沟通,不收费(其实是感觉开源没必要,AI时代人人都可以轻易构建出复制的应用程序,我基于自身需要开发的软件,并不适合其他人)

简介#

自动 DNS 代理服务器,支持域名分类、GeoIP 路由、ECS、多级缓存和自动回退。

特性#

  • 自动路由 - 对未分类的域名自动进行分类,记录
  • GeoIP/ASN 匹配 - IP 验证和地理位置判断
  • CNAME 链缓存 - RR 级别缓存,支持 CNAME 链部分命中
  • ECS 支持 - EDNS Client Subnet,可按组配置
  • 并发回退 - proxy_ecs_fallback 策略并发查询多个上游,自动选择最优结果
  • 多级缓存 - DNS 缓存和域名分类缓存,支持 Redis 和内存两种后端
  • 代理支持 - 上游 DNS 和文件下载支持 SOCKS5 代理
  • 自动更新 - 定时更新域名分类和 GeoIP 数据库
  • 高性能 - Singleflight 去重,连接池复用

核心#

Pasted image 20251215001418

域名分类#

域名分类存储在 dlc.dat(来自 v2ray/domain-list-community),支持三种匹配方式:

  • 完整匹配 - example.com 只匹配 example.com
  • 域名匹配 - domain:example.com 匹配 example.com 和所有子域名
  • 关键字匹配 - keyword:google 匹配包含 google 的所有域名

分类缓存支持两种模式:

  1. 按需查询(默认)- 查询时从 dlc.dat 读取,结果缓存到 Redis/内存
  2. 预加载(-load 模式)- 启动时将所有分类加载到 Redis

查询策略#

每个域名分类对应一个查询策略,策略指定:

  • 上游组 - 使用哪个 upstream_group
  • 策略选项 - disable_cache, disable_https, ecs, expected_ips, fallback_group 等

特殊策略#

block - 阻断域名,返回指定类型的响应:

  • nxdomain - NXDOMAIN(域名不存在)
  • noerror - NOERROR(空响应)
  • 0.0.0.0 - 返回 0.0.0.0

proxy_ecs_fallback - 并发查询策略(未分类域名的默认策略):

  1. 并发查询 proxy_ecs 和 proxy 组
  2. 检查 proxy_ecs 结果的 IP 是否匹配 fallback.rule(GeoIP 规则)
  3. 如果匹配,查询 direct 组并返回
  4. 否则返回 proxy 或 proxy_ecs 结果
  5. 自动将域名分类为 direct_site 或 proxy_site

IP 验证与回退#

策略可以配置 expected_ips(GeoIP 规则数组),验证上游返回的 IP:

query_policy:
  - name: "cn_site"
    group: "proxy"
    options:
      expected_ips: ["geoip:cn"]      # 期望返回国内 IP
      fallback_group: "direct"        # 如果不是国内 IP,使用 direct 组重查
yaml

验证逻辑:

  • 所有返回的 IP 必须匹配 expected_ips 中的任一规则
  • 如果验证失败且配置了 fallback_group,使用该组重新查询(最终结果,不再验证)
  • 如果没有配置 fallback_group,回退到 proxy_ecs_fallback 策略

GeoIP 规则#

支持的规则格式:

  • geoip:cn - 国家代码(ISO 3166-1 alpha-2)
  • geoip:private - 私有 IP(10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16)
  • asn:13335 - ASN 号(自治系统号)

CNAME 链缓存#

DNS 缓存按 RR 记录级别存储(不是完整的 DNS 消息),支持 CNAME 链部分命中:

示例: a.com -> b.com -> c.com -> 1.2.3.4

  1. 第一次查询 a.com,缓存所有 RR:

    • a.com CNAME b.com
    • b.com CNAME c.com
    • c.com A 1.2.3.4
  2. c.com A 记录过期后再次查询 a.com:

    • 从缓存返回 a.com CNAME b.com 和 b.com CNAME c.com
    • 只查询上游 c.com A
    • 合并结果返回

ECS(EDNS Client Subnet)#

ECS 在上游组级别配置:

upstream_group:
  proxy_ecs:
    nameservers: ["https://dns.google/dns-query"]
    ecs_ip: "8.8.8.8"              # 固定 ECS IP
  proxy_ecs_auto:
    nameservers: ["https://dns.google/dns-query"]
    ecs_ip: ""                     # 使用全局默认 ECS(如果启用)

ecs:
  enable: true                     # 全局 ECS 开关
  default_ipv4: "8.8.8.8"          # 默认 IPv4 ECS
  default_ipv6: "2001:4860:4860::8888"
  ipv4_prefix: 24                  # ECS 前缀长度
  ipv6_prefix: 48
yaml

缓存#

DNS 缓存#

RR 级别缓存,每条记录独立存储,包含:

  • RR 记录内容
  • 原始 TTL 和存储时间
  • Rcode, AD, RA 标志

支持后端:

  • Redis - 跨进程共享,持久化
  • Memory - 进程内存,重启丢失

最大 TTL 固定为 24 小时。

域名分类缓存#

存储域名到分类的映射(如 google.com -> proxy_site)。

支持后端:

  • Redis - TTL 可配置(默认 1 天)
  • Memory - 无 TTL 限制

代理支持#

支持通过 SOCKS5 代理进行:

  • 上游 DNS 查询 - DoH (DNS-over-HTTPS) 和 TCP 协议
  • 文件下载 - dlc.dat, Country.mmdb, GeoLite2-ASN.mmdb

每个上游组可以指定不同的 outbound:

自用配置#

构建#

未提供产物,需要自行从源码构建

Linux#

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
bash

OpenWRT#

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -trimpath
bash

部署#

Systemd 服务#

[Unit]
Description=violet-dns
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/violet-dns -d /etc/violet-dns
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
ini

使用建议#

预先导入category_policy中定义的网站到redis中 此处不需要定义cn和非cn网站,等待后续自动分配即可(因为此种分流必然是不完整且有错误的不如不导入) 只需要定义需要单独分流的域名即可

其余的配置看配文件足够简单明了

violet-dns -d /var/run/violet-dns -load
sh
一个自动分类的DNS服务器
https://vio.vin/blog/yi-ge-zi-dong-fen-lei-de-dns-fu-wu-qi
Author violet
Published at 2025年12月14日