mirror of
				https://github.com/v2fly/v2ray-core.git
				synced 2025-10-26 15:25:07 +00:00 
			
		
		
		
	Remove VMess UDP
This commit is contained in:
		
							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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 V2Ray
						V2Ray