xiaorouji / openwrt-passwall

7.22k stars 2.65k forks source link

[Bug]: 分流规则中的域名仍会被发往直连和远程 DNS 查询两次 #3153

Closed MkQtS closed 6 months ago

MkQtS commented 6 months ago

描述您遇到的bug

我通过 passwall sing-box 分流+本地 Socks 节点(ZJU RVPN)远程访问校内资源。某些校内站点公共DNS会解析成公网 IP,而内网 DNS 会解析为内网 IP(10.x.x.x),RVPN + 公网 IP 会使相关站点无法访问。RVPN 程序能够在本机特定接口提供校内 DNS,我是通过 AdGuard Home 给指定域名指定此 DNS,之前使用一切正常。

最近的某次更新后,"ChinaDNS-NG 域名默认标签"默认为"默认",即直连+远程。即使在分流规则中的域名也会被查询两次,并在上述的公网 IP 结果和内网 IP 结果中选择公网 IP 造成网络异常。

虽然我可以在 AdGuard Home 中来自直连 DNS 的对相关域名的查询,但如果国内 DNS 使用无法自定义返回结果的公共 DNS 就不行了。另外分流列表中已经设置为使用代理的域名使用国内 DNS 解析的 IP 再通过代理访问也可能也会造成其他问题。

复现此Bug的步骤

分流规则:

image

内网查询结果:

image

公网查询结果:

image

实际使用了公网 IP,无法访问相关网站

image

您想要实现的目的

希望分流规则中非直连的域名不要转发给直连 DNS,直接使用远程 DNS; 同样,直连的域名可以直接发给直连 DNS

日志信息


截图

No response

系统相关信息

Passwall 4.77-4

其他信息

No response

nftbty commented 6 months ago

这个问题我早几天发现的,有点复杂,不单单是你说的这样。 同时使用 分流模式 和 ChinaDNS-NG,就会有这个问题。当时还在想,怎么没有人遇到过这个问题,都没有过相关的issue。

问题产生的原因在于,passwall目前会把分流规则里的域名根据直连还是代理,跟直连列表和代理列表中的域名一样,通过dnsmasq 直接指定直连或远程DNS,并添加到 ipset/nftset。在使用ChinaDNS-NG时,这些列表的DNS分流和ipset/nftset的添加都交给ChinaDNS-NG来完成,偏偏分流规则的域名需要动态判断、处理,这部分没适配ChinaDNS-NG,直连的域名不影响最终效果,但是走代理的域名根据具体的DNS过滤模式不同,转发给ChinaDNS-NG(UDP、TCP这两个能直接处理的)或者ChinaDNS-NG 的上游(dns2socks、Xray、Sing-Box)。

这就有2种情况了:

  1. DNS直接使用UDP或TCP(新版直接由ChinaDNS-NG处理的情况,之前版本由dns2tcp处理的属第2种),请求会进入ChinaDNS-NG,但没有相应的域名列表,除非 直连列表代理列表 里有相同域名,否则会归为默认标签。 默认直连,这些域名的DNS都走直连DNS,网络连接也会走直连; 默认远程,这些域名的DNS都通过代理走远程DNS,网络连接也会全走代理; 默认none,也就是你的情况,DNS就会同时请求,网络连接直连还是代理取决于 TCP 默认代理模式
  2. DNS使用dns2tcp(现在没有这种组合了,之前有)、dns2socks、Xray、Sing-Box等,DNS查询会跳过ChinaDNS-NG,直接由远程DNS查询,请求也会走代理。 看似没什么问题,但我之前就是dns2tcp出现问题。如果开了过滤代理域名IPv6地址,会导致分流规则里走代理的域名IPv6无法过滤,一般被墙网站也没什么影响,但是像Bing,偏偏国内可以直连,本来想让Bing走代理,结果浏览器选择使用IPv6地址连接,变成直连了,就跳转 cn.bing.com了。不过Xray设置了只返回IPv4,刚好无意中避免了这个问题。Sing-Box未测试,应该和Xray一样。

这个问题之前就打算修,但是想了几种方案,都不是很好解决。可能得等几天。 你先参照我上面说的改下设置,避开这个问题。

MkQtS commented 6 months ago

参照我上面说的改下设置,避开这个问题。

~我把 ZJU 的域名添加到代理列表试试~ 添加到代理列表无效,还是会查两次。

简单的默认直连, 默认远程, 默认none似乎都不适合我,因为我需要解析出 10.x.x.x 相关域名只能使用 RVPN 程序提供的 DNS,这个 RVPN DNS 并不适合设置为直连/远程 DNS。我还是在 AdGuard Home 上动手脚吧。

这些列表的DNS分流和ipset/nftset的添加都交给ChinaDNS-NG来完成,偏偏分流规则的域名需要动态判断、处理,这部分没适配ChinaDNS-NG

请求会进入ChinaDNS-NG,但没有相应的域名列表

ChinaDNS-NG 的 README 是写明支持 gfwlist/chnlist 域名列表以及纯域名分流的,能否把 passwall 的直连/代理列表以及分流规则中的明确域名直接传给 ChinaDNS-NG 呢?

wtfr-dot commented 6 months ago

我这两天用主分支编译passwall,然后用自定义udp的形式将远程dns解析发给smartdns第二服务器端口的海外组进行解析,本地dns解析则通过dnsmasq转发给smartdns的默认组,passwall使用的xray分流,没有启用chinadns-ng,默认选用的远程,然后在smartdns的审计记录文件里发现部分应该走远程解析的域名会同时出现本地和远程同时解析的记录,这部分域名包含Google和Netflix,很显然这个无论如何都不应该会发向本地查询的,特别是Netflix还专门设了分流节点的,但又不是所有应该走远程的域名都有这种情况,这个就很纳闷了,然后我在分流总节点的域名解析策略将ipifnomath改为asia,直接通过域名分流后再看smartdns的审计记录文件里没看见同时本地远程解析的记录了

nftbty commented 6 months ago

你这种使用场景是典型的虚拟专用网(VPN),一般应该都是相应协议的客户端连接,会在本地设备生成一个虚拟的接口设备,分配专用网的IP和网关(只接管内网流量的不设默认网关,通过DHCP option121通告路由表项)等信息。如果VPN没有生成路由表项而是使用默认网关,可以手动配置静态路由,取消默认网关。

搜了下rvpn,搜出来直接就是你们学校,这个名字应该是你们学校自己取的名字,即 反向VPN,其实就是深信服的私有SSL VPN协议,官方客户端是 EasyConnect,另外还有个开源实现 EasierConnect,好像只支持socks代理的形式,应官方要求已停止维护。 不知道你是用的哪种客户端,部署在哪个设备上的。但是,能使用网关路由的方式尽量使用网关,然后配置路由表。dns直接在监听53端口的程序配置就行(一般都是dnsmasq,不知道你改了没)。 你这种访问虚拟内网的场景真不适合使用这些设计初衷为突破封锁的代理软件。

如果你使用的EasyConnect客户端不方便部署为网关,只能使用socks代理的方式,也可以尝试使用 tun2socks 在路由器上生成 tun设备,也可以使用路由表来路由。

如果你的vpn网关部署在路由器本机上,直接设置静态路由即可。 如果部署在局域网其他设备上,也可以设置路由器的静态路由。还可以在 LAN接口DHCP设置,添加 option121 选项,通告路由表项。设备下次连接路由器时,就可以通过DHCP动态获取路由表项,直接添加到本设备的路由表。

nftbty commented 6 months ago

单说你目前这种使用socks代理分流的方式

如果是浏览器直接连接socks代理访问网站,是不会发起DNS请求的,直接域名发给socks代理服务器,由代理服务器进行解析。所以你的EasyConnect 客户端应该是要支持直接解析域名的。如果确实可以,那你可以在hosts文件给你们学校几个内网IP的域名指定FakeIP 网段的某个地址,最终发往socks代理的请求地址会还原成域名。或者开启流量嗅探/覆盖连接目标地址应该也可以。 一般内网服务IP都不会变,域名不多的话你也可以直接手动查询然后直接写入hosts。 可能会觉得不够优雅,但其实效果应该最好,几个内网服务,IP又不会变,这样还可以减少DNS查询的时间。要不是IP记不住,都可以直接用IP访问的。

如果还是走内网DNS 查询,因为学校域名肯定是要进代理软件然后分流的,所以相应域名的DNS请求也只能走远程DNS,然后还需要分流。那么远程DNS就只能设置本地某个支持分流的DNS转发工具。 所以,我估计你的DNS拓扑应该是dnsmasq监听53端口,转发所有/大部分 DNS请求到 ChinaDNS-NG(这部分是passwall默认生成,应该不会变),然后你的本地直连DNS和远程DNS应该都是设置的本地AdGuard Home的监听地址,2个端口不同?我没用过AdGuard Home,不清楚是不是可以监听多个端口转发给不同的上游或进行不同的分流处理。 这样分析下来,只要校内域名的解析请求能进入远程DNS就没问题。所以你上面把校内域名加入代理列表(proxy_host)应该就不存在问题了。如果还有问题,可能就跟上面 @wtfr-dot 说的一样,是规则匹配时域名解析策略的问题。


当然,我还是不建议你用passwall来分流你校内的内网流量。我建议你配置的优先级:

  1. 首选 EasyConnect客户端提供的网关接口 + 路由表 + Dnsmasq指定校内域名走你们学校提供的DNS而不是VPN客户端提供的本地转发端口(如果需要统计DNS查询记录,才使用AGH分流);
  2. 客户端没法提供网关接口,只能使用Socks5代理,使用 tun2socks 在路由器生成一个tun接口,接收流量转发给socks代理,路由器跟上面一条一样,使用静态路由表来路由,DNS转发给学校DNS服务器地址;
  3. passwall 分流,但是手动查询域名对应IP地址,填入hosts,不配置相关DNS分流和转发,将内网IP段10.x.x.x/x填入代理列表IP部分(proxy_ip),分流规则使用CIDR 10.x.x.x/x IP段分流。
  4. 你目前所用的,DNS转发 + 域名分流。
MkQtS commented 6 months ago

我估计你的DNS拓扑应该是dnsmasq监听53端口,转发所有/大部分 DNS请求到 ChinaDNS-NG(这部分是passwall默认生成,应该不会变),然后你的本地直连DNS和远程DNS应该都是设置的本地AdGuard Home的监听地址,2个端口不同?

我是 AdGuardHome 监听 953 端口,直连 DNS 通过 dnsmasq 转发到 127.0.0.1:953,远程 DNS 是在 passwall 设置的 udp lan:953 ,AdGuardHome 可以区分两个查询来源设置为两个“客户端”,可以根据客户端以及域名设置不同的上游 DNS。

RVPN 是在 OpenWrt 上跑的 zju-connect,支持 TUN,但我嫌配接口和路由麻烦,作为一个普通的 Socks 节点用 passwall 分流比较方便,这也是分流的作用,我的分流规则就是校内域名+10.0.0.0/8

可能会觉得不够优雅,但其实效果应该最好,几个内网服务,IP又不会变,这样还可以减少DNS查询的时间。

RVPN 的作用不仅是访问内网网站,还可以校外使用学校图书馆购买的资源,比如通过学校的 IP 解锁一些学术网站查看下载文献,部分内网域名确实是固定的内网 IP,可以写到 hosts 里,但校外网站就不太好这么操作了。

目前我的 workaround 是同时在 127.0.0.1:953lan:953 两个 AdGuardHome 客户端中都配置 [/cc98.org/zju.edu.cn/]127.0.0.1:9853,直连 DNS 和远程 DNS 查询结果也就一样了。

讨论我的 RVPN 有点偏题了,这里的问题还是 passwall 最好是把需要代理的域名只通过远程 DNS 进行解析。

nftbty commented 6 months ago

你不使用ChinaDNS-NG的话应该是不存在问题的,我之前也说了,问题在于分流规则的域名没适配chinadns-ng,而且因为要连同访问控制的一起改,就比较复杂,还不太好改,需要时间好好想一个尽量简单、完善的改法。

但其实修改的最终效果也就是动态添加分流规则里走代理的域名到chinadns-ng的proxy组,和你把域名手动添加到代理列表最终表现是一样的。

你把学校域名添加到代理列表后,检查下/tmp/dnsmasq.d/passwall/001-server.conf,和/tmp/etc/passwall/acl/default/chinadns_ng.conf,根据配置文件手动分析下你学校域名的dns请求流向,是不是通过chinadns-ng发往proxy组上游的。 如果配置检查没问题,但还是会走国内租和可信组一起查询,那就是其他地方还有问题。

同时使用分流和ChinaDNS-NG的DNS分流问题并不是一定会触发,在修复之前,应该有很多办法可以暂时避开这个问题。你的情况,将域名添加到代理列表应该是已经不受这个问题影响了,不过也要检查配置文件才能确认。

MkQtS commented 6 months ago

我搞错了,之前没有我启用“使用 代理列表”,所以把学校的域名添加到代理列表也会查两次,然后启用“使用 代理列表”就只会向远程 DNS 查询一次了。

/tmp/dnsmasq.d/passwall/001-server.conf 的内容是把我所有分流列表中直连域名的 DNS 服务器设置为 127.0.0.1:953,其他代理域名(包括已经添加到代理列表的学校的域名)的 DNS 服务器设置为 127.0.0.1:15353(ChinaDNS-NG)

ZqinKing commented 6 months ago

我这两天用主分支编译passwall,然后用自定义udp的形式将远程dns解析发给smartdns第二服务器端口的海外组进行解析,本地dns解析则通过dnsmasq转发给smartdns的默认组,passwall使用的xray分流,没有启用chinadns-ng,默认选用的远程,然后在smartdns的审计记录文件里发现部分应该走远程解析的域名会同时出现本地和远程同时解析的记录,这部分域名包含Google和Netflix,很显然这个无论如何都不应该会发向本地查询的,特别是Netflix还专门设了分流节点的,但又不是所有应该走远程的域名都有这种情况,这个就很纳闷了,然后我在分流总节点的域名解析策略将ipifnomath改为asia,直接通过域名分流后再看smartdns的审计记录文件里没看见同时本地远程解析的记录了

xray分流你需要将嗅探流量只供路由使用勾选,不然xray会进行二次域名解析。

wtfr-dot commented 6 months ago

我这两天用主分支编译passwall,然后用自定义udp的形式将远程dns解析发给smartdns第二服务器端口的海外组进行解析,本地dns解析则通过dnsmasq转发给smartdns的默认组,passwall使用的xray分流,没有启用chinadns-ng,默认选用的远程,然后在smartdns的审计记录文件里发现部分应该走远程解析的域名会同时出现本地和远程同时解析的记录,这部分域名包含Google和Netflix,很显然这个无论如何都不应该会发向本地查询的,特别是Netflix还专门设了分流节点的,但又不是所有应该走远程的域名都有这种情况,这个就很纳闷了,然后我在分流总节点的域名解析策略将ipifnomath改为asia,直接通过域名分流后再看smartdns的审计记录文件里没看见同时本地远程解析的记录了

xray分流你需要将嗅探流量只供路由使用勾选,不然xray会进行二次域名解析。

这个一直是选中了的,之前用smartdns分支没发现这个问题,因为smartdns分支更新慢一些,而且我发现主分支现在用udp方式与smartdns通讯没有早期的bug了,所以准备一直用,结果发现了这个问题,但这个问题比较难复现,现在改为asia不进行域名解析目前没有发现问题了

xcyll commented 6 months ago

smartdns通讯 早期的bug 旧版本什么bug @wtfr-dot

wtfr-dot commented 6 months ago

smartdns通讯 早期的bug 旧版本什么bug @wtfr-dot

早期passwall这边会生成"server 127.0.0.1:6553"这类语句,smartdns那边会把它作为一个真正的server加载,但实际上127.0.0.1:6553指向的是smartdns第二服务器里的dns成员,这样smartdns在解析dns的时候会调用两次第二服务器组成员,使用上不是大问题,所以之前我都是将passwall源码git下来后手动注释掉,这个问题非常早了,应该是在smartdns38版本左右以前,后来passwall出来smartdns分支后就直接编译的smartdns分支没在关注这个问题了,只是因为smartdns分支更新比main慢,我才想到又在main上实现原来的功能,实际上现在main上应该是可以smartdns、chinadns-ng共存了,smartdns分支只是简化了smartdns使用难度

MkQtS commented 6 months ago

最新版本依旧存在此问题,没有添加到代理列表但在分流规则中已经指定需要代理的域名,在 ChianDNS-NG 默认模式下仍然会被发到直连 DNS 和远程 DNS 查询两次。我用的是 sing-box 分流,最近的提交记录似乎是对 xray 分流的一些修改 @nftbty

nftbty commented 6 months ago

上面说的问题,目前并没有着手修改,主要是确实不太好修改,想了大概两种修改方案,感觉都不是太好。 最近改的都是其他一些问题。接下来可能会优先添加 Xray分流下 DNS按查询域名路由,匹配分流规则的功能,实现走哪个分流节点出去的域名,其DNS请求也走相同出站。 因为在很多用户的使用场景下,开启 FakeDNS 或者流量嗅探覆盖目标域名会有其他一些问题,而 DNS路由 这个功能可以说是他们的刚需。