From b4d93c4438866628444c106f36a5d3f6139da8ef Mon Sep 17 00:00:00 2001 From: yaling888 <73897884+yaling888@users.noreply.github.com> Date: Tue, 6 Jul 2021 23:55:34 +0800 Subject: [PATCH] Feature: add xtls support for VLESS --- README.md | 62 +++++++++ adapter/outbound/vless.go | 127 ++++++++++------- go.mod | 1 + go.sum | 2 + rule/geodata/router/config.pb.go | 229 ++++++++++++++++--------------- transport/gun/gun_xtls.go | 56 ++++++++ transport/vless/config.pb.go | 158 +++++++++++++++++++++ transport/vless/config.proto | 12 ++ transport/vless/conn.go | 68 +++++---- transport/vless/vless.go | 20 ++- transport/vless/xtls.go | 25 ++++ 11 files changed, 567 insertions(+), 193 deletions(-) create mode 100644 transport/gun/gun_xtls.go create mode 100644 transport/vless/config.pb.go create mode 100644 transport/vless/config.proto create mode 100644 transport/vless/xtls.go diff --git a/README.md b/README.md index d6f4849f..ed43f2c7 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,7 @@ rules: - GEOSITE,category-ads-all,REJECT - GEOSITE,icloud@cn,DIRECT - GEOSITE,apple@cn,DIRECT + - GEOSITE,apple-cn,DIRECT - GEOSITE,microsoft@cn,DIRECT - GEOSITE,facebook,PROXY - GEOSITE,youtube,PROXY @@ -81,6 +82,67 @@ rules: - MATCH,PROXY ``` + +### Proxies configuration +Support outbound transport protocol `VLESS` +```yaml +proxies: + - name: "vless" + type: vless + server: server + port: 443 + uuid: uuid + # udp: true + # skip-cert-verify: true + # servername: example.com # priority over wss host + # network: ws # not support xtls + # ws-path: /path + # ws-headers: + # Host: v2ray.com + + - name: "vless-h2" + type: vless + server: server + port: 443 + uuid: uuid + network: h2 + # flow: xtls-rprx-direct # xtls-rprx-origin xtls-rprx-direct # enable xtls + h2-opts: + host: + - http.example.com + - http-alt.example.com + path: / + + - name: "vless-http" + type: vless + server: server + port: 443 + uuid: uuid + # udp: true + # network: http + # flow: xtls-rprx-direct # xtls-rprx-origin xtls-rprx-direct # enable xtls + # http-opts: + # # method: "GET" + # # path: + # # - '/' + # # - '/video' + # # headers: + # # Connection: + # # - keep-alive + + - name: vless-grpc + server: server + port: 443 + type: vless + uuid: uuid + network: grpc + # flow: xtls-rprx-direct # xtls-rprx-origin xtls-rprx-direct # enable xtls + servername: example.com + # skip-cert-verify: true + grpc-opts: + grpc-service-name: "example" +``` + ### IPTABLES auto-configuration Only work on Linux OS who support `iptables`, Clash will auto-configuration iptables for tproxy listener when `tproxy-port` value isn't zero. diff --git a/adapter/outbound/vless.go b/adapter/outbound/vless.go index 5c2308c8..9e44740c 100644 --- a/adapter/outbound/vless.go +++ b/adapter/outbound/vless.go @@ -34,6 +34,8 @@ type VlessOption struct { Server string `proxy:"server"` Port int `proxy:"port"` UUID string `proxy:"uuid"` + Flow string `proxy:"flow,omitempty"` + FlowShow bool `proxy:"flow_show,omitempty"` TLS bool `proxy:"tls,omitempty"` UDP bool `proxy:"udp,omitempty"` Network string `proxy:"network,omitempty"` @@ -73,21 +75,9 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { c, err = vmess.StreamWebsocketConn(c, wsOpts) case "http": // readability first, so just copy default TLS logic - if v.option.TLS { - host, _, _ := net.SplitHostPort(v.addr) - tlsOpts := &vmess.TLSConfig{ - Host: host, - SkipCertVerify: v.option.SkipCertVerify, - } - - if v.option.ServerName != "" { - tlsOpts.Host = v.option.ServerName - } - - c, err = vmess.StreamTLSConn(c, tlsOpts) - if err != nil { - return nil, err - } + c, err = v.streamTLSOrXTLSConn(c, false) + if err != nil { + return nil, err } host, _, _ := net.SplitHostPort(v.addr) @@ -100,18 +90,7 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { c = vmess.StreamHTTPConn(c, httpOpts) case "h2": - host, _, _ := net.SplitHostPort(v.addr) - tlsOpts := vmess.TLSConfig{ - Host: host, - SkipCertVerify: v.option.SkipCertVerify, - NextProtos: []string{"h2"}, - } - - if v.option.ServerName != "" { - tlsOpts.Host = v.option.ServerName - } - - c, err = vmess.StreamTLSConn(c, &tlsOpts) + c, err = v.streamTLSOrXTLSConn(c, true) if err != nil { return nil, err } @@ -123,23 +102,14 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { c, err = vmess.StreamH2Conn(c, h2Opts) case "grpc": - c, err = gun.StreamGunWithConn(c, v.gunTLSConfig, v.gunConfig) - default: - // handle TLS - if v.option.TLS { - host, _, _ := net.SplitHostPort(v.addr) - tlsOpts := &vmess.TLSConfig{ - Host: host, - SkipCertVerify: v.option.SkipCertVerify, - NextProtos: []string{"h2"}, - } - - if v.option.ServerName != "" { - tlsOpts.Host = v.option.ServerName - } - - c, err = vmess.StreamTLSConn(c, tlsOpts) + if v.isXTLSEnabled() { + c, err = gun.StreamGunWithXTLSConn(c, v.gunTLSConfig, v.gunConfig) + } else { + c, err = gun.StreamGunWithConn(c, v.gunTLSConfig, v.gunConfig) } + default: + // handle TLS And XTLS + c, err = v.streamTLSOrXTLSConn(c, true) } if err != nil { @@ -149,6 +119,49 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { return v.client.StreamConn(c, parseVlessAddr(metadata)) } +func (v *Vless) streamTLSOrXTLSConn(conn net.Conn, isH2 bool) (net.Conn, error) { + host, _, _ := net.SplitHostPort(v.addr) + + if v.isXTLSEnabled() { + xtlsOpts := vless.XTLSConfig{ + Host: host, + SkipCertVerify: v.option.SkipCertVerify, + } + + if isH2 { + xtlsOpts.NextProtos = []string{"h2"} + } + + if v.option.ServerName != "" { + xtlsOpts.Host = v.option.ServerName + } + + return vless.StreamXTLSConn(conn, &xtlsOpts) + + } else if v.option.TLS { + tlsOpts := vmess.TLSConfig{ + Host: host, + SkipCertVerify: v.option.SkipCertVerify, + } + + if isH2 { + tlsOpts.NextProtos = []string{"h2"} + } + + if v.option.ServerName != "" { + tlsOpts.Host = v.option.ServerName + } + + return vmess.StreamTLSConn(conn, &tlsOpts) + } + + return conn, nil +} + +func (v *Vless) isXTLSEnabled() bool { + return v.client.Addons != nil +} + // DialContext implements C.ProxyAdapter func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata) (_ C.Conn, err error) { // gun transport @@ -262,14 +275,24 @@ func (uc *vlessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) { } func NewVless(option VlessOption) (*Vless, error) { - client, err := vless.NewClient(option.UUID) - if err != nil { - return nil, err + var addons *vless.Addons + if option.Network != "ws" && len(option.Flow) >= 16 { + option.Flow = option.Flow[:16] + switch option.Flow { + case vless.XRO, vless.XRD, vless.XRS: + addons = &vless.Addons{ + Flow: option.Flow, + } + default: + return nil, fmt.Errorf("unsupported vless flow type: %s", option.Flow) + } } - if option.Network != "ws" { - option.TLS = true - option.SkipCertVerify = false + option.TLS = true + + client, err := vless.NewClient(option.UUID, addons, option.FlowShow) + if err != nil { + return nil, err } v := &Vless{ @@ -315,7 +338,11 @@ func NewVless(option VlessOption) (*Vless, error) { v.gunTLSConfig = tlsConfig v.gunConfig = gunConfig - v.transport = gun.NewHTTP2Client(dialFn, tlsConfig) + if v.isXTLSEnabled() { + v.transport = gun.NewHTTP2XTLSClient(dialFn, tlsConfig) + } else { + v.transport = gun.NewHTTP2Client(dialFn, tlsConfig) + } } return v, nil diff --git a/go.mod b/go.mod index 83470250..c12533ba 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/miekg/dns v1.1.43 github.com/sirupsen/logrus v1.8.1 github.com/stretchr/testify v1.7.0 + github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 go.uber.org/atomic v1.8.0 golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e golang.org/x/net v0.0.0-20210614182718-04defd469f4e diff --git a/go.sum b/go.sum index a3a76366..29e5acf7 100644 --- a/go.sum +++ b/go.sum @@ -286,6 +286,8 @@ github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1 github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499 h1:QHESTXtfgc1ABV+ArlbPVqUx9Ht5I0dDkYhxYoXFxNo= +github.com/xtls/go v0.0.0-20201118062508-3632bf3b7499/go.mod h1:5TB2+k58gx4A4g2Nf5miSHNDF6CuAzHKpWBooLAshTs= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= diff --git a/rule/geodata/router/config.pb.go b/rule/geodata/router/config.pb.go index 3f97c80b..96762c12 100644 --- a/rule/geodata/router/config.pb.go +++ b/rule/geodata/router/config.pb.go @@ -1,8 +1,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.15.8 -// source: config.proto +// protoc-gen-go v1.27.1 +// protoc v3.17.3 +// source: rule/geodata/router/config.proto package router @@ -61,11 +61,11 @@ func (x Domain_Type) String() string { } func (Domain_Type) Descriptor() protoreflect.EnumDescriptor { - return file_config_proto_enumTypes[0].Descriptor() + return file_rule_geodata_router_config_proto_enumTypes[0].Descriptor() } func (Domain_Type) Type() protoreflect.EnumType { - return &file_config_proto_enumTypes[0] + return &file_rule_geodata_router_config_proto_enumTypes[0] } func (x Domain_Type) Number() protoreflect.EnumNumber { @@ -74,7 +74,7 @@ func (x Domain_Type) Number() protoreflect.EnumNumber { // Deprecated: Use Domain_Type.Descriptor instead. func (Domain_Type) EnumDescriptor() ([]byte, []int) { - return file_config_proto_rawDescGZIP(), []int{0, 0} + return file_rule_geodata_router_config_proto_rawDescGZIP(), []int{0, 0} } // Domain for routing decision. @@ -94,7 +94,7 @@ type Domain struct { func (x *Domain) Reset() { *x = Domain{} if protoimpl.UnsafeEnabled { - mi := &file_config_proto_msgTypes[0] + mi := &file_rule_geodata_router_config_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -107,7 +107,7 @@ func (x *Domain) String() string { func (*Domain) ProtoMessage() {} func (x *Domain) ProtoReflect() protoreflect.Message { - mi := &file_config_proto_msgTypes[0] + mi := &file_rule_geodata_router_config_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -120,7 +120,7 @@ func (x *Domain) ProtoReflect() protoreflect.Message { // Deprecated: Use Domain.ProtoReflect.Descriptor instead. func (*Domain) Descriptor() ([]byte, []int) { - return file_config_proto_rawDescGZIP(), []int{0} + return file_rule_geodata_router_config_proto_rawDescGZIP(), []int{0} } func (x *Domain) GetType() Domain_Type { @@ -159,7 +159,7 @@ type CIDR struct { func (x *CIDR) Reset() { *x = CIDR{} if protoimpl.UnsafeEnabled { - mi := &file_config_proto_msgTypes[1] + mi := &file_rule_geodata_router_config_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -172,7 +172,7 @@ func (x *CIDR) String() string { func (*CIDR) ProtoMessage() {} func (x *CIDR) ProtoReflect() protoreflect.Message { - mi := &file_config_proto_msgTypes[1] + mi := &file_rule_geodata_router_config_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -185,7 +185,7 @@ func (x *CIDR) ProtoReflect() protoreflect.Message { // Deprecated: Use CIDR.ProtoReflect.Descriptor instead. func (*CIDR) Descriptor() ([]byte, []int) { - return file_config_proto_rawDescGZIP(), []int{1} + return file_rule_geodata_router_config_proto_rawDescGZIP(), []int{1} } func (x *CIDR) GetIp() []byte { @@ -215,7 +215,7 @@ type GeoIP struct { func (x *GeoIP) Reset() { *x = GeoIP{} if protoimpl.UnsafeEnabled { - mi := &file_config_proto_msgTypes[2] + mi := &file_rule_geodata_router_config_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -228,7 +228,7 @@ func (x *GeoIP) String() string { func (*GeoIP) ProtoMessage() {} func (x *GeoIP) ProtoReflect() protoreflect.Message { - mi := &file_config_proto_msgTypes[2] + mi := &file_rule_geodata_router_config_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -241,7 +241,7 @@ func (x *GeoIP) ProtoReflect() protoreflect.Message { // Deprecated: Use GeoIP.ProtoReflect.Descriptor instead. func (*GeoIP) Descriptor() ([]byte, []int) { - return file_config_proto_rawDescGZIP(), []int{2} + return file_rule_geodata_router_config_proto_rawDescGZIP(), []int{2} } func (x *GeoIP) GetCountryCode() string { @@ -276,7 +276,7 @@ type GeoIPList struct { func (x *GeoIPList) Reset() { *x = GeoIPList{} if protoimpl.UnsafeEnabled { - mi := &file_config_proto_msgTypes[3] + mi := &file_rule_geodata_router_config_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -289,7 +289,7 @@ func (x *GeoIPList) String() string { func (*GeoIPList) ProtoMessage() {} func (x *GeoIPList) ProtoReflect() protoreflect.Message { - mi := &file_config_proto_msgTypes[3] + mi := &file_rule_geodata_router_config_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -302,7 +302,7 @@ func (x *GeoIPList) ProtoReflect() protoreflect.Message { // Deprecated: Use GeoIPList.ProtoReflect.Descriptor instead. func (*GeoIPList) Descriptor() ([]byte, []int) { - return file_config_proto_rawDescGZIP(), []int{3} + return file_rule_geodata_router_config_proto_rawDescGZIP(), []int{3} } func (x *GeoIPList) GetEntry() []*GeoIP { @@ -324,7 +324,7 @@ type GeoSite struct { func (x *GeoSite) Reset() { *x = GeoSite{} if protoimpl.UnsafeEnabled { - mi := &file_config_proto_msgTypes[4] + mi := &file_rule_geodata_router_config_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -337,7 +337,7 @@ func (x *GeoSite) String() string { func (*GeoSite) ProtoMessage() {} func (x *GeoSite) ProtoReflect() protoreflect.Message { - mi := &file_config_proto_msgTypes[4] + mi := &file_rule_geodata_router_config_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -350,7 +350,7 @@ func (x *GeoSite) ProtoReflect() protoreflect.Message { // Deprecated: Use GeoSite.ProtoReflect.Descriptor instead. func (*GeoSite) Descriptor() ([]byte, []int) { - return file_config_proto_rawDescGZIP(), []int{4} + return file_rule_geodata_router_config_proto_rawDescGZIP(), []int{4} } func (x *GeoSite) GetCountryCode() string { @@ -378,7 +378,7 @@ type GeoSiteList struct { func (x *GeoSiteList) Reset() { *x = GeoSiteList{} if protoimpl.UnsafeEnabled { - mi := &file_config_proto_msgTypes[5] + mi := &file_rule_geodata_router_config_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -391,7 +391,7 @@ func (x *GeoSiteList) String() string { func (*GeoSiteList) ProtoMessage() {} func (x *GeoSiteList) ProtoReflect() protoreflect.Message { - mi := &file_config_proto_msgTypes[5] + mi := &file_rule_geodata_router_config_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -404,7 +404,7 @@ func (x *GeoSiteList) ProtoReflect() protoreflect.Message { // Deprecated: Use GeoSiteList.ProtoReflect.Descriptor instead. func (*GeoSiteList) Descriptor() ([]byte, []int) { - return file_config_proto_rawDescGZIP(), []int{5} + return file_rule_geodata_router_config_proto_rawDescGZIP(), []int{5} } func (x *GeoSiteList) GetEntry() []*GeoSite { @@ -429,7 +429,7 @@ type Domain_Attribute struct { func (x *Domain_Attribute) Reset() { *x = Domain_Attribute{} if protoimpl.UnsafeEnabled { - mi := &file_config_proto_msgTypes[6] + mi := &file_rule_geodata_router_config_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -442,7 +442,7 @@ func (x *Domain_Attribute) String() string { func (*Domain_Attribute) ProtoMessage() {} func (x *Domain_Attribute) ProtoReflect() protoreflect.Message { - mi := &file_config_proto_msgTypes[6] + mi := &file_rule_geodata_router_config_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -455,7 +455,7 @@ func (x *Domain_Attribute) ProtoReflect() protoreflect.Message { // Deprecated: Use Domain_Attribute.ProtoReflect.Descriptor instead. func (*Domain_Attribute) Descriptor() ([]byte, []int) { - return file_config_proto_rawDescGZIP(), []int{0, 0} + return file_rule_geodata_router_config_proto_rawDescGZIP(), []int{0, 0} } func (x *Domain_Attribute) GetKey() string { @@ -502,84 +502,85 @@ func (*Domain_Attribute_BoolValue) isDomain_Attribute_TypedValue() {} func (*Domain_Attribute_IntValue) isDomain_Attribute_TypedValue() {} -var File_config_proto protoreflect.FileDescriptor +var File_rule_geodata_router_config_proto protoreflect.FileDescriptor -var file_config_proto_rawDesc = []byte{ - 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, - 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, - 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x22, 0xc7, 0x02, 0x0a, 0x06, 0x44, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, - 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x49, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6c, 0x61, 0x73, - 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, - 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x41, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x1a, 0x6c, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x42, 0x0d, 0x0a, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0x32, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x6c, 0x61, 0x69, 0x6e, - 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x01, 0x12, 0x0a, 0x0a, - 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, - 0x6c, 0x10, 0x03, 0x22, 0x2e, 0x0a, 0x04, 0x43, 0x49, 0x44, 0x52, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x70, - 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, - 0x66, 0x69, 0x78, 0x22, 0x84, 0x01, 0x0a, 0x05, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, - 0x12, 0x33, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, - 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, - 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52, 0x52, - 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, - 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x72, 0x65, - 0x76, 0x65, 0x72, 0x73, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x43, 0x0a, 0x09, 0x47, 0x65, - 0x6f, 0x49, 0x50, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, +var file_rule_geodata_router_config_proto_rawDesc = []byte{ + 0x0a, 0x20, 0x72, 0x75, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x72, + 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x12, 0x19, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, + 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x22, 0xc7, 0x02, + 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, - 0x67, 0x0a, 0x07, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x39, 0x0a, - 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, + 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x49, 0x0a, 0x09, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, - 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x47, 0x0a, 0x0b, 0x47, 0x65, 0x6f, 0x53, - 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, - 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, - 0x79, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, - 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, - 0x65, 0x72, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x2f, 0x63, 0x6c, 0x61, 0x73, 0x68, - 0x2f, 0x72, 0x75, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x72, 0x6f, - 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x19, 0x43, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x52, 0x75, 0x6c, - 0x65, 0x2e, 0x47, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x1a, 0x6c, 0x0a, 0x09, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x0a, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x6f, 0x6c, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x22, 0x32, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x50, + 0x6c, 0x61, 0x69, 0x6e, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, + 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x02, 0x12, 0x08, 0x0a, + 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x03, 0x22, 0x2e, 0x0a, 0x04, 0x43, 0x49, 0x44, 0x52, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, + 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x84, 0x01, 0x0a, 0x05, 0x47, 0x65, 0x6f, 0x49, + 0x50, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, + 0x43, 0x6f, 0x64, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, + 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, + 0x49, 0x44, 0x52, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, + 0x65, 0x72, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0c, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x43, + 0x0a, 0x09, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x05, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x6c, 0x61, + 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x22, 0x67, 0x0a, 0x07, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x12, 0x21, + 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, + 0x65, 0x12, 0x39, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, + 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, + 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x47, 0x0a, 0x0b, + 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x05, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6c, 0x61, + 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52, 0x05, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x63, 0x6c, 0x61, + 0x73, 0x68, 0x2e, 0x72, 0x75, 0x6c, 0x65, 0x2e, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, + 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x2f, 0x63, + 0x6c, 0x61, 0x73, 0x68, 0x2f, 0x72, 0x75, 0x6c, 0x65, 0x2f, 0x67, 0x65, 0x6f, 0x64, 0x61, 0x74, + 0x61, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x19, 0x43, 0x6c, 0x61, 0x73, 0x68, + 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x47, 0x65, 0x6f, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( - file_config_proto_rawDescOnce sync.Once - file_config_proto_rawDescData = file_config_proto_rawDesc + file_rule_geodata_router_config_proto_rawDescOnce sync.Once + file_rule_geodata_router_config_proto_rawDescData = file_rule_geodata_router_config_proto_rawDesc ) -func file_config_proto_rawDescGZIP() []byte { - file_config_proto_rawDescOnce.Do(func() { - file_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_config_proto_rawDescData) +func file_rule_geodata_router_config_proto_rawDescGZIP() []byte { + file_rule_geodata_router_config_proto_rawDescOnce.Do(func() { + file_rule_geodata_router_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_rule_geodata_router_config_proto_rawDescData) }) - return file_config_proto_rawDescData + return file_rule_geodata_router_config_proto_rawDescData } -var file_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_config_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_config_proto_goTypes = []interface{}{ +var file_rule_geodata_router_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_rule_geodata_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_rule_geodata_router_config_proto_goTypes = []interface{}{ (Domain_Type)(0), // 0: clash.rule.geodata.router.Domain.Type (*Domain)(nil), // 1: clash.rule.geodata.router.Domain (*CIDR)(nil), // 2: clash.rule.geodata.router.CIDR @@ -589,7 +590,7 @@ var file_config_proto_goTypes = []interface{}{ (*GeoSiteList)(nil), // 6: clash.rule.geodata.router.GeoSiteList (*Domain_Attribute)(nil), // 7: clash.rule.geodata.router.Domain.Attribute } -var file_config_proto_depIdxs = []int32{ +var file_rule_geodata_router_config_proto_depIdxs = []int32{ 0, // 0: clash.rule.geodata.router.Domain.type:type_name -> clash.rule.geodata.router.Domain.Type 7, // 1: clash.rule.geodata.router.Domain.attribute:type_name -> clash.rule.geodata.router.Domain.Attribute 2, // 2: clash.rule.geodata.router.GeoIP.cidr:type_name -> clash.rule.geodata.router.CIDR @@ -603,13 +604,13 @@ var file_config_proto_depIdxs = []int32{ 0, // [0:6] is the sub-list for field type_name } -func init() { file_config_proto_init() } -func file_config_proto_init() { - if File_config_proto != nil { +func init() { file_rule_geodata_router_config_proto_init() } +func file_rule_geodata_router_config_proto_init() { + if File_rule_geodata_router_config_proto != nil { return } if !protoimpl.UnsafeEnabled { - file_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_rule_geodata_router_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Domain); i { case 0: return &v.state @@ -621,7 +622,7 @@ func file_config_proto_init() { return nil } } - file_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_rule_geodata_router_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CIDR); i { case 0: return &v.state @@ -633,7 +634,7 @@ func file_config_proto_init() { return nil } } - file_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_rule_geodata_router_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeoIP); i { case 0: return &v.state @@ -645,7 +646,7 @@ func file_config_proto_init() { return nil } } - file_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_rule_geodata_router_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeoIPList); i { case 0: return &v.state @@ -657,7 +658,7 @@ func file_config_proto_init() { return nil } } - file_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_rule_geodata_router_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeoSite); i { case 0: return &v.state @@ -669,7 +670,7 @@ func file_config_proto_init() { return nil } } - file_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_rule_geodata_router_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeoSiteList); i { case 0: return &v.state @@ -681,7 +682,7 @@ func file_config_proto_init() { return nil } } - file_config_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_rule_geodata_router_config_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Domain_Attribute); i { case 0: return &v.state @@ -694,7 +695,7 @@ func file_config_proto_init() { } } } - file_config_proto_msgTypes[6].OneofWrappers = []interface{}{ + file_rule_geodata_router_config_proto_msgTypes[6].OneofWrappers = []interface{}{ (*Domain_Attribute_BoolValue)(nil), (*Domain_Attribute_IntValue)(nil), } @@ -702,19 +703,19 @@ func file_config_proto_init() { out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_config_proto_rawDesc, + RawDescriptor: file_rule_geodata_router_config_proto_rawDesc, NumEnums: 1, NumMessages: 7, NumExtensions: 0, NumServices: 0, }, - GoTypes: file_config_proto_goTypes, - DependencyIndexes: file_config_proto_depIdxs, - EnumInfos: file_config_proto_enumTypes, - MessageInfos: file_config_proto_msgTypes, + GoTypes: file_rule_geodata_router_config_proto_goTypes, + DependencyIndexes: file_rule_geodata_router_config_proto_depIdxs, + EnumInfos: file_rule_geodata_router_config_proto_enumTypes, + MessageInfos: file_rule_geodata_router_config_proto_msgTypes, }.Build() - File_config_proto = out.File - file_config_proto_rawDesc = nil - file_config_proto_goTypes = nil - file_config_proto_depIdxs = nil + File_rule_geodata_router_config_proto = out.File + file_rule_geodata_router_config_proto_rawDesc = nil + file_rule_geodata_router_config_proto_goTypes = nil + file_rule_geodata_router_config_proto_depIdxs = nil } diff --git a/transport/gun/gun_xtls.go b/transport/gun/gun_xtls.go new file mode 100644 index 00000000..d97dd7bf --- /dev/null +++ b/transport/gun/gun_xtls.go @@ -0,0 +1,56 @@ +// Modified from: https://github.com/Qv2ray/gun-lite +// License: MIT + +package gun + +import ( + "crypto/tls" + "fmt" + "net" + + xtls "github.com/xtls/go" + "golang.org/x/net/http2" +) + +func NewHTTP2XTLSClient(dialFn DialFn, tlsConfig *tls.Config) *http2.Transport { + dialFunc := func(network, addr string, cfg *tls.Config) (net.Conn, error) { + pconn, err := dialFn(network, addr) + if err != nil { + return nil, err + } + + xtlsConfig := &xtls.Config{ + InsecureSkipVerify: cfg.InsecureSkipVerify, + ServerName: cfg.ServerName, + } + + cn := xtls.Client(pconn, xtlsConfig) + if err := cn.Handshake(); err != nil { + pconn.Close() + return nil, err + } + state := cn.ConnectionState() + if p := state.NegotiatedProtocol; p != http2.NextProtoTLS { + cn.Close() + return nil, fmt.Errorf("http2: unexpected ALPN protocol %s, want %s", p, http2.NextProtoTLS) + } + return cn, nil + } + + return &http2.Transport{ + DialTLS: dialFunc, + TLSClientConfig: tlsConfig, + AllowHTTP: false, + DisableCompression: true, + PingTimeout: 0, + } +} + +func StreamGunWithXTLSConn(conn net.Conn, tlsConfig *tls.Config, cfg *Config) (net.Conn, error) { + dialFn := func(network, addr string) (net.Conn, error) { + return conn, nil + } + + transport := NewHTTP2XTLSClient(dialFn, tlsConfig) + return StreamGunWithTransport(transport, cfg) +} diff --git a/transport/vless/config.pb.go b/transport/vless/config.pb.go new file mode 100644 index 00000000..b622def3 --- /dev/null +++ b/transport/vless/config.pb.go @@ -0,0 +1,158 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.27.1 +// protoc v3.17.3 +// source: transport/vless/config.proto + +package vless + +import ( + 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 Addons struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Flow string `protobuf:"bytes,1,opt,name=Flow,proto3" json:"Flow,omitempty"` + Seed []byte `protobuf:"bytes,2,opt,name=Seed,proto3" json:"Seed,omitempty"` +} + +func (x *Addons) Reset() { + *x = Addons{} + if protoimpl.UnsafeEnabled { + mi := &file_transport_vless_config_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Addons) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Addons) ProtoMessage() {} + +func (x *Addons) ProtoReflect() protoreflect.Message { + mi := &file_transport_vless_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 Addons.ProtoReflect.Descriptor instead. +func (*Addons) Descriptor() ([]byte, []int) { + return file_transport_vless_config_proto_rawDescGZIP(), []int{0} +} + +func (x *Addons) GetFlow() string { + if x != nil { + return x.Flow + } + return "" +} + +func (x *Addons) GetSeed() []byte { + if x != nil { + return x.Seed + } + return nil +} + +var File_transport_vless_config_proto protoreflect.FileDescriptor + +var file_transport_vless_config_proto_rawDesc = []byte{ + 0x0a, 0x1c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x76, 0x6c, 0x65, 0x73, + 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, + 0x63, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x76, 0x6c, 0x65, 0x73, 0x73, 0x22, 0x30, 0x0a, 0x06, 0x41, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x12, + 0x12, 0x0a, 0x04, 0x46, 0x6c, 0x6f, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x46, + 0x6c, 0x6f, 0x77, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x65, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0c, 0x52, 0x04, 0x53, 0x65, 0x65, 0x64, 0x42, 0x61, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x63, + 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x76, + 0x6c, 0x65, 0x73, 0x73, 0x50, 0x01, 0x5a, 0x2a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x44, 0x72, 0x65, 0x61, 0x6d, 0x61, 0x63, 0x72, 0x6f, 0x2f, 0x63, 0x6c, 0x61, + 0x73, 0x68, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x76, 0x6c, 0x65, + 0x73, 0x73, 0xaa, 0x02, 0x15, 0x43, 0x6c, 0x61, 0x73, 0x68, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_transport_vless_config_proto_rawDescOnce sync.Once + file_transport_vless_config_proto_rawDescData = file_transport_vless_config_proto_rawDesc +) + +func file_transport_vless_config_proto_rawDescGZIP() []byte { + file_transport_vless_config_proto_rawDescOnce.Do(func() { + file_transport_vless_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_vless_config_proto_rawDescData) + }) + return file_transport_vless_config_proto_rawDescData +} + +var file_transport_vless_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_transport_vless_config_proto_goTypes = []interface{}{ + (*Addons)(nil), // 0: clash.transport.vless.Addons +} +var file_transport_vless_config_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_transport_vless_config_proto_init() } +func file_transport_vless_config_proto_init() { + if File_transport_vless_config_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_transport_vless_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Addons); 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_vless_config_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_transport_vless_config_proto_goTypes, + DependencyIndexes: file_transport_vless_config_proto_depIdxs, + MessageInfos: file_transport_vless_config_proto_msgTypes, + }.Build() + File_transport_vless_config_proto = out.File + file_transport_vless_config_proto_rawDesc = nil + file_transport_vless_config_proto_goTypes = nil + file_transport_vless_config_proto_depIdxs = nil +} diff --git a/transport/vless/config.proto b/transport/vless/config.proto new file mode 100644 index 00000000..80900230 --- /dev/null +++ b/transport/vless/config.proto @@ -0,0 +1,12 @@ +syntax = "proto3"; + +package clash.transport.vless; +option csharp_namespace = "Clash.Transport.Vless"; +option go_package = "github.com/Dreamacro/clash/transport/vless"; +option java_package = "com.clash.transport.vless"; +option java_multiple_files = true; + +message Addons { + string Flow = 1; + bytes Seed = 2; +} \ No newline at end of file diff --git a/transport/vless/conn.go b/transport/vless/conn.go index ba309c09..36e8918e 100644 --- a/transport/vless/conn.go +++ b/transport/vless/conn.go @@ -4,29 +4,21 @@ import ( "bytes" "encoding/binary" "errors" + "fmt" "io" "io/ioutil" "net" "github.com/gofrs/uuid" + xtls "github.com/xtls/go" + "google.golang.org/protobuf/proto" ) -/*var ( - - //proto.Marshal(addons) bytes for Flow: "xtls-rprx-direct" - addOnBytes, _ = hex.DecodeString("120a1078746c732d727072782d646972656374") - addOnBytesLen = len(addOnBytes) - - //proto.Marshal(addons) bytes for Flow: "" - //addOnEmptyBytes, _ = hex.DecodeString("00") - //addOnEmptyBytesLen = len(addOnEmptyBytes) -)*/ - type Conn struct { net.Conn - dst *DstAddr - id *uuid.UUID - + dst *DstAddr + id *uuid.UUID + addons *Addons received bool } @@ -48,16 +40,22 @@ func (vc *Conn) sendRequest() error { buf.WriteByte(Version) // protocol version buf.Write(vc.id.Bytes()) // 16 bytes of uuid - // command - if vc.dst.UDP { - buf.WriteByte(0) // addon data length. 0 means no addon data - //buf.WriteByte(byte(addOnEmptyBytesLen)) - //buf.Write(addOnEmptyBytes) - buf.WriteByte(CommandUDP) + if vc.addons != nil { + bytes, err := proto.Marshal(vc.addons) + if err != nil { + return err + } + + buf.WriteByte(byte(len(bytes))) + buf.Write(bytes) } else { buf.WriteByte(0) // addon data length. 0 means no addon data - //buf.WriteByte(byte(addOnBytesLen)) - //buf.Write(addOnBytes) + } + + // command + if vc.dst.UDP { + buf.WriteByte(CommandUDP) + } else { buf.WriteByte(CommandTCP) } @@ -96,12 +94,34 @@ func (vc *Conn) recvResponse() error { } // newConn return a Conn instance -func newConn(conn net.Conn, id *uuid.UUID, dst *DstAddr) (*Conn, error) { +func newConn(conn net.Conn, client *Client, dst *DstAddr) (*Conn, error) { c := &Conn{ Conn: conn, - id: id, + id: client.uuid, dst: dst, } + + if !dst.UDP && client.Addons != nil { + switch client.Addons.Flow { + case XRO, XRD, XRS: + if xtlsConn, ok := conn.(*xtls.Conn); ok { + xtlsConn.RPRX = true + xtlsConn.SHOW = client.XTLSShow + xtlsConn.MARK = "XTLS" + if client.Addons.Flow == XRS { + client.Addons.Flow = XRD + } + + if client.Addons.Flow == XRD { + xtlsConn.DirectMode = true + } + c.addons = client.Addons + } else { + return nil, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", client.Addons.Flow) + } + } + } + if err := c.sendRequest(); err != nil { return nil, err } diff --git a/transport/vless/vless.go b/transport/vless/vless.go index 30309d71..458f54de 100644 --- a/transport/vless/vless.go +++ b/transport/vless/vless.go @@ -6,7 +6,13 @@ import ( "github.com/gofrs/uuid" ) -const Version byte = 0 // protocol version. preview version is 0 +const ( + XRO = "xtls-rprx-origin" + XRD = "xtls-rprx-direct" + XRS = "xtls-rprx-splice" + + Version byte = 0 // protocol version. preview version is 0 +) // Command types const ( @@ -40,22 +46,26 @@ type Config struct { // Client is vless connection generator type Client struct { - uuid *uuid.UUID + uuid *uuid.UUID + Addons *Addons + XTLSShow bool } // StreamConn return a Conn with net.Conn and DstAddr func (c *Client) StreamConn(conn net.Conn, dst *DstAddr) (net.Conn, error) { - return newConn(conn, c.uuid, dst) + return newConn(conn, c, dst) } // NewClient return Client instance -func NewClient(uuidStr string) (*Client, error) { +func NewClient(uuidStr string, addons *Addons, xtlsShow bool) (*Client, error) { uid, err := uuid.FromString(uuidStr) if err != nil { return nil, err } return &Client{ - uuid: &uid, + uuid: &uid, + Addons: addons, + XTLSShow: xtlsShow, }, nil } diff --git a/transport/vless/xtls.go b/transport/vless/xtls.go new file mode 100644 index 00000000..69035aa0 --- /dev/null +++ b/transport/vless/xtls.go @@ -0,0 +1,25 @@ +package vless + +import ( + "net" + + xtls "github.com/xtls/go" +) + +type XTLSConfig struct { + Host string + SkipCertVerify bool + NextProtos []string +} + +func StreamXTLSConn(conn net.Conn, cfg *XTLSConfig) (net.Conn, error) { + xtlsConfig := &xtls.Config{ + ServerName: cfg.Host, + InsecureSkipVerify: cfg.SkipCertVerify, + NextProtos: cfg.NextProtos, + } + + xtlsConn := xtls.Client(conn, xtlsConfig) + err := xtlsConn.Handshake() + return xtlsConn, err +}