diff --git a/common/mux/server.go b/common/mux/server.go index 30dcf06e..99a144a5 100644 --- a/common/mux/server.go +++ b/common/mux/server.go @@ -118,9 +118,7 @@ func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.Bu } func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error { - // deep-clone outbounds because it is going to be mutated concurrently - // (Target and OriginalTarget) - ctx = session.ContextCloneOutboundsAndContent(ctx) + ctx = session.SubContextFromMuxInbound(ctx) errors.LogInfo(ctx, "received request for ", meta.Target) { msg := &log.AccessMessage{ diff --git a/common/session/context.go b/common/session/context.go index 0e2558c2..ba3530b5 100644 --- a/common/session/context.go +++ b/common/session/context.go @@ -16,15 +16,15 @@ const ( inboundSessionKey ctx.SessionKey = 1 outboundSessionKey ctx.SessionKey = 2 contentSessionKey ctx.SessionKey = 3 - muxPreferredSessionKey ctx.SessionKey = 4 - sockoptSessionKey ctx.SessionKey = 5 - trackedConnectionErrorKey ctx.SessionKey = 6 - dispatcherKey ctx.SessionKey = 7 - timeoutOnlyKey ctx.SessionKey = 8 - allowedNetworkKey ctx.SessionKey = 9 - handlerSessionKey ctx.SessionKey = 10 - mitmAlpn11Key ctx.SessionKey = 11 - mitmServerNameKey ctx.SessionKey = 12 + muxPreferredSessionKey ctx.SessionKey = 4 // unused + sockoptSessionKey ctx.SessionKey = 5 // used by dokodemo to only receive sockopt.Mark + trackedConnectionErrorKey ctx.SessionKey = 6 // used by observer to get outbound error + dispatcherKey ctx.SessionKey = 7 // used by ss2022 inbounds to get dispatcher + timeoutOnlyKey ctx.SessionKey = 8 // mux context's child contexts to only cancel when its own traffic times out + allowedNetworkKey ctx.SessionKey = 9 // muxcool server control incoming request tcp/udp + handlerSessionKey ctx.SessionKey = 10 // unused + mitmAlpn11Key ctx.SessionKey = 11 // used by TLS dialer + mitmServerNameKey ctx.SessionKey = 12 // used by TLS dialer ) func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context { @@ -42,18 +42,8 @@ func ContextWithOutbounds(ctx context.Context, outbounds []*Outbound) context.Co return context.WithValue(ctx, outboundSessionKey, outbounds) } -func ContextCloneOutboundsAndContent(ctx context.Context) context.Context { - outbounds := OutboundsFromContext(ctx) - newOutbounds := make([]*Outbound, len(outbounds)) - for i, ob := range outbounds { - if ob == nil { - continue - } - - // copy outbound by value - v := *ob - newOutbounds[i] = &v - } +func SubContextFromMuxInbound(ctx context.Context) context.Context { + newOutbounds := []*Outbound{{}} content := ContentFromContext(ctx) newContent := Content{} diff --git a/common/session/session.go b/common/session/session.go index 272aa5fb..aad31cdf 100644 --- a/common/session/session.go +++ b/common/session/session.go @@ -48,9 +48,9 @@ type Inbound struct { User *protocol.MemoryUser // VlessRoute is the user-sent VLESS UUID's last byte. VlessRoute net.Port - // Conn is actually internet.Connection. May be nil. + // Used by splice copy. Conn is actually internet.Connection. May be nil. Conn net.Conn - // Timer of the inbound buf copier. May be nil. + // Used by splice copy. Timer of the inbound buf copier. May be nil. Timer *signal.ActivityTimer // CanSpliceCopy is a property for this connection // 1 = can, 2 = after processing protocol info should be able to, 3 = cannot @@ -69,31 +69,33 @@ type Outbound struct { Tag string // Name of the outbound proxy that handles the connection. Name string - // Conn is actually internet.Connection. May be nil. It is currently nil for outbound with proxySettings + // Unused. Conn is actually internet.Connection. May be nil. It is currently nil for outbound with proxySettings Conn net.Conn // CanSpliceCopy is a property for this connection // 1 = can, 2 = after processing protocol info should be able to, 3 = cannot CanSpliceCopy int } -// SniffingRequest controls the behavior of content sniffing. +// SniffingRequest controls the behavior of content sniffing. They are from inbound config. Read-only type SniffingRequest struct { - ExcludeForDomain []string // read-only once set - OverrideDestinationForProtocol []string // read-only once set + ExcludeForDomain []string + OverrideDestinationForProtocol []string Enabled bool MetadataOnly bool RouteOnly bool } -// Content is the metadata of the connection content. +// Content is the metadata of the connection content. Mainly used for routing. type Content struct { // Protocol of current content. Protocol string SniffingRequest SniffingRequest + // HTTP traffic sniffed headers Attributes map[string]string + // SkipDNSResolve is set from DNS module. the DOH remote server maybe a domain name, this prevents cycle resolving dead loop SkipDNSResolve bool } diff --git a/proxy/wireguard/server.go b/proxy/wireguard/server.go index ecf35541..97442397 100644 --- a/proxy/wireguard/server.go +++ b/proxy/wireguard/server.go @@ -126,17 +126,19 @@ func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) { ctx, cancel := context.WithCancel(context.Background()) sid := session.NewID() ctx = c.ContextWithID(ctx, sid) + inbound := session.Inbound{} // since promiscuousModeHandler mixed-up context, we shallow copy inbound (tag) and content (configs) if s.info.inboundTag != nil { - ctx = session.ContextWithInbound(ctx, s.info.inboundTag) + inbound = *s.info.inboundTag } + inbound.Name = "wireguard" + inbound.CanSpliceCopy = 3 + inbound.Source = net.DestinationFromAddr(conn.RemoteAddr()) + inbound.Gateway = net.DestinationFromAddr(conn.LocalAddr()) + ctx = session.ContextWithInbound(ctx, &inbound) if s.info.contentTag != nil { ctx = session.ContextWithContent(ctx, s.info.contentTag) } - inbound := session.InboundFromContext(ctx) - inbound.Name = "wireguard" - inbound.CanSpliceCopy = 3 - outbounds := []*session.Outbound{{}} - ctx = session.ContextWithOutbounds(ctx, outbounds) // since promiscuousModeHandler mixed-up context, we need to define new Outbounds here + ctx = session.SubContextFromMuxInbound(ctx) plcy := s.policyManager.ForLevel(0) timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle)