diff --git a/app/proxyman/inbound/inbound.go b/app/proxyman/inbound/inbound.go index 3fe5597ca..6a0f67592 100644 --- a/app/proxyman/inbound/inbound.go +++ b/app/proxyman/inbound/inbound.go @@ -16,6 +16,7 @@ import ( // Manager is to manage all inbound handlers. type Manager struct { + ctx context.Context access sync.RWMutex untaggedHandler []inbound.Handler taggedHandlers map[string]inbound.Handler @@ -25,6 +26,7 @@ type Manager struct { // New returns a new Manager for inbound handlers. func New(ctx context.Context, config *proxyman.InboundConfig) (*Manager, error) { m := &Manager{ + ctx: ctx, taggedHandlers: make(map[string]inbound.Handler), } return m, nil diff --git a/app/proxyman/inbound/worker.go b/app/proxyman/inbound/worker.go index b2d74c892..1434af078 100644 --- a/app/proxyman/inbound/worker.go +++ b/app/proxyman/inbound/worker.go @@ -9,6 +9,8 @@ import ( "github.com/v2fly/v2ray-core/v5/app/proxyman" "github.com/v2fly/v2ray-core/v5/common" "github.com/v2fly/v2ray-core/v5/common/buf" + "github.com/v2fly/v2ray-core/v5/common/environment" + "github.com/v2fly/v2ray-core/v5/common/environment/envctx" "github.com/v2fly/v2ray-core/v5/common/net" "github.com/v2fly/v2ray-core/v5/common/serial" "github.com/v2fly/v2ray-core/v5/common/session" @@ -112,6 +114,12 @@ func (w *tcpWorker) Proxy() proxy.Inbound { func (w *tcpWorker) Start() error { ctx := context.Background() + proxyEnvironment := envctx.EnvironmentFromContext(w.ctx).(environment.ProxyEnvironment) + transportEnvironment, err := proxyEnvironment.NarrowScopeToTransport("transport") + if err != nil { + return newError("unable to narrow environment to transport").Base(err) + } + ctx = envctx.ContextWithEnvironment(ctx, transportEnvironment) hub, err := internet.ListenTCP(ctx, w.address, w.port, w.stream, func(conn internet.Connection) { go w.callback(conn) }) @@ -371,6 +379,12 @@ func (w *udpWorker) clean() error { func (w *udpWorker) Start() error { w.activeConn = make(map[connID]*udpConn, 16) ctx := context.Background() + proxyEnvironment := envctx.EnvironmentFromContext(w.ctx).(environment.ProxyEnvironment) + transportEnvironment, err := proxyEnvironment.NarrowScopeToTransport("transport") + if err != nil { + return newError("unable to narrow environment to transport").Base(err) + } + ctx = envctx.ContextWithEnvironment(ctx, transportEnvironment) h, err := udp.ListenUDP(ctx, w.address, w.port, w.stream, udp.HubCapacity(256)) if err != nil { return err @@ -480,6 +494,12 @@ func (w *dsWorker) Port() net.Port { func (w *dsWorker) Start() error { ctx := context.Background() + proxyEnvironment := envctx.EnvironmentFromContext(w.ctx).(environment.ProxyEnvironment) + transportEnvironment, err := proxyEnvironment.NarrowScopeToTransport("transport") + if err != nil { + return newError("unable to narrow environment to transport").Base(err) + } + ctx = envctx.ContextWithEnvironment(ctx, transportEnvironment) hub, err := internet.ListenUnix(ctx, w.address, w.stream, func(conn internet.Connection) { go w.callback(conn) }) diff --git a/app/proxyman/outbound/handler.go b/app/proxyman/outbound/handler.go index 1ba81413e..5c6d0dd3d 100644 --- a/app/proxyman/outbound/handler.go +++ b/app/proxyman/outbound/handler.go @@ -7,6 +7,8 @@ import ( "github.com/v2fly/v2ray-core/v5/app/proxyman" "github.com/v2fly/v2ray-core/v5/common" "github.com/v2fly/v2ray-core/v5/common/dice" + "github.com/v2fly/v2ray-core/v5/common/environment" + "github.com/v2fly/v2ray-core/v5/common/environment/envctx" "github.com/v2fly/v2ray-core/v5/common/mux" "github.com/v2fly/v2ray-core/v5/common/net" "github.com/v2fly/v2ray-core/v5/common/net/packetaddr" @@ -50,6 +52,7 @@ func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) // Handler is an implements of outbound.Handler. type Handler struct { + ctx context.Context tag string senderSettings *proxyman.SenderConfig streamSettings *internet.MemoryStreamConfig @@ -66,6 +69,7 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou v := core.MustFromContext(ctx) uplinkCounter, downlinkCounter := getStatCounter(v, config.Tag) h := &Handler{ + ctx: ctx, tag: config.Tag, outboundManager: v.GetFeature(outbound.ManagerType()).(outbound.Manager), uplinkCounter: uplinkCounter, @@ -251,6 +255,12 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn return h.getStatCouterConnection(conn), nil } + proxyEnvironment := envctx.EnvironmentFromContext(h.ctx).(environment.ProxyEnvironment) + transportEnvironment, err := proxyEnvironment.NarrowScopeToTransport("transport") + if err != nil { + return nil, newError("unable to narrow environment to transport").Base(err) + } + ctx = envctx.ContextWithEnvironment(ctx, transportEnvironment) conn, err := internet.Dial(ctx, dest, h.streamSettings) return h.getStatCouterConnection(conn), err } diff --git a/app/proxyman/outbound/handler_test.go b/app/proxyman/outbound/handler_test.go index a609c5872..af5c6ab68 100644 --- a/app/proxyman/outbound/handler_test.go +++ b/app/proxyman/outbound/handler_test.go @@ -5,6 +5,12 @@ import ( "testing" _ "unsafe" + "github.com/v2fly/v2ray-core/v5/common/environment/systemnetworkimpl" + + "github.com/v2fly/v2ray-core/v5/common/environment" + "github.com/v2fly/v2ray-core/v5/common/environment/envctx" + "github.com/v2fly/v2ray-core/v5/common/environment/transientstorageimpl" + "google.golang.org/protobuf/types/known/anypb" core "github.com/v2fly/v2ray-core/v5" @@ -43,6 +49,10 @@ func TestOutboundWithoutStatCounter(t *testing.T) { v, _ := core.New(config) v.AddFeature((outbound.Manager)(new(Manager))) ctx := toContext(context.Background(), v) + defaultNetworkImpl := systemnetworkimpl.NewSystemNetworkDefault() + rootEnv := environment.NewRootEnvImpl(ctx, transientstorageimpl.NewScopedTransientStorageImpl(), defaultNetworkImpl.Dialer(), defaultNetworkImpl.Listener()) + proxyEnvironment := rootEnv.ProxyEnvironment("o") + ctx = envctx.ContextWithEnvironment(ctx, proxyEnvironment) h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{ Tag: "tag", ProxySettings: serial.ToTypedMessage(&freedom.Config{}), @@ -72,6 +82,10 @@ func TestOutboundWithStatCounter(t *testing.T) { v, _ := core.New(config) v.AddFeature((outbound.Manager)(new(Manager))) ctx := toContext(context.Background(), v) + defaultNetworkImpl := systemnetworkimpl.NewSystemNetworkDefault() + rootEnv := environment.NewRootEnvImpl(ctx, transientstorageimpl.NewScopedTransientStorageImpl(), defaultNetworkImpl.Dialer(), defaultNetworkImpl.Listener()) + proxyEnvironment := rootEnv.ProxyEnvironment("o") + ctx = envctx.ContextWithEnvironment(ctx, proxyEnvironment) h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{ Tag: "tag", ProxySettings: serial.ToTypedMessage(&freedom.Config{}), diff --git a/common/environment/rootcap_impl.go b/common/environment/rootcap_impl.go index acea6a516..85ca4eab1 100644 --- a/common/environment/rootcap_impl.go +++ b/common/environment/rootcap_impl.go @@ -9,12 +9,21 @@ import ( "github.com/v2fly/v2ray-core/v5/transport/internet/tagged" ) -func NewRootEnvImpl(ctx context.Context, transientStorage storage.ScopedTransientStorage) RootEnvironment { - return &rootEnvImpl{transientStorage: transientStorage, ctx: ctx} +func NewRootEnvImpl(ctx context.Context, transientStorage storage.ScopedTransientStorage, + systemDialer internet.SystemDialer, systemListener internet.SystemListener, +) RootEnvironment { + return &rootEnvImpl{ + transientStorage: transientStorage, + systemListener: systemListener, + systemDialer: systemDialer, + ctx: ctx, + } } type rootEnvImpl struct { transientStorage storage.ScopedTransientStorage + systemDialer internet.SystemDialer + systemListener internet.SystemListener ctx context.Context } @@ -30,6 +39,8 @@ func (r *rootEnvImpl) AppEnvironment(tag string) AppEnvironment { } return &appEnvImpl{ transientStorage: transientStorage, + systemListener: r.systemListener, + systemDialer: r.systemDialer, ctx: r.ctx, } } @@ -41,12 +52,16 @@ func (r *rootEnvImpl) ProxyEnvironment(tag string) ProxyEnvironment { } return &proxyEnvImpl{ transientStorage: transientStorage, + systemListener: r.systemListener, + systemDialer: r.systemDialer, ctx: r.ctx, } } type appEnvImpl struct { transientStorage storage.ScopedTransientStorage + systemDialer internet.SystemDialer + systemListener internet.SystemListener ctx context.Context } @@ -98,6 +113,8 @@ func (a *appEnvImpl) NarrowScope(key string) (AppEnvironment, error) { } return &appEnvImpl{ transientStorage: transientStorage, + systemDialer: a.systemDialer, + systemListener: a.systemListener, ctx: a.ctx, }, nil } @@ -108,6 +125,8 @@ func (a *appEnvImpl) doNotImpl() { type proxyEnvImpl struct { transientStorage storage.ScopedTransientStorage + systemDialer internet.SystemDialer + systemListener internet.SystemListener ctx context.Context } @@ -156,6 +175,8 @@ func (p *proxyEnvImpl) doNotImpl() { type transportEnvImpl struct { transientStorage storage.ScopedTransientStorage + systemDialer internet.SystemDialer + systemListener internet.SystemListener ctx context.Context } diff --git a/common/environment/systemnetworkimpl/systemnetwork.go b/common/environment/systemnetworkimpl/systemnetwork.go new file mode 100644 index 000000000..e6e770cd0 --- /dev/null +++ b/common/environment/systemnetworkimpl/systemnetwork.go @@ -0,0 +1,84 @@ +package systemnetworkimpl + +import ( + "context" + + "github.com/v2fly/v2ray-core/v5/common/environment" + "github.com/v2fly/v2ray-core/v5/common/net" + "github.com/v2fly/v2ray-core/v5/transport/internet" +) + +func NewSystemNetworkImpl(listener internet.SystemListener, dialer internet.SystemDialer) environment.SystemNetworkCapabilitySet { + return &systemNetworkImpl{dialer: dialer, listener: listener} +} + +type systemDefaultDialer struct{} + +func (s systemDefaultDialer) Listen(ctx context.Context, addr net.Addr, sockopt *internet.SocketConfig) (net.Listener, error) { + return internet.ListenSystem(ctx, addr, sockopt) +} + +func (s systemDefaultDialer) ListenPacket(ctx context.Context, addr net.Addr, sockopt *internet.SocketConfig) (net.PacketConn, error) { + return internet.ListenSystemPacket(ctx, addr, sockopt) +} + +func (s systemDefaultDialer) Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *internet.SocketConfig) (net.Conn, error) { + return internet.DialSystem(ctx, destination, sockopt) +} + +func NewSystemNetworkDefault() environment.SystemNetworkCapabilitySet { + systemDefault := systemDefaultDialer{} + return &systemNetworkImpl{dialer: systemDefault, listener: systemDefault} +} + +type systemNetworkImpl struct { + listener internet.SystemListener + dialer internet.SystemDialer +} + +func (s systemNetworkImpl) Dialer() internet.SystemDialer { + return s.dialer +} + +func (s systemNetworkImpl) Listener() internet.SystemListener { + return s.listener +} + +func NewSystemListenerWithDefaultOpt(listener internet.SystemListener, opt *internet.SocketConfig) internet.SystemListener { + return systemListenerWithDefaultOpt{SystemListener: listener, opt: opt} +} + +type systemListenerWithDefaultOpt struct { + internet.SystemListener + opt *internet.SocketConfig +} + +func (s systemListenerWithDefaultOpt) Listen(ctx context.Context, addr net.Addr, sockopt *internet.SocketConfig) (net.Listener, error) { + if sockopt == nil { + return s.Listen(ctx, addr, s.opt) + } + return s.Listen(ctx, addr, sockopt) +} + +func (s systemListenerWithDefaultOpt) ListenPacket(ctx context.Context, addr net.Addr, sockopt *internet.SocketConfig) (net.PacketConn, error) { + if sockopt == nil { + return s.ListenPacket(ctx, addr, s.opt) + } + return s.ListenPacket(ctx, addr, sockopt) +} + +func NewSystemDialerWithDefaultOpt(listener internet.SystemDialer, opt *internet.SocketConfig) internet.SystemDialer { + return systemDialerWithDefaultOpt{SystemDialer: listener, opt: opt} +} + +type systemDialerWithDefaultOpt struct { + internet.SystemDialer + opt *internet.SocketConfig +} + +func (s systemDialerWithDefaultOpt) Dial(ctx context.Context, source net.Address, destination net.Destination, sockopt *internet.SocketConfig) (net.Conn, error) { + if sockopt == nil { + return s.Dial(ctx, source, destination, s.opt) + } + return s.Dial(ctx, source, destination, sockopt) +} diff --git a/v2ray.go b/v2ray.go index 4ca389f07..2d0397d91 100644 --- a/v2ray.go +++ b/v2ray.go @@ -3,10 +3,11 @@ package core import ( "context" "reflect" - "sync" + sync "sync" "github.com/v2fly/v2ray-core/v5/common" "github.com/v2fly/v2ray-core/v5/common/environment" + "github.com/v2fly/v2ray-core/v5/common/environment/systemnetworkimpl" "github.com/v2fly/v2ray-core/v5/common/environment/transientstorageimpl" "github.com/v2fly/v2ray-core/v5/common/serial" "github.com/v2fly/v2ray-core/v5/features" @@ -191,7 +192,8 @@ func initInstanceWithConfig(config *Config, server *Instance) (bool, error) { return true, err } - server.env = environment.NewRootEnvImpl(server.ctx, transientstorageimpl.NewScopedTransientStorageImpl()) + defaultNetworkImpl := systemnetworkimpl.NewSystemNetworkDefault() + server.env = environment.NewRootEnvImpl(server.ctx, transientstorageimpl.NewScopedTransientStorageImpl(), defaultNetworkImpl.Dialer(), defaultNetworkImpl.Listener()) for _, appSettings := range config.App { settings, err := serial.GetInstanceOf(appSettings)