From 84aaf3a1e36795ba82669ecf633a546c72b2c6d9 Mon Sep 17 00:00:00 2001 From: RPRX <63339210+rprx@users.noreply.github.com> Date: Fri, 28 Aug 2020 07:51:09 +0000 Subject: [PATCH] VLESS PREVIEW 1.5 --- infra/conf/vless.go | 192 ++++++++++++----------- infra/conf/vless_test.go | 65 ++++---- proxy/vless/encoding/encoding.go | 6 +- proxy/vless/inbound/config.pb.go | 250 +++++++++--------------------- proxy/vless/inbound/config.proto | 22 +-- proxy/vless/inbound/inbound.go | 205 +++++++++++++++--------- proxy/vless/outbound/config.pb.go | 35 ++--- proxy/vless/outbound/config.proto | 2 +- proxy/vless/outbound/outbound.go | 3 +- 9 files changed, 374 insertions(+), 406 deletions(-) diff --git a/infra/conf/vless.go b/infra/conf/vless.go index b13537054..64d9e9af4 100644 --- a/infra/conf/vless.go +++ b/infra/conf/vless.go @@ -2,6 +2,7 @@ package conf import ( "encoding/json" + "strconv" "github.com/golang/protobuf/proto" @@ -14,17 +15,18 @@ import ( ) type VLessInboundFallback struct { - Addr *Address `json:"addr"` - Port uint16 `json:"port"` - Unix string `json:"unix"` - Xver uint16 `json:"xver"` + Alpn string `json:"alpn"` + Path string `json:"path"` + Type string `json:"type"` + Dest json.RawMessage `json:"dest"` + Xver uint64 `json:"xver"` } type VLessInboundConfig struct { - Users []json.RawMessage `json:"clients"` - Decryption string `json:"decryption"` - Fallback *VLessInboundFallback `json:"fallback"` - Fallback_h2 *VLessInboundFallback `json:"fallback_h2"` + Clients []json.RawMessage `json:"clients"` + Decryption string `json:"decryption"` + Fallback json.RawMessage `json:"fallback"` + Fallbacks []*VLessInboundFallback `json:"fallbacks"` } // Build implements Buildable @@ -32,99 +34,103 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) { config := new(inbound.Config) + if len(c.Clients) == 0 { + return nil, newError(`VLESS settings: "clients" is empty`) + } + config.Clients = make([]*protocol.User, len(c.Clients)) + for idx, rawUser := range c.Clients { + user := new(protocol.User) + if err := json.Unmarshal(rawUser, user); err != nil { + return nil, newError(`VLESS clients: invalid user`).Base(err) + } + account := new(vless.Account) + if err := json.Unmarshal(rawUser, account); err != nil { + return nil, newError(`VLESS clients: invalid user`).Base(err) + } + + if account.Schedulers != "" { + return nil, newError(`VLESS clients: "schedulers" is not available in this version`) + } + if account.Encryption != "" { + return nil, newError(`VLESS clients: "encryption" should not in inbound settings`) + } + + user.Account = serial.ToTypedMessage(account) + config.Clients[idx] = user + } + if c.Decryption != "none" { - return nil, newError(`please add/set "decryption":"none" directly to every VLESS "settings"`) + return nil, newError(`VLESS settings: please add/set "decryption":"none" to every settings`) } config.Decryption = c.Decryption if c.Fallback != nil { - if c.Fallback.Xver > 2 { - return nil, newError(`VLESS "fallback": invalid PROXY protocol version, "xver" only accepts 0, 1, 2`) - } - if c.Fallback.Unix != "" { - if c.Fallback.Unix[0] == '@' { - c.Fallback.Unix = "\x00" + c.Fallback.Unix[1:] - } - } else { - if c.Fallback.Port == 0 { - return nil, newError(`please fill in a valid value for "port" in VLESS "fallback"`) - } - } - if c.Fallback.Addr == nil { - c.Fallback.Addr = &Address{ - Address: net.ParseAddress("127.0.0.1"), - } - } - config.Fallback = &inbound.Fallback{ - Addr: c.Fallback.Addr.Build(), - Port: uint32(c.Fallback.Port), - Unix: c.Fallback.Unix, - Xver: uint32(c.Fallback.Xver), - } + return nil, newError(`VLESS settings: please use "fallbacks":[{}] instead of "fallback":{}`) } - - if c.Fallback_h2 != nil { - if config.Fallback == nil { - return nil, newError(`VLESS "fallback_h2" can't exist alone without "fallback"`) - } - if c.Fallback_h2.Xver > 2 { - return nil, newError(`VLESS "fallback_h2": invalid PROXY protocol version, "xver" only accepts 0, 1, 2`) - } - if c.Fallback_h2.Unix != "" { - if c.Fallback_h2.Unix[0] == '@' { - c.Fallback_h2.Unix = "\x00" + c.Fallback_h2.Unix[1:] - } + for _, fb := range c.Fallbacks { + var i uint16 + var s string + if err := json.Unmarshal(fb.Dest, &i); err == nil { + s = strconv.Itoa(int(i)) } else { - if c.Fallback_h2.Port == 0 { - return nil, newError(`please fill in a valid value for "port" in VLESS "fallback_h2"`) - } - } - if c.Fallback_h2.Addr == nil { - c.Fallback_h2.Addr = &Address{ - Address: net.ParseAddress("127.0.0.1"), - } - } - config.FallbackH2 = &inbound.FallbackH2{ - Addr: c.Fallback_h2.Addr.Build(), - Port: uint32(c.Fallback_h2.Port), - Unix: c.Fallback_h2.Unix, - Xver: uint32(c.Fallback_h2.Xver), + _ = json.Unmarshal(fb.Dest, &s) } + config.Fallbacks = append(config.Fallbacks, &inbound.Fallback{ + Alpn: fb.Alpn, + Path: fb.Path, + Type: fb.Type, + Dest: s, + Xver: fb.Xver, + }) } - - config.User = make([]*protocol.User, len(c.Users)) - for idx, rawData := range c.Users { - user := new(protocol.User) - if err := json.Unmarshal(rawData, user); err != nil { - return nil, newError("invalid VLESS user").Base(err) + for _, fb := range config.Fallbacks { + /* + if fb.Alpn == "h2" && fb.Path != "" { + return nil, newError(`VLESS fallbacks: "alpn":"h2" doesn't support "path"`) + } + */ + if fb.Path != "" && fb.Path[0] != '/' { + return nil, newError(`VLESS fallbacks: "path" must be empty or start with "/"`) } - account := new(vless.Account) - if err := json.Unmarshal(rawData, account); err != nil { - return nil, newError("invalid VLESS user").Base(err) + if fb.Type == "" && fb.Dest != "" { + if fb.Dest == "serve-ws-none" { + fb.Type = "serve" + } else { + switch fb.Dest[0] { + case '@': + fb.Dest = "\x00" + fb.Dest[1:] + fallthrough + case '/': + fb.Type = "unix" + default: + if _, err := strconv.Atoi(fb.Dest); err == nil { + fb.Dest = "127.0.0.1:" + fb.Dest + } + if _, _, err := net.SplitHostPort(fb.Dest); err == nil { + fb.Type = "tcp" + } + } + } } - - if account.Schedulers != "" { - return nil, newError(`VLESS attr "schedulers" is not available in this version`) + if fb.Type == "" { + return nil, newError(`VLESS fallbacks: please fill in a valid value for every "dest"`) } - if account.Encryption != "" { - return nil, newError(`VLESS attr "encryption" should not in inbound settings`) + if fb.Xver > 2 { + return nil, newError(`VLESS fallbacks: invalid PROXY protocol version, "xver" only accepts 0, 1, 2`) } - - user.Account = serial.ToTypedMessage(account) - config.User[idx] = user } return config, nil } -type VLessOutboundTarget struct { +type VLessOutboundVnext struct { Address *Address `json:"address"` Port uint16 `json:"port"` Users []json.RawMessage `json:"users"` } type VLessOutboundConfig struct { - Receivers []*VLessOutboundTarget `json:"vnext"` + Vnext []*VLessOutboundVnext `json:"vnext"` } // Build implements Buildable @@ -132,44 +138,44 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) { config := new(outbound.Config) - if len(c.Receivers) == 0 { - return nil, newError("0 VLESS receiver configured") + if len(c.Vnext) == 0 { + return nil, newError(`VLESS settings: "vnext" is empty`) } - serverSpecs := make([]*protocol.ServerEndpoint, len(c.Receivers)) - for idx, rec := range c.Receivers { - if len(rec.Users) == 0 { - return nil, newError("0 user configured for VLESS outbound") - } + config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext)) + for idx, rec := range c.Vnext { if rec.Address == nil { - return nil, newError("address is not set in VLESS outbound config") + return nil, newError(`VLESS vnext: "address" is not set`) + } + if len(rec.Users) == 0 { + return nil, newError(`VLESS vnext: "users" is empty`) } spec := &protocol.ServerEndpoint{ Address: rec.Address.Build(), Port: uint32(rec.Port), + User: make([]*protocol.User, len(rec.Users)), } - for _, rawUser := range rec.Users { + for idx, rawUser := range rec.Users { user := new(protocol.User) if err := json.Unmarshal(rawUser, user); err != nil { - return nil, newError("invalid VLESS user").Base(err) + return nil, newError(`VLESS users: invalid user`).Base(err) } account := new(vless.Account) if err := json.Unmarshal(rawUser, account); err != nil { - return nil, newError("invalid VLESS user").Base(err) + return nil, newError(`VLESS users: invalid user`).Base(err) } if account.Schedulers != "" { - return nil, newError(`VLESS attr "schedulers" is not available in this version`) + return nil, newError(`VLESS users: "schedulers" is not available in this version`) } if account.Encryption != "none" { - return nil, newError(`please add/set "encryption":"none" for every VLESS user in "users"`) + return nil, newError(`VLESS users: please add/set "encryption":"none" for every user`) } user.Account = serial.ToTypedMessage(account) - spec.User = append(spec.User, user) + spec.User[idx] = user } - serverSpecs[idx] = spec + config.Vnext[idx] = spec } - config.Receiver = serverSpecs return config, nil } diff --git a/infra/conf/vless_test.go b/infra/conf/vless_test.go index 813ef80f1..ac7124c3b 100644 --- a/infra/conf/vless_test.go +++ b/infra/conf/vless_test.go @@ -26,7 +26,6 @@ func TestVLessOutbound(t *testing.T) { "users": [ { "id": "27848739-7e62-4138-9fd3-098a63964b6b", - "schedulers": "", "encryption": "none", "level": 0 } @@ -35,7 +34,7 @@ func TestVLessOutbound(t *testing.T) { }`, Parser: loadJSON(creator), Output: &outbound.Config{ - Receiver: []*protocol.ServerEndpoint{ + Vnext: []*protocol.ServerEndpoint{ { Address: &net.IPOrDomain{ Address: &net.IPOrDomain_Domain{ @@ -47,7 +46,6 @@ func TestVLessOutbound(t *testing.T) { { Account: serial.ToTypedMessage(&vless.Account{ Id: "27848739-7e62-4138-9fd3-098a63964b6b", - Schedulers: "", Encryption: "none", }), Level: 0, @@ -71,49 +69,60 @@ func TestVLessInbound(t *testing.T) { "clients": [ { "id": "27848739-7e62-4138-9fd3-098a63964b6b", - "schedulers": "", "level": 0, "email": "love@v2fly.org" } ], "decryption": "none", - "fallback": { - "port": 80 - }, - "fallback_h2": { - "unix": "@/dev/shm/domain.socket", - "xver": 2 - } + "fallbacks": [ + { + "dest": 80 + }, + { + "alpn": "h2", + "dest": "@/dev/shm/domain.socket", + "xver": 2 + }, + { + "path": "/innerws", + "dest": "serve-ws-none" + } + ] }`, Parser: loadJSON(creator), Output: &inbound.Config{ - User: []*protocol.User{ + Clients: []*protocol.User{ { Account: serial.ToTypedMessage(&vless.Account{ - Id: "27848739-7e62-4138-9fd3-098a63964b6b", - Schedulers: "", + Id: "27848739-7e62-4138-9fd3-098a63964b6b", }), Level: 0, Email: "love@v2fly.org", }, }, Decryption: "none", - Fallback: &inbound.Fallback{ - Addr: &net.IPOrDomain{ - Address: &net.IPOrDomain_Ip{ - Ip: []byte{127, 0, 0, 1}, - }, + Fallbacks: []*inbound.Fallback{ + { + Alpn: "", + Path: "", + Type: "tcp", + Dest: "127.0.0.1:80", + Xver: 0, }, - Port: 80, - }, - FallbackH2: &inbound.FallbackH2{ - Addr: &net.IPOrDomain{ - Address: &net.IPOrDomain_Ip{ - Ip: []byte{127, 0, 0, 1}, - }, + { + Alpn: "h2", + Path: "", + Type: "unix", + Dest: "\x00/dev/shm/domain.socket", + Xver: 2, + }, + { + Alpn: "", + Path: "/innerws", + Type: "serve", + Dest: "serve-ws-none", + Xver: 0, }, - Unix: "\x00/dev/shm/domain.socket", - Xver: 2, }, }, }, diff --git a/proxy/vless/encoding/encoding.go b/proxy/vless/encoding/encoding.go index 1a238397d..a0d5b54f8 100644 --- a/proxy/vless/encoding/encoding.go +++ b/proxy/vless/encoding/encoding.go @@ -1,5 +1,9 @@ +// +build !confonly + package encoding +//go:generate errorgen + import ( "io" @@ -9,8 +13,6 @@ import ( "v2ray.com/core/proxy/vless" ) -//go:generate errorgen - const ( Version = byte(0) ) diff --git a/proxy/vless/inbound/config.pb.go b/proxy/vless/inbound/config.pb.go index ad3b041e3..f22d2b258 100644 --- a/proxy/vless/inbound/config.pb.go +++ b/proxy/vless/inbound/config.pb.go @@ -12,7 +12,6 @@ import ( protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" - net "v2ray.com/core/common/net" protocol "v2ray.com/core/common/protocol" ) @@ -32,10 +31,11 @@ type Fallback struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Addr *net.IPOrDomain `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` - Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` - Unix string `protobuf:"bytes,3,opt,name=unix,proto3" json:"unix,omitempty"` - Xver uint32 `protobuf:"varint,4,opt,name=xver,proto3" json:"xver,omitempty"` + Alpn string `protobuf:"bytes,1,opt,name=alpn,proto3" json:"alpn,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + Dest string `protobuf:"bytes,4,opt,name=dest,proto3" json:"dest,omitempty"` + Xver uint64 `protobuf:"varint,5,opt,name=xver,proto3" json:"xver,omitempty"` } func (x *Fallback) Reset() { @@ -70,99 +70,35 @@ func (*Fallback) Descriptor() ([]byte, []int) { return file_proxy_vless_inbound_config_proto_rawDescGZIP(), []int{0} } -func (x *Fallback) GetAddr() *net.IPOrDomain { +func (x *Fallback) GetAlpn() string { if x != nil { - return x.Addr - } - return nil -} - -func (x *Fallback) GetPort() uint32 { - if x != nil { - return x.Port - } - return 0 -} - -func (x *Fallback) GetUnix() string { - if x != nil { - return x.Unix + return x.Alpn } return "" } -func (x *Fallback) GetXver() uint32 { +func (x *Fallback) GetPath() string { if x != nil { - return x.Xver - } - return 0 -} - -type FallbackH2 struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Addr *net.IPOrDomain `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"` - Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"` - Unix string `protobuf:"bytes,3,opt,name=unix,proto3" json:"unix,omitempty"` - Xver uint32 `protobuf:"varint,4,opt,name=xver,proto3" json:"xver,omitempty"` -} - -func (x *FallbackH2) Reset() { - *x = FallbackH2{} - if protoimpl.UnsafeEnabled { - mi := &file_proxy_vless_inbound_config_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *FallbackH2) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FallbackH2) ProtoMessage() {} - -func (x *FallbackH2) ProtoReflect() protoreflect.Message { - mi := &file_proxy_vless_inbound_config_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use FallbackH2.ProtoReflect.Descriptor instead. -func (*FallbackH2) Descriptor() ([]byte, []int) { - return file_proxy_vless_inbound_config_proto_rawDescGZIP(), []int{1} -} - -func (x *FallbackH2) GetAddr() *net.IPOrDomain { - if x != nil { - return x.Addr - } - return nil -} - -func (x *FallbackH2) GetPort() uint32 { - if x != nil { - return x.Port - } - return 0 -} - -func (x *FallbackH2) GetUnix() string { - if x != nil { - return x.Unix + return x.Path } return "" } -func (x *FallbackH2) GetXver() uint32 { +func (x *Fallback) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Fallback) GetDest() string { + if x != nil { + return x.Dest + } + return "" +} + +func (x *Fallback) GetXver() uint64 { if x != nil { return x.Xver } @@ -174,17 +110,16 @@ type Config struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - User []*protocol.User `protobuf:"bytes,1,rep,name=user,proto3" json:"user,omitempty"` + Clients []*protocol.User `protobuf:"bytes,1,rep,name=clients,proto3" json:"clients,omitempty"` // Decryption settings. Only applies to server side, and only accepts "none" for now. Decryption string `protobuf:"bytes,2,opt,name=decryption,proto3" json:"decryption,omitempty"` - Fallback *Fallback `protobuf:"bytes,3,opt,name=fallback,proto3" json:"fallback,omitempty"` - FallbackH2 *FallbackH2 `protobuf:"bytes,4,opt,name=fallback_h2,json=fallbackH2,proto3" json:"fallback_h2,omitempty"` + Fallbacks []*Fallback `protobuf:"bytes,3,rep,name=fallbacks,proto3" json:"fallbacks,omitempty"` } func (x *Config) Reset() { *x = Config{} if protoimpl.UnsafeEnabled { - mi := &file_proxy_vless_inbound_config_proto_msgTypes[2] + mi := &file_proxy_vless_inbound_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -197,7 +132,7 @@ func (x *Config) String() string { func (*Config) ProtoMessage() {} func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_proxy_vless_inbound_config_proto_msgTypes[2] + mi := &file_proxy_vless_inbound_config_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -210,12 +145,12 @@ func (x *Config) ProtoReflect() protoreflect.Message { // Deprecated: Use Config.ProtoReflect.Descriptor instead. func (*Config) Descriptor() ([]byte, []int) { - return file_proxy_vless_inbound_config_proto_rawDescGZIP(), []int{2} + return file_proxy_vless_inbound_config_proto_rawDescGZIP(), []int{1} } -func (x *Config) GetUser() []*protocol.User { +func (x *Config) GetClients() []*protocol.User { if x != nil { - return x.User + return x.Clients } return nil } @@ -227,16 +162,9 @@ func (x *Config) GetDecryption() string { return "" } -func (x *Config) GetFallback() *Fallback { +func (x *Config) GetFallbacks() []*Fallback { if x != nil { - return x.Fallback - } - return nil -} - -func (x *Config) GetFallbackH2() *FallbackH2 { - if x != nil { - return x.FallbackH2 + return x.Fallbacks } return nil } @@ -248,49 +176,34 @@ var file_proxy_vless_inbound_config_proto_rawDesc = []byte{ 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1a, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x75, 0x73, - 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x7d, 0x0a, 0x08, 0x46, 0x61, 0x6c, 0x6c, - 0x62, 0x61, 0x63, 0x6b, 0x12, 0x35, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, - 0x12, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, - 0x6e, 0x69, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x80, 0x01, 0x0a, 0x0b, 0x46, 0x61, 0x6c, 0x6c, - 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x68, 0x32, 0x12, 0x35, 0x0a, 0x04, 0x61, 0x64, 0x64, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, - 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, - 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x04, 0x61, 0x64, 0x64, 0x72, 0x12, 0x12, - 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, - 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x75, 0x6e, 0x69, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0xf2, 0x01, 0x0a, 0x06, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x64, - 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x08, 0x66, - 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, - 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, - 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x46, - 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x08, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, - 0x6b, 0x12, 0x4c, 0x0a, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x68, 0x32, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, - 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, - 0x5f, 0x68, 0x32, 0x52, 0x0a, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x48, 0x32, 0x42, - 0x6b, 0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, - 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x22, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, - 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1e, 0x56, 0x32, - 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, - 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x64, 0x1a, 0x1a, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6e, + 0x0a, 0x08, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x12, 0x0a, 0x04, 0x61, 0x6c, + 0x70, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x61, 0x6c, 0x70, 0x6e, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, + 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0xac, + 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x07, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76, 0x32, 0x72, + 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x07, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, + 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, + 0x63, 0x6b, 0x52, 0x09, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x73, 0x42, 0x6b, 0x0a, + 0x22, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x22, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, + 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1e, 0x56, 0x32, 0x52, 0x61, + 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x65, + 0x73, 0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -305,25 +218,20 @@ func file_proxy_vless_inbound_config_proto_rawDescGZIP() []byte { return file_proxy_vless_inbound_config_proto_rawDescData } -var file_proxy_vless_inbound_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3) +var file_proxy_vless_inbound_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_proxy_vless_inbound_config_proto_goTypes = []interface{}{ - (*Fallback)(nil), // 0: v2ray.core.proxy.vless.inbound.Fallback - (*FallbackH2)(nil), // 1: v2ray.core.proxy.vless.inbound.Fallback_h2 - (*Config)(nil), // 2: v2ray.core.proxy.vless.inbound.Config - (*net.IPOrDomain)(nil), // 3: v2ray.core.common.net.IPOrDomain - (*protocol.User)(nil), // 4: v2ray.core.common.protocol.User + (*Fallback)(nil), // 0: v2ray.core.proxy.vless.inbound.Fallback + (*Config)(nil), // 1: v2ray.core.proxy.vless.inbound.Config + (*protocol.User)(nil), // 2: v2ray.core.common.protocol.User } var file_proxy_vless_inbound_config_proto_depIdxs = []int32{ - 3, // 0: v2ray.core.proxy.vless.inbound.Fallback.addr:type_name -> v2ray.core.common.net.IPOrDomain - 3, // 1: v2ray.core.proxy.vless.inbound.Fallback_h2.addr:type_name -> v2ray.core.common.net.IPOrDomain - 4, // 2: v2ray.core.proxy.vless.inbound.Config.user:type_name -> v2ray.core.common.protocol.User - 0, // 3: v2ray.core.proxy.vless.inbound.Config.fallback:type_name -> v2ray.core.proxy.vless.inbound.Fallback - 1, // 4: v2ray.core.proxy.vless.inbound.Config.fallback_h2:type_name -> v2ray.core.proxy.vless.inbound.Fallback_h2 - 5, // [5:5] is the sub-list for method output_type - 5, // [5:5] is the sub-list for method input_type - 5, // [5:5] is the sub-list for extension type_name - 5, // [5:5] is the sub-list for extension extendee - 0, // [0:5] is the sub-list for field type_name + 2, // 0: v2ray.core.proxy.vless.inbound.Config.clients:type_name -> v2ray.core.common.protocol.User + 0, // 1: v2ray.core.proxy.vless.inbound.Config.fallbacks:type_name -> v2ray.core.proxy.vless.inbound.Fallback + 2, // [2:2] is the sub-list for method output_type + 2, // [2:2] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_proxy_vless_inbound_config_proto_init() } @@ -345,18 +253,6 @@ func file_proxy_vless_inbound_config_proto_init() { } } file_proxy_vless_inbound_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*FallbackH2); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_proxy_vless_inbound_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Config); i { case 0: return &v.state @@ -375,7 +271,7 @@ func file_proxy_vless_inbound_config_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proxy_vless_inbound_config_proto_rawDesc, NumEnums: 0, - NumMessages: 3, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/proxy/vless/inbound/config.proto b/proxy/vless/inbound/config.proto index d4d8201b9..8b6970ff7 100644 --- a/proxy/vless/inbound/config.proto +++ b/proxy/vless/inbound/config.proto @@ -6,27 +6,19 @@ option go_package = "v2ray.com/core/proxy/vless/inbound"; option java_package = "com.v2ray.core.proxy.vless.inbound"; option java_multiple_files = true; -import "common/net/address.proto"; import "common/protocol/user.proto"; message Fallback { - v2ray.core.common.net.IPOrDomain addr = 1; - uint32 port = 2; - string unix = 3; - uint32 xver = 4; -} - -message Fallback_h2 { - v2ray.core.common.net.IPOrDomain addr = 1; - uint32 port = 2; - string unix = 3; - uint32 xver = 4; + string alpn = 1; + string path = 2; + string type = 3; + string dest = 4; + uint64 xver = 5; } message Config { - repeated v2ray.core.common.protocol.User user = 1; + repeated v2ray.core.common.protocol.User clients = 1; // Decryption settings. Only applies to server side, and only accepts "none" for now. string decryption = 2; - Fallback fallback = 3; - Fallback_h2 fallback_h2 = 4; + repeated Fallback fallbacks = 3; } diff --git a/proxy/vless/inbound/inbound.go b/proxy/vless/inbound/inbound.go index a19bbdd8b..d02a534bf 100644 --- a/proxy/vless/inbound/inbound.go +++ b/proxy/vless/inbound/inbound.go @@ -51,10 +51,8 @@ type Handler struct { policyManager policy.Manager validator *vless.Validator dns dns.Client - fallback *Fallback // or nil - addrport string - fallback_h2 *FallbackH2 // or nil - addrport_h2 string + fallbacks map[string]map[string]*Fallback // or nil + //regexps map[string]*regexp.Regexp // or nil } // New creates a new VLess inbound handler. @@ -68,7 +66,7 @@ func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) { dns: dc, } - for _, user := range config.User { + for _, user := range config.Clients { u, err := user.ToMemoryUser() if err != nil { return nil, newError("failed to get VLESS user").Base(err).AtError() @@ -78,13 +76,35 @@ func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) { } } - if config.Fallback != nil { - handler.fallback = config.Fallback - handler.addrport = handler.fallback.Addr.AsAddress().String() + ":" + strconv.Itoa(int(handler.fallback.Port)) - } - if config.FallbackH2 != nil { - handler.fallback_h2 = config.FallbackH2 - handler.addrport_h2 = handler.fallback_h2.Addr.AsAddress().String() + ":" + strconv.Itoa(int(handler.fallback_h2.Port)) + if config.Fallbacks != nil { + handler.fallbacks = make(map[string]map[string]*Fallback) + //handler.regexps = make(map[string]*regexp.Regexp) + for _, fb := range config.Fallbacks { + if handler.fallbacks[fb.Alpn] == nil { + handler.fallbacks[fb.Alpn] = make(map[string]*Fallback) + } + handler.fallbacks[fb.Alpn][fb.Path] = fb + /* + if fb.Path != "" { + if r, err := regexp.Compile(fb.Path); err != nil { + return nil, newError("invalid path regexp").Base(err).AtError() + } else { + handler.regexps[fb.Path] = r + } + } + */ + } + if handler.fallbacks[""] != nil { + for alpn, pfb := range handler.fallbacks { + if alpn != "" { // && alpn != "h2" { + for path, fb := range handler.fallbacks[""] { + if pfb[path] == nil { + pfb[path] = fb + } + } + } + } + } } return handler, nil @@ -113,6 +133,8 @@ func (*Handler) Network() []net.Network { // Process implements proxy.Inbound.Process(). func (h *Handler) Process(ctx context.Context, network net.Network, connection internet.Connection, dispatcher routing.Dispatcher) error { + sid := session.ExportIDToError(ctx) + sessionPolicy := h.policyManager.ForLevel(0) if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { return newError("unable to set read deadline").Base(err).AtWarning() @@ -121,8 +143,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i first := buf.New() first.ReadFrom(connection) - sid := session.ExportIDToError(ctx) - newError("firstLen = ", first.Len()).AtInfo().WriteToLog(sid) + firstLen := first.Len() + newError("firstLen = ", firstLen).AtInfo().WriteToLog(sid) reader := &buf.BufferedReader{ Reader: buf.NewReader(connection), @@ -134,81 +156,124 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i var err error var pre *buf.Buffer - fallback := 0 - if h.fallback != nil { - fallback = 1 + isfb := false + apfb := h.fallbacks + if apfb != nil { + isfb = true } - if fallback == 1 && first.Len() < 18 { + if isfb && firstLen < 18 { err = newError("fallback directly") } else { request, requestAddons, err, pre = encoding.DecodeRequestHeader(reader, h.validator) if pre == nil { - fallback = 0 + isfb = false } } if err != nil { - if fallback == 1 { - if h.fallback_h2 != nil { + if isfb { + if err := connection.SetReadDeadline(time.Time{}); err != nil { + newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid) + } + newError("fallback starts").Base(err).AtInfo().WriteToLog(sid) + + alpn := "" + if len(apfb) > 1 || apfb[""] == nil { iConn := connection if statConn, ok := iConn.(*internet.StatCouterConnection); ok { iConn = statConn.Connection } if tlsConn, ok := iConn.(*tls.Conn); ok { - if tlsConn.ConnectionState().NegotiatedProtocol == "h2" { - fallback = 2 + alpn = tlsConn.ConnectionState().NegotiatedProtocol + newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid) + if apfb[alpn] == nil { + alpn = "" } } } - - var addrport string - var unixpath string - var proxyver uint32 - - switch fallback { - case 1: - addrport = h.addrport - unixpath = h.fallback.Unix - proxyver = h.fallback.Xver - newError("fallback starts").Base(err).AtInfo().WriteToLog(sid) - case 2: - addrport = h.addrport_h2 - unixpath = h.fallback_h2.Unix - proxyver = h.fallback_h2.Xver - newError("fallback_h2 starts").Base(err).AtInfo().WriteToLog(sid) + pfb := apfb[alpn] + if pfb == nil { + return newError(`failed to find the default "alpn" config`).AtWarning() } + path := "" + if len(pfb) > 1 || pfb[""] == nil { + /* + if lines := bytes.Split(firstBytes, []byte{'\r', '\n'}); len(lines) > 1 { + if s := bytes.Split(lines[0], []byte{' '}); len(s) == 3 { + if len(s[0]) < 8 && len(s[1]) > 0 && len(s[2]) == 8 { + newError("realPath = " + string(s[1])).AtInfo().WriteToLog(sid) + for _, fb := range pfb { + if fb.Path != "" && h.regexps[fb.Path].Match(s[1]) { + path = fb.Path + break + } + } + } + } + } + */ + if pre != nil && pre.Len() == 1 && first.Byte(3) != '*' { // firstLen >= 18 && invalid request version && not h2c + firstBytes := first.Bytes() + for i := 3; i <= 7; i++ { // 5 -> 9 + if firstBytes[i] == '/' && firstBytes[i-1] == ' ' { + search := len(firstBytes) + if search > 64 { + search = 64 // up to 60 + } + for j := i + 1; j < search; j++ { + k := firstBytes[j] + if k == '\r' || k == '\n' { // avoid logging \r or \n + break + } + if k == ' ' { + path = string(firstBytes[i:j]) + newError("realPath = " + path).AtInfo().WriteToLog(sid) + if pfb[path] == nil { + path = "" + } + break + } + } + break + } + } + } + } + fb := pfb[path] + if fb == nil { + return newError(`failed to find the default "path" config`).AtWarning() + } + + ctx, cancel := context.WithCancel(ctx) + timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) + ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer) + var conn net.Conn if err := retry.ExponentialBackoff(5, 100).On(func() error { var dialer net.Dialer - var err error - if unixpath != "" { - conn, err = dialer.DialContext(ctx, "unix", unixpath) - } else { - conn, err = dialer.DialContext(ctx, "tcp", addrport) - } + conn, err = dialer.DialContext(ctx, fb.Type, fb.Dest) if err != nil { return err } return nil }); err != nil { - return newError("failed to fallback connection").Base(err).AtWarning() + dest := fb.Dest + if dest[0] == '\x00' { + dest = "@" + dest[1:] + } + return newError("failed to dial to " + dest).Base(err).AtWarning() } defer conn.Close() // nolint: errcheck - ctx, cancel := context.WithCancel(ctx) - timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) - - writer := buf.NewWriter(connection) - serverReader := buf.NewReader(conn) serverWriter := buf.NewWriter(conn) postRequest := func() error { defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly) - if proxyver > 0 { + if fb.Xver != 0 { remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String()) if err != nil { return err @@ -225,7 +290,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i } } pro := buf.New() - switch proxyver { + switch fb.Xver { case 1: if ipv4 { pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")) @@ -257,7 +322,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i pro.Write(b2) } if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil { - return newError("failed to set PROXY protocol v", proxyver).Base(err).AtWarning() + return newError("failed to set PROXY protocol v", fb.Xver).Base(err).AtWarning() } } if pre != nil && pre.Len() > 0 { @@ -266,15 +331,17 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i } } if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil { - return err // ... + return newError("failed to fallback request payload").Base(err).AtInfo() } return nil } + writer := buf.NewWriter(connection) + getResponse := func() error { defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly) if err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil { - return err // ... + return newError("failed to deliver response payload").Base(err).AtInfo() } return nil } @@ -299,6 +366,17 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i return err } + if err := connection.SetReadDeadline(time.Time{}); err != nil { + newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid) + } + newError("received request for ", request.Destination()).AtInfo().WriteToLog(sid) + + inbound := session.InboundFromContext(ctx) + if inbound == nil { + panic("no inbound metadata") + } + inbound.User = request.User + if request.Command != protocol.RequestCommandMux { ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ From: connection.RemoteAddr(), @@ -309,24 +387,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i }) } - newError("received request for ", request.Destination()).AtInfo().WriteToLog(sid) - - if err := connection.SetReadDeadline(time.Time{}); err != nil { - newError("unable to set back read deadline").Base(err).AtWarning().WriteToLog(sid) - } - - inbound := session.InboundFromContext(ctx) - if inbound == nil { - panic("no inbound metadata") - } - inbound.User = request.User - sessionPolicy = h.policyManager.ForLevel(request.User.Level) - ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle) - ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer) + link, err := dispatcher.Dispatch(ctx, request.Destination()) if err != nil { return newError("failed to dispatch request to ", request.Destination()).Base(err).AtWarning() diff --git a/proxy/vless/outbound/config.pb.go b/proxy/vless/outbound/config.pb.go index 0b840b4a8..ea4d0b472 100644 --- a/proxy/vless/outbound/config.pb.go +++ b/proxy/vless/outbound/config.pb.go @@ -31,7 +31,7 @@ type Config struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Receiver []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=receiver,proto3" json:"receiver,omitempty"` + Vnext []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=vnext,proto3" json:"vnext,omitempty"` } func (x *Config) Reset() { @@ -66,9 +66,9 @@ func (*Config) Descriptor() ([]byte, []int) { return file_proxy_vless_outbound_config_proto_rawDescGZIP(), []int{0} } -func (x *Config) GetReceiver() []*protocol.ServerEndpoint { +func (x *Config) GetVnext() []*protocol.ServerEndpoint { if x != nil { - return x.Receiver + return x.Vnext } return nil } @@ -82,20 +82,19 @@ var file_proxy_vless_outbound_config_proto_rawDesc = []byte{ 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, - 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x50, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x46, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, - 0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x42, 0x6e, 0x0a, 0x23, 0x63, 0x6f, 0x6d, - 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, - 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, - 0x50, 0x01, 0x5a, 0x23, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, - 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x6f, - 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, - 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, - 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x40, 0x0a, 0x05, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x05, 0x76, 0x6e, + 0x65, 0x78, 0x74, 0x42, 0x6e, 0x0a, 0x23, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, + 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6c, 0x65, 0x73, + 0x73, 0x2e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x23, 0x76, 0x32, + 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, + 0x78, 0x79, 0x2f, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x2f, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, + 0x64, 0xaa, 0x02, 0x1f, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, + 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, + 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -116,7 +115,7 @@ var file_proxy_vless_outbound_config_proto_goTypes = []interface{}{ (*protocol.ServerEndpoint)(nil), // 1: v2ray.core.common.protocol.ServerEndpoint } var file_proxy_vless_outbound_config_proto_depIdxs = []int32{ - 1, // 0: v2ray.core.proxy.vless.outbound.Config.receiver:type_name -> v2ray.core.common.protocol.ServerEndpoint + 1, // 0: v2ray.core.proxy.vless.outbound.Config.vnext:type_name -> v2ray.core.common.protocol.ServerEndpoint 1, // [1:1] is the sub-list for method output_type 1, // [1:1] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name diff --git a/proxy/vless/outbound/config.proto b/proxy/vless/outbound/config.proto index 15b32f1a2..3604b72d5 100644 --- a/proxy/vless/outbound/config.proto +++ b/proxy/vless/outbound/config.proto @@ -9,5 +9,5 @@ option java_multiple_files = true; import "common/protocol/server_spec.proto"; message Config { - repeated v2ray.core.common.protocol.ServerEndpoint receiver = 1; + repeated v2ray.core.common.protocol.ServerEndpoint vnext = 1; } diff --git a/proxy/vless/outbound/outbound.go b/proxy/vless/outbound/outbound.go index a5919f627..6fdea3cea 100644 --- a/proxy/vless/outbound/outbound.go +++ b/proxy/vless/outbound/outbound.go @@ -41,7 +41,7 @@ type Handler struct { func New(ctx context.Context, config *Config) (*Handler, error) { serverList := protocol.NewServerList() - for _, rec := range config.Receiver { + for _, rec := range config.Vnext { s, err := protocol.NewServerSpecFromPB(rec) if err != nil { return nil, newError("failed to parse server spec").Base(err).AtError() @@ -109,7 +109,6 @@ func (v *Handler) Process(ctx context.Context, link *transport.Link, dialer inte } sessionPolicy := v.policyManager.ForLevel(request.User.Level) - ctx, cancel := context.WithCancel(ctx) timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)