From db32ce6fd9d25ff6c4c84fe90af752ca9ec5b306 Mon Sep 17 00:00:00 2001 From: Jim Han <50871214+JimhHan@users.noreply.github.com> Date: Sun, 7 Mar 2021 00:29:17 +0800 Subject: [PATCH] Enhance DNS and Dialer (#341) --- app/dns/dohdns.go | 95 +++++---- app/dns/server.go | 2 + app/dns/udpns.go | 12 ++ app/log/config.pb.go | 30 ++- app/log/config.proto | 1 + app/log/log.go | 6 + common/log/dns.go | 59 ++++++ core/config.pb.go | 8 +- core/xray.go | 9 + infra/conf/log.go | 2 + infra/conf/transport.go | 6 +- infra/conf/transport_internet.go | 20 +- infra/conf/transport_test.go | 14 +- infra/conf/xray.go | 26 +++ transport/config.pb.go | 165 --------------- transport/{ => global}/config.go | 2 +- transport/global/config.pb.go | 167 +++++++++++++++ transport/{ => global}/config.proto | 6 +- transport/internet/config.pb.go | 216 ++++++++++++++------ transport/internet/config.proto | 15 +- transport/internet/system_dialer.go | 93 +++++++++ transport/internet/system_dialer_context.go | 18 ++ 22 files changed, 682 insertions(+), 290 deletions(-) create mode 100644 common/log/dns.go delete mode 100644 transport/config.pb.go rename transport/{ => global}/config.go (92%) create mode 100644 transport/global/config.pb.go rename transport/{ => global}/config.proto (69%) create mode 100644 transport/internet/system_dialer_context.go diff --git a/app/dns/dohdns.go b/app/dns/dohdns.go index 9d94d125..85fc6967 100644 --- a/app/dns/dohdns.go +++ b/app/dns/dohdns.go @@ -13,6 +13,7 @@ import ( "time" "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net/cnc" "github.com/xtls/xray-core/common/protocol/dns" @@ -47,6 +48,56 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, clientIP net. s := baseDOHNameServer(url, "DOH", clientIP) s.dispatcher = dispatcher + tr := &http.Transport{ + MaxIdleConns: 30, + IdleConnTimeout: 90 * time.Second, + TLSHandshakeTimeout: 30 * time.Second, + ForceAttemptHTTP2: true, + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + dispatcherCtx := context.Background() + if inbound := session.InboundFromContext(ctx); inbound != nil { + dispatcherCtx = session.ContextWithInbound(dispatcherCtx, inbound) + } + if content := session.ContentFromContext(ctx); content != nil { + dispatcherCtx = session.ContextWithContent(dispatcherCtx, content) + } + dispatcherCtx = internet.ContextWithLookupDomain(dispatcherCtx, internet.LookupDomainFromContext(ctx)) + + dest, err := net.ParseDestination(network + ":" + addr) + if err != nil { + return nil, err + } + + dispatcherCtx = log.ContextWithAccessMessage(dispatcherCtx, &log.AccessMessage{ + From: "DoH", + To: s.dohURL, + Status: log.AccessAccepted, + Reason: "", + }) + + link, err := s.dispatcher.Dispatch(dispatcherCtx, dest) + if err != nil { + return nil, err + } + + cc := common.ChainedClosable{} + if cw, ok := link.Writer.(common.Closable); ok { + cc = append(cc, cw) + } + if cr, ok := link.Reader.(common.Closable); ok { + cc = append(cc, cr) + } + return cnc.NewConnection( + cnc.ConnectionInputMulti(link.Writer), + cnc.ConnectionOutputMulti(link.Reader), + cnc.ConnectionOnClose(cc), + ), nil + }, + } + s.httpClient = &http.Client{ + Timeout: time.Second * 180, + Transport: tr, + } return s, nil } @@ -64,6 +115,12 @@ func NewDoHLocalNameServer(url *url.URL, clientIP net.IP) *DoHNameServer { return nil, err } conn, err := internet.DialSystem(ctx, dest, nil) + log.Record(&log.AccessMessage{ + From: "DoH", + To: s.dohURL, + Status: log.AccessAccepted, + Detour: "local", + }) if err != nil { return nil, err } @@ -249,41 +306,6 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte, hc := s.httpClient - // Dispatched connection will be closed (interrupted) after each request - // This makes DOH inefficient without a keep-alived connection - // See: core/app/proxyman/outbound/handler.go:113 - // Using mux (https request wrapped in a stream layer) improves the situation. - // Recommend to use NewDoHLocalNameServer (DOHL:) if xray instance is running on - // a normal network eg. the server side of xray - - if s.dispatcher != nil { - tr := &http.Transport{ - MaxIdleConns: 30, - IdleConnTimeout: 90 * time.Second, - TLSHandshakeTimeout: 30 * time.Second, - ForceAttemptHTTP2: true, - DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { - dest, err := net.ParseDestination(network + ":" + addr) - if err != nil { - return nil, err - } - - link, err := s.dispatcher.Dispatch(ctx, dest) - if err != nil { - return nil, err - } - return cnc.NewConnection( - cnc.ConnectionInputMulti(link.Writer), - cnc.ConnectionOutputMulti(link.Reader), - ), nil - }, - } - hc = &http.Client{ - Timeout: time.Second * 180, - Transport: tr, - } - } - resp, err := hc.Do(req.WithContext(ctx)) if err != nil { return nil, err @@ -347,6 +369,7 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option IPOpt ips, err := s.findIPsForDomain(fqdn, option) if err != errRecordNotFound { newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() + log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err}) return ips, err } @@ -377,10 +400,12 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option IPOpt close(done) }() s.sendQuery(ctx, fqdn, option) + start := time.Now() for { ips, err := s.findIPsForDomain(fqdn, option) if err != errRecordNotFound { + log.Record(&log.DNSLog{s.name, domain, ips, log.DNSQueried, time.Since(start), err}) return ips, err } diff --git a/app/dns/server.go b/app/dns/server.go index 82f9d23e..1c2796e6 100644 --- a/app/dns/server.go +++ b/app/dns/server.go @@ -22,6 +22,7 @@ import ( "github.com/xtls/xray-core/features" "github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/routing" + "github.com/xtls/xray-core/transport/internet" ) // Server is a DNS rely server. @@ -301,6 +302,7 @@ func (s *Server) queryIPTimeout(idx int, client Client, domain string, option IP Tag: s.tag, }) } + ctx = internet.ContextWithLookupDomain(ctx, Fqdn(domain)) ips, err := client.QueryIP(ctx, domain, option) cancel() diff --git a/app/dns/udpns.go b/app/dns/udpns.go index 8dde08e7..06d834bc 100644 --- a/app/dns/udpns.go +++ b/app/dns/udpns.go @@ -2,12 +2,14 @@ package dns import ( "context" + "github.com/xtls/xray-core/transport/internet" "strings" "sync" "sync/atomic" "time" "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/protocol/dns" udp_proto "github.com/xtls/xray-core/common/protocol/udp" @@ -190,9 +192,16 @@ func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, option if inbound := session.InboundFromContext(ctx); inbound != nil { udpCtx = session.ContextWithInbound(udpCtx, inbound) } + udpCtx = internet.ContextWithLookupDomain(udpCtx, internet.LookupDomainFromContext(ctx)) udpCtx = session.ContextWithContent(udpCtx, &session.Content{ Protocol: "dns", }) + udpCtx = log.ContextWithAccessMessage(udpCtx, &log.AccessMessage{ + From: "DNS", + To: s.address, + Status: log.AccessAccepted, + Reason: "", + }) s.udpServer.Dispatch(udpCtx, s.address, b) } } @@ -241,6 +250,7 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option I ips, err := s.findIPsForDomain(fqdn, option) if err != errRecordNotFound { newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog() + log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err}) return ips, err } @@ -271,10 +281,12 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option I close(done) }() s.sendQuery(ctx, fqdn, option) + start := time.Now() for { ips, err := s.findIPsForDomain(fqdn, option) if err != errRecordNotFound { + log.Record(&log.DNSLog{s.name, domain, ips, log.DNSQueried, time.Since(start), err}) return ips, err } diff --git a/app/log/config.pb.go b/app/log/config.pb.go index 85463847..bc0e4946 100644 --- a/app/log/config.pb.go +++ b/app/log/config.pb.go @@ -88,6 +88,7 @@ type Config struct { ErrorLogPath string `protobuf:"bytes,3,opt,name=error_log_path,json=errorLogPath,proto3" json:"error_log_path,omitempty"` AccessLogType LogType `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,proto3,enum=xray.app.log.LogType" json:"access_log_type,omitempty"` AccessLogPath string `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath,proto3" json:"access_log_path,omitempty"` + EnableDnsLog bool `protobuf:"varint,6,opt,name=enable_dns_log,json=enableDnsLog,proto3" json:"enable_dns_log,omitempty"` } func (x *Config) Reset() { @@ -157,13 +158,20 @@ func (x *Config) GetAccessLogPath() string { return "" } +func (x *Config) GetEnableDnsLog() bool { + if x != nil { + return x.EnableDnsLog + } + return false +} + var File_app_log_config_proto protoreflect.FileDescriptor var file_app_log_config_proto_rawDesc = []byte{ 0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x1a, 0x14, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6c, 0x6f, 0x67, - 0x2f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x95, 0x02, 0x0a, 0x06, 0x43, + 0x2f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x4c, 0x6f, 0x67, @@ -181,15 +189,17 @@ var file_app_log_config_proto_rawDesc = []byte{ 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x50, 0x61, - 0x74, 0x68, 0x2a, 0x35, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, - 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, - 0x6c, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, - 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x10, 0x03, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, - 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x50, 0x01, 0x5a, - 0x21, 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, 0x61, 0x70, 0x70, 0x2f, 0x6c, - 0x6f, 0x67, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, - 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x6e, 0x73, + 0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x44, 0x6e, 0x73, 0x4c, 0x6f, 0x67, 0x2a, 0x35, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x0b, 0x0a, + 0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x69, + 0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x10, 0x03, 0x42, + 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, + 0x6c, 0x6f, 0x67, 0x50, 0x01, 0x5a, 0x21, 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, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, + 0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/app/log/config.proto b/app/log/config.proto index 401e727c..47e010d2 100644 --- a/app/log/config.proto +++ b/app/log/config.proto @@ -22,4 +22,5 @@ message Config { LogType access_log_type = 4; string access_log_path = 5; + bool enable_dns_log = 6; } diff --git a/app/log/log.go b/app/log/log.go index dc729136..7cdd5390 100644 --- a/app/log/log.go +++ b/app/log/log.go @@ -17,6 +17,7 @@ type Instance struct { accessLogger log.Handler errorLogger log.Handler active bool + dns bool } // New creates a new log.Instance based on the given config. @@ -24,6 +25,7 @@ func New(ctx context.Context, config *Config) (*Instance, error) { g := &Instance{ config: config, active: false, + dns: config.EnableDnsLog, } log.RegisterHandler(g) @@ -103,6 +105,10 @@ func (g *Instance) Handle(msg log.Message) { if g.accessLogger != nil { g.accessLogger.Handle(msg) } + case *log.DNSLog: + if g.dns && g.accessLogger != nil { + g.accessLogger.Handle(msg) + } case *log.GeneralMessage: if g.errorLogger != nil && msg.Severity <= g.config.ErrorLogLevel { g.errorLogger.Handle(msg) diff --git a/common/log/dns.go b/common/log/dns.go new file mode 100644 index 00000000..76f5bbe3 --- /dev/null +++ b/common/log/dns.go @@ -0,0 +1,59 @@ +package log + +import ( + "net" + "strings" + "time" +) + +type DNSLog struct { + Server string + Domain string + Result []net.IP + Status dnsStatus + Elapsed time.Duration + Error error +} + +func (l *DNSLog) String() string { + builder := &strings.Builder{} + + // Server got answer: domain -> [ip1, ip2] 23ms + builder.WriteString(l.Server) + builder.WriteString(" ") + builder.WriteString(string(l.Status)) + builder.WriteString(" ") + builder.WriteString(l.Domain) + builder.WriteString(" -> [") + builder.WriteString(joinNetIP(l.Result)) + builder.WriteString("]") + + if l.Elapsed > 0 { + builder.WriteString(" ") + builder.WriteString(l.Elapsed.String()) + } + if l.Error != nil { + builder.WriteString(" <") + builder.WriteString(l.Error.Error()) + builder.WriteString(">") + } + return builder.String() +} + +type dnsStatus string + +var ( + DNSQueried = dnsStatus("got answer:") + DNSCacheHit = dnsStatus("cache HIT:") +) + +func joinNetIP(ips []net.IP) string { + if len(ips) == 0 { + return "" + } + sips := make([]string, 0, len(ips)) + for _, ip := range ips { + sips = append(sips, ip.String()) + } + return strings.Join(sips, ", ") +} diff --git a/core/config.pb.go b/core/config.pb.go index de3d26a2..29cffafa 100644 --- a/core/config.pb.go +++ b/core/config.pb.go @@ -9,7 +9,7 @@ package core import ( proto "github.com/golang/protobuf/proto" serial "github.com/xtls/xray-core/common/serial" - transport "github.com/xtls/xray-core/transport" + "github.com/xtls/xray-core/transport/global" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" @@ -48,7 +48,7 @@ type Config struct { // config. Date to remove: 2020-01-13 // // Deprecated: Do not use. - Transport *transport.Config `protobuf:"bytes,5,opt,name=transport,proto3" json:"transport,omitempty"` + Transport *global.Config `protobuf:"bytes,5,opt,name=transport,proto3" json:"transport,omitempty"` // Configuration for extensions. The config may not work if corresponding // extension is not loaded into Xray. Xray will ignore such config during // initialization. @@ -109,7 +109,7 @@ func (x *Config) GetApp() []*serial.TypedMessage { } // Deprecated: Do not use. -func (x *Config) GetTransport() *transport.Config { +func (x *Config) GetTransport() *global.Config { if x != nil { return x.Transport } @@ -356,7 +356,7 @@ var file_core_config_proto_goTypes = []interface{}{ (*InboundHandlerConfig)(nil), // 1: xray.core.InboundHandlerConfig (*OutboundHandlerConfig)(nil), // 2: xray.core.OutboundHandlerConfig (*serial.TypedMessage)(nil), // 3: xray.common.serial.TypedMessage - (*transport.Config)(nil), // 4: xray.transport.Config + (*global.Config)(nil), // 4: xray.transport.Config } var file_core_config_proto_depIdxs = []int32{ 1, // 0: xray.core.Config.inbound:type_name -> xray.core.InboundHandlerConfig diff --git a/core/xray.go b/core/xray.go index fd8e5c4e..c18a3101 100644 --- a/core/xray.go +++ b/core/xray.go @@ -16,6 +16,7 @@ import ( "github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/stats" + "github.com/xtls/xray-core/transport/internet" ) // Server is an instance of Xray. At any time, there must be at most one Server instance running. @@ -223,6 +224,14 @@ func initInstanceWithConfig(config *Config, server *Instance) (bool, error) { } } + internet.InitSystemDialer( + server.GetFeature(dns.ClientType()).(dns.Client), + func() outbound.Manager { + obm, _ := server.GetFeature(outbound.ManagerType()).(outbound.Manager) + return obm + }(), + ) + if server.featureResolutions != nil { return true, newError("not all dependency are resolved.") } diff --git a/infra/conf/log.go b/infra/conf/log.go index 932a9b25..14f2a694 100644 --- a/infra/conf/log.go +++ b/infra/conf/log.go @@ -19,6 +19,7 @@ type LogConfig struct { AccessLog string `json:"access"` ErrorLog string `json:"error"` LogLevel string `json:"loglevel"` + DNSLog bool `json:"dnsLog"` } func (v *LogConfig) Build() *log.Config { @@ -28,6 +29,7 @@ func (v *LogConfig) Build() *log.Config { config := &log.Config{ ErrorLogType: log.LogType_Console, AccessLogType: log.LogType_Console, + EnableDnsLog: v.DNSLog, } if v.AccessLog == "none" { diff --git a/infra/conf/transport.go b/infra/conf/transport.go index 69d74832..1108167b 100644 --- a/infra/conf/transport.go +++ b/infra/conf/transport.go @@ -2,7 +2,7 @@ package conf import ( "github.com/xtls/xray-core/common/serial" - "github.com/xtls/xray-core/transport" + "github.com/xtls/xray-core/transport/global" "github.com/xtls/xray-core/transport/internet" ) @@ -16,8 +16,8 @@ type TransportConfig struct { } // Build implements Buildable. -func (c *TransportConfig) Build() (*transport.Config, error) { - config := new(transport.Config) +func (c *TransportConfig) Build() (*global.Config, error) { + config := new(global.Config) if c.TCPConfig != nil { ts, err := c.TCPConfig.Build() diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index bed00dfa..6a7e7694 100644 --- a/infra/conf/transport_internet.go +++ b/infra/conf/transport_internet.go @@ -455,6 +455,8 @@ type SocketConfig struct { TFO interface{} `json:"tcpFastOpen"` TProxy string `json:"tproxy"` AcceptProxyProtocol bool `json:"acceptProxyProtocol"` + DomainStrategy string `json:"domainStrategy"` + DialerProxy string `json:"dialerProxy"` } // Build implements Buildable. @@ -487,11 +489,23 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) { tproxy = internet.SocketConfig_Off } + var dStrategy = internet.DomainStrategy_AS_IS + switch strings.ToLower(c.DomainStrategy) { + case "useip", "use_ip": + dStrategy = internet.DomainStrategy_USE_IP + case "useip4", "useipv4", "use_ipv4", "use_ip_v4", "use_ip4": + dStrategy = internet.DomainStrategy_USE_IP4 + case "useip6", "useipv6", "use_ipv6", "use_ip_v6", "use_ip6": + dStrategy = internet.DomainStrategy_USE_IP6 + } + return &internet.SocketConfig{ Mark: c.Mark, Tfo: tfo, Tproxy: tproxy, + DomainStrategy: dStrategy, AcceptProxyProtocol: c.AcceptProxyProtocol, + DialerProxy: c.DialerProxy, }, nil } @@ -628,6 +642,9 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) { type ProxyConfig struct { Tag string `json:"tag"` + + // TransportLayerProxy: For compatibility. + TransportLayerProxy bool `json:"transportLayer"` } // Build implements Buildable. @@ -636,6 +653,7 @@ func (v *ProxyConfig) Build() (*internet.ProxyConfig, error) { return nil, newError("Proxy tag is not set.") } return &internet.ProxyConfig{ - Tag: v.Tag, + Tag: v.Tag, + TransportLayerProxy: v.TransportLayerProxy, }, nil } diff --git a/infra/conf/transport_test.go b/infra/conf/transport_test.go index 85531ded..acc15dd0 100644 --- a/infra/conf/transport_test.go +++ b/infra/conf/transport_test.go @@ -8,7 +8,7 @@ import ( "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/serial" . "github.com/xtls/xray-core/infra/conf" - "github.com/xtls/xray-core/transport" + "github.com/xtls/xray-core/transport/global" "github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet/headers/http" "github.com/xtls/xray-core/transport/internet/headers/noop" @@ -34,12 +34,16 @@ func TestSocketConfig(t *testing.T) { { Input: `{ "mark": 1, - "tcpFastOpen": true + "tcpFastOpen": true, + "domainStrategy": "UseIP", + "dialerProxy": "tag" }`, Parser: createParser(), Output: &internet.SocketConfig{ - Mark: 1, - Tfo: 256, + Mark: 1, + Tfo: 256, + DomainStrategy: internet.DomainStrategy_USE_IP, + DialerProxy: "tag", }, }, }) @@ -119,7 +123,7 @@ func TestTransportConfig(t *testing.T) { } }`, Parser: createParser(), - Output: &transport.Config{ + Output: &global.Config{ TransportSettings: []*internet.TransportConfig{ { ProtocolName: "tcp", diff --git a/infra/conf/xray.go b/infra/conf/xray.go index e21018a5..948112f5 100644 --- a/infra/conf/xray.go +++ b/infra/conf/xray.go @@ -2,6 +2,7 @@ package conf import ( "encoding/json" + "github.com/xtls/xray-core/transport/internet" "log" "os" "strings" @@ -267,9 +268,22 @@ type OutboundDetourConfig struct { MuxSettings *MuxConfig `json:"mux"` } +func (c *OutboundDetourConfig) checkChainProxyConfig() error { + if c.StreamSetting == nil || c.ProxySettings == nil || c.StreamSetting.SocketSettings == nil { + return nil + } + if len(c.ProxySettings.Tag) > 0 && len(c.StreamSetting.SocketSettings.DialerProxy) > 0 { + return newError("proxySettings.tag is conflicted with sockopt.dialerProxy").AtWarning() + } + return nil +} + // Build implements Buildable. func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) { senderSettings := &proxyman.SenderConfig{} + if err := c.checkChainProxyConfig(); err != nil { + return nil, err + } if c.SendThrough != nil { address := c.SendThrough @@ -295,6 +309,18 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) { if err != nil { return nil, newError("invalid outbound detour proxy settings.").Base(err) } + if ps.TransportLayerProxy { + if senderSettings.StreamSettings != nil { + if senderSettings.StreamSettings.SocketSettings != nil { + senderSettings.StreamSettings.SocketSettings.DialerProxy = ps.Tag + } else { + senderSettings.StreamSettings.SocketSettings = &internet.SocketConfig{DialerProxy: ps.Tag} + } + } else { + senderSettings.StreamSettings = &internet.StreamConfig{SocketSettings: &internet.SocketConfig{DialerProxy: ps.Tag}} + } + ps = nil + } senderSettings.ProxySettings = ps } diff --git a/transport/config.pb.go b/transport/config.pb.go deleted file mode 100644 index adc76565..00000000 --- a/transport/config.pb.go +++ /dev/null @@ -1,165 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.25.0 -// protoc v3.14.0 -// source: transport/config.proto - -package transport - -import ( - proto "github.com/golang/protobuf/proto" - internet "github.com/xtls/xray-core/transport/internet" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// This is a compile-time assertion that a sufficiently up-to-date version -// of the legacy proto package is being used. -const _ = proto.ProtoPackageIsVersion4 - -// Global transport settings. This affects all type of connections that go -// through Xray. Deprecated. Use each settings in StreamConfig. -// -// Deprecated: Do not use. -type Config struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - TransportSettings []*internet.TransportConfig `protobuf:"bytes,1,rep,name=transport_settings,json=transportSettings,proto3" json:"transport_settings,omitempty"` -} - -func (x *Config) Reset() { - *x = Config{} - if protoimpl.UnsafeEnabled { - mi := &file_transport_config_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Config) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Config) ProtoMessage() {} - -func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_transport_config_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Config.ProtoReflect.Descriptor instead. -func (*Config) Descriptor() ([]byte, []int) { - return file_transport_config_proto_rawDescGZIP(), []int{0} -} - -func (x *Config) GetTransportSettings() []*internet.TransportConfig { - if x != nil { - return x.TransportSettings - } - return nil -} - -var File_transport_config_proto protoreflect.FileDescriptor - -var file_transport_config_proto_rawDesc = []byte{ - 0x0a, 0x16, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 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, 0x65, 0x0a, 0x06, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x57, 0x0a, 0x12, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, - 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x28, 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, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, - 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, - 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x3a, 0x02, 0x18, 0x01, - 0x42, 0x4c, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x01, 0x5a, 0x23, 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, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0xaa, 0x02, 0x0e, - 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_transport_config_proto_rawDescOnce sync.Once - file_transport_config_proto_rawDescData = file_transport_config_proto_rawDesc -) - -func file_transport_config_proto_rawDescGZIP() []byte { - file_transport_config_proto_rawDescOnce.Do(func() { - file_transport_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_config_proto_rawDescData) - }) - return file_transport_config_proto_rawDescData -} - -var file_transport_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_transport_config_proto_goTypes = []interface{}{ - (*Config)(nil), // 0: xray.transport.Config - (*internet.TransportConfig)(nil), // 1: xray.transport.internet.TransportConfig -} -var file_transport_config_proto_depIdxs = []int32{ - 1, // 0: xray.transport.Config.transport_settings:type_name -> xray.transport.internet.TransportConfig - 1, // [1:1] is the sub-list for method output_type - 1, // [1:1] is the sub-list for method input_type - 1, // [1:1] is the sub-list for extension type_name - 1, // [1:1] is the sub-list for extension extendee - 0, // [0:1] is the sub-list for field type_name -} - -func init() { file_transport_config_proto_init() } -func file_transport_config_proto_init() { - if File_transport_config_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_transport_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Config); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_transport_config_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_transport_config_proto_goTypes, - DependencyIndexes: file_transport_config_proto_depIdxs, - MessageInfos: file_transport_config_proto_msgTypes, - }.Build() - File_transport_config_proto = out.File - file_transport_config_proto_rawDesc = nil - file_transport_config_proto_goTypes = nil - file_transport_config_proto_depIdxs = nil -} diff --git a/transport/config.go b/transport/global/config.go similarity index 92% rename from transport/config.go rename to transport/global/config.go index c4a6c124..b6dd8e2a 100644 --- a/transport/config.go +++ b/transport/global/config.go @@ -1,4 +1,4 @@ -package transport +package global import ( "github.com/xtls/xray-core/transport/internet" diff --git a/transport/global/config.pb.go b/transport/global/config.pb.go new file mode 100644 index 00000000..126b101d --- /dev/null +++ b/transport/global/config.pb.go @@ -0,0 +1,167 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.25.0 +// protoc v3.14.0 +// source: transport/global/config.proto + +package global + +import ( + proto "github.com/golang/protobuf/proto" + internet "github.com/xtls/xray-core/transport/internet" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// This is a compile-time assertion that a sufficiently up-to-date version +// of the legacy proto package is being used. +const _ = proto.ProtoPackageIsVersion4 + +// Global transport settings. This affects all type of connections that go +// through Xray. Deprecated. Use each settings in StreamConfig. +// +// Deprecated: Do not use. +type Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + TransportSettings []*internet.TransportConfig `protobuf:"bytes,1,rep,name=transport_settings,json=transportSettings,proto3" json:"transport_settings,omitempty"` +} + +func (x *Config) Reset() { + *x = Config{} + if protoimpl.UnsafeEnabled { + mi := &file_transport_global_config_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Config) ProtoMessage() {} + +func (x *Config) ProtoReflect() protoreflect.Message { + mi := &file_transport_global_config_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Config.ProtoReflect.Descriptor instead. +func (*Config) Descriptor() ([]byte, []int) { + return file_transport_global_config_proto_rawDescGZIP(), []int{0} +} + +func (x *Config) GetTransportSettings() []*internet.TransportConfig { + if x != nil { + return x.TransportSettings + } + return nil +} + +var File_transport_global_config_proto protoreflect.FileDescriptor + +var file_transport_global_config_proto_rawDesc = []byte{ + 0x0a, 0x1d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x0e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 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, 0x65, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x57, 0x0a, 0x12, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 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, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x3a, 0x02, 0x18, 0x01, 0x42, 0x61, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78, + 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x67, 0x6c, + 0x6f, 0x62, 0x61, 0x6c, 0x50, 0x01, 0x5a, 0x2a, 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, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x6c, 0x6f, 0x62, + 0x61, 0x6c, 0xaa, 0x02, 0x15, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_transport_global_config_proto_rawDescOnce sync.Once + file_transport_global_config_proto_rawDescData = file_transport_global_config_proto_rawDesc +) + +func file_transport_global_config_proto_rawDescGZIP() []byte { + file_transport_global_config_proto_rawDescOnce.Do(func() { + file_transport_global_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_global_config_proto_rawDescData) + }) + return file_transport_global_config_proto_rawDescData +} + +var file_transport_global_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_transport_global_config_proto_goTypes = []interface{}{ + (*Config)(nil), // 0: xray.transport.Config + (*internet.TransportConfig)(nil), // 1: xray.transport.internet.TransportConfig +} +var file_transport_global_config_proto_depIdxs = []int32{ + 1, // 0: xray.transport.Config.transport_settings:type_name -> xray.transport.internet.TransportConfig + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_transport_global_config_proto_init() } +func file_transport_global_config_proto_init() { + if File_transport_global_config_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_transport_global_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_transport_global_config_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_transport_global_config_proto_goTypes, + DependencyIndexes: file_transport_global_config_proto_depIdxs, + MessageInfos: file_transport_global_config_proto_msgTypes, + }.Build() + File_transport_global_config_proto = out.File + file_transport_global_config_proto_rawDesc = nil + file_transport_global_config_proto_goTypes = nil + file_transport_global_config_proto_depIdxs = nil +} diff --git a/transport/config.proto b/transport/global/config.proto similarity index 69% rename from transport/config.proto rename to transport/global/config.proto index 2380307d..367036ec 100644 --- a/transport/config.proto +++ b/transport/global/config.proto @@ -1,9 +1,9 @@ syntax = "proto3"; package xray.transport; -option csharp_namespace = "Xray.Transport"; -option go_package = "github.com/xtls/xray-core/transport"; -option java_package = "com.xray.transport"; +option csharp_namespace = "Xray.Transport.Global"; +option go_package = "github.com/xtls/xray-core/transport/global"; +option java_package = "com.xray.transport.global"; option java_multiple_files = true; import "transport/internet/config.proto"; diff --git a/transport/internet/config.pb.go b/transport/internet/config.pb.go index 6d91270b..24f47e68 100644 --- a/transport/internet/config.pb.go +++ b/transport/internet/config.pb.go @@ -84,6 +84,58 @@ func (TransportProtocol) EnumDescriptor() ([]byte, []int) { return file_transport_internet_config_proto_rawDescGZIP(), []int{0} } +type DomainStrategy int32 + +const ( + DomainStrategy_AS_IS DomainStrategy = 0 + DomainStrategy_USE_IP DomainStrategy = 1 + DomainStrategy_USE_IP4 DomainStrategy = 2 + DomainStrategy_USE_IP6 DomainStrategy = 3 +) + +// Enum value maps for DomainStrategy. +var ( + DomainStrategy_name = map[int32]string{ + 0: "AS_IS", + 1: "USE_IP", + 2: "USE_IP4", + 3: "USE_IP6", + } + DomainStrategy_value = map[string]int32{ + "AS_IS": 0, + "USE_IP": 1, + "USE_IP4": 2, + "USE_IP6": 3, + } +) + +func (x DomainStrategy) Enum() *DomainStrategy { + p := new(DomainStrategy) + *p = x + return p +} + +func (x DomainStrategy) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DomainStrategy) Descriptor() protoreflect.EnumDescriptor { + return file_transport_internet_config_proto_enumTypes[1].Descriptor() +} + +func (DomainStrategy) Type() protoreflect.EnumType { + return &file_transport_internet_config_proto_enumTypes[1] +} + +func (x DomainStrategy) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DomainStrategy.Descriptor instead. +func (DomainStrategy) EnumDescriptor() ([]byte, []int) { + return file_transport_internet_config_proto_rawDescGZIP(), []int{1} +} + type SocketConfig_TProxyMode int32 const ( @@ -120,11 +172,11 @@ func (x SocketConfig_TProxyMode) String() string { } func (SocketConfig_TProxyMode) Descriptor() protoreflect.EnumDescriptor { - return file_transport_internet_config_proto_enumTypes[1].Descriptor() + return file_transport_internet_config_proto_enumTypes[2].Descriptor() } func (SocketConfig_TProxyMode) Type() protoreflect.EnumType { - return &file_transport_internet_config_proto_enumTypes[1] + return &file_transport_internet_config_proto_enumTypes[2] } func (x SocketConfig_TProxyMode) Number() protoreflect.EnumNumber { @@ -305,7 +357,8 @@ type ProxyConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` + TransportLayerProxy bool `protobuf:"varint,2,opt,name=transportLayerProxy,proto3" json:"transportLayerProxy,omitempty"` } func (x *ProxyConfig) Reset() { @@ -347,6 +400,13 @@ func (x *ProxyConfig) GetTag() string { return "" } +func (x *ProxyConfig) GetTransportLayerProxy() bool { + if x != nil { + return x.TransportLayerProxy + } + return false +} + // SocketConfig is options to be applied on network sockets. type SocketConfig struct { state protoimpl.MessageState @@ -361,10 +421,12 @@ type SocketConfig struct { Tproxy SocketConfig_TProxyMode `protobuf:"varint,3,opt,name=tproxy,proto3,enum=xray.transport.internet.SocketConfig_TProxyMode" json:"tproxy,omitempty"` // ReceiveOriginalDestAddress is for enabling IP_RECVORIGDSTADDR socket // option. This option is for UDP only. - ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"` - BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"` - BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"` - AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` + ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"` + BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"` + BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"` + AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` + DomainStrategy DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"` + DialerProxy string `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"` } func (x *SocketConfig) Reset() { @@ -448,6 +510,20 @@ func (x *SocketConfig) GetAcceptProxyProtocol() bool { return false } +func (x *SocketConfig) GetDomainStrategy() DomainStrategy { + if x != nil { + return x.DomainStrategy + } + return DomainStrategy_AS_IS +} + +func (x *SocketConfig) GetDialerProxy() string { + if x != nil { + return x.DialerProxy + } + return "" +} + var File_transport_internet_config_proto protoreflect.FileDescriptor var file_transport_internet_config_proto_rawDesc = []byte{ @@ -495,44 +571,58 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, - 0x1f, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, + 0x51, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, - 0x22, 0xe6, 0x02, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 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, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x54, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x74, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, - 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, - 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x41, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x69, 0x6e, 0x64, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64, 0x5f, - 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x69, 0x6e, 0x64, - 0x50, 0x6f, 0x72, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, - 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, - 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, - 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, - 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, - 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, - 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, - 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x10, 0x05, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, - 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 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, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x12, 0x30, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, + 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x22, 0xdb, 0x03, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 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, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x2e, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x74, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, + 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x69, + 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x69, 0x6e, + 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x69, + 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, + 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, + 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x50, 0x0a, 0x0f, 0x64, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x08, 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, 0x21, 0x0a, 0x0c, + 0x64, 0x69, 0x61, 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x09, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x22, + 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, + 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, + 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, + 0x2a, 0x5a, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, + 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, + 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, + 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x05, 0x2a, 0x41, 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, 0x42, + 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, + 0x5a, 0x2c, 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, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, + 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -547,30 +637,32 @@ func file_transport_internet_config_proto_rawDescGZIP() []byte { return file_transport_internet_config_proto_rawDescData } -var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_transport_internet_config_proto_goTypes = []interface{}{ (TransportProtocol)(0), // 0: xray.transport.internet.TransportProtocol - (SocketConfig_TProxyMode)(0), // 1: xray.transport.internet.SocketConfig.TProxyMode - (*TransportConfig)(nil), // 2: xray.transport.internet.TransportConfig - (*StreamConfig)(nil), // 3: xray.transport.internet.StreamConfig - (*ProxyConfig)(nil), // 4: xray.transport.internet.ProxyConfig - (*SocketConfig)(nil), // 5: xray.transport.internet.SocketConfig - (*serial.TypedMessage)(nil), // 6: xray.common.serial.TypedMessage + (DomainStrategy)(0), // 1: xray.transport.internet.DomainStrategy + (SocketConfig_TProxyMode)(0), // 2: xray.transport.internet.SocketConfig.TProxyMode + (*TransportConfig)(nil), // 3: xray.transport.internet.TransportConfig + (*StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig + (*ProxyConfig)(nil), // 5: xray.transport.internet.ProxyConfig + (*SocketConfig)(nil), // 6: xray.transport.internet.SocketConfig + (*serial.TypedMessage)(nil), // 7: xray.common.serial.TypedMessage } var file_transport_internet_config_proto_depIdxs = []int32{ 0, // 0: xray.transport.internet.TransportConfig.protocol:type_name -> xray.transport.internet.TransportProtocol - 6, // 1: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage + 7, // 1: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage 0, // 2: xray.transport.internet.StreamConfig.protocol:type_name -> xray.transport.internet.TransportProtocol - 2, // 3: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig - 6, // 4: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage - 5, // 5: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig - 1, // 6: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 3, // 3: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig + 7, // 4: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage + 6, // 5: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig + 2, // 6: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode + 1, // 7: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_transport_internet_config_proto_init() } @@ -633,7 +725,7 @@ func file_transport_internet_config_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_transport_internet_config_proto_rawDesc, - NumEnums: 2, + NumEnums: 3, NumMessages: 4, NumExtensions: 0, NumServices: 0, diff --git a/transport/internet/config.proto b/transport/internet/config.proto index bb91c44c..41e19378 100644 --- a/transport/internet/config.proto +++ b/transport/internet/config.proto @@ -17,6 +17,13 @@ enum TransportProtocol { DomainSocket = 5; } +enum DomainStrategy { + AS_IS = 0; + USE_IP = 1; + USE_IP4 = 2; + USE_IP6 = 3; +} + message TransportConfig { // Type of network that this settings supports. // Deprecated. Use the string form below. @@ -47,7 +54,10 @@ message StreamConfig { SocketConfig socket_settings = 6; } -message ProxyConfig { string tag = 1; } +message ProxyConfig { + string tag = 1; + bool transportLayerProxy = 2; +} // SocketConfig is options to be applied on network sockets. message SocketConfig { @@ -78,4 +88,7 @@ message SocketConfig { uint32 bind_port = 6; bool accept_proxy_protocol = 7; + + DomainStrategy domain_strategy = 8; + string dialer_proxy = 9; } diff --git a/transport/internet/system_dialer.go b/transport/internet/system_dialer.go index 52fe5e76..3f0095d3 100644 --- a/transport/internet/system_dialer.go +++ b/transport/internet/system_dialer.go @@ -5,20 +5,35 @@ import ( "syscall" "time" + "github.com/xtls/xray-core/common" + "github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/net" + "github.com/xtls/xray-core/common/net/cnc" "github.com/xtls/xray-core/common/session" + "github.com/xtls/xray-core/features/dns" + "github.com/xtls/xray-core/features/outbound" + "github.com/xtls/xray-core/transport" + "github.com/xtls/xray-core/transport/pipe" ) var ( effectiveSystemDialer SystemDialer = &DefaultSystemDialer{} ) +// InitSystemDialer: It's private method and you are NOT supposed to use this function. +func InitSystemDialer(dc dns.Client, om outbound.Manager) { + effectiveSystemDialer.init(dc, om) +} + type SystemDialer interface { Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *SocketConfig) (net.Conn, error) + init(dc dns.Client, om outbound.Manager) } type DefaultSystemDialer struct { controllers []controller + dns dns.Client + obm outbound.Manager } func resolveSrcAddr(network net.Network, src net.Address) net.Addr { @@ -43,7 +58,78 @@ func hasBindAddr(sockopt *SocketConfig) bool { return sockopt != nil && len(sockopt.BindAddress) > 0 && sockopt.BindPort > 0 } +func (d *DefaultSystemDialer) lookupIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]net.IP, error) { + if d.dns == nil { + return nil, nil + } + + var lookup = d.dns.LookupIP + + switch { + case strategy == DomainStrategy_USE_IP4 || (localAddr != nil && localAddr.Family().IsIPv4()): + if lookupIPv4, ok := d.dns.(dns.IPv4Lookup); ok { + lookup = lookupIPv4.LookupIPv4 + } + case strategy == DomainStrategy_USE_IP6 || (localAddr != nil && localAddr.Family().IsIPv6()): + if lookupIPv4, ok := d.dns.(dns.IPv4Lookup); ok { + lookup = lookupIPv4.LookupIPv4 + } + case strategy == DomainStrategy_AS_IS: + return nil, nil + } + + return lookup(domain) +} + +func (d *DefaultSystemDialer) canLookupIP(ctx context.Context, dst net.Destination, sockopt *SocketConfig) bool { + if sockopt == nil || dst.Address.Family().IsIP() || d.dns == nil { + return false + } + if dst.Address.Domain() == LookupDomainFromContext(ctx) { + newError("infinite loop detected").AtError().WriteToLog(session.ExportIDToError(ctx)) + return false + } + return sockopt.DomainStrategy != DomainStrategy_AS_IS +} + +func (d *DefaultSystemDialer) redirect(ctx context.Context, dst net.Destination, obt string) net.Conn { + newError("redirecting request " + dst.String() + " to " + obt).WriteToLog(session.ExportIDToError(ctx)) + h := d.obm.GetHandler(obt) + ctx = session.ContextWithOutbound(ctx, &session.Outbound{dst, nil}) + if h != nil { + ur, uw := pipe.New(pipe.OptionsFromContext(ctx)...) + dr, dw := pipe.New(pipe.OptionsFromContext(ctx)...) + + go h.Dispatch(ctx, &transport.Link{ur, dw}) + nc := cnc.NewConnection( + cnc.ConnectionInputMulti(uw), + cnc.ConnectionOutputMulti(dr), + cnc.ConnectionOnClose(common.ChainedClosable{uw, dw}), + ) + return nc + } + return nil +} + func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { + newError("dialing to " + dest.String()).AtDebug().WriteToLog() + if d.obm != nil && sockopt != nil && len(sockopt.DialerProxy) > 0 { + nc := d.redirect(ctx, dest, sockopt.DialerProxy) + if nc != nil { + return nc, nil + } + } + + if d.canLookupIP(ctx, dest, sockopt) { + ips, err := d.lookupIP(dest.Address.String(), sockopt.DomainStrategy, src) + if err == nil && len(ips) > 0 { + dest.Address = net.IPAddress(ips[dice.Roll(len(ips))]) + newError("replace destination with " + dest.String()).AtInfo().WriteToLog() + } else if err != nil { + newError("failed to resolve ip").Base(err).AtWarning().WriteToLog() + } + } + if dest.Network == net.Network_UDP && !hasBindAddr(sockopt) { srcAddr := resolveSrcAddr(net.Network_UDP, src) if srcAddr == nil { @@ -98,6 +184,11 @@ func (d *DefaultSystemDialer) Dial(ctx context.Context, src net.Address, dest ne return dialer.DialContext(ctx, dest.Network.SystemString(), dest.NetAddr()) } +func (d *DefaultSystemDialer) init(dc dns.Client, om outbound.Manager) { + d.dns = dc + d.obm = om +} + type PacketConnWrapper struct { conn net.PacketConn dest net.Addr @@ -158,6 +249,8 @@ func WithAdapter(dialer SystemDialerAdapter) SystemDialer { } } +func (v *SimpleSystemDialer) init(_ dns.Client, _ outbound.Manager) {} + func (v *SimpleSystemDialer) Dial(ctx context.Context, src net.Address, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) { return v.adapter.Dial(dest.Network.SystemString(), dest.NetAddr()) } diff --git a/transport/internet/system_dialer_context.go b/transport/internet/system_dialer_context.go new file mode 100644 index 00000000..abc6c104 --- /dev/null +++ b/transport/internet/system_dialer_context.go @@ -0,0 +1,18 @@ +package internet + +import "context" + +type systemDialer int + +const systemDialerKey systemDialer = 0 + +func ContextWithLookupDomain(ctx context.Context, domain string) context.Context { + return context.WithValue(ctx, systemDialerKey, domain) +} + +func LookupDomainFromContext(ctx context.Context) string { + if domain, ok := ctx.Value(systemDialerKey).(string); ok { + return domain + } + return "" +}