Coder Social home page Coder Social logo

zfl9 / chinadns-ng Goto Github PK

View Code? Open in Web Editor NEW
1.0K 42.0 177.0 2.16 MB

chinadns 重构增强版,支持域名分流、ipset/nftset、UDP/TCP/DoT

License: GNU Affero General Public License v3.0

C 28.34% Shell 0.59% Zig 71.07%
chinadns chinadns-ng ipset netlink ss-tproxy dns gfwlist dnsmasq nftables dot

chinadns-ng's Introduction

简介

ChinaDNS 的个人重构版本,功能简述:

  • 基于 epoll、netlink(ipset/nftset) 实现,性能更强。
  • 完整支持 IPv4 和 IPv6 协议,兼容 EDNS 请求和响应。
  • 手动指定国内 DNS 和可信 DNS,而非自动识别,更加可控。
  • 修复原版对保留地址的处理问题,去除过时特性,只留核心功能。
  • 修复原版对可信 DNS 先于国内 DNS 返回而导致判断失效的问题。
  • 支持 gfwlist/chnlist 域名列表,并深度优化了性能以及内存占用。
  • 支持纯域名分流:要么走china上游,要么走trust上游,不进行ip测试。
  • 可动态添加大陆域名结果IP至ipset/nftset,实现完美chnroute分流。
  • 可动态添加gfw域名结果IP至ipset/nftset,用于实现gfwlist透明代理。
  • 支持nftables set,并针对 add 操作进行了性能优化,避免操作延迟。
  • 更加细致的 no-ipv6(AAAA) 控制,可根据域名类型,IP测试结果进行过滤。
  • DNS 缓存、stale 缓存模式、缓存预刷新、缓存忽略名单(不缓存的域名)。
  • 支持 tag:none 域名的判定结果缓存,避免重复请求和判定,减少DNS泄露。
  • 除默认的 china、trust 组外,还支持最多 6 个自定义组(上游DNS、ipset)。

对于常规的使用模式,大致原理和流程可总结为:

  • 两组DNS上游:china组(大陆DNS)、trust组(国外DNS)。

  • 两个域名列表:chnlist.txt(大陆域名)、gfwlist.txt(受污染域名)。

  • chnlist.txt域名(tag:chn域名),转发给china组,保证大陆域名不会被解析到国外,对大陆域名cdn友好。

  • gfwlist.txt域名(tag:gfw域名),转发给trust组,trust需返回未受污染的结果,比如走代理,具体方式不限。

  • 其他域名(tag:none域名),同时转发给china组和trust组,如果china组解析结果(A/AAAA)是大陆ip,则采纳china组,否则采纳trust组。是否为大陆ip的核心依据,就是测试ip是否位于ipset-name4/6指定的那个地址集合。

  • 若启用了tag:none域名的判决缓存,则同一域名的后续请求只会转发给特定的上游组(china组或trust组,具体取决于之前的ip测试结果),建议启用此功能,避免重复请求、判定,减少DNS泄露。

  • 如果使用纯域名分流模式,则不存在tag:none域名,因此要么走china组,要么走trust组,可避免dns泄露问题。

  • 若启用--add-tagchn-ip,则tag:chn域名的解析结果IP会被动态添加到指定的ipset/nftset,配合chnroute透明代理分流时,可用于实现大陆域名必走直连,使dns分流与ip分流一致;类似 dnsmasq 的 ipset/nftset 功能。

  • 若启用--add-taggfw-ip,则tag:gfw域名的解析结果IP会被动态添加到指定的ipset/nftset,可用来实现gfwlist透明代理分流;也可配合chnroute透明代理分流,用来收集黑名单域名的IP,用于iptables/nftables操作,比如确保黑名单域名必走代理,即使某些黑名单域名的IP是大陆IP。

chinadns-ng 根据域名 tag 来执行不同逻辑,包括 ipset/nftset 的逻辑(test、add),见 原理

编译

不想编译或无法编译的,请前往 releases 页面下载预编译的可执行文件(静态链接 musl)。

点我展开编译说明


zig 工具链

  • 从 2024.03.07 版本起,程序使用 Zig + C 语言编写,zig 是唯一需要的工具链。
  • ziglang.org 下载 zig 0.10.1,请根据当前(编译)主机的架构来选择合适的版本。
  • 将解压后的目录加入 PATH 环境变量,执行 zig version,检查是否有输出 0.10.1
  • 注意,目前必须使用 zig 0.10.1 版本,因为 0.11、master 版本暂时不支持 async 特性。

如果要构建 DoT 支持,请带上 -Dwolfssl 参数,构建过程需要以下依赖:

  • wgetcurl 用于下载 wolfssl 源码包;tar 用于解压缩
  • autoconfautomakelibtoolmake 用于构建 wolfssl

针对 x86_64(v3/v4)、aarch64 的 wolfssl 构建已默认启用硬件指令加速,若目标硬件(CPU)不支持相关指令(部分树莓派阉割了 aes 相关指令),请指定 -Dwolfssl-noasm 选项,避免运行 chinadns-ng 时出现 SIGILL 非法指令异常。


如果遇到编译错误,请先执行 zig build clean-all,然后重新执行相关构建命令。

可执行文件在 ./zig-out/bin 目录,将文件安装(复制)到目标主机 PATH 路径下即可。


git clone https://github.com/zfl9/chinadns-ng
cd chinadns-ng

# 本机
zig build # 链接到glibc
zig build -Dtarget=native-native-musl # 静态链接到musl

# x86
zig build -Dtarget=i386-linux-musl -Dcpu=i686
zig build -Dtarget=i386-linux-musl -Dcpu=pentium4

# x86_64
zig build -Dtarget=x86_64-linux-musl -Dcpu=x86_64 # v1
zig build -Dtarget=x86_64-linux-musl -Dcpu=x86_64_v2
zig build -Dtarget=x86_64-linux-musl -Dcpu=x86_64_v3
zig build -Dtarget=x86_64-linux-musl -Dcpu=x86_64_v4

# arm
zig build -Dtarget=arm-linux-musleabi -Dcpu=generic+v5t+soft_float
zig build -Dtarget=arm-linux-musleabi -Dcpu=generic+v5te+soft_float
zig build -Dtarget=arm-linux-musleabi -Dcpu=generic+v6+soft_float
zig build -Dtarget=arm-linux-musleabi -Dcpu=generic+v6t2+soft_float
zig build -Dtarget=arm-linux-musleabi -Dcpu=generic+v7a # soft_float
zig build -Dtarget=arm-linux-musleabihf -Dcpu=generic+v7a # hard_float

# aarch64
zig build -Dtarget=aarch64-linux-musl -Dcpu=generic+v8a
zig build -Dtarget=aarch64-linux-musl -Dcpu=generic+v9a

# mips + soft_float
# 请先阅读 https://www.zfl9.com/zig-mips.html
ARCH=mips32 && MIPS_M_ARCH=$ARCH MIPS_SOFT_FP=1 zig build -Dtarget=mips-linux-musl -Dcpu=$ARCH+soft_float
ARCH=mips32r2 && MIPS_M_ARCH=$ARCH MIPS_SOFT_FP=1 zig build -Dtarget=mips-linux-musl -Dcpu=$ARCH+soft_float
ARCH=mips32r3 && MIPS_M_ARCH=$ARCH MIPS_SOFT_FP=1 zig build -Dtarget=mips-linux-musl -Dcpu=$ARCH+soft_float
ARCH=mips32r5 && MIPS_M_ARCH=$ARCH MIPS_SOFT_FP=1 zig build -Dtarget=mips-linux-musl -Dcpu=$ARCH+soft_float

# mipsel + soft_float
# 请先阅读 https://www.zfl9.com/zig-mips.html
ARCH=mips32 && MIPS_M_ARCH=$ARCH MIPS_SOFT_FP=1 zig build -Dtarget=mipsel-linux-musl -Dcpu=$ARCH+soft_float
ARCH=mips32r2 && MIPS_M_ARCH=$ARCH MIPS_SOFT_FP=1 zig build -Dtarget=mipsel-linux-musl -Dcpu=$ARCH+soft_float
ARCH=mips32r3 && MIPS_M_ARCH=$ARCH MIPS_SOFT_FP=1 zig build -Dtarget=mipsel-linux-musl -Dcpu=$ARCH+soft_float
ARCH=mips32r5 && MIPS_M_ARCH=$ARCH MIPS_SOFT_FP=1 zig build -Dtarget=mipsel-linux-musl -Dcpu=$ARCH+soft_float

# mips + hard_float
# 请先阅读 https://www.zfl9.com/zig-mips.html
ARCH=mips32 && MIPS_M_ARCH=$ARCH zig build -Dtarget=mips-linux-musl -Dcpu=$ARCH
ARCH=mips32r2 && MIPS_M_ARCH=$ARCH zig build -Dtarget=mips-linux-musl -Dcpu=$ARCH
ARCH=mips32r3 && MIPS_M_ARCH=$ARCH zig build -Dtarget=mips-linux-musl -Dcpu=$ARCH
ARCH=mips32r5 && MIPS_M_ARCH=$ARCH zig build -Dtarget=mips-linux-musl -Dcpu=$ARCH

# mipsel + hard_float
# 请先阅读 https://www.zfl9.com/zig-mips.html
ARCH=mips32 && MIPS_M_ARCH=$ARCH zig build -Dtarget=mipsel-linux-musl -Dcpu=$ARCH
ARCH=mips32r2 && MIPS_M_ARCH=$ARCH zig build -Dtarget=mipsel-linux-musl -Dcpu=$ARCH
ARCH=mips32r3 && MIPS_M_ARCH=$ARCH zig build -Dtarget=mipsel-linux-musl -Dcpu=$ARCH
ARCH=mips32r5 && MIPS_M_ARCH=$ARCH zig build -Dtarget=mipsel-linux-musl -Dcpu=$ARCH

# mips64、mips64el 暂不支持,需要等 zig 这边的版本更新

Docker

由于运行时会访问内核 ipset/nft 子系统,所以 docker run 时请带上 --privileged

建议去 releases 页面下载预编译好的 musl 静态链接二进制,这样就不需要 build 了。

OpenWrt

命令选项

  • --foo <value>:选项值是 required 的
  • --bar [value]:选项值是 optional 的
  • --flag:没有选项值,即 bool/flag 选项
$ chinadns-ng --help
usage: chinadns-ng <options...>. the existing options are as follows:
 -C, --config <path>                  format similar to the long option
 -b, --bind-addr <ip>                 listen address, default: 127.0.0.1
 -l, --bind-port <port[@proto]>       listen port number, default: 65353
 -c, --china-dns <upstreams>          china dns server, default: <114 DNS>
 -t, --trust-dns <upstreams>          trust dns server, default: <Google DNS>
 -m, --chnlist-file <paths>           path(s) of chnlist, '-' indicate stdin
 -g, --gfwlist-file <paths>           path(s) of gfwlist, '-' indicate stdin
 -M, --chnlist-first                  match chnlist first, default gfwlist first
 -d, --default-tag <tag>              chn or gfw or <user-tag> or none(default)
 -a, --add-tagchn-ip [set4,set6]      add the ip of name-tag:chn to ipset/nftset
                                      use '--ipset-name4/6' setname if no value
 -A, --add-taggfw-ip <set4,set6>      add the ip of name-tag:gfw to ipset/nftset
 -4, --ipset-name4 <set4>             ip test for tag:none, default: chnroute
 -6, --ipset-name6 <set6>             ip test for tag:none, default: chnroute6
                                      if setname contains @, then use nftset
                                      format: family_name@table_name@set_name
 --group <name>                       define rule group: {dnl, upstream, ipset}
 --group-dnl <paths>                  domain name list for the current group
 --group-upstream <upstreams>         upstream dns server for the current group
 --group-ipset <set4,set6>            add the ip of the current group to ipset
 -N, --no-ipv6 [rules]                rule: tag:<name>, ip:china, ip:non_china
                                      if no rules, then filter all AAAA queries
 --filter-qtype <qtypes>              filter queries with the given qtype (u16)
 --cache <size>                       enable dns caching, size 0 means disabled
 --cache-stale <N>                    use stale cache: expired time <= N(second)
 --cache-refresh <N>                  pre-refresh the cached data if TTL <= N(%)
 --cache-nodata-ttl <ttl>             TTL of the NODATA response, default is 60
 --cache-ignore <domain>              ignore the dns cache for this domain(suffix)
 --verdict-cache <size>               enable verdict caching for tag:none domains
 --hosts [path]                       load hosts file, default path is /etc/hosts
 --dns-rr-ip <names>=<ips>            define local resource records of type A/AAAA
 --cert-verify                        enable SSL certificate validation, default: no
 --ca-certs <path>                    CA certs path for SSL certificate validation
 --no-ipset-blacklist                 add-ip: don't enable built-in ip blacklist
                                      blacklist: 127.0.0.0/8, 0.0.0.0/8, ::1, ::
 -o, --timeout-sec <sec>              response timeout of upstream, default: 5
 -p, --repeat-times <num>             num of packets to trustdns, default:1, max:5
 -n, --noip-as-chnip                  allow no-ip reply from chinadns (tag:none)
 -f, --fair-mode                      enable fair mode (nop, only fair mode now)
 -r, --reuse-port                     enable SO_REUSEPORT, default: <disabled>
 -v, --verbose                        print the verbose log, default: <disabled>
 -V, --version                        print `chinadns-ng` version number and exit
 -h, --help                           print `chinadns-ng` help information and exit
bug report: https://github.com/zfl9/chinadns-ng. email: [email protected] (Otokaze)

配置示例

  • chinadns-ng 通常与 iptables/nftables 透明代理一起用。
  • 这里列举的三个例子其实就是 ss-tproxy 中的使用范例。
  • 当然也可以在其他 Linux 环境下使用,具体看你的需求。

chnroute 分流模式

  • chnlist.txt (tag:chn) 走国内上游,将 IP 收集至 chnip,chnip6 ipset
  • gfwlist.txt (tag:gfw) 走可信上游,将 IP 收集至 gfwip,gfwip6 ipset
  • 其他域名 (tag:none) 同时走国内和可信上游,根据 IP 测试结果决定最终响应
# 监听地址和端口
bind-addr 0.0.0.0
bind-port 53

# 国内上游、可信上游
china-dns 114.114.114.114
trust-dns tcp://8.8.8.8

# 域名列表,用于分流
chnlist-file /etc/chinadns/chnlist.txt
gfwlist-file /etc/chinadns/gfwlist.txt
# chnlist-first

# 收集 tag:chn、tag:gfw 域名的 IP
add-tagchn-ip chnip,chnip6
add-taggfw-ip gfwip,gfwip6

# 用于测试 tag:none 域名的 IP (国内上游)
ipset-name4 chnroute
ipset-name6 chnroute6

# dns 缓存
cache 4096
cache-stale 86400
cache-refresh 20

# verdict 缓存 (用于 tag:none 域名)
verdict-cache 4096

# 详细日志
# verbose

gfwlist 分流模式

  • gfwlist.txt (tag:gfw) 走可信上游,将 IP 收集至 gfwip,gfwip6 ipset
  • 其他域名 (tag:chn) 走国内上游,不需要收集 IP(未指定 add-tagchn-ip)
# 监听地址和端口
bind-addr 0.0.0.0
bind-port 53

# 国内上游、可信上游
china-dns 114.114.114.114
trust-dns tcp://8.8.8.8

# 域名列表,用于分流
# 未被 gfwlist.txt 匹配的归为 tag:chn
gfwlist-file /etc/chinadns/gfwlist.txt
default-tag chn

# 收集 tag:gfw 域名的 IP
add-taggfw-ip gfwip,gfwip6

# dns 缓存
cache 4096
cache-stale 86400
cache-refresh 20

# 详细日志
# verbose

global 分流模式

  • ignlist.txt (tag:chn) 走国内上游,将 IP 收集至 ignip,ignip6 ipset
  • 其他域名 (tag:gfw) 走可信上游,不需要收集 IP(未指定 add-taggfw-ip)
# 监听地址和端口
bind-addr 0.0.0.0
bind-port 53

# 国内上游、可信上游
china-dns 114.114.114.114
trust-dns tcp://8.8.8.8

# 域名列表,用于分流
# 未被 ignlist.txt 匹配的归为 tag:gfw
chnlist-file /etc/chinadns/ignlist.txt
default-tag gfw

# 收集 tag:chn 域名的 IP
add-tagchn-ip ignip,ignip6

# dns 缓存
cache 4096
cache-stale 86400
cache-refresh 20

# 详细日志
# verbose


config

  • 2024.03.07 版本起,开始支持 -C/--config <path> 选项。
  • config 配置文件,一行一个,空行和#开头的行被忽略。
    • 格式 optname [value]optname 是不带 -- 的长命令行选项名。
    • 例如 bind-addr 127.0.0.1bind-port 65353noip-as-chnip
    • 不支持行尾注释(如 verbose # foo),请使用单独的#开头行。
    • 配置文件内可使用 config path/to/config 实现文件包含的效果。
    • 命令行选项中也可以指定多个 -C/--config 来使用多个配置文件。
  • -C/--config/config 只是从文件读取“命令行选项”并处理,无其他特别之处。
  • -C/--config 与其他命令行选项可随意混用,不可重复的选项以最后一个为准。

bind-addr、bind-port

  • bind-addr 用于指定监听地址,默认为 127.0.0.1。
    • 2023.10.28 版本起,若监听地址为 ::,则允许来自 IPv4/IPv6 的 DNS 查询。
    • 2024.03.07 版本起,bind-addr 允许指定多次,以便监听多个不同的 ip 地址。
  • bind-port 用于指定监听端口,默认为 65353。
    • 2024.03.07 版本起,会同时监听 TCP 和 UDP 端口,之前只监听了 UDP 端口。
    • 2024.03.25 版本起,可以给 bind-port 选项指定要监听的协议(TCP、UDP):
      • --bind-port 65353:监听 TCP + UDP,默认值。
      • --bind-port 65353@tcp+udp:监听 TCP + UDP,同上。
      • --bind-port 65353@tcp:只监听 TCP。
      • --bind-port 65353@udp:只监听 UDP。

china-dns、trust-dns

  • china-dns 选项指定国内上游 DNS 服务器,多个用逗号隔开。
  • trust-dns 选项指定可信上游 DNS 服务器,多个用逗号隔开。
    • 国内上游默认为 114.114.114.114,可信上游默认为 8.8.8.8
    • 组内的多个上游服务器是并发查询的模式,采纳最先返回的那个结果。
    • 2024.03.07 版本起,允许多次指定 china-dnstrust-dns 选项/配置。
    • 2024.03.07 版本起,每组上游的服务器数量不受限制(之前最多两个)。
  • 上游服务器的地址格式是 IP#端口,如果只给出 IP,则端口默认为 53。
  • 2024.03.07 版本起,支持 UDP + TCP 上游(根据查询方的传入协议决定)。
    • 若上游仅支持 UDP 查询,不支持 TCP 查询,请带上 udp:// 限定。
  • 2024.03.07 版本起,可在上游地址前加上 tcp:// 来强制使用 TCP DNS。
  • 2024.04.13 版本起,可在上游地址前加上 udp:// 来强制使用 UDP DNS。
  • 2024.04.27 版本起,支持 DoT 上游,tls://域名@IP,端口默认为 853。
  • 2024.05.12 版本起,DoT 上游地址中,允许省略域名信息,即 tls://IP

chnlist-file、gfwlist-file、chnlist-first

  • chnlist-file 白名单 域名列表文件,命中的域名只走国内 DNS。
  • gfwlist-file 黑名单 域名列表文件,命中的域名只走可信 DNS。
    • 2023.04.01 版本起,可指定多个路径,逗号隔开,如 -g a.txt,b.txt
    • 2024.03.07 版本起,可多次指定 chnlist-filegfwlist-file 选项。
  • chnlist-first 选项表示优先加载 chnlist,默认是优先加载 gfwlist。
    • 只有 chnlist 和 gfwlist 文件都提供时,*-first 才有实际意义。

default-tag

  • default-tag 可用于实现"纯域名分流",也可用于实现 gfwlist分流模式
  • 该选项的核心逻辑就是指定不匹配任何列表的域名tag,并无特别之处。
  • 通常与-g-m选项一起使用,比如下述例子,实现了"纯域名分流"模式:
    • -g gfwlist.txt -d chn:gfw列表的域名走可信上游,其他走国内上游。
    • -m chnlist.txt -d gfw:chn列表的域名走国内上游,其他走可信上游。
  • 如果想了解更多细节,建议看一下 chinadns-ng 的核心处理流程

add-tagchn-ip、add-taggfw-ip

  • add-tagchn-ip 用于动态添加 tag:chn 域名的解析结果 ip 到 ipset/nftset。
  • add-taggfw-ip 用于动态添加 tag:gfw 域名的解析结果 ip 到 ipset/nftset。
    • 对于add-tagchn-ip,若未给出集合名,则使用ipset-name4/6的那个集合。
    • 参数格式:ipv4集合名,ipv6集合名,nftset 的名称格式同 ipset-name4/6
    • 如果要使用 nftset,则创建 nftset 集合时必须带上 flags interval 标志。
    • 2024.04.13 版本起,可使用特殊集合名 null 表示对应集合不会被使用:
      • --add-tagchn-ip null,chnip6:表示不需要收集 ipv4 地址
      • --add-tagchn-ip chnip,null:表示不需要收集 ipv6 地址
      • --add-tagchn-ip chnip:表示不需要收集 ipv6 地址
      • 注意:仅当 ipv6 集合为 null 时,才可被省略

ipset-name4、ipset-name6

  • ipset-name4 指定存储了大陆 IPv4 地址的 ipset/nftset 集合名,默认 chnroute。
  • ipset-name6 指定存储了大陆 IPv6 地址的 ipset/nftset 集合名,默认 chnroute6。
  • nftset 名称格式:family名@table名@set名,自带的 nftset 数据文件使用如下名称:
    • 大陆 IPv4 地址集合:inet@global@chnroute
    • 大陆 IPv6 地址集合:inet@global@chnroute6
  • 这两个集合只用于 tag:none 域名,用于判定 china 上游的解析结果是否为大陆 IP。
  • 2024.04.13 版本起,也用于 --no-ipv6ip:chinaip:non_china 规则。
  • 2024.04.13 版本起,可使用特殊集合名 null 表示对应集合不会被使用。

group、group-*

  • group 声明一个自定义组(tag),参数值是组(tag)的名字。
    • 支持最多 6 个自定义组,每个组都有 3 个信息可配置,其中 ipset 可选。
    • 加载域名列表文件时,优先加载自定义组,然后加载内置组(chn、gfw)。
    • 内置组的加载顺序没有改变,依旧默认 gfw 优先,使用 -M 切换为 chn 优先。
    • 对于多个自定义组,按照命令行参数/配置顺序,后声明的组具有更高优先级。
    • 用例 1:将 DDNS域名 划分出来,单独一个组,用域名提供商的 DNS 去解析。
    • 用例 2:将 公司域名 划分出来,单独一个组,用公司内网专用的 DNS 去解析。
    • 2024.04.27 版本起,使用 null 作为 group 名时,表示过滤该组的域名查询。
      • null 组只有 group-dnl 信息,查询相关域名时,将返回 NODATA 响应消息。
  • group-dnl 当前组的域名列表文件,多个用逗号隔开,可多次指定。
  • group-upstream 当前组的上游 DNS,多个用逗号隔开,可多次指定。
  • group-ipset 当前组的 ipset/nftset (可选),用于收集解析出的结果 IP。

以配置文件举例:

# 声明自定义组 "foo"
group foo
group-dnl foo.txt
group-upstream 1.1.1.1,8.8.8.8
group-ipset fooip,fooip6

# 声明自定义组 "bar"
group bar
group-dnl bar.txt
group-upstream 192.168.1.1
# 没有 group-ipset,表示不需要 add ip

no-ipv6

  • no-ipv6 用于过滤 AAAA 查询(查询域名的 IPv6 地址),默认不设置此选项。
    • 未给出规则时,过滤所有 AAAA 查询。
    • 2024.04.13 版本起,规则有修改(不兼容旧版),多个规则使用逗号隔开:
      • tag:<name>:按域名 tag 过滤,如 tag:gfw,支持自定义的 tag
      • ip:china:若响应的 answer 中有 china IP,则过滤(空响应)
      • ip:non_china:若响应的 answer 中有 non-china IP,则过滤(空响应)
      • ip:* 规则的测试数据库由 --ipset-name6 选项提供,默认为 chnroute6

filter-qtype

  • filter-qtype 过滤给定 qtype 的查询,多个用逗号隔开,可多次指定。
    • --filter-qtype 64,65:过滤 SVCB(64)、HTTPS(65) 查询

cache、cache-*

  • cache 启用 DNS 缓存,参数是缓存容量(最多缓存多少个请求的响应消息)。
  • cache-stale 允许使用 TTL 已过期的(陈旧)缓存,参数是最大过期时长(秒)。
    • 向查询方返回“陈旧”缓存的同时,自动在后台刷新缓存,以便稍后能使用新数据。
    • 2024.04.13 版本起,数据类型从 u16 改为 u32,以允许设置更大的过期时长。
  • cache-refresh 若当前查询的缓存的 TTL 不足初始值的百分之 N,则提前在后台刷新。
  • cache-nodata-ttl 给 NODATA 响应提供默认的缓存时长,默认 60 秒,0 表示不缓存。
  • cache-ignore 不要缓存给定的域名(后缀,最高支持 8 级),此选项可多次指定。

verdict-cache

  • verdict-cache 启用 tag:none 域名的判决结果缓存,参数是缓存容量。
    • tag:none 域名的查询会同时转发给 china、trust 上游,根据 china 上游的 ip test 结果,决定最终响应。
    • 这里说的 判决结果 就是指这个 ip test 结果,即:给定的 tag:none 域名是 大陆域名 还是 非大陆域名
    • 如果记下此信息,则后续查询同一域名时(未命中 DNS 缓存时),只转发给特定上游组,不同时转发。
    • 缓存容量上限是 65535,此缓存没有 TTL 限制;缓存满时会随机删除一个旧缓存数据。
    • 建议启用此缓存,可帮助减少 tag:none 域名的重复请求和判定,还能减少 DNS 泄露。
    • 注意,判决结果缓存与 DNS 缓存是互相独立的、互补的;这两个缓存系统可同时启用。

hosts、dns-rr-ip

  • hosts 加载 hosts 文件,参数默认值为 /etc/hosts,此选项可多次指定。
  • dns-rr-ip 定义本地的 A/AAAA 记录(与 hosts 类似),此选项可多次指定。
    • 格式:<names>=<ips>,多个 name 使用逗号隔开,多个 ip 使用逗号隔开。

cert-verify、ca-certs

  • cert-verify 验证 DoT 上游的 SSL 证书(有效性,是否受信任,域名是否匹配)。
    • wolfssl 在某些平台(arm32、mips)可能无法正确验证 SSL 证书,见 #169
  • ca-certs CA 根证书路径,用于验证 DoT 上游的 SSL 证书。默认自动检测。

no-ipset-blacklist

  • no-ipset-blacklist 若指定此选项,则 add-ip 时不进行内置的 IP 过滤。
    • 默认情况下,以下 IP 不会被添加到 ipset/nftset 集合,见 #162
    • 127.0.0.0/80.0.0.0/8::1:: (loopback地址、全0地址)

其他杂项配置

  • timeout-sec 用于指定上游的响应超时时长,单位秒,默认 5 秒。
  • repeat-times 针对可信 DNS (UDP) 重复发包,默认为 1,最大为 5。
  • noip-as-chnip 接受来自 china 上游的没有 IP 地址的响应,详细说明
  • fair-mode2023.03.06版本开始,只有公平模式,指不指定都一样。
  • reuse-port 用于多进程负载均衡(实践证明没这个必要,没必要使用)。
  • verbose 选项表示记录详细的运行日志,除非调试,否则不建议启用。

域名列表

文件格式

域名列表是一个纯文本文件(不支持注释),每行都是一个 域名后缀,如baidu.comwww.google.comwww.google.com.hk,不要以.开头或结尾,出于性能考虑,域名label数量做了人为限制,最多只能4个,过长的会被截断,如test.www.google.com.hk截断为www.google.com.hk


加载顺序

所有组的域名列表都被 加载 到同一个数据结构,一个 域名后缀 一旦被加载,其内部属性就不会被修改。因此,当一个 域名后缀 存在于多个组的域名列表时,优先加载的那个组将“获胜”。举个例子:假设 foo.com 同时存在于 tag:chn、tag:gfw 组的域名列表内,且优先加载 tag:gfw 组,则 foo.com 属于 tag:gfw 组。

先加载“自定义组”的域名列表,然后再加载“内置组”的域名列表(chn 和 gfw 谁先,取决于--chnlist-first)。


匹配顺序

收到 dns query 时,会对 qname 进行 最长后缀匹配。举个例子,若 qname 为 x.y.z.d.c.b.a,则匹配顺序为:

  • d.c.b.a,检查数据结构中是否存在此域名后缀。
  • c.b.a,检查数据结构中是否存在此域名后缀。
  • b.a,检查数据结构中是否存在此域名后缀。
  • a,检查数据结构中是否存在此域名后缀。

一旦其中某个 域名后缀 匹配成功,匹配就结束,并获取该 域名后缀 所属的 tag(group),并将 tag 信息记录到该 dns query 的相关数据结构,后续所有逻辑(分流、ipset/nftset)都基于这个 tag 信息,与 qname 无关。

如果都匹配失败,则该 dns query 的 tag 被设为 default-tag 选项的值,默认情况下,default-tag 是 none。global 分流、gfwlist 分流都基于此机制实现。你可以将 default-tag 设为不同的 tag,来实现各种目的。


性能、内存开销

chinadns-ng 在编码时特意考虑了性能和内存占用,并进行了深度优化,因此不必担心查询效率和内存开销。域名条目数量只会影响一点儿内存占用,对查询速度没影响,也不必担心内存占用,这是在Linux x86-64的实测数据:

  • 没有加载域名列表时,内存为 140 KB
  • 加载 5700+ 条 gfwlist.txt 时,内存为 304 KB
  • 加载 5700+ 条 gfwlist.txt 以及 73300+ 条 chnlist.txt 时,内存为 2424 KB
  • 如果确实内存吃紧,可以使用更加精简的 chnlist 源(不建议只使用 gfwlist.txt 列表)
  • 2023.04.11 版本针对域名列表的内存占用做了进一步优化,因此占用会更少,测试数据就不贴了

简单测试

导入项目根目录下的 chnroute*.ipsetchnroute*.nftset

# 使用 ipset
ipset -R <chnroute.ipset
ipset -R <chnroute6.ipset

# 使用 nftset
nft -f chnroute.nftset
nft -f chnroute6.nftset

只要没有从内核删除 ipset/nftset 集合,下次运行就不需要再次导入了。

运行 chinadns-ng,我自己配了全局透明代理,所以访问 8.8.8.8 会走代理出去。

# 加载 gfwlist 和 chnlist,并动态添加 tag:chn 域名解析结果至 ipset/nftset
chinadns-ng -g gfwlist.txt -m chnlist.txt -a # 使用 ipset
chinadns-ng -g gfwlist.txt -m chnlist.txt -a -4 inet@global@chnroute -6 inet@global@chnroute6 # 使用 nftset

chinadns-ng 默认监听 127.0.0.1:65353,可以给 chinadns-ng 带上 -v 参数,使用 dig 测试,观察其日志。

常见问题

tag:chn、tag:gfw、tag:none 是指什么

这是 chinadns-ng 对域名的一个简单分类:

  • 被 chnlist.txt 匹配的域名归为 tag:chn
  • 被 gfwlist.txt 匹配的域名归为 tag:gfw
  • group-dnl 匹配的域名归为 自定义组
  • 其它域名默认归为 tag:none,可通过 -d 修改

域名分流ipset/nftset 的核心流程,可以用这几句话来描述:

  • tag:chn:只走 china 上游(单纯转发),如果启用 --add-tagchn-ip,则添加解析结果至 ipset/nftset
  • tag:gfw:只走 trust 上游(单纯转发),如果启用 --add-taggfw-ip,则添加解析结果至 ipset/nftset
  • 自定义组:只走 所属组的 上游(单纯转发),如果启用 --group-ipset,则添加解析结果至 ipset/nftset
  • tag:none:同时走 china 和 trust,如果 china 上游返回国内 IP,则接受其结果,否则采纳 trust 结果

tag:chntag:gfw自定义组不存在任何判定/过滤;tag:none的判定/过滤也仅限于 china 上游的响应结果


如何以守护进程形式在后台运行 chinadns-ng

(chinadns-ng 参数... </dev/null &>>/var/log/chinadns-ng.log &)

如何更新 chnroute.ipset、chnroute6.ipset

./update-chnroute.sh
./update-chnroute6.sh
ipset -F chnroute
ipset -F chnroute6
ipset -R -exist <chnroute.ipset
ipset -R -exist <chnroute6.ipset

如何更新 chnroute.nftset、chnroute6.nftset

./update-chnroute-nft.sh
./update-chnroute6-nft.sh
nft flush set inet global chnroute
nft flush set inet global chnroute6
nft -f chnroute.nftset
nft -f chnroute6.nftset

如何更新 gfwlist.txt、chnlist.txt

./update-gfwlist.sh
./update-chnlist.sh
chinadns-ng -g gfwlist.txt -m chnlist.txt 其他参数... # 重新运行 chinadns-ng

如何使用 TCP 协议与 DNS 上游进行通信

从 2024.03.07 版本开始,有以下更改:

  • 假设上游地址为 1.1.1.1,则根据查询方的传入协议来选择与上游的通信协议:
    • 若查询方的传入协议为 UDP,则 chinadns-ng 与该上游的通信协议是 UDP。
    • 若查询方的传入协议为 TCP,则 chinadns-ng 与该上游的通信协议是 TCP。
  • 假设上游地址为 tcp://1.1.1.1,则 chinadns-ng 与该上游的通信方式总是 TCP。
  • 假设上游地址为 udp://1.1.1.1,则 chinadns-ng 与该上游的通信方式总是 UDP。

对于之前的版本,原生只支持 UDP 协议,如果想使用 TCP 访问上游,可以使用 dns2tcp 这个小工具,作为 chinadns-ng 的上游。其他协议也是一样的道理,比如 DoH/DoT/DoQ,可以借助 dnsproxy 等实用工具。

# 运行 dns2tcp
dns2tcp -L "127.0.0.1#5353" -R "8.8.8.8#53"

# 运行 chinadns-ng
chinadns-ng -c 114.114.114.114 -t '127.0.0.1#5353'

为什么不内置 TCP、DoH、DoT 等协议的支持

2024.03.07 版本起,已内置完整的 TCP 支持(传入、传出)。
2024.04.27 版本起,支持 DoT 协议的上游,DoH 不打算实现。

我想让代码保持简单,只做真正必要的事情,其他事情让专业的工具去干。

换句话说,保持简单和愚蠢,只做一件事,并认真做好这件事。


chinadns-ng 并不读取 chnroute.ipset、chnroute6.ipset

只有 tag:none 域名存在 ipset/nftset 判断&&过滤,tag:gfw 和 tag:chn 域名不会走 ip test 逻辑。

启动时也不会检查这些 ipset 集合是否存在,它只是在收到 dns 响应时通过 netlink 询问 ipset 模块,给定的 ip 是否存在。这种机制使得我们可以在 chinadns-ng 运行时直接更新 chnroute、chnroute6 列表,它会立即生效,不需要重启 chinadns-ng。使用 ipset 存储地址段还能与 iptables 规则更好的契合,因为不需要维护两份独立的 chnroute 列表。TODO:支持nftables sets(已支持)。


接受 china 上游返回的 IP为保留地址 的解析记录

将对应的保留地址(段)加入到 chnroutechnroute6 集合即可。chinadns-ng 判断是否为"大陆IP"的核心就是查询 chnroute、chnroute6 集合,程序内部并没有其他隐含的判断规则。

注意:只有 tag:none 域名需要这么做;对于 tag:chn 域名,chinadns-ng 只是单纯转发,不涉及 ipset/nftset 判定;所以你也可以将相关域名加入 chnlist.txt(支持从多个文件加载域名列表)。

为什么没有默认将保留地址加入 chnroute*.ipset/nftset?因为我担心 gfw 会给受污染域名返回保留地址,所以没放到 chnroute 去。不过现在受污染域名都走 gfwlist.txt 机制了,只会走 trust 上游,加进去应该没问题。


received an error code from kernel: (-2) No such file or directory

只有 tag:none 域名存在 ipset/nftset 判断&&过滤,tag:gfw 和 tag:chn 域名不会走 ip test 逻辑。

意思是指定的 ipset 集合不存在;如果是 [ipset_addr4_is_exists] 提示此错误,说明没有导入 chnroute ipset(IPv4);如果是 [ipset_addr6_is_exists] 提示此错误,说明没有导入 chnroute6 ipset(IPv6)。要解决此问题,请导入项目根目录下 chnroute.ipsetchnroute6.ipset 文件。

需要提示的是:chinadns-ng 在查询 ipset 集合时,如果遇到类似的 ipset 错误,都会将给定 IP 视为国外 IP。因此如果你因为各种原因不想导入 chnroute6.ipset,那么产生的效果就是:当客户端查询 IPv6 域名时(即 AAAA 查询),会导致所有国内 DNS 返回的解析结果都被过滤,然后采用可信 DNS 的解析结果。


trust上游存在一定的丢包,怎么缓解

  • 方法1:重复发包,也即 --repeat-times N 选项,这里的 N 默认为 1,可以改为 3,表示在给一个 trust 上游(UDP)转发查询消息时,同时发送 3 个相同的查询消息。
  • 方法2:TCP查询,对于新版本(>= 2024.03.07),在 trust 上游的地址前加上 tcp://;对于老版本,可以加一层 dns2tcp,来将 chinadns-ng 发出的 UDP 查询转为 TCP 查询。

推荐方法2,因为 QoS 等因素,TCP 流量的优先级通常比 UDP 高,且 TCP 本身就提供丢包重传等机制,比重复发包策略更可靠。另外,很多代理程序的 UDP 实现效率较低,很有可能出现 TCP 查询总体耗时低于 UDP 查询的情况。


为何选择 ipset/nftset 来处理 chnroute 查询

因为使用 ipset/nftset 可以与 iptables/nftables 规则共用一份 chnroute;达到联动的效果。


是否支持 nftables 的 set 查询接口

目前还不支持,但已加入 TODO 列表,不出意外应该快了(主要是还在寻找不依赖任何库的情况下访问nft set。2023.04.11 版本已支持。


是否打算支持 geoip.dat 等格式的 chnroute

目前没有这个计划,因为如果要自己实现 chnroute 集合,那就要实现高性能的数据结构和算法,这有点超出了我的能力范围。但更重要的是因为 chinadns-ng 通常与 iptables/nftables 一起使用(配合透明代理),若使用非 ipset/nftset 实现,会导致两份重复的 chnroute,且无法与 iptables/nftables 规则实现联动。


是否打算支持 geosite.dat 等格式的 gfwlist/chnlist

目前也没有这个计划,这些二进制格式需要引入 protobuf 等库,我不是很想引入依赖,而且 geosite.dat 本身也大。


--add-tagchn-ip 选项的作用

主要用于配合 chnroute 分流模式(透明代理),这样只要是 chnlist.txt 里面的域名,都必定走直连,不会走代理。在这之前,如果想实现类似功能,可能需要借助 dnsmasq,但 dnsmasq 不适合配置大量域名(server/ipset/nftset),会影响解析性能。chinadns-ng 为此做了专门优化,以最大可能来降低开销。


chinadns-ng 也可用于 gfwlist 透明代理分流

# 创建 ipset,用于存储 tag:gfw 域名的 IP (nftset 同理)
ipset create gfwlist hash:net family inet # ipv4
ipset create gfwlist6 hash:net family inet6 # ipv6

# 指定 gfwlist.txt,default-tag,add-taggfw-ip 选项
chinadns-ng -g gfwlist.txt -d chn -A gfwlist,gfwlist6

传统上,这是通过 dnsmasq 来实现的,但 dnsmasq 的 server/ipset/nftset 功能不擅长处理大量域名,影响性能,只是 gfwlist.txt 域名数量比 chnlist.txt 少,所以影响较小。如果你在意性能,如低端路由器,可使用 chinadns-ng 来实现。


使用 chinadns-ng 替代 dnsmasq 的注意事项

chinadns-ng 2.0 已经足以替代经典用例下的 dnsmasq:

  • 域名分流效率比 dnsmasq 高得多,即使存在大量域名规则,也不影响性能,内存占用也很低
  • nftset 操作效率比 dnsmasq 高,即使在短时间内写入大量 IP 也没问题(dnsmasq 可能会报错)
  • dnsmasq 的 TCP DNS 实现方式非常低效,每个 TCP 连接都可能在后台 fork 一个 dnsmasq 进程
  • chinadns-ng 可强制使用 TCP 上游,且原生支持 DoT,wolfssl 的体积/性能/内存开销都非常优秀

对于路由器这种场景,你可能仍然需要 dnsmasq 的 DHCP 等功能,这种情况下,建议关闭 dnsmasq 的 DNS 功能:

  • 修改 dnsmasq 配置,将port改为0,关闭 dnsmasq 的 DNS 功能,其他功能不受影响(如 DHCP)
  • 此时请务必配置 dhcp-option=option:dns-server,0.0.0.0,确保会下发 dns-server 给 DHCP 客户端
  • 因为关闭 DNS 功能后,在未显式配置相关 dhcp-option 的情况下,dnsmasq 不会自动下发 dns-server
  • 0.0.0.0 是一个特殊 IP,dnsmasq 在内部会替换为“dnsmasq 所在主机的 IP”,避免写死 IP 地址,更灵活

--noip-as-chnip 选项的作用

此选项只作用于 tag:none 域名 && qtype=A/AAAA && china 上游,trust 上游不存在过滤。

chinadns-ng 对 tag:none 域名的 A/AAAA 查询有特殊处理逻辑:对 china 上游返回的 reply 进行 ip test (chnroute),如果测试结果是 china IP,则采纳 china 上游的结果,否则采纳 trust 上游的结果(为了减少重复判定,可启用 verdict-cache 来缓存该测试结果)。

要进行 ip test,显然要求 reply 中有 IP 地址;如果没有 IP(如 NODATA 响应),就没办法 test 了。

  • 默认情况下,chinadns-ng 将 no-ip 视为 非 china IP,也即:采纳 trust 上游结果。
  • 若指定了 --noip-as-chnip,则将 no-ip 视为 china IP,也即:采纳 china 上游结果。

默认拒绝 china 上游的 no-ip 结果是为了避开 gfw 污染,防止 gfw 故意对某些域名返回空 answer (no-ip)。


如何以普通用户身份运行 chinadns-ng

向内核查询 ipset/nftset 需要 CAP_NET_ADMIN 权限,使用非 root 用户身份运行 chinadns-ng 时将产生 Operation not permitted 错误。解决方法有很多,这里介绍其中一种:

# 授予 CAP_NET_ADMIN 权限
# 用于执行 ipset/nftset 操作
sudo setcap cap_net_admin+ep /usr/local/bin/chinadns-ng

# 授予 CAP_NET_ADMIN + CAP_NET_BIND_SERVICE 权限
# 用于执行 ipset/nftset 操作、监听小于 1024 的端口
sudo setcap cap_net_bind_service,cap_net_admin+ep /usr/local/bin/chinadns-ng

chinadns-ng's People

Contributors

pexcn avatar sakamoto-poteko avatar zfl9 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

chinadns-ng's Issues

设置两个国内DNS或两个可信DNS时,其中一个DNS不可用可能导致查询失败

作者你好,

想请教下,当设置两个国内DNS和两个可信DNS时,当其中一个国内DNS或其中一个可信DNS不可用时(e.g. 国内DoH服务器故障,或可信DNS走的代理失效),有时候会导致ChinaDNS-ng timeout无法给出结果。我想知道查询的逻辑是同时查询两个DNS,还是会先查询第一个,如果失效再查询第二个呢?看log感觉似乎是前者,但不太理解为何有时把失效的DNS放在第二个时又能给出结果。

谢谢!

目前两个模式的逻辑疑似存在问题

我用的是电信网,有公网IPv4,也有原生双栈的支持,但因一些原因,我改用6in4作为IPv6地址。
我将您的这个项目布置在刷了openwrt的路由器上,用了一段时间,感觉没有任何问题。
然而好景不长,目前我发现了您的这个项目存在逻辑问题:当国内DNS返回国内网站的IPv6地址查询结果为空时,会将从国外DNS的IPv6地址查询结果混进来,并可能因此导致访问体验劣化

图一 我再路由器的5453口部署了stubby并直接使用了DoT来进行DNS查询,图一是只从那个端口进行dig的结果.

图二 我再直接向114DNS进行dig查询,显而易见的是没有IPv6结果的.

图三 那我再向路由器进行nslookup查询会如何?图三就是结果

图四 这是我在用的配置,免得又说无图言O之类的

我只想说目前的逻辑看起来存在没有细分IPv4和IPv6结果的逻辑问题,还望改进

使用Alpine镜像编译报错 error: unknown type name 'time_t'; did you mean 'size_t'?

报错信息如下

/chinadns-ng # make
gcc -std=c99 -Wall -Wextra -O3 -c chinadns.c -o chinadns.o
gcc -std=c99 -Wall -Wextra -O3 -c dnsutils.c -o dnsutils.o
gcc -std=c99 -Wall -Wextra -O3 -c maputils.c -o maputils.o
In file included from maputils.h:6,
                 from maputils.c:2:
netutils.h:43:22: error: unknown type name 'time_t'; did you mean 'size_t'?
 int new_once_timerfd(time_t second);
                      ^~~~~~
                      size_t
make: *** [Makefile:23: maputils.o] Error 1
/chinadns-ng # cat /etc/os-release 
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.9.3
PRETTY_NAME="Alpine Linux v3.9"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
/chinadns-ng # 

编译过程使用的命令

docker run -it --rm alpine sh

sed -i 's/dl-cdn.alpinelinux.org/mirrors.huaweicloud.com/g' /etc/apk/repositories

apk add build-base git

git clone https://github.com/zfl9/chinadns-ng

cd chinadns-ng

make # 这步报错

make install

功能请求:提供未命中黑白名单的查询结果的更多处理方式

按照目前文档的描述,无论如何设置,最终都会判断上游 dns 的返回 IP 是否为国内的,如果不为国内的 IP 就会丢弃 china-dns 的结果,只使用上游 trus-dns 的返回结果。

如果说我 trus-dns 的查询是走代理的,一些未被污染的国外域名且未被墙的(其 IP 非国内)查询到的结果最终也是通过代理查询到的,其返回的 IP 地址对代理服务器是最优的,然而对于我本地来说却可能不是最优的。

基于此,希望能提供一个选项来提供未命中黑白名单的查询结果的更多处理方式。如:

  1. 未命中黑白名单的请求结果判断其 IP 是否命中 chnroute, 如果命中使用 china-dns 的结果,负责使用 trus-dns 的结果
  2. 未命中黑白名单的请求结果统一使用 china-dns 的结果
  3. 未命中黑白名单的请求结果统一使用 trus-dns 的结果
  4. 未命中黑白名单的请求结果使用 china-dnstrus-dns 最先返回的结果

How to compile arm base binary file?

I tried to change command to make CC=arm-linux-gnueabihf-gcc, and there is no respond for it.

it only report"make: Nothing to be done for 'all'." it looks like that can not finish cross compile if the method I tried is right.

Thanks if you have time to reply!

逻辑上的一点儿小疑问

举例

网址:iptv.pdsu.edu.cn,不在黑名单和白名单里
A:211.69.16.31,不在chnroute
AAAA:2001:250:4814:1::200,在chnroute6

软件设置:指定国内dns和可信dns,指定黑名单和白名单,白名单优先,公平模式,
备注:上游dns禁止返回AAAA,只能返回A记录,

按照公平模式来的话,实测最终只返回了211.69.16.31这个结果。

因为是双栈的,所以我没太明白,国内的dns返回结果因为211.69.16.31不在chnroute就连同AAAA地址一起都被丢弃了吗?

请问gfwlist是否可以只解析ipv4?

我不会设置ipv6分流规则,好像路由的ip6tables也不支持nat,同时,我有pt需要,不能禁用ipv6。

所以希望gfwlist只解析ipv4,不知道该如何设置?还是默认就可以不需要设置?

谢谢。

查询一些特定的域名有问题?

查询一些特定的域名,比如 scontent-sin6-2.cdninstagram.com, scontent-lax3-2.cdninstagram.com 等(浏览器打开 instagram.com 就能重现),国内 DNS 是查不到结果的,而国外 DNS 却可以查到结果。

按照目前的逻辑,只能等到超时,在这种情况下非常的慢。以下是我的启动命令和日志,可以看出,从发起请求到得到结果耗时 8 秒。而 ChinaDNS 原版的逻辑是直接采用可信 DNS 的结果,那样虽然很快,但是却没有了线路优化的效果,前几个 issue 提到过。

我想能不能优化一下这种情况?
比如(加一个 --fast 选项?)或者把逻辑改成,当国内 DNS 超过 200ms 没有响应时,直接采用可信 DNS 的结果?
EDIT:
似乎没有比较好的方式...?

# server
chinadns-ng -b 0.0.0.0 -l 5354 -c 114.114.114.114 -t 127.0.0.1#5300 -4 chnroute -6 chnroute6 -o 3 -v

# client
dig scontent-sin6-2.cdninstagram.com @192.168.1.1 -p 5354

# log
2019-08-30 03:44:03 INF: [handle_local_packet] query [scontent-sin6-2.cdninstagram.com] from 192.168.1.107#54729
2019-08-30 03:44:03 INF: [handle_remote_packet] reply [scontent-sin6-2.cdninstagram.com] from 127.0.0.1#5300, result: delay
2019-08-30 03:44:06 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 35
2019-08-30 03:44:07 INF: [handle_local_packet] query [scontent-sin6-2.cdninstagram.com] from 192.168.1.107#54729
2019-08-30 03:44:07 INF: [handle_remote_packet] reply [scontent-sin6-2.cdninstagram.com] from 127.0.0.1#5300, result: delay
2019-08-30 03:44:10 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 36
2019-08-30 03:44:10 INF: [handle_local_packet] query [scontent-sin6-2.cdninstagram.com] from 192.168.1.107#54729
2019-08-30 03:44:10 ERR: [dns_rheader_check] the response code not equal to RCODE_NOERROR
2019-08-30 03:44:10 INF: [handle_remote_packet] reply [scontent-sin6-2.cdninstagram.com] from 114.114.114.114#53, result: filter
2019-08-30 03:44:10 ERR: [dns_rheader_check] the response code not equal to RCODE_NOERROR
2019-08-30 03:44:10 INF: [handle_remote_packet] reply [scontent-sin6-2.cdninstagram.com] from 114.114.114.114#53, result: ignore
2019-08-30 03:44:10 ERR: [dns_rheader_check] the response code not equal to RCODE_NOERROR
2019-08-30 03:44:10 INF: [handle_remote_packet] reply [scontent-sin6-2.cdninstagram.com] from 114.114.114.114#53, result: ignore
2019-08-30 03:44:11 INF: [handle_remote_packet] reply [scontent-sin6-2.cdninstagram.com] from 127.0.0.1#5300, result: accept

顺便问下,日志里的 [dns_rheader_check] the response code not equal to RCODE_NOERROR 是怎么回事?

macOS support

gcc -std=c99 -Wall -Wextra -O3 -c chinadns.c -o chinadns.o
gcc -std=c99 -Wall -Wextra -O3 -c dnsutils.c -o dnsutils.o
gcc -std=c99 -Wall -Wextra -O3 -c dnlutils.c -o dnlutils.o
gcc -std=c99 -Wall -Wextra -O3 -c maputils.c -o maputils.o
gcc -std=c99 -Wall -Wextra -O3 -c netutils.c -o netutils.o
netutils.c:12:10: fatal error: chinadns.c:20:'sys/timerfd.h'10: fatal error: 'sys/epoll.h' file not found
 file not found
#include <sys/timerfd.h>
         ^~~~~~~~~~~~~~~
#include <sys/epoll.h>
         ^~~~~~~~~~~~~
1 error generated1.
 error generated.
make: *** [netutils.o] Error 1
make: *** Waiting for unfinished jobs....
make: *** [chinadns.o] Error 1

It seems macOS should use kqueue instead.

讨论:一个关于国内、可信dns返回的处理的逻辑问题

当可信dns先返回,如果是国内ip,则结束此次回话,直接以这个国内ip作为标准。这里一个问题是,可能一些网站,国外解析线路都会解析到沿海(比如广东移动),来加速国外访问,这时候如果我是联通,可能访问就炸了。

出错提示failed to bind address to socket

# /usr/local/bin/chinadns-ng -v
2019-10-28 14:23:16 INF: [main] local listen addr: 127.0.0.1#65353
2019-10-28 14:23:16 INF: [main] chinadns server#1: 114.114.114.114#53
2019-10-28 14:23:16 INF: [main] trustdns server#1: 8.8.8.8#53
2019-10-28 14:23:16 INF: [main] ipset ip4 setname: chnroute
2019-10-28 14:23:16 INF: [main] ipset ip6 setname: chnroute6
2019-10-28 14:23:16 INF: [main] dns query timeout: 3 seconds
2019-10-28 14:23:16 INF: [main] core judgment mode: fast mode
2019-10-28 14:23:16 INF: [main] print the verbose running log
2019-10-28 14:23:16 ERR: [main] failed to bind address to socket: (98) Address already in use

交叉编译的文件不能运行

我用entware的toolchain交叉编译出来的文件,在K3上不能运行,提示 -sh: ./chinadns-ng: not found 。编译过程中没有报错。

dnsutils.c 似乎和centos 6不兼容?

2020-03-03 20:03:23 ERR: [dns_qheader_check] this is a query packet, but header->qr != 0
2020-03-03 20:03:28 ERR: [dns_qheader_check] this is a query packet, but header->qr != 0
2020-03-03 20:03:33 ERR: [dns_qheader_check] this is a query packet, but header->qr != 0
完全无法解析,修改dns_qheader_check函数,直接return true倒是可以绕过

最新的commit 在 CentOS7上编译失败

Makefile:22: *** mixed implicit and static pattern rules. Stop.

然后我把第22行改成 .c.o:
编译成功

gcc -std=c99 -Wall -Wextra -O2 -c chinadns.c -o chinadns.o
gcc -std=c99 -Wall -Wextra -O2 -c dnsutils.c -o dnsutils.o
gcc -std=c99 -Wall -Wextra -O2 -c dnlutils.c -o dnlutils.o
gcc -std=c99 -Wall -Wextra -O2 -c maputils.c -o maputils.o
gcc -std=c99 -Wall -Wextra -O2 -c netutils.c -o netutils.o
gcc -std=c99 -Wall -Wextra -O2 -s -o chinadns-ng chinadns.o dnsutils.o dnlutils.o maputils.o netutils.o

upstream dns server reply timeout

2020-03-14 15:28:49 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12916
2020-03-14 15:28:51 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12918
2020-03-14 15:28:51 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12919
2020-03-14 15:28:51 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12920
2020-03-14 15:28:51 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12921
2020-03-14 15:28:52 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12922
2020-03-14 15:28:53 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12923
2020-03-14 15:28:53 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12924
2020-03-14 15:28:55 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12925
2020-03-14 15:29:04 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 12927

日志有非常多的报错,提示上游dns服务器replay超时,但是我测试是没有问题的,不知道这个超时的机制是如何判断的,或者能否修改超时的判断和时延。多谢!

使用时报错

root@Mashiro:/ovo# chinadns-ng -l 7913 -c 127.0.0.1#53 -t 127.0.0.1#7053 -g /var/etc/passwall/gfwlist.txt
2020-06-07 22:47:06 INF: [main] local listen addr: 127.0.0.1#7913
2020-06-07 22:47:06 INF: [main] chinadns server#1: 127.0.0.1#53
2020-06-07 22:47:06 INF: [main] trustdns server#1: 127.0.0.1#7053
2020-06-07 22:47:06 INF: [main] ipset ip4 setname: chnroute
2020-06-07 22:47:06 INF: [main] ipset ip6 setname: chnroute6
2020-06-07 22:47:06 INF: [main] dns query timeout: 5 seconds
2020-06-07 22:47:06 INF: [main] gfwlist entries count: 5499
2020-06-07 22:47:06 INF: [main] filter reply without ip addr
2020-06-07 22:47:06 INF: [main] cur judgment mode: fast mode
2020-06-07 22:47:08 ERR: [new_once_timerfd] failed to create timer fd: (24) No file descriptors available

请问这个怎么解决

新功能请求:并发请求

记录一些能想到的一些新功能:

  1. 并发请求,来自这里 e768685#r34908475
    2. 添加一个 --cache-size <num> 选项,用于设置缓存域名的个数,默认值为 0,即不设置缓存。
    当有客户端请求域名时,先查找缓存中是否有该域名的结果,如果有,则不向上游请求,直接从缓存中返回;如果没有再接着当前版本的逻辑执行下去。缓存过期时间默认为 TTL 超时的时间。

    3. 再添加一个 --min-cache-ttl <seconds> 选项,用于重新设置缓存结果的 TTL 超时时间,默认值为 0,即不设置,这时的 TTL 为默认上游返回的时间。

待定:
1. 是否应该缓存无效的结果?例如一些不存在的域名:dig jdhfjdufjsisgovojdjdjf.com...
2. 是否应该添加一个 --min-ttl <seconds> 用于设置不开启缓存时候的 TTL 超时时间?
3. 当不存在指定的 ipset 时,是不是应该直接退出程序显得比较合理?不然没有意义。

@zfl9

failed: connection refused

root@iZwz9d1rjhrzzxa4lsoi93Z:~# dig pixiv.net @127.0.0.1 -p 5360
;; Truncated, retrying in TCP mode.
;; Connection to 127.0.0.1#5360(127.0.0.1) for pixiv.net failed: connection refused.
root@iZwz9d1rjhrzzxa4lsoi93Z:~# dig pixiv.net @127.0.0.1 -p 5360

; <<>> DiG 9.10.3-P4-Debian <<>> pixiv.net @127.0.0.1 -p 5360
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44245
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;pixiv.net.                     IN      A

;; ANSWER SECTION:
pixiv.net.              168     IN      A       210.140.131.219

;; Query time: 5 msec
;; SERVER: 127.0.0.1#5360(127.0.0.1)
;; WHEN: Tue Mar 31 22:31:45 CST 2020
;; MSG SIZE  rcvd: 43

第一TCP查询失败,第二次才正常,怎么解决这中问题?
A}$KPTIBX7DXN$~~@ZV8ZHJ

what will happen if china-dns return 127.0.0.1

In the README, it was said that "if a result from china-dns is in ipset CHNRoute, we use that result, and ignore any other results", while in "chnroute.ipset", 127.0.0.1/8 is included;
so, if china-dns return 127.0.0.1 for sites like google.com, chinadns-ng will use that result too?

chinadns-ng 与 Unbound EDNS 配合貌似有问题

大神您好,我使用的是 Unbound 做缓存 + 上游 chinadns-ng (使用国内dns 119.29.29.29 + dot/doh 可信dns),但是我测试的时候发现当 Unbound 开启 edns 后,会频繁出现上游链接超时,不开启 edns 上游就不超时,而且很多域名无法解析,关闭 unbound edns 就正常了,我有三台机器全部能复现,使用 dnsdist 开启 edns 后也是这个样子,搞不清楚是哪里的问题,请教一下大神。

2020-03-11 17:45:32 INF: [handle_remote_packet] reply [sb.scorecardresearch.com.edgekey.net] from 127.0.0.1#5354, result: delay
2020-03-11 17:45:32 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 335
2020-03-11 17:45:32 INF: [handle_local_packet] query [c.bing.com] from 127.0.0.1#65445
2020-03-11 17:45:32 INF: [handle_remote_packet] reply [c.bing.com] from 127.0.0.1#5354, result: delay
2020-03-11 17:45:33 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 336
2020-03-11 17:45:33 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 337
2020-03-11 17:45:34 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 338
2020-03-11 17:45:35 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 339
2020-03-11 17:45:35 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 340
2020-03-11 17:45:35 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 341
2020-03-11 17:45:35 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 342
2020-03-11 17:45:35 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 343
2020-03-11 17:45:35 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 344
2020-03-11 17:45:35 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 345
2020-03-11 17:45:35 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 346
2020-03-11 17:45:36 INF: [handle_local_packet] query [www.bing.com] from 127.0.0.1#50444
2020-03-11 17:45:39 ERR: [handle_timeout_event] upstream dns server reply timeout, unique msgid: 347

有俩网址,原版没问题,但是chinadns-ng就不行?该怎么设置,哪里的问题呀?

版本是最新的ChinaDNS-NG v1.0-beta.15

跑在路由器上的,配合ss的dnsmsq,ss是gfwlist模式

这两个网址,同样跑在路由器上原版chinadns使用服务器202.106.195.68,202.106.46.151,dns.google可以打开
https://cn.wsj.com/
https://cn.nytimes.com/

ss没有改动任何配置情况下ng版打不开这俩网址,试了下边这几个参数都打不开

  • -g /opt/app/chinadns_ng/gfwlist.txt
  • -g /opt/app/chinadns_ng/gfwlist.txt -f
  • -f
  • 空,没加任何参数

gfwlist是采用https://github.com/gfwlist/gfwlist ,包含
.nytimes.com
||nytimes.com
.wsj.com
||wsj.com

然后ng版本,测试访问google,youtube正常

关于trust-dns 的问题

trust-dns 可以为本地的dnscrypt-proxy么?
我看readme里说访问可信DNS必须经过代理,不过我这里的trust-dns 是本地的dnscrypt-proxy(127.0.0.1:5753),应该是可以的吧? 多谢!

默认延时的问题

不知道是不是我部署的问题,我用默认参数延时为5的时候,老是出问题,很多时候返回被污染的数据,手动用-o 10 设成10秒之后,基本没任何问题了,但是其实不可能有这么大延时啊,解析很快的,就算是5秒也应该绰绰有余了,很奇怪。

需求建议

由于某些原因我希望用sniproxy来实现(半)透明代理。
sniproxy运行在VPS上,局域网里某台机器443端口tunnel到sniproxy上。
希望能实现若国内DNS的解析结果是国外IP/不在ipset里,则返回自定义IP,不需要去跟可信DNS解析。
不知道是否方便实现?

OpenWRT 上编译错误

root@OpenWrt:~/chinadns-ng# make gcc -std=c99 -Wall -Wextra -O3 -c chinadns.c -o chinadns.o chinadns.c: In function 'parse_command_args': chinadns.c:210:42: error: 'PATH_MAX' undeclared (first use in this function) if (strlen(optarg) + 1 > PATH_MAX) { ^ chinadns.c:210:42: note: each undeclared identifier is reported only once for each function it appears in make: *** [Makefile:23: chinadns.o] Error 1

chinadns.c 里加了 #include <linux/limits.h> 就通过了

功能请求:支持 EDNS Client Subnet (ECS)

用过一些支持 EDNS 的工具,可以把 IP 地址传递给 DNS,以获得距离用户位置更近、精度更高的解析效果。

希望能添加这两个选项:

--china-dns-subnet <subnet>    # 向国内 DNS 请求时所附带的信息
--trust-dns-subnet <subnet>    # 向可信 DNS 请求时所附带的信息

它们的值可以为:

# China DNS
--china-dns-subnet 203.208.39.216
--china-dns-subnet 203.208.39.216/32
--china-dns-subnet 203.208.39.0/24
# Trust DNS
--trust-dns-subnet 172.217.11.78
--trust-dns-subnet 172.217.11.78/32
--trust-dns-subnet 172.217.11.0/24
  • 当这两个参数为空时,关闭 EDNS 功能,逻辑和目前的版本一样。
  • 这两个参数可以被独立使用,即当 --china-dns-subnet 被指定,--trust-dns-subnet 不指定,则只向国内 DNS 使用 EDNS, 反之亦然。

这样就能得到距离自己实际位置最近的结果,和距离自己 VPS 最近的结果了。

参考

  1. https://tools.ietf.org/html/rfc7871
  2. https://en.wikipedia.org/wiki/EDNS_Client_Subnet

feature request:白名单域名支持

首先,chinadns-ng很好用,在我的使用情形下,域名能得到正确的解析,并且有相当好的cdn效果。很喜欢-g, --gfwlist-file功能,但是在使用中遇到一些问题:

1. -g模式下:

运行命令chinadns-ng -l 7913 -t 127.0.0.1#1055 -g /path/to/gfwlist.txt
设置详情:其中,国内DNS默认114DNS,国外DNS127.0.0.1#1055是我的dns2socks上游,通过ss-local转发到vps进行远程解析,无污染可信任,gfwlist.txt来自本项目,chnroute从ipip源生成。
问题描述:此情况下,一些希望解析到国内IP的域名,被解析到了国外,比如clientservices.googleapis.com,查了下gfwlist.txt,应该是gfwlist.txt里收录了googleapis.com原因导致(链接)。 虽然谷歌在大陆关闭了搜索等业务,但是还是有很多服务是在国内的,找到dnsmasq-china-list项目整理了一份列表:google.china.conf,这里的域名应该用国内DNS解析,以达到国内cdn的效果。
我简单写了个脚本,在-g模式下对google.china.conf进行了DNS查询,结果如下:

1	203.208.40.88	mainland_ip!	265.com
2	--------------	-------------	2mdn.net
3	172.217.24.66	overseas_ip!	adservice.google.com
4	203.208.40.103	mainland_ip!	app-measurement.com
5	203.208.41.119	mainland_ip!	beacons.gcp.gvt2.com
6	203.208.41.111	mainland_ip!	beacons.gvt2.com
7	203.208.41.127	mainland_ip!	beacons3.gvt2.com
8	216.58.220.194	overseas_ip!	c.admob.com
9	--------------	-------------	c.android.clients.google.com
10	172.217.25.14	overseas_ip!	cache.pack.google.com
11	216.58.200.3	overseas_ip!	cdn.ampproject.org
12	216.58.221.227	overseas_ip!	checkin.gstatic.com
13	203.208.41.40	mainland_ip!	clickserve.dartsearch.net
14	172.217.24.195	overseas_ip!	clientservices.googleapis.com
15	172.217.31.227	overseas_ip!	connectivitycheck.gstatic.com
16	172.217.25.3	overseas_ip!	crl.pki.goog
17	172.217.24.67	overseas_ip!	csi.gstatic.com
18	172.217.24.78	overseas_ip!	dl.google.com
19	172.217.161.174	overseas_ip!	dl.l.google.com
20	216.58.221.238	overseas_ip!	doubleclick.net
21	172.217.31.234	overseas_ip!	fonts.googleapis.com
22	216.58.220.195	overseas_ip!	fonts.gstatic.com
23	172.217.161.132	overseas_ip!	google-analytics.com
24	203.208.41.121	mainland_ip!	googleadservices.com
25	172.217.161.164	overseas_ip!	googleanalytics.com
26	216.58.199.4	overseas_ip!	googlesyndication.com
27	203.208.41.94	mainland_ip!	googletagmanager.com
28	--------------	-------------	googletagservices.com
29	203.208.40.94	mainland_ip!	gtm.oasisfeng.com
30	172.217.24.42	overseas_ip!	imasdk.googleapis.com
31	172.217.163.238	overseas_ip!	kh.google.com
32	172.217.161.142	overseas_ip!	khm.google.com
33	172.217.24.206	overseas_ip!	khm.googleapis.com
34	172.217.161.142	overseas_ip!	khm0.google.com
35	172.217.163.238	overseas_ip!	khm0.googleapis.com
36	172.217.161.142	overseas_ip!	khm1.google.com
37	172.217.161.174	overseas_ip!	khm1.googleapis.com
38	172.217.161.142	overseas_ip!	khm2.google.com
39	216.58.200.78	overseas_ip!	khm2.googleapis.com
40	172.217.161.142	overseas_ip!	khm3.google.com
41	216.58.220.206	overseas_ip!	khm3.googleapis.com
42	172.217.24.78	overseas_ip!	khmdb.google.com
43	216.58.199.14	overseas_ip!	khmdb.googleapis.com
44	64.233.189.100	overseas_ip!	media.admob.com
45	216.58.221.227	overseas_ip!	ocsp.pki.goog
46	172.217.31.225	overseas_ip!	pagead-googlehosted.l.google.com
47	203.208.40.87	mainland_ip!	recaptcha.net
48	216.58.199.110	overseas_ip!	redirector.gvt1.com
49	216.58.200.14	overseas_ip!	safebrowsing-cache.google.com
50	172.217.31.234	overseas_ip!	safebrowsing.googleapis.com
51	203.208.41.88	mainland_ip!	settings.crashlytics.com
52	172.217.161.136	overseas_ip!	ssl-google-analytics.l.google.com
53	216.58.197.99	overseas_ip!	ssl.gstatic.com
54	216.58.199.4	overseas_ip!	toolbarqueries.google.com
55	216.58.221.227	overseas_ip!	tools.google.com
56	216.58.221.227	overseas_ip!	tools.l.google.com
57	216.58.197.106	overseas_ip!	translate.googleapis.com
58	216.58.200.3	overseas_ip!	update.googleapis.com
59	203.208.40.94	mainland_ip!	www-googletagmanager.l.google.com
60	172.217.161.131	overseas_ip!	www.gstatic.com

------------------------------------------------------------------------
总共尝试了60个域名,耗时11秒
57个域名得到了解析,3个域名解析失败!
解析到大陆的12个,解析到海外的45个
------------------------------------------------------------------------

结果是很多域名都被解析到了国外,原因当然是因为这些域名和gfwlist的匹配

2. 非-g模式下:

运行命令chinadns-ng -l 7913 -t 127.0.0.1#1055
设置详情:同上,去除-g选项

1	203.208.40.88	mainland_ip!	265.com
2	--------------	-------------	2mdn.net
3	203.208.41.90	mainland_ip!	adservice.google.com
4	203.208.40.100	mainland_ip!	app-measurement.com
5	203.208.41.88	mainland_ip!	beacons.gcp.gvt2.com
6	203.208.40.120	mainland_ip!	beacons.gvt2.com
7	203.208.41.120	mainland_ip!	beacons3.gvt2.com
8	203.208.41.122	mainland_ip!	c.admob.com
9	--------------	-------------	c.android.clients.google.com
10	203.208.40.98	mainland_ip!	cache.pack.google.com
11	203.208.41.63	mainland_ip!	cdn.ampproject.org
12	203.208.40.119	mainland_ip!	checkin.gstatic.com
13	203.208.41.37	mainland_ip!	clickserve.dartsearch.net
14	203.208.41.127	mainland_ip!	clientservices.googleapis.com
15	203.208.41.88	mainland_ip!	connectivitycheck.gstatic.com
16	203.208.40.127	mainland_ip!	crl.pki.goog
17	203.208.41.87	mainland_ip!	csi.gstatic.com
18	203.208.41.66	mainland_ip!	dl.google.com
19	203.208.41.78	mainland_ip!	dl.l.google.com
20	216.58.221.238	overseas_ip!	doubleclick.net
21	203.208.41.98	mainland_ip!	fonts.googleapis.com
22	203.208.40.111	mainland_ip!	fonts.gstatic.com
23	172.217.161.132	overseas_ip!	google-analytics.com
24	203.208.41.122	mainland_ip!	googleadservices.com
25	172.217.161.164	overseas_ip!	googleanalytics.com
26	216.58.199.4	overseas_ip!	googlesyndication.com
27	203.208.41.94	mainland_ip!	googletagmanager.com
28	--------------	-------------	googletagservices.com
29	203.208.40.94	mainland_ip!	gtm.oasisfeng.com
30	203.208.40.98	mainland_ip!	imasdk.googleapis.com
31	203.208.41.99	mainland_ip!	kh.google.com
32	203.208.40.71	mainland_ip!	khm.google.com
33	203.208.40.35	mainland_ip!	khm.googleapis.com
34	203.208.40.66	mainland_ip!	khm0.google.com
35	203.208.40.110	mainland_ip!	khm0.googleapis.com
36	203.208.40.72	mainland_ip!	khm1.google.com
37	203.208.41.37	mainland_ip!	khm1.googleapis.com
38	203.208.40.64	mainland_ip!	khm2.google.com
39	203.208.41.40	mainland_ip!	khm2.googleapis.com
40	203.208.40.71	mainland_ip!	khm3.google.com
41	203.208.40.35	mainland_ip!	khm3.googleapis.com
42	--------------	-------------	khmdb.google.com
43	203.208.41.78	mainland_ip!	khmdb.googleapis.com
44	64.233.189.139	overseas_ip!	media.admob.com
45	203.208.41.119	mainland_ip!	ocsp.pki.goog
46	203.208.40.107	mainland_ip!	pagead-googlehosted.l.google.com
47	203.208.40.88	mainland_ip!	recaptcha.net
48	203.208.40.41	mainland_ip!	redirector.gvt1.com
49	203.208.40.46	mainland_ip!	safebrowsing-cache.google.com
50	203.208.41.71	mainland_ip!	safebrowsing.googleapis.com
51	203.208.41.87	mainland_ip!	settings.crashlytics.com
52	203.208.41.94	mainland_ip!	ssl-google-analytics.l.google.com
53	203.208.40.56	mainland_ip!	ssl.gstatic.com
54	203.208.41.83	mainland_ip!	toolbarqueries.google.com
55	203.208.40.87	mainland_ip!	tools.google.com
56	203.208.40.79	mainland_ip!	tools.l.google.com
57	203.208.40.35	mainland_ip!	translate.googleapis.com
58	203.208.40.63	mainland_ip!	update.googleapis.com
59	203.208.40.94	mainland_ip!	www-googletagmanager.l.google.com
60	203.208.40.47	mainland_ip!	www.gstatic.com

------------------------------------------------------------------------
总共尝试了60个域名,耗时13秒
56个域名得到了解析,4个域名解析失败!
解析到大陆的51个,解析到海外的5个
------------------------------------------------------------------------

结果更多的域名得到了国内解析,不过还不能达到完美,还有5个地址被解析到国外。

3. 域名白名单功能 feature request

  • 请作者考虑是否可以添加-m, --mainland-file 功能,起域名白名单功能,-m里指定的域名强制使用国内DNS解析,并且优先级高于-g,这样在-g + -m模式下,诸如clientservices.googleapis.com这样的域名就不会解析到国外去了。
  • 另外,dnsmasq-china-list项目项目里,还有整理超过6万条使用国内DNS解析加速的域名列表:accelerated-domains.china.conf,如果有域名白名单功能,那么这份列表就能能用chinadns-ng了,得益于chinadns-ng高效的hash查询方式,运行起来应该没有问题。如果使用遍历查询的dnsmasq来实现,查询速度大大折扣不说,cpu占用率还超高。

-4, --ipset-name4 <ipv4-setname> 这个参数不使用也是默认在用吗?

请教作者

-4, --ipset-name4 ipset ipv4 set name, default: chnroute
说明文档中说该参数默认是 chnroute, 如果我在命令行中不使用-4, 程序也是默认使用chnroute的吗? 还是说命令行中没有-4 就不使用ipset了? 只是在用-4 不指定时默认chnroute?

我想问的意思是是不是不管命令行有没有-4的参数, 这个ipset都是起作用的?

抢答模式感觉有问题

启动脚本:chinadns-ng -b 127.0.0.1 -l 6333 -c 114.114.114.114 -t 8.8.8.9#535 -v
然后用 nslookup www.baidu.com 127.0.0.1#6333

可以明显感觉到解析域名要卡两秒钟。
按抢答模式的理解是,即使可信DNS配置不正确或各种原因连不上,
收到国内DNS响应并且是国内IP,就应该返回解析结果了。

卡两秒的感觉是在等待可信DNS。

[ipset_addr4_is_exists] received an error code from kernel: (-1)

Hi, 我遇到了一些问题,按照readme的提示,安装完简单测试的时候会出现下面的错误提示

2020-01-03 23:52:38 ERR: [ipset_addr4_is_exists] received an error code from kernel: (-1) Operation not permitted
2020-01-03 23:52:52 ERR: [ipset_addr6_is_exists] received an error code from kernel: (-1) Operation not permitted

启动程序的命令
chinadns-ng -l 1314 -t 8.8.8.8#53 -g ~/Downloads/chinadns-ng-master/gfwlist.txt
测试:
dig @127.0.0.1 -p1314 www.google.com
测试结果:

; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> @127.0.0.1 -p1314 www.google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63019
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.google.com.			IN	A

;; ANSWER SECTION:
www.google.com.		148	IN	A	172.217.160.68

;; Query time: 69 msec
;; SERVER: 127.0.0.1#1314(127.0.0.1)
;; WHEN: Fri Jan 03 23:52:38 HKT 2020
;; MSG SIZE  rcvd: 59

也测了百度,测试结果好像没什么问题,但是控制台那里每发出一次查询就会出现上边的错误提示,
希望有空帮忙看看,不胜感激

alpine编译报错

你好,我在使用alpine编译时报错,错误信息如下:

alpine:~/chinadns-ng# make
gcc -std=c99 -Wall -Wextra -O3 -c chinadns.c -o chinadns.o
In file included from chinadns.h:6,
                 from chinadns.c:2:
netutils.h:5:10: fatal error: time.h: No such file or directory
 #include <time.h>
          ^~~~~~~~
compilation terminated.
make: *** [Makefile:23: chinadns.o] Error 1
alpine:~/chinadns-ng# uname -a
Linux alpine 5.4.5-0-lts

希望可以解决一下。

googleapis.cn的域名解析为污染地址

log dump
query [services.googleapis.cn] from 127.0.0.1#53351
[handle_remote_packet] reply [services.googleapis.cn] from 114.114.114.114#53, result: accept
[handle_remote_packet] reply [services.googleapis.cn] from 127.0.0.1#5300, result: ignore

googleapis.cn解析发送给了国内DNS。

root@OpenWrt:~/chinadns-ng-latest# dig services.googleapis.cn @127.0.0.1 -p 5300

; <<>> DiG 9.14.8 <<>> services.googleapis.cn @127.0.0.1 -p 5300
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 41291
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;services.googleapis.cn. IN A

;; ANSWER SECTION:
services.googleapis.cn. 299 IN A 74.125.200.94

127.0.0.1#5300为可信DNS,因为cn后缀没有转发给它,所以我还还要在dnsmasq中单独添加一条/googleapis.cn/127.0.0.1#5300

Windows 10 WSL问题,Protocol not supported

如下,ipset出现了奇怪的错误,反而是老版chinadns能用,但是它又不能过滤AAAA的查询。

:~/chinadns-ng$ sudo ./chinadns-ng -c 114.114.114.114,223.5.5.5 -t 208.67.222.222#5353,208.67.220.
220#5353
2020-05-19 11:20:26 INF: [main] local listen addr: 127.0.0.1#65353
2020-05-19 11:20:26 INF: [main] chinadns server#1: 114.114.114.114#53
2020-05-19 11:20:26 INF: [main] chinadns server#2: 223.5.5.5#53
2020-05-19 11:20:26 INF: [main] trustdns server#1: 208.67.222.222#5353
2020-05-19 11:20:26 INF: [main] trustdns server#2: 208.67.220.220#5353
2020-05-19 11:20:26 INF: [main] ipset ip4 setname: chnroute
2020-05-19 11:20:26 INF: [main] ipset ip6 setname: chnroute6
2020-05-19 11:20:26 INF: [main] dns query timeout: 5 seconds
2020-05-19 11:20:26 INF: [main] filter reply without ip addr
2020-05-19 11:20:26 INF: [main] cur judgment mode: fast mode
2020-05-19 11:20:26 ERR: [ipset_create_nlsocket] failed to create netlink socket: (93) Protocol not supported

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.