SagerNet / sing-box

The universal proxy platform
https://sing-box.sagernet.org/
Other
20.44k stars 2.44k forks source link

sniffed dns request mismatch domain list #61

Closed zakuwaki closed 2 years ago

zakuwaki commented 2 years ago

Welcome

Description of the problem

When using dns rules to lookup domain for anti dns pollution, a weird mismatch behavior appears when a dns request is sniffed and redirected to internal dns, and mismatched in domain list.

For example, in the following log, first a tcp connection comes in and is sniffed domain clientservices.googleapis.com. This domain has service in mainland China and has @cn attribute in rule, and should be resolved in dns rule [0]., while mismatched and a remote dns record(blocked by gfw) is cached. Then, when route by domain, it is routed to direct, while get a cached and blocked ip when perform ipv4_only domain strategy. And the connection fails.

Version of sing-box

```console $ sing-box version sing-box 1.0-beta3 (go1.18.5, linux/amd64, CGO disabled) ```

Server and client configuration file

```console { "log": { "level": "debug", "timestamp": false }, "dns": { "servers": [ { "tag": "local-adguard", "address": "127.0.0.1", "detour": "direct" }, { "tag": "remote-adguard", "address": "127.0.0.1", "detour": "proxy" } ], "rules": [ { "server": "local-adguard", "disable_cache": false, "geosite": [ "private", "cn" ] }, { "server": "remote-adguard", "disable_cache": false, "inbound": [ "socks", "http", "shadowsocks" ] } ] }, "route": { "rules": [ { "outbound": "dns", "inbound": [ "dns-tunnel" ] }, { "outbound": "dns", "port": 53 }, { "outbound": "direct", "geosite": [ "private", "cn" ], "geoip": [ "private", "cn" ] }, { "outbound": "proxy", "inbound": [ "socks", "http", "shadowsocks" ] } ] }, "inbounds": [ { "tag": "dns-tunnel", "type": "direct", "listen": "0.0.0.0", "listen_port": 5353 }, { "tag": "socks", "type": "socks", "listen": "0.0.0.0", "listen_port": 1080, "sniff": true, "sniff_override_destination": true }, { "tag": "http", "type": "http", "listen": "0.0.0.0", "listen_port": 1081, "sniff": true, "sniff_override_destination": true }, { "tag": "shadowsocks", "type": "shadowsocks", "listen": "0.0.0.0", "listen_port": 12306, "sniff": true, "sniff_override_destination": true, "method": "chacha20-ietf-poly1305", "password": "MyShadowSocks" } ], "outbounds": [ { "tag": "direct", "type": "direct", "domain_strategy": "ipv4_only" }, { "tag": "dns", "type": "dns" }, { "tag": "proxy" } ] } ```

Server and client log file

```console Sep 04 09:54:44 ICL sing[17279]: INFO[0004] [4225494766] inbound/shadowsocks[shadowsocks]: inbound connection to 8.8.4.4:53 Sep 04 09:54:44 ICL sing[17279]: DEBUG[0004] [4225494766] router: sniffed protocol: dns Sep 04 09:54:44 ICL sing[17279]: DEBUG[0004] [4225494766] router: match[1] port=53 => dns Sep 04 09:54:44 ICL sing[17279]: DEBUG[0004] [4225494766] dns: exchange clientservices.googleapis.com A INET Sep 04 09:54:44 ICL sing[17279]: DEBUG[0004] [4225494766] dns: match[1] inbound=[socks http shadowsocks] => remote-adguard Sep 04 09:54:44 ICL sing[17279]: INFO[0004] outbound/trojan[proxy]: outbound multiplex packet connection to 127.0.0.1:53 Sep 04 09:54:44 ICL sing[17279]: INFO[0004] [4225494766] dns: exchanged clientservices.googleapis.com. A 172.217.164.99 Sep 04 09:54:45 ICL sing[17279]: INFO[0004] [3666427029] inbound/shadowsocks[shadowsocks]: inbound connection from 127.0.0.1:34798 Sep 04 09:54:45 ICL sing[17279]: INFO[0004] [3040906465] inbound/shadowsocks[shadowsocks]: inbound connection to 172.217.164.99:443 Sep 04 09:54:45 ICL sing[17279]: DEBUG[0004] [3040906465] router: sniffed protocol: tls, domain: clientservices.googleapis.com Sep 04 09:54:45 ICL sing[17279]: DEBUG[0004] [3040906465] router: match[2] geosite=[private cn scholar-database] geoip=[private cn] => direct Sep 04 09:54:45 ICL sing[17279]: INFO[0004] [3040906465] outbound/direct[direct]: outbound connection to clientservices.googleapis.com:443 Sep 04 09:54:45 ICL sing[17279]: DEBUG[0004] [3040906465] dns: lookup domain clientservices.googleapis.com Sep 04 09:54:45 ICL sing[17279]: DEBUG[0004] [3040906465] dns: match[0] geosite=[private cn scholar-database] => local-adguard Sep 04 09:54:45 ICL sing[17279]: INFO[0004] [3040906465] dns: lookup succeed for clientservices.googleapis.com: 172.217.164.99 Sep 04 09:54:50 ICL sing[17279]: ERROR[0009] [3666427029] inbound/shadowsocks[shadowsocks]: process connection from 127.0.0.1:34798: shadowsocks: serve TCP from 127.0.0.1:34798: dial tcp 172.217.164.99:443: i/o timeout ```
zakuwaki commented 2 years ago

I've noticed this code and I wonder why it is commented. https://github.com/SagerNet/sing-box/blob/9078bc2de5bbb528433a99a3f543a3e1047f35a4/common/sniff/dns.go#L58

nekohasekai commented 2 years ago

clientservices.googleapis.com is not in geosite:cn, but in geosite:google@cn which not supported by sing-box.

zakuwaki commented 2 years ago

Yes, you are right. I'm using a self build rule follows Loyalsoldier's way. https://github.com/zakuwaki/domain-list-custom/blob/ce86dcea0bea7bde64ae3dc90fd5298ec6dfae50/.github/workflows/build.yml#L45-L46

And I believe the reason is not this, because we can see rules work in this log:

Sep 04 09:54:45 ICL sing[17279]: DEBUG[0004] [3040906465] router: match[2] geosite=[private cn scholar-database] geoip=[private cn] => direct
Sep 04 09:54:45 ICL sing[17279]: INFO[0004] [3040906465] outbound/direct[direct]: outbound connection to clientservices.googleapis.com:443

I think the reason is in dns sniff like this behavior diff

# sniff
Sep 04 09:54:44 ICL sing[17279]: INFO[0004] [4225494766] inbound/shadowsocks[shadowsocks]: inbound connection to 8.8.4.4:53
Sep 04 09:54:44 ICL sing[17279]: DEBUG[0004] [4225494766] router: sniffed protocol: dns
Sep 04 09:54:44 ICL sing[17279]: DEBUG[0004] [4225494766] router: match[1] port=53 => dns
Sep 04 09:54:44 ICL sing[17279]: DEBUG[0004] [4225494766] dns: exchange clientservices.googleapis.com A INET
Sep 04 09:54:44 ICL sing[17279]: DEBUG[0004] [4225494766] dns: match[1] inbound=[socks http shadowsocks] => remote-adguard

Sep 04 09:54:45 ICL sing[17279]: DEBUG[0004] [3040906465] dns: lookup domain clientservices.googleapis.com
Sep 04 09:54:45 ICL sing[17279]: DEBUG[0004] [3040906465] dns: match[0] geosite=[private cn scholar-database] => local-adguard
Sep 04 09:54:45 ICL sing[17279]: INFO[0004] [3040906465] dns: lookup succeed for clientservices.googleapis.com: 172.217.164.99

I think that domain to be resolved is not filled in sniff so it is mismatched in this code https://github.com/SagerNet/sing-box/blob/9078bc2de5bbb528433a99a3f543a3e1047f35a4/common/sniff/dns.go#L58

nekohasekai commented 2 years ago

The role of the sniffer is to identify the protocol, and the DNS domain name is handled in another code.

nekohasekai commented 2 years ago

Try 4801b6f05772f2217a913efae6c654acf9988fbc

nekohasekai commented 2 years ago

I have added attr support to geosite, try https://github.com/SagerNet/sing-geosite/commit/50c4bf766c5f7b1d7611f338474df8382e867cd3

zakuwaki commented 2 years ago

Try 4801b6f

It works. Thank you!

I have added attr support to geosite, try SagerNet/sing-geosite@50c4bf7

Awesome, I'll have it a try.