XuLaLa.Tech

首页客户端下载Windows 使用V2Ray 教程SSR 教程Clash 教程

V2Ray接管系统DNS并实现DNS分流

2025.04.21
机场加速器梯子推荐:

优质SS/SSR/Trojan/Xray/V2Ray机场推荐 | IPLC/IEPL专线加速器梯子推荐 | 解锁奈飞Netflix/HBO/Hulu等国外流媒体

为什么要用 DNS 分流

  1. 如果只用国外 DNS,一些国内域名会被解析到国外 CDN 的 IP,访问缓慢。
  2. 如果只用国内 DNS,会有 DNS 污染 的问题。而且和国外 DNS 相比,使用国内 DNS 隐私风险相对较高。

之前所用方案及其痛点

我之前使用 SmartDNS 作为 DNS 服务器,用 dnsmasq-china-list 实现 DNS 分流。

dnsmasq-china-list 这类分流方案的核心是维护一个常用的国内域名列表,当查询列表内域名的 IP 时,DNS 服务器选用国内 DNS 查询,其它情况下,使用国外 DNS 查询,V2Ray 也能这么实现 DNS 分流。V2Ray 有 domain-list-community 这样的官方列表,也有 v2ray-rules-dat 这种第三方路由规则文件加强版。

我日常使用 V2Ray 跨越长城,配置 V2Ray 的路由让 geosite:geolocation-cn 列表里的域名直连。用 dnsmasq-china-list 分流 DNS 的时候,可能会遇到某个域名「国内 DNS 解析出国内 IP 后走代理 / 国外 DNS 解析出国外 IP 后直连」的情况,而我的期望是:对于国内域名,使用国内 DNS 解析并直连,其它的任何情况都使用国外 DNS 解析并通过代理连接。

由此可见,解决方法有以下几种:

  1. 让 DNS 服务器使用 domain-list-community。
  2. 让 V2Ray 使用 dnsmasq-china-list 分流。
  3. 让 V2Ray 和 DNS 服务器都用 v2ray-rules-dat。

本文介绍的是第一种方法:直接把 V2Ray 配置成 DNS 服务器。

V2Ray as a Standalone DNS Server

我最初的想法是单独跑一个 V2Ray 作为 DNS 服务器,所用配置是这样的:

{
"dns": {
"servers": [
// 如果想配置域名 DoH 服务器(例如 https+local://dns.google/dns-query),
// 得另外加个 IP 服务器(例如 https+local://1.1.1.1/dns-query)
// 并让 dns.google 匹配到该 IP 服务器解析。
"https+local://1.1.1.1/dns-query",
"https+local://1.0.0.1/dns-query",
{
"address": "https+local://223.5.5.5/dns-query",
"domains": [
"geosite:geolocation-cn"
]
}
]
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 53,
"protocol": "dokodemo-door",
"tag": "dns-in",
"settings": {
// A 记录和 AAAA 记录会由上面配置的 DNS 服务器处理,
// 不会被转发到这里。
// 这里只是流量转发,不能像上面那样写 DoH。
"address": "8.8.8.8",
"port": 53,
"network": "tcp,udp"
}
}
],
"outbounds": [
{
"protocol": "dns",
"tag": "dns-out"
}
],
"routing": {
"rules": [
{
"type": "field",
"inboundTag": "dns-in",
"outboundTag": "dns-out"
}
]
}
}

按照配置,V2Ray 是这么工作的:V2Ray 监听本地的 53 端口,程序向它发送 DNS 请求时,V2Ray 通过路由将其发送至 DNS 出站协议,而 DNS 出站协议会将 IP 查询(即 A 记录和 AAAA 记录)转发至 V2Ray 内置的 DNS 服务器,再通过配置 V2Ray 的内置 DNS 服务器实现分流。

用了一会,发现:

  1. 通过 https+local://223.5.5.5/dns-query 查询未缓存的国内域名耗时 1.04-1.10s,作为对比,SmartDNS 下查询未缓存的域名耗时 35-120ms。
  2. 通过 https+local://1.1.1.1/dns-query 查询未缓存的国外域名耗时 1.24-1.27s,作为对比,SmartDNS 下查询未缓存的域名耗时 0.236s-1.46s。
  3. 查询已经缓存的域名仍需 1.01-1.02s,作为对比,SmartDNS 下查询已缓存域名只需 9-15ms。
这样的速度实在是不可接受。

SmartDNS in Front of V2Ray DNS Server

我们可以在 V2Ray 前面加一个 DNS 服务器用作缓存,让该缓存 DNS 服务器监听本地 53 端口,同时配置上游 DNS 为 V2Ray。

以下是 SmartDNS 的配置示例:

bind [::]:53
speed-check-mode none
server 127.0.0.1:5353
同时,V2Ray inbounds 部分的 ports 也要改成 5353。

One More Thing

$ dig google.com TXT +short
93.46.8.90
$ dig google.com TXT +short
8.7.198.46
$ dig baidu.com TXT +short
"google-site-verification=GHb98-6msqyx_qqjGl5eRatD3QTHyVB6-xQ3gJB5UwM"
"v=spf1 include:spf1.baidu.com include:spf2.baidu.com include:spf3.baidu.com a mx ptr -all"

前面提到过,V2Ray 的内置 DNS 服务器只支持 A 和 AAAA 记录,如果查询其它记录,会将请求转发至 8.8.8.8 的 53 端口,所以我们查询 google.com 的 TXT 记录时,返回的结果就被污染了。

解决方法很简单:在 V2Ray 后面加一个 DNS 服务器,专门处理非 A 和 AAAA 记录的查询。

以下是 SmartDNS 的配置示例:

bind [::]:5354
speed-check-mode none
server-https https://1.1.1.1/dns-query
同时,V2Ray inbounds 部分的 settings 中的 address 与 port 要分别改为 127.0.0.1 和 5354。

如果将两个配置写在一起:

bind [::]:53 -group front
bind [::]:5354 -group back
speed-check-mode none
server 127.0.0.1:5353 -group front
# 如果想配置域名 DoH 服务器,参见 https://github.com/pymumu/smartdns/issues/613。
server-https https://1.1.1.1/dns-query -group back

之后,DNS 记录就不会被污染了:

$ dig google.com TXT +short
"facebook-domain-verification=22rm551cu4k0ab0bxsw536tlds4h95"
"docusign=1b0a6754-49b1-4db5-8540-d2c12664b289"
"globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8="
"docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e"
"v=spf1 include:_spf.google.com ~all"

其它方案

以下是我想到的其它方案,不再赘述:

  1. 只让 V2Ray DNS 承担分流工作,具体解析交给 SmartDNS 进行,这样或许能降低查询时间,也能用上 SmartDNS 的测速功能。
  2. 不让 V2Ray 接管系统 DNS,以 domain-list-community 或 v2ray-rules-dat 为基础生成 SmartDNS 的分流配置,这样也能避免「某个域名国内 DNS 解析后走代理 / 国外 DNS 解析后直连」的情况。
© 2010-2022 XuLaLa 保留所有权利 本站由 WordPress 强力驱动
请求次数:69 次,加载用时:0.665 秒,内存占用:32.19 MB