Browse Source

Sockopt: Fix some domainStrategy & dialerProxy bugs (#4661)

patterniha 6 months ago
parent
commit
1c4e246788
1 changed files with 39 additions and 31 deletions
  1. 39 31
      transport/internet/dialer.go

+ 39 - 31
transport/internet/dialer.go

@@ -87,7 +87,7 @@ var (
 
 
 func lookupIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]net.IP, error) {
 func lookupIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]net.IP, error) {
 	if dnsClient == nil {
 	if dnsClient == nil {
-		return nil, nil
+		return nil, errors.New("DNS client not initialized").AtError()
 	}
 	}
 
 
 	ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{
 	ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{
@@ -103,44 +103,45 @@ func lookupIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]
 		}
 		}
 	}
 	}
 
 
+	if err == nil && len(ips) == 0 {
+		return nil, dns.ErrEmptyResponse
+	}
 	return ips, err
 	return ips, err
 }
 }
 
 
-func canLookupIP(ctx context.Context, dst net.Destination, sockopt *SocketConfig) bool {
-	if dst.Address.Family().IsIP() || dnsClient == nil {
+func canLookupIP(dst net.Destination, sockopt *SocketConfig) bool {
+	if dst.Address.Family().IsIP() {
 		return false
 		return false
 	}
 	}
 	return sockopt.DomainStrategy.hasStrategy()
 	return sockopt.DomainStrategy.hasStrategy()
 }
 }
 
 
-func redirect(ctx context.Context, dst net.Destination, obt string) net.Conn {
+func redirect(ctx context.Context, dst net.Destination, obt string, h outbound.Handler) net.Conn {
 	errors.LogInfo(ctx, "redirecting request "+dst.String()+" to "+obt)
 	errors.LogInfo(ctx, "redirecting request "+dst.String()+" to "+obt)
-	h := obm.GetHandler(obt)
 	outbounds := session.OutboundsFromContext(ctx)
 	outbounds := session.OutboundsFromContext(ctx)
 	ctx = session.ContextWithOutbounds(ctx, append(outbounds, &session.Outbound{
 	ctx = session.ContextWithOutbounds(ctx, append(outbounds, &session.Outbound{
 		Target:  dst,
 		Target:  dst,
 		Gateway: nil,
 		Gateway: nil,
 		Tag:     obt,
 		Tag:     obt,
 	})) // add another outbound in session ctx
 	})) // add another outbound in session ctx
-	if h != nil {
-		ur, uw := pipe.New(pipe.OptionsFromContext(ctx)...)
-		dr, dw := pipe.New(pipe.OptionsFromContext(ctx)...)
-
-		go h.Dispatch(context.WithoutCancel(ctx), &transport.Link{Reader: ur, Writer: dw})
-		var readerOpt cnc.ConnectionOption
-		if dst.Network == net.Network_TCP {
-			readerOpt = cnc.ConnectionOutputMulti(dr)
-		} else {
-			readerOpt = cnc.ConnectionOutputMultiUDP(dr)
-		}
-		nc := cnc.NewConnection(
-			cnc.ConnectionInputMulti(uw),
-			readerOpt,
-			cnc.ConnectionOnClose(common.ChainedClosable{uw, dw}),
-		)
-		return nc
+
+	ur, uw := pipe.New(pipe.OptionsFromContext(ctx)...)
+	dr, dw := pipe.New(pipe.OptionsFromContext(ctx)...)
+
+	go h.Dispatch(context.WithoutCancel(ctx), &transport.Link{Reader: ur, Writer: dw})
+	var readerOpt cnc.ConnectionOption
+	if dst.Network == net.Network_TCP {
+		readerOpt = cnc.ConnectionOutputMulti(dr)
+	} else {
+		readerOpt = cnc.ConnectionOutputMultiUDP(dr)
 	}
 	}
-	return nil
+	nc := cnc.NewConnection(
+		cnc.ConnectionInputMulti(uw),
+		readerOpt,
+		cnc.ConnectionOnClose(common.ChainedClosable{uw, dw}),
+	)
+	return nc
+
 }
 }
 
 
 func checkAddressPortStrategy(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (*net.Destination, error) {
 func checkAddressPortStrategy(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (*net.Destination, error) {
@@ -247,21 +248,28 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
 		dest = *newDest
 		dest = *newDest
 	}
 	}
 
 
-	if canLookupIP(ctx, dest, sockopt) {
+	if canLookupIP(dest, sockopt) {
 		ips, err := lookupIP(dest.Address.String(), sockopt.DomainStrategy, src)
 		ips, err := lookupIP(dest.Address.String(), sockopt.DomainStrategy, src)
-		if err == nil && len(ips) > 0 {
+		if err != nil {
+			errors.LogErrorInner(ctx, err, "failed to resolve ip")
+			if sockopt.DomainStrategy.forceIP() {
+				return nil, err
+			}
+		} else {
 			dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])
 			dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])
 			errors.LogInfo(ctx, "replace destination with "+dest.String())
 			errors.LogInfo(ctx, "replace destination with "+dest.String())
-		} else if err != nil {
-			errors.LogWarningInner(ctx, err, "failed to resolve ip")
 		}
 		}
 	}
 	}
 
 
-	if obm != nil && len(sockopt.DialerProxy) > 0 {
-		nc := redirect(ctx, dest, sockopt.DialerProxy)
-		if nc != nil {
-			return nc, nil
+	if len(sockopt.DialerProxy) > 0 {
+		if obm == nil {
+			return nil, errors.New("there is no outbound manager for dialerProxy").AtError()
+		}
+		h := obm.GetHandler(sockopt.DialerProxy)
+		if h == nil {
+			return nil, errors.New("there is no outbound handler for dialerProxy").AtError()
 		}
 		}
+		return redirect(ctx, dest, sockopt.DialerProxy, h), nil
 	}
 	}
 
 
 	return effectiveSystemDialer.Dial(ctx, src, dest, sockopt)
 	return effectiveSystemDialer.Dial(ctx, src, dest, sockopt)