mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-30 05:56:54 -05:00
handle inbound detour in vmess inbound
This commit is contained in:
parent
573d0a9c29
commit
b0adb24003
@ -10,18 +10,20 @@ import (
|
||||
"github.com/v2ray/v2ray-core/common/log"
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/common/retry"
|
||||
"github.com/v2ray/v2ray-core/proxy"
|
||||
)
|
||||
|
||||
type DokodemoDoor struct {
|
||||
tcpMutex sync.RWMutex
|
||||
udpMutex sync.RWMutex
|
||||
config *Config
|
||||
accepting bool
|
||||
address v2net.Address
|
||||
port v2net.Port
|
||||
space app.Space
|
||||
tcpListener *net.TCPListener
|
||||
udpConn *net.UDPConn
|
||||
tcpMutex sync.RWMutex
|
||||
udpMutex sync.RWMutex
|
||||
config *Config
|
||||
accepting bool
|
||||
address v2net.Address
|
||||
port v2net.Port
|
||||
space app.Space
|
||||
tcpListener *net.TCPListener
|
||||
udpConn *net.UDPConn
|
||||
listeningPort v2net.Port
|
||||
}
|
||||
|
||||
func NewDokodemoDoor(space app.Space, config *Config) *DokodemoDoor {
|
||||
@ -33,6 +35,10 @@ func NewDokodemoDoor(space app.Space, config *Config) *DokodemoDoor {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *DokodemoDoor) Port() v2net.Port {
|
||||
return this.listeningPort
|
||||
}
|
||||
|
||||
func (this *DokodemoDoor) Close() {
|
||||
this.accepting = false
|
||||
if this.tcpListener != nil {
|
||||
@ -50,6 +56,14 @@ func (this *DokodemoDoor) Close() {
|
||||
}
|
||||
|
||||
func (this *DokodemoDoor) Listen(port v2net.Port) error {
|
||||
if this.accepting {
|
||||
if this.listeningPort == port {
|
||||
return nil
|
||||
} else {
|
||||
return proxy.ErrorAlreadyListening
|
||||
}
|
||||
}
|
||||
this.listeningPort = port
|
||||
this.accepting = true
|
||||
|
||||
if this.config.Network.HasNetwork(v2net.TCPNetwork) {
|
||||
|
@ -7,4 +7,5 @@ import (
|
||||
var (
|
||||
InvalidAuthentication = errors.New("Invalid authentication.")
|
||||
InvalidProtocolVersion = errors.New("Invalid protocol version.")
|
||||
ErrorAlreadyListening = errors.New("Already listening on another port.")
|
||||
)
|
||||
|
@ -15,15 +15,17 @@ import (
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/common/retry"
|
||||
"github.com/v2ray/v2ray-core/common/serial"
|
||||
"github.com/v2ray/v2ray-core/proxy"
|
||||
"github.com/v2ray/v2ray-core/transport/ray"
|
||||
)
|
||||
|
||||
type HttpProxyServer struct {
|
||||
sync.Mutex
|
||||
accepting bool
|
||||
space app.Space
|
||||
config *Config
|
||||
tcpListener *net.TCPListener
|
||||
accepting bool
|
||||
space app.Space
|
||||
config *Config
|
||||
tcpListener *net.TCPListener
|
||||
listeningPort v2net.Port
|
||||
}
|
||||
|
||||
func NewHttpProxyServer(space app.Space, config *Config) *HttpProxyServer {
|
||||
@ -33,6 +35,10 @@ func NewHttpProxyServer(space app.Space, config *Config) *HttpProxyServer {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *HttpProxyServer) Port() v2net.Port {
|
||||
return this.listeningPort
|
||||
}
|
||||
|
||||
func (this *HttpProxyServer) Close() {
|
||||
this.accepting = false
|
||||
if this.tcpListener != nil {
|
||||
@ -44,6 +50,15 @@ func (this *HttpProxyServer) Close() {
|
||||
}
|
||||
|
||||
func (this *HttpProxyServer) Listen(port v2net.Port) error {
|
||||
if this.accepting {
|
||||
if this.listeningPort == port {
|
||||
return nil
|
||||
} else {
|
||||
return proxy.ErrorAlreadyListening
|
||||
}
|
||||
}
|
||||
this.listeningPort = port
|
||||
|
||||
tcpListener, err := net.ListenTCP("tcp", &net.TCPAddr{
|
||||
Port: int(port.Value()),
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
|
@ -13,6 +13,8 @@ type InboundConnectionHandler interface {
|
||||
Listen(port v2net.Port) error
|
||||
// Close stops the handler to accepting anymore inbound connections.
|
||||
Close()
|
||||
// Port returns the port that the handler is listening on.
|
||||
Port() v2net.Port
|
||||
}
|
||||
|
||||
// An OutboundConnectionHandler handles outbound network connection for V2Ray.
|
||||
|
@ -23,14 +23,15 @@ var (
|
||||
|
||||
// SocksServer is a SOCKS 5 proxy server
|
||||
type SocksServer struct {
|
||||
tcpMutex sync.RWMutex
|
||||
udpMutex sync.RWMutex
|
||||
accepting bool
|
||||
space app.Space
|
||||
config *Config
|
||||
tcpListener *net.TCPListener
|
||||
udpConn *net.UDPConn
|
||||
udpAddress v2net.Destination
|
||||
tcpMutex sync.RWMutex
|
||||
udpMutex sync.RWMutex
|
||||
accepting bool
|
||||
space app.Space
|
||||
config *Config
|
||||
tcpListener *net.TCPListener
|
||||
udpConn *net.UDPConn
|
||||
udpAddress v2net.Destination
|
||||
listeningPort v2net.Port
|
||||
}
|
||||
|
||||
func NewSocksServer(space app.Space, config *Config) *SocksServer {
|
||||
@ -40,6 +41,10 @@ func NewSocksServer(space app.Space, config *Config) *SocksServer {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *SocksServer) Port() v2net.Port {
|
||||
return this.listeningPort
|
||||
}
|
||||
|
||||
func (this *SocksServer) Close() {
|
||||
this.accepting = false
|
||||
if this.tcpListener != nil {
|
||||
@ -57,6 +62,15 @@ func (this *SocksServer) Close() {
|
||||
}
|
||||
|
||||
func (this *SocksServer) Listen(port v2net.Port) error {
|
||||
if this.accepting {
|
||||
if this.listeningPort == port {
|
||||
return nil
|
||||
} else {
|
||||
return proxy.ErrorAlreadyListening
|
||||
}
|
||||
}
|
||||
this.listeningPort = port
|
||||
|
||||
listener, err := net.ListenTCP("tcp", &net.TCPAddr{
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
Port: int(port),
|
||||
|
@ -9,17 +9,21 @@ import (
|
||||
)
|
||||
|
||||
type InboundConnectionHandler struct {
|
||||
Port v2net.Port
|
||||
port v2net.Port
|
||||
Space app.Space
|
||||
ConnInput io.Reader
|
||||
ConnOutput io.Writer
|
||||
}
|
||||
|
||||
func (this *InboundConnectionHandler) Listen(port v2net.Port) error {
|
||||
this.Port = port
|
||||
this.port = port
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *InboundConnectionHandler) Port() v2net.Port {
|
||||
return this.port
|
||||
}
|
||||
|
||||
func (this *InboundConnectionHandler) Close() {
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package command
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
v2net "github.com/v2ray/v2ray-core/common/net"
|
||||
"github.com/v2ray/v2ray-core/common/serial"
|
||||
@ -22,44 +21,33 @@ func init() {
|
||||
// 2 bytes: alterid
|
||||
// 8 bytes: time
|
||||
type SwitchAccount struct {
|
||||
Host v2net.Address
|
||||
Port v2net.Port
|
||||
ID *uuid.UUID
|
||||
AlterIds serial.Uint16Literal
|
||||
ValidUntil time.Time
|
||||
Host v2net.Address
|
||||
Port v2net.Port
|
||||
ID *uuid.UUID
|
||||
AlterIds serial.Uint16Literal
|
||||
ValidSec serial.Uint16Literal
|
||||
}
|
||||
|
||||
func (this *SwitchAccount) Marshal(writer io.Writer) (int, error) {
|
||||
outBytes := 0
|
||||
func (this *SwitchAccount) Marshal(writer io.Writer) {
|
||||
hostStr := ""
|
||||
if this.Host != nil {
|
||||
hostStr = this.Host.String()
|
||||
}
|
||||
writer.Write([]byte{byte(len(hostStr))})
|
||||
outBytes++
|
||||
|
||||
if len(hostStr) > 0 {
|
||||
writer.Write([]byte(hostStr))
|
||||
outBytes += len(hostStr)
|
||||
}
|
||||
|
||||
writer.Write(this.Port.Bytes())
|
||||
outBytes += 2
|
||||
|
||||
idBytes := this.ID.Bytes()
|
||||
writer.Write(idBytes)
|
||||
outBytes += len(idBytes)
|
||||
|
||||
writer.Write(this.AlterIds.Bytes())
|
||||
outBytes += 2
|
||||
|
||||
timestamp := this.ValidUntil.Unix()
|
||||
timeBytes := serial.Int64Literal(timestamp).Bytes()
|
||||
|
||||
timeBytes := this.ValidSec.Bytes()
|
||||
writer.Write(timeBytes)
|
||||
outBytes += len(timeBytes)
|
||||
|
||||
return outBytes, nil
|
||||
}
|
||||
|
||||
func (this *SwitchAccount) Unmarshal(data []byte) error {
|
||||
@ -84,9 +72,9 @@ func (this *SwitchAccount) Unmarshal(data []byte) error {
|
||||
}
|
||||
this.AlterIds = serial.ParseUint16(data[alterIdStart : alterIdStart+2])
|
||||
timeStart := alterIdStart + 2
|
||||
if len(data) < timeStart+8 {
|
||||
if len(data) < timeStart+2 {
|
||||
return transport.CorruptedPacket
|
||||
}
|
||||
this.ValidUntil = time.Unix(serial.BytesLiteral(data[timeStart:timeStart+8]).Int64Value(), 0)
|
||||
this.ValidSec = serial.ParseUint16(data[timeStart : timeStart+2])
|
||||
return nil
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package command_test
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
netassert "github.com/v2ray/v2ray-core/common/net/testing/assert"
|
||||
"github.com/v2ray/v2ray-core/common/uuid"
|
||||
@ -16,19 +15,17 @@ func TestSwitchAccount(t *testing.T) {
|
||||
v2testing.Current(t)
|
||||
|
||||
sa := &SwitchAccount{
|
||||
Port: 1234,
|
||||
ID: uuid.New(),
|
||||
AlterIds: 1024,
|
||||
ValidUntil: time.Now(),
|
||||
Port: 1234,
|
||||
ID: uuid.New(),
|
||||
AlterIds: 1024,
|
||||
ValidSec: 8080,
|
||||
}
|
||||
|
||||
cmd, err := CreateResponseCommand(1)
|
||||
assert.Error(err).IsNil()
|
||||
|
||||
buffer := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
nBytes, err := sa.Marshal(buffer)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Int(nBytes).Equals(buffer.Len())
|
||||
sa.Marshal(buffer)
|
||||
|
||||
cmd.Unmarshal(buffer.Bytes())
|
||||
sa2, ok := cmd.(*SwitchAccount)
|
||||
@ -36,5 +33,5 @@ func TestSwitchAccount(t *testing.T) {
|
||||
netassert.Port(sa.Port).Equals(sa2.Port)
|
||||
assert.String(sa.ID).Equals(sa2.ID.String())
|
||||
assert.Uint16(sa.AlterIds.Value()).Equals(sa2.AlterIds.Value())
|
||||
assert.Int64(sa.ValidUntil.Unix()).Equals(sa2.ValidUntil.Unix())
|
||||
assert.Uint16(sa.ValidSec.Value()).Equals(sa2.ValidSec.Value())
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ var (
|
||||
)
|
||||
|
||||
type Command interface {
|
||||
Marshal(io.Writer) (int, error)
|
||||
Marshal(io.Writer)
|
||||
Unmarshal([]byte) error
|
||||
}
|
||||
|
||||
|
@ -26,20 +26,16 @@ type CacheDns struct {
|
||||
Address v2net.Address
|
||||
}
|
||||
|
||||
func (this *CacheDns) Marshal(writer io.Writer) (int, error) {
|
||||
func (this *CacheDns) Marshal(writer io.Writer) {
|
||||
if this.Address.IsIPv4() {
|
||||
writer.Write([]byte{typeIPv4})
|
||||
writer.Write(this.Address.IP())
|
||||
return 5, nil
|
||||
}
|
||||
|
||||
if this.Address.IsIPv6() {
|
||||
writer.Write([]byte{typeIPv6})
|
||||
writer.Write(this.Address.IP())
|
||||
return 17, nil
|
||||
}
|
||||
|
||||
return 0, ErrDomainAddress
|
||||
}
|
||||
|
||||
func (this *CacheDns) Unmarshal(data []byte) error {
|
||||
|
@ -21,12 +21,10 @@ func TestCacheDnsIPv4(t *testing.T) {
|
||||
buffer := alloc.NewBuffer().Clear()
|
||||
defer buffer.Release()
|
||||
|
||||
nBytes, err := cd.Marshal(buffer)
|
||||
assert.Error(err).IsNil()
|
||||
assert.Int(nBytes).Equals(buffer.Len())
|
||||
cd.Marshal(buffer)
|
||||
|
||||
cd2 := &CacheDns{}
|
||||
err = cd2.Unmarshal(buffer.Value)
|
||||
err := cd2.Unmarshal(buffer.Value)
|
||||
assert.Error(err).IsNil()
|
||||
netassert.Address(cd.Address).Equals(cd2.Address)
|
||||
}
|
||||
|
45
proxy/vmess/inbound/command.go
Normal file
45
proxy/vmess/inbound/command.go
Normal file
@ -0,0 +1,45 @@
|
||||
package inbound
|
||||
|
||||
import (
|
||||
"github.com/v2ray/v2ray-core/common/alloc"
|
||||
"github.com/v2ray/v2ray-core/common/serial"
|
||||
"github.com/v2ray/v2ray-core/proxy/vmess/command"
|
||||
)
|
||||
|
||||
func (this *VMessInboundHandler) generateCommand(buffer *alloc.Buffer) {
|
||||
cmd := byte(0)
|
||||
commandBytes := alloc.NewSmallBuffer().Clear()
|
||||
defer commandBytes.Release()
|
||||
|
||||
if this.features != nil && this.features.Detour != nil {
|
||||
tag := this.features.Detour.ToTag
|
||||
if this.space.HasInboundHandlerManager() {
|
||||
handlerManager := this.space.InboundHandlerManager()
|
||||
handler, availableSec := handlerManager.GetHandler(tag)
|
||||
inboundHandler, ok := handler.(*VMessInboundHandler)
|
||||
if ok {
|
||||
user := inboundHandler.GetUser()
|
||||
availableSecUint16 := uint16(65535)
|
||||
if availableSec < 65535 {
|
||||
availableSecUint16 = uint16(availableSec)
|
||||
}
|
||||
|
||||
saCmd := &command.SwitchAccount{
|
||||
Port: inboundHandler.Port(),
|
||||
ID: user.ID.UUID(),
|
||||
AlterIds: serial.Uint16Literal(len(user.AlterIDs)),
|
||||
ValidSec: serial.Uint16Literal(availableSecUint16),
|
||||
}
|
||||
saCmd.Marshal(commandBytes)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if commandBytes.Len() > 256 {
|
||||
buffer.AppendBytes(byte(0), byte(0))
|
||||
} else {
|
||||
buffer.AppendBytes(cmd, byte(commandBytes.Len()))
|
||||
buffer.Append(commandBytes.Value)
|
||||
}
|
||||
}
|
@ -22,17 +22,17 @@ import (
|
||||
// Inbound connection handler that handles messages in VMess format.
|
||||
type VMessInboundHandler struct {
|
||||
sync.Mutex
|
||||
space app.Space
|
||||
clients protocol.UserSet
|
||||
accepting bool
|
||||
listener *net.TCPListener
|
||||
space app.Space
|
||||
clients protocol.UserSet
|
||||
user *vmess.User
|
||||
accepting bool
|
||||
listener *net.TCPListener
|
||||
features *FeaturesConfig
|
||||
listeningPort v2net.Port
|
||||
}
|
||||
|
||||
func NewVMessInboundHandler(space app.Space, clients protocol.UserSet) *VMessInboundHandler {
|
||||
return &VMessInboundHandler{
|
||||
space: space,
|
||||
clients: clients,
|
||||
}
|
||||
func (this *VMessInboundHandler) Port() v2net.Port {
|
||||
return this.listeningPort
|
||||
}
|
||||
|
||||
func (this *VMessInboundHandler) Close() {
|
||||
@ -45,11 +45,20 @@ func (this *VMessInboundHandler) Close() {
|
||||
}
|
||||
}
|
||||
|
||||
func (this *VMessInboundHandler) AddUser(user vmess.User) {
|
||||
|
||||
func (this *VMessInboundHandler) GetUser() *vmess.User {
|
||||
return this.user
|
||||
}
|
||||
|
||||
func (this *VMessInboundHandler) Listen(port v2net.Port) error {
|
||||
if this.accepting {
|
||||
if this.listeningPort == port {
|
||||
return nil
|
||||
} else {
|
||||
return proxy.ErrorAlreadyListening
|
||||
}
|
||||
}
|
||||
this.listeningPort = port
|
||||
|
||||
listener, err := net.ListenTCP("tcp", &net.TCPAddr{
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
Port: int(port),
|
||||
@ -175,6 +184,11 @@ func init() {
|
||||
allowedClients.AddUser(user)
|
||||
}
|
||||
|
||||
return NewVMessInboundHandler(space, allowedClients), nil
|
||||
return &VMessInboundHandler{
|
||||
space: space,
|
||||
clients: allowedClients,
|
||||
features: config.Features,
|
||||
user: config.AllowedUsers[0],
|
||||
}, nil
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user