diff --git a/app/dispatcher/dispatcher.go b/app/dispatcher/dispatcher.go index a8902a3d..0447b6a3 100644 --- a/app/dispatcher/dispatcher.go +++ b/app/dispatcher/dispatcher.go @@ -3,6 +3,7 @@ package dispatcher import ( "github.com/v2ray/v2ray-core/app" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" "github.com/v2ray/v2ray-core/transport/ray" ) @@ -12,5 +13,5 @@ const ( // PacketDispatcher dispatch a packet and possibly further network payload to its destination. type PacketDispatcher interface { - DispatchToOutbound(destination v2net.Destination) ray.InboundRay + DispatchToOutbound(meta *proxy.InboundHandlerMeta, destination v2net.Destination) ray.InboundRay } diff --git a/app/dispatcher/impl/default.go b/app/dispatcher/impl/default.go index 0643cdc2..cc823d5d 100644 --- a/app/dispatcher/impl/default.go +++ b/app/dispatcher/impl/default.go @@ -4,6 +4,7 @@ import ( "github.com/v2ray/v2ray-core/app" "github.com/v2ray/v2ray-core/app/proxyman" "github.com/v2ray/v2ray-core/app/router" + "github.com/v2ray/v2ray-core/common/alloc" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" "github.com/v2ray/v2ray-core/proxy" @@ -42,7 +43,7 @@ func (this *DefaultDispatcher) Release() { } -func (this *DefaultDispatcher) DispatchToOutbound(destination v2net.Destination) ray.InboundRay { +func (this *DefaultDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, destination v2net.Destination) ray.InboundRay { direct := ray.NewRay() dispatcher := this.ohm.GetDefaultHandler() @@ -59,7 +60,11 @@ func (this *DefaultDispatcher) DispatchToOutbound(destination v2net.Destination) } } - go this.FilterPacketAndDispatch(destination, direct, dispatcher) + if meta.AllowPassiveConnection { + go dispatcher.Dispatch(destination, alloc.NewLocalBuffer(32).Clear(), direct) + } else { + go this.FilterPacketAndDispatch(destination, direct, dispatcher) + } return direct } diff --git a/app/dispatcher/testing/dispatcher.go b/app/dispatcher/testing/dispatcher.go index 2ae1f1a0..e9bf69cd 100644 --- a/app/dispatcher/testing/dispatcher.go +++ b/app/dispatcher/testing/dispatcher.go @@ -2,6 +2,7 @@ package testing import ( v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" "github.com/v2ray/v2ray-core/transport/ray" ) @@ -29,7 +30,7 @@ func NewTestPacketDispatcher(handler func(destination v2net.Destination, traffic } } -func (this *TestPacketDispatcher) DispatchToOutbound(destination v2net.Destination) ray.InboundRay { +func (this *TestPacketDispatcher) DispatchToOutbound(meta *proxy.InboundHandlerMeta, destination v2net.Destination) ray.InboundRay { traffic := ray.NewRay() this.Destination <- destination go this.Handler(destination, traffic) diff --git a/app/dns/nameserver.go b/app/dns/nameserver.go index 26f9b3d5..475f729d 100644 --- a/app/dns/nameserver.go +++ b/app/dns/nameserver.go @@ -10,6 +10,7 @@ import ( "github.com/v2ray/v2ray-core/common/dice" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" "github.com/v2ray/v2ray-core/transport/internet/udp" "github.com/miekg/dns" @@ -49,9 +50,11 @@ type UDPNameServer struct { func NewUDPNameServer(address v2net.Destination, dispatcher dispatcher.PacketDispatcher) *UDPNameServer { s := &UDPNameServer{ - address: address, - requests: make(map[uint16]*PendingRequest), - udpServer: udp.NewUDPServer(dispatcher), + address: address, + requests: make(map[uint16]*PendingRequest), + udpServer: udp.NewUDPServer(&proxy.InboundHandlerMeta{ + AllowPassiveConnection: false, + }, dispatcher), } return s } diff --git a/proxy/dokodemo/dokodemo.go b/proxy/dokodemo/dokodemo.go index 42d3b25a..db60fbf2 100644 --- a/proxy/dokodemo/dokodemo.go +++ b/proxy/dokodemo/dokodemo.go @@ -89,7 +89,7 @@ func (this *DokodemoDoor) Start() error { } func (this *DokodemoDoor) ListenUDP() error { - this.udpServer = udp.NewUDPServer(this.packetDispatcher) + this.udpServer = udp.NewUDPServer(this.meta, this.packetDispatcher) udpHub, err := udp.ListenUDP(this.meta.Address, this.meta.Port, this.handleUDPPackets) if err != nil { log.Error("Dokodemo failed to listen on ", this.meta.Address, ":", this.meta.Port, ": ", err) @@ -148,7 +148,7 @@ func (this *DokodemoDoor) HandleTCPConnection(conn internet.Connection) { } log.Info("Dokodemo: Handling request to ", dest) - ray := this.packetDispatcher.DispatchToOutbound(dest) + ray := this.packetDispatcher.DispatchToOutbound(this.meta, dest) defer ray.InboundOutput().Release() var inputFinish, outputFinish sync.Mutex diff --git a/proxy/http/server.go b/proxy/http/server.go index 453b04c9..008b092c 100644 --- a/proxy/http/server.go +++ b/proxy/http/server.go @@ -140,7 +140,7 @@ func (this *Server) handleConnect(request *http.Request, destination v2net.Desti } response.Write(writer) - ray := this.packetDispatcher.DispatchToOutbound(destination) + ray := this.packetDispatcher.DispatchToOutbound(this.meta, destination) this.transport(reader, writer, ray) } @@ -220,7 +220,7 @@ func (this *Server) handlePlainHTTP(request *http.Request, dest v2net.Destinatio request.Host = request.URL.Host StripHopByHopHeaders(request) - ray := this.packetDispatcher.DispatchToOutbound(dest) + ray := this.packetDispatcher.DispatchToOutbound(this.meta, dest) defer ray.InboundInput().Close() defer ray.InboundOutput().Release() diff --git a/proxy/proxy.go b/proxy/proxy.go index c8ee37e9..978a7a33 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -16,10 +16,11 @@ const ( ) type InboundHandlerMeta struct { - Tag string - Address v2net.Address - Port v2net.Port - StreamSettings *internet.StreamSettings + Tag string + Address v2net.Address + Port v2net.Port + AllowPassiveConnection bool + StreamSettings *internet.StreamSettings } type OutboundHandlerMeta struct { diff --git a/proxy/shadowsocks/server.go b/proxy/shadowsocks/server.go index 884927c7..d54ff250 100644 --- a/proxy/shadowsocks/server.go +++ b/proxy/shadowsocks/server.go @@ -70,7 +70,7 @@ func (this *Server) Start() error { this.tcpHub = tcpHub if this.config.UDP { - this.udpServer = udp.NewUDPServer(this.packetDispatcher) + this.udpServer = udp.NewUDPServer(this.meta, this.packetDispatcher) udpHub, err := udp.ListenUDP(this.meta.Address, this.meta.Port, this.handlerUDPPayload) if err != nil { log.Error("Shadowsocks: Failed to listen UDP on ", this.meta.Address, ":", this.meta.Port, ": ", err) @@ -204,7 +204,7 @@ func (this *Server) handleConnection(conn internet.Connection) { log.Access(conn.RemoteAddr(), dest, log.AccessAccepted, "") log.Info("Shadowsocks: Tunnelling request to ", dest) - ray := this.packetDispatcher.DispatchToOutbound(dest) + ray := this.packetDispatcher.DispatchToOutbound(this.meta, dest) defer ray.InboundOutput().Release() var writeFinish sync.Mutex diff --git a/proxy/socks/server.go b/proxy/socks/server.go index 90b0f562..4bb01d57 100644 --- a/proxy/socks/server.go +++ b/proxy/socks/server.go @@ -283,7 +283,7 @@ func (this *Server) handleSocks4(clientAddr string, reader *v2io.BufferedReader, } func (this *Server) transport(reader io.Reader, writer io.Writer, destination v2net.Destination) { - ray := this.packetDispatcher.DispatchToOutbound(destination) + ray := this.packetDispatcher.DispatchToOutbound(this.meta, destination) input := ray.InboundInput() output := ray.InboundOutput() diff --git a/proxy/socks/server_udp.go b/proxy/socks/server_udp.go index 34f5d2ae..78f1beef 100644 --- a/proxy/socks/server_udp.go +++ b/proxy/socks/server_udp.go @@ -9,7 +9,7 @@ import ( ) func (this *Server) listenUDP() error { - this.udpServer = udp.NewUDPServer(this.packetDispatcher) + this.udpServer = udp.NewUDPServer(this.meta, this.packetDispatcher) udpHub, err := udp.ListenUDP(this.meta.Address, this.meta.Port, this.handleUDPPayload) if err != nil { log.Error("Socks: Failed to listen on udp ", this.meta.Address, ":", this.meta.Port) diff --git a/proxy/testing/mocks/inboundhandler.go b/proxy/testing/mocks/inboundhandler.go index 2e076b7f..e09da586 100644 --- a/proxy/testing/mocks/inboundhandler.go +++ b/proxy/testing/mocks/inboundhandler.go @@ -7,6 +7,7 @@ import ( "github.com/v2ray/v2ray-core/app/dispatcher" v2io "github.com/v2ray/v2ray-core/common/io" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" ) type InboundConnectionHandler struct { @@ -30,7 +31,9 @@ func (this *InboundConnectionHandler) Close() { } func (this *InboundConnectionHandler) Communicate(destination v2net.Destination) error { - ray := this.PacketDispatcher.DispatchToOutbound(destination) + ray := this.PacketDispatcher.DispatchToOutbound(&proxy.InboundHandlerMeta{ + AllowPassiveConnection: false, + }, destination) input := ray.InboundInput() output := ray.InboundOutput() diff --git a/proxy/vmess/inbound/inbound.go b/proxy/vmess/inbound/inbound.go index 14117cf0..1e201343 100644 --- a/proxy/vmess/inbound/inbound.go +++ b/proxy/vmess/inbound/inbound.go @@ -163,7 +163,7 @@ func (this *VMessInboundHandler) HandleConnection(connection internet.Connection connection.SetReusable(request.Option.Has(protocol.RequestOptionConnectionReuse)) - ray := this.packetDispatcher.DispatchToOutbound(request.Destination()) + ray := this.packetDispatcher.DispatchToOutbound(this.meta, request.Destination()) input := ray.InboundInput() output := ray.InboundOutput() defer input.Close() diff --git a/shell/point/config.go b/shell/point/config.go index 01cbcef5..0d02bffa 100644 --- a/shell/point/config.go +++ b/shell/point/config.go @@ -10,11 +10,12 @@ import ( ) type InboundConnectionConfig struct { - Port v2net.Port - ListenOn v2net.Address - StreamSettings *internet.StreamSettings - Protocol string - Settings []byte + Port v2net.Port + ListenOn v2net.Address + StreamSettings *internet.StreamSettings + Protocol string + Settings []byte + AllowPassiveConnection bool } type OutboundConnectionConfig struct { @@ -43,13 +44,14 @@ type InboundDetourAllocationConfig struct { } type InboundDetourConfig struct { - Protocol string - PortRange v2net.PortRange - ListenOn v2net.Address - Tag string - Allocation *InboundDetourAllocationConfig - StreamSettings *internet.StreamSettings - Settings []byte + Protocol string + PortRange v2net.PortRange + ListenOn v2net.Address + Tag string + Allocation *InboundDetourAllocationConfig + StreamSettings *internet.StreamSettings + Settings []byte + AllowPassiveConnection bool } type OutboundDetourConfig struct { diff --git a/shell/point/config_json.go b/shell/point/config_json.go index a636cbdf..254f2b26 100644 --- a/shell/point/config_json.go +++ b/shell/point/config_json.go @@ -71,6 +71,7 @@ func (this *InboundConnectionConfig) UnmarshalJSON(data []byte) error { Protocol string `json:"protocol"` StreamSetting *internet.StreamSettings `json:"streamSettings"` Settings json.RawMessage `json:"settings"` + AllowPassive bool `json:"allowPassive"` } jsonConfig := new(JsonConfig) @@ -91,6 +92,7 @@ func (this *InboundConnectionConfig) UnmarshalJSON(data []byte) error { this.Protocol = jsonConfig.Protocol this.Settings = jsonConfig.Settings + this.AllowPassiveConnection = jsonConfig.AllowPassive return nil } @@ -186,6 +188,7 @@ func (this *InboundDetourConfig) UnmarshalJSON(data []byte) error { Tag string `json:"tag"` Allocation *InboundDetourAllocationConfig `json:"allocate"` StreamSetting *internet.StreamSettings `json:"streamSettings"` + AllowPassive bool `json:"allowPassive"` } jsonConfig := new(JsonInboundDetourConfig) if err := json.Unmarshal(data, jsonConfig); err != nil { @@ -216,6 +219,7 @@ func (this *InboundDetourConfig) UnmarshalJSON(data []byte) error { if jsonConfig.StreamSetting != nil { this.StreamSettings = jsonConfig.StreamSetting } + this.AllowPassiveConnection = jsonConfig.AllowPassive return nil } diff --git a/shell/point/inbound_detour_always.go b/shell/point/inbound_detour_always.go index d439443d..bbe99c73 100644 --- a/shell/point/inbound_detour_always.go +++ b/shell/point/inbound_detour_always.go @@ -26,10 +26,12 @@ func NewInboundDetourHandlerAlways(space app.Space, config *InboundDetourConfig) for i := ports.From; i <= ports.To; i++ { ichConfig := config.Settings ich, err := proxyrepo.CreateInboundHandler(config.Protocol, space, ichConfig, &proxy.InboundHandlerMeta{ - Address: config.ListenOn, - Port: i, - Tag: config.Tag, - StreamSettings: config.StreamSettings}) + Address: config.ListenOn, + Port: i, + Tag: config.Tag, + StreamSettings: config.StreamSettings, + AllowPassiveConnection: config.AllowPassiveConnection, + }) if err != nil { log.Error("Failed to create inbound connection handler: ", err) return nil, err diff --git a/shell/point/inbound_detour_dynamic.go b/shell/point/inbound_detour_dynamic.go index 634525a3..4303d071 100644 --- a/shell/point/inbound_detour_dynamic.go +++ b/shell/point/inbound_detour_dynamic.go @@ -33,10 +33,12 @@ func NewInboundDetourHandlerDynamic(space app.Space, config *InboundDetourConfig // To test configuration ich, err := proxyrepo.CreateInboundHandler(config.Protocol, space, config.Settings, &proxy.InboundHandlerMeta{ - Address: config.ListenOn, - Port: 0, - Tag: config.Tag, - StreamSettings: config.StreamSettings}) + Address: config.ListenOn, + Port: 0, + Tag: config.Tag, + StreamSettings: config.StreamSettings, + AllowPassiveConnection: config.AllowPassiveConnection, + }) if err != nil { log.Error("Point: Failed to create inbound connection handler: ", err) return nil, err diff --git a/shell/point/point.go b/shell/point/point.go index 57276d10..5c53d978 100644 --- a/shell/point/point.go +++ b/shell/point/point.go @@ -93,10 +93,12 @@ func NewPoint(pConfig *Config) (*Point, error) { ichConfig := pConfig.InboundConfig.Settings ich, err := proxyrepo.CreateInboundHandler( pConfig.InboundConfig.Protocol, vpoint.space, ichConfig, &proxy.InboundHandlerMeta{ - Tag: "system.inbound", - Address: pConfig.InboundConfig.ListenOn, - Port: vpoint.port, - StreamSettings: pConfig.InboundConfig.StreamSettings}) + Tag: "system.inbound", + Address: pConfig.InboundConfig.ListenOn, + Port: vpoint.port, + StreamSettings: pConfig.InboundConfig.StreamSettings, + AllowPassiveConnection: pConfig.InboundConfig.AllowPassiveConnection, + }) if err != nil { log.Error("Failed to create inbound connection handler: ", err) return nil, err diff --git a/transport/internet/udp/udp_server.go b/transport/internet/udp/udp_server.go index ca162998..d8c64def 100644 --- a/transport/internet/udp/udp_server.go +++ b/transport/internet/udp/udp_server.go @@ -8,6 +8,7 @@ import ( "github.com/v2ray/v2ray-core/common/alloc" "github.com/v2ray/v2ray-core/common/log" v2net "github.com/v2ray/v2ray-core/common/net" + "github.com/v2ray/v2ray-core/proxy" "github.com/v2ray/v2ray-core/transport/ray" ) @@ -95,12 +96,14 @@ type UDPServer struct { sync.RWMutex conns map[string]*TimedInboundRay packetDispatcher dispatcher.PacketDispatcher + meta *proxy.InboundHandlerMeta } -func NewUDPServer(packetDispatcher dispatcher.PacketDispatcher) *UDPServer { +func NewUDPServer(meta *proxy.InboundHandlerMeta, packetDispatcher dispatcher.PacketDispatcher) *UDPServer { return &UDPServer{ conns: make(map[string]*TimedInboundRay), packetDispatcher: packetDispatcher, + meta: meta, } } @@ -137,7 +140,7 @@ func (this *UDPServer) Dispatch(source v2net.Destination, destination v2net.Dest } log.Info("UDP Server: establishing new connection for ", destString) - inboundRay := this.packetDispatcher.DispatchToOutbound(destination) + inboundRay := this.packetDispatcher.DispatchToOutbound(this.meta, destination) timedInboundRay := NewTimedInboundRay(destString, inboundRay, this) outputStream := timedInboundRay.InboundInput() if outputStream != nil {