1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2024-12-30 05:56:54 -05:00

Added Transport Layer Chained Proxy Support

This commit is contained in:
Shelikhoo 2021-02-28 18:47:31 +00:00
parent 8980cf2fcc
commit dd51d32250
No known key found for this signature in database
GPG Key ID: C4D5E79D22B25316
5 changed files with 74 additions and 3 deletions

View File

@ -294,6 +294,19 @@ 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 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("non existing tag for platform initialized detour: ", forcedOutboundTag).AtError().WriteToLog(session.ExportIDToError(ctx))
common.Close(link.Writer)
common.Interrupt(link.Reader)
return
}
}
if d.router != nil {
if route, err := d.router.PickRoute(routing_session.AsRoutingContext(ctx)); err == nil {
tag := route.GetOutboundTag()

View File

@ -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.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
}

View File

@ -84,3 +84,19 @@ func SockoptFromContext(ctx context.Context) *Sockopt {
}
return nil
}
func GetTransportLayerProxyTagFromContext(ctx context.Context) string {
return ContentFromContext(ctx).Attribute("transportLayerOutgoingTag")
}
func SetTransportLayerProxyTagToContext(ctx context.Context, tag string) {
ContentFromContext(ctx).SetAttribute("transportLayerOutgoingTag", tag)
}
func GetForcedOutboundTagFromContext(ctx context.Context) string {
return ContentFromContext(ctx).Attribute("forcedOutboundTag")
}
func SetForcedOutboundTagToContext(ctx context.Context, tag string) {
ContentFromContext(ctx).SetAttribute("forcedOutboundTag", tag)
}

View File

@ -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
}

View File

@ -2,6 +2,8 @@ package internet
import (
"context"
core "github.com/v2fly/v2ray-core/v4"
"github.com/v2fly/v2ray-core/v4/features/routing"
"github.com/v2fly/v2ray-core/v4/common/net"
"github.com/v2fly/v2ray-core/v4/common/session"
@ -68,5 +70,37 @@ 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) {
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
session.SetForcedOutboundTagToContext(ctx, tag)
ctx = session.ContextWithContent(ctx, content)
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
}