diff --git a/infra/conf/vless.go b/infra/conf/vless.go index 503fd7816..b13537054 100644 --- a/infra/conf/vless.go +++ b/infra/conf/vless.go @@ -17,12 +17,14 @@ type VLessInboundFallback struct { Addr *Address `json:"addr"` Port uint16 `json:"port"` Unix string `json:"unix"` + Xver uint16 `json:"xver"` } type VLessInboundConfig struct { - Users []json.RawMessage `json:"clients"` - Decryption string `json:"decryption"` - Fallback *VLessInboundFallback `json:"fallback"` + Users []json.RawMessage `json:"clients"` + Decryption string `json:"decryption"` + Fallback *VLessInboundFallback `json:"fallback"` + Fallback_h2 *VLessInboundFallback `json:"fallback_h2"` } // Build implements Buildable @@ -36,6 +38,9 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) { 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:] @@ -54,6 +59,36 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) { Addr: c.Fallback.Addr.Build(), Port: uint32(c.Fallback.Port), Unix: c.Fallback.Unix, + Xver: uint32(c.Fallback.Xver), + } + } + + 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:] + } + } 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), } } diff --git a/infra/conf/vless_test.go b/infra/conf/vless_test.go index aacd53028..4ef74829f 100644 --- a/infra/conf/vless_test.go +++ b/infra/conf/vless_test.go @@ -79,7 +79,10 @@ func TestVLessInbound(t *testing.T) { "decryption": "none", "fallback": { "port": 80, - "unix": "@/dev/shm/domain.socket" + }, + "fallback_h2": { + "unix": "@/dev/shm/domain.socket", + "xver": 2 } }`, Parser: loadJSON(creator), @@ -102,7 +105,15 @@ func TestVLessInbound(t *testing.T) { }, }, Port: 80, + }, + FallbackH2: &inbound.FallbackH2{ + Addr: &net.IPOrDomain{ + Address: &net.IPOrDomain_Ip{ + Ip: []byte{127, 0, 0, 1}, + }, + }, Unix: "\x00/dev/shm/domain.socket", + Xver: 2, }, }, }, diff --git a/proxy/vless/encoding/addons.go b/proxy/vless/encoding/addons.go index f4d4ac4d2..80d66f30d 100644 --- a/proxy/vless/encoding/addons.go +++ b/proxy/vless/encoding/addons.go @@ -17,7 +17,7 @@ func EncodeHeaderAddons(buffer *buf.Buffer, addons *Addons) error { default: if err := buffer.WriteByte(0); err != nil { - return newError("failed to write addons protobuf length").Base(err).AtWarning() + return newError("failed to write addons protobuf length").Base(err) } } @@ -32,18 +32,18 @@ func DecodeHeaderAddons(buffer *buf.Buffer, reader io.Reader) (*Addons, error) { buffer.Clear() if _, err := buffer.ReadFullFrom(reader, 1); err != nil { - return nil, newError("failed to read addons protobuf length").Base(err).AtWarning() + return nil, newError("failed to read addons protobuf length").Base(err) } if length := int32(buffer.Byte(0)); length != 0 { buffer.Clear() if _, err := buffer.ReadFullFrom(reader, length); err != nil { - return nil, newError("failed to read addons protobuf value").Base(err).AtWarning() + return nil, newError("failed to read addons protobuf value").Base(err) } if err := proto.Unmarshal(buffer.Bytes(), addons); err != nil { - return nil, newError("failed to unmarshal addons protobuf value").Base(err).AtWarning() + return nil, newError("failed to unmarshal addons protobuf value").Base(err) } // Verification. diff --git a/proxy/vless/encoding/encoding.go b/proxy/vless/encoding/encoding.go index dc121a244..7c0ccc3dd 100644 --- a/proxy/vless/encoding/encoding.go +++ b/proxy/vless/encoding/encoding.go @@ -29,29 +29,29 @@ func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requ defer buffer.Release() if err := buffer.WriteByte(request.Version); err != nil { - return newError("failed to write request version").Base(err).AtWarning() + return newError("failed to write request version").Base(err) } if _, err := buffer.Write(request.User.Account.(*vless.MemoryAccount).ID.Bytes()); err != nil { - return newError("failed to write request user id").Base(err).AtWarning() + return newError("failed to write request user id").Base(err) } if err := EncodeHeaderAddons(&buffer, requestAddons); err != nil { - return newError("failed to encode request header addons").Base(err).AtWarning() + return newError("failed to encode request header addons").Base(err) } if err := buffer.WriteByte(byte(request.Command)); err != nil { - return newError("failed to write request command").Base(err).AtWarning() + return newError("failed to write request command").Base(err) } if request.Command != protocol.RequestCommandMux { if err := addrParser.WriteAddressPort(&buffer, request.Address, request.Port); err != nil { - return newError("failed to write request address and port").Base(err).AtWarning() + return newError("failed to write request address and port").Base(err) } } if _, err := writer.Write(buffer.Bytes()); err != nil { - return newError("failed to write request header").Base(err).AtWarning() + return newError("failed to write request header").Base(err) } return nil @@ -67,7 +67,7 @@ func DecodeRequestHeader(reader io.Reader, validator *vless.Validator) (*protoco if _, err := buffer.ReadFullFrom(reader, 1); err != nil { pre.Write(buffer.Bytes()) - return nil, nil, newError("failed to read request version").Base(err).AtWarning(), pre + return nil, nil, newError("failed to read request version").Base(err), pre } request := &protocol.RequestHeader{ @@ -82,7 +82,7 @@ func DecodeRequestHeader(reader io.Reader, validator *vless.Validator) (*protoco buffer.Clear() if _, err := buffer.ReadFullFrom(reader, protocol.IDBytesLen); err != nil { pre.Write(buffer.Bytes()) - return nil, nil, newError("failed to read request user id").Base(err).AtWarning(), pre + return nil, nil, newError("failed to read request user id").Base(err), pre } var id [16]byte @@ -90,17 +90,17 @@ func DecodeRequestHeader(reader io.Reader, validator *vless.Validator) (*protoco if request.User = validator.Get(id); request.User == nil { pre.Write(buffer.Bytes()) - return nil, nil, newError("invalid request user id").AtWarning(), pre + return nil, nil, newError("invalid request user id"), pre } requestAddons, err := DecodeHeaderAddons(&buffer, reader) if err != nil { - return nil, nil, newError("failed to decode request header addons").Base(err).AtWarning(), nil + return nil, nil, newError("failed to decode request header addons").Base(err), nil } buffer.Clear() if _, err := buffer.ReadFullFrom(reader, 1); err != nil { - return nil, nil, newError("failed to read request command").Base(err).AtWarning(), nil + return nil, nil, newError("failed to read request command").Base(err), nil } request.Command = protocol.RequestCommand(buffer.Byte(0)) @@ -116,14 +116,14 @@ func DecodeRequestHeader(reader io.Reader, validator *vless.Validator) (*protoco } if request.Address == nil { - return nil, nil, newError("invalid request address").AtWarning(), nil + return nil, nil, newError("invalid request address"), nil } return request, requestAddons, nil, nil default: - return nil, nil, newError("unexpected request version").AtWarning(), pre + return nil, nil, newError("unexpected request version"), pre } @@ -136,15 +136,15 @@ func EncodeResponseHeader(writer io.Writer, request *protocol.RequestHeader, res defer buffer.Release() if err := buffer.WriteByte(request.Version); err != nil { - return newError("failed to write response version").Base(err).AtWarning() + return newError("failed to write response version").Base(err) } if err := EncodeHeaderAddons(&buffer, responseAddons); err != nil { - return newError("failed to encode response header addons").Base(err).AtWarning() + return newError("failed to encode response header addons").Base(err) } if _, err := writer.Write(buffer.Bytes()); err != nil { - return newError("failed to write response header").Base(err).AtWarning() + return newError("failed to write response header").Base(err) } return nil @@ -157,16 +157,16 @@ func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader, res defer buffer.Release() if _, err := buffer.ReadFullFrom(reader, 1); err != nil { - return newError("failed to read response version").Base(err).AtWarning() + return newError("failed to read response version").Base(err) } if buffer.Byte(0) != request.Version { - return newError("unexpected response version. Expecting ", int(request.Version), " but actually ", int(buffer.Byte(0))).AtWarning() + return newError("unexpected response version. Expecting ", int(request.Version), " but actually ", int(buffer.Byte(0))) } responseAddons, err := DecodeHeaderAddons(&buffer, reader) if err != nil { - return newError("failed to decode response header addons").Base(err).AtWarning() + return newError("failed to decode response header addons").Base(err) } return nil diff --git a/proxy/vless/inbound/config.pb.go b/proxy/vless/inbound/config.pb.go index 65777262d..bb8f5c410 100644 --- a/proxy/vless/inbound/config.pb.go +++ b/proxy/vless/inbound/config.pb.go @@ -35,6 +35,7 @@ type Fallback struct { 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 *Fallback) Reset() { @@ -90,6 +91,84 @@ func (x *Fallback) GetUnix() string { return "" } +func (x *Fallback) GetXver() uint32 { + 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_v2ray_com_core_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_v2ray_com_core_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_v2ray_com_core_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 "" +} + +func (x *FallbackH2) GetXver() uint32 { + if x != nil { + return x.Xver + } + return 0 +} + type Config struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -97,14 +176,15 @@ type Config struct { User []*protocol.User `protobuf:"bytes,1,rep,name=user,proto3" json:"user,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"` + 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"` } func (x *Config) Reset() { *x = Config{} if protoimpl.UnsafeEnabled { - mi := &file_v2ray_com_core_proxy_vless_inbound_config_proto_msgTypes[1] + mi := &file_v2ray_com_core_proxy_vless_inbound_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -117,7 +197,7 @@ func (x *Config) String() string { func (*Config) ProtoMessage() {} func (x *Config) ProtoReflect() protoreflect.Message { - mi := &file_v2ray_com_core_proxy_vless_inbound_config_proto_msgTypes[1] + mi := &file_v2ray_com_core_proxy_vless_inbound_config_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -130,7 +210,7 @@ func (x *Config) ProtoReflect() protoreflect.Message { // Deprecated: Use Config.ProtoReflect.Descriptor instead. func (*Config) Descriptor() ([]byte, []int) { - return file_v2ray_com_core_proxy_vless_inbound_config_proto_rawDescGZIP(), []int{1} + return file_v2ray_com_core_proxy_vless_inbound_config_proto_rawDescGZIP(), []int{2} } func (x *Config) GetUser() []*protocol.User { @@ -154,6 +234,13 @@ func (x *Config) GetFallback() *Fallback { return nil } +func (x *Config) GetFallbackH2() *FallbackH2 { + if x != nil { + return x.FallbackH2 + } + return nil +} + var File_v2ray_com_core_proxy_vless_inbound_config_proto protoreflect.FileDescriptor var file_v2ray_com_core_proxy_vless_inbound_config_proto_rawDesc = []byte{ @@ -167,30 +254,44 @@ var file_v2ray_com_core_proxy_vless_inbound_config_proto_rawDesc = []byte{ 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0x2f, 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, 0x69, 0x0a, 0x08, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 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, - 0x22, 0xa4, 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, + 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, 0x52, 0x08, 0x66, - 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x42, 0x50, 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, - 0x07, 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, + 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, 0x50, 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, 0x07, 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 ( @@ -205,22 +306,25 @@ func file_v2ray_com_core_proxy_vless_inbound_config_proto_rawDescGZIP() []byte { return file_v2ray_com_core_proxy_vless_inbound_config_proto_rawDescData } -var file_v2ray_com_core_proxy_vless_inbound_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_v2ray_com_core_proxy_vless_inbound_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_v2ray_com_core_proxy_vless_inbound_config_proto_goTypes = []interface{}{ (*Fallback)(nil), // 0: v2ray.core.proxy.vless.inbound.Fallback - (*Config)(nil), // 1: v2ray.core.proxy.vless.inbound.Config - (*net.IPOrDomain)(nil), // 2: v2ray.core.common.net.IPOrDomain - (*protocol.User)(nil), // 3: v2ray.core.common.protocol.User + (*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 } var file_v2ray_com_core_proxy_vless_inbound_config_proto_depIdxs = []int32{ - 2, // 0: v2ray.core.proxy.vless.inbound.Fallback.addr:type_name -> v2ray.core.common.net.IPOrDomain - 3, // 1: v2ray.core.proxy.vless.inbound.Config.user:type_name -> v2ray.core.common.protocol.User - 0, // 2: v2ray.core.proxy.vless.inbound.Config.fallback:type_name -> v2ray.core.proxy.vless.inbound.Fallback - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 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 } func init() { file_v2ray_com_core_proxy_vless_inbound_config_proto_init() } @@ -242,6 +346,18 @@ func file_v2ray_com_core_proxy_vless_inbound_config_proto_init() { } } file_v2ray_com_core_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_v2ray_com_core_proxy_vless_inbound_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Config); i { case 0: return &v.state @@ -260,7 +376,7 @@ func file_v2ray_com_core_proxy_vless_inbound_config_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_v2ray_com_core_proxy_vless_inbound_config_proto_rawDesc, NumEnums: 0, - NumMessages: 2, + NumMessages: 3, NumExtensions: 0, NumServices: 0, }, diff --git a/proxy/vless/inbound/config.proto b/proxy/vless/inbound/config.proto index f48845040..1a0bffe86 100644 --- a/proxy/vless/inbound/config.proto +++ b/proxy/vless/inbound/config.proto @@ -13,6 +13,14 @@ 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; } message Config { @@ -20,4 +28,5 @@ message Config { // Decryption settings. Only applies to server side, and only accepts "none" for now. string decryption = 2; Fallback fallback = 3; + Fallback_h2 fallback_h2 = 4; } diff --git a/proxy/vless/inbound/inbound.go b/proxy/vless/inbound/inbound.go index 9a14481f8..357784e87 100644 --- a/proxy/vless/inbound/inbound.go +++ b/proxy/vless/inbound/inbound.go @@ -6,6 +6,7 @@ package inbound import ( "context" + "encoding/hex" "io" "strconv" "time" @@ -28,6 +29,7 @@ import ( "v2ray.com/core/proxy/vless" "v2ray.com/core/proxy/vless/encoding" "v2ray.com/core/transport/internet" + "v2ray.com/core/transport/internet/tls" ) func init() { @@ -51,6 +53,8 @@ type Handler struct { dns dns.Client fallback *Fallback // or nil addrport string + fallback_h2 *FallbackH2 // or nil + addrport_h2 string } // New creates a new VLess inbound handler. @@ -78,6 +82,10 @@ func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) { 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)) + } return handler, nil } @@ -113,6 +121,33 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i first := buf.New() first.ReadFrom(connection) + var fallback uint32 + var addrport string + var unixpath string + var proxyver uint32 + + if h.fallback != nil { + fallback = 1 + addrport = h.addrport + unixpath = h.fallback.Unix + proxyver = h.fallback.Xver + } + + if h.fallback_h2 != 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 + addrport = h.addrport_h2 + unixpath = h.fallback_h2.Unix + proxyver = h.fallback_h2.Xver + } + } + } + sid := session.ExportIDToError(ctx) newError("firstLen = ", first.Len()).AtInfo().WriteToLog(sid) @@ -126,26 +161,33 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i var err error var pre *buf.Buffer - if h.fallback != nil && first.Len() < 18 { + if fallback > 0 && first.Len() < 18 { err = newError("fallback directly") - pre = buf.New() } else { request, requestAddons, err, pre = encoding.DecodeRequestHeader(reader, h.validator) + if pre == nil { + fallback = 0 + } } if err != nil { - if h.fallback != nil && pre != nil { - newError("fallback starts").AtInfo().WriteToLog(sid) + if fallback > 0 { + switch fallback { + case 1: + newError("fallback starts").Base(err).AtInfo().WriteToLog(sid) + case 2: + newError("fallback_h2 starts").Base(err).AtInfo().WriteToLog(sid) + } var conn net.Conn if err := retry.ExponentialBackoff(5, 100).On(func() error { var dialer net.Dialer var err error - if h.fallback.Unix != "" { - conn, err = dialer.DialContext(ctx, "unix", h.fallback.Unix) + if unixpath != "" { + conn, err = dialer.DialContext(ctx, "unix", unixpath) } else { - conn, err = dialer.DialContext(ctx, "tcp", h.addrport) + conn, err = dialer.DialContext(ctx, "tcp", addrport) } if err != nil { return err @@ -166,7 +208,59 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection i postRequest := func() error { defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly) - if pre.Len() > 0 { + if proxyver > 0 { + remoteAddr, remotePort, err := net.SplitHostPort(connection.RemoteAddr().String()) + if err != nil { + return err + } + localAddr, localPort, err := net.SplitHostPort(connection.LocalAddr().String()) + if err != nil { + return err + } + ipv4 := true + for i := 0; i < len(remoteAddr); i++ { + if remoteAddr[i] == ':' { + ipv4 = false + break + } + } + pro := buf.New() + switch proxyver { + case 1: + if ipv4 { + pro.Write([]byte("PROXY TCP4 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")) + } else { + pro.Write([]byte("PROXY TCP6 " + remoteAddr + " " + localAddr + " " + remotePort + " " + localPort + "\r\n")) + } + case 2: + pro.Write([]byte("\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x21")) // signature + v2 + PROXY + if ipv4 { + pro.Write([]byte("\x11\x00\x0C")) // AF_INET + STREAM + 12 bytes + pro.Write(net.ParseIP(remoteAddr).To4()) + pro.Write(net.ParseIP(localAddr).To4()) + } else { + pro.Write([]byte("\x21\x00\x24")) // AF_INET6 + STREAM + 36 bytes + pro.Write(net.ParseIP(remoteAddr).To16()) + pro.Write(net.ParseIP(localAddr).To16()) + } + p1, _ := strconv.ParseInt(remotePort, 10, 64) + b1, _ := hex.DecodeString(strconv.FormatInt(p1, 16)) + p2, _ := strconv.ParseInt(localPort, 10, 64) + b2, _ := hex.DecodeString(strconv.FormatInt(p2, 16)) + if len(b1) == 1 { + pro.WriteByte(0) + } + pro.Write(b1) + if len(b2) == 1 { + pro.WriteByte(0) + } + pro.Write(b2) + } + if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil { + return newError("failed to set PROXY protocol v", proxyver).Base(err).AtWarning() + } + } + if pre != nil && pre.Len() > 0 { if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pre}); err != nil { return newError("failed to fallback request pre").Base(err).AtWarning() }