diff --git a/dns/client.go b/dns/client.go index f456f878..90c950b4 100644 --- a/dns/client.go +++ b/dns/client.go @@ -483,7 +483,7 @@ func (c *Client) loadResponse(question dns.Question, transport adapter.DNSTransp } func MessageToAddresses(response *dns.Msg) ([]netip.Addr, error) { - if response.Rcode != dns.RcodeSuccess && response.Rcode != dns.RcodeNameError { + if response.Rcode != dns.RcodeSuccess { return nil, RcodeError(response.Rcode) } addresses := make([]netip.Addr, 0, len(response.Answer)) diff --git a/dns/router.go b/dns/router.go index 18939c37..2dab57cc 100644 --- a/dns/router.go +++ b/dns/router.go @@ -330,6 +330,9 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ err error ) printResult := func() { + if err == nil && len(responseAddrs) == 0 { + err = E.New("empty result") + } if err != nil { if errors.Is(err, ErrResponseRejectedCached) { r.logger.DebugContext(ctx, "response rejected for ", domain, " (cached)") @@ -338,15 +341,15 @@ func (r *Router) Lookup(ctx context.Context, domain string, options adapter.DNSQ } else { r.logger.ErrorContext(ctx, E.Cause(err, "lookup failed for ", domain)) } - } else if len(responseAddrs) == 0 { - r.logger.ErrorContext(ctx, "lookup failed for ", domain, ": empty result") - err = RcodeNameError + } + if err != nil { + err = E.Cause(err, "lookup ", domain) } } responseAddrs, cached = r.client.LookupCache(domain, options.Strategy) if cached { if len(responseAddrs) == 0 { - return nil, RcodeNameError + return nil, E.New("lookup ", domain, ": empty result (cached)") } return responseAddrs, nil } diff --git a/dns/transport/local/local.go b/dns/transport/local/local.go index df473b3c..15be54c3 100644 --- a/dns/transport/local/local.go +++ b/dns/transport/local/local.go @@ -3,6 +3,7 @@ package local import ( "context" "math/rand" + "net/netip" "time" "github.com/sagernet/sing-box/adapter" @@ -90,8 +91,9 @@ func (t *Transport) exchangeParallel(ctx context.Context, systemConfig *dnsConfi startRacer := func(ctx context.Context, fqdn string) { response, err := t.tryOneName(ctx, systemConfig, fqdn, message) if err == nil { - addresses, _ := dns.MessageToAddresses(response) - if len(addresses) == 0 { + var addresses []netip.Addr + addresses, err = dns.MessageToAddresses(response) + if err == nil && len(addresses) == 0 { err = E.New(fqdn, ": empty result") } } diff --git a/route/conn.go b/route/conn.go index 582562eb..f46283ad 100644 --- a/route/conn.go +++ b/route/conn.go @@ -7,6 +7,7 @@ import ( "net" "net/netip" "os" + "strings" "sync" "sync/atomic" "time" @@ -66,7 +67,17 @@ func (m *ConnectionManager) NewConnection(ctx context.Context, this N.Dialer, co remoteConn, err = this.DialContext(ctx, N.NetworkTCP, metadata.Destination) } if err != nil { - err = E.Cause(err, "open outbound connection") + var remoteString string + if len(metadata.DestinationAddresses) > 0 { + remoteString = "[" + strings.Join(common.Map(metadata.DestinationAddresses, netip.Addr.String), ",") + "]" + } else { + remoteString = metadata.Destination.String() + } + var dialerString string + if outbound, isOutbound := this.(adapter.Outbound); isOutbound { + dialerString = " using outbound/" + outbound.Type() + "[" + outbound.Tag() + "]" + } + err = E.Cause(err, "open connection to ", remoteString, dialerString) N.CloseOnHandshakeFailure(conn, onClose, err) m.logger.ErrorContext(ctx, err) return @@ -133,8 +144,19 @@ func (m *ConnectionManager) NewPacketConnection(ctx context.Context, this N.Dial remoteConn, err = this.DialContext(ctx, N.NetworkUDP, metadata.Destination) } if err != nil { + var remoteString string + if len(metadata.DestinationAddresses) > 0 { + remoteString = "[" + strings.Join(common.Map(metadata.DestinationAddresses, netip.Addr.String), ",") + "]" + } else { + remoteString = metadata.Destination.String() + } + var dialerString string + if outbound, isOutbound := this.(adapter.Outbound); isOutbound { + dialerString = " using outbound/" + outbound.Type() + "[" + outbound.Tag() + "]" + } + err = E.Cause(err, "open packet connection to ", remoteString, dialerString) N.CloseOnHandshakeFailure(conn, onClose, err) - m.logger.ErrorContext(ctx, "open outbound packet connection: ", err) + m.logger.ErrorContext(ctx, err) return } remotePacketConn = bufio.NewUnbindPacketConn(remoteConn) @@ -149,8 +171,13 @@ func (m *ConnectionManager) NewPacketConnection(ctx context.Context, this N.Dial remotePacketConn, err = this.ListenPacket(ctx, metadata.Destination) } if err != nil { + var dialerString string + if outbound, isOutbound := this.(adapter.Outbound); isOutbound { + dialerString = " using outbound/" + outbound.Type() + "[" + outbound.Tag() + "]" + } + err = E.Cause(err, "listen packet connection using ", dialerString) N.CloseOnHandshakeFailure(conn, onClose, err) - m.logger.ErrorContext(ctx, "listen outbound packet connection: ", err) + m.logger.ErrorContext(ctx, err) return } }