mirror of https://github.com/XTLS/Xray-core
				
				
				
			Some refines related to direct/freedom and `targetStrategy`; More intelligent "useIP"/"ForceIP", enhance "origin" functionality (#5030)
https://github.com/XTLS/Xray-core/pull/5009#issuecomment-3194264277pull/5039/head
							parent
							
								
									3a54924045
								
							
						
					
					
						commit
						6d1695a686
					
				| 
						 | 
				
			
			@ -322,10 +322,18 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
 | 
			
		|||
				outbounds[0].Target = originalDest
 | 
			
		||||
			}
 | 
			
		||||
			ctx = session.ContextWithOutbounds(ctx, outbounds)
 | 
			
		||||
			local := net.DestinationFromAddr(w.hub.Addr())
 | 
			
		||||
			if local.Address == net.AnyIP || local.Address == net.AnyIPv6 {
 | 
			
		||||
				if source.Address.Family().IsIPv4() {
 | 
			
		||||
					local.Address = net.AnyIP
 | 
			
		||||
				} else if source.Address.Family().IsIPv6() {
 | 
			
		||||
					local.Address = net.AnyIPv6
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			ctx = session.ContextWithInbound(ctx, &session.Inbound{
 | 
			
		||||
				Source:  source,
 | 
			
		||||
				Local:   net.DestinationFromAddr(w.hub.Addr()), // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
 | 
			
		||||
				Local:   local, // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
 | 
			
		||||
				Gateway: net.UDPDestination(w.address, w.port),
 | 
			
		||||
				Tag:     w.tag,
 | 
			
		||||
			})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,12 +4,13 @@ import (
 | 
			
		|||
	"context"
 | 
			
		||||
	"crypto/rand"
 | 
			
		||||
	goerrors "errors"
 | 
			
		||||
	"github.com/xtls/xray-core/common/dice"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	gonet "net"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/xtls/xray-core/common/dice"
 | 
			
		||||
 | 
			
		||||
	"github.com/xtls/xray-core/app/proxyman"
 | 
			
		||||
	"github.com/xtls/xray-core/common"
 | 
			
		||||
	"github.com/xtls/xray-core/common/buf"
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +181,11 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
 | 
			
		|||
	ob := outbounds[len(outbounds)-1]
 | 
			
		||||
	content := session.ContentFromContext(ctx)
 | 
			
		||||
	if h.senderSettings != nil && h.senderSettings.TargetStrategy.HasStrategy() && ob.Target.Address.Family().IsDomain() && (content == nil || !content.SkipDNSResolve) {
 | 
			
		||||
		ips, err := internet.LookupForIP(ob.Target.Address.Domain(), h.senderSettings.TargetStrategy, nil)
 | 
			
		||||
		strategy := h.senderSettings.TargetStrategy
 | 
			
		||||
		if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil {
 | 
			
		||||
			strategy = strategy.GetDynamicStrategy(ob.OriginalTarget.Address.Family())
 | 
			
		||||
		}
 | 
			
		||||
		ips, err := internet.LookupForIP(ob.Target.Address.Domain(), strategy, nil)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			errors.LogInfoInner(ctx, err, "failed to resolve ip for target ", ob.Target.Address.Domain())
 | 
			
		||||
			if h.senderSettings.TargetStrategy.ForceIP() {
 | 
			
		||||
| 
						 | 
				
			
			@ -251,14 +256,6 @@ out:
 | 
			
		|||
	common.Interrupt(link.Reader)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Address implements internet.Dialer.
 | 
			
		||||
func (h *Handler) Address() net.Address {
 | 
			
		||||
	if h.senderSettings == nil || h.senderSettings.Via == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return h.senderSettings.Via.AsAddress()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handler) DestIpAddress() net.IP {
 | 
			
		||||
	return internet.DestIpAddress()
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -293,41 +290,16 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
 | 
			
		|||
				return h.getStatCouterConnection(conn), nil
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			errors.LogWarning(ctx, "failed to get outbound handler with tag: ", tag)
 | 
			
		||||
			errors.LogError(ctx, "failed to get outbound handler with tag: ", tag)
 | 
			
		||||
			return nil, errors.New("failed to get outbound handler with tag: " + tag)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if h.senderSettings.Via != nil {
 | 
			
		||||
 | 
			
		||||
			outbounds := session.OutboundsFromContext(ctx)
 | 
			
		||||
			ob := outbounds[len(outbounds)-1]
 | 
			
		||||
			var domain string
 | 
			
		||||
			addr := h.senderSettings.Via.AsAddress()
 | 
			
		||||
			domain = h.senderSettings.Via.GetDomain()
 | 
			
		||||
			switch {
 | 
			
		||||
			case h.senderSettings.ViaCidr != "":
 | 
			
		||||
				ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
 | 
			
		||||
 | 
			
		||||
			case domain == "origin":
 | 
			
		||||
				if inbound := session.InboundFromContext(ctx); inbound != nil {
 | 
			
		||||
					if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
 | 
			
		||||
						ob.Gateway = inbound.Local.Address
 | 
			
		||||
						errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			case domain == "srcip":
 | 
			
		||||
				if inbound := session.InboundFromContext(ctx); inbound != nil {
 | 
			
		||||
					if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
 | 
			
		||||
						ob.Gateway = inbound.Source.Address
 | 
			
		||||
						errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			//case addr.Family().IsDomain():
 | 
			
		||||
			default:
 | 
			
		||||
				ob.Gateway = addr
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			h.SetOutboundGateway(ctx, ob)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
 | 
			
		||||
| 
						 | 
				
			
			@ -342,6 +314,38 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
 | 
			
		|||
	return conn, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handler) SetOutboundGateway(ctx context.Context, ob *session.Outbound) {
 | 
			
		||||
	if ob.Gateway == nil && h.senderSettings != nil && h.senderSettings.Via != nil && !h.senderSettings.ProxySettings.HasTag() && (h.streamSettings.SocketSettings == nil || len(h.streamSettings.SocketSettings.DialerProxy) == 0) {
 | 
			
		||||
		var domain string
 | 
			
		||||
		addr := h.senderSettings.Via.AsAddress()
 | 
			
		||||
		domain = h.senderSettings.Via.GetDomain()
 | 
			
		||||
		switch {
 | 
			
		||||
		case h.senderSettings.ViaCidr != "":
 | 
			
		||||
			ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
 | 
			
		||||
 | 
			
		||||
		case domain == "origin":
 | 
			
		||||
			if inbound := session.InboundFromContext(ctx); inbound != nil {
 | 
			
		||||
				if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
 | 
			
		||||
					ob.Gateway = inbound.Local.Address
 | 
			
		||||
					errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		case domain == "srcip":
 | 
			
		||||
			if inbound := session.InboundFromContext(ctx); inbound != nil {
 | 
			
		||||
				if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
 | 
			
		||||
					ob.Gateway = inbound.Source.Address
 | 
			
		||||
					errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		//case addr.Family().IsDomain():
 | 
			
		||||
		default:
 | 
			
		||||
			ob.Gateway = addr
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handler) getStatCouterConnection(conn stat.Connection) stat.Connection {
 | 
			
		||||
	if h.uplinkCounter != nil || h.downlinkCounter != nil {
 | 
			
		||||
		return &stat.CounterConnection{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ import (
 | 
			
		|||
	"github.com/xtls/xray-core/common/protocol"
 | 
			
		||||
	"github.com/xtls/xray-core/proxy/freedom"
 | 
			
		||||
	"google.golang.org/protobuf/proto"
 | 
			
		||||
	"github.com/xtls/xray-core/transport/internet"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type FreedomConfig struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -47,27 +48,27 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
 | 
			
		|||
	}
 | 
			
		||||
	switch strings.ToLower(targetStrategy) {
 | 
			
		||||
	case "asis", "":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_AS_IS
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_AS_IS
 | 
			
		||||
	case "useip":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_USE_IP
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_USE_IP
 | 
			
		||||
	case "useipv4":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_USE_IP4
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_USE_IP4
 | 
			
		||||
	case "useipv6":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_USE_IP6
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_USE_IP6
 | 
			
		||||
	case "useipv4v6":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_USE_IP46
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_USE_IP46
 | 
			
		||||
	case "useipv6v4":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_USE_IP64
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_USE_IP64
 | 
			
		||||
	case "forceip":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_FORCE_IP
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_FORCE_IP
 | 
			
		||||
	case "forceipv4":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_FORCE_IP4
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_FORCE_IP4
 | 
			
		||||
	case "forceipv6":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_FORCE_IP6
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_FORCE_IP6
 | 
			
		||||
	case "forceipv4v6":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_FORCE_IP46
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_FORCE_IP46
 | 
			
		||||
	case "forceipv6v4":
 | 
			
		||||
		config.DomainStrategy = freedom.Config_FORCE_IP64
 | 
			
		||||
		config.DomainStrategy = internet.DomainStrategy_FORCE_IP64
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, errors.New("unsupported domain strategy: ", targetStrategy)
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
	"github.com/xtls/xray-core/common/protocol"
 | 
			
		||||
	. "github.com/xtls/xray-core/infra/conf"
 | 
			
		||||
	"github.com/xtls/xray-core/proxy/freedom"
 | 
			
		||||
	"github.com/xtls/xray-core/transport/internet"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestFreedomConfig(t *testing.T) {
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +24,7 @@ func TestFreedomConfig(t *testing.T) {
 | 
			
		|||
			}`,
 | 
			
		||||
			Parser: loadJSON(creator),
 | 
			
		||||
			Output: &freedom.Config{
 | 
			
		||||
				DomainStrategy: freedom.Config_AS_IS,
 | 
			
		||||
				DomainStrategy: internet.DomainStrategy_AS_IS,
 | 
			
		||||
				DestinationOverride: &freedom.DestinationOverride{
 | 
			
		||||
					Server: &protocol.ServerEndpoint{
 | 
			
		||||
						Address: &net.IPOrDomain{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,44 +1 @@
 | 
			
		|||
package freedom
 | 
			
		||||
 | 
			
		||||
var strategy = [][]byte{
 | 
			
		||||
	//              name        strategy,   prefer, fallback
 | 
			
		||||
	{0, 0, 0}, //   AsIs        none,       /,      /
 | 
			
		||||
	{1, 0, 0}, //   UseIP       use,        both,   none
 | 
			
		||||
	{1, 4, 0}, //   UseIPv4     use,        4,      none
 | 
			
		||||
	{1, 6, 0}, //   UseIPv6     use,        6,      none
 | 
			
		||||
	{1, 4, 6}, //   UseIPv4v6   use,        4,      6
 | 
			
		||||
	{1, 6, 4}, //   UseIPv6v4   use,        6,      4
 | 
			
		||||
	{2, 0, 0}, //   ForceIP     force,      both,   none
 | 
			
		||||
	{2, 4, 0}, //   ForceIPv4   force,      4,      none
 | 
			
		||||
	{2, 6, 0}, //   ForceIPv6   force,      6,      none
 | 
			
		||||
	{2, 4, 6}, //   ForceIPv4v6 force,      4,      6
 | 
			
		||||
	{2, 6, 4}, //   ForceIPv6v4 force,      6,      4
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) hasStrategy() bool {
 | 
			
		||||
	return strategy[c.DomainStrategy][0] != 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) forceIP() bool {
 | 
			
		||||
	return strategy[c.DomainStrategy][0] == 2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) preferIP4() bool {
 | 
			
		||||
	return strategy[c.DomainStrategy][1] == 4 || strategy[c.DomainStrategy][1] == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) preferIP6() bool {
 | 
			
		||||
	return strategy[c.DomainStrategy][1] == 6 || strategy[c.DomainStrategy][1] == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) hasFallback() bool {
 | 
			
		||||
	return strategy[c.DomainStrategy][2] != 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) fallbackIP4() bool {
 | 
			
		||||
	return strategy[c.DomainStrategy][2] == 4
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Config) fallbackIP6() bool {
 | 
			
		||||
	return strategy[c.DomainStrategy][2] == 6
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@ package freedom
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	protocol "github.com/xtls/xray-core/common/protocol"
 | 
			
		||||
	internet "github.com/xtls/xray-core/transport/internet"
 | 
			
		||||
	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
 | 
			
		||||
	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
 | 
			
		||||
	reflect "reflect"
 | 
			
		||||
| 
						 | 
				
			
			@ -21,79 +22,6 @@ const (
 | 
			
		|||
	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Config_DomainStrategy int32
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	Config_AS_IS      Config_DomainStrategy = 0
 | 
			
		||||
	Config_USE_IP     Config_DomainStrategy = 1
 | 
			
		||||
	Config_USE_IP4    Config_DomainStrategy = 2
 | 
			
		||||
	Config_USE_IP6    Config_DomainStrategy = 3
 | 
			
		||||
	Config_USE_IP46   Config_DomainStrategy = 4
 | 
			
		||||
	Config_USE_IP64   Config_DomainStrategy = 5
 | 
			
		||||
	Config_FORCE_IP   Config_DomainStrategy = 6
 | 
			
		||||
	Config_FORCE_IP4  Config_DomainStrategy = 7
 | 
			
		||||
	Config_FORCE_IP6  Config_DomainStrategy = 8
 | 
			
		||||
	Config_FORCE_IP46 Config_DomainStrategy = 9
 | 
			
		||||
	Config_FORCE_IP64 Config_DomainStrategy = 10
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Enum value maps for Config_DomainStrategy.
 | 
			
		||||
var (
 | 
			
		||||
	Config_DomainStrategy_name = map[int32]string{
 | 
			
		||||
		0:  "AS_IS",
 | 
			
		||||
		1:  "USE_IP",
 | 
			
		||||
		2:  "USE_IP4",
 | 
			
		||||
		3:  "USE_IP6",
 | 
			
		||||
		4:  "USE_IP46",
 | 
			
		||||
		5:  "USE_IP64",
 | 
			
		||||
		6:  "FORCE_IP",
 | 
			
		||||
		7:  "FORCE_IP4",
 | 
			
		||||
		8:  "FORCE_IP6",
 | 
			
		||||
		9:  "FORCE_IP46",
 | 
			
		||||
		10: "FORCE_IP64",
 | 
			
		||||
	}
 | 
			
		||||
	Config_DomainStrategy_value = map[string]int32{
 | 
			
		||||
		"AS_IS":      0,
 | 
			
		||||
		"USE_IP":     1,
 | 
			
		||||
		"USE_IP4":    2,
 | 
			
		||||
		"USE_IP6":    3,
 | 
			
		||||
		"USE_IP46":   4,
 | 
			
		||||
		"USE_IP64":   5,
 | 
			
		||||
		"FORCE_IP":   6,
 | 
			
		||||
		"FORCE_IP4":  7,
 | 
			
		||||
		"FORCE_IP6":  8,
 | 
			
		||||
		"FORCE_IP46": 9,
 | 
			
		||||
		"FORCE_IP64": 10,
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (x Config_DomainStrategy) Enum() *Config_DomainStrategy {
 | 
			
		||||
	p := new(Config_DomainStrategy)
 | 
			
		||||
	*p = x
 | 
			
		||||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x Config_DomainStrategy) String() string {
 | 
			
		||||
	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (Config_DomainStrategy) Descriptor() protoreflect.EnumDescriptor {
 | 
			
		||||
	return file_proxy_freedom_config_proto_enumTypes[0].Descriptor()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (Config_DomainStrategy) Type() protoreflect.EnumType {
 | 
			
		||||
	return &file_proxy_freedom_config_proto_enumTypes[0]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x Config_DomainStrategy) Number() protoreflect.EnumNumber {
 | 
			
		||||
	return protoreflect.EnumNumber(x)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Deprecated: Use Config_DomainStrategy.Descriptor instead.
 | 
			
		||||
func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) {
 | 
			
		||||
	return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3, 0}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type DestinationOverride struct {
 | 
			
		||||
	state         protoimpl.MessageState
 | 
			
		||||
	sizeCache     protoimpl.SizeCache
 | 
			
		||||
| 
						 | 
				
			
			@ -330,12 +258,12 @@ type Config struct {
 | 
			
		|||
	sizeCache     protoimpl.SizeCache
 | 
			
		||||
	unknownFields protoimpl.UnknownFields
 | 
			
		||||
 | 
			
		||||
	DomainStrategy      Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.proxy.freedom.Config_DomainStrategy" json:"domain_strategy,omitempty"`
 | 
			
		||||
	DestinationOverride *DestinationOverride  `protobuf:"bytes,3,opt,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
 | 
			
		||||
	UserLevel           uint32                `protobuf:"varint,4,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"`
 | 
			
		||||
	Fragment            *Fragment             `protobuf:"bytes,5,opt,name=fragment,proto3" json:"fragment,omitempty"`
 | 
			
		||||
	ProxyProtocol       uint32                `protobuf:"varint,6,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"`
 | 
			
		||||
	Noises              []*Noise              `protobuf:"bytes,7,rep,name=noises,proto3" json:"noises,omitempty"`
 | 
			
		||||
	DomainStrategy      internet.DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
 | 
			
		||||
	DestinationOverride *DestinationOverride    `protobuf:"bytes,3,opt,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
 | 
			
		||||
	UserLevel           uint32                  `protobuf:"varint,4,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"`
 | 
			
		||||
	Fragment            *Fragment               `protobuf:"bytes,5,opt,name=fragment,proto3" json:"fragment,omitempty"`
 | 
			
		||||
	ProxyProtocol       uint32                  `protobuf:"varint,6,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"`
 | 
			
		||||
	Noises              []*Noise                `protobuf:"bytes,7,rep,name=noises,proto3" json:"noises,omitempty"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *Config) Reset() {
 | 
			
		||||
| 
						 | 
				
			
			@ -368,11 +296,11 @@ func (*Config) Descriptor() ([]byte, []int) {
 | 
			
		|||
	return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *Config) GetDomainStrategy() Config_DomainStrategy {
 | 
			
		||||
func (x *Config) GetDomainStrategy() internet.DomainStrategy {
 | 
			
		||||
	if x != nil {
 | 
			
		||||
		return x.DomainStrategy
 | 
			
		||||
	}
 | 
			
		||||
	return Config_AS_IS
 | 
			
		||||
	return internet.DomainStrategy(0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (x *Config) GetDestinationOverride() *DestinationOverride {
 | 
			
		||||
| 
						 | 
				
			
			@ -418,81 +346,72 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
 | 
			
		|||
	0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d,
 | 
			
		||||
	0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
 | 
			
		||||
	0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72,
 | 
			
		||||
	0x6f, 0x74, 0x6f, 0x22, 0x53, 0x0a, 0x13, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
 | 
			
		||||
	0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65,
 | 
			
		||||
	0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
 | 
			
		||||
	0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
 | 
			
		||||
	0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
 | 
			
		||||
	0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x02, 0x0a, 0x08, 0x46, 0x72, 0x61,
 | 
			
		||||
	0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73,
 | 
			
		||||
	0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61, 0x63,
 | 
			
		||||
	0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b,
 | 
			
		||||
	0x65, 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70, 0x61,
 | 
			
		||||
	0x63, 0x6b, 0x65, 0x74, 0x73, 0x54, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74,
 | 
			
		||||
	0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e,
 | 
			
		||||
	0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
 | 
			
		||||
	0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67,
 | 
			
		||||
	0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
 | 
			
		||||
	0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74,
 | 
			
		||||
	0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65,
 | 
			
		||||
	0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
 | 
			
		||||
	0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x12, 0x22, 0x0a, 0x0d, 0x6d,
 | 
			
		||||
	0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01,
 | 
			
		||||
	0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x69, 0x6e, 0x12,
 | 
			
		||||
	0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x61, 0x78,
 | 
			
		||||
	0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74,
 | 
			
		||||
	0x4d, 0x61, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x05, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a,
 | 
			
		||||
	0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
 | 
			
		||||
	0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a,
 | 
			
		||||
	0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
 | 
			
		||||
	0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64,
 | 
			
		||||
	0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
 | 
			
		||||
	0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61,
 | 
			
		||||
	0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c,
 | 
			
		||||
	0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18,
 | 
			
		||||
	0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19, 0x0a,
 | 
			
		||||
	0x08, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
 | 
			
		||||
	0x07, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
 | 
			
		||||
	0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74,
 | 
			
		||||
	0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x78,
 | 
			
		||||
	0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f,
 | 
			
		||||
	0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
 | 
			
		||||
	0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
 | 
			
		||||
	0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69,
 | 
			
		||||
	0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18,
 | 
			
		||||
	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
 | 
			
		||||
	0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69,
 | 
			
		||||
	0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13,
 | 
			
		||||
	0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72,
 | 
			
		||||
	0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65,
 | 
			
		||||
	0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76,
 | 
			
		||||
	0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05,
 | 
			
		||||
	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
 | 
			
		||||
	0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65,
 | 
			
		||||
	0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e,
 | 
			
		||||
	0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06,
 | 
			
		||||
	0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f,
 | 
			
		||||
	0x63, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20,
 | 
			
		||||
	0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
 | 
			
		||||
	0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06,
 | 
			
		||||
	0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
 | 
			
		||||
	0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f,
 | 
			
		||||
	0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01,
 | 
			
		||||
	0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a,
 | 
			
		||||
	0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53,
 | 
			
		||||
	0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f,
 | 
			
		||||
	0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
 | 
			
		||||
	0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
 | 
			
		||||
	0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36,
 | 
			
		||||
	0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36,
 | 
			
		||||
	0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34,
 | 
			
		||||
	0x10, 0x0a, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
 | 
			
		||||
	0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27,
 | 
			
		||||
	0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
 | 
			
		||||
	0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
 | 
			
		||||
	0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50,
 | 
			
		||||
	0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72,
 | 
			
		||||
	0x6f, 0x74, 0x6f, 0x33,
 | 
			
		||||
	0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69,
 | 
			
		||||
	0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70,
 | 
			
		||||
	0x72, 0x6f, 0x74, 0x6f, 0x22, 0x53, 0x0a, 0x13, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
 | 
			
		||||
	0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x73,
 | 
			
		||||
	0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72,
 | 
			
		||||
	0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
 | 
			
		||||
	0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
 | 
			
		||||
	0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x02, 0x0a, 0x08, 0x46, 0x72,
 | 
			
		||||
	0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
 | 
			
		||||
	0x73, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61,
 | 
			
		||||
	0x63, 0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63,
 | 
			
		||||
	0x6b, 0x65, 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70,
 | 
			
		||||
	0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x54, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67,
 | 
			
		||||
	0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65,
 | 
			
		||||
	0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74,
 | 
			
		||||
	0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e,
 | 
			
		||||
	0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
 | 
			
		||||
	0x61, 0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e,
 | 
			
		||||
	0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74,
 | 
			
		||||
	0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52,
 | 
			
		||||
	0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x12, 0x22, 0x0a, 0x0d,
 | 
			
		||||
	0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x07, 0x20,
 | 
			
		||||
	0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x69, 0x6e,
 | 
			
		||||
	0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x61,
 | 
			
		||||
	0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69,
 | 
			
		||||
	0x74, 0x4d, 0x61, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x05, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d,
 | 
			
		||||
	0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01,
 | 
			
		||||
	0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a,
 | 
			
		||||
	0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
 | 
			
		||||
	0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09,
 | 
			
		||||
	0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
 | 
			
		||||
	0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c,
 | 
			
		||||
	0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65,
 | 
			
		||||
	0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
 | 
			
		||||
	0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19,
 | 
			
		||||
	0x0a, 0x08, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
 | 
			
		||||
	0x52, 0x07, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x22, 0xe9, 0x02, 0x0a, 0x06, 0x43, 0x6f,
 | 
			
		||||
	0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73,
 | 
			
		||||
	0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e,
 | 
			
		||||
	0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
 | 
			
		||||
	0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
 | 
			
		||||
	0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
 | 
			
		||||
	0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e,
 | 
			
		||||
	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03,
 | 
			
		||||
	0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
 | 
			
		||||
	0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e,
 | 
			
		||||
	0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13, 0x64,
 | 
			
		||||
	0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
 | 
			
		||||
	0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c,
 | 
			
		||||
	0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65,
 | 
			
		||||
	0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20,
 | 
			
		||||
	0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
 | 
			
		||||
	0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
 | 
			
		||||
	0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70,
 | 
			
		||||
	0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20,
 | 
			
		||||
	0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
 | 
			
		||||
	0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03,
 | 
			
		||||
	0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
 | 
			
		||||
	0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06, 0x6e,
 | 
			
		||||
	0x6f, 0x69, 0x73, 0x65, 0x73, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61,
 | 
			
		||||
	0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50,
 | 
			
		||||
	0x01, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
 | 
			
		||||
	0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f,
 | 
			
		||||
	0x78, 0x79, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61,
 | 
			
		||||
	0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62,
 | 
			
		||||
	0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
| 
						 | 
				
			
			@ -507,22 +426,21 @@ func file_proxy_freedom_config_proto_rawDescGZIP() []byte {
 | 
			
		|||
	return file_proxy_freedom_config_proto_rawDescData
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var file_proxy_freedom_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
 | 
			
		||||
var file_proxy_freedom_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
 | 
			
		||||
var file_proxy_freedom_config_proto_goTypes = []any{
 | 
			
		||||
	(Config_DomainStrategy)(0),      // 0: xray.proxy.freedom.Config.DomainStrategy
 | 
			
		||||
	(*DestinationOverride)(nil),     // 1: xray.proxy.freedom.DestinationOverride
 | 
			
		||||
	(*Fragment)(nil),                // 2: xray.proxy.freedom.Fragment
 | 
			
		||||
	(*Noise)(nil),                   // 3: xray.proxy.freedom.Noise
 | 
			
		||||
	(*Config)(nil),                  // 4: xray.proxy.freedom.Config
 | 
			
		||||
	(*protocol.ServerEndpoint)(nil), // 5: xray.common.protocol.ServerEndpoint
 | 
			
		||||
	(*DestinationOverride)(nil),     // 0: xray.proxy.freedom.DestinationOverride
 | 
			
		||||
	(*Fragment)(nil),                // 1: xray.proxy.freedom.Fragment
 | 
			
		||||
	(*Noise)(nil),                   // 2: xray.proxy.freedom.Noise
 | 
			
		||||
	(*Config)(nil),                  // 3: xray.proxy.freedom.Config
 | 
			
		||||
	(*protocol.ServerEndpoint)(nil), // 4: xray.common.protocol.ServerEndpoint
 | 
			
		||||
	(internet.DomainStrategy)(0),    // 5: xray.transport.internet.DomainStrategy
 | 
			
		||||
}
 | 
			
		||||
var file_proxy_freedom_config_proto_depIdxs = []int32{
 | 
			
		||||
	5, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
 | 
			
		||||
	0, // 1: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.proxy.freedom.Config.DomainStrategy
 | 
			
		||||
	1, // 2: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
 | 
			
		||||
	2, // 3: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
 | 
			
		||||
	3, // 4: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
 | 
			
		||||
	4, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
 | 
			
		||||
	5, // 1: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
 | 
			
		||||
	0, // 2: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
 | 
			
		||||
	1, // 3: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
 | 
			
		||||
	2, // 4: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
 | 
			
		||||
	5, // [5:5] is the sub-list for method output_type
 | 
			
		||||
	5, // [5:5] is the sub-list for method input_type
 | 
			
		||||
	5, // [5:5] is the sub-list for extension type_name
 | 
			
		||||
| 
						 | 
				
			
			@ -540,14 +458,13 @@ func file_proxy_freedom_config_proto_init() {
 | 
			
		|||
		File: protoimpl.DescBuilder{
 | 
			
		||||
			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 | 
			
		||||
			RawDescriptor: file_proxy_freedom_config_proto_rawDesc,
 | 
			
		||||
			NumEnums:      1,
 | 
			
		||||
			NumEnums:      0,
 | 
			
		||||
			NumMessages:   4,
 | 
			
		||||
			NumExtensions: 0,
 | 
			
		||||
			NumServices:   0,
 | 
			
		||||
		},
 | 
			
		||||
		GoTypes:           file_proxy_freedom_config_proto_goTypes,
 | 
			
		||||
		DependencyIndexes: file_proxy_freedom_config_proto_depIdxs,
 | 
			
		||||
		EnumInfos:         file_proxy_freedom_config_proto_enumTypes,
 | 
			
		||||
		MessageInfos:      file_proxy_freedom_config_proto_msgTypes,
 | 
			
		||||
	}.Build()
 | 
			
		||||
	File_proxy_freedom_config_proto = out.File
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ option java_package = "com.xray.proxy.freedom";
 | 
			
		|||
option java_multiple_files = true;
 | 
			
		||||
 | 
			
		||||
import "common/protocol/server_spec.proto";
 | 
			
		||||
import "transport/internet/config.proto";
 | 
			
		||||
 | 
			
		||||
message DestinationOverride {
 | 
			
		||||
  xray.common.protocol.ServerEndpoint server = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -32,20 +33,7 @@ message Noise {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
message Config {
 | 
			
		||||
  enum DomainStrategy {
 | 
			
		||||
    AS_IS = 0;
 | 
			
		||||
    USE_IP = 1;
 | 
			
		||||
    USE_IP4 = 2;
 | 
			
		||||
    USE_IP6 = 3;
 | 
			
		||||
    USE_IP46 = 4;
 | 
			
		||||
    USE_IP64 = 5;
 | 
			
		||||
    FORCE_IP = 6;
 | 
			
		||||
    FORCE_IP4 = 7;
 | 
			
		||||
    FORCE_IP6 = 8;
 | 
			
		||||
    FORCE_IP46 = 9;
 | 
			
		||||
    FORCE_IP64 = 10;
 | 
			
		||||
  }
 | 
			
		||||
  DomainStrategy domain_strategy = 1;
 | 
			
		||||
  xray.transport.internet.DomainStrategy domain_strategy = 1;
 | 
			
		||||
  DestinationOverride destination_override = 3;
 | 
			
		||||
  uint32 user_level = 4;
 | 
			
		||||
  Fragment fragment = 5;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,6 @@ import (
 | 
			
		|||
	"github.com/xtls/xray-core/common/task"
 | 
			
		||||
	"github.com/xtls/xray-core/common/utils"
 | 
			
		||||
	"github.com/xtls/xray-core/core"
 | 
			
		||||
	"github.com/xtls/xray-core/features/dns"
 | 
			
		||||
	"github.com/xtls/xray-core/features/policy"
 | 
			
		||||
	"github.com/xtls/xray-core/features/stats"
 | 
			
		||||
	"github.com/xtls/xray-core/proxy"
 | 
			
		||||
| 
						 | 
				
			
			@ -35,8 +34,8 @@ var useSplice bool
 | 
			
		|||
func init() {
 | 
			
		||||
	common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
 | 
			
		||||
		h := new(Handler)
 | 
			
		||||
		if err := core.RequireFeatures(ctx, func(pm policy.Manager, d dns.Client) error {
 | 
			
		||||
			return h.Init(config.(*Config), pm, d)
 | 
			
		||||
		if err := core.RequireFeatures(ctx, func(pm policy.Manager) error {
 | 
			
		||||
			return h.Init(config.(*Config), pm)
 | 
			
		||||
		}); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -53,16 +52,13 @@ func init() {
 | 
			
		|||
// Handler handles Freedom connections.
 | 
			
		||||
type Handler struct {
 | 
			
		||||
	policyManager policy.Manager
 | 
			
		||||
	dns           dns.Client
 | 
			
		||||
	config        *Config
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Init initializes the Handler with necessary parameters.
 | 
			
		||||
func (h *Handler) Init(config *Config, pm policy.Manager, d dns.Client) error {
 | 
			
		||||
func (h *Handler) Init(config *Config, pm policy.Manager) error {
 | 
			
		||||
	h.config = config
 | 
			
		||||
	h.policyManager = pm
 | 
			
		||||
	h.dns = d
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -71,28 +67,6 @@ func (h *Handler) policy() policy.Session {
 | 
			
		|||
	return p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
 | 
			
		||||
	ips, _, err := h.dns.LookupIP(domain, dns.IPOption{
 | 
			
		||||
		IPv4Enable: (localAddr == nil || localAddr.Family().IsIPv4()) && h.config.preferIP4(),
 | 
			
		||||
		IPv6Enable: (localAddr == nil || localAddr.Family().IsIPv6()) && h.config.preferIP6(),
 | 
			
		||||
	})
 | 
			
		||||
	{ // Resolve fallback
 | 
			
		||||
		if (len(ips) == 0 || err != nil) && h.config.hasFallback() && localAddr == nil {
 | 
			
		||||
			ips, _, err = h.dns.LookupIP(domain, dns.IPOption{
 | 
			
		||||
				IPv4Enable: h.config.fallbackIP4(),
 | 
			
		||||
				IPv6Enable: h.config.fallbackIP6(),
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", domain)
 | 
			
		||||
	}
 | 
			
		||||
	if len(ips) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return net.IPAddress(ips[dice.Roll(len(ips))])
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isValidAddress(addr *net.IPOrDomain) bool {
 | 
			
		||||
	if addr == nil {
 | 
			
		||||
		return false
 | 
			
		||||
| 
						 | 
				
			
			@ -114,6 +88,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
 | 
			
		|||
	inbound := session.InboundFromContext(ctx)
 | 
			
		||||
 | 
			
		||||
	destination := ob.Target
 | 
			
		||||
	origTargetAddr := ob.OriginalTarget.Address
 | 
			
		||||
	if origTargetAddr == nil {
 | 
			
		||||
		origTargetAddr = ob.Target.Address
 | 
			
		||||
	}
 | 
			
		||||
	dialer.SetOutboundGateway(ctx, ob)
 | 
			
		||||
	outGateway := ob.Gateway
 | 
			
		||||
	UDPOverride := net.UDPDestination(nil, 0)
 | 
			
		||||
	if h.config.DestinationOverride != nil {
 | 
			
		||||
		server := h.config.DestinationOverride.Server
 | 
			
		||||
| 
						 | 
				
			
			@ -133,17 +113,24 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
 | 
			
		|||
	var conn stat.Connection
 | 
			
		||||
	err := retry.ExponentialBackoff(5, 100).On(func() error {
 | 
			
		||||
		dialDest := destination
 | 
			
		||||
		if h.config.hasStrategy() && dialDest.Address.Family().IsDomain() {
 | 
			
		||||
			ip := h.resolveIP(ctx, dialDest.Address.Domain(), dialer.Address())
 | 
			
		||||
			if ip != nil {
 | 
			
		||||
		if h.config.DomainStrategy.HasStrategy() && dialDest.Address.Family().IsDomain() {
 | 
			
		||||
			strategy := h.config.DomainStrategy
 | 
			
		||||
			if destination.Network == net.Network_UDP && origTargetAddr != nil && outGateway == nil {
 | 
			
		||||
				strategy = strategy.GetDynamicStrategy(origTargetAddr.Family())
 | 
			
		||||
			}
 | 
			
		||||
			ips, err := internet.LookupForIP(dialDest.Address.Domain(), strategy, outGateway)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", dialDest.Address.Domain())
 | 
			
		||||
				if h.config.DomainStrategy.ForceIP() {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				dialDest = net.Destination{
 | 
			
		||||
					Network: dialDest.Network,
 | 
			
		||||
					Address: ip,
 | 
			
		||||
					Address: net.IPAddress(ips[dice.Roll(len(ips))]),
 | 
			
		||||
					Port:    dialDest.Port,
 | 
			
		||||
				}
 | 
			
		||||
				errors.LogInfo(ctx, "dialing to ", dialDest)
 | 
			
		||||
			} else if h.config.forceIP() {
 | 
			
		||||
				return dns.ErrEmptyResponse
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -203,7 +190,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
 | 
			
		|||
				writer = buf.NewWriter(conn)
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			writer = NewPacketWriter(conn, h, ctx, UDPOverride, destination)
 | 
			
		||||
			writer = NewPacketWriter(conn, h, UDPOverride, destination)
 | 
			
		||||
			if h.config.Noises != nil {
 | 
			
		||||
				errors.LogDebug(ctx, "NOISE", h.config.Noises)
 | 
			
		||||
				writer = &NoisePacketWriter{
 | 
			
		||||
| 
						 | 
				
			
			@ -339,7 +326,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// DialDest means the dial target used in the dialer when creating conn
 | 
			
		||||
func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination, DialDest net.Destination) buf.Writer {
 | 
			
		||||
func NewPacketWriter(conn net.Conn, h *Handler, UDPOverride net.Destination, DialDest net.Destination) buf.Writer {
 | 
			
		||||
	iConn := conn
 | 
			
		||||
	statConn, ok := iConn.(*stat.CounterConnection)
 | 
			
		||||
	if ok {
 | 
			
		||||
| 
						 | 
				
			
			@ -360,9 +347,9 @@ func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride
 | 
			
		|||
			PacketConnWrapper: c,
 | 
			
		||||
			Counter:           counter,
 | 
			
		||||
			Handler:           h,
 | 
			
		||||
			Context:           ctx,
 | 
			
		||||
			UDPOverride:       UDPOverride,
 | 
			
		||||
			resolvedUDPAddr:   resolvedUDPAddr,
 | 
			
		||||
			ResolvedUDPAddr:   resolvedUDPAddr,
 | 
			
		||||
			LocalAddr:         net.DestinationFromAddr(conn.LocalAddr()).Address,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -373,14 +360,14 @@ type PacketWriter struct {
 | 
			
		|||
	*internet.PacketConnWrapper
 | 
			
		||||
	stats.Counter
 | 
			
		||||
	*Handler
 | 
			
		||||
	context.Context
 | 
			
		||||
	UDPOverride net.Destination
 | 
			
		||||
 | 
			
		||||
	// Dest of udp packets might be a domain, we will resolve them to IP
 | 
			
		||||
	// But resolver will return a random one if the domain has many IPs
 | 
			
		||||
	// Resulting in these packets being sent to many different IPs randomly
 | 
			
		||||
	// So, cache and keep the resolve result
 | 
			
		||||
	resolvedUDPAddr *utils.TypedSyncMap[string, net.Address]
 | 
			
		||||
	ResolvedUDPAddr *utils.TypedSyncMap[string, net.Address]
 | 
			
		||||
	LocalAddr       net.Address
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
 | 
			
		||||
| 
						 | 
				
			
			@ -400,20 +387,22 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
 | 
			
		|||
				b.UDP.Port = w.UDPOverride.Port
 | 
			
		||||
			}
 | 
			
		||||
			if b.UDP.Address.Family().IsDomain() {
 | 
			
		||||
				if ip, ok := w.resolvedUDPAddr.Load(b.UDP.Address.Domain()); ok {
 | 
			
		||||
				if ip, ok := w.ResolvedUDPAddr.Load(b.UDP.Address.Domain()); ok {
 | 
			
		||||
					b.UDP.Address = ip
 | 
			
		||||
				} else {
 | 
			
		||||
					ShouldUseSystemResolver := true
 | 
			
		||||
					if w.Handler.config.hasStrategy() {
 | 
			
		||||
						ip = w.Handler.resolveIP(w.Context, b.UDP.Address.Domain(), nil)
 | 
			
		||||
						if ip != nil {
 | 
			
		||||
					if w.Handler.config.DomainStrategy.HasStrategy() {
 | 
			
		||||
						ips, err := internet.LookupForIP(b.UDP.Address.Domain(), w.Handler.config.DomainStrategy, w.LocalAddr)
 | 
			
		||||
						if err != nil {
 | 
			
		||||
							// drop packet if resolve failed when forceIP
 | 
			
		||||
							if w.Handler.config.DomainStrategy.ForceIP() {
 | 
			
		||||
								b.Release()
 | 
			
		||||
								continue
 | 
			
		||||
							}
 | 
			
		||||
						} else {
 | 
			
		||||
							ip = net.IPAddress(ips[dice.Roll(len(ips))])
 | 
			
		||||
							ShouldUseSystemResolver = false
 | 
			
		||||
						}
 | 
			
		||||
						// drop packet if resolve failed when forceIP
 | 
			
		||||
						if ip == nil && w.Handler.config.forceIP() {
 | 
			
		||||
							b.Release()
 | 
			
		||||
							continue
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if ShouldUseSystemResolver {
 | 
			
		||||
						udpAddr, err := net.ResolveUDPAddr("udp", b.UDP.NetAddr())
 | 
			
		||||
| 
						 | 
				
			
			@ -425,7 +414,7 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
 | 
			
		|||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if ip != nil {
 | 
			
		||||
						b.UDP.Address, _ = w.resolvedUDPAddr.LoadOrStore(b.UDP.Address.Domain(), ip)
 | 
			
		||||
						b.UDP.Address, _ = w.ResolvedUDPAddr.LoadOrStore(b.UDP.Address.Domain(), ip)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -496,7 +485,10 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
 | 
			
		|||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
			w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
 | 
			
		||||
			err = w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if n.DelayMin != 0 || n.DelayMax != 0 {
 | 
			
		||||
				time.Sleep(time.Duration(crypto.RandBetween(int64(n.DelayMin), int64(n.DelayMax))) * time.Millisecond)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ import (
 | 
			
		|||
	"github.com/xtls/xray-core/proxy/freedom"
 | 
			
		||||
	"github.com/xtls/xray-core/proxy/socks"
 | 
			
		||||
	"github.com/xtls/xray-core/testing/servers/tcp"
 | 
			
		||||
	"github.com/xtls/xray-core/transport/internet"
 | 
			
		||||
	xproxy "golang.org/x/net/proxy"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,7 +84,7 @@ func TestResolveIP(t *testing.T) {
 | 
			
		|||
			{
 | 
			
		||||
				Tag: "direct",
 | 
			
		||||
				ProxySettings: serial.ToTypedMessage(&freedom.Config{
 | 
			
		||||
					DomainStrategy: freedom.Config_USE_IP,
 | 
			
		||||
					DomainStrategy: internet.DomainStrategy_USE_IP,
 | 
			
		||||
				}),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,6 +2,7 @@ package internet
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/xtls/xray-core/common/errors"
 | 
			
		||||
	"github.com/xtls/xray-core/common/net"
 | 
			
		||||
	"github.com/xtls/xray-core/common/serial"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -127,3 +128,25 @@ func (s DomainStrategy) FallbackIP4() bool {
 | 
			
		|||
func (s DomainStrategy) FallbackIP6() bool {
 | 
			
		||||
	return strategy[s][2] == 6
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s DomainStrategy) GetDynamicStrategy(addrFamily net.AddressFamily) DomainStrategy {
 | 
			
		||||
	if  addrFamily.IsDomain(){
 | 
			
		||||
		return s
 | 
			
		||||
	}
 | 
			
		||||
	switch s {
 | 
			
		||||
	case DomainStrategy_USE_IP:
 | 
			
		||||
		if addrFamily.IsIPv4() {
 | 
			
		||||
			return DomainStrategy_USE_IP46
 | 
			
		||||
		} else if addrFamily.IsIPv6() {
 | 
			
		||||
			return DomainStrategy_USE_IP64
 | 
			
		||||
		}
 | 
			
		||||
	case DomainStrategy_FORCE_IP:
 | 
			
		||||
		if addrFamily.IsIPv4() {
 | 
			
		||||
			return DomainStrategy_FORCE_IP46
 | 
			
		||||
		} else if addrFamily.IsIPv6() {
 | 
			
		||||
			return DomainStrategy_FORCE_IP64
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
	}
 | 
			
		||||
	return s
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,11 +24,11 @@ type Dialer interface {
 | 
			
		|||
	// Dial dials a system connection to the given destination.
 | 
			
		||||
	Dial(ctx context.Context, destination net.Destination) (stat.Connection, error)
 | 
			
		||||
 | 
			
		||||
	// Address returns the address used by this Dialer. Maybe nil if not known.
 | 
			
		||||
	Address() net.Address
 | 
			
		||||
 | 
			
		||||
	// DestIpAddress returns the ip of proxy server. It is useful in case of Android client, which prepare an IP before proxy connection is established
 | 
			
		||||
	DestIpAddress() net.IP
 | 
			
		||||
 | 
			
		||||
	// SetOutboundGateway set outbound gateway
 | 
			
		||||
	SetOutboundGateway(ctx context.Context, ob *session.Outbound)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// dialFunc is an interface to dial network connection to a specific destination.
 | 
			
		||||
| 
						 | 
				
			
			@ -91,8 +91,8 @@ func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{
 | 
			
		||||
		IPv4Enable: (localAddr == nil || localAddr.Family().IsIPv4()) && strategy.PreferIP4(),
 | 
			
		||||
		IPv6Enable: (localAddr == nil || localAddr.Family().IsIPv6()) && strategy.PreferIP6(),
 | 
			
		||||
		IPv4Enable: (localAddr == nil && strategy.PreferIP4()) || (localAddr != nil && localAddr.Family().IsIPv4() && (strategy.PreferIP4() || strategy.FallbackIP4())),
 | 
			
		||||
		IPv6Enable: (localAddr == nil && strategy.PreferIP6()) || (localAddr != nil && localAddr.Family().IsIPv6() && (strategy.PreferIP6() || strategy.FallbackIP6())),
 | 
			
		||||
	})
 | 
			
		||||
	{ // Resolve fallback
 | 
			
		||||
		if (len(ips) == 0 || err != nil) && strategy.HasFallback() && localAddr == nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -109,13 +109,6 @@ func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address)
 | 
			
		|||
	return ips, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func canLookupIP(dst net.Destination, sockopt *SocketConfig) bool {
 | 
			
		||||
	if dst.Address.Family().IsIP() {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return sockopt.DomainStrategy.HasStrategy()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func redirect(ctx context.Context, dst net.Destination, obt string, h outbound.Handler) net.Conn {
 | 
			
		||||
	errors.LogInfo(ctx, "redirecting request "+dst.String()+" to "+obt)
 | 
			
		||||
	outbounds := session.OutboundsFromContext(ctx)
 | 
			
		||||
| 
						 | 
				
			
			@ -235,9 +228,18 @@ func checkAddressPortStrategy(ctx context.Context, dest net.Destination, sockopt
 | 
			
		|||
func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
 | 
			
		||||
	var src net.Address
 | 
			
		||||
	outbounds := session.OutboundsFromContext(ctx)
 | 
			
		||||
	var outboundName string
 | 
			
		||||
	var origTargetAddr net.Address
 | 
			
		||||
	if len(outbounds) > 0 {
 | 
			
		||||
		ob := outbounds[len(outbounds)-1]
 | 
			
		||||
		src = ob.Gateway
 | 
			
		||||
		if sockopt == nil || len(sockopt.DialerProxy) == 0 {
 | 
			
		||||
			src = ob.Gateway
 | 
			
		||||
		}
 | 
			
		||||
		outboundName = ob.Name
 | 
			
		||||
		origTargetAddr = ob.OriginalTarget.Address
 | 
			
		||||
		if origTargetAddr == nil {
 | 
			
		||||
			origTargetAddr = ob.Target.Address
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if sockopt == nil {
 | 
			
		||||
		return effectiveSystemDialer.Dial(ctx, src, dest, sockopt)
 | 
			
		||||
| 
						 | 
				
			
			@ -248,8 +250,12 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
 | 
			
		|||
		dest = *newDest
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if canLookupIP(dest, sockopt) {
 | 
			
		||||
		ips, err := LookupForIP(dest.Address.String(), sockopt.DomainStrategy, src)
 | 
			
		||||
	if sockopt.DomainStrategy.HasStrategy() && dest.Address.Family().IsDomain() {
 | 
			
		||||
		finalStrategy := sockopt.DomainStrategy
 | 
			
		||||
		if outboundName == "freedom" && dest.Network == net.Network_UDP && origTargetAddr != nil && src == nil {
 | 
			
		||||
			finalStrategy = finalStrategy.GetDynamicStrategy(origTargetAddr.Family())
 | 
			
		||||
		}
 | 
			
		||||
		ips, err := LookupForIP(dest.Address.Domain(), finalStrategy, src)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			errors.LogErrorInner(ctx, err, "failed to resolve ip")
 | 
			
		||||
			if sockopt.DomainStrategy.ForceIP() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue