关于dns泄露的那些事情 路由器 mosdns分流 clash

# dns 为什么会被泄露

因为默认情况下家庭网络的dns都是走 明文 udp的53端口。但是即便是配置了走doh/dot也会泄露。

# dns 泄露后有什么不好的

如果 你对运营商或者国内dns 发起了一个 查询某一个域名dns的请求,随后你又加密连接到了一个境外ip并传输了大流量数据。 你在干什么 就非常显而易见了。 在这个红色恐怖充斥的2023年,这是一个非常作死的事情。

# 什么是dns污染 阻断和劫持

简单的说,就是 你请求了某一个公共dns,但返回的数据是错误的,或者半路被篡改掉了。
返回错误数据 是因为国内政策要求,所以公共dns服务器对某一些域名进行了阻断,一般会返回一个本地局域网i或者随意一个国外ip。所以需要使用国外公共dns来处理一些域名的解析。 数据被篡改,只有你在明文进行dns请求的时候,返回数据被运营商或者某部门或者恶意第四方篡改掉,这种情况仅限明文dns请求的情况下。所以有了doh和dot的加密dns请求。

# 什么是doh和dot

dns over tls 和 dns over https 就是用用tcp tls 或者 https 加密你的 dns请求。
一般浏览器和操作系统 都支持。

# doh和dot可以避免污染 阻断 劫持和 泄露吗

并不能完全避免。 doh和dot是可以避免dns解析记录被中间人篡改和窥探的,但是使用国内公共dns无法解决政策原因导致的污染。
如果你 doh/dot到 国内的 doh/dot的dns服务,那么只是你上游网络(宽带运营商)无法得知你的dns请求了而已。但是对应的国内dns服务商依旧可以得知。

你直接使用国外加密dns,理论去是可以的避免所有问题,但是国外加密dns有三个问题:

  • 国内直接访问速度太慢 严重影响使用
  • 国外加密dns都已经被干扰并且不定期阻断和重定向 无法正常稳定使用
  • 有一些国内网站基于dns做了分地区或者一些优化,例如你访问某一个网站用的国外的dns可能会被重定向到对方的国际站点。

# 怎么完美解决

三句话:

  • 使用clash代理国外主流doh/dot的dns服务,一般情况下所有的第三方clash转换规则包括机场自带的规则 以及常见的路由器分流配置 都可以识别到这部分流量 都会帮你代理出去。
  • 国内域名到 国内的doh/dot的dns服务商,gfw清单中的域名到国外主流doh/dot的dns服务商
  • 如果非gfw清单中域名,但是返回了国外ip,那么到国外主流doh/dot上再次查询一次
    这样就完美规避了上述所有问题。

# 怎么实现

mosdns分流搞定一切。如果有特殊需求,加辅助dns的上游,例如AdGuardHome和自建doh。

# 怎么优雅实现

# 原理

使用mosdns,mosdns 判断是gfw域名直接请求 google和cf或者你的自建doh。否则请求国内doh/dot 如果请求了国内dns但是返回了一个国外ip,那么再次请求 google和cf或者你的自建doh 确认修正一次。 国内doh/dot 我们也可以作为AdGuardHome的上游,顺带去广告或者处理一下别的情况。

# 最佳方案(新手推荐)

mosdns 作为网内的主dns,或者路由器的上游主dns。 两个 AdGuardHome 分别处理 境外网站和国内网站,这两个AdGuardHome作为mosdns的上游dns. 这样的好处是 AdGuardHome有较为直观的webui管理界面,并顺带处理广告问题。 另外一个猴版方案 是 AdGuardHome作为主dns, mosdns作为 AdGuardHome 的上游,一样可以实现。这样省一个AdGuardHome,但是有特殊要求的情况下不适用。

# 单mosdns方案(老手推荐)

也是我目前使用的方案,优点是更加灵活性能也比较好。
https://dev.leiyanhui.com/route/mosdns-all-in-one

# 为什么不直接用clash自带的dns劫持

主要是自带的clash dns规则较为复杂,一不消息就会泄露dns。

# 这么复杂不会拖累速度吗

不会,因为mosdns速度非常快,而且自己有良好的缓存机制。 我们使用运营商的dns他也会逐级请求上层dns,只是不需要我们配置而已。

# 准备:

1、mosdns和对应的geoip.dat,geosite.dat
2、(可选)cfwork自建一个doh
3、(可选)AdGuardHome顺带去广告

# mosdns

建议docker安装 推荐 https://hub.docker.com/r/601096721/mosdns

# cfwork自建doh

因为cf和google包括其他知名国外的dns,无论是否doh/dot都被干扰了,非常不稳定甚至某些时候无法使用。 而有时候我们需要直连查询。
推荐index.js https://github.com/tina-hello/doh-cf-workers
记得绑定一个自己的域名,因为cfwork默认分配的域名本身是被墙的状态,那么你自己搭建的反向代理也就无意义了。
cfwork每个账户每天有免费10万次查询额度,自己用足够了。上面的代码中没有包含路由功能,你可以自己配置一下,防止被盗用。
这个方式自建doh 速度肯定是不好的,因为我们一般会在clash或者软路由的分流规则直连这个地址,本身速度就不快,而且我们的自建doh实际是反向代理了一次cf的doh,所以速度方面就不用想会多快了。这只是在我们无法使用代理,并且需要正确dns的时候最后的手段。

因为cfwork只支持http/https请求,所以不能搭建dot只能doh,理论上doh因为基于http协议需要携带http头部信息,数据包大一些,速度会慢一点,实际上两者使用体验上并无差别 上面的脚本可以适当的修改后缀,或者在cf面板中添加规则防止被别人白嫖。js语法很简单,自己看注释修改一下即可。

# AdGuardHome

为什么要AdGuardHome ? 除了去广告之外 AdGuardHome的并发dns查询可以加快访问速度。另外ddns的域名,我们可以直接指向内网ip,这样在我们ip变化后但是ddns因为受到ttl的限制不能马上刷新的情况下不会影响内网使用。
AdGuardHome的配置较为简单 就不用多说了。dns里面加一堆国内的dot运营商即可,参考下面的上游 DNS 服务器 分别配置的阿里云 360和腾讯dnspod的dot

1
2
3
4
5
6
tls://223.5.5.5
tls://223.6.6.6
tls://101.226.4.6
tls://123.125.81.6
tls://1.12.12.12
tls://120.53.53.53

建议全部直接用ip走dot或doh 而不是用域名 ,这样可以避免Bootstrap dns配置错误导致的问题。 你可以先用https://ip地址 访问对应的dns如果没有提示证书错误 那么他就是支持ip直连doh,那也可以ip走dot。也可以查询对应dns服务器的文档。

# 在爱快和ros openwrt下如何配置

建议 mosdns和AdGuardHome都不要劫持本地的dns.而在 路由器设置吧mosdns的内网ip或者dockerip作为路由的首选dns。
爱快3.7.7 体验版本已经支持 dns的第三方代理模式 配置主dns(mosdns)和三个备用dns(国内公共dns),虽然目前测试存在问题,但是后续版本应该会修复。

# openclash里面怎么配置

直接吧clash的dns 所有dns全部替换为mosdns

# mosdns配置文件

mosdns 相当于是我们的核心dns了。我目前的配置如下。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# 日志
log:
  level: error #日志级别。可选 "debug" "info" "warn" "error"。默认 "info"
  file: ""
  production: false

# api:
#   http: 127.0.0.1:8888

# include: []

