SagerNet / sing-box

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

direct inbound for dns-in(udp) unable to respond dns query properly #1512

Closed nunu6689 closed 8 months ago

nunu6689 commented 8 months ago

Operating system

Linux

System version

openwrt 23.05.2

Installation type

Original sing-box Command Line

If you are using a graphical client, please provide the version of the client.

No response

Version

sing-box version 1.9.0-beta.5
                                                                                        Environment: go1.22.0 linux/arm64
Tags: with_gvisor,with_quic,with_dhcp,with_wireguard,with_ech,with_utls,with_reality_server,with_acme,with_clash_api
Revision: 9f6233de0db9239b5310920b7bc8b2f06105fc88                                      CGO: disabled

Description

Direct inbound as dns-in unable to respond DNS properly over UDP when the respond is long. 512?

It gave malformed reply packet. dnsmasq also unable to parse it.

 root@ kdig www.youtube.com @127.0.0.1 -p 1096
;; WARNING: malformed reply packet (trailing data)
;; WARNING: reply ID (0) is different from query ID (36109)
;; WARNING: response timeout for 127.0.0.1@1096(UDP)
;; WARNING: malformed reply packet (trailing data)
;; WARNING: reply ID (0) is different from query ID (36109)
;; WARNING: response timeout for 127.0.0.1@1096(UDP)
;; WARNING: malformed reply packet (trailing data)
;; WARNING: reply ID (0) is different from query ID (36109)
;; WARNING: response timeout for 127.0.0.1@1096(UDP)
;; ERROR: failed to query server 127.0.0.1@1096(UDP)
FORTIFY: pthread_mutex_destroy called on a destroyed mutex (0x7fc6aaafd0)
[1]    10225 abort      kdig www.youtube.com @127.0.0.1 -p 1096

root@ kdig youtube.com @127.0.0.1 -p 1096
;; ->>HEADER<<- opcode: QUERY; status: NOERROR; id: 41384
;; Flags: qr aa rd ra; QUERY: 1; ANSWER: 1; AUTHORITY: 0; ADDITIONAL: 0

;; QUESTION SECTION:
;; youtube.com.                 IN      A

;; ANSWER SECTION:
youtube.com.            1       IN      A       172.217.31.142

;; Received 56 B
;; Time 2024-02-29 22:04:22 WITA
;; From 127.0.0.1@1096(UDP) in 17.4 ms

Using TCP is fine. Version 1.8.7 also working fine though it gave truncated message and fallback to TCP. Tun also seems working fine with v1.9.0-beta.5

On router tun is too resource hungry. It choke the traffic when there's many connections. So I'd like to reduce the use of tun. Currently I use redir, tun for UDP only and direct for DNS in.

Reproduction

sing-box run -c config.json

config.json :

{
  "log": {
    "timestamp": true,
    "level": "trace"
  },
  "dns": {
    "servers": [
      {
        "tag": "dns-direct",
        "address": "8.8.8.8",
        "strategy": "ipv4_only",
        "detour": "direct"
      }
    ]
  },
  "inbounds": [
    {
      "tag": "dns-in",
      "type": "direct",
      "listen": "::",
      "listen_port": 1096,
      "override_address": "8.8.8.8",
      "override_port": 53
    }
  ],
  "outbounds": [
    {
      "type": "direct",
      "tag": "direct"
    },
    {
      "type": "dns",
      "tag": "dns-out"
    }
  ],
  "route": {
    "rules": [
      {
        "inbound": "dns-in",
        "outbound": "dns-out"
      }
    ]
  }
}

Logs

