diff --git a/app/dispatcher/default.go b/app/dispatcher/default.go index e6e21f0ba..40beed96d 100644 --- a/app/dispatcher/default.go +++ b/app/dispatcher/default.go @@ -294,17 +294,30 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool) (Sni func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) { var handler outbound.Handler - if d.router != nil { - if route, err := d.router.PickRoute(routing_session.AsRoutingContext(ctx)); err == nil { - tag := route.GetOutboundTag() - if h := d.ohm.GetHandler(tag); h != nil { - newError("taking detour [", tag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx)) - handler = h - } else { - newError("non existing tag: ", tag).AtWarning().WriteToLog(session.ExportIDToError(ctx)) - } + if forcedOutboundTag := session.GetForcedOutboundTagFromContext(ctx); forcedOutboundTag != "" { + session.SetForcedOutboundTagToContext(ctx, "") + if h := d.ohm.GetHandler(forcedOutboundTag); h != nil { + newError("taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx)) + handler = h } else { - newError("default route for ", destination).WriteToLog(session.ExportIDToError(ctx)) + newError("non existing tag for platform initialized detour: ", forcedOutboundTag).AtError().WriteToLog(session.ExportIDToError(ctx)) + common.Close(link.Writer) + common.Interrupt(link.Reader) + return + } + } else { + if d.router != nil { + if route, err := d.router.PickRoute(routing_session.AsRoutingContext(ctx)); err == nil { + tag := route.GetOutboundTag() + if h := d.ohm.GetHandler(tag); h != nil { + newError("taking detour [", tag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx)) + handler = h + } else { + newError("non existing tag: ", tag).AtWarning().WriteToLog(session.ExportIDToError(ctx)) + } + } else { + newError("default route for ", destination).WriteToLog(session.ExportIDToError(ctx)) + } } } diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index 5e5ba1216..46c564630 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -159,7 +159,7 @@ func (h *Handler) Address() net.Address { // Dial implements internet.Dialer. func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Connection, error) { if h.senderSettings != nil { - if h.senderSettings.ProxySettings.HasTag() { + if h.senderSettings.ProxySettings.HasTag() && !h.senderSettings.ProxySettings.TransportLayerProxy { tag := h.senderSettings.ProxySettings.Tag handler := h.outboundManager.GetHandler(tag) if handler != nil { @@ -196,6 +196,12 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn } } + if h.senderSettings != nil && h.senderSettings.ProxySettings != nil && h.senderSettings.ProxySettings.HasTag() && h.senderSettings.ProxySettings.TransportLayerProxy { + tag := h.senderSettings.ProxySettings.Tag + newError("transport layer proxying to ", tag, " for dest ", dest).AtDebug().WriteToLog(session.ExportIDToError(ctx)) + session.SetTransportLayerProxyTagToContext(ctx, tag) + } + conn, err := internet.Dial(ctx, dest, h.streamSettings) return h.getStatCouterConnection(conn), err } diff --git a/common/session/context.go b/common/session/context.go index 7f1d7df9b..8fdb01fa6 100644 --- a/common/session/context.go +++ b/common/session/context.go @@ -84,3 +84,25 @@ func SockoptFromContext(ctx context.Context) *Sockopt { } return nil } + +func GetTransportLayerProxyTagFromContext(ctx context.Context) string { + if ContentFromContext(ctx) == nil { + return "" + } + return ContentFromContext(ctx).Attribute("transportLayerOutgoingTag") +} + +func SetTransportLayerProxyTagToContext(ctx context.Context, tag string) { + ContentFromContext(ctx).SetAttribute("transportLayerOutgoingTag", tag) +} + +func GetForcedOutboundTagFromContext(ctx context.Context) string { + if ContentFromContext(ctx) == nil { + return "" + } + return ContentFromContext(ctx).Attribute("forcedOutboundTag") +} + +func SetForcedOutboundTagToContext(ctx context.Context, tag string) { + ContentFromContext(ctx).SetAttribute("forcedOutboundTag", tag) +} diff --git a/infra/conf/transport_internet.go b/infra/conf/transport_internet.go index 9a1a04d06..301f324de 100644 --- a/infra/conf/transport_internet.go +++ b/infra/conf/transport_internet.go @@ -485,7 +485,8 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) { } type ProxyConfig struct { - Tag string `json:"tag"` + Tag string `json:"tag"` + TransportLayerProxy bool `json:"transportLayer"` } // Build implements Buildable. @@ -494,6 +495,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/main/distro/all/all.go b/main/distro/all/all.go index 9c6e1b0fb..5351a54cb 100644 --- a/main/distro/all/all.go +++ b/main/distro/all/all.go @@ -23,6 +23,8 @@ import ( _ "github.com/v2fly/v2ray-core/v4/app/router" _ "github.com/v2fly/v2ray-core/v4/app/stats" + _ "github.com/v2fly/v2ray-core/v4/transport/internet/tagged/taggedimpl" + // Inbound and outbound proxies. _ "github.com/v2fly/v2ray-core/v4/proxy/blackhole" _ "github.com/v2fly/v2ray-core/v4/proxy/dns" diff --git a/transport/internet/config.pb.go b/transport/internet/config.pb.go index a93288631..833617fb8 100644 --- a/transport/internet/config.pb.go +++ b/transport/internet/config.pb.go @@ -357,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() { @@ -399,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 @@ -549,53 +557,56 @@ var file_transport_internet_config_proto_rawDesc = []byte{ 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x52, 0x0e, 0x73, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x1f, 0x0a, 0x0b, 0x50, 0x72, 0x6f, + 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 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, 0xe1, 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, - 0x4e, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, 0x2e, 0x76, - 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x43, 0x50, 0x46, 0x61, 0x73, - 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, - 0x4e, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x36, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x35, 0x0a, 0x10, 0x54, 0x43, 0x50, 0x46, 0x61, 0x73, - 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, - 0x49, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x01, - 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 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, 0x78, 0x0a, 0x21, 0x63, 0x6f, - 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, - 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, - 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, - 0x34, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x1d, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, - 0x65, 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, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 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, 0xe1, 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, 0x4e, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3c, + 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x43, 0x50, 0x46, + 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x03, 0x74, 0x66, + 0x6f, 0x12, 0x4e, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0e, 0x32, 0x36, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x35, 0x0a, 0x10, 0x54, 0x43, 0x50, 0x46, + 0x61, 0x73, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x08, 0x0a, 0x04, + 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x02, 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, 0x78, 0x0a, 0x21, + 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, + 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, + 0x74, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, + 0x2f, 0x76, 0x34, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x1d, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, + 0x6f, 0x72, 0x65, 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 ( diff --git a/transport/internet/config.proto b/transport/internet/config.proto index d23b5a6bd..139ef83cc 100644 --- a/transport/internet/config.proto +++ b/transport/internet/config.proto @@ -47,7 +47,11 @@ 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 { diff --git a/transport/internet/dialer.go b/transport/internet/dialer.go index 78a45fdf8..66af2f0e5 100644 --- a/transport/internet/dialer.go +++ b/transport/internet/dialer.go @@ -2,6 +2,7 @@ package internet import ( "context" + "github.com/v2fly/v2ray-core/v4/transport/internet/tagged" "github.com/v2fly/v2ray-core/v4/common/net" "github.com/v2fly/v2ray-core/v4/common/session" @@ -68,5 +69,17 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig if outbound := session.OutboundFromContext(ctx); outbound != nil { src = outbound.Gateway } + + if transportLayerOutgoingTag := session.GetTransportLayerProxyTagFromContext(ctx); transportLayerOutgoingTag != "" { + return DialTaggedOutbound(ctx, dest, transportLayerOutgoingTag) + } + return effectiveSystemDialer.Dial(ctx, src, dest, sockopt) } + +func DialTaggedOutbound(ctx context.Context, dest net.Destination, tag string) (net.Conn, error) { + if tagged.Dialer == nil { + return nil, newError("tagged dial not enabled") + } + return tagged.Dialer(ctx, dest, tag) +} diff --git a/transport/internet/tagged/tagged.go b/transport/internet/tagged/tagged.go new file mode 100644 index 000000000..a99a7b88d --- /dev/null +++ b/transport/internet/tagged/tagged.go @@ -0,0 +1,10 @@ +package tagged + +import ( + "context" + "github.com/v2fly/v2ray-core/v4/common/net" +) + +type DialFunc func(ctx context.Context, dest net.Destination, tag string) (net.Conn, error) + +var Dialer DialFunc diff --git a/transport/internet/tagged/taggedimpl/errors.generated.go b/transport/internet/tagged/taggedimpl/errors.generated.go new file mode 100644 index 000000000..88339a09c --- /dev/null +++ b/transport/internet/tagged/taggedimpl/errors.generated.go @@ -0,0 +1,9 @@ +package taggedimpl + +import "github.com/v2fly/v2ray-core/v4/common/errors" + +type errPathObjHolder struct{} + +func newError(values ...interface{}) *errors.Error { + return errors.New(values...).WithPathObj(errPathObjHolder{}) +} diff --git a/transport/internet/tagged/taggedimpl/impl.go b/transport/internet/tagged/taggedimpl/impl.go new file mode 100644 index 000000000..5688c58e7 --- /dev/null +++ b/transport/internet/tagged/taggedimpl/impl.go @@ -0,0 +1,43 @@ +// +build !confonly + +package taggedimpl + +import ( + "context" + core "github.com/v2fly/v2ray-core/v4" + "github.com/v2fly/v2ray-core/v4/common/net" + "github.com/v2fly/v2ray-core/v4/common/session" + "github.com/v2fly/v2ray-core/v4/features/routing" + "github.com/v2fly/v2ray-core/v4/transport/internet/tagged" +) + +func DialTaggedOutbound(ctx context.Context, dest net.Destination, tag string) (net.Conn, error) { + var dispatcher routing.Dispatcher + if err := core.RequireFeatures(ctx, func(dispatcherInstance routing.Dispatcher) { + dispatcher = dispatcherInstance + }); err != nil { + return nil, newError("Required Feature dispatcher not resolved").Base(err) + } + + content := new(session.Content) + content.SkipDNSResolve = true + + ctx = session.ContextWithContent(ctx, content) + session.SetForcedOutboundTagToContext(ctx, tag) + + r, err := dispatcher.Dispatch(ctx, dest) + if err != nil { + return nil, err + } + var readerOpt net.ConnectionOption + if dest.Network == net.Network_TCP { + readerOpt = net.ConnectionOutputMulti(r.Reader) + } else { + readerOpt = net.ConnectionOutputMultiUDP(r.Reader) + } + return net.NewConnection(net.ConnectionInputMulti(r.Writer), readerOpt), nil +} + +func init() { + tagged.Dialer = DialTaggedOutbound +} diff --git a/transport/internet/tagged/taggedimpl/taggedimpl.go b/transport/internet/tagged/taggedimpl/taggedimpl.go new file mode 100644 index 000000000..1597c7b75 --- /dev/null +++ b/transport/internet/tagged/taggedimpl/taggedimpl.go @@ -0,0 +1,3 @@ +package taggedimpl + +//go:generate go run github.com/v2fly/v2ray-core/v4/common/errors/errorgen