mirror of
https://github.com/v2fly/v2ray-core.git
synced 2024-12-30 05:56:54 -05:00
Add Add Hysteria2 Protocol
This commit is contained in:
parent
485f5a0ef7
commit
2078480c4e
2
.github/workflows/linter.yml
vendored
2
.github/workflows/linter.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ^1.19
|
||||
go-version: ^1.21
|
||||
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v3
|
||||
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@ -5,7 +5,7 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- v*
|
||||
- dev-*
|
||||
- dev*
|
||||
paths:
|
||||
- "**/*.go"
|
||||
- "go.mod"
|
||||
@ -30,7 +30,7 @@ jobs:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ^1.19
|
||||
go-version: ^1.21
|
||||
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v3
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -26,3 +26,5 @@ vprotogen
|
||||
errorgen
|
||||
!common/errors/errorgen/
|
||||
*.dat
|
||||
*~
|
||||
[._]*.un~
|
||||
|
@ -32,7 +32,7 @@ This repo relies on the following third-party projects:
|
||||
|
||||
- In production:
|
||||
- [gorilla/websocket](https://github.com/gorilla/websocket)
|
||||
- [lucas-clemente/quic-go](https://github.com/lucas-clemente/quic-go)
|
||||
- [quic-go/quic-go](https://github.com/quic-go/quic-go)
|
||||
- [pires/go-proxyproto](https://github.com/pires/go-proxyproto)
|
||||
- [seiflotfy/cuckoofilter](https://github.com/seiflotfy/cuckoofilter)
|
||||
- [google/starlark-go](https://github.com/google/starlark-go)
|
||||
|
@ -1,9 +1,3 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.24.4
|
||||
// source: app/dns/config.proto
|
||||
|
||||
package dns
|
||||
|
||||
import (
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/test/bufconn"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/app/router"
|
||||
@ -90,7 +91,13 @@ func TestServiceSubscribeRoutingStats(t *testing.T) {
|
||||
// Client goroutine
|
||||
go func() {
|
||||
defer lis.Close()
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
|
||||
conn, err := grpc.DialContext(
|
||||
context.Background(),
|
||||
"bufnet",
|
||||
grpc.WithContextDialer(bufDialer),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
return
|
||||
@ -268,7 +275,11 @@ func TestSerivceTestRoute(t *testing.T) {
|
||||
// Client goroutine
|
||||
go func() {
|
||||
defer lis.Close()
|
||||
conn, err := grpc.DialContext(context.Background(), "bufnet", grpc.WithContextDialer(bufDialer), grpc.WithInsecure())
|
||||
conn, err := grpc.DialContext(
|
||||
context.Background(),
|
||||
"bufnet", grpc.WithContextDialer(bufDialer),
|
||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
||||
)
|
||||
if err != nil {
|
||||
errCh <- err
|
||||
}
|
||||
|
@ -1,18 +1,12 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.27.1
|
||||
// protoc v3.12.4
|
||||
// source: app/router/config.proto
|
||||
|
||||
package router
|
||||
|
||||
import (
|
||||
any "github.com/golang/protobuf/ptypes/any"
|
||||
routercommon "github.com/v2fly/v2ray-core/v5/app/router/routercommon"
|
||||
net "github.com/v2fly/v2ray-core/v5/common/net"
|
||||
_ "github.com/v2fly/v2ray-core/v5/common/protoext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
anypb "google.golang.org/protobuf/types/known/anypb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
@ -86,6 +80,7 @@ type RoutingRule struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to TargetTag:
|
||||
//
|
||||
// *RoutingRule_Tag
|
||||
// *RoutingRule_BalancingTag
|
||||
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
||||
@ -94,7 +89,7 @@ type RoutingRule struct {
|
||||
// List of CIDRs for target IP address matching.
|
||||
// Deprecated. Use geoip below.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||
Cidr []*routercommon.CIDR `protobuf:"bytes,3,rep,name=cidr,proto3" json:"cidr,omitempty"`
|
||||
// List of GeoIPs for target IP address matching. If this entry exists, the
|
||||
// cidr above will have no effect. GeoIP fields with the same country code are
|
||||
@ -104,19 +99,19 @@ type RoutingRule struct {
|
||||
// A range of port [from, to]. If the destination port is in this range, this
|
||||
// rule takes effect. Deprecated. Use port_list.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||
PortRange *net.PortRange `protobuf:"bytes,4,opt,name=port_range,json=portRange,proto3" json:"port_range,omitempty"`
|
||||
// List of ports.
|
||||
PortList *net.PortList `protobuf:"bytes,14,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
||||
// List of networks. Deprecated. Use networks.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||
NetworkList *net.NetworkList `protobuf:"bytes,5,opt,name=network_list,json=networkList,proto3" json:"network_list,omitempty"`
|
||||
// List of networks for matching.
|
||||
Networks []net.Network `protobuf:"varint,13,rep,packed,name=networks,proto3,enum=v2ray.core.common.net.Network" json:"networks,omitempty"`
|
||||
// List of CIDRs for source IP address matching.
|
||||
//
|
||||
// Deprecated: Do not use.
|
||||
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||
SourceCidr []*routercommon.CIDR `protobuf:"bytes,6,rep,name=source_cidr,json=sourceCidr,proto3" json:"source_cidr,omitempty"`
|
||||
// List of GeoIPs for source IP address matching. If this entry exists, the
|
||||
// source_cidr above will have no effect.
|
||||
@ -192,7 +187,7 @@ func (x *RoutingRule) GetDomain() []*routercommon.Domain {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||
func (x *RoutingRule) GetCidr() []*routercommon.CIDR {
|
||||
if x != nil {
|
||||
return x.Cidr
|
||||
@ -207,7 +202,7 @@ func (x *RoutingRule) GetGeoip() []*routercommon.GeoIP {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||
func (x *RoutingRule) GetPortRange() *net.PortRange {
|
||||
if x != nil {
|
||||
return x.PortRange
|
||||
@ -222,7 +217,7 @@ func (x *RoutingRule) GetPortList() *net.PortList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||
func (x *RoutingRule) GetNetworkList() *net.NetworkList {
|
||||
if x != nil {
|
||||
return x.NetworkList
|
||||
@ -237,7 +232,7 @@ func (x *RoutingRule) GetNetworks() []net.Network {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||
func (x *RoutingRule) GetSourceCidr() []*routercommon.CIDR {
|
||||
if x != nil {
|
||||
return x.SourceCidr
|
||||
@ -324,11 +319,11 @@ type BalancingRule struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
OutboundSelector []string `protobuf:"bytes,2,rep,name=outbound_selector,json=outboundSelector,proto3" json:"outbound_selector,omitempty"`
|
||||
Strategy string `protobuf:"bytes,3,opt,name=strategy,proto3" json:"strategy,omitempty"`
|
||||
StrategySettings *any.Any `protobuf:"bytes,4,opt,name=strategy_settings,json=strategySettings,proto3" json:"strategy_settings,omitempty"`
|
||||
FallbackTag string `protobuf:"bytes,5,opt,name=fallback_tag,json=fallbackTag,proto3" json:"fallback_tag,omitempty"`
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
OutboundSelector []string `protobuf:"bytes,2,rep,name=outbound_selector,json=outboundSelector,proto3" json:"outbound_selector,omitempty"`
|
||||
Strategy string `protobuf:"bytes,3,opt,name=strategy,proto3" json:"strategy,omitempty"`
|
||||
StrategySettings *anypb.Any `protobuf:"bytes,4,opt,name=strategy_settings,json=strategySettings,proto3" json:"strategy_settings,omitempty"`
|
||||
FallbackTag string `protobuf:"bytes,5,opt,name=fallback_tag,json=fallbackTag,proto3" json:"fallback_tag,omitempty"`
|
||||
}
|
||||
|
||||
func (x *BalancingRule) Reset() {
|
||||
@ -384,7 +379,7 @@ func (x *BalancingRule) GetStrategy() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *BalancingRule) GetStrategySettings() *any.Any {
|
||||
func (x *BalancingRule) GetStrategySettings() *anypb.Any {
|
||||
if x != nil {
|
||||
return x.StrategySettings
|
||||
}
|
||||
@ -724,6 +719,7 @@ type SimplifiedRoutingRule struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Types that are assignable to TargetTag:
|
||||
//
|
||||
// *SimplifiedRoutingRule_Tag
|
||||
// *SimplifiedRoutingRule_BalancingTag
|
||||
TargetTag isSimplifiedRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
||||
@ -1068,110 +1064,109 @@ var file_app_router_config_proto_rawDesc = []byte{
|
||||
0x67, 0x65, 0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x22, 0x74, 0x0a, 0x14, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x61, 0x6e, 0x64,
|
||||
0x22, 0x70, 0x0a, 0x14, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x61, 0x6e, 0x64,
|
||||
0x6f, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x62, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
|
||||
0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x09, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x3a, 0x1a, 0x82, 0xb5, 0x18, 0x0a,
|
||||
0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x82, 0xb5, 0x18, 0x08, 0x12, 0x06,
|
||||
0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x22, 0x5b, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
|
||||
0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x61,
|
||||
0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x54, 0x61, 0x67, 0x3a, 0x1d, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x72, 0x82, 0xb5, 0x18, 0x0b, 0x12, 0x09, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x70,
|
||||
0x69, 0x6e, 0x67, 0x22, 0x88, 0x02, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||
0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||
0x3b, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
|
||||
0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57,
|
||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09,
|
||||
0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52,
|
||||
0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78,
|
||||
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78,
|
||||
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c,
|
||||
0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c,
|
||||
0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x61, 0x67, 0x3a,
|
||||
0x1d, 0x82, 0xb5, 0x18, 0x0a, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x82,
|
||||
0xb5, 0x18, 0x0b, 0x12, 0x09, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0xdd,
|
||||
0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d,
|
||||
0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0e, 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x36, 0x0a, 0x04, 0x72, 0x75, 0x6c,
|
||||
0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x09, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x4f, 0x6e, 0x6c, 0x79, 0x3a, 0x16, 0x82, 0xb5, 0x18, 0x12,
|
||||
0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x06, 0x72, 0x61, 0x6e, 0x64,
|
||||
0x6f, 0x6d, 0x22, 0x57, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65,
|
||||
0x61, 0x73, 0x74, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a,
|
||||
0x0c, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x54, 0x61, 0x67,
|
||||
0x3a, 0x19, 0x82, 0xb5, 0x18, 0x15, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72,
|
||||
0x12, 0x09, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x70, 0x69, 0x6e, 0x67, 0x22, 0x84, 0x02, 0x0a, 0x17,
|
||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61,
|
||||
0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63,
|
||||
0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65,
|
||||
0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e,
|
||||
0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06,
|
||||
0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x5f, 0x74, 0x61, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x62, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x54, 0x61, 0x67, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x15, 0x0a, 0x08, 0x62,
|
||||
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x12, 0x09, 0x6c, 0x65, 0x61, 0x73, 0x74, 0x6c, 0x6f,
|
||||
0x61, 0x64, 0x22, 0xdd, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a,
|
||||
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44,
|
||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64,
|
||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x36, 0x0a,
|
||||
0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x32,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52,
|
||||
0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
|
||||
0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
|
||||
0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52,
|
||||
0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75,
|
||||
0x6c, 0x65, 0x22, 0xab, 0x05, 0x0a, 0x15, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65,
|
||||
0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03,
|
||||
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67,
|
||||
0x12, 0x25, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61,
|
||||
0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x12, 0x42, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e,
|
||||
0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c,
|
||||
0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72,
|
||||
0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x32, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52,
|
||||
0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0xab,
|
||||
0x05, 0x0a, 0x15, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x52, 0x6f, 0x75,
|
||||
0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x0d,
|
||||
0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c, 0x20,
|
||||
0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67,
|
||||
0x54, 0x61, 0x67, 0x12, 0x42, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
|
||||
0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70,
|
||||
0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49,
|
||||
0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
|
||||
0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e,
|
||||
0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x6e, 0x65, 0x74,
|
||||
0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x4c, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f,
|
||||
0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||
0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x65,
|
||||
0x6f, 0x69, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73,
|
||||
0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28,
|
||||
0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x0a, 0x0b,
|
||||
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28,
|
||||
0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a,
|
||||
0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||
0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61,
|
||||
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d,
|
||||
0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
|
||||
0x12, 0x4c, 0x0a, 0x0a, 0x67, 0x65, 0x6f, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0xa1,
|
||||
0x93, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x53,
|
||||
0x69, 0x74, 0x65, 0x52, 0x09, 0x67, 0x65, 0x6f, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x42, 0x0c,
|
||||
0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0x8c, 0x02, 0x0a,
|
||||
0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61,
|
||||
0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25, 0x2e, 0x76, 0x32, 0x72,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x44, 0x6f, 0x6d,
|
||||
0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x05, 0x67,
|
||||
0x65, 0x6f, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||
0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||
0x79, 0x12, 0x40, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x2c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69,
|
||||
0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72,
|
||||
0x75, 0x6c, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67,
|
||||
0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x76, 0x32,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c,
|
||||
0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65,
|
||||
0x3a, 0x19, 0x82, 0xb5, 0x18, 0x09, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x82,
|
||||
0xb5, 0x18, 0x08, 0x12, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2a, 0x47, 0x0a, 0x0e, 0x44,
|
||||
0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||
0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3e, 0x0a, 0x08, 0x6e, 0x65, 0x74,
|
||||
0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x76, 0x32,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||
0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x52,
|
||||
0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x4c, 0x0a, 0x0c, 0x73, 0x6f, 0x75,
|
||||
0x72, 0x63, 0x65, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72,
|
||||
0x63, 0x65, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63,
|
||||
0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73,
|
||||
0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18,
|
||||
0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c,
|
||||
0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18,
|
||||
0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61,
|
||||
0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20,
|
||||
0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a,
|
||||
0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a,
|
||||
0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18,
|
||||
0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74,
|
||||
0x63, 0x68, 0x65, 0x72, 0x12, 0x4c, 0x0a, 0x0a, 0x67, 0x65, 0x6f, 0x5f, 0x64, 0x6f, 0x6d, 0x61,
|
||||
0x69, 0x6e, 0x18, 0xa1, 0x93, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x76, 0x32, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||
0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52, 0x09, 0x67, 0x65, 0x6f, 0x44, 0x6f, 0x6d, 0x61,
|
||||
0x69, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67,
|
||||
0x22, 0x88, 0x02, 0x0a, 0x10, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
|
||||
0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x25,
|
||||
0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72,
|
||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72,
|
||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x40, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x69, 0x6d, 0x70,
|
||||
0x6c, 0x69, 0x66, 0x69, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c,
|
||||
0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x4b, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x24, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e,
|
||||
0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67,
|
||||
0x52, 0x75, 0x6c, 0x65, 0x3a, 0x15, 0x82, 0xb5, 0x18, 0x11, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x12, 0x06, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2a, 0x47, 0x0a, 0x0e, 0x44,
|
||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a,
|
||||
0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70,
|
||||
0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74,
|
||||
@ -1218,7 +1213,7 @@ var file_app_router_config_proto_goTypes = []interface{}{
|
||||
(*net.NetworkList)(nil), // 15: v2ray.core.common.net.NetworkList
|
||||
(net.Network)(0), // 16: v2ray.core.common.net.Network
|
||||
(*routercommon.GeoSite)(nil), // 17: v2ray.core.app.router.routercommon.GeoSite
|
||||
(*any.Any)(nil), // 18: google.protobuf.Any
|
||||
(*anypb.Any)(nil), // 18: google.protobuf.Any
|
||||
}
|
||||
var file_app_router_config_proto_depIdxs = []int32{
|
||||
10, // 0: v2ray.core.app.router.RoutingRule.domain:type_name -> v2ray.core.app.router.routercommon.Domain
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v3.17.3
|
||||
// protoc v4.24.4
|
||||
// source: config.proto
|
||||
|
||||
package core
|
||||
|
10
go.mod
10
go.mod
@ -6,6 +6,8 @@ toolchain go1.21.4
|
||||
|
||||
require (
|
||||
github.com/adrg/xdg v0.5.0
|
||||
github.com/apernet/hysteria/core/v2 v2.4.5
|
||||
github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/go-playground/validator/v10 v10.22.0
|
||||
@ -61,21 +63,23 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect
|
||||
github.com/google/pprof v0.0.0-20240320155624-b11c3daa6f07 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/klauspost/reedsolomon v1.11.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mustafaturan/monoton v1.0.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.10.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.17.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pion/logging v0.2.2 // indirect
|
||||
github.com/pion/randutil v0.1.0 // indirect
|
||||
github.com/pion/sctp v1.8.7 // indirect
|
||||
github.com/pion/transport/v3 v3.0.7 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||
github.com/secure-io/siv-go v0.0.0-20180922214919-5ff40651e2c4 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/xtaci/smux v1.5.24 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
@ -87,3 +91,5 @@ require (
|
||||
)
|
||||
|
||||
replace github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 => github.com/xiaokangwang/struc v0.0.0-20231031203518-0e381172f248
|
||||
|
||||
replace github.com/apernet/hysteria/core/v2 v2.4.5 => github.com/JimmyHuang454/hysteria/core/v2 v2.0.0-20240724161647-b3347cf6334d
|
||||
|
34
go.sum
34
go.sum
@ -14,6 +14,8 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/FlowerWrong/water v0.0.0-20180301012659-01a4eaa1f6f2/go.mod h1:xrG5L7lq7T2DLnPr2frMnL906CNEoKRwLB+VYFhPq2w=
|
||||
github.com/JimmyHuang454/hysteria/core/v2 v2.0.0-20240724161647-b3347cf6334d h1:DN3vqWeuVa1anRkwCueIqPEUPnSyFCk4PR2LcyJKrZk=
|
||||
github.com/JimmyHuang454/hysteria/core/v2 v2.0.0-20240724161647-b3347cf6334d/go.mod h1:3OIt9vhWrxoHUMPm6WcpAg7jUEqfy6Q4IyFZA67Azcg=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/adrg/xdg v0.5.0 h1:dDaZvhMXatArP1NPHhnfaQUqWBLBsmx1h1HXQdMoFCY=
|
||||
github.com/adrg/xdg v0.5.0/go.mod h1:dDdY4M4DF9Rjy4kHPeNL+ilVF+p2lK8IdM9/rTSGcI4=
|
||||
@ -25,6 +27,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e h1:KBs8aBfKl5AKPKGpfn3bl0joDJXDq5fnH+AjFODiU+A=
|
||||
github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e/go.mod h1:MjGWpXA31DZZWESdX3/PjIpSWIT1fOm8FNCqyXXFZFU=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
@ -77,8 +81,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
@ -131,8 +135,8 @@ github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs=
|
||||
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
|
||||
github.com/google/pprof v0.0.0-20240320155624-b11c3daa6f07 h1:57oOH2Mu5Nw16KnZAVLdlUjmPH/TSYCKTJgG0OVfX0Y=
|
||||
github.com/google/pprof v0.0.0-20240320155624-b11c3daa6f07/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
@ -187,8 +191,9 @@ github.com/klauspost/reedsolomon v1.11.7 h1:9uaHU0slncktTEEg4+7Vl7q7XUNMBUOK4R9g
|
||||
github.com/klauspost/reedsolomon v1.11.7/go.mod h1:4bXRN+cVzMdml6ti7qLouuYi32KHJ5MGv0Qd8a47h6A=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
@ -221,10 +226,10 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs=
|
||||
github.com/onsi/ginkgo/v2 v2.10.0/go.mod h1:UDQOh5wbQUlMnkLfVaIUMtQ1Vus92oM+P2JX1aulgcE=
|
||||
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
|
||||
github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4=
|
||||
github.com/onsi/ginkgo/v2 v2.17.0 h1:kdnunFXpBjbzN56hcJHrXZ8M+LOkenKA7NnBzTNigTI=
|
||||
github.com/onsi/ginkgo/v2 v2.17.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||
@ -268,6 +273,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y=
|
||||
github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
||||
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
|
||||
@ -276,6 +283,8 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
@ -304,6 +313,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@ -347,6 +358,8 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.starlark.net v0.0.0-20230612165344-9532f5667272 h1:2/wtqS591wZyD2OsClsVBKRPEvBsQt/Js+fsCiYhwu8=
|
||||
go.starlark.net v0.0.0-20230612165344-9532f5667272/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
@ -566,8 +579,9 @@ google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWn
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
|
87
infra/conf/v4/hysteria2.go
Normal file
87
infra/conf/v4/hysteria2.go
Normal file
@ -0,0 +1,87 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
"github.com/v2fly/v2ray-core/v5/common/serial"
|
||||
"github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/hysteria2"
|
||||
)
|
||||
|
||||
// Hysteria2ServerTarget is configuration of a single hysteria2 server
|
||||
type Hysteria2ServerTarget struct {
|
||||
Address *cfgcommon.Address `json:"address"`
|
||||
Port uint16 `json:"port"`
|
||||
Email string `json:"email"`
|
||||
Level byte `json:"level"`
|
||||
}
|
||||
|
||||
// Hysteria2ClientConfig is configuration of hysteria2 servers
|
||||
type Hysteria2ClientConfig struct {
|
||||
Servers []*Hysteria2ServerTarget `json:"servers"`
|
||||
}
|
||||
|
||||
// Build implements Buildable
|
||||
func (c *Hysteria2ClientConfig) Build() (proto.Message, error) {
|
||||
config := new(hysteria2.ClientConfig)
|
||||
|
||||
if len(c.Servers) == 0 {
|
||||
return nil, newError("0 Hysteria2 server configured.")
|
||||
}
|
||||
|
||||
serverSpecs := make([]*protocol.ServerEndpoint, len(c.Servers))
|
||||
for idx, rec := range c.Servers {
|
||||
if rec.Address == nil {
|
||||
return nil, newError("Hysteria2 server address is not set.")
|
||||
}
|
||||
if rec.Port == 0 {
|
||||
return nil, newError("Invalid Hysteria2 port.")
|
||||
}
|
||||
account := &hysteria2.Account{}
|
||||
hysteria2 := &protocol.ServerEndpoint{
|
||||
Address: rec.Address.Build(),
|
||||
Port: uint32(rec.Port),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Level: uint32(rec.Level),
|
||||
Email: rec.Email,
|
||||
Account: serial.ToTypedMessage(account),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
serverSpecs[idx] = hysteria2
|
||||
}
|
||||
|
||||
config.Server = serverSpecs
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// Hysteria2UserConfig is user configuration
|
||||
type Hysteria2UserConfig struct {
|
||||
Level byte `json:"level"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// Hysteria2ServerConfig is Inbound configuration
|
||||
type Hysteria2ServerConfig struct {
|
||||
Clients []*Hysteria2UserConfig `json:"clients"`
|
||||
}
|
||||
|
||||
// Build implements Buildable
|
||||
func (c *Hysteria2ServerConfig) Build() (proto.Message, error) {
|
||||
config := new(hysteria2.ServerConfig)
|
||||
config.Users = make([]*protocol.User, len(c.Clients))
|
||||
for idx, rawUser := range c.Clients {
|
||||
user := new(protocol.User)
|
||||
account := &hysteria2.Account{}
|
||||
|
||||
user.Email = rawUser.Email
|
||||
user.Level = uint32(rawUser.Level)
|
||||
user.Account = serial.ToTypedMessage(account)
|
||||
config.Users[idx] = user
|
||||
}
|
||||
return config, nil
|
||||
}
|
@ -16,6 +16,7 @@ import (
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/domainsocket"
|
||||
httpheader "github.com/v2fly/v2ray-core/v5/transport/internet/headers/http"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/http"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/kcp"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/quic"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tcp"
|
||||
@ -137,6 +138,29 @@ func (c *TCPConfig) Build() (proto.Message, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type Hy2ConfigCongestion struct {
|
||||
Type string `json:"type"`
|
||||
UpMbps uint64 `json:"up_mbps"`
|
||||
DownMbps uint64 `json:"down_mbps"`
|
||||
}
|
||||
|
||||
type Hy2Config struct {
|
||||
Password string `json:"password"`
|
||||
Congestion Hy2ConfigCongestion `json:"congestion"`
|
||||
UseUdpExtension bool `json:"use_udp_extension"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
func (c *Hy2Config) Build() (proto.Message, error) {
|
||||
return &hysteria2.Config{Password: c.Password,
|
||||
Congestion: &hysteria2.Congestion{
|
||||
Type: c.Congestion.Type,
|
||||
DownMbps: c.Congestion.DownMbps,
|
||||
UpMbps: c.Congestion.UpMbps,
|
||||
},
|
||||
UseUdpExtension: c.UseUdpExtension}, nil
|
||||
}
|
||||
|
||||
type WebSocketConfig struct {
|
||||
Path string `json:"path"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
@ -279,6 +303,8 @@ func (p TransportProtocol) Build() (string, error) {
|
||||
return "quic", nil
|
||||
case "gun", "grpc":
|
||||
return "gun", nil
|
||||
case "hy2", "hysteria2":
|
||||
return "hysteria2", nil
|
||||
default:
|
||||
return "", newError("Config: unknown transport protocol: ", p)
|
||||
}
|
||||
@ -296,6 +322,7 @@ type StreamConfig struct {
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
GunSettings *GunConfig `json:"gunSettings"`
|
||||
GRPCSettings *GunConfig `json:"grpcSettings"`
|
||||
Hy2Settings *Hy2Config `json:"hy2Settings"`
|
||||
SocketSettings *socketcfg.SocketConfig `json:"sockopt"`
|
||||
}
|
||||
|
||||
@ -397,6 +424,16 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
Settings: serial.ToTypedMessage(gs),
|
||||
})
|
||||
}
|
||||
if c.Hy2Settings != nil {
|
||||
hy2, err := c.Hy2Settings.Build()
|
||||
if err != nil {
|
||||
return nil, newError("Failed to build hy2 config.").Base(err)
|
||||
}
|
||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(hy2),
|
||||
})
|
||||
}
|
||||
if c.SocketSettings != nil {
|
||||
ss, err := c.SocketSettings.Build()
|
||||
if err != nil {
|
||||
|
@ -35,6 +35,7 @@ var (
|
||||
"vless": func() interface{} { return new(VLessInboundConfig) },
|
||||
"vmess": func() interface{} { return new(VMessInboundConfig) },
|
||||
"trojan": func() interface{} { return new(TrojanServerConfig) },
|
||||
"hysteria2": func() interface{} { return new(Hysteria2ServerConfig) },
|
||||
}, "protocol", "settings")
|
||||
|
||||
outboundConfigLoader = loader.NewJSONConfigLoader(loader.ConfigCreatorCache{
|
||||
@ -46,6 +47,7 @@ var (
|
||||
"vless": func() interface{} { return new(VLessOutboundConfig) },
|
||||
"vmess": func() interface{} { return new(VMessOutboundConfig) },
|
||||
"trojan": func() interface{} { return new(TrojanClientConfig) },
|
||||
"hysteria2": func() interface{} { return new(Hysteria2ClientConfig) },
|
||||
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
||||
"loopback": func() interface{} { return new(LoopbackConfig) },
|
||||
}, "protocol", "settings")
|
||||
|
@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
@ -121,7 +122,17 @@ func getInstalledProtocVersion(protocPath string) (string, error) {
|
||||
}
|
||||
versionRegexp := regexp.MustCompile(`protoc\s*(\d+\.\d+(\.\d)*)`)
|
||||
matched := versionRegexp.FindStringSubmatch(string(output))
|
||||
return matched[1], nil
|
||||
installedVersion := ""
|
||||
if len(matched) == 0 {
|
||||
return "", errors.New("Can not parse protoc version.")
|
||||
}
|
||||
|
||||
if len(matched) == 2 {
|
||||
installedVersion += "4." // in contrast to getProjectProtocVersion()
|
||||
}
|
||||
installedVersion += matched[1]
|
||||
fmt.Println("Using protoc version: " + installedVersion)
|
||||
return installedVersion, nil
|
||||
}
|
||||
|
||||
func parseVersion(s string, width int) int64 {
|
||||
|
@ -53,6 +53,7 @@ import (
|
||||
_ "github.com/v2fly/v2ray-core/v5/proxy/vlite/inbound"
|
||||
_ "github.com/v2fly/v2ray-core/v5/proxy/vlite/outbound"
|
||||
|
||||
_ "github.com/v2fly/v2ray-core/v5/proxy/hysteria2"
|
||||
_ "github.com/v2fly/v2ray-core/v5/proxy/shadowsocks2022"
|
||||
|
||||
// Transports
|
||||
@ -81,6 +82,8 @@ import (
|
||||
|
||||
_ "github.com/v2fly/v2ray-core/v5/transport/internet/httpupgrade"
|
||||
|
||||
_ "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
|
||||
// Transport headers
|
||||
_ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/http"
|
||||
_ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/noop"
|
||||
|
170
proxy/hysteria2/client.go
Normal file
170
proxy/hysteria2/client.go
Normal file
@ -0,0 +1,170 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
"github.com/v2fly/v2ray-core/v5/common/retry"
|
||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
||||
"github.com/v2fly/v2ray-core/v5/common/signal"
|
||||
"github.com/v2fly/v2ray-core/v5/common/task"
|
||||
"github.com/v2fly/v2ray-core/v5/features/policy"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy"
|
||||
"github.com/v2fly/v2ray-core/v5/transport"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
hyTransport "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
)
|
||||
|
||||
// Client is an inbound handler
|
||||
type Client struct {
|
||||
serverPicker protocol.ServerPicker
|
||||
policyManager policy.Manager
|
||||
}
|
||||
|
||||
// NewClient create a new client.
|
||||
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
serverList := protocol.NewServerList()
|
||||
for _, rec := range config.Server {
|
||||
s, err := protocol.NewServerSpecFromPB(rec)
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse server spec").Base(err)
|
||||
}
|
||||
serverList.AddServer(s)
|
||||
}
|
||||
if serverList.Size() == 0 {
|
||||
return nil, newError("0 server")
|
||||
}
|
||||
|
||||
v := core.MustFromContext(ctx)
|
||||
client := &Client{
|
||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Process implements OutboundHandler.Process().
|
||||
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
return newError("target not specified")
|
||||
}
|
||||
destination := outbound.Target
|
||||
network := destination.Network
|
||||
|
||||
var server *protocol.ServerSpec
|
||||
var conn internet.Connection
|
||||
|
||||
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||
server = c.serverPicker.PickServer()
|
||||
rawConn, err := dialer.Dial(ctx, server.Destination())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn = rawConn
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return newError("failed to find an available destination").AtWarning().Base(err)
|
||||
}
|
||||
newError("tunneling request to ", destination, " via ", server.Destination().NetAddr()).WriteToLog(session.ExportIDToError(ctx))
|
||||
|
||||
iConn := conn
|
||||
if statConn, ok := conn.(*internet.StatCouterConnection); ok {
|
||||
iConn = statConn.Connection // will not count the UDP traffic.
|
||||
}
|
||||
hyConn, IsHy2Transport := iConn.(*hyTransport.HyConn)
|
||||
|
||||
if !IsHy2Transport && network == net.Network_UDP {
|
||||
// hysteria2 need to use udp extension to proxy UDP.
|
||||
return newError(hyTransport.CanNotUseUdpExtension)
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
user := server.PickUser()
|
||||
account, ok := user.Account.(*MemoryAccount)
|
||||
if !ok {
|
||||
return newError("user account is not valid")
|
||||
}
|
||||
|
||||
sessionPolicy := c.policyManager.ForLevel(user.Level)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||
|
||||
postRequest := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||
|
||||
var bodyWriter buf.Writer
|
||||
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
|
||||
connWriter := &ConnWriter{Writer: bufferWriter, Target: destination, Account: account}
|
||||
bodyWriter = connWriter
|
||||
|
||||
if network == net.Network_UDP {
|
||||
bodyWriter = &PacketWriter{Writer: connWriter, Target: destination, HyConn: hyConn}
|
||||
} else {
|
||||
// write some request payload to buffer
|
||||
err = buf.CopyOnceTimeout(link.Reader, bodyWriter, proxy.FirstPayloadTimeout)
|
||||
switch err {
|
||||
case buf.ErrNotTimeoutReader, buf.ErrReadTimeout:
|
||||
if err := connWriter.WriteTCPHeader(); err != nil {
|
||||
return newError("failed to write request header").Base(err).AtWarning()
|
||||
}
|
||||
case nil:
|
||||
default:
|
||||
return newError("failed to write a request payload").Base(err).AtWarning()
|
||||
}
|
||||
// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer
|
||||
if err = bufferWriter.SetBuffered(false); err != nil {
|
||||
return newError("failed to flush payload").Base(err).AtWarning()
|
||||
}
|
||||
}
|
||||
|
||||
if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {
|
||||
return newError("failed to transfer request payload").Base(err).AtInfo()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
getResponse := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
|
||||
|
||||
var reader buf.Reader
|
||||
if network == net.Network_UDP {
|
||||
reader = &PacketReader{
|
||||
Reader: conn, HyConn: hyConn,
|
||||
}
|
||||
} else {
|
||||
ok, msg, err := hyProtocol.ReadTCPResponse(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return newError(msg)
|
||||
}
|
||||
reader = buf.NewReader(conn)
|
||||
}
|
||||
return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
|
||||
}
|
||||
|
||||
responseDoneAndCloseWriter := task.OnSuccess(getResponse, task.Close(link.Writer))
|
||||
if err := task.Run(ctx, postRequest, responseDoneAndCloseWriter); err != nil {
|
||||
return newError("connection ends").Base(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return NewClient(ctx, config.(*ClientConfig))
|
||||
}))
|
||||
}
|
45
proxy/hysteria2/config.go
Normal file
45
proxy/hysteria2/config.go
Normal file
@ -0,0 +1,45 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
)
|
||||
|
||||
// MemoryAccount is an account type converted from Account.
|
||||
type MemoryAccount struct {
|
||||
Password string
|
||||
Key []byte
|
||||
}
|
||||
|
||||
// AsAccount implements protocol.AsAccount.
|
||||
func (a *Account) AsAccount() (protocol.Account, error) {
|
||||
return &MemoryAccount{}, nil
|
||||
}
|
||||
|
||||
// Equals implements protocol.Account.Equals().
|
||||
func (a *MemoryAccount) Equals(another protocol.Account) bool {
|
||||
if account, ok := another.(*MemoryAccount); ok {
|
||||
return a.Password == account.Password
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hexSha224(password string) []byte {
|
||||
buf := make([]byte, 56)
|
||||
hash := sha256.New224()
|
||||
common.Must2(hash.Write([]byte(password)))
|
||||
hex.Encode(buf, hash.Sum(nil))
|
||||
return buf
|
||||
}
|
||||
|
||||
func hexString(data []byte) string {
|
||||
str := ""
|
||||
for _, v := range data {
|
||||
str += fmt.Sprintf("%02x", v)
|
||||
}
|
||||
return str
|
||||
}
|
363
proxy/hysteria2/config.pb.go
Normal file
363
proxy/hysteria2/config.pb.go
Normal file
@ -0,0 +1,363 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
protocol "github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
_ "github.com/v2fly/v2ray-core/v5/common/protoext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type OBFS struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
|
||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||
}
|
||||
|
||||
func (x *OBFS) Reset() {
|
||||
*x = OBFS{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *OBFS) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*OBFS) ProtoMessage() {}
|
||||
|
||||
func (x *OBFS) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[0]
|
||||
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 OBFS.ProtoReflect.Descriptor instead.
|
||||
func (*OBFS) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_hysteria2_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *OBFS) GetType() string {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *OBFS) GetPassword() string {
|
||||
if x != nil {
|
||||
return x.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type Account struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Obfs *OBFS `protobuf:"bytes,1,opt,name=obfs,proto3" json:"obfs,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Account) Reset() {
|
||||
*x = Account{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Account) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Account) ProtoMessage() {}
|
||||
|
||||
func (x *Account) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_hysteria2_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 Account.ProtoReflect.Descriptor instead.
|
||||
func (*Account) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_hysteria2_config_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Account) GetObfs() *OBFS {
|
||||
if x != nil {
|
||||
return x.Obfs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ClientConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ClientConfig) Reset() {
|
||||
*x = ClientConfig{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClientConfig) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ClientConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ClientConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[2]
|
||||
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 ClientConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ClientConfig) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_hysteria2_config_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint {
|
||||
if x != nil {
|
||||
return x.Server
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ServerConfig) Reset() {
|
||||
*x = ServerConfig{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServerConfig) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServerConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ServerConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[3]
|
||||
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 ServerConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ServerConfig) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_hysteria2_config_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ServerConfig) GetUsers() []*protocol.User {
|
||||
if x != nil {
|
||||
return x.Users
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_proxy_hysteria2_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proxy_hysteria2_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61,
|
||||
0x32, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a,
|
||||
0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x2e, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 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, 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, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||
0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e,
|
||||
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x36, 0x0a, 0x04, 0x4f,
|
||||
0x42, 0x46, 0x53, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
|
||||
0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
|
||||
0x6f, 0x72, 0x64, 0x22, 0x3f, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x34,
|
||||
0x0a, 0x04, 0x6f, 0x62, 0x66, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x76,
|
||||
0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
||||
0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x2e, 0x4f, 0x42, 0x46, 0x53, 0x52, 0x04,
|
||||
0x6f, 0x62, 0x66, 0x73, 0x22, 0x6d, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x42, 0x0a, 0x06, 0x73, 0x65, 0x72, 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, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x15, 0x0a, 0x08,
|
||||
0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x09, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72,
|
||||
0x69, 0x61, 0x32, 0x22, 0x60, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 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, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x3a, 0x18, 0x82, 0xb5, 0x18,
|
||||
0x14, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x09, 0x68, 0x79, 0x73, 0x74,
|
||||
0x65, 0x72, 0x69, 0x61, 0x32, 0x42, 0x6f, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x68, 0x79,
|
||||
0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61,
|
||||
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
|
||||
0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, 0x61,
|
||||
0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x48, 0x79, 0x73,
|
||||
0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_proxy_hysteria2_config_proto_rawDescOnce sync.Once
|
||||
file_proxy_hysteria2_config_proto_rawDescData = file_proxy_hysteria2_config_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_proxy_hysteria2_config_proto_rawDescGZIP() []byte {
|
||||
file_proxy_hysteria2_config_proto_rawDescOnce.Do(func() {
|
||||
file_proxy_hysteria2_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_proxy_hysteria2_config_proto_rawDescData)
|
||||
})
|
||||
return file_proxy_hysteria2_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proxy_hysteria2_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_proxy_hysteria2_config_proto_goTypes = []interface{}{
|
||||
(*OBFS)(nil), // 0: v2ray.core.proxy.hysteria2.OBFS
|
||||
(*Account)(nil), // 1: v2ray.core.proxy.hysteria2.Account
|
||||
(*ClientConfig)(nil), // 2: v2ray.core.proxy.hysteria2.ClientConfig
|
||||
(*ServerConfig)(nil), // 3: v2ray.core.proxy.hysteria2.ServerConfig
|
||||
(*protocol.ServerEndpoint)(nil), // 4: v2ray.core.common.protocol.ServerEndpoint
|
||||
(*protocol.User)(nil), // 5: v2ray.core.common.protocol.User
|
||||
}
|
||||
var file_proxy_hysteria2_config_proto_depIdxs = []int32{
|
||||
0, // 0: v2ray.core.proxy.hysteria2.Account.obfs:type_name -> v2ray.core.proxy.hysteria2.OBFS
|
||||
4, // 1: v2ray.core.proxy.hysteria2.ClientConfig.server:type_name -> v2ray.core.common.protocol.ServerEndpoint
|
||||
5, // 2: v2ray.core.proxy.hysteria2.ServerConfig.users:type_name -> v2ray.core.common.protocol.User
|
||||
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
|
||||
}
|
||||
|
||||
func init() { file_proxy_hysteria2_config_proto_init() }
|
||||
func file_proxy_hysteria2_config_proto_init() {
|
||||
if File_proxy_hysteria2_config_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_proxy_hysteria2_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*OBFS); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proxy_hysteria2_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Account); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proxy_hysteria2_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ClientConfig); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proxy_hysteria2_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ServerConfig); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proxy_hysteria2_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_proxy_hysteria2_config_proto_goTypes,
|
||||
DependencyIndexes: file_proxy_hysteria2_config_proto_depIdxs,
|
||||
MessageInfos: file_proxy_hysteria2_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proxy_hysteria2_config_proto = out.File
|
||||
file_proxy_hysteria2_config_proto_rawDesc = nil
|
||||
file_proxy_hysteria2_config_proto_goTypes = nil
|
||||
file_proxy_hysteria2_config_proto_depIdxs = nil
|
||||
}
|
34
proxy/hysteria2/config.proto
Normal file
34
proxy/hysteria2/config.proto
Normal file
@ -0,0 +1,34 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.proxy.hysteria2;
|
||||
option csharp_namespace = "V2Ray.Core.Proxy.Hysteria2";
|
||||
option go_package = "github.com/v2fly/v2ray-core/v5/proxy/hysteria2";
|
||||
option java_package = "com.v2ray.core.proxy.hysteria2";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "common/protocol/user.proto";
|
||||
import "common/protocol/server_spec.proto";
|
||||
import "common/protoext/extensions.proto";
|
||||
|
||||
message OBFS {
|
||||
string type = 1;
|
||||
string password = 2;
|
||||
}
|
||||
|
||||
message Account {
|
||||
OBFS obfs = 1;
|
||||
}
|
||||
|
||||
message ClientConfig {
|
||||
option (v2ray.core.common.protoext.message_opt).type = "outbound";
|
||||
option (v2ray.core.common.protoext.message_opt).short_name = "hysteria2";
|
||||
|
||||
repeated v2ray.core.common.protocol.ServerEndpoint server = 1;
|
||||
}
|
||||
|
||||
message ServerConfig {
|
||||
option (v2ray.core.common.protoext.message_opt).type = "inbound";
|
||||
option (v2ray.core.common.protoext.message_opt).short_name = "hysteria2";
|
||||
|
||||
repeated v2ray.core.common.protocol.User users = 1;
|
||||
}
|
9
proxy/hysteria2/errors.generated.go
Normal file
9
proxy/hysteria2/errors.generated.go
Normal file
@ -0,0 +1,9 @@
|
||||
package hysteria2
|
||||
|
||||
import "github.com/v2fly/v2ray-core/v5/common/errors"
|
||||
|
||||
type errPathObjHolder struct{}
|
||||
|
||||
func newError(values ...interface{}) *errors.Error {
|
||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||
}
|
1
proxy/hysteria2/hysteria2.go
Normal file
1
proxy/hysteria2/hysteria2.go
Normal file
@ -0,0 +1 @@
|
||||
package hysteria2
|
204
proxy/hysteria2/protocol.go
Normal file
204
proxy/hysteria2/protocol.go
Normal file
@ -0,0 +1,204 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"io"
|
||||
gonet "net"
|
||||
|
||||
hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
"github.com/apernet/quic-go/quicvarint"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
hyTransport "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
)
|
||||
|
||||
// ConnWriter is TCP Connection Writer Wrapper
|
||||
type ConnWriter struct {
|
||||
io.Writer
|
||||
Target net.Destination
|
||||
Account *MemoryAccount
|
||||
TCPHeaderSent bool
|
||||
}
|
||||
|
||||
// Write implements io.Writer
|
||||
func (c *ConnWriter) Write(p []byte) (n int, err error) {
|
||||
if !c.TCPHeaderSent {
|
||||
if err := c.writeTCPHeader(); err != nil {
|
||||
return 0, newError("failed to write request header").Base(err)
|
||||
}
|
||||
}
|
||||
|
||||
return c.Writer.Write(p)
|
||||
}
|
||||
|
||||
// WriteMultiBuffer implements buf.Writer
|
||||
func (c *ConnWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
defer buf.ReleaseMulti(mb)
|
||||
|
||||
for _, b := range mb {
|
||||
if !b.IsEmpty() {
|
||||
if _, err := c.Write(b.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConnWriter) WriteTCPHeader() error {
|
||||
if !c.TCPHeaderSent {
|
||||
if err := c.writeTCPHeader(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func QuicLen(s int) int {
|
||||
return int(quicvarint.Len(uint64(s)))
|
||||
}
|
||||
|
||||
func (c *ConnWriter) writeTCPHeader() error {
|
||||
c.TCPHeaderSent = true
|
||||
|
||||
// TODO: the padding length here should be randomized
|
||||
|
||||
padding := "Jimmy Was Here"
|
||||
paddingLen := len(padding)
|
||||
addressAndPort := c.Target.NetAddr()
|
||||
addressLen := len(addressAndPort)
|
||||
size := QuicLen(addressLen) + addressLen + QuicLen(paddingLen) + paddingLen
|
||||
|
||||
if size > hyProtocol.MaxAddressLength+hyProtocol.MaxPaddingLength {
|
||||
return newError("invalid header length")
|
||||
}
|
||||
|
||||
buf := make([]byte, size)
|
||||
i := hyProtocol.VarintPut(buf, uint64(addressLen))
|
||||
i += copy(buf[i:], addressAndPort)
|
||||
i += hyProtocol.VarintPut(buf[i:], uint64(paddingLen))
|
||||
copy(buf[i:], padding)
|
||||
|
||||
_, err := c.Writer.Write(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
// PacketWriter UDP Connection Writer Wrapper
|
||||
type PacketWriter struct {
|
||||
io.Writer
|
||||
HyConn *hyTransport.HyConn
|
||||
Target net.Destination
|
||||
}
|
||||
|
||||
// WriteMultiBuffer implements buf.Writer
|
||||
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
for _, b := range mb {
|
||||
if b.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
if _, err := w.writePacket(b.Bytes(), w.Target); err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMultiBufferWithMetadata writes udp packet with destination specified
|
||||
func (w *PacketWriter) WriteMultiBufferWithMetadata(mb buf.MultiBuffer, dest net.Destination) error {
|
||||
for _, b := range mb {
|
||||
if b.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
if _, err := w.writePacket(b.Bytes(), dest); err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *PacketWriter) WriteTo(payload []byte, addr gonet.Addr) (int, error) {
|
||||
dest := net.DestinationFromAddr(addr)
|
||||
|
||||
return w.writePacket(payload, dest)
|
||||
}
|
||||
|
||||
func (w *PacketWriter) writePacket(payload []byte, dest net.Destination) (int, error) {
|
||||
return w.HyConn.WritePacket(payload, dest)
|
||||
}
|
||||
|
||||
// ConnReader is TCP Connection Reader Wrapper
|
||||
type ConnReader struct {
|
||||
io.Reader
|
||||
Target net.Destination
|
||||
}
|
||||
|
||||
// Read implements io.Reader
|
||||
func (c *ConnReader) Read(p []byte) (int, error) {
|
||||
return c.Reader.Read(p)
|
||||
}
|
||||
|
||||
// ReadMultiBuffer implements buf.Reader
|
||||
func (c *ConnReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
b := buf.New()
|
||||
_, err := b.ReadFrom(c)
|
||||
return buf.MultiBuffer{b}, err
|
||||
}
|
||||
|
||||
// PacketPayload combines udp payload and destination
|
||||
type PacketPayload struct {
|
||||
Target net.Destination
|
||||
Buffer buf.MultiBuffer
|
||||
}
|
||||
|
||||
// PacketReader is UDP Connection Reader Wrapper
|
||||
type PacketReader struct {
|
||||
io.Reader
|
||||
HyConn *hyTransport.HyConn
|
||||
}
|
||||
|
||||
// ReadMultiBuffer implements buf.Reader
|
||||
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
p, err := r.ReadMultiBufferWithMetadata()
|
||||
if p != nil {
|
||||
return p.Buffer, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ReadMultiBufferWithMetadata reads udp packet with destination
|
||||
func (r *PacketReader) ReadMultiBufferWithMetadata() (*PacketPayload, error) {
|
||||
_, data, dest, err := r.HyConn.ReadPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := buf.FromBytes(data)
|
||||
return &PacketPayload{Target: *dest, Buffer: buf.MultiBuffer{b}}, nil
|
||||
}
|
||||
|
||||
type PacketConnectionReader struct {
|
||||
reader *PacketReader
|
||||
payload *PacketPayload
|
||||
}
|
||||
|
||||
func (r *PacketConnectionReader) ReadFrom(p []byte) (n int, addr gonet.Addr, err error) {
|
||||
if r.payload == nil || r.payload.Buffer.IsEmpty() {
|
||||
r.payload, err = r.reader.ReadMultiBufferWithMetadata()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
addr = &gonet.UDPAddr{
|
||||
IP: r.payload.Target.Address.IP(),
|
||||
Port: int(r.payload.Target.Port),
|
||||
}
|
||||
|
||||
r.payload.Buffer, n = buf.SplitFirstBytes(r.payload.Buffer, p)
|
||||
|
||||
return
|
||||
}
|
216
proxy/hysteria2/server.go
Normal file
216
proxy/hysteria2/server.go
Normal file
@ -0,0 +1,216 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/errors"
|
||||
"github.com/v2fly/v2ray-core/v5/common/log"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net/packetaddr"
|
||||
udp_proto "github.com/v2fly/v2ray-core/v5/common/protocol/udp"
|
||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
||||
"github.com/v2fly/v2ray-core/v5/common/signal"
|
||||
"github.com/v2fly/v2ray-core/v5/common/task"
|
||||
"github.com/v2fly/v2ray-core/v5/features/policy"
|
||||
"github.com/v2fly/v2ray-core/v5/features/routing"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
hyTransport "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/udp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return NewServer(ctx, config.(*ServerConfig))
|
||||
}))
|
||||
}
|
||||
|
||||
// Server is an inbound connection handler that handles messages in protocol.
|
||||
type Server struct {
|
||||
policyManager policy.Manager
|
||||
packetEncoding packetaddr.PacketAddrType
|
||||
}
|
||||
|
||||
// NewServer creates a new inbound handler.
|
||||
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||
v := core.MustFromContext(ctx)
|
||||
server := &Server{
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
}
|
||||
return server, nil
|
||||
}
|
||||
|
||||
// Network implements proxy.Inbound.Network().
|
||||
func (s *Server) Network() []net.Network {
|
||||
return []net.Network{net.Network_TCP, net.Network_UNIX}
|
||||
}
|
||||
|
||||
// Process implements proxy.Inbound.Process().
|
||||
func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
||||
sid := session.ExportIDToError(ctx)
|
||||
|
||||
iConn := conn
|
||||
if statConn, ok := conn.(*internet.StatCouterConnection); ok {
|
||||
iConn = statConn.Connection // will not count the UDP traffic.
|
||||
}
|
||||
hyConn, IsHy2Transport := iConn.(*hyTransport.HyConn)
|
||||
|
||||
if IsHy2Transport && hyConn.IsUDPExtension {
|
||||
network = net.Network_UDP
|
||||
}
|
||||
|
||||
if !IsHy2Transport && network == net.Network_UDP {
|
||||
return newError(hyTransport.CanNotUseUdpExtension)
|
||||
}
|
||||
|
||||
sessionPolicy := s.policyManager.ForLevel(0)
|
||||
if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
|
||||
return newError("unable to set read deadline").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
bufferedReader := &buf.BufferedReader{
|
||||
Reader: buf.NewReader(conn),
|
||||
}
|
||||
clientReader := &ConnReader{Reader: bufferedReader}
|
||||
|
||||
if err := conn.SetReadDeadline(time.Time{}); err != nil {
|
||||
return newError("unable to set read deadline").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
if network == net.Network_UDP { // handle udp request
|
||||
return s.handleUDPPayload(ctx,
|
||||
&PacketReader{Reader: clientReader, HyConn: hyConn},
|
||||
&PacketWriter{Writer: conn, HyConn: hyConn}, dispatcher)
|
||||
}
|
||||
|
||||
var reqAddr string
|
||||
var err error
|
||||
reqAddr, err = hyProtocol.ReadTCPRequest(conn)
|
||||
if err != nil {
|
||||
return newError("failed to parse header").Base(err)
|
||||
}
|
||||
err = hyProtocol.WriteTCPResponse(conn, true, "")
|
||||
if err != nil {
|
||||
return newError("failed to send response").Base(err)
|
||||
}
|
||||
|
||||
address, stringPort, err := net.SplitHostPort(reqAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
port, err := net.PortFromString(stringPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
destination := net.Destination{Network: network, Address: net.ParseAddress(address), Port: port}
|
||||
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound == nil {
|
||||
panic("no inbound metadata")
|
||||
}
|
||||
sessionPolicy = s.policyManager.ForLevel(0)
|
||||
|
||||
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
||||
From: conn.RemoteAddr(),
|
||||
To: destination,
|
||||
Status: log.AccessAccepted,
|
||||
Reason: "",
|
||||
})
|
||||
|
||||
newError("received request for ", destination).WriteToLog(sid)
|
||||
return s.handleConnection(ctx, sessionPolicy, destination, clientReader, buf.NewWriter(conn), dispatcher)
|
||||
}
|
||||
|
||||
func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Session,
|
||||
destination net.Destination,
|
||||
clientReader buf.Reader,
|
||||
clientWriter buf.Writer, dispatcher routing.Dispatcher,
|
||||
) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||
ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
|
||||
|
||||
link, err := dispatcher.Dispatch(ctx, destination)
|
||||
if err != nil {
|
||||
return newError("failed to dispatch request to ", destination).Base(err)
|
||||
}
|
||||
|
||||
requestDone := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||
|
||||
if err := buf.Copy(clientReader, link.Writer, buf.UpdateActivity(timer)); err != nil {
|
||||
return newError("failed to transfer request").Base(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
responseDone := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
|
||||
|
||||
if err := buf.Copy(link.Reader, clientWriter, buf.UpdateActivity(timer)); err != nil {
|
||||
return newError("failed to write response").Base(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
requestDonePost := task.OnSuccess(requestDone, task.Close(link.Writer))
|
||||
if err := task.Run(ctx, requestDonePost, responseDone); err != nil {
|
||||
common.Must(common.Interrupt(link.Reader))
|
||||
common.Must(common.Interrupt(link.Writer))
|
||||
return newError("connection ends").Base(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error { // {{{
|
||||
udpDispatcherConstructor := udp.NewSplitDispatcher
|
||||
switch s.packetEncoding {
|
||||
case packetaddr.PacketAddrType_None:
|
||||
case packetaddr.PacketAddrType_Packet:
|
||||
packetAddrDispatcherFactory := udp.NewPacketAddrDispatcherCreator(ctx)
|
||||
udpDispatcherConstructor = packetAddrDispatcherFactory.NewPacketAddrDispatcher
|
||||
}
|
||||
|
||||
udpServer := udpDispatcherConstructor(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
||||
if err := clientWriter.WriteMultiBufferWithMetadata(buf.MultiBuffer{packet.Payload}, packet.Source); err != nil {
|
||||
newError("failed to write response").Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
})
|
||||
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
// user := inbound.User
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
default:
|
||||
p, err := clientReader.ReadMultiBufferWithMetadata()
|
||||
if err != nil {
|
||||
if errors.Cause(err) != io.EOF {
|
||||
return newError("unexpected EOF").Base(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
currentPacketCtx := ctx
|
||||
currentPacketCtx = log.ContextWithAccessMessage(currentPacketCtx, &log.AccessMessage{
|
||||
From: inbound.Source,
|
||||
To: p.Target,
|
||||
Status: log.AccessAccepted,
|
||||
Reason: "",
|
||||
})
|
||||
newError("tunnelling request to ", p.Target).WriteToLog(session.ExportIDToError(ctx))
|
||||
|
||||
for _, b := range p.Buffer {
|
||||
udpServer.Dispatch(currentPacketCtx, p.Target, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
} // }}}
|
480
testing/scenarios/hy2_test.go
Normal file
480
testing/scenarios/hy2_test.go
Normal file
@ -0,0 +1,480 @@
|
||||
package scenarios
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/app/log"
|
||||
"github.com/v2fly/v2ray-core/v5/app/proxyman"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
clog "github.com/v2fly/v2ray-core/v5/common/log"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol/tls/cert"
|
||||
"github.com/v2fly/v2ray-core/v5/common/serial"
|
||||
"github.com/v2fly/v2ray-core/v5/common/uuid"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/dokodemo"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/freedom"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/vmess"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/vmess/inbound"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/vmess/outbound"
|
||||
"github.com/v2fly/v2ray-core/v5/testing/servers/tcp"
|
||||
"github.com/v2fly/v2ray-core/v5/testing/servers/udp"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/headers/http"
|
||||
hyTransport "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
tcpTransport "github.com/v2fly/v2ray-core/v5/transport/internet/tcp"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
|
||||
)
|
||||
|
||||
func TestVMessHysteria2Congestion(t *testing.T) {
|
||||
for _, v := range []string{"bbr", "brutal"} {
|
||||
testVMessHysteria2(t, v)
|
||||
}
|
||||
}
|
||||
|
||||
func testVMessHysteria2(t *testing.T, congestionType string) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err := tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
|
||||
userID := protocol.NewID(uuid.New())
|
||||
serverPort := udp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(serverPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(&hyTransport.Config{
|
||||
Congestion: &hyTransport.Congestion{Type: congestionType, UpMbps: 100, DownMbps: 100},
|
||||
Password: "password",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&inbound.Config{
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&vmess.Account{
|
||||
Id: userID.String(),
|
||||
AlterId: 0,
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
clientConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(clientPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
NetworkList: &net.NetworkList{
|
||||
Network: []net.Network{net.Network_TCP},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(&hyTransport.Config{
|
||||
Congestion: &hyTransport.Congestion{Type: congestionType, UpMbps: 100, DownMbps: 100},
|
||||
Password: "password",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||
Receiver: []*protocol.ServerEndpoint{
|
||||
{
|
||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||
Port: uint32(serverPort),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&vmess.Account{
|
||||
Id: userID.String(),
|
||||
AlterId: 0,
|
||||
SecuritySettings: &protocol.SecurityConfig{
|
||||
Type: protocol.SecurityType_NONE,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to initialize all servers: ", err.Error())
|
||||
}
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 10; i++ {
|
||||
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*40))
|
||||
}
|
||||
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHysteria2Offical(t *testing.T) {
|
||||
for _, v := range []bool{true, false} {
|
||||
testHysteria2Offical(t, v)
|
||||
}
|
||||
}
|
||||
|
||||
func testHysteria2Offical(t *testing.T, isUDP bool) {
|
||||
var dest net.Destination
|
||||
var err error
|
||||
if isUDP {
|
||||
udpServer := udp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err = udpServer.Start()
|
||||
common.Must(err)
|
||||
defer udpServer.Close()
|
||||
} else {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err = tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
}
|
||||
|
||||
serverPort := udp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(serverPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(&hyTransport.Config{
|
||||
Congestion: &hyTransport.Congestion{Type: "brutal", UpMbps: 100, DownMbps: 100},
|
||||
UseUdpExtension: true,
|
||||
Password: "password",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&hysteria2.ServerConfig{
|
||||
Users: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&hysteria2.Account{}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
clientConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(clientPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
NetworkList: &net.NetworkList{
|
||||
Network: []net.Network{net.Network_TCP, net.Network_UDP},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(&hyTransport.Config{
|
||||
Congestion: &hyTransport.Congestion{Type: "brutal", UpMbps: 100, DownMbps: 100},
|
||||
UseUdpExtension: true,
|
||||
Password: "password",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&hysteria2.ClientConfig{
|
||||
Server: []*protocol.ServerEndpoint{
|
||||
{
|
||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||
Port: uint32(serverPort),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&hysteria2.Account{}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to initialize all servers: ", err.Error())
|
||||
}
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 10; i++ {
|
||||
if isUDP {
|
||||
errg.Go(testUDPConn(clientPort, 1024, time.Second*4))
|
||||
} else {
|
||||
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*40))
|
||||
}
|
||||
}
|
||||
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHysteria2OnTCP(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err := tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
|
||||
serverPort := udp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(serverPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
Protocol: internet.TransportProtocol_TCP,
|
||||
Settings: serial.ToTypedMessage(&tcpTransport.Config{
|
||||
HeaderSettings: serial.ToTypedMessage(&http.Config{}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&hysteria2.ServerConfig{
|
||||
Users: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&hysteria2.Account{}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
clientConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(clientPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
NetworkList: &net.NetworkList{
|
||||
Network: []net.Network{net.Network_TCP},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
Protocol: internet.TransportProtocol_TCP,
|
||||
Settings: serial.ToTypedMessage(&tcpTransport.Config{
|
||||
HeaderSettings: serial.ToTypedMessage(&http.Config{}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&hysteria2.ClientConfig{
|
||||
Server: []*protocol.ServerEndpoint{
|
||||
{
|
||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||
Port: uint32(serverPort),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&hysteria2.Account{}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to initialize all servers: ", err.Error())
|
||||
}
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 1; i++ {
|
||||
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*40))
|
||||
}
|
||||
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ import (
|
||||
"google.golang.org/grpc/backoff"
|
||||
"google.golang.org/grpc/connectivity"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
@ -48,11 +49,12 @@ func dialgRPC(ctx context.Context, dest net.Destination, streamSettings *interne
|
||||
grpcSettings := streamSettings.ProtocolSettings.(*Config)
|
||||
|
||||
config := tls.ConfigFromStreamSettings(streamSettings)
|
||||
dialOption := grpc.WithInsecure()
|
||||
|
||||
transportCredentials := insecure.NewCredentials()
|
||||
if config != nil {
|
||||
dialOption = grpc.WithTransportCredentials(credentials.NewTLS(config.GetTLSConfig()))
|
||||
transportCredentials = credentials.NewTLS(config.GetTLSConfig())
|
||||
}
|
||||
dialOption := grpc.WithTransportCredentials(transportCredentials)
|
||||
|
||||
conn, canceller, err := getGrpcClient(ctx, dest, dialOption, streamSettings)
|
||||
if err != nil {
|
||||
|
298
transport/internet/hysteria2/config.pb.go
Normal file
298
transport/internet/hysteria2/config.pb.go
Normal file
@ -0,0 +1,298 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
protocol "github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
_ "github.com/v2fly/v2ray-core/v5/common/protoext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Congestion struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
|
||||
UpMbps uint64 `protobuf:"varint,2,opt,name=up_mbps,json=upMbps,proto3" json:"up_mbps,omitempty"`
|
||||
DownMbps uint64 `protobuf:"varint,3,opt,name=down_mbps,json=downMbps,proto3" json:"down_mbps,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Congestion) Reset() {
|
||||
*x = Congestion{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_transport_internet_hysteria2_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Congestion) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Congestion) ProtoMessage() {}
|
||||
|
||||
func (x *Congestion) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_hysteria2_config_proto_msgTypes[0]
|
||||
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 Congestion.ProtoReflect.Descriptor instead.
|
||||
func (*Congestion) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_hysteria2_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Congestion) GetType() string {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Congestion) GetUpMbps() uint64 {
|
||||
if x != nil {
|
||||
return x.UpMbps
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Congestion) GetDownMbps() uint64 {
|
||||
if x != nil {
|
||||
return x.DownMbps
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Security *protocol.SecurityConfig `protobuf:"bytes,2,opt,name=security,proto3" json:"security,omitempty"`
|
||||
Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
|
||||
Congestion *Congestion `protobuf:"bytes,4,opt,name=congestion,proto3" json:"congestion,omitempty"`
|
||||
IgnoreClientBandwidth bool `protobuf:"varint,5,opt,name=ignore_client_bandwidth,json=ignoreClientBandwidth,proto3" json:"ignore_client_bandwidth,omitempty"`
|
||||
UseUdpExtension bool `protobuf:"varint,6,opt,name=use_udp_extension,json=useUdpExtension,proto3" json:"use_udp_extension,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
*x = Config{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_transport_internet_hysteria2_config_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Config) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Config) ProtoMessage() {}
|
||||
|
||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_hysteria2_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 Config.ProtoReflect.Descriptor instead.
|
||||
func (*Config) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_hysteria2_config_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Config) GetKey() string {
|
||||
if x != nil {
|
||||
return x.Key
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetSecurity() *protocol.SecurityConfig {
|
||||
if x != nil {
|
||||
return x.Security
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetPassword() string {
|
||||
if x != nil {
|
||||
return x.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetCongestion() *Congestion {
|
||||
if x != nil {
|
||||
return x.Congestion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetIgnoreClientBandwidth() bool {
|
||||
if x != nil {
|
||||
return x.IgnoreClientBandwidth
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *Config) GetUseUdpExtension() bool {
|
||||
if x != nil {
|
||||
return x.UseUdpExtension
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_transport_internet_hysteria2_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_transport_internet_hysteria2_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x29, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x2f, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x27, 0x76, 0x32, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x79, 0x73, 0x74, 0x65,
|
||||
0x72, 0x69, 0x61, 0x32, 0x1a, 0x1d, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x70, 0x5f, 0x6d, 0x62,
|
||||
0x70, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x75, 0x70, 0x4d, 0x62, 0x70, 0x73,
|
||||
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x6d, 0x62, 0x70, 0x73, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x62, 0x70, 0x73, 0x22, 0xd3, 0x02,
|
||||
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x46, 0x0a, 0x08, 0x73, 0x65,
|
||||
0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 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, 0x63, 0x75, 0x72, 0x69,
|
||||
0x74, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69,
|
||||
0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x53,
|
||||
0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x33, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e,
|
||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x65, 0x74, 0x2e, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x2e, 0x43, 0x6f, 0x6e,
|
||||
0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x6c,
|
||||
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x05,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x43, 0x6c, 0x69, 0x65,
|
||||
0x6e, 0x74, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64, 0x74, 0x68, 0x12, 0x2a, 0x0a, 0x11, 0x75,
|
||||
0x73, 0x65, 0x5f, 0x75, 0x64, 0x70, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e,
|
||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x75, 0x73, 0x65, 0x55, 0x64, 0x70, 0x45, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x1a, 0x82, 0xb5, 0x18, 0x16, 0x0a, 0x09, 0x74,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x09, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72,
|
||||
0x69, 0x61, 0x32, 0x42, 0x96, 0x01, 0x0a, 0x2b, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72,
|
||||
0x69, 0x61, 0x32, 0x50, 0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f,
|
||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69,
|
||||
0x61, 0x32, 0xaa, 0x02, 0x27, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e,
|
||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x65, 0x74, 0x2e, 0x48, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_transport_internet_hysteria2_config_proto_rawDescOnce sync.Once
|
||||
file_transport_internet_hysteria2_config_proto_rawDescData = file_transport_internet_hysteria2_config_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_transport_internet_hysteria2_config_proto_rawDescGZIP() []byte {
|
||||
file_transport_internet_hysteria2_config_proto_rawDescOnce.Do(func() {
|
||||
file_transport_internet_hysteria2_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_hysteria2_config_proto_rawDescData)
|
||||
})
|
||||
return file_transport_internet_hysteria2_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_transport_internet_hysteria2_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_transport_internet_hysteria2_config_proto_goTypes = []interface{}{
|
||||
(*Congestion)(nil), // 0: v2ray.core.transport.internet.hysteria2.Congestion
|
||||
(*Config)(nil), // 1: v2ray.core.transport.internet.hysteria2.Config
|
||||
(*protocol.SecurityConfig)(nil), // 2: v2ray.core.common.protocol.SecurityConfig
|
||||
}
|
||||
var file_transport_internet_hysteria2_config_proto_depIdxs = []int32{
|
||||
2, // 0: v2ray.core.transport.internet.hysteria2.Config.security:type_name -> v2ray.core.common.protocol.SecurityConfig
|
||||
0, // 1: v2ray.core.transport.internet.hysteria2.Config.congestion:type_name -> v2ray.core.transport.internet.hysteria2.Congestion
|
||||
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_transport_internet_hysteria2_config_proto_init() }
|
||||
func file_transport_internet_hysteria2_config_proto_init() {
|
||||
if File_transport_internet_hysteria2_config_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_transport_internet_hysteria2_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Congestion); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_transport_internet_hysteria2_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Config); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_transport_internet_hysteria2_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_transport_internet_hysteria2_config_proto_goTypes,
|
||||
DependencyIndexes: file_transport_internet_hysteria2_config_proto_depIdxs,
|
||||
MessageInfos: file_transport_internet_hysteria2_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_transport_internet_hysteria2_config_proto = out.File
|
||||
file_transport_internet_hysteria2_config_proto_rawDesc = nil
|
||||
file_transport_internet_hysteria2_config_proto_goTypes = nil
|
||||
file_transport_internet_hysteria2_config_proto_depIdxs = nil
|
||||
}
|
30
transport/internet/hysteria2/config.proto
Normal file
30
transport/internet/hysteria2/config.proto
Normal file
@ -0,0 +1,30 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.transport.internet.hysteria2;
|
||||
option csharp_namespace = "V2Ray.Core.Transport.Internet.Hysteria2";
|
||||
option go_package = "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2";
|
||||
option java_package = "com.v2ray.core.transport.internet.hysteria2";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "common/protocol/headers.proto";
|
||||
|
||||
import "common/protoext/extensions.proto";
|
||||
|
||||
message Congestion{
|
||||
string type = 1;
|
||||
|
||||
uint64 up_mbps = 2;
|
||||
uint64 down_mbps = 3;
|
||||
}
|
||||
|
||||
message Config {
|
||||
option (v2ray.core.common.protoext.message_opt).type = "transport";
|
||||
option (v2ray.core.common.protoext.message_opt).short_name = "hysteria2";
|
||||
|
||||
string key = 1;
|
||||
v2ray.core.common.protocol.SecurityConfig security = 2;
|
||||
string password = 3;
|
||||
Congestion congestion = 4;
|
||||
bool ignore_client_bandwidth = 5;
|
||||
bool use_udp_extension = 6;
|
||||
}
|
136
transport/internet/hysteria2/conn.go
Normal file
136
transport/internet/hysteria2/conn.go
Normal file
@ -0,0 +1,136 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
hyClient "github.com/apernet/hysteria/core/v2/client"
|
||||
"github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
hyServer "github.com/apernet/hysteria/core/v2/server"
|
||||
"github.com/apernet/quic-go"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
)
|
||||
|
||||
const CanNotUseUdpExtension = "Only hysteria2 proxy protocol can use udpExtension."
|
||||
const Hy2MustNeedTLS = "Hysteria2 based on QUIC that requires TLS."
|
||||
|
||||
type HyConn struct {
|
||||
IsUDPExtension bool
|
||||
IsServer bool
|
||||
ClientUDPSession hyClient.HyUDPConn
|
||||
ServerUDPSession *hyServer.UdpSessionEntry
|
||||
Target net.Destination
|
||||
|
||||
stream quic.Stream
|
||||
local net.Addr
|
||||
remote net.Addr
|
||||
}
|
||||
|
||||
func (c *HyConn) Read(b []byte) (int, error) {
|
||||
if c.IsUDPExtension {
|
||||
n, data, _, err := c.ReadPacket()
|
||||
copy(b, data)
|
||||
return n, err
|
||||
}
|
||||
return c.stream.Read(b)
|
||||
}
|
||||
|
||||
func (c *HyConn) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
mb = buf.Compact(mb)
|
||||
mb, err := buf.WriteMultiBuffer(c, mb)
|
||||
buf.ReleaseMulti(mb)
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *HyConn) Write(b []byte) (int, error) {
|
||||
if c.IsUDPExtension {
|
||||
dest, _ := net.ParseDestination("udp:v2fly.org:6666")
|
||||
return c.WritePacket(b, dest)
|
||||
}
|
||||
return c.stream.Write(b)
|
||||
}
|
||||
|
||||
func (c *HyConn) WritePacket(b []byte, dest net.Destination) (int, error) {
|
||||
if !c.IsUDPExtension {
|
||||
return 0, newError(CanNotUseUdpExtension)
|
||||
}
|
||||
|
||||
if c.IsServer {
|
||||
msg := &protocol.UDPMessage{
|
||||
SessionID: c.ServerUDPSession.ID,
|
||||
PacketID: 0,
|
||||
FragID: 0,
|
||||
FragCount: 1,
|
||||
Addr: dest.NetAddr(),
|
||||
Data: b,
|
||||
}
|
||||
c.ServerUDPSession.SendCh <- msg
|
||||
return len(b), nil
|
||||
}
|
||||
return len(b), c.ClientUDPSession.Send(b, dest.NetAddr())
|
||||
}
|
||||
|
||||
func (c *HyConn) ReadPacket() (int, []byte, *net.Destination, error) {
|
||||
if !c.IsUDPExtension {
|
||||
return 0, nil, nil, newError(CanNotUseUdpExtension)
|
||||
}
|
||||
|
||||
if c.IsServer {
|
||||
msg := <-c.ServerUDPSession.ReceiveCh
|
||||
dest, err := net.ParseDestination("udp:" + msg.Addr)
|
||||
return len(msg.Data), msg.Data, &dest, err
|
||||
}
|
||||
data, address, err := c.ClientUDPSession.Receive()
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
dest, err := net.ParseDestination("udp:" + address)
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
return len(data), data, &dest, nil
|
||||
}
|
||||
|
||||
func (c *HyConn) Close() error {
|
||||
if c.IsUDPExtension {
|
||||
if !c.IsServer && c.ClientUDPSession == nil || (c.IsServer && c.ServerUDPSession == nil) {
|
||||
return newError(CanNotUseUdpExtension)
|
||||
}
|
||||
if c.IsServer {
|
||||
c.ServerUDPSession.Close()
|
||||
return c.ServerUDPSession.Conn.Close()
|
||||
}
|
||||
return c.ClientUDPSession.Close()
|
||||
}
|
||||
return c.stream.Close()
|
||||
}
|
||||
|
||||
func (c *HyConn) LocalAddr() net.Addr {
|
||||
return c.local
|
||||
}
|
||||
|
||||
func (c *HyConn) RemoteAddr() net.Addr {
|
||||
return c.remote
|
||||
}
|
||||
|
||||
func (c *HyConn) SetDeadline(t time.Time) error {
|
||||
if c.IsUDPExtension {
|
||||
return nil
|
||||
}
|
||||
return c.stream.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (c *HyConn) SetReadDeadline(t time.Time) error {
|
||||
if c.IsUDPExtension {
|
||||
return nil
|
||||
}
|
||||
return c.stream.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (c *HyConn) SetWriteDeadline(t time.Time) error {
|
||||
if c.IsUDPExtension {
|
||||
return nil
|
||||
}
|
||||
return c.stream.SetWriteDeadline(t)
|
||||
}
|
199
transport/internet/hysteria2/dialer.go
Normal file
199
transport/internet/hysteria2/dialer.go
Normal file
@ -0,0 +1,199 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
hyClient "github.com/apernet/hysteria/core/v2/client"
|
||||
hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
"github.com/apernet/quic-go/quicvarint"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
|
||||
)
|
||||
|
||||
var RunningClient map[net.Addr](hyClient.Client)
|
||||
var ClientMutex sync.Mutex
|
||||
var MBps uint64 = 1000000 / 8 // MByte
|
||||
|
||||
func GetClientTLSConfig(streamSettings *internet.MemoryStreamConfig) (*hyClient.TLSConfig, error) {
|
||||
config := tls.ConfigFromStreamSettings(streamSettings)
|
||||
if config == nil {
|
||||
return nil, newError(Hy2MustNeedTLS)
|
||||
}
|
||||
tlsConfig := config.GetTLSConfig()
|
||||
|
||||
return &hyClient.TLSConfig{
|
||||
RootCAs: tlsConfig.RootCAs,
|
||||
ServerName: tlsConfig.ServerName,
|
||||
InsecureSkipVerify: tlsConfig.InsecureSkipVerify,
|
||||
VerifyPeerCertificate: tlsConfig.VerifyPeerCertificate,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ResolveAddress(dest net.Destination) (net.Addr, error) {
|
||||
var destAddr *net.UDPAddr
|
||||
if dest.Address.Family().IsIP() {
|
||||
destAddr = &net.UDPAddr{
|
||||
IP: dest.Address.IP(),
|
||||
Port: int(dest.Port),
|
||||
}
|
||||
} else {
|
||||
addr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
destAddr = addr
|
||||
}
|
||||
return destAddr, nil
|
||||
}
|
||||
|
||||
type connFactory struct {
|
||||
hyClient.ConnFactory
|
||||
|
||||
NewFunc func(addr net.Addr) (net.PacketConn, error)
|
||||
}
|
||||
|
||||
func (f *connFactory) New(addr net.Addr) (net.PacketConn, error) {
|
||||
return f.NewFunc(addr)
|
||||
}
|
||||
|
||||
func NewHyClient(serverAddr net.Addr, streamSettings *internet.MemoryStreamConfig) (hyClient.Client, error) {
|
||||
tlsConfig, err := GetClientTLSConfig(streamSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := streamSettings.ProtocolSettings.(*Config)
|
||||
client, _, err := hyClient.NewClient(&hyClient.Config{
|
||||
Auth: config.GetPassword(),
|
||||
TLSConfig: *tlsConfig,
|
||||
ServerAddr: serverAddr,
|
||||
ConnFactory: &connFactory{
|
||||
NewFunc: func(addr net.Addr) (net.PacketConn, error) {
|
||||
rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
Port: 0,
|
||||
}, streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rawConn.(*net.UDPConn), nil
|
||||
},
|
||||
},
|
||||
BandwidthConfig: hyClient.BandwidthConfig{MaxTx: config.Congestion.GetUpMbps() * MBps, MaxRx: config.GetCongestion().GetDownMbps() * MBps},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func CloseHyClient(serverAddr net.Addr) error {
|
||||
ClientMutex.Lock()
|
||||
defer ClientMutex.Unlock()
|
||||
|
||||
client, found := RunningClient[serverAddr]
|
||||
if found {
|
||||
delete(RunningClient, serverAddr)
|
||||
return client.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetHyClient(serverAddr net.Addr, streamSettings *internet.MemoryStreamConfig) (hyClient.Client, error) {
|
||||
var err error
|
||||
var client hyClient.Client
|
||||
|
||||
ClientMutex.Lock()
|
||||
client, found := RunningClient[serverAddr]
|
||||
ClientMutex.Unlock()
|
||||
if !found || !CheckHyClientHealthy(client) {
|
||||
if found {
|
||||
// retry
|
||||
CloseHyClient(serverAddr)
|
||||
}
|
||||
client, err = NewHyClient(serverAddr, streamSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ClientMutex.Lock()
|
||||
RunningClient[serverAddr] = client
|
||||
ClientMutex.Unlock()
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func CheckHyClientHealthy(client hyClient.Client) bool {
|
||||
quicConn := client.GetQuicConn()
|
||||
if quicConn == nil {
|
||||
return false
|
||||
}
|
||||
select {
|
||||
case <-quicConn.Context().Done():
|
||||
return false
|
||||
default:
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
|
||||
config := streamSettings.ProtocolSettings.(*Config)
|
||||
|
||||
serverAddr, err := ResolveAddress(dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := GetHyClient(serverAddr, streamSettings)
|
||||
if err != nil {
|
||||
CloseHyClient(serverAddr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
quicConn := client.GetQuicConn()
|
||||
conn := &HyConn{
|
||||
local: quicConn.LocalAddr(),
|
||||
remote: quicConn.RemoteAddr(),
|
||||
}
|
||||
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
network := net.Network_TCP
|
||||
if outbound != nil {
|
||||
network = outbound.Target.Network
|
||||
conn.Target = outbound.Target
|
||||
}
|
||||
|
||||
if network == net.Network_UDP && config.GetUseUdpExtension() { // only hysteria2 can use udpExtension
|
||||
conn.IsUDPExtension = true
|
||||
conn.IsServer = false
|
||||
conn.ClientUDPSession, err = client.UDP()
|
||||
if err != nil {
|
||||
CloseHyClient(serverAddr)
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
conn.stream, err = client.OpenStream()
|
||||
if err != nil {
|
||||
CloseHyClient(serverAddr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// write TCP frame type
|
||||
frameSize := int(quicvarint.Len(hyProtocol.FrameTypeTCPRequest))
|
||||
buf := make([]byte, frameSize)
|
||||
hyProtocol.VarintPut(buf, hyProtocol.FrameTypeTCPRequest)
|
||||
conn.stream.Write(buf)
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
RunningClient = make(map[net.Addr]hyClient.Client)
|
||||
common.Must(internet.RegisterTransportDialer(protocolName, Dial))
|
||||
}
|
9
transport/internet/hysteria2/errors.generated.go
Normal file
9
transport/internet/hysteria2/errors.generated.go
Normal file
@ -0,0 +1,9 @@
|
||||
package hysteria2
|
||||
|
||||
import "github.com/v2fly/v2ray-core/v5/common/errors"
|
||||
|
||||
type errPathObjHolder struct{}
|
||||
|
||||
func newError(values ...interface{}) *errors.Error {
|
||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||
}
|
128
transport/internet/hysteria2/hub.go
Normal file
128
transport/internet/hysteria2/hub.go
Normal file
@ -0,0 +1,128 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
hyServer "github.com/apernet/hysteria/core/v2/server"
|
||||
"github.com/apernet/quic-go"
|
||||
"github.com/apernet/quic-go/http3"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
|
||||
)
|
||||
|
||||
// Listener is an internet.Listener that listens for TCP connections.
|
||||
type Listener struct {
|
||||
hyServer hyServer.Server
|
||||
rawConn net.PacketConn
|
||||
addConn internet.ConnHandler
|
||||
}
|
||||
|
||||
// Addr implements internet.Listener.Addr.
|
||||
func (l *Listener) Addr() net.Addr {
|
||||
return l.rawConn.LocalAddr()
|
||||
}
|
||||
|
||||
// Close implements internet.Listener.Close.
|
||||
func (l *Listener) Close() error {
|
||||
return l.hyServer.Close()
|
||||
}
|
||||
|
||||
func (l *Listener) StreamHijacker(ft http3.FrameType, conn quic.Connection, stream quic.Stream, err error) (bool, error) {
|
||||
// err always == nil
|
||||
|
||||
tcpConn := &HyConn{
|
||||
stream: stream,
|
||||
local: conn.LocalAddr(),
|
||||
remote: conn.RemoteAddr(),
|
||||
}
|
||||
l.addConn(tcpConn)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (l *Listener) UdpHijacker(entry *hyServer.UdpSessionEntry, originalAddr string) {
|
||||
addr, err := net.ResolveUDPAddr("udp", originalAddr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
udpConn := &HyConn{
|
||||
IsUDPExtension: true,
|
||||
IsServer: true,
|
||||
ServerUDPSession: entry,
|
||||
remote: addr,
|
||||
local: l.rawConn.LocalAddr(),
|
||||
}
|
||||
l.addConn(udpConn)
|
||||
}
|
||||
|
||||
// Listen creates a new Listener based on configurations.
|
||||
func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
||||
tlsConfig, err := GetServerTLSConfig(streamSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if address.Family().IsDomain() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config := streamSettings.ProtocolSettings.(*Config)
|
||||
rawConn, err := internet.ListenSystemPacket(context.Background(),
|
||||
&net.UDPAddr{
|
||||
IP: address.IP(),
|
||||
Port: int(port),
|
||||
}, streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener := &Listener{
|
||||
rawConn: rawConn,
|
||||
addConn: handler,
|
||||
}
|
||||
|
||||
hyServer, err := hyServer.NewServer(&hyServer.Config{
|
||||
Conn: rawConn,
|
||||
TLSConfig: *tlsConfig,
|
||||
DisableUDP: !config.GetUseUdpExtension(),
|
||||
Authenticator: &Authenticator{Password: config.GetPassword()},
|
||||
StreamHijacker: listener.StreamHijacker, // acceptStreams
|
||||
BandwidthConfig: hyServer.BandwidthConfig{MaxTx: config.Congestion.GetUpMbps() * MBps, MaxRx: config.GetCongestion().GetDownMbps() * MBps},
|
||||
UdpSessionHijacker: listener.UdpHijacker, // acceptUDPSession
|
||||
IgnoreClientBandwidth: config.GetIgnoreClientBandwidth(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener.hyServer = hyServer
|
||||
go hyServer.Serve()
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
func GetServerTLSConfig(streamSettings *internet.MemoryStreamConfig) (*hyServer.TLSConfig, error) {
|
||||
config := tls.ConfigFromStreamSettings(streamSettings)
|
||||
if config == nil {
|
||||
return nil, newError(Hy2MustNeedTLS)
|
||||
}
|
||||
tlsConfig := config.GetTLSConfig()
|
||||
|
||||
return &hyServer.TLSConfig{Certificates: tlsConfig.Certificates, GetCertificate: tlsConfig.GetCertificate}, nil
|
||||
}
|
||||
|
||||
type Authenticator struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
func (a *Authenticator) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) {
|
||||
if auth == a.Password || a.Password == "" {
|
||||
return true, "user"
|
||||
}
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterTransportListener(protocolName, Listen))
|
||||
}
|
155
transport/internet/hysteria2/hy2_transport_test.go
Normal file
155
transport/internet/hysteria2/hy2_transport_test.go
Normal file
@ -0,0 +1,155 @@
|
||||
package hysteria2_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol/tls/cert"
|
||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
||||
"github.com/v2fly/v2ray-core/v5/testing/servers/udp"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
|
||||
)
|
||||
|
||||
func TestTCP(t *testing.T) {
|
||||
port := udp.PickPort()
|
||||
|
||||
listener, err := hysteria2.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
ProtocolSettings: &hysteria2.Config{Password: "123"},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
Certificate: []*tls.Certificate{
|
||||
tls.ParseCertificate(
|
||||
cert.MustGenerate(nil,
|
||||
cert.DNSNames("www.v2fly.org"),
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
}, func(conn internet.Connection) {
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
|
||||
b := buf.New()
|
||||
defer b.Release()
|
||||
|
||||
for {
|
||||
b.Clear()
|
||||
if _, err := b.ReadFrom(conn); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
common.Must2(conn.Write(b.Bytes()))
|
||||
}
|
||||
}()
|
||||
})
|
||||
common.Must(err)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
dctx := context.Background()
|
||||
conn, err := hysteria2.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
ProtocolSettings: &hysteria2.Config{Password: "123"},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
})
|
||||
common.Must(err)
|
||||
defer conn.Close()
|
||||
|
||||
const N = 1000
|
||||
b1 := make([]byte, N)
|
||||
common.Must2(rand.Read(b1))
|
||||
b2 := buf.New()
|
||||
|
||||
common.Must2(conn.Write(b1))
|
||||
|
||||
b2.Clear()
|
||||
common.Must2(b2.ReadFullFrom(conn, N))
|
||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
||||
t.Error(r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDP(t *testing.T) {
|
||||
port := udp.PickPort()
|
||||
|
||||
listener, err := hysteria2.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
ProtocolSettings: &hysteria2.Config{Password: "123", UseUdpExtension: true},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
Certificate: []*tls.Certificate{
|
||||
tls.ParseCertificate(
|
||||
cert.MustGenerate(nil,
|
||||
cert.DNSNames("www.v2fly.org"),
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
}, func(conn internet.Connection) {
|
||||
fmt.Println("incoming")
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
|
||||
b := buf.New()
|
||||
defer b.Release()
|
||||
|
||||
for {
|
||||
b.Clear()
|
||||
if _, err := b.ReadFrom(conn); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
common.Must2(conn.Write(b.Bytes()))
|
||||
}
|
||||
}()
|
||||
})
|
||||
common.Must(err)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
address, err := net.ParseDestination("udp:127.0.0.1:1180")
|
||||
dctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: address})
|
||||
|
||||
conn, err := hysteria2.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
ProtocolSettings: &hysteria2.Config{Password: "123", UseUdpExtension: true},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
})
|
||||
common.Must(err)
|
||||
defer conn.Close()
|
||||
|
||||
const N = 1000
|
||||
b1 := make([]byte, N)
|
||||
common.Must2(rand.Read(b1))
|
||||
common.Must2(conn.Write(b1))
|
||||
|
||||
b2 := buf.New()
|
||||
b2.Clear()
|
||||
common.Must2(b2.ReadFullFrom(conn, N))
|
||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
||||
t.Error(r)
|
||||
}
|
||||
}
|
18
transport/internet/hysteria2/hysteria2.go
Normal file
18
transport/internet/hysteria2/hysteria2.go
Normal file
@ -0,0 +1,18 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
|
||||
|
||||
const (
|
||||
protocolName = "hysteria2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
|
||||
return new(Config)
|
||||
}))
|
||||
}
|
Loading…
Reference in New Issue
Block a user