plugins:
  # forward 可以将所有的 upstream 写一起,sequence 里按需调用 "$插件tag 上游tag..."。看下一条注释。
  - tag: cache
    type: cache
    args:
      size: 1024
      lazy_cache_ttl: 0

 # 自定义Hosts
  - tag: hosts
    type: hosts
    args:
      files:
        - "./hosts"

  - tag: upstreams
    type: forward
    args:
      upstreams:
        - tag: adguardhome
          addr: udp://10.10.1.3 #上游是境内dns
          enable_pipeline: true
          idle_timeout: 30
          insecure_skip_verify: true
        - tag: adguardhome2 #上游是境外dns
          addr: udp://10.10.1.5
          enable_pipeline: true
          idle_timeout: 30
          insecure_skip_verify: true
        # 后面的作为备用暂时不使用,这里直接使用两个adg作为上游
        - tag: cf_worker
          addr: https://xxxxx  #自己在cfwork搭建的doh
          enable_pipeline: true
          idle_timeout: 50
          insecure_skip_verify: true
        - tag: cloudflare_tls
          addr: tls://1.0.0.1
          enable_pipeline: true
          idle_timeout: 50
          insecure_skip_verify: true
        - tag: google_tls
          addr: tls://8.8.8.8
          enable_pipeline: true
          idle_timeout: 50
          insecure_skip_verify: true
        - tag: dnspod
          addr: tls://1.12.12.12
          enable_pipeline: true
          idle_timeout: 30
          insecure_skip_verify: true
        - tag: aliyun
          addr: tls://dns.alidns.com
          bootstrap: 223.5.5.5
          enable_pipeline: true
          idle_timeout: 30
          insecure_skip_verify: true

  # cn域名的规则
  - tag: geosite_cn_seq
    type: sequence
    args:
      - exec: $upstreams adguardhome
  # 替换 cloudflare 的 IP 成自己的最优 IP 的规则
  # 没找到txt,不用这条
  # - tag: fastest_cf
  #   type: sequence
  #   args:
  #     - matches: resp_ip &./geoip_cloudflare.txt # 是不是 cloudflare 的 IP
  #       exec: black_hole 1.1.1.1 ::1    # 用 black_hole 强制换成这些 IP 的应答。注意,这里的 IP 只是示例不是 cloudflare 的。

  # 远程域名的规则
  - tag: remote_seq
    type: sequence
    args:
      - exec: prefer_ipv4       # 希望 remote 优先 ipv4.
      #- exec: $upstreams adguardhome2 cf_worker cloudflare_tls google_tls
      - exec: $upstreams adguardhome2 
      # - exec: jump fastest_cf # jump 相对于把 fastest_cf 的规则链插到此处。

  # 这个 sequence 转发请求到本地,返回只包含 cn IP 的应答。(过滤掉非 cn 的应答)
  - tag: local_must_has_cn
    type: sequence
    args:
      #- exec: $upstreams adguardhome dnspod aliyun
      - exec: $upstreams adguardhome
      - matches: "!resp_ip &./geoip_cn.txt"
        exec: drop_resp     # 如果应答里没有 cn IP,丢掉。

  # 利用 fallback 机制按 IP 分流。如果 local 服务器返回了 cn 的应答就接受,非 cn 的应答会被丢弃,使用 remote 服务器的应答。
  - tag: fallback_ip
    type: fallback
    args:
      primary: local_must_has_cn  # 空应答(本地服务器返回了非cn IP然后应答被丢弃了)触发 fallback。
      secondary: remote_seq       # fallback 后就会使用 remote 的应答。
      always_standby: true


  ##############################
  # 配置主 sequence 规则,作为服务器的入口。
  - tag: main
    type: sequence
    args:
      - exec: $hosts
      - exec: query_summary entry
      #- matches:
      #    - qname &./geosite_category-ads-all.txt #自带的广告过滤
      #  exec: reject 0
      - exec: $cache
      - {matches: has_resp, exec: accept}   # cache/hosts 等插件不再“命中记录自动跳过后续插件”,需用户自行判断是否有应答。
        # 方便需要 ipset/nftables 用户定制流程。
      # yaml 支持这种简写。
      - matches:
          - qname &./geosite_cn.txt # cn 域名
        exec: goto geosite_cn_seq          # goto 到 local 规则,不在执行后续规则。
      - matches:
          - qname &./geosite_geolocation-!cn.txt # 非 cn 域名
        exec: goto remote_seq          # goto 到 remote 规则。

      - exec: $fallback_ip            # 剩余域名用 ip 分流。

  ####  动态路由 + cache。
  # 新版的cache只会将命中的应答放在请求,不再自动终止后续规则。所以需要动态路由时,可以将
  # sequence 的转发操作用 !has_resp 短路。做到每次请求都能刷新路由表。
#  - tag: s1
#    type: sequence
#    args:
#      - exec: $cache
#      - matches:
#          - "!has_resp" # 上一步cache命中缓存有应答了就不转发了。
#        exec: $forward_remote
#      - exec: ipset ...... # ipset 每次请求都能执行。
  #####


  ####### mark 使用示例
  # mark 在 exec 内是打标。在 matches 内是匹配。
  # mark 当作开关的示例。
#  - tag: s1
#    type: sequence
#    args:
#      - exec: mark 1 2  # 先打标。
#      - matches:
#          - mark 1
#        exec: $cache  # 有 mark 1 缓存会生效
#      - matches:
#          - mark 2
#        exec: ecs 1.2.3.4 # 有 mark 2 请求会被附加 ecs
      # ...
      # - matches:
      #     - mark 3
      #   exec:  jump fastest_cf # 没 mark 3 不会替换 cloudflare ip。


  #### 最后配置 server........略
  - tag: server
    type: udp_server # 目前有 udp/tcp/http_server
    args:
      entry: main
      listen: 0.0.0.0:53
  - tag: server_tcp
    type: tcp_server
    args:
      entry: main
      listen: 0.0.0.0:53
  - tag: "server_http"
    type: "http_server"
    args:
      entries:                 # []extry
        - path: /dns-query     # 本路径执行   
          exec: main # 可执行插件的 tag。  
      src_ip_header: "X-Forwarded-For"  # 从 HTTP 头获取用户 IP。
      listen: 0.0.0.0:80  # 监听地址。
      cert: "" # 留空 cert 和 key 后会禁用 TLS。 这里没有配置证书,外网使用我这里另外有acme和nginx处理https
      key: "" 
      idle_timeout: 10       # 空连接超时。单位秒。默认 30。

#######

# 手动更新mosdns的分流数据

601096721/mosdns的docker镜像没有添加计划任务,只有在更新镜像的时候 才会更新。 可以在容器内部执行下面的命令更新数据库文件,也可以在容器内部安装crond 定时更新。

1
2
3
4
5
6
7
8
wget https://raw.githubusercontent.com/IceCodeNew/4Share/master/geoip_china/china_ip_list.txt -O /geoip_cn.txt
wget https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/reject-list.txt -O /geosite_category-ads-all.txt
wget https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/proxy-list.txt -O /geosite_geolocation-!cn.txt
wget https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/direct-list.txt -O /geosite_cn.txt
cp -u /geoip_cn.txt /etc/mosdns/geoip_cn.txt
cp -u /geosite_category-ads-all.txt /etc/mosdns/geosite_category-ads-all.txt
cp -u /geosite_geolocation-!cn.txt /etc/mosdns/geosite_geolocation-!cn.txt
cp -u /geosite_cn.txt /etc/mosdns/geosite_cn.txt

# 补充

adguardhome 本身可以利用规则的方式实现分流协议。有第三方作者的规则,实际测试效果不好,主要是速度不理想。
adguardhome 搭建自己的私有doh需要强制证书,略微不方便。而mosdns 性能更好,且可以不使用证书搭建 dns over http(非https),而后用nginx+acme.sh统一反代到https。 但是mosdns没有简单方便的webui管理工具,去广告功能也没有adguardhome那么方便。所以如果不是内存特别紧张的情况下,mosdns+adguardhome依旧是新手的最佳方案。
adguardhome 本身大概需要 40-80M内存,我在使用mosdns+双adguardhome的时候,大概需要消耗150-180M内存。
如果对可视化管理没有需求,建议用单mosdns方案 https://dev.leiyanhui.com/route/mosdns-all-in-one

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计