1
0
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:
v2ray 2016-01-19 23:41:40 +01:00
parent 573d0a9c29
commit b0adb24003
13 changed files with 163 additions and 75 deletions

View File

@ -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) {

View File

@ -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.")
)

View File

@ -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},

View File

@ -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.

View File

@ -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),

View File

@ -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() {
}

View File

@ -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
}

View File

@ -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())
}

View File

@ -10,7 +10,7 @@ var (
)
type Command interface {
Marshal(io.Writer) (int, error)
Marshal(io.Writer)
Unmarshal([]byte) error
}

View File

@ -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 {

View File

@ -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)
}

View 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)
}
}

View File

@ -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
})
}