DNS零泄露,零污染之终级方案

1-前言

dns的泄露会导致运营商或者防火墙知道你在访问google、youtube、facebook等网站,说白了就是知道你在科学上网,另外像奈飞这种对地区敏感的应用可能会通过dns来判断你的实际所在地,如果存在泄露将会被判定为使用了代理工具,无法使用他们的服务

2-方案

2.0 本案环境准备

方案环境可依据个人情况调整,一些站友私信希望给出相应的教程,故增加环境相应教程,仅供参考,有需要自取即可

A-01 PVE安装指南
A01-PVE 详细安装手册
A02-PVE_Openwrt 安装指南
OpenWrt是一个开源的路由器固件,OpenWrt为用户提供了一种在路由器上运行自定义固件的选择,以满足个性化和高级网络需求。
《DNS零泄露~~》对应Openwrt 版本调整建议
💡DNS双零方案完美避免DNS污染,但当时推荐的高大全版本经3个月试用后,确认存在BUG,请选择其他Openwrt版本 ,本人推荐版本详情见下(也同时含有AD,MOSDNS,Clash,但取消了Dokcer和Softether VPN)DNS零泄露,零污染之终级方案DNS零泄露,零污染之终级方案- 与看油管,BiliBili卡出翔或隔三差五的断流说再见 与DNS泄露,污染甚至封节点IP说再见。知识就是力量tgssr 01.原文使用的版本(gdq): OpenWrt R22.11.11 GDQ Autumn[2022] Compiled by eSir / LuCI Master (git-22.330.64765-00290b6) 使用3个月后遇到的问题: 在折腾openclash过程中,经常会修改设置并保存应用,时间久了后,在上图中的空闲空间趋于“0”,同时后续保存会越来越慢,直至无法保存。 02.建议解决方案: 1.已经安装了此版本的GDQ版本:建议不使用的话尽早删除其中的docker组件,否则只能是扩容(

2.1 效果

Openwrt下:Adguard+MosDns+openclash
讲方案前先看效果-2160P下油管无卡顿60K Kbps

2.2 方案解决的痛点问题

  1. 通过路由,全家网络均达到本案效果,无需设置各种移动端应用,即所谓:受累你一个,幸福一家人。
  2. 再也不怕辛辛苦苦搭建的节点因DNS泄漏被侦测甚至至封号了。
  3. 再也不怕因DNS污染而导致访问网络变慢,看国外视频卡出翔或隔三差五的断流了。
  4. 一个Openwrt全搞定,推荐使用Esir大佬的高大全固件,笔者使用的是:openwrt-SPP-v2[2023]-x86-64-generic-squashfs-uefi(建议使用精简版,原因见上:环境准备链接),涵盖上述三个软件,如果你是OP其他版本,先装上这三个软件先。(相关软件均可本站或官网下载)
  5. 保留了 AdGuardHome 的各种功能

2.3 方案原理

基于 DNS 的流量分流,国内流量绕过 Clash 核心用 Fake-IP 模式来解决 DNS 污染的问题,但限制 Fake-IP 的范围,不需要代理的域名仍返回正常 IP,不用再费心找无污染的 DNS 服务器,使用运营商提供的 DNS 也没问题

  1. 因为彻底解决了 DNS 污染,可以放心缓存 DNS 请求结果,开启 AdGuardHome 的乐观缓存后,DNS 平均处理时间降到 3ms
  2. 可以通过 AdGuardHome 的 Web 管理页面轻松切换内网设备是否走代理
  3. 经过 DNS 分流后,所有需要代理的域名都分配到了 Fake IP,无需代理的域名都是由运营商 DNS 返回的最优结果。Clash 的 DNS 在 Fake IP 模式下可以无需请求直接返回结果,所以整体的 DNS 响应速度非常快。在处理 Fake IP 的流量时,Clash 会把 hostname 发送到远端进行 DNS 解析,也就自然不存在 DNS 污染的问题了。
  4. 通过mosdns进行流量代理分流后,国内部分交Dnsmasq处理,国外部分交Openclash处理,由于Fake-IP的存在,我们只需要一条防火墙规则,把所有目的地址是 Fake IP 的流量都转发到 Clash 核心,所有其他流量都不经转发正常通行。由于只有 Fake IP 流量会经过代理,那么直连流量自然就不会经过代理了,这样就不用再担心 BT/PT 跑代理的流量了。
  5. 解决个别 IP 的代理问题有的需要代理的 App 是直连 IP,不经过 DNS 域名解析的步骤的,目前我用到的只有一个,就是 telegram。好在 telegram 提供了它所使用的 ip-cidr 列表,我们只需要为这些 IP 单独配置防火墙规则,给它们转发到 Clash 核心。
  6. 基于域名的黑白名单,通过 mosdns 的 query_matcher 功能,可以构建基于域名的黑白名单,保证一些你选择的域名一定通过或不通过 Clash 核心的代理。常见的用途比如:搭建的DDNS服务,Cloudflare的Tunnel服务,自建的VPN服务等等。
  7. AdGuardHome 乐观缓存,Clash 可以在重启过程中对 Fake IP 列表进行保存,运营商 DNS 的返回结果也基本稳定,所以我们可以放心的开启 AdGuardHome 的乐观缓存功能。这时 AdGuardHome 会优先返回已过期的缓存结果然后再自己慢慢去更新缓存内容,可以大大提高内网客户端的 DNS 请求响应速度。

2.4 方案过程

对应的包都安装好:luci-app-adguardhome,luci-app-mosdns,OpenClash。然后我们来一个一个的配置。

2.4.1 OpenClash

插件设置 - 模式设置 - 运行模式: 切换到 Fake-IP(增强)模式

插件设置 - DNS 设置 - 本地 DNS 劫持 选择 禁用
插件设置 - 流量控制 - 绕过中国大陆 IP 取消勾选
插件设置 - 流量控制 - 仅允许内网 开启
插件设置 - IPv6 设置 这页的选项全都关闭就行了
覆写设置 - 常规设置 这里都不用改,只需要记住 DNS 监听,后面配置 mosdns 要用
覆写设置 - DNS 设置 - 自定义上游 DNS 服务器 勾选
覆写设置 - DNS 设置 - 追加上游 DNS 勾选
覆写设置 - DNS 设置 - 追加默认 DNS 勾选
覆写设置 - DNS 设置 - Fake-IP 持久化 勾选

覆写设置 - DNS 设置 页面下方 NameServer,FallBack,Default-NameServer 里的 DNS 服务器全都取消勾选,因为国内访问一般运营商 DNS 都是最快的,也是 CDN 最优化的,而国外部分交给OPENCLASH的代理,所以这部分留空即可。

插件设置 - GEO 数据库订阅 把 GeoIP Dat 和 GeoSite 这两个库的自动更新打开,都选 Loyalsoldier 的版本,这个是用来给 mosdns 用的。
插件设置 - 开发者选项里,我们自定义一下防火墙规则,

在原有内容和EXIT 0 之间增加如下这些行:

en_mode=$(uci -q get openclash.config.en_mode)
proxy_port=$(uci -q get openclash.config.proxy_port)

if [ "$en_mode" == "fake-ip" ]; then
	LOG_OUT "limit route to only fake ips with proxy port $proxy_port"
	iptables -t nat -D openclash -p tcp -j REDIRECT --to-ports $proxy_port
	sleep 1

	LOG_OUT "update telegram ipset"
	/etc/mosdns/rule/geoip2ipset.sh /etc/openclash/GeoIP.dat telegram
	iptables -t nat -A openclash -m set --match-set telegram dst -p tcp -j REDIRECT --to-ports $proxy_port
	sleep 1

	LOG_OUT "update netflix ipset"
	/etc/mosdns/rule/geoip2ipset.sh /etc/openclash/GeoIP.dat netflix
	iptables -t nat -A openclash -m set --match-set netflix dst -p tcp -j REDIRECT --to-ports $proxy_port
	sleep 1
fi

#  停止AdguradHome
LOG_OUT "stop adguardhome"
/etc/init.d/AdGuardHome stop
sleep 1

#  开启AdguradHome
LOG_OUT "start adguardhome"
/etc/init.d/AdGuardHome start
sleep 1

# 停止Mosdns
LOG_OUT "stop mosdns"
/etc/init.d/mosdns stop
sleep 1

# 开启Mosdns
LOG_OUT "start mosdns"
/etc/init.d/mosdns start
sleep 1

# 重载Mosdns
LOG_OUT "reload mosdns"
/etc/init.d/mosdns reload
sleep 1

2.4.2 MosDns

选自定义配置文件,取消 DNS 转发的勾
在 GeoData 数据导出 里配置上我们用到的标签:
GeoSite: cn, apple-cn, category-games@cn
geolocation-!cn, GeoIP: cn

2.4.2.1 自定义配置如下:

Clash DNS 端口要改成你自己在 OpenClash 里的配置(如7874)
LAN IP-CIDR 也要改成你自己的内网配置,这里 mosdns 监听了 5335 端口。

log:
  level: info
  file: "/tmp/mosdns.log"

include: []

plugins:
  # 国内域名
  - tag: geosite_cn
    type: domain_set
    args:
      exps:
        - "lan"
        - "local"
        - "arpa"
      files:
        - "/etc/mosdns/rule/whitelist.txt"
        - "/var/mosdns/geosite_cn.txt"
        #- "/var/mosdns/geosite_apple-cn.txt"
        #- "/var/mosdns/geosite_category-games@cn.txt"
#上述两行需要注销,否则无法启动mosdns
#原因为Geoip和Geosite两个文件UNPACK后无上述两文件。
  # 国内 IP
  - tag: geoip_cn
    type: ip_set
    args:
      files:
        - "/var/mosdns/geoip_cn.txt"

  # 国外域名
  - tag: geosite_no_cn
    type: domain_set
    args:
      files:
        - "/etc/mosdns/rule/greylist.txt"
        - "/var/mosdns/geosite_geolocation-!cn.txt"

  # hosts
  - tag: hosts
    type: hosts
    args:
      files:
        - "/etc/mosdns/rule/hosts.txt"

  # 国内解析
  - tag: local_sequence
    type: sequence
    args:
      - exec: forward 202.101.XXX.XXX 
      #国内解析DNS:填114或当地运管商DNS均可,建议后者,一般解析速度快
      - matches:
        - has_resp
        - resp_ip 192.168.0.3/24 # 局域网IP段
        exec: ttl 1800-0

  # 国外解析
  - tag: remote_sequence
    type: sequence
    args:
      - matches:
        - qtype 28
        exec: reject 0
      - exec: forward 127.127.127.127:7874 
      #openclash 端口,127.X.X.X随便填均可,常用为127.0.0.1
      - exec: ttl 1800-0

  # 有响应终止返回
  - tag: has_resp_sequence
    type: sequence
    args:
      - matches: has_resp
        exec: accept

  # fallback 用本地服务器 sequence
  # 返回非国内 ip 则 drop_resp
  - tag: fallback_local
    type: sequence
    args:
      - exec: $local_sequence
      - matches: "!resp_ip $geoip_cn"
        exec: drop_resp

  # fallback 用远程服务器 sequence
  - tag: fallback
    type: fallback
    args:
      primary: fallback_local
      secondary: remote_sequence
      threshold: 200
      always_standby: true

  # 主要的运行逻辑插件
  # sequence 插件中调用的插件 tag 必须在 sequence 前定义,
  # 否则 sequence 找不到对应插件。
  - tag: main_sequence
    type: sequence
    args:

      # hosts
      - exec: $hosts
      - exec: jump has_resp_sequence

      # drop https query type
      - matches:
        - qtype 65
        exec: reject 3

      # handle local ptr
      - matches:
        - qtype 12
        exec: $local_sequence
      - exec: jump has_resp_sequence

      - matches:
        - qname $geosite_cn
        exec: $local_sequence
      - exec: jump has_resp_sequence

      - matches:
        - qname $geosite_no_cn
        exec: $remote_sequence
      - exec: jump has_resp_sequence

      - exec: $fallback

  - tag: udp_server
    type: udp_server
    args:
      entry: main_sequence
      listen: ":5335" #mosdns监听端口,后续在Adguard中作为上游地址填写。
2.4.2.2 设置IPSET文件

SSH至路由,新建geoip2ipset.sh文件,路径: /etc/mosdns/rule/geoip2ipset.sh
这个脚本可以根据 GeoIP 数据库来生成对应的 ipset。
记得要执行:chmod 777 geoip2ipset.sh 给它赋予可执行权限。

#!/bin/bash

geoipfile="$1"
tag="$2"
tmpdir="/tmp/v2dat"

cd $(cd $(dirname $BASH_SOURCE) && pwd)

mkdir -p "$tmpdir"
filename=$(basename -- "$geoipfile")
filename="${filename%.*}"
filename="$tmpdir/${filename}_$tag.txt"

if [ "$tag" == "telegram" ]; then
    wget --timeout 5 -O "$filename" 'https://core.telegram.org/resources/cidr.txt'
    if [ "$?" != "0" ]; then
         /usr/bin/mosdns v2dat unpack-ip -o "$tmpdir" "$geoipfile:$tag"
    fi
else
    /usr/bin/mosdns v2dat unpack-ip -o "$tmpdir" "$geoipfile:$tag"
fi

if test -f "$filename"; then
    ipset destroy "$tag"
    ipset create "$tag" hash:net
    while read p; do
        if ! grep -q ":" <<< "$p"; then
            ipset add "$tag" "$p"
        fi
    done <"$filename"
else
    echo "$filename missing."
fi

rm -rf "$tmpdir"

2.4.3 Adguard

  1. AdGuardHome 本身监听 53 端口,把 非53 端口留给 dnsmasq,重定向:无
  2. 在 Web 管理页面上,设置 - DNS 设置中,上游 DNS 服务器内只填写一个 mosdns 的地址 127.0.0.1:5335 #mosdns,
    私人反向 DNS 服务器写上 127.0.0.1:端口 #dnsmasq地址。DNS 缓存配置里面,缓存大小看你内存大小填写,乐观缓存勾上。





2.5 收尾工作

最后一步:在Openwrt-网络-防火墙-自定义设置中添加一段规则,重启Firewall后生效。

iptables -t nat -A PREROUTING -d 198.18.0.0/16 -p tcp -j REDIRECT --to-ports 7892

代码意思:将Fake-IP网段的流量(即外网域名)转至Openclash处理,Openclash接收后交节点,由节点直接向真实无污染的外网DNS查询后获得有效访问地址。

通过查看Openclash的yacd面板,若无国内链接仅有国外链接,即代表DNS分流正常,节点工作正常

3-Q&A环节

3.1 Mosdns无法启动如何处理?

SSH至路由后,使用代码运行,此模式有报错,可依此进行处理。
/usr/bin/mosdns start -c /etc/mosdns/config_custom.yaml,笔者遇到的问题就是Geoip和Geosite两个文件UNPACK后无 APPLE-CN等文件,注销行后即可。
遇到数据库无法更新,可输入:/usr/share/mosdns/mosdns.sh geodata,查看失败原因

3.2 Adguard无流量是怎么回事?

笔者也碰到,所以将53端口交Adguard全面接管dnsmasq后,问题解除,DNS分流(mosdns功能)+去广告(adguard功能)功能配合完美。

3.3 openclash无法订阅节点?

由于网络问题,有时openclash会订阅失效(甚至可科学上网环境下也有一定机率失效),此时,可通过可信的第三方线上节点转换器或本地转换器产生链接后导致导入openclash即可。(附上本人自建的在线节点转换,可放心食用,采用先进手段,无法获取节点信息)

3.4 为何openclsh中节点无效,但ssr等其他软件中节点ping值正常?

疑时mosdns数据库未更新所致,但因为无法科学就没法更新,是个死结。笔者的方法是先用ssr正常科学后,完成mosdns升级后切换回此方案即可。

3.5 本案是否支持IPV6

经测试,完美支持IPV6,建议在CLASH环境下,无特殊需求,IPV6最好还是禁用(修正完美的定义:即开启IPV6下clash可正常使用,但分流并不完美)。

3.6 openclash配置文件正常未报错,启动也正常,但查看YACD面板后无链接,即节点无法连通,状态栏内提示国外无法连通,且在日志中提示:“【/tmp/openclash_last_version】下载失败:【curl: (35) ssl_handshake returned - mbedTLS: (-0x7280) SSL - The connection indicated an EOF】”

解决方案:访问,https://sites.ipaddress.com/raw.githubusercontent.com/
将其IP放入HOST文件中,openwrt文件路径为etc/host
185.199.109.133 raw.githubusercontent.com

4-相关软件下载

💡
方案相关软件可至官方下载,以下为笔者整理的本方案相关软体,如有需要可注册后下载。

1.Openwrt对应版本:2024 V1 版本--OpenWrt R24.2.2 SPP V1 [2024] Compiled by eSir。
2.openclash:045.157版本及对应的DEV核心,TUN及META文件,非必须升级,若在方案部暑后出现一些奇怪无解现象,可尝试升级。
3.mosdns:5.31版本+Lcui控制台文件+中文包文件+vdat依赖文件+geoip,geosite文件。