diff --git a/app/proxyman/inbound/always.go b/app/proxyman/inbound/always.go index 6fb3ba435a4c..a1cb7b7cc10e 100644 --- a/app/proxyman/inbound/always.go +++ b/app/proxyman/inbound/always.go @@ -9,6 +9,7 @@ import ( "github.com/xtls/xray-core/common/mux" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/serial" + "github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/core" "github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/stats" @@ -52,6 +53,20 @@ type AlwaysOnInboundHandler struct { } func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) { + // Set tag and sniffing config in context before creating proxy + // This allows proxies like TUN to access these settings + ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: tag}) + if receiverConfig.SniffingSettings != nil { + ctx = session.ContextWithContent(ctx, &session.Content{ + SniffingRequest: session.SniffingRequest{ + Enabled: receiverConfig.SniffingSettings.Enabled, + OverrideDestinationForProtocol: receiverConfig.SniffingSettings.DestinationOverride, + ExcludeForDomain: receiverConfig.SniffingSettings.DomainsExcluded, + MetadataOnly: receiverConfig.SniffingSettings.MetadataOnly, + RouteOnly: receiverConfig.SniffingSettings.RouteOnly, + }, + }) + } rawProxy, err := common.CreateObject(ctx, proxyConfig) if err != nil { return nil, err diff --git a/infra/conf/xray.go b/infra/conf/xray.go index 2080bd8c57c6..eff6b8a91c4f 100644 --- a/infra/conf/xray.go +++ b/infra/conf/xray.go @@ -130,7 +130,10 @@ type InboundDetourConfig struct { func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) { receiverSettings := &proxyman.ReceiverConfig{} - if c.ListenOn == nil { + // TUN inbound doesn't need port configuration as it uses network interface instead + if strings.ToLower(c.Protocol) == "tun" { + // Skip port validation for TUN + } else if c.ListenOn == nil { // Listen on anyip, must set PortList if c.PortList == nil { return nil, errors.New("Listen on AnyIP but no Port(s) set in InboundDetour.") diff --git a/proxy/tun/handler.go b/proxy/tun/handler.go index 760d872e752c..f830a4ea3dd0 100644 --- a/proxy/tun/handler.go +++ b/proxy/tun/handler.go @@ -7,6 +7,7 @@ import ( "github.com/xtls/xray-core/common/buf" c "github.com/xtls/xray-core/common/ctx" "github.com/xtls/xray-core/common/errors" + "github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/session" @@ -19,11 +20,13 @@ import ( // Handler is managing object that tie together tun interface, ip stack and dispatch connections to the routing type Handler struct { - ctx context.Context - config *Config - stack Stack - policyManager policy.Manager - dispatcher routing.Dispatcher + ctx context.Context + config *Config + stack Stack + policyManager policy.Manager + dispatcher routing.Dispatcher + tag string + sniffingRequest session.SniffingRequest } // ConnectionHandler interface with the only method that stack is going to push new connections to @@ -43,6 +46,14 @@ func (t *Handler) policy() policy.Session { func (t *Handler) Init(ctx context.Context, pm policy.Manager, dispatcher routing.Dispatcher) error { var err error + // Retrieve tag and sniffing config from context (set by AlwaysOnInboundHandler) + if inbound := session.InboundFromContext(ctx); inbound != nil { + t.tag = inbound.Tag + } + if content := session.ContentFromContext(ctx); content != nil { + t.sniffingRequest = content.SniffingRequest + } + t.ctx = core.ToBackgroundDetachedContext(ctx) t.policyManager = pm t.dispatcher = dispatcher @@ -93,29 +104,38 @@ func (t *Handler) Init(ctx context.Context, pm policy.Manager, dispatcher routin func (t *Handler) HandleConnection(conn net.Conn, destination net.Destination) { sid := session.NewID() ctx := c.ContextWithID(t.ctx, sid) - errors.LogInfo(ctx, "processing connection from: ", conn.RemoteAddr()) - - inbound := session.Inbound{} - inbound.Name = "tun" - inbound.CanSpliceCopy = 1 - inbound.Source = net.DestinationFromAddr(conn.RemoteAddr()) - inbound.User = &protocol.MemoryUser{ - Level: t.config.UserLevel, + + inbound := session.Inbound{ + Name: "tun", + Tag: t.tag, + CanSpliceCopy: 3, + Source: net.DestinationFromAddr(conn.RemoteAddr()), + User: &protocol.MemoryUser{ + Level: t.config.UserLevel, + }, } ctx = session.ContextWithInbound(ctx, &inbound) + ctx = session.ContextWithContent(ctx, &session.Content{ + SniffingRequest: t.sniffingRequest, + }) ctx = session.SubContextFromMuxInbound(ctx) + ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ + From: inbound.Source, + To: destination, + Status: log.AccessAccepted, + Reason: "", + }) + errors.LogInfo(ctx, "processing TCP from ", conn.RemoteAddr(), " to ", destination) + link := &transport.Link{ Reader: &buf.TimeoutWrapperReader{Reader: buf.NewReader(conn)}, Writer: buf.NewWriter(conn), } if err := t.dispatcher.DispatchLink(ctx, destination, link); err != nil { errors.LogError(ctx, errors.New("connection closed").Base(err)) - return } - - errors.LogInfo(ctx, "connection completed") } // Network implements proxy.Inbound diff --git a/proxy/tun/udp_fullcone.go b/proxy/tun/udp_fullcone.go index bc50a7f3a305..d2920b341416 100644 --- a/proxy/tun/udp_fullcone.go +++ b/proxy/tun/udp_fullcone.go @@ -10,6 +10,7 @@ import ( "github.com/xtls/xray-core/common/buf" c "github.com/xtls/xray-core/common/ctx" "github.com/xtls/xray-core/common/errors" + "github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/protocol" "github.com/xtls/xray-core/common/session" @@ -100,12 +101,23 @@ func (u *udpConnectionHandler) HandlePacket(src net.Destination, dst net.Destina inbound := &session.Inbound{ Name: "tun", + Tag: u.handler.tag, Source: src, - CanSpliceCopy: 1, + CanSpliceCopy: 3, User: &protocol.MemoryUser{Level: u.handler.config.UserLevel}, } ctx = session.ContextWithInbound(c.ContextWithID(ctx, session.NewID()), inbound) + ctx = session.ContextWithContent(ctx, &session.Content{ + SniffingRequest: u.handler.sniffingRequest, + }) ctx = session.SubContextFromMuxInbound(ctx) + ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ + From: src, + To: dst, + Status: log.AccessAccepted, + Reason: "", + }) + errors.LogInfo(ctx, "processing UDP from ", src, " to ", dst) link := &transport.Link{ Reader: &buf.TimeoutWrapperReader{Reader: conn.reader}, // reverse source and destination, indicating the packets to write are going in the other