mirror of https://github.com/v2ray/v2ray-core
Remove VMess UDP
parent
581e6b7104
commit
31fb65b3d8
|
@ -2,5 +2,4 @@ package config
|
||||||
|
|
||||||
type Inbound interface {
|
type Inbound interface {
|
||||||
AllowedUsers() []User
|
AllowedUsers() []User
|
||||||
UDPEnabled() bool
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
|
|
||||||
type Inbound struct {
|
type Inbound struct {
|
||||||
AllowedClients []*ConfigUser `json:"clients"`
|
AllowedClients []*ConfigUser `json:"clients"`
|
||||||
UDP bool `json:"udp"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Inbound) AllowedUsers() []vmessconfig.User {
|
func (c *Inbound) AllowedUsers() []vmessconfig.User {
|
||||||
|
@ -18,10 +17,6 @@ func (c *Inbound) AllowedUsers() []vmessconfig.User {
|
||||||
return users
|
return users
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Inbound) UDPEnabled() bool {
|
|
||||||
return c.UDP
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
json.RegisterInboundConnectionConfig("vmess", func() interface{} {
|
json.RegisterInboundConnectionConfig("vmess", func() interface{} {
|
||||||
return new(Inbound)
|
return new(Inbound)
|
||||||
|
|
|
@ -3,7 +3,6 @@ package json
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/v2ray/v2ray-core/common/log"
|
"github.com/v2ray/v2ray-core/common/log"
|
||||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||||
|
@ -16,18 +15,11 @@ type RawConfigTarget struct {
|
||||||
Address string `json:"address"`
|
Address string `json:"address"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
Users []*ConfigUser `json:"users"`
|
Users []*ConfigUser `json:"users"`
|
||||||
Network string `json:"network"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (config RawConfigTarget) HasNetwork(network string) bool {
|
|
||||||
return strings.Contains(config.Network, network)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigTarget struct {
|
type ConfigTarget struct {
|
||||||
Address v2net.Address
|
Address v2net.Address
|
||||||
Users []*ConfigUser
|
Users []*ConfigUser
|
||||||
TCPEnabled bool
|
|
||||||
UDPEnabled bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ConfigTarget) UnmarshalJSON(data []byte) error {
|
func (t *ConfigTarget) UnmarshalJSON(data []byte) error {
|
||||||
|
@ -42,12 +34,6 @@ func (t *ConfigTarget) UnmarshalJSON(data []byte) error {
|
||||||
return proxyconfig.BadConfiguration
|
return proxyconfig.BadConfiguration
|
||||||
}
|
}
|
||||||
t.Address = v2net.IPAddress(ip, rawConfig.Port)
|
t.Address = v2net.IPAddress(ip, rawConfig.Port)
|
||||||
if rawConfig.HasNetwork("tcp") {
|
|
||||||
t.TCPEnabled = true
|
|
||||||
}
|
|
||||||
if rawConfig.HasNetwork("udp") {
|
|
||||||
t.UDPEnabled = true
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,19 +48,11 @@ func (o *Outbound) Targets() []*vmessconfig.OutboundTarget {
|
||||||
for _, rawUser := range rawTarget.Users {
|
for _, rawUser := range rawTarget.Users {
|
||||||
users = append(users, rawUser)
|
users = append(users, rawUser)
|
||||||
}
|
}
|
||||||
if rawTarget.TCPEnabled {
|
|
||||||
targets = append(targets, &vmessconfig.OutboundTarget{
|
targets = append(targets, &vmessconfig.OutboundTarget{
|
||||||
Destination: v2net.NewTCPDestination(rawTarget.Address),
|
Destination: v2net.NewTCPDestination(rawTarget.Address),
|
||||||
Accounts: users,
|
Accounts: users,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if rawTarget.UDPEnabled {
|
|
||||||
targets = append(targets, &vmessconfig.OutboundTarget{
|
|
||||||
Destination: v2net.NewUDPDestination(rawTarget.Address),
|
|
||||||
Accounts: users,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return targets
|
return targets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/v2ray/v2ray-core/app/point"
|
"github.com/v2ray/v2ray-core/app/point"
|
||||||
"github.com/v2ray/v2ray-core/common/alloc"
|
|
||||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||||
v2nettesting "github.com/v2ray/v2ray-core/common/net/testing"
|
v2nettesting "github.com/v2ray/v2ray-core/common/net/testing"
|
||||||
"github.com/v2ray/v2ray-core/proxy/common/connhandler"
|
"github.com/v2ray/v2ray-core/proxy/common/connhandler"
|
||||||
|
@ -46,7 +45,6 @@ func TestVMessInAndOut(t *testing.T) {
|
||||||
[]*json.ConfigTarget{
|
[]*json.ConfigTarget{
|
||||||
&json.ConfigTarget{
|
&json.ConfigTarget{
|
||||||
Address: v2net.IPAddress([]byte{127, 0, 0, 1}, portB),
|
Address: v2net.IPAddress([]byte{127, 0, 0, 1}, portB),
|
||||||
TCPEnabled: true,
|
|
||||||
Users: []*json.ConfigUser{
|
Users: []*json.ConfigUser{
|
||||||
&json.ConfigUser{Id: testAccount},
|
&json.ConfigUser{Id: testAccount},
|
||||||
},
|
},
|
||||||
|
@ -98,92 +96,3 @@ func TestVMessInAndOut(t *testing.T) {
|
||||||
assert.Bytes(ichConnInput).Equals(ochConnOutput.Bytes())
|
assert.Bytes(ichConnInput).Equals(ochConnOutput.Bytes())
|
||||||
assert.Bytes(ichConnOutput.Bytes()).Equals(ochConnInput)
|
assert.Bytes(ichConnOutput.Bytes()).Equals(ochConnInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVMessInAndOutUDP(t *testing.T) {
|
|
||||||
assert := unit.Assert(t)
|
|
||||||
|
|
||||||
data2Send := "The data to be send to outbound server."
|
|
||||||
testAccount, err := config.NewID("ad937d9d-6e23-4a5a-ba23-bce5092a7c51")
|
|
||||||
assert.Error(err).IsNil()
|
|
||||||
|
|
||||||
portA := v2nettesting.PickPort()
|
|
||||||
portB := v2nettesting.PickPort()
|
|
||||||
|
|
||||||
ichConnInput := []byte("The data to be send to outbound server.")
|
|
||||||
ichConnOutput := bytes.NewBuffer(make([]byte, 0, 1024))
|
|
||||||
ich := &proxymocks.InboundConnectionHandler{
|
|
||||||
ConnInput: bytes.NewReader(ichConnInput),
|
|
||||||
ConnOutput: ichConnOutput,
|
|
||||||
}
|
|
||||||
|
|
||||||
connhandler.RegisterInboundConnectionHandlerFactory("mock_ich", ich)
|
|
||||||
|
|
||||||
configA := mocks.Config{
|
|
||||||
PortValue: portA,
|
|
||||||
InboundConfigValue: &mocks.ConnectionConfig{
|
|
||||||
ProtocolValue: "mock_ich",
|
|
||||||
SettingsValue: nil,
|
|
||||||
},
|
|
||||||
OutboundConfigValue: &mocks.ConnectionConfig{
|
|
||||||
ProtocolValue: "vmess",
|
|
||||||
SettingsValue: &json.Outbound{
|
|
||||||
[]*json.ConfigTarget{
|
|
||||||
&json.ConfigTarget{
|
|
||||||
Address: v2net.IPAddress([]byte{127, 0, 0, 1}, portB),
|
|
||||||
UDPEnabled: true,
|
|
||||||
Users: []*json.ConfigUser{
|
|
||||||
&json.ConfigUser{Id: testAccount},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pointA, err := point.NewPoint(&configA)
|
|
||||||
assert.Error(err).IsNil()
|
|
||||||
|
|
||||||
err = pointA.Start()
|
|
||||||
assert.Error(err).IsNil()
|
|
||||||
|
|
||||||
ochConnInput := []byte("The data to be returned to inbound server.")
|
|
||||||
ochConnOutput := bytes.NewBuffer(make([]byte, 0, 1024))
|
|
||||||
och := &proxymocks.OutboundConnectionHandler{
|
|
||||||
ConnInput: bytes.NewReader(ochConnInput),
|
|
||||||
ConnOutput: ochConnOutput,
|
|
||||||
}
|
|
||||||
|
|
||||||
connhandler.RegisterOutboundConnectionHandlerFactory("mock_och", och)
|
|
||||||
|
|
||||||
configB := mocks.Config{
|
|
||||||
PortValue: portB,
|
|
||||||
InboundConfigValue: &mocks.ConnectionConfig{
|
|
||||||
ProtocolValue: "vmess",
|
|
||||||
SettingsValue: &json.Inbound{
|
|
||||||
AllowedClients: []*json.ConfigUser{
|
|
||||||
&json.ConfigUser{Id: testAccount},
|
|
||||||
},
|
|
||||||
UDP: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
OutboundConfigValue: &mocks.ConnectionConfig{
|
|
||||||
ProtocolValue: "mock_och",
|
|
||||||
SettingsValue: nil,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pointB, err := point.NewPoint(&configB)
|
|
||||||
assert.Error(err).IsNil()
|
|
||||||
|
|
||||||
err = pointB.Start()
|
|
||||||
assert.Error(err).IsNil()
|
|
||||||
|
|
||||||
data2SendBuffer := alloc.NewBuffer()
|
|
||||||
data2SendBuffer.Clear()
|
|
||||||
data2SendBuffer.Append([]byte(data2Send))
|
|
||||||
dest := v2net.NewUDPDestination(v2net.IPAddress([]byte{1, 2, 3, 4}, 80))
|
|
||||||
ich.Communicate(v2net.NewPacket(dest, data2SendBuffer, false))
|
|
||||||
|
|
||||||
assert.Bytes(ichConnInput).Equals(ochConnOutput.Bytes())
|
|
||||||
assert.Bytes(ichConnOutput.Bytes()).Equals(ochConnInput)
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,14 +22,12 @@ type VMessInboundHandler struct {
|
||||||
dispatcher app.PacketDispatcher
|
dispatcher app.PacketDispatcher
|
||||||
clients user.UserSet
|
clients user.UserSet
|
||||||
accepting bool
|
accepting bool
|
||||||
udpEnabled bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVMessInboundHandler(dispatcher app.PacketDispatcher, clients user.UserSet, udpEnabled bool) *VMessInboundHandler {
|
func NewVMessInboundHandler(dispatcher app.PacketDispatcher, clients user.UserSet) *VMessInboundHandler {
|
||||||
return &VMessInboundHandler{
|
return &VMessInboundHandler{
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
clients: clients,
|
clients: clients,
|
||||||
udpEnabled: udpEnabled,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,11 +43,6 @@ func (handler *VMessInboundHandler) Listen(port uint16) error {
|
||||||
}
|
}
|
||||||
handler.accepting = true
|
handler.accepting = true
|
||||||
go handler.AcceptConnections(listener)
|
go handler.AcceptConnections(listener)
|
||||||
|
|
||||||
if handler.udpEnabled {
|
|
||||||
handler.ListenUDP(port)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +147,7 @@ func (factory *VMessInboundHandlerFactory) Create(dispatcher app.PacketDispatche
|
||||||
allowedClients.AddUser(user)
|
allowedClients.AddUser(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewVMessInboundHandler(dispatcher, allowedClients, config.UDPEnabled()), nil
|
return NewVMessInboundHandler(dispatcher, allowedClients), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -1,111 +0,0 @@
|
||||||
package vmess
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"crypto/md5"
|
|
||||||
"net"
|
|
||||||
|
|
||||||
"github.com/v2ray/v2ray-core/common/alloc"
|
|
||||||
v2crypto "github.com/v2ray/v2ray-core/common/crypto"
|
|
||||||
"github.com/v2ray/v2ray-core/common/log"
|
|
||||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
|
||||||
"github.com/v2ray/v2ray-core/proxy/vmess/protocol"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
bufferSize = 2 * 1024
|
|
||||||
)
|
|
||||||
|
|
||||||
func (handler *VMessInboundHandler) ListenUDP(port uint16) error {
|
|
||||||
addr := &net.UDPAddr{
|
|
||||||
IP: net.IP{0, 0, 0, 0},
|
|
||||||
Port: int(port),
|
|
||||||
Zone: "",
|
|
||||||
}
|
|
||||||
conn, err := net.ListenUDP("udp", addr)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("VMessIn failed to listen UDP on port %d: %v", port, err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
go handler.AcceptPackets(conn)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (handler *VMessInboundHandler) AcceptPackets(conn *net.UDPConn) {
|
|
||||||
for {
|
|
||||||
buffer := alloc.NewBuffer()
|
|
||||||
nBytes, addr, err := conn.ReadFromUDP(buffer.Value)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("VMessIn failed to read UDP packets: %v", err)
|
|
||||||
buffer.Release()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
reader := bytes.NewReader(buffer.Value[:nBytes])
|
|
||||||
requestReader := protocol.NewVMessRequestReader(handler.clients)
|
|
||||||
|
|
||||||
request, err := requestReader.Read(reader)
|
|
||||||
if err != nil {
|
|
||||||
log.Access(addr.String(), "", log.AccessRejected, err.Error())
|
|
||||||
log.Warning("VMessIn: Invalid request from (%s): %v", addr.String(), err)
|
|
||||||
buffer.Release()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
log.Access(addr.String(), request.Address.String(), log.AccessAccepted, "")
|
|
||||||
|
|
||||||
aesStream, err := v2crypto.NewAesDecryptionStream(request.RequestKey, request.RequestIV)
|
|
||||||
if err != nil {
|
|
||||||
log.Error("VMessIn: Failed to AES decryption stream: %v", err)
|
|
||||||
buffer.Release()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cryptReader := v2crypto.NewCryptionReader(aesStream, reader)
|
|
||||||
|
|
||||||
data := alloc.NewBuffer()
|
|
||||||
nBytes, err = cryptReader.Read(data.Value)
|
|
||||||
buffer.Release()
|
|
||||||
if err != nil {
|
|
||||||
log.Warning("VMessIn: Unable to decrypt data: %v", err)
|
|
||||||
data.Release()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
data.Slice(0, nBytes)
|
|
||||||
|
|
||||||
packet := v2net.NewPacket(request.Destination(), data, false)
|
|
||||||
go handler.handlePacket(conn, request, packet, addr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (handler *VMessInboundHandler) handlePacket(conn *net.UDPConn, request *protocol.VMessRequest, packet v2net.Packet, clientAddr *net.UDPAddr) {
|
|
||||||
ray := handler.dispatcher.DispatchToOutbound(packet)
|
|
||||||
close(ray.InboundInput())
|
|
||||||
|
|
||||||
responseKey := md5.Sum(request.RequestKey)
|
|
||||||
responseIV := md5.Sum(request.RequestIV)
|
|
||||||
|
|
||||||
buffer := alloc.NewBuffer().Clear()
|
|
||||||
defer buffer.Release()
|
|
||||||
|
|
||||||
aesStream, err := v2crypto.NewAesEncryptionStream(responseKey[:], responseIV[:])
|
|
||||||
if err != nil {
|
|
||||||
log.Error("VMessIn: Failed to create AES encryption stream: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
responseWriter := v2crypto.NewCryptionWriter(aesStream, buffer)
|
|
||||||
|
|
||||||
responseWriter.Write(request.ResponseHeader)
|
|
||||||
|
|
||||||
hasData := false
|
|
||||||
|
|
||||||
if data, ok := <-ray.InboundOutput(); ok {
|
|
||||||
hasData = true
|
|
||||||
responseWriter.Write(data.Value)
|
|
||||||
data.Release()
|
|
||||||
}
|
|
||||||
|
|
||||||
if hasData {
|
|
||||||
conn.WriteToUDP(buffer.Value, clientAddr)
|
|
||||||
log.Info("VMessIn sending %d bytes to %s", buffer.Len(), clientAddr.String())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,13 +21,11 @@ import (
|
||||||
|
|
||||||
type VMessOutboundHandler struct {
|
type VMessOutboundHandler struct {
|
||||||
vNextList []*config.OutboundTarget
|
vNextList []*config.OutboundTarget
|
||||||
vNextListUDP []*config.OutboundTarget
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewVMessOutboundHandler(vNextList, vNextListUDP []*config.OutboundTarget) *VMessOutboundHandler {
|
func NewVMessOutboundHandler(vNextList []*config.OutboundTarget) *VMessOutboundHandler {
|
||||||
return &VMessOutboundHandler{
|
return &VMessOutboundHandler{
|
||||||
vNextList: vNextList,
|
vNextList: vNextList,
|
||||||
vNextListUDP: vNextListUDP,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,9 +54,6 @@ func pickVNext(serverList []*config.OutboundTarget) (v2net.Destination, config.U
|
||||||
|
|
||||||
func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
|
func (handler *VMessOutboundHandler) Dispatch(firstPacket v2net.Packet, ray ray.OutboundRay) error {
|
||||||
vNextList := handler.vNextList
|
vNextList := handler.vNextList
|
||||||
if firstPacket.Destination().IsUDP() {
|
|
||||||
vNextList = handler.vNextListUDP
|
|
||||||
}
|
|
||||||
vNextAddress, vNextUser := pickVNext(vNextList)
|
vNextAddress, vNextUser := pickVNext(vNextList)
|
||||||
|
|
||||||
command := protocol.CmdTCP
|
command := protocol.CmdTCP
|
||||||
|
@ -194,17 +189,7 @@ type VMessOutboundHandlerFactory struct {
|
||||||
|
|
||||||
func (factory *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) {
|
func (factory *VMessOutboundHandlerFactory) Create(rawConfig interface{}) (connhandler.OutboundConnectionHandler, error) {
|
||||||
vOutConfig := rawConfig.(config.Outbound)
|
vOutConfig := rawConfig.(config.Outbound)
|
||||||
servers := make([]*config.OutboundTarget, 0, 16)
|
return NewVMessOutboundHandler(vOutConfig.Targets()), nil
|
||||||
udpServers := make([]*config.OutboundTarget, 0, 16)
|
|
||||||
for _, target := range vOutConfig.Targets() {
|
|
||||||
if target.Destination.IsTCP() {
|
|
||||||
servers = append(servers, target)
|
|
||||||
}
|
|
||||||
if target.Destination.IsUDP() {
|
|
||||||
udpServers = append(udpServers, target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NewVMessOutboundHandler(servers, udpServers), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
"port": 37192,
|
"port": 37192,
|
||||||
"users": [
|
"users": [
|
||||||
{"id": "27848739-7e62-4138-9fd3-098a63964b6b"}
|
{"id": "27848739-7e62-4138-9fd3-098a63964b6b"}
|
||||||
],
|
]
|
||||||
"network": "tcp"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,7 @@
|
||||||
"port": 37192,
|
"port": 37192,
|
||||||
"users": [
|
"users": [
|
||||||
{"id": "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}
|
{"id": "ad937d9d-6e23-4a5a-ba23-bce5092a7c51"}
|
||||||
],
|
]
|
||||||
"network": "tcp"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
"id": "3b129dec-72a3-4d28-aeee-028a0fe86e22",
|
"id": "3b129dec-72a3-4d28-aeee-028a0fe86e22",
|
||||||
"level": 1
|
"level": 1
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"udp": false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"outbound": {
|
"outbound": {
|
||||||
|
|
Loading…
Reference in New Issue