+0000 2024-02-29 14:03:31 INFO inbound/direct[dns-in]: tcp server started at [::]:1096
+0000 2024-02-29 14:03:31 INFO inbound/direct[dns-in]: udp server started at [::]:1096
+0000 2024-02-29 14:03:31 INFO sing-box started (0.00s)
+0000 2024-02-29 14:03:37 INFO [2429414438 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:37110
+0000 2024-02-29 14:03:37 DEBUG [2429414438 0ms] router: match[0] inbound=dns-in => dns-out
+0000 2024-02-29 14:03:37 DEBUG dns: exchange www.youtube.com. IN A
+0000 2024-02-29 14:03:37 INFO outbound/direct[direct]: outbound packet connection to 8.8.8.8:53
+0000 2024-02-29 14:03:37 DEBUG dns: exchanged www.youtube.com NOERROR 1
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com CNAME www.youtube.com. 1 IN CNAME youtube-ui.l.google.com.
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.200.91
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.200.136
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.200.93
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.130.136
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.130.93
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.130.190
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.130.91
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.68.93
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.68.136
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.68.190
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.68.91
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 64.233.170.91
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 64.233.170.93
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 172.253.118.91
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 172.253.118.136
+0000 2024-02-29 14:03:37 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1 IN A 74.125.200.190
+0000 2024-02-29 14:03:42 INFO [3961525778 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:40322
+0000 2024-02-29 14:03:42 DEBUG [3961525778 0ms] router: match[0] inbound=dns-in => dns-out
+0000 2024-02-29 14:03:42 DEBUG dns: exchange www.youtube.com. IN A
+0000 2024-02-29 14:03:42 DEBUG dns: exchanged www.youtube.com NOERROR 1795
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com CNAME www.youtube.com. 1795 IN CNAME youtube-ui.l.google.com.
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.200.91
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.200.136
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.200.93
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.130.136
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.130.93
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.130.190
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.130.91
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.68.93
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.68.136
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.68.190
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.68.91
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 64.233.170.91
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 64.233.170.93
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 172.253.118.91
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 172.253.118.136
+0000 2024-02-29 14:03:42 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1795 IN A 74.125.200.190
+0000 2024-02-29 14:03:47 DEBUG [629762229 10.2s] inbound/direct[dns-in]: connection closed: io: read/write on closed pipe | upstream: context canceled
+0000 2024-02-29 14:03:47 INFO [2493408974 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:49738
+0000 2024-02-29 14:03:47 DEBUG [2493408974 0ms] router: match[0] inbound=dns-in => dns-out
+0000 2024-02-29 14:03:47 DEBUG dns: exchange www.youtube.com. IN A
+0000 2024-02-29 14:03:47 DEBUG dns: exchanged www.youtube.com NOERROR 1790
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com CNAME www.youtube.com. 1790 IN CNAME youtube-ui.l.google.com.
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.200.190
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.200.91
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.200.136
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.200.93
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.130.136
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.130.93
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.130.190
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.130.91
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.68.93
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.68.136
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.68.190
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 74.125.68.91
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 64.233.170.91
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 64.233.170.93
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 172.253.118.91
+0000 2024-02-29 14:03:47 INFO dns: exchanged www.youtube.com A youtube-ui.l.google.com. 1790 IN A 172.253.118.136
+0000 2024-02-29 14:03:52 DEBUG [990896655 10.2s] inbound/direct[dns-in]: connection closed: io: read/write on closed pipe | upstream: context canceled
+0000 2024-02-29 14:03:57 DEBUG [69820969 10.2s] inbound/direct[dns-in]: connection closed: io: read/write on closed pipe | upstream: context canceled
+0000 2024-02-29 14:04:22 INFO [916179856 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:39867
+0000 2024-02-29 14:04:22 DEBUG [916179856 0ms] router: match[0] inbound=dns-in => dns-out
+0000 2024-02-29 14:04:22 DEBUG dns: exchange youtube.com. IN A
+0000 2024-02-29 14:04:22 DEBUG dns: exchanged youtube.com NOERROR 1
+0000 2024-02-29 14:04:22 INFO dns: exchanged youtube.com A youtube.com. 1 IN A 172.217.31.142
+0000 2024-02-29 14:04:32 DEBUG [3143088917 10.2s] inbound/direct[dns-in]: connection closed: io: read/write on closed pipe | upstream: context canceled

Integrity requirements

nunu6689 commented 8 months ago

It seems to be the same as #1508 I tried with tproxy as dns-in it gave the same malformed error. Previously tproxy acted similar with direct as dns-in.

nunu6689 commented 8 months ago

It seems due to the wrong buffer size for compression in sing-dns? And consider enable compression by default. https://github.com/AdguardTeam/dnsproxy/blob/68d417bfdc10e87e5d268aca3bd055e9fd88d206/proxy/dnscontext.go#L127

I don't know if it's even correct, but it works:

diff --git a/client_truncate.go b/client_truncate.go
index a0b4afd..5b8e80a 100644
--- a/client_truncate.go
+++ b/client_truncate.go
@@ -14,7 +14,8 @@ func TruncateDNSMessage(request *dns.Msg, response *dns.Msg, frontHeadroom int)
                }
        }
        response.Truncate(maxLen)
-       buffer := buf.NewSize(frontHeadroom + 1 + maxLen)
+       response.Compress = true
+       buffer := buf.NewSize(frontHeadroom + response.Len() + maxLen)
        buffer.Resize(frontHeadroom, 0)
        rawMessage, err := response.PackBuffer(buffer.FreeBytes())
        if err != nil {
nunu6689 commented 8 months ago

Aight I tested v1.9.0-beta.16 it seems to be fixed. Thanks.