mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-23 10:06:48 +08:00
Compare commits
47 Commits
refactor/d
...
v1.4.5
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a149c78a4c | ||
![]() |
b0886027f5 | ||
![]() |
7033f7cf5f | ||
![]() |
ffc2f7c4e2 | ||
![]() |
ab927d2cca | ||
![]() |
0c0d878456 | ||
![]() |
24b637cd5e | ||
![]() |
f2cb13a8ec | ||
![]() |
dbcbb519e3 | ||
![]() |
8a5bf06925 | ||
![]() |
b0b2aaa70c | ||
![]() |
d111a046c0 | ||
![]() |
eaf30aa14a | ||
![]() |
42d158bd85 | ||
![]() |
00bcd40c34 | ||
![]() |
1adfc2720a | ||
![]() |
0f79126379 | ||
![]() |
7246001029 | ||
![]() |
5e6eff5ffa | ||
![]() |
1dca3cb3dd | ||
![]() |
28d17ac17f | ||
![]() |
e6019a89c9 | ||
![]() |
3213e5dd81 | ||
![]() |
c950edede2 | ||
![]() |
64892fb2c3 | ||
![]() |
0403e6ddc3 | ||
![]() |
d9d239750b | ||
![]() |
73e10f0f6f | ||
![]() |
7a9e72b133 | ||
![]() |
66b58e6076 | ||
![]() |
17cdeac57f | ||
![]() |
e4bf620795 | ||
![]() |
31c7141fef | ||
![]() |
57b9006d26 | ||
![]() |
d9d04a230f | ||
![]() |
3dc9fba20d | ||
![]() |
d45298a10d | ||
![]() |
6e8581f5dc | ||
![]() |
86a8fb5d84 | ||
![]() |
3531b95d82 | ||
![]() |
b977899926 | ||
![]() |
2220411644 | ||
![]() |
3b8618b379 | ||
![]() |
e8a8465220 | ||
![]() |
1f92b948c0 | ||
![]() |
53b99efe78 | ||
![]() |
1e3d739a5b |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -121,7 +121,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: ^1.16
|
go-version: ^1.17.1
|
||||||
|
|
||||||
- name: Get project dependencies
|
- name: Get project dependencies
|
||||||
run: go mod download
|
run: go mod download
|
||||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
|||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v2
|
||||||
with:
|
with:
|
||||||
go-version: ^1.16
|
go-version: ^1.17.1
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
@@ -40,13 +40,16 @@
|
|||||||
- [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
|
- [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
|
||||||
- Windows
|
- Windows
|
||||||
- [v2rayN](https://github.com/2dust/v2rayN)
|
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
- [Qv2ray](https://github.com/Qv2ray/Qv2ray)
|
- [Qv2ray](https://github.com/Qv2ray/Qv2ray) (This project had been archived and currently inactive)
|
||||||
- [Netch (NetFilter & TUN/TAP)](https://github.com/NetchX/Netch)
|
- [Netch (NetFilter & TUN/TAP)](https://github.com/NetchX/Netch)
|
||||||
- Android
|
- Android
|
||||||
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
||||||
|
- [AnXray](https://github.com/XTLS/AnXray)
|
||||||
- [Kitsunebi](https://github.com/rurirei/Kitsunebi/tree/release_xtls)
|
- [Kitsunebi](https://github.com/rurirei/Kitsunebi/tree/release_xtls)
|
||||||
- iOS / Mac
|
- iOS & macOS (with M1 chip)
|
||||||
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
||||||
|
- macOS (Intel chip & M1 chip)
|
||||||
|
- [Qv2ray](https://github.com/Qv2ray/Qv2ray) (This project had been archived and currently inactive)
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/commander/config.proto
|
// source: app/commander/config.proto
|
||||||
|
|
||||||
package commander
|
package commander
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
serial "github.com/xtls/xray-core/common/serial"
|
serial "github.com/xtls/xray-core/common/serial"
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
@@ -22,10 +21,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
// Config is the settings for Commander.
|
// Config is the settings for Commander.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
|
@@ -3,9 +3,10 @@ package commander
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/reflection"
|
"google.golang.org/grpc/reflection"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Service is a Commander service.
|
// Service is a Commander service.
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/dispatcher/config.proto
|
// source: app/dispatcher/config.proto
|
||||||
|
|
||||||
package dispatcher
|
package dispatcher
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type SessionConfig struct {
|
type SessionConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@@ -178,8 +178,8 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
|
|||||||
|
|
||||||
func shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
|
func shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
|
||||||
domain := result.Domain()
|
domain := result.Domain()
|
||||||
if request.ExcludedDomainMatcher != nil {
|
for _, d := range request.ExcludeForDomain {
|
||||||
if request.ExcludedDomainMatcher.ApplyDomain(domain) {
|
if strings.ToLower(domain) == d {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,16 +205,6 @@ func shouldOverride(ctx context.Context, result SniffResult, request session.Sni
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func canSniff(ctx context.Context, req session.SniffingRequest, destination net.Destination) bool {
|
|
||||||
if destination.Address.Family().IsIP() && req.ExcludedIPMatcher != nil {
|
|
||||||
if req.ExcludedIPMatcher.MatchIP(destination.Address.IP()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispatch implements routing.Dispatcher.
|
// Dispatch implements routing.Dispatcher.
|
||||||
func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (*transport.Link, error) {
|
func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destination) (*transport.Link, error) {
|
||||||
if !destination.IsValid() {
|
if !destination.IsValid() {
|
||||||
@@ -232,12 +222,6 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
|||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
}
|
}
|
||||||
sniffingRequest := content.SniffingRequest
|
sniffingRequest := content.SniffingRequest
|
||||||
|
|
||||||
if !canSniff(ctx, sniffingRequest, destination) {
|
|
||||||
newError("skip sniffing for ip ", destination.Address.String()).AtDebug().WriteToLog()
|
|
||||||
sniffingRequest.Enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case !sniffingRequest.Enabled:
|
case !sniffingRequest.Enabled:
|
||||||
go d.routedDispatch(ctx, outbound, destination)
|
go d.routedDispatch(ctx, outbound, destination)
|
||||||
@@ -325,10 +309,15 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool) (Sni
|
|||||||
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
|
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
|
||||||
var handler outbound.Handler
|
var handler outbound.Handler
|
||||||
|
|
||||||
|
skipRoutePick := false
|
||||||
|
if content := session.ContentFromContext(ctx); content != nil {
|
||||||
|
skipRoutePick = content.SkipRoutePick
|
||||||
|
}
|
||||||
|
|
||||||
routingLink := routing_session.AsRoutingContext(ctx)
|
routingLink := routing_session.AsRoutingContext(ctx)
|
||||||
inTag := routingLink.GetInboundTag()
|
inTag := routingLink.GetInboundTag()
|
||||||
isPickRoute := false
|
isPickRoute := false
|
||||||
if d.router != nil {
|
if d.router != nil && !skipRoutePick {
|
||||||
if route, err := d.router.PickRoute(routingLink); err == nil {
|
if route, err := d.router.PickRoute(routingLink); err == nil {
|
||||||
outTag := route.GetOutboundTag()
|
outTag := route.GetOutboundTag()
|
||||||
isPickRoute = true
|
isPickRoute = true
|
||||||
|
@@ -1,64 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
dm "github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/str"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
var typeMap = map[dm.MatchingType]str.Type{
|
|
||||||
dm.MatchingType_Keyword: str.Substr,
|
|
||||||
dm.MatchingType_Regex: str.Regex,
|
|
||||||
dm.MatchingType_Subdomain: str.Domain,
|
|
||||||
dm.MatchingType_Full: str.Full,
|
|
||||||
}
|
|
||||||
|
|
||||||
// References:
|
|
||||||
// https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml
|
|
||||||
// https://unix.stackexchange.com/questions/92441/whats-the-difference-between-local-home-and-lan
|
|
||||||
var localTLDsAndDotlessDomains = []*dm.Domain{
|
|
||||||
{Type: dm.MatchingType_Regex, Value: "^[^.]+$"}, // This will only match domains without any dot
|
|
||||||
{Type: dm.MatchingType_Subdomain, Value: "local"},
|
|
||||||
{Type: dm.MatchingType_Subdomain, Value: "localdomain"},
|
|
||||||
{Type: dm.MatchingType_Subdomain, Value: "localhost"},
|
|
||||||
{Type: dm.MatchingType_Subdomain, Value: "lan"},
|
|
||||||
{Type: dm.MatchingType_Subdomain, Value: "home.arpa"},
|
|
||||||
{Type: dm.MatchingType_Subdomain, Value: "example"},
|
|
||||||
{Type: dm.MatchingType_Subdomain, Value: "invalid"},
|
|
||||||
{Type: dm.MatchingType_Subdomain, Value: "test"},
|
|
||||||
}
|
|
||||||
|
|
||||||
var localTLDsAndDotlessDomainsRule = &NameServer_OriginalRule{
|
|
||||||
Rule: "geosite:private",
|
|
||||||
Size: uint32(len(localTLDsAndDotlessDomains)),
|
|
||||||
}
|
|
||||||
|
|
||||||
func toStrMatcher(t dm.MatchingType, domain string) (str.Matcher, error) {
|
|
||||||
strMType, f := typeMap[t]
|
|
||||||
if !f {
|
|
||||||
return nil, newError("unknown mapping type", t).AtWarning()
|
|
||||||
}
|
|
||||||
matcher, err := strMType.New(domain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to create str matcher").Base(err)
|
|
||||||
}
|
|
||||||
return matcher, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func toNetIP(addrs []net.Address) ([]net.IP, error) {
|
|
||||||
ips := make([]net.IP, 0, len(addrs))
|
|
||||||
for _, addr := range addrs {
|
|
||||||
if addr.Family().IsIP() {
|
|
||||||
ips = append(ips, addr.IP())
|
|
||||||
} else {
|
|
||||||
return nil, newError("Failed to convert address", addr, "to Net IP.").AtWarning()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ips, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateRandomTag() string {
|
|
||||||
id := uuid.New()
|
|
||||||
return "xray.system." + id.String()
|
|
||||||
}
|
|
@@ -1,14 +1,13 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.15.8
|
// protoc v3.18.0
|
||||||
// source: app/dns/config.proto
|
// source: app/dns/config.proto
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
domain "github.com/xtls/xray-core/common/matcher/domain"
|
router "github.com/xtls/xray-core/app/router"
|
||||||
geoip "github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
net "github.com/xtls/xray-core/common/net"
|
net "github.com/xtls/xray-core/common/net"
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
@@ -23,115 +22,67 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
type QueryStrategy int32
|
type DomainMatchingType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
QueryStrategy_USE_IP QueryStrategy = 0
|
DomainMatchingType_Full DomainMatchingType = 0
|
||||||
QueryStrategy_USE_IP4 QueryStrategy = 1
|
DomainMatchingType_Subdomain DomainMatchingType = 1
|
||||||
QueryStrategy_USE_IP6 QueryStrategy = 2
|
DomainMatchingType_Keyword DomainMatchingType = 2
|
||||||
|
DomainMatchingType_Regex DomainMatchingType = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for QueryStrategy.
|
// Enum value maps for DomainMatchingType.
|
||||||
var (
|
var (
|
||||||
QueryStrategy_name = map[int32]string{
|
DomainMatchingType_name = map[int32]string{
|
||||||
0: "USE_IP",
|
0: "Full",
|
||||||
1: "USE_IP4",
|
1: "Subdomain",
|
||||||
2: "USE_IP6",
|
2: "Keyword",
|
||||||
|
3: "Regex",
|
||||||
}
|
}
|
||||||
QueryStrategy_value = map[string]int32{
|
DomainMatchingType_value = map[string]int32{
|
||||||
"USE_IP": 0,
|
"Full": 0,
|
||||||
"USE_IP4": 1,
|
"Subdomain": 1,
|
||||||
"USE_IP6": 2,
|
"Keyword": 2,
|
||||||
|
"Regex": 3,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (x QueryStrategy) Enum() *QueryStrategy {
|
func (x DomainMatchingType) Enum() *DomainMatchingType {
|
||||||
p := new(QueryStrategy)
|
p := new(DomainMatchingType)
|
||||||
*p = x
|
*p = x
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x QueryStrategy) String() string {
|
func (x DomainMatchingType) String() string {
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (QueryStrategy) Descriptor() protoreflect.EnumDescriptor {
|
func (DomainMatchingType) Descriptor() protoreflect.EnumDescriptor {
|
||||||
return file_app_dns_config_proto_enumTypes[0].Descriptor()
|
return file_app_dns_config_proto_enumTypes[0].Descriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (QueryStrategy) Type() protoreflect.EnumType {
|
func (DomainMatchingType) Type() protoreflect.EnumType {
|
||||||
return &file_app_dns_config_proto_enumTypes[0]
|
return &file_app_dns_config_proto_enumTypes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x QueryStrategy) Number() protoreflect.EnumNumber {
|
func (x DomainMatchingType) Number() protoreflect.EnumNumber {
|
||||||
return protoreflect.EnumNumber(x)
|
return protoreflect.EnumNumber(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use QueryStrategy.Descriptor instead.
|
// Deprecated: Use DomainMatchingType.Descriptor instead.
|
||||||
func (QueryStrategy) EnumDescriptor() ([]byte, []int) {
|
func (DomainMatchingType) EnumDescriptor() ([]byte, []int) {
|
||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{0}
|
return file_app_dns_config_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
type CacheStrategy int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
CacheStrategy_Cache_ALL CacheStrategy = 0
|
|
||||||
CacheStrategy_Cache_NOERROR CacheStrategy = 1
|
|
||||||
CacheStrategy_Cache_DISABLE CacheStrategy = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for CacheStrategy.
|
|
||||||
var (
|
|
||||||
CacheStrategy_name = map[int32]string{
|
|
||||||
0: "Cache_ALL",
|
|
||||||
1: "Cache_NOERROR",
|
|
||||||
2: "Cache_DISABLE",
|
|
||||||
}
|
|
||||||
CacheStrategy_value = map[string]int32{
|
|
||||||
"Cache_ALL": 0,
|
|
||||||
"Cache_NOERROR": 1,
|
|
||||||
"Cache_DISABLE": 2,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x CacheStrategy) Enum() *CacheStrategy {
|
|
||||||
p := new(CacheStrategy)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x CacheStrategy) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (CacheStrategy) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_app_dns_config_proto_enumTypes[1].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (CacheStrategy) Type() protoreflect.EnumType {
|
|
||||||
return &file_app_dns_config_proto_enumTypes[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x CacheStrategy) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use CacheStrategy.Descriptor instead.
|
|
||||||
func (CacheStrategy) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
type NameServer struct {
|
type NameServer struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||||
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
|
PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
|
||||||
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
|
Geoip []*router.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
|
||||||
PrioritizedDomain []*domain.Domain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
|
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
|
||||||
Geoip []*geoip.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
|
|
||||||
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) Reset() {
|
func (x *NameServer) Reset() {
|
||||||
@@ -173,28 +124,14 @@ func (x *NameServer) GetAddress() *net.Endpoint {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetClientIp() []byte {
|
func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
|
||||||
if x != nil {
|
|
||||||
return x.ClientIp
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetSkipFallback() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.SkipFallback
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetPrioritizedDomain() []*domain.Domain {
|
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.PrioritizedDomain
|
return x.PrioritizedDomain
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetGeoip() []*geoip.GeoIP {
|
func (x *NameServer) GetGeoip() []*router.GeoIP {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Geoip
|
return x.Geoip
|
||||||
}
|
}
|
||||||
@@ -232,10 +169,6 @@ type Config struct {
|
|||||||
StaticHosts []*Config_HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"`
|
StaticHosts []*Config_HostMapping `protobuf:"bytes,4,rep,name=static_hosts,json=staticHosts,proto3" json:"static_hosts,omitempty"`
|
||||||
// Tag is the inbound tag of DNS client.
|
// Tag is the inbound tag of DNS client.
|
||||||
Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"`
|
Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
// DisableCache disables DNS cache
|
|
||||||
CacheStrategy CacheStrategy `protobuf:"varint,8,opt,name=cache_strategy,json=cacheStrategy,proto3,enum=xray.app.dns.CacheStrategy" json:"cache_strategy,omitempty"`
|
|
||||||
QueryStrategy QueryStrategy `protobuf:"varint,9,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
|
||||||
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -314,25 +247,59 @@ func (x *Config) GetTag() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetCacheStrategy() CacheStrategy {
|
type NameServer_PriorityDomain struct {
|
||||||
if x != nil {
|
state protoimpl.MessageState
|
||||||
return x.CacheStrategy
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
unknownFields protoimpl.UnknownFields
|
||||||
return CacheStrategy_Cache_ALL
|
|
||||||
|
Type DomainMatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
|
||||||
|
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetQueryStrategy() QueryStrategy {
|
func (x *NameServer_PriorityDomain) Reset() {
|
||||||
if x != nil {
|
*x = NameServer_PriorityDomain{}
|
||||||
return x.QueryStrategy
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_dns_config_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
return QueryStrategy_USE_IP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetDisableFallback() bool {
|
func (x *NameServer_PriorityDomain) String() string {
|
||||||
if x != nil {
|
return protoimpl.X.MessageStringOf(x)
|
||||||
return x.DisableFallback
|
}
|
||||||
|
|
||||||
|
func (*NameServer_PriorityDomain) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *NameServer_PriorityDomain) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_dns_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 false
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use NameServer_PriorityDomain.ProtoReflect.Descriptor instead.
|
||||||
|
func (*NameServer_PriorityDomain) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_dns_config_proto_rawDescGZIP(), []int{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NameServer_PriorityDomain) GetType() DomainMatchingType {
|
||||||
|
if x != nil {
|
||||||
|
return x.Type
|
||||||
|
}
|
||||||
|
return DomainMatchingType_Full
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NameServer_PriorityDomain) GetDomain() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Domain
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type NameServer_OriginalRule struct {
|
type NameServer_OriginalRule struct {
|
||||||
@@ -347,7 +314,7 @@ type NameServer_OriginalRule struct {
|
|||||||
func (x *NameServer_OriginalRule) Reset() {
|
func (x *NameServer_OriginalRule) Reset() {
|
||||||
*x = NameServer_OriginalRule{}
|
*x = NameServer_OriginalRule{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_app_dns_config_proto_msgTypes[2]
|
mi := &file_app_dns_config_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -360,7 +327,7 @@ func (x *NameServer_OriginalRule) String() string {
|
|||||||
func (*NameServer_OriginalRule) ProtoMessage() {}
|
func (*NameServer_OriginalRule) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
|
func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_dns_config_proto_msgTypes[2]
|
mi := &file_app_dns_config_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -373,7 +340,7 @@ func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use NameServer_OriginalRule.ProtoReflect.Descriptor instead.
|
// Deprecated: Use NameServer_OriginalRule.ProtoReflect.Descriptor instead.
|
||||||
func (*NameServer_OriginalRule) Descriptor() ([]byte, []int) {
|
func (*NameServer_OriginalRule) Descriptor() ([]byte, []int) {
|
||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{0, 0}
|
return file_app_dns_config_proto_rawDescGZIP(), []int{0, 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer_OriginalRule) GetRule() string {
|
func (x *NameServer_OriginalRule) GetRule() string {
|
||||||
@@ -395,18 +362,19 @@ type Config_HostMapping struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Type domain.MatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.common.matcher.domain.MatchingType" json:"type,omitempty"`
|
Type DomainMatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
|
||||||
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
||||||
Ip [][]byte `protobuf:"bytes,3,rep,name=ip,proto3" json:"ip,omitempty"`
|
Ip [][]byte `protobuf:"bytes,3,rep,name=ip,proto3" json:"ip,omitempty"`
|
||||||
// ProxiedDomain indicates the mapped domain has the same IP address on this
|
// ProxiedDomain indicates the mapped domain has the same IP address on this
|
||||||
// domain. Xray will use this domain for IP queries.
|
// domain. Xray will use this domain for IP queries. This field is only
|
||||||
|
// effective if ip is empty.
|
||||||
ProxiedDomain string `protobuf:"bytes,4,opt,name=proxied_domain,json=proxiedDomain,proto3" json:"proxied_domain,omitempty"`
|
ProxiedDomain string `protobuf:"bytes,4,opt,name=proxied_domain,json=proxiedDomain,proto3" json:"proxied_domain,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config_HostMapping) Reset() {
|
func (x *Config_HostMapping) Reset() {
|
||||||
*x = Config_HostMapping{}
|
*x = Config_HostMapping{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_app_dns_config_proto_msgTypes[4]
|
mi := &file_app_dns_config_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -419,7 +387,7 @@ func (x *Config_HostMapping) String() string {
|
|||||||
func (*Config_HostMapping) ProtoMessage() {}
|
func (*Config_HostMapping) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
|
func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_dns_config_proto_msgTypes[4]
|
mi := &file_app_dns_config_proto_msgTypes[5]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -435,11 +403,11 @@ func (*Config_HostMapping) Descriptor() ([]byte, []int) {
|
|||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{1, 1}
|
return file_app_dns_config_proto_rawDescGZIP(), []int{1, 1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config_HostMapping) GetType() domain.MatchingType {
|
func (x *Config_HostMapping) GetType() DomainMatchingType {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Type
|
return x.Type
|
||||||
}
|
}
|
||||||
return domain.MatchingType_Full
|
return DomainMatchingType_Full
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config_HostMapping) GetDomain() string {
|
func (x *Config_HostMapping) GetDomain() string {
|
||||||
@@ -471,96 +439,80 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
|||||||
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
||||||
0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c,
|
0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69,
|
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x64, 0x65, 0x73, 0x74, 0x69,
|
||||||
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x22, 0x63, 0x6f,
|
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70,
|
||||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x64, 0x6f, 0x6d,
|
0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||||
0x61, 0x69, 0x6e, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xad, 0x03, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65,
|
||||||
0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
|
0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18,
|
||||||
0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x70, 0x72, 0x6f,
|
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
0x74, 0x6f, 0x22, 0x93, 0x03, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
|
0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
|
0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x56, 0x0a, 0x12, 0x70, 0x72, 0x69,
|
||||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
|
||||||
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61,
|
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e,
|
||||||
0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11,
|
||||||
0x74, 0x49, 0x70, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62,
|
0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46,
|
0x6e, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x51, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72,
|
0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||||
0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20,
|
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12,
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65,
|
||||||
0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||||
0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74,
|
0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||||
0x69, 0x7a, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x36, 0x0a, 0x05, 0x67, 0x65,
|
0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d,
|
||||||
0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x1a, 0x5e, 0x0a,
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e,
|
0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12,
|
||||||
0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f,
|
0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e,
|
||||||
0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d,
|
||||||
0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61,
|
0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52,
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65,
|
|
||||||
0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c,
|
|
||||||
0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x73,
|
|
||||||
0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65,
|
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
|
||||||
0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01,
|
|
||||||
0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xdf, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
|
|
||||||
0x66, 0x69, 0x67, 0x12, 0x3f, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
|
|
||||||
0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f,
|
|
||||||
0x69, 0x6e, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
|
|
||||||
0x76, 0x65, 0x72, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72,
|
|
||||||
0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
|
|
||||||
0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12,
|
|
||||||
0x39, 0x0a, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f,
|
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f,
|
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42,
|
|
||||||
0x02, 0x18, 0x01, 0x52, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
|
|
||||||
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63,
|
|
||||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69,
|
|
||||||
0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e,
|
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e,
|
|
||||||
0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52,
|
|
||||||
0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
|
|
||||||
0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x42,
|
|
||||||
0x0a, 0x0e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
|
||||||
0x18, 0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
|
||||||
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74,
|
|
||||||
0x65, 0x67, 0x79, 0x52, 0x0d, 0x63, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
|
|
||||||
0x67, 0x79, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61,
|
|
||||||
0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
|
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
|
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
|
||||||
0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52,
|
|
||||||
0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
|
||||||
0x1a, 0x55, 0x0a, 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10,
|
|
||||||
0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79,
|
|
||||||
0x12, 0x31, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
|
||||||
0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
|
|
||||||
0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x76, 0x61,
|
|
||||||
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9a, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74,
|
|
||||||
0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
|
|
||||||
0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61,
|
|
||||||
0x69, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52,
|
|
||||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
|
0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a,
|
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a,
|
||||||
0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a,
|
0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a,
|
||||||
0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18,
|
0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c,
|
||||||
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f,
|
0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75,
|
0x04, 0x73, 0x69, 0x7a, 0x65, 0x22, 0xa5, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55,
|
0x12, 0x3f, 0x0a, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18,
|
||||||
0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10,
|
0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
0x02, 0x2a, 0x44, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
|
0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||||
0x67, 0x79, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x41, 0x4c, 0x4c, 0x10,
|
0x73, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||||
0x00, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x4e, 0x4f, 0x45, 0x52, 0x52,
|
0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x4f, 0x52, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x43, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x44, 0x49,
|
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||||
0x53, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x02, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x39, 0x0a, 0x05,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67,
|
0x48, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72,
|
||||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78,
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73,
|
0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x02, 0x18, 0x01,
|
||||||
0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62,
|
0x52, 0x05, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65,
|
||||||
|
0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68,
|
||||||
|
0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
|
0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74,
|
||||||
|
0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67,
|
||||||
|
0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x1a, 0x55, 0x0a, 0x0a, 0x48,
|
||||||
|
0x6f, 0x73, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
|
||||||
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x31, 0x0a, 0x05, 0x76,
|
||||||
|
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f,
|
||||||
|
0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||||
|
0x38, 0x01, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69,
|
||||||
|
0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
|
||||||
|
0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e,
|
||||||
|
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79,
|
||||||
|
0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61,
|
||||||
|
0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
|
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70,
|
||||||
|
0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61,
|
||||||
|
0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65,
|
||||||
|
0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x45, 0x0a,
|
||||||
|
0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54,
|
||||||
|
0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a,
|
||||||
|
0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07,
|
||||||
|
0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67,
|
||||||
|
0x65, 0x78, 0x10, 0x03, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68,
|
||||||
|
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
|
||||||
|
0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c,
|
||||||
|
0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -575,40 +527,37 @@ func file_app_dns_config_proto_rawDescGZIP() []byte {
|
|||||||
return file_app_dns_config_proto_rawDescData
|
return file_app_dns_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||||
var file_app_dns_config_proto_goTypes = []interface{}{
|
var file_app_dns_config_proto_goTypes = []interface{}{
|
||||||
(QueryStrategy)(0), // 0: xray.app.dns.QueryStrategy
|
(DomainMatchingType)(0), // 0: xray.app.dns.DomainMatchingType
|
||||||
(CacheStrategy)(0), // 1: xray.app.dns.CacheStrategy
|
(*NameServer)(nil), // 1: xray.app.dns.NameServer
|
||||||
(*NameServer)(nil), // 2: xray.app.dns.NameServer
|
(*Config)(nil), // 2: xray.app.dns.Config
|
||||||
(*Config)(nil), // 3: xray.app.dns.Config
|
(*NameServer_PriorityDomain)(nil), // 3: xray.app.dns.NameServer.PriorityDomain
|
||||||
(*NameServer_OriginalRule)(nil), // 4: xray.app.dns.NameServer.OriginalRule
|
(*NameServer_OriginalRule)(nil), // 4: xray.app.dns.NameServer.OriginalRule
|
||||||
nil, // 5: xray.app.dns.Config.HostsEntry
|
nil, // 5: xray.app.dns.Config.HostsEntry
|
||||||
(*Config_HostMapping)(nil), // 6: xray.app.dns.Config.HostMapping
|
(*Config_HostMapping)(nil), // 6: xray.app.dns.Config.HostMapping
|
||||||
(*net.Endpoint)(nil), // 7: xray.common.net.Endpoint
|
(*net.Endpoint)(nil), // 7: xray.common.net.Endpoint
|
||||||
(*domain.Domain)(nil), // 8: xray.common.matcher.domain.Domain
|
(*router.GeoIP)(nil), // 8: xray.app.router.GeoIP
|
||||||
(*geoip.GeoIP)(nil), // 9: xray.common.matcher.geoip.GeoIP
|
(*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain
|
||||||
(*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
|
|
||||||
(domain.MatchingType)(0), // 11: xray.common.matcher.domain.MatchingType
|
|
||||||
}
|
}
|
||||||
var file_app_dns_config_proto_depIdxs = []int32{
|
var file_app_dns_config_proto_depIdxs = []int32{
|
||||||
7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
|
7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
|
||||||
8, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.common.matcher.domain.Domain
|
3, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
|
||||||
9, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.common.matcher.geoip.GeoIP
|
8, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.app.router.GeoIP
|
||||||
4, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
|
4, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
|
||||||
7, // 4: xray.app.dns.Config.NameServers:type_name -> xray.common.net.Endpoint
|
7, // 4: xray.app.dns.Config.NameServers:type_name -> xray.common.net.Endpoint
|
||||||
2, // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
|
1, // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
|
||||||
5, // 6: xray.app.dns.Config.Hosts:type_name -> xray.app.dns.Config.HostsEntry
|
5, // 6: xray.app.dns.Config.Hosts:type_name -> xray.app.dns.Config.HostsEntry
|
||||||
6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
|
6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
|
||||||
1, // 8: xray.app.dns.Config.cache_strategy:type_name -> xray.app.dns.CacheStrategy
|
0, // 8: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
|
||||||
0, // 9: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
9, // 9: xray.app.dns.Config.HostsEntry.value:type_name -> xray.common.net.IPOrDomain
|
||||||
10, // 10: xray.app.dns.Config.HostsEntry.value:type_name -> xray.common.net.IPOrDomain
|
0, // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
|
||||||
11, // 11: xray.app.dns.Config.HostMapping.type:type_name -> xray.common.matcher.domain.MatchingType
|
11, // [11:11] is the sub-list for method output_type
|
||||||
12, // [12:12] is the sub-list for method output_type
|
11, // [11:11] is the sub-list for method input_type
|
||||||
12, // [12:12] is the sub-list for method input_type
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
12, // [12:12] is the sub-list for extension type_name
|
11, // [11:11] is the sub-list for extension extendee
|
||||||
12, // [12:12] is the sub-list for extension extendee
|
0, // [0:11] is the sub-list for field type_name
|
||||||
0, // [0:12] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_dns_config_proto_init() }
|
func init() { file_app_dns_config_proto_init() }
|
||||||
@@ -642,6 +591,18 @@ func file_app_dns_config_proto_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_app_dns_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
file_app_dns_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*NameServer_PriorityDomain); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_app_dns_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*NameServer_OriginalRule); i {
|
switch v := v.(*NameServer_OriginalRule); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -653,7 +614,7 @@ func file_app_dns_config_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_app_dns_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
file_app_dns_config_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*Config_HostMapping); i {
|
switch v := v.(*Config_HostMapping); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
@@ -671,8 +632,8 @@ func file_app_dns_config_proto_init() {
|
|||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_dns_config_proto_rawDesc,
|
RawDescriptor: file_app_dns_config_proto_rawDesc,
|
||||||
NumEnums: 2,
|
NumEnums: 1,
|
||||||
NumMessages: 5,
|
NumMessages: 6,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
@@ -8,34 +8,31 @@ option java_multiple_files = true;
|
|||||||
|
|
||||||
import "common/net/address.proto";
|
import "common/net/address.proto";
|
||||||
import "common/net/destination.proto";
|
import "common/net/destination.proto";
|
||||||
import "common/matcher/domain/domain.proto";
|
import "app/router/config.proto";
|
||||||
import "common/matcher/geoip/geoip.proto";
|
|
||||||
|
|
||||||
message NameServer {
|
message NameServer {
|
||||||
xray.common.net.Endpoint address = 1;
|
xray.common.net.Endpoint address = 1;
|
||||||
bytes client_ip = 5;
|
|
||||||
bool skipFallback = 6;
|
message PriorityDomain {
|
||||||
|
DomainMatchingType type = 1;
|
||||||
|
string domain = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message OriginalRule {
|
message OriginalRule {
|
||||||
string rule = 1;
|
string rule = 1;
|
||||||
uint32 size = 2;
|
uint32 size = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
repeated xray.common.matcher.domain.Domain prioritized_domain = 2;
|
repeated PriorityDomain prioritized_domain = 2;
|
||||||
repeated xray.common.matcher.geoip.GeoIP geoip = 3;
|
repeated xray.app.router.GeoIP geoip = 3;
|
||||||
repeated OriginalRule original_rules = 4;
|
repeated OriginalRule original_rules = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum QueryStrategy {
|
enum DomainMatchingType {
|
||||||
USE_IP = 0;
|
Full = 0;
|
||||||
USE_IP4 = 1;
|
Subdomain = 1;
|
||||||
USE_IP6 = 2;
|
Keyword = 2;
|
||||||
}
|
Regex = 3;
|
||||||
|
|
||||||
enum CacheStrategy {
|
|
||||||
Cache_ALL = 0;
|
|
||||||
Cache_NOERROR = 1;
|
|
||||||
Cache_DISABLE = 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
@@ -56,13 +53,14 @@ message Config {
|
|||||||
bytes client_ip = 3;
|
bytes client_ip = 3;
|
||||||
|
|
||||||
message HostMapping {
|
message HostMapping {
|
||||||
xray.common.matcher.domain.MatchingType type = 1;
|
DomainMatchingType type = 1;
|
||||||
string domain = 2;
|
string domain = 2;
|
||||||
|
|
||||||
repeated bytes ip = 3;
|
repeated bytes ip = 3;
|
||||||
|
|
||||||
// ProxiedDomain indicates the mapped domain has the same IP address on this
|
// ProxiedDomain indicates the mapped domain has the same IP address on this
|
||||||
// domain. Xray will use this domain for IP queries.
|
// domain. Xray will use this domain for IP queries. This field is only
|
||||||
|
// effective if ip is empty.
|
||||||
string proxied_domain = 4;
|
string proxied_domain = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,11 +70,4 @@ message Config {
|
|||||||
string tag = 6;
|
string tag = 6;
|
||||||
|
|
||||||
reserved 7;
|
reserved 7;
|
||||||
|
|
||||||
// DisableCache disables DNS cache
|
|
||||||
CacheStrategy cache_strategy = 8;
|
|
||||||
|
|
||||||
QueryStrategy query_strategy = 9;
|
|
||||||
|
|
||||||
bool disableFallback = 10;
|
|
||||||
}
|
}
|
||||||
|
293
app/dns/dns.go
293
app/dns/dns.go
@@ -2,296 +2,3 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/session"
|
|
||||||
"github.com/xtls/xray-core/features"
|
|
||||||
"github.com/xtls/xray-core/features/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DNS is a DNS rely server.
|
|
||||||
type DNS struct {
|
|
||||||
sync.Mutex
|
|
||||||
tag string
|
|
||||||
cacheStrategy CacheStrategy
|
|
||||||
disableFallback bool
|
|
||||||
ipOption *dns.IPOption
|
|
||||||
hosts *StaticHosts
|
|
||||||
clients []*Client
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
|
|
||||||
type DomainMatcherInfo struct {
|
|
||||||
clientIdx uint16
|
|
||||||
domainRuleIdx uint16
|
|
||||||
}
|
|
||||||
|
|
||||||
// New creates a new DNS server with given configuration.
|
|
||||||
func New(ctx context.Context, config *Config) (*DNS, error) {
|
|
||||||
var tag string
|
|
||||||
if len(config.Tag) > 0 {
|
|
||||||
tag = config.Tag
|
|
||||||
} else {
|
|
||||||
tag = generateRandomTag()
|
|
||||||
}
|
|
||||||
|
|
||||||
var clientIP net.IP
|
|
||||||
switch len(config.ClientIp) {
|
|
||||||
case 0, net.IPv4len, net.IPv6len:
|
|
||||||
clientIP = net.IP(config.ClientIp)
|
|
||||||
default:
|
|
||||||
return nil, newError("unexpected client IP length ", len(config.ClientIp))
|
|
||||||
}
|
|
||||||
|
|
||||||
var ipOption *dns.IPOption
|
|
||||||
switch config.QueryStrategy {
|
|
||||||
case QueryStrategy_USE_IP:
|
|
||||||
ipOption = &dns.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: true,
|
|
||||||
FakeEnable: false,
|
|
||||||
}
|
|
||||||
case QueryStrategy_USE_IP4:
|
|
||||||
ipOption = &dns.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: false,
|
|
||||||
FakeEnable: false,
|
|
||||||
}
|
|
||||||
case QueryStrategy_USE_IP6:
|
|
||||||
ipOption = &dns.IPOption{
|
|
||||||
IPv4Enable: false,
|
|
||||||
IPv6Enable: true,
|
|
||||||
FakeEnable: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hosts, err := NewStaticHosts(config.StaticHosts, config.Hosts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to create hosts").Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
clients := []*Client{}
|
|
||||||
domainRuleCount := 0
|
|
||||||
for _, ns := range config.NameServer {
|
|
||||||
domainRuleCount += len(ns.PrioritizedDomain)
|
|
||||||
}
|
|
||||||
|
|
||||||
geoipContainer := geoip.GeoIPMatcherContainer{}
|
|
||||||
|
|
||||||
for _, endpoint := range config.NameServers {
|
|
||||||
features.PrintDeprecatedFeatureWarning("simple DNS server")
|
|
||||||
client, err := NewSimpleClient(ctx, endpoint, clientIP)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to create client").Base(err)
|
|
||||||
}
|
|
||||||
clients = append(clients, client)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ns := range config.NameServer {
|
|
||||||
|
|
||||||
myClientIP := clientIP
|
|
||||||
switch len(ns.ClientIp) {
|
|
||||||
case net.IPv4len, net.IPv6len:
|
|
||||||
myClientIP = ns.ClientIp
|
|
||||||
}
|
|
||||||
client, err := NewClient(ctx, ns, myClientIP, geoipContainer)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to create client").Base(err)
|
|
||||||
}
|
|
||||||
clients = append(clients, client)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is no DNS client in config, add a `localhost` DNS client
|
|
||||||
if len(clients) == 0 {
|
|
||||||
clients = append(clients, NewLocalDNSClient())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DNS{
|
|
||||||
tag: tag,
|
|
||||||
hosts: hosts,
|
|
||||||
ipOption: ipOption,
|
|
||||||
clients: clients,
|
|
||||||
ctx: ctx,
|
|
||||||
cacheStrategy: config.CacheStrategy,
|
|
||||||
disableFallback: config.DisableFallback,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type implements common.HasType.
|
|
||||||
func (*DNS) Type() interface{} {
|
|
||||||
return dns.ClientType()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start implements common.Runnable.
|
|
||||||
func (s *DNS) Start() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close implements common.Closable.
|
|
||||||
func (s *DNS) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsOwnLink implements proxy.dns.ownLinkVerifier
|
|
||||||
func (s *DNS) IsOwnLink(ctx context.Context) bool {
|
|
||||||
inbound := session.InboundFromContext(ctx)
|
|
||||||
return inbound != nil && inbound.Tag == s.tag
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupIP implements dns.Client.
|
|
||||||
func (s *DNS) LookupIP(domain string) ([]net.IP, error) {
|
|
||||||
return s.lookupIPInternal(domain, s.ipOption.Copy())
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupOptions implements dns.Client.
|
|
||||||
func (s *DNS) LookupOptions(domain string, opts ...dns.Option) ([]net.IP, error) {
|
|
||||||
opt := s.ipOption.Copy()
|
|
||||||
for _, o := range opts {
|
|
||||||
if o != nil {
|
|
||||||
o(opt)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.lookupIPInternal(domain, opt)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupIPv4 implements dns.IPv4Lookup.
|
|
||||||
func (s *DNS) LookupIPv4(domain string) ([]net.IP, error) {
|
|
||||||
return s.lookupIPInternal(domain, &dns.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// LookupIPv6 implements dns.IPv6Lookup.
|
|
||||||
func (s *DNS) LookupIPv6(domain string) ([]net.IP, error) {
|
|
||||||
return s.lookupIPInternal(domain, &dns.IPOption{
|
|
||||||
IPv6Enable: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DNS) lookupIPInternal(domain string, option *dns.IPOption) ([]net.IP, error) {
|
|
||||||
if domain == "" {
|
|
||||||
return nil, newError("empty domain name")
|
|
||||||
}
|
|
||||||
if isQuery(option) {
|
|
||||||
return nil, newError("empty option: Impossible.").AtWarning()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normalize the FQDN form query
|
|
||||||
if strings.HasSuffix(domain, ".") {
|
|
||||||
domain = domain[:len(domain)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Static host lookup
|
|
||||||
switch addrs := s.hosts.Lookup(domain, option); {
|
|
||||||
case addrs == nil: // Domain not recorded in static host
|
|
||||||
break
|
|
||||||
case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
|
|
||||||
return nil, dns.ErrEmptyResponse
|
|
||||||
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement
|
|
||||||
newError("domain replaced: ", domain, " -> ", addrs[0].Domain()).WriteToLog()
|
|
||||||
domain = addrs[0].Domain()
|
|
||||||
default:
|
|
||||||
// Successfully found ip records in static host.
|
|
||||||
// Skip hosts mapping result in FakeDNS query.
|
|
||||||
if isIPQuery(option) {
|
|
||||||
newError("returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs).WriteToLog()
|
|
||||||
return toNetIP(addrs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name servers lookup
|
|
||||||
errs := []error{}
|
|
||||||
ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag})
|
|
||||||
for _, client := range s.sortClients(domain, option) {
|
|
||||||
ips, err := client.QueryIP(ctx, domain, *option, s.cacheStrategy)
|
|
||||||
if len(ips) > 0 {
|
|
||||||
return ips, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, newError("returning nil for domain ", domain).Base(errors.Combine(errs...))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *DNS) sortClients(domain string, option *dns.IPOption) []*Client {
|
|
||||||
clients := make([]*Client, 0, len(s.clients))
|
|
||||||
clientUsed := make([]bool, len(s.clients))
|
|
||||||
clientNames := make([]string, 0, len(s.clients))
|
|
||||||
domainRules := []string{}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if len(domainRules) > 0 {
|
|
||||||
newError("domain ", domain, " matches following rules: ", domainRules).AtDebug().WriteToLog()
|
|
||||||
}
|
|
||||||
if len(clientNames) > 0 {
|
|
||||||
newError("domain ", domain, " will use DNS in order: ", clientNames).AtDebug().WriteToLog()
|
|
||||||
}
|
|
||||||
if len(clients) == 0 {
|
|
||||||
clients = append(clients, s.clients[0])
|
|
||||||
clientNames = append(clientNames, s.clients[0].Name())
|
|
||||||
newError("domain ", domain, " will use the first DNS: ", clientNames).AtDebug().WriteToLog()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Priority domain matching
|
|
||||||
for clientIdx, client := range s.clients {
|
|
||||||
if ids := client.domainMatcher.Match(domain); len(ids) > 0 {
|
|
||||||
if !canQueryOnClient(option, client) {
|
|
||||||
newError("skipping the client " + client.Name()).AtDebug().WriteToLog()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, id := range ids {
|
|
||||||
rule := client.findRule(id)
|
|
||||||
domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", rule, clientIdx))
|
|
||||||
}
|
|
||||||
if clientUsed[clientIdx] {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
clients = append(clients, client)
|
|
||||||
clientNames = append(clientNames, client.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.disableFallback {
|
|
||||||
// Default round-robin query
|
|
||||||
for idx, client := range s.clients {
|
|
||||||
if clientUsed[idx] || client.skipFallback {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !canQueryOnClient(option, client) {
|
|
||||||
newError("skipping the client " + client.Name()).AtDebug().WriteToLog()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
clientUsed[idx] = true
|
|
||||||
clients = append(clients, client)
|
|
||||||
clientNames = append(clientNames, client.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return clients
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
|
||||||
return New(ctx, config.(*Config))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
@@ -5,11 +5,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fqdn normalize domain make sure it ends with '.'
|
// Fqdn normalize domain make sure it ends with '.'
|
||||||
|
@@ -7,10 +7,11 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseResponse(t *testing.T) {
|
func Test_parseResponse(t *testing.T) {
|
||||||
|
@@ -12,6 +12,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -23,7 +25,6 @@ import (
|
|||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format,
|
// DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format,
|
||||||
@@ -42,10 +43,10 @@ type DoHNameServer struct {
|
|||||||
name string
|
name string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDoHNameServer creates DOH server object for remote resolving
|
// NewDoHNameServer creates DOH client object for remote resolving
|
||||||
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher) (*DoHNameServer, error) {
|
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, clientIP net.IP) (*DoHNameServer, error) {
|
||||||
newError("DNS: created Remote DOH client for ", url.String()).AtInfo().WriteToLog()
|
newError("DNS: created Remote DOH client for ", url.String()).AtInfo().WriteToLog()
|
||||||
s := baseDOHNameServer(url, "DOH")
|
s := baseDOHNameServer(url, "DOH", clientIP)
|
||||||
|
|
||||||
s.dispatcher = dispatcher
|
s.dispatcher = dispatcher
|
||||||
tr := &http.Transport{
|
tr := &http.Transport{
|
||||||
@@ -80,12 +81,6 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher) (*DoHNameServ
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
log.Record(&log.AccessMessage{
|
|
||||||
From: "DoH",
|
|
||||||
To: s.dohURL,
|
|
||||||
Status: log.AccessAccepted,
|
|
||||||
Detour: "local",
|
|
||||||
})
|
|
||||||
|
|
||||||
cc := common.ChainedClosable{}
|
cc := common.ChainedClosable{}
|
||||||
if cw, ok := link.Writer.(common.Closable); ok {
|
if cw, ok := link.Writer.(common.Closable); ok {
|
||||||
@@ -110,9 +105,9 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher) (*DoHNameServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewDoHLocalNameServer creates DOH client object for local resolving
|
// NewDoHLocalNameServer creates DOH client object for local resolving
|
||||||
func NewDoHLocalNameServer(url *url.URL) *DoHNameServer {
|
func NewDoHLocalNameServer(url *url.URL, clientIP net.IP) *DoHNameServer {
|
||||||
url.Scheme = "https"
|
url.Scheme = "https"
|
||||||
s := baseDOHNameServer(url, "DOHL")
|
s := baseDOHNameServer(url, "DOHL", clientIP)
|
||||||
tr := &http.Transport{
|
tr := &http.Transport{
|
||||||
IdleConnTimeout: 90 * time.Second,
|
IdleConnTimeout: 90 * time.Second,
|
||||||
ForceAttemptHTTP2: true,
|
ForceAttemptHTTP2: true,
|
||||||
@@ -142,12 +137,13 @@ func NewDoHLocalNameServer(url *url.URL) *DoHNameServer {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func baseDOHNameServer(url *url.URL, prefix string) *DoHNameServer {
|
func baseDOHNameServer(url *url.URL, prefix string, clientIP net.IP) *DoHNameServer {
|
||||||
s := &DoHNameServer{
|
s := &DoHNameServer{
|
||||||
ips: make(map[string]record),
|
ips: make(map[string]record),
|
||||||
pub: pubsub.NewService(),
|
clientIP: clientIP,
|
||||||
name: prefix + "//" + url.Host,
|
pub: pubsub.NewService(),
|
||||||
dohURL: url.String(),
|
name: prefix + "//" + url.Host,
|
||||||
|
dohURL: url.String(),
|
||||||
}
|
}
|
||||||
s.cleanup = &task.Periodic{
|
s.cleanup = &task.Periodic{
|
||||||
Interval: time.Minute,
|
Interval: time.Minute,
|
||||||
@@ -157,7 +153,7 @@ func baseDOHNameServer(url *url.URL, prefix string) *DoHNameServer {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name implements Server.
|
// Name returns client name
|
||||||
func (s *DoHNameServer) Name() string {
|
func (s *DoHNameServer) Name() string {
|
||||||
return s.name
|
return s.name
|
||||||
}
|
}
|
||||||
@@ -240,7 +236,7 @@ func (s *DoHNameServer) newReqID() uint16 {
|
|||||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, option dns_feature.IPOption) {
|
||||||
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx))
|
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
|
||||||
if s.name+"." == "DOH//"+domain {
|
if s.name+"." == "DOH//"+domain {
|
||||||
@@ -248,7 +244,7 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP n
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP))
|
||||||
|
|
||||||
var deadline time.Time
|
var deadline time.Time
|
||||||
if d, ok := ctx.Deadline(); ok {
|
if d, ok := ctx.Deadline(); ok {
|
||||||
@@ -269,8 +265,8 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP n
|
|||||||
}
|
}
|
||||||
|
|
||||||
dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{
|
dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{
|
||||||
Protocol: "https",
|
Protocol: "https",
|
||||||
SkipDNSResolve: true,
|
//SkipRoutePick: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
// forced to use mux for DOH
|
// forced to use mux for DOH
|
||||||
@@ -354,7 +350,7 @@ func (s *DoHNameServer) findIPsForDomain(domain string, option dns_feature.IPOpt
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
return toNetIP(ips)
|
return toNetIP(ips), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if lastErr != nil {
|
if lastErr != nil {
|
||||||
@@ -368,21 +364,15 @@ func (s *DoHNameServer) findIPsForDomain(domain string, option dns_feature.IPOpt
|
|||||||
return nil, errRecordNotFound
|
return nil, errRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP is called from dns.Server->queryIPTimeout
|
||||||
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) { // nolint: dupl
|
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, error) { // nolint: dupl
|
||||||
fqdn := Fqdn(domain)
|
fqdn := Fqdn(domain)
|
||||||
|
|
||||||
if cs == CacheStrategy_Cache_DISABLE {
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog()
|
if err != errRecordNotFound {
|
||||||
} else {
|
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
||||||
ips, err := s.findIPsForDomain(fqdn, option)
|
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
|
||||||
if err != errRecordNotFound {
|
return ips, err
|
||||||
if cs == CacheStrategy_Cache_NOERROR && err == nil {
|
|
||||||
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
|
||||||
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
|
|
||||||
return ips, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ipv4 and ipv6 belong to different subscription groups
|
// ipv4 and ipv6 belong to different subscription groups
|
||||||
@@ -411,7 +401,7 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net
|
|||||||
}
|
}
|
||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
s.sendQuery(ctx, fqdn, clientIP, option)
|
s.sendQuery(ctx, fqdn, option)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
for {
|
for {
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.13.0
|
// protoc v3.18.0
|
||||||
// source: app/dns/fakedns/fakedns.proto
|
// source: app/dns/fakedns/fakedns.proto
|
||||||
|
|
||||||
package fakedns
|
package fakedns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type FakeDnsPool struct {
|
type FakeDnsPool struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -85,19 +80,18 @@ var File_app_dns_fakedns_fakedns_proto protoreflect.FileDescriptor
|
|||||||
var file_app_dns_fakedns_fakedns_proto_rawDesc = []byte{
|
var file_app_dns_fakedns_fakedns_proto_rawDesc = []byte{
|
||||||
0x0a, 0x1d, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e,
|
0x0a, 0x1d, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e,
|
||||||
0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
|
0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
|
||||||
0x1a, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
0x14, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61,
|
||||||
0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x22, 0x40, 0x0a, 0x0b, 0x46,
|
0x6b, 0x65, 0x64, 0x6e, 0x73, 0x22, 0x40, 0x0a, 0x0b, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73,
|
||||||
0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70,
|
0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18,
|
||||||
0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x50,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x18, 0x0a,
|
||||||
0x6f, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02,
|
0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07,
|
||||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x5f, 0x0a,
|
0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x5e, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||||
0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65,
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x50,
|
0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||||
0x01, 0x5a, 0x1e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x72,
|
0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65,
|
||||||
0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e,
|
0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73,
|
||||||
0x73, 0xaa, 0x02, 0x1a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41,
|
0xaa, 0x02, 0x14, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x2e,
|
||||||
0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x62, 0x06,
|
0x46, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -2,8 +2,8 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/matcher/str"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
"github.com/xtls/xray-core/features"
|
"github.com/xtls/xray-core/features"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
)
|
)
|
||||||
@@ -11,12 +11,31 @@ import (
|
|||||||
// StaticHosts represents static domain-ip mapping in DNS server.
|
// StaticHosts represents static domain-ip mapping in DNS server.
|
||||||
type StaticHosts struct {
|
type StaticHosts struct {
|
||||||
ips [][]net.Address
|
ips [][]net.Address
|
||||||
matchers *str.MatcherGroup
|
matchers *strmatcher.MatcherGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
var typeMap = map[DomainMatchingType]strmatcher.Type{
|
||||||
|
DomainMatchingType_Full: strmatcher.Full,
|
||||||
|
DomainMatchingType_Subdomain: strmatcher.Domain,
|
||||||
|
DomainMatchingType_Keyword: strmatcher.Substr,
|
||||||
|
DomainMatchingType_Regex: strmatcher.Regex,
|
||||||
|
}
|
||||||
|
|
||||||
|
func toStrMatcher(t DomainMatchingType, domain string) (strmatcher.Matcher, error) {
|
||||||
|
strMType, f := typeMap[t]
|
||||||
|
if !f {
|
||||||
|
return nil, newError("unknown mapping type", t).AtWarning()
|
||||||
|
}
|
||||||
|
matcher, err := strMType.New(domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to create str matcher").Base(err)
|
||||||
|
}
|
||||||
|
return matcher, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStaticHosts creates a new StaticHosts instance.
|
// NewStaticHosts creates a new StaticHosts instance.
|
||||||
func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDomain) (*StaticHosts, error) {
|
func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDomain) (*StaticHosts, error) {
|
||||||
g := new(str.MatcherGroup)
|
g := new(strmatcher.MatcherGroup)
|
||||||
sh := &StaticHosts{
|
sh := &StaticHosts{
|
||||||
ips: make([][]net.Address, len(hosts)+len(legacy)+16),
|
ips: make([][]net.Address, len(hosts)+len(legacy)+16),
|
||||||
matchers: g,
|
matchers: g,
|
||||||
@@ -26,7 +45,7 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
|||||||
features.PrintDeprecatedFeatureWarning("simple host mapping")
|
features.PrintDeprecatedFeatureWarning("simple host mapping")
|
||||||
|
|
||||||
for domain, ip := range legacy {
|
for domain, ip := range legacy {
|
||||||
matcher, err := str.Full.New(domain)
|
matcher, err := strmatcher.Full.New(domain)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
id := g.Add(matcher)
|
id := g.Add(matcher)
|
||||||
|
|
||||||
@@ -47,9 +66,6 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
|||||||
id := g.Add(matcher)
|
id := g.Add(matcher)
|
||||||
ips := make([]net.Address, 0, len(mapping.Ip)+1)
|
ips := make([]net.Address, 0, len(mapping.Ip)+1)
|
||||||
switch {
|
switch {
|
||||||
case len(mapping.ProxiedDomain) > 0:
|
|
||||||
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
|
|
||||||
|
|
||||||
case len(mapping.Ip) > 0:
|
case len(mapping.Ip) > 0:
|
||||||
for _, ip := range mapping.Ip {
|
for _, ip := range mapping.Ip {
|
||||||
addr := net.IPAddress(ip)
|
addr := net.IPAddress(ip)
|
||||||
@@ -59,56 +75,49 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
|||||||
ips = append(ips, addr)
|
ips = append(ips, addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case len(mapping.ProxiedDomain) > 0:
|
||||||
|
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, newError("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning()
|
return nil, newError("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special handling for localhost IPv6. This is a dirty workaround as JSON config supports only single IP mapping.
|
||||||
|
if len(ips) == 1 && ips[0] == net.LocalHostIP {
|
||||||
|
ips = append(ips, net.LocalHostIPv6)
|
||||||
|
}
|
||||||
|
|
||||||
sh.ips[id] = ips
|
sh.ips[id] = ips
|
||||||
}
|
}
|
||||||
|
|
||||||
return sh, nil
|
return sh, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterIP(ips []net.Address, option *dns.IPOption) []net.Address {
|
func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
||||||
filtered := make([]net.Address, 0, len(ips))
|
filtered := make([]net.Address, 0, len(ips))
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) {
|
if (ip.Family().IsIPv4() && option.IPv4Enable) || (ip.Family().IsIPv6() && option.IPv6Enable) {
|
||||||
filtered = append(filtered, ip)
|
filtered = append(filtered, ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(filtered) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *StaticHosts) lookupInternal(domain string) []net.Address {
|
// LookupIP returns IP address for the given domain, if exists in this StaticHosts.
|
||||||
var ips []net.Address
|
func (h *StaticHosts) LookupIP(domain string, option dns.IPOption) []net.Address {
|
||||||
for _, id := range h.matchers.Match(domain) {
|
indices := h.matchers.Match(domain)
|
||||||
|
if len(indices) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ips := []net.Address{}
|
||||||
|
for _, id := range indices {
|
||||||
ips = append(ips, h.ips[id]...)
|
ips = append(ips, h.ips[id]...)
|
||||||
}
|
}
|
||||||
if len(ips) == 1 && ips[0].Family().IsDomain() {
|
if len(ips) == 1 && ips[0].Family().IsDomain() {
|
||||||
return ips
|
return ips
|
||||||
}
|
}
|
||||||
return ips
|
return filterIP(ips, option)
|
||||||
}
|
|
||||||
|
|
||||||
func (h *StaticHosts) lookup(domain string, option *dns.IPOption, maxDepth int) []net.Address {
|
|
||||||
switch addrs := h.lookupInternal(domain); {
|
|
||||||
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
|
||||||
return nil
|
|
||||||
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
|
|
||||||
newError("found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it").AtDebug().WriteToLog()
|
|
||||||
if maxDepth > 0 {
|
|
||||||
unwrapped := h.lookup(addrs[0].Domain(), option, maxDepth-1)
|
|
||||||
if unwrapped != nil {
|
|
||||||
return unwrapped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return addrs
|
|
||||||
default: // IP record found, return a non-nil IP array
|
|
||||||
return filterIP(addrs, option)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
|
|
||||||
func (h *StaticHosts) Lookup(domain string, option *dns.IPOption) []net.Address {
|
|
||||||
return h.lookup(domain, option, 5)
|
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
. "github.com/xtls/xray-core/app/dns"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
)
|
)
|
||||||
@@ -15,39 +14,24 @@ import (
|
|||||||
func TestStaticHosts(t *testing.T) {
|
func TestStaticHosts(t *testing.T) {
|
||||||
pb := []*Config_HostMapping{
|
pb := []*Config_HostMapping{
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Full,
|
Type: DomainMatchingType_Full,
|
||||||
Domain: "example.com",
|
Domain: "example.com",
|
||||||
Ip: [][]byte{
|
Ip: [][]byte{
|
||||||
{1, 1, 1, 1},
|
{1, 1, 1, 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Full,
|
Type: DomainMatchingType_Subdomain,
|
||||||
Domain: "proxy.example.com",
|
|
||||||
Ip: [][]byte{
|
|
||||||
{1, 2, 3, 4},
|
|
||||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
||||||
},
|
|
||||||
ProxiedDomain: "another-proxy.example.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: domain.MatchingType_Full,
|
|
||||||
Domain: "proxy2.example.com",
|
|
||||||
ProxiedDomain: "proxy.example.com",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: domain.MatchingType_Subdomain,
|
|
||||||
Domain: "example.cn",
|
Domain: "example.cn",
|
||||||
Ip: [][]byte{
|
Ip: [][]byte{
|
||||||
{2, 2, 2, 2},
|
{2, 2, 2, 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Subdomain,
|
Type: DomainMatchingType_Subdomain,
|
||||||
Domain: "baidu.com",
|
Domain: "baidu.com",
|
||||||
Ip: [][]byte{
|
Ip: [][]byte{
|
||||||
{127, 0, 0, 1},
|
{127, 0, 0, 1},
|
||||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -56,7 +40,7 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
{
|
{
|
||||||
ips := hosts.Lookup("example.com", &dns.IPOption{
|
ips := hosts.LookupIP("example.com", dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
})
|
||||||
@@ -69,33 +53,7 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
domain := hosts.Lookup("proxy.example.com", &dns.IPOption{
|
ips := hosts.LookupIP("www.example.cn", dns.IPOption{
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: false,
|
|
||||||
})
|
|
||||||
if len(domain) != 1 {
|
|
||||||
t.Error("expect 1 domain, but got ", len(domain))
|
|
||||||
}
|
|
||||||
if diff := cmp.Diff(domain[0].Domain(), "another-proxy.example.com"); diff != "" {
|
|
||||||
t.Error(diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
domain := hosts.Lookup("proxy2.example.com", &dns.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: false,
|
|
||||||
})
|
|
||||||
if len(domain) != 1 {
|
|
||||||
t.Error("expect 1 domain, but got ", len(domain))
|
|
||||||
}
|
|
||||||
if diff := cmp.Diff(domain[0].Domain(), "another-proxy.example.com"); diff != "" {
|
|
||||||
t.Error(diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
ips := hosts.Lookup("www.example.cn", &dns.IPOption{
|
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
})
|
||||||
@@ -108,7 +66,7 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ips := hosts.Lookup("baidu.com", &dns.IPOption{
|
ips := hosts.LookupIP("baidu.com", dns.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: false,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
})
|
||||||
|
@@ -2,207 +2,40 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/str"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
core "github.com/xtls/xray-core/core"
|
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/dns/localdns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server is the interface for Name Server.
|
// Client is the interface for DNS client.
|
||||||
type Server interface {
|
type Client interface {
|
||||||
// Name of the Client.
|
// Name of the Client.
|
||||||
Name() string
|
Name() string
|
||||||
|
|
||||||
// QueryIP sends IP queries to its configured server.
|
// QueryIP sends IP queries to its configured server.
|
||||||
QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns.IPOption, cs CacheStrategy) ([]net.IP, error)
|
QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is the interface for DNS client.
|
type LocalNameServer struct {
|
||||||
type Client struct {
|
client *localdns.Client
|
||||||
server Server
|
|
||||||
clientIP net.IP
|
|
||||||
skipFallback bool
|
|
||||||
expectIPs []*geoip.GeoIPMatcher
|
|
||||||
domainMatcher str.MatcherGroup
|
|
||||||
originRules []*NameServer_OriginalRule
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c Client) findRule(idx uint32) string {
|
func (s *LocalNameServer) QueryIP(_ context.Context, domain string, option dns.IPOption) ([]net.IP, error) {
|
||||||
for _, r := range c.originRules {
|
if option.IPv4Enable || option.IPv6Enable {
|
||||||
if idx <= r.Size {
|
return s.client.LookupIP(domain, option)
|
||||||
return r.Rule
|
|
||||||
}
|
|
||||||
idx -= r.Size
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "unknown rule"
|
return nil, newError("neither IPv4 nor IPv6 is enabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
var errExpectedIPNonMatch = errors.New("expectIPs not match")
|
func (s *LocalNameServer) Name() string {
|
||||||
|
return "localhost"
|
||||||
// NewServer creates a name server object according to the network destination url.
|
|
||||||
func NewServer(dest net.Destination, dispatcher routing.Dispatcher) (Server, error) {
|
|
||||||
if address := dest.Address; address.Family().IsDomain() {
|
|
||||||
u, err := url.Parse(address.Domain())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case strings.EqualFold(u.String(), "localhost"):
|
|
||||||
return NewLocalNameServer(), nil
|
|
||||||
case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode
|
|
||||||
return NewDoHNameServer(u, dispatcher)
|
|
||||||
case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode
|
|
||||||
return NewDoHLocalNameServer(u), nil
|
|
||||||
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
|
||||||
return NewQUICNameServer(u)
|
|
||||||
case strings.EqualFold(u.String(), "fakedns"):
|
|
||||||
return NewFakeDNSServer(), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dest.Network == net.Network_Unknown {
|
|
||||||
dest.Network = net.Network_UDP
|
|
||||||
}
|
|
||||||
if dest.Network == net.Network_UDP { // UDP classic DNS mode
|
|
||||||
return NewClassicNameServer(dest, dispatcher), nil
|
|
||||||
}
|
|
||||||
return nil, newError("No available name server could be created from ", dest).AtWarning()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs.
|
func NewLocalNameServer() *LocalNameServer {
|
||||||
func NewClient(ctx context.Context, ns *NameServer, clientIP net.IP, container geoip.GeoIPMatcherContainer) (*Client, error) {
|
newError("DNS: created localhost client").AtInfo().WriteToLog()
|
||||||
client := &Client{}
|
return &LocalNameServer{
|
||||||
|
client: localdns.New(),
|
||||||
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
|
||||||
// Create a new server for each client for now
|
|
||||||
server, err := NewServer(ns.Address.AsDestination(), dispatcher)
|
|
||||||
if err != nil {
|
|
||||||
return newError("failed to create nameserver").Base(err).AtWarning()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Priotize local domains with specific TLDs or without any dot to local DNS
|
|
||||||
if _, isLocalDNS := server.(*LocalNameServer); isLocalDNS {
|
|
||||||
ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
|
|
||||||
ns.OriginalRules = append(ns.OriginalRules, localTLDsAndDotlessDomainsRule)
|
|
||||||
// The following lines is a solution to avoid core panics(rule index out of range) when setting `localhost` DNS client in config.
|
|
||||||
// Because the `localhost` DNS client will append len(localTLDsAndDotlessDomains) rules into matcherInfos to match `geosite:private` default rule.
|
|
||||||
// But `matcherInfos` has no enough length to add rules, which leads to core panics (rule index out of range).
|
|
||||||
// To avoid this, the length of `matcherInfos` must be equal to the expected, so manually append it with Golang default zero value first for later modification.
|
|
||||||
// ;)
|
|
||||||
/*
|
|
||||||
for i := 0; i < len(localTLDsAndDotlessDomains); i++ {
|
|
||||||
*matcherInfos = append(*matcherInfos, DomainMatcherInfo{
|
|
||||||
clientIdx: uint16(0),
|
|
||||||
domainRuleIdx: uint16(0),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establish domain rules
|
|
||||||
var domainMatcher = str.MatcherGroup{}
|
|
||||||
for _, domain := range ns.PrioritizedDomain {
|
|
||||||
domainRule, err := toStrMatcher(domain.Type, domain.Value)
|
|
||||||
if err != nil {
|
|
||||||
return newError("failed to create prioritized domain").Base(err).AtWarning()
|
|
||||||
}
|
|
||||||
domainMatcher.Add(domainRule)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establish expected IPs
|
|
||||||
var ipMatchers []*geoip.GeoIPMatcher
|
|
||||||
for _, geoip := range ns.Geoip {
|
|
||||||
matcher, err := container.Add(geoip)
|
|
||||||
if err != nil {
|
|
||||||
return newError("failed to create ip matcher").Base(err).AtWarning()
|
|
||||||
}
|
|
||||||
ipMatchers = append(ipMatchers, matcher)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(clientIP) > 0 {
|
|
||||||
switch ns.Address.Address.GetAddress().(type) {
|
|
||||||
case *net.IPOrDomain_Domain:
|
|
||||||
newError("DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog()
|
|
||||||
case *net.IPOrDomain_Ip:
|
|
||||||
newError("DNS: client ", ns.Address.Address.GetIp(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client.server = server
|
|
||||||
client.clientIP = clientIP
|
|
||||||
client.expectIPs = ipMatchers
|
|
||||||
client.originRules = ns.OriginalRules
|
|
||||||
client.domainMatcher = domainMatcher
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return client, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSimpleClient creates a DNS client with a simple destination.
|
|
||||||
func NewSimpleClient(ctx context.Context, endpoint *net.Endpoint, clientIP net.IP) (*Client, error) {
|
|
||||||
client := &Client{}
|
|
||||||
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
|
||||||
server, err := NewServer(endpoint.AsDestination(), dispatcher)
|
|
||||||
if err != nil {
|
|
||||||
return newError("failed to create nameserver").Base(err).AtWarning()
|
|
||||||
}
|
|
||||||
client.server = server
|
|
||||||
client.clientIP = clientIP
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if len(clientIP) > 0 {
|
|
||||||
switch endpoint.Address.GetAddress().(type) {
|
|
||||||
case *net.IPOrDomain_Domain:
|
|
||||||
newError("DNS: client ", endpoint.Address.GetDomain(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog()
|
|
||||||
case *net.IPOrDomain_Ip:
|
|
||||||
newError("DNS: client ", endpoint.Address.GetIp(), " uses clientIP ", clientIP.String()).AtInfo().WriteToLog()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return client, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns the server name the client manages.
|
|
||||||
func (c *Client) Name() string {
|
|
||||||
return c.server.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryIP send DNS query to the name server with the client's IP.
|
|
||||||
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, cs CacheStrategy) ([]net.IP, error) {
|
|
||||||
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
|
||||||
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, cs)
|
|
||||||
cancel()
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return ips, err
|
|
||||||
}
|
|
||||||
return c.MatchExpectedIPs(domain, ips)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones.
|
|
||||||
func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error) {
|
|
||||||
if len(c.expectIPs) == 0 {
|
|
||||||
return ips, nil
|
|
||||||
}
|
|
||||||
newIps := []net.IP{}
|
|
||||||
for _, ip := range ips {
|
|
||||||
for _, matcher := range c.expectIPs {
|
|
||||||
if matcher.Match(ip) {
|
|
||||||
newIps = append(newIps, ip)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(newIps) == 0 {
|
|
||||||
return nil, errExpectedIPNonMatch
|
|
||||||
}
|
|
||||||
newError("domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name()).AtDebug().WriteToLog()
|
|
||||||
return newIps, nil
|
|
||||||
}
|
}
|
||||||
|
@@ -1,60 +0,0 @@
|
|||||||
package dns_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestDOHNameServer(t *testing.T) {
|
|
||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
s := NewDoHLocalNameServer(url)
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: true,
|
|
||||||
}, CacheStrategy_Cache_ALL)
|
|
||||||
cancel()
|
|
||||||
common.Must(err)
|
|
||||||
if len(ips) == 0 {
|
|
||||||
t.Error("expect some ips, but got 0")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDOHNameServerWithCache(t *testing.T) {
|
|
||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
s := NewDoHLocalNameServer(url)
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: true,
|
|
||||||
}, CacheStrategy_Cache_ALL)
|
|
||||||
cancel()
|
|
||||||
common.Must(err)
|
|
||||||
if len(ips) == 0 {
|
|
||||||
t.Error("expect some ips, but got 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
|
||||||
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: true,
|
|
||||||
}, CacheStrategy_Cache_ALL)
|
|
||||||
cancel()
|
|
||||||
common.Must(err)
|
|
||||||
if r := cmp.Diff(ips2, ips); r != "" {
|
|
||||||
t.Fatal(r)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -16,13 +16,11 @@ func NewFakeDNSServer() *FakeDNSServer {
|
|||||||
return &FakeDNSServer{}
|
return &FakeDNSServer{}
|
||||||
}
|
}
|
||||||
|
|
||||||
const FakeDNSName = "FakeDNS"
|
|
||||||
|
|
||||||
func (FakeDNSServer) Name() string {
|
func (FakeDNSServer) Name() string {
|
||||||
return FakeDNSName
|
return "FakeDNS"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _ dns.IPOption, _ CacheStrategy) ([]net.IP, error) {
|
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ dns.IPOption) ([]net.IP, error) {
|
||||||
if f.fakeDNSEngine == nil {
|
if f.fakeDNSEngine == nil {
|
||||||
if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) {
|
if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) {
|
||||||
f.fakeDNSEngine = fd
|
f.fakeDNSEngine = fd
|
||||||
@@ -32,9 +30,9 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, _
|
|||||||
}
|
}
|
||||||
ips := f.fakeDNSEngine.GetFakeIPForDomain(domain)
|
ips := f.fakeDNSEngine.GetFakeIPForDomain(domain)
|
||||||
|
|
||||||
netIP, err := toNetIP(ips)
|
netIP := toNetIP(ips)
|
||||||
if err != nil {
|
if netIP == nil {
|
||||||
return nil, newError("Unable to convert IP to net ip").Base(err).AtError()
|
return nil, newError("Unable to convert IP to net ip").AtError()
|
||||||
}
|
}
|
||||||
|
|
||||||
newError(f.Name(), " got answer: ", domain, " -> ", ips).AtInfo().WriteToLog()
|
newError(f.Name(), " got answer: ", domain, " -> ", ips).AtInfo().WriteToLog()
|
||||||
|
@@ -1,53 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/features/dns"
|
|
||||||
"github.com/xtls/xray-core/features/dns/localdns"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LocalNameServer is an wrapper over local DNS feature.
|
|
||||||
type LocalNameServer struct {
|
|
||||||
client *localdns.Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryIP implements Server.
|
|
||||||
func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, option dns.IPOption, _ CacheStrategy) ([]net.IP, error) {
|
|
||||||
var ips []net.IP
|
|
||||||
var err error
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case option.IPv4Enable && option.IPv6Enable:
|
|
||||||
ips, err = s.client.LookupIP(domain)
|
|
||||||
case option.IPv4Enable:
|
|
||||||
ips, err = s.client.LookupIPv4(domain)
|
|
||||||
case option.IPv6Enable:
|
|
||||||
ips, err = s.client.LookupIPv6(domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ips) > 0 {
|
|
||||||
newError("Localhost got answer: ", domain, " -> ", ips).AtInfo().WriteToLog()
|
|
||||||
}
|
|
||||||
|
|
||||||
return ips, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name implements Server.
|
|
||||||
func (s *LocalNameServer) Name() string {
|
|
||||||
return "localhost"
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
|
|
||||||
func NewLocalNameServer() *LocalNameServer {
|
|
||||||
newError("DNS: created localhost client").AtInfo().WriteToLog()
|
|
||||||
return &LocalNameServer{
|
|
||||||
client: localdns.New(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
|
|
||||||
func NewLocalDNSClient() *Client {
|
|
||||||
return &Client{server: NewLocalNameServer()}
|
|
||||||
}
|
|
@@ -1,394 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/url"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
"golang.org/x/net/http2"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
|
||||||
"github.com/xtls/xray-core/common/log"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/protocol/dns"
|
|
||||||
"github.com/xtls/xray-core/common/session"
|
|
||||||
"github.com/xtls/xray-core/common/signal/pubsub"
|
|
||||||
"github.com/xtls/xray-core/common/task"
|
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NextProtoDQ - During connection establishment, DNS/QUIC support is indicated
|
|
||||||
// by selecting the ALPN token "dq" in the crypto handshake.
|
|
||||||
const NextProtoDQ = "doq-i00"
|
|
||||||
|
|
||||||
// QUICNameServer implemented DNS over QUIC
|
|
||||||
type QUICNameServer struct {
|
|
||||||
sync.RWMutex
|
|
||||||
ips map[string]record
|
|
||||||
pub *pubsub.Service
|
|
||||||
cleanup *task.Periodic
|
|
||||||
reqID uint32
|
|
||||||
name string
|
|
||||||
destination net.Destination
|
|
||||||
session quic.Session
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
|
||||||
func NewQUICNameServer(url *url.URL) (*QUICNameServer, error) {
|
|
||||||
newError("DNS: created Local DNS-over-QUIC client for ", url.String()).AtInfo().WriteToLog()
|
|
||||||
|
|
||||||
var err error
|
|
||||||
port := net.Port(784)
|
|
||||||
if url.Port() != "" {
|
|
||||||
port, err = net.PortFromString(url.Port())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dest := net.UDPDestination(net.DomainAddress(url.Hostname()), port)
|
|
||||||
|
|
||||||
s := &QUICNameServer{
|
|
||||||
ips: make(map[string]record),
|
|
||||||
pub: pubsub.NewService(),
|
|
||||||
name: url.String(),
|
|
||||||
destination: dest,
|
|
||||||
}
|
|
||||||
s.cleanup = &task.Periodic{
|
|
||||||
Interval: time.Minute,
|
|
||||||
Execute: s.Cleanup,
|
|
||||||
}
|
|
||||||
|
|
||||||
return s, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Name returns client name
|
|
||||||
func (s *QUICNameServer) Name() string {
|
|
||||||
return s.name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup clears expired items from cache
|
|
||||||
func (s *QUICNameServer) Cleanup() error {
|
|
||||||
now := time.Now()
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
if len(s.ips) == 0 {
|
|
||||||
return newError("nothing to do. stopping...")
|
|
||||||
}
|
|
||||||
|
|
||||||
for domain, record := range s.ips {
|
|
||||||
if record.A != nil && record.A.Expire.Before(now) {
|
|
||||||
record.A = nil
|
|
||||||
}
|
|
||||||
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
|
|
||||||
record.AAAA = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if record.A == nil && record.AAAA == nil {
|
|
||||||
newError(s.name, " cleanup ", domain).AtDebug().WriteToLog()
|
|
||||||
delete(s.ips, domain)
|
|
||||||
} else {
|
|
||||||
s.ips[domain] = record
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(s.ips) == 0 {
|
|
||||||
s.ips = make(map[string]record)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *QUICNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
|
|
||||||
elapsed := time.Since(req.start)
|
|
||||||
|
|
||||||
s.Lock()
|
|
||||||
rec := s.ips[req.domain]
|
|
||||||
updated := false
|
|
||||||
|
|
||||||
switch req.reqType {
|
|
||||||
case dnsmessage.TypeA:
|
|
||||||
if isNewer(rec.A, ipRec) {
|
|
||||||
rec.A = ipRec
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
case dnsmessage.TypeAAAA:
|
|
||||||
addr := make([]net.Address, 0)
|
|
||||||
for _, ip := range ipRec.IP {
|
|
||||||
if len(ip.IP()) == net.IPv6len {
|
|
||||||
addr = append(addr, ip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ipRec.IP = addr
|
|
||||||
if isNewer(rec.AAAA, ipRec) {
|
|
||||||
rec.AAAA = ipRec
|
|
||||||
updated = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newError(s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed).AtInfo().WriteToLog()
|
|
||||||
|
|
||||||
if updated {
|
|
||||||
s.ips[req.domain] = rec
|
|
||||||
}
|
|
||||||
switch req.reqType {
|
|
||||||
case dnsmessage.TypeA:
|
|
||||||
s.pub.Publish(req.domain+"4", nil)
|
|
||||||
case dnsmessage.TypeAAAA:
|
|
||||||
s.pub.Publish(req.domain+"6", nil)
|
|
||||||
}
|
|
||||||
s.Unlock()
|
|
||||||
common.Must(s.cleanup.Start())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *QUICNameServer) newReqID() uint16 {
|
|
||||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
|
||||||
newError(s.name, " querying: ", domain).AtInfo().WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
|
||||||
|
|
||||||
var deadline time.Time
|
|
||||||
if d, ok := ctx.Deadline(); ok {
|
|
||||||
deadline = d
|
|
||||||
} else {
|
|
||||||
deadline = time.Now().Add(time.Second * 5)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, req := range reqs {
|
|
||||||
go func(r *dnsRequest) {
|
|
||||||
// generate new context for each req, using same context
|
|
||||||
// may cause reqs all aborted if any one encounter an error
|
|
||||||
dnsCtx := context.Background()
|
|
||||||
|
|
||||||
// reserve internal dns server requested Inbound
|
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
|
||||||
dnsCtx = session.ContextWithInbound(dnsCtx, inbound)
|
|
||||||
}
|
|
||||||
dnsCtx = session.ContextWithContent(dnsCtx, &session.Content{
|
|
||||||
Protocol: "quic",
|
|
||||||
SkipDNSResolve: true,
|
|
||||||
})
|
|
||||||
dnsCtx = log.ContextWithAccessMessage(dnsCtx, &log.AccessMessage{
|
|
||||||
From: "DoQ",
|
|
||||||
To: s.name,
|
|
||||||
Status: log.AccessAccepted,
|
|
||||||
Reason: "",
|
|
||||||
})
|
|
||||||
|
|
||||||
var cancel context.CancelFunc
|
|
||||||
dnsCtx, cancel = context.WithDeadline(dnsCtx, deadline)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
b, err := dns.PackMessage(r.msg)
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to pack dns query").Base(err).AtError().WriteToLog()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
conn, err := s.openStream(dnsCtx)
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to open quic session").Base(err).AtError().WriteToLog()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = conn.Write(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to send query").Base(err).AtError().WriteToLog()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = conn.Close()
|
|
||||||
|
|
||||||
respBuf := buf.New()
|
|
||||||
defer respBuf.Release()
|
|
||||||
n, err := respBuf.ReadFrom(conn)
|
|
||||||
if err != nil && n == 0 {
|
|
||||||
newError("failed to read response").Base(err).AtError().WriteToLog()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rec, err := parseResponse(respBuf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to handle response").Base(err).AtError().WriteToLog()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.updateIP(r, rec)
|
|
||||||
}(req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *QUICNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
|
||||||
s.RLock()
|
|
||||||
record, found := s.ips[domain]
|
|
||||||
s.RUnlock()
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return nil, errRecordNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
var ips []net.Address
|
|
||||||
var lastErr error
|
|
||||||
if option.IPv6Enable && record.AAAA != nil && record.AAAA.RCode == dnsmessage.RCodeSuccess {
|
|
||||||
aaaa, err := record.AAAA.getIPs()
|
|
||||||
if err != nil {
|
|
||||||
lastErr = err
|
|
||||||
}
|
|
||||||
ips = append(ips, aaaa...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if option.IPv4Enable && record.A != nil && record.A.RCode == dnsmessage.RCodeSuccess {
|
|
||||||
a, err := record.A.getIPs()
|
|
||||||
if err != nil {
|
|
||||||
lastErr = err
|
|
||||||
}
|
|
||||||
ips = append(ips, a...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ips) > 0 {
|
|
||||||
return toNetIP(ips)
|
|
||||||
}
|
|
||||||
|
|
||||||
if lastErr != nil {
|
|
||||||
return nil, lastErr
|
|
||||||
}
|
|
||||||
|
|
||||||
if (option.IPv4Enable && record.A != nil) || (option.IPv6Enable && record.AAAA != nil) {
|
|
||||||
return nil, dns_feature.ErrEmptyResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errRecordNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
// QueryIP is called from dns.Server->queryIPTimeout
|
|
||||||
func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) {
|
|
||||||
fqdn := Fqdn(domain)
|
|
||||||
|
|
||||||
if cs == CacheStrategy_Cache_DISABLE {
|
|
||||||
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog()
|
|
||||||
} else {
|
|
||||||
ips, err := s.findIPsForDomain(fqdn, option)
|
|
||||||
if err != errRecordNotFound {
|
|
||||||
if cs == CacheStrategy_Cache_NOERROR && err == nil {
|
|
||||||
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
|
||||||
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
|
|
||||||
return ips, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ipv4 and ipv6 belong to different subscription groups
|
|
||||||
var sub4, sub6 *pubsub.Subscriber
|
|
||||||
if option.IPv4Enable {
|
|
||||||
sub4 = s.pub.Subscribe(fqdn + "4")
|
|
||||||
defer sub4.Close()
|
|
||||||
}
|
|
||||||
if option.IPv6Enable {
|
|
||||||
sub6 = s.pub.Subscribe(fqdn + "6")
|
|
||||||
defer sub6.Close()
|
|
||||||
}
|
|
||||||
done := make(chan interface{})
|
|
||||||
go func() {
|
|
||||||
if sub4 != nil {
|
|
||||||
select {
|
|
||||||
case <-sub4.Wait():
|
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sub6 != nil {
|
|
||||||
select {
|
|
||||||
case <-sub6.Wait():
|
|
||||||
case <-ctx.Done():
|
|
||||||
}
|
|
||||||
}
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
s.sendQuery(ctx, fqdn, clientIP, option)
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
for {
|
|
||||||
ips, err := s.findIPsForDomain(fqdn, option)
|
|
||||||
if err != errRecordNotFound {
|
|
||||||
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSQueried, time.Since(start), err})
|
|
||||||
return ips, err
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, ctx.Err()
|
|
||||||
case <-done:
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func isActive(s quic.Session) bool {
|
|
||||||
select {
|
|
||||||
case <-s.Context().Done():
|
|
||||||
return false
|
|
||||||
default:
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *QUICNameServer) getSession() (quic.Session, error) {
|
|
||||||
var session quic.Session
|
|
||||||
s.RLock()
|
|
||||||
session = s.session
|
|
||||||
if session != nil && isActive(session) {
|
|
||||||
s.RUnlock()
|
|
||||||
return session, nil
|
|
||||||
}
|
|
||||||
if session != nil {
|
|
||||||
// we're recreating the session, let's create a new one
|
|
||||||
_ = session.CloseWithError(0, "")
|
|
||||||
}
|
|
||||||
s.RUnlock()
|
|
||||||
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
var err error
|
|
||||||
session, err = s.openSession()
|
|
||||||
if err != nil {
|
|
||||||
// This does not look too nice, but QUIC (or maybe quic-go)
|
|
||||||
// doesn't seem stable enough.
|
|
||||||
// Maybe retransmissions aren't fully implemented in quic-go?
|
|
||||||
// Anyways, the simple solution is to make a second try when
|
|
||||||
// it fails to open the QUIC session.
|
|
||||||
session, err = s.openSession()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.session = session
|
|
||||||
return session, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *QUICNameServer) openSession() (quic.Session, error) {
|
|
||||||
tlsConfig := tls.Config{}
|
|
||||||
quicConfig := &quic.Config{}
|
|
||||||
|
|
||||||
session, err := quic.DialAddrContext(context.Background(), s.destination.NetAddr(), tlsConfig.GetTLSConfig(tls.WithNextProto("http/1.1", http2.NextProtoTLS, NextProtoDQ)), quicConfig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return session, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *QUICNameServer) openStream(ctx context.Context) (quic.Stream, error) {
|
|
||||||
session, err := s.getSession()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// open a new stream
|
|
||||||
return session.OpenStreamSync(ctx)
|
|
||||||
}
|
|
@@ -1,60 +0,0 @@
|
|||||||
package dns_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestQUICNameServer(t *testing.T) {
|
|
||||||
url, err := url.Parse("quic://dns.adguard.com")
|
|
||||||
common.Must(err)
|
|
||||||
s, err := NewQUICNameServer(url)
|
|
||||||
common.Must(err)
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: true,
|
|
||||||
}, CacheStrategy_Cache_ALL)
|
|
||||||
cancel()
|
|
||||||
common.Must(err)
|
|
||||||
if len(ips) == 0 {
|
|
||||||
t.Error("expect some ips, but got 0")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestQUICNameServerWithCache(t *testing.T) {
|
|
||||||
url, err := url.Parse("quic://dns.adguard.com")
|
|
||||||
common.Must(err)
|
|
||||||
s, err := NewQUICNameServer(url)
|
|
||||||
common.Must(err)
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: true,
|
|
||||||
}, CacheStrategy_Cache_ALL)
|
|
||||||
cancel()
|
|
||||||
common.Must(err)
|
|
||||||
if len(ips) == 0 {
|
|
||||||
t.Error("expect some ips, but got 0")
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
|
||||||
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: true,
|
|
||||||
}, CacheStrategy_Cache_ALL)
|
|
||||||
cancel()
|
|
||||||
common.Must(err)
|
|
||||||
if r := cmp.Diff(ips2, ips); r != "" {
|
|
||||||
t.Fatal(r)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -7,17 +7,17 @@ import (
|
|||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
. "github.com/xtls/xray-core/app/dns"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLocalNameServer(t *testing.T) {
|
func TestLocalNameServer(t *testing.T) {
|
||||||
s := NewLocalNameServer()
|
s := NewLocalNameServer()
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
}, CacheStrategy_Cache_ALL)
|
FakeEnable: false,
|
||||||
|
})
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
@@ -1,16 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/features/dns"
|
|
||||||
|
|
||||||
func isIPQuery(o *dns.IPOption) bool {
|
|
||||||
return o.IPv4Enable || o.IPv6Enable
|
|
||||||
}
|
|
||||||
|
|
||||||
func canQueryOnClient(o *dns.IPOption, c *Client) bool {
|
|
||||||
isIPClient := !(c.Name() == FakeDNSName)
|
|
||||||
return isIPClient && isIPQuery(o)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isQuery(o *dns.IPOption) bool {
|
|
||||||
return !(o.IPv4Enable || o.IPv6Enable || o.FakeEnable)
|
|
||||||
}
|
|
437
app/dns/server.go
Normal file
437
app/dns/server.go
Normal file
@@ -0,0 +1,437 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/app/router"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
|
"github.com/xtls/xray-core/common/uuid"
|
||||||
|
core "github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
|
"github.com/xtls/xray-core/features/routing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Server is a DNS rely server.
|
||||||
|
type Server struct {
|
||||||
|
sync.Mutex
|
||||||
|
hosts *StaticHosts
|
||||||
|
clientIP net.IP
|
||||||
|
clients []Client // clientIdx -> Client
|
||||||
|
ctx context.Context
|
||||||
|
ipIndexMap []*MultiGeoIPMatcher // clientIdx -> *MultiGeoIPMatcher
|
||||||
|
domainRules [][]string // clientIdx -> domainRuleIdx -> DomainRule
|
||||||
|
domainMatcher strmatcher.IndexMatcher
|
||||||
|
matcherInfos []DomainMatcherInfo // matcherIdx -> DomainMatcherInfo
|
||||||
|
tag string
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
|
||||||
|
type DomainMatcherInfo struct {
|
||||||
|
clientIdx uint16
|
||||||
|
domainRuleIdx uint16
|
||||||
|
}
|
||||||
|
|
||||||
|
// MultiGeoIPMatcher for match
|
||||||
|
type MultiGeoIPMatcher struct {
|
||||||
|
matchers []*router.GeoIPMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
var errExpectedIPNonMatch = errors.New("expectIPs not match")
|
||||||
|
|
||||||
|
// Match check ip match
|
||||||
|
func (c *MultiGeoIPMatcher) Match(ip net.IP) bool {
|
||||||
|
for _, matcher := range c.matchers {
|
||||||
|
if matcher.Match(ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// HasMatcher check has matcher
|
||||||
|
func (c *MultiGeoIPMatcher) HasMatcher() bool {
|
||||||
|
return len(c.matchers) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func generateRandomTag() string {
|
||||||
|
id := uuid.New()
|
||||||
|
return "xray.system." + id.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new DNS server with given configuration.
|
||||||
|
func New(ctx context.Context, config *Config) (*Server, error) {
|
||||||
|
server := &Server{
|
||||||
|
clients: make([]Client, 0, len(config.NameServers)+len(config.NameServer)),
|
||||||
|
ctx: ctx,
|
||||||
|
tag: config.Tag,
|
||||||
|
}
|
||||||
|
if server.tag == "" {
|
||||||
|
server.tag = generateRandomTag()
|
||||||
|
}
|
||||||
|
if len(config.ClientIp) > 0 {
|
||||||
|
if len(config.ClientIp) != net.IPv4len && len(config.ClientIp) != net.IPv6len {
|
||||||
|
return nil, newError("unexpected IP length", len(config.ClientIp))
|
||||||
|
}
|
||||||
|
server.clientIP = net.IP(config.ClientIp)
|
||||||
|
}
|
||||||
|
|
||||||
|
hosts, err := NewStaticHosts(config.StaticHosts, config.Hosts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to create hosts").Base(err)
|
||||||
|
}
|
||||||
|
server.hosts = hosts
|
||||||
|
|
||||||
|
addNameServer := func(ns *NameServer) int {
|
||||||
|
endpoint := ns.Address
|
||||||
|
address := endpoint.Address.AsAddress()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case address.Family().IsDomain() && address.Domain() == "localhost":
|
||||||
|
server.clients = append(server.clients, NewLocalNameServer())
|
||||||
|
// Priotize local domains with specific TLDs or without any dot to local DNS
|
||||||
|
// References:
|
||||||
|
// https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml
|
||||||
|
// https://unix.stackexchange.com/questions/92441/whats-the-difference-between-local-home-and-lan
|
||||||
|
localTLDsAndDotlessDomains := []*NameServer_PriorityDomain{
|
||||||
|
{Type: DomainMatchingType_Regex, Domain: "^[^.]+$"}, // This will only match domains without any dot
|
||||||
|
{Type: DomainMatchingType_Subdomain, Domain: "local"},
|
||||||
|
{Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
|
||||||
|
{Type: DomainMatchingType_Subdomain, Domain: "localhost"},
|
||||||
|
{Type: DomainMatchingType_Subdomain, Domain: "lan"},
|
||||||
|
{Type: DomainMatchingType_Subdomain, Domain: "home.arpa"},
|
||||||
|
{Type: DomainMatchingType_Subdomain, Domain: "example"},
|
||||||
|
{Type: DomainMatchingType_Subdomain, Domain: "invalid"},
|
||||||
|
{Type: DomainMatchingType_Subdomain, Domain: "test"},
|
||||||
|
}
|
||||||
|
ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
|
||||||
|
|
||||||
|
case address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https+local://"):
|
||||||
|
// URI schemed string treated as domain
|
||||||
|
// DOH Local mode
|
||||||
|
u, err := url.Parse(address.Domain())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(newError("DNS config error").Base(err))
|
||||||
|
}
|
||||||
|
server.clients = append(server.clients, NewDoHLocalNameServer(u, server.clientIP))
|
||||||
|
|
||||||
|
case address.Family().IsDomain() && strings.HasPrefix(address.Domain(), "https://"):
|
||||||
|
// DOH Remote mode
|
||||||
|
u, err := url.Parse(address.Domain())
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(newError("DNS config error").Base(err))
|
||||||
|
}
|
||||||
|
idx := len(server.clients)
|
||||||
|
server.clients = append(server.clients, nil)
|
||||||
|
|
||||||
|
// need the core dispatcher, register DOHClient at callback
|
||||||
|
common.Must(core.RequireFeatures(ctx, func(d routing.Dispatcher) {
|
||||||
|
c, err := NewDoHNameServer(u, d, server.clientIP)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalln(newError("DNS config error").Base(err))
|
||||||
|
}
|
||||||
|
server.clients[idx] = c
|
||||||
|
}))
|
||||||
|
|
||||||
|
case address.Family().IsDomain() && address.Domain() == "fakedns":
|
||||||
|
server.clients = append(server.clients, NewFakeDNSServer())
|
||||||
|
|
||||||
|
default:
|
||||||
|
// UDP classic DNS mode
|
||||||
|
dest := endpoint.AsDestination()
|
||||||
|
if dest.Network == net.Network_Unknown {
|
||||||
|
dest.Network = net.Network_UDP
|
||||||
|
}
|
||||||
|
if dest.Network == net.Network_UDP {
|
||||||
|
idx := len(server.clients)
|
||||||
|
server.clients = append(server.clients, nil)
|
||||||
|
|
||||||
|
common.Must(core.RequireFeatures(ctx, func(d routing.Dispatcher) {
|
||||||
|
server.clients[idx] = NewClassicNameServer(dest, d, server.clientIP)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.ipIndexMap = append(server.ipIndexMap, nil)
|
||||||
|
return len(server.clients) - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.NameServers) > 0 {
|
||||||
|
features.PrintDeprecatedFeatureWarning("simple DNS server")
|
||||||
|
for _, destPB := range config.NameServers {
|
||||||
|
addNameServer(&NameServer{Address: destPB})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(config.NameServer) > 0 {
|
||||||
|
clientIndices := []int{}
|
||||||
|
domainRuleCount := 0
|
||||||
|
for _, ns := range config.NameServer {
|
||||||
|
idx := addNameServer(ns)
|
||||||
|
clientIndices = append(clientIndices, idx)
|
||||||
|
domainRuleCount += len(ns.PrioritizedDomain)
|
||||||
|
}
|
||||||
|
|
||||||
|
domainRules := make([][]string, len(server.clients))
|
||||||
|
domainMatcher := &strmatcher.MatcherGroup{}
|
||||||
|
matcherInfos := make([]DomainMatcherInfo, domainRuleCount+1) // matcher index starts from 1
|
||||||
|
var geoIPMatcherContainer router.GeoIPMatcherContainer
|
||||||
|
for nidx, ns := range config.NameServer {
|
||||||
|
idx := clientIndices[nidx]
|
||||||
|
|
||||||
|
// Establish domain rule matcher
|
||||||
|
rules := []string{}
|
||||||
|
ruleCurr := 0
|
||||||
|
ruleIter := 0
|
||||||
|
for _, domain := range ns.PrioritizedDomain {
|
||||||
|
matcher, err := toStrMatcher(domain.Type, domain.Domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to create prioritized domain").Base(err).AtWarning()
|
||||||
|
}
|
||||||
|
midx := domainMatcher.Add(matcher)
|
||||||
|
if midx >= uint32(len(matcherInfos)) { // This rarely happens according to current matcher's implementation
|
||||||
|
newError("expanding domain matcher info array to size ", midx, " when adding ", matcher).AtDebug().WriteToLog()
|
||||||
|
matcherInfos = append(matcherInfos, make([]DomainMatcherInfo, midx-uint32(len(matcherInfos))+1)...)
|
||||||
|
}
|
||||||
|
info := &matcherInfos[midx]
|
||||||
|
info.clientIdx = uint16(idx)
|
||||||
|
if ruleCurr < len(ns.OriginalRules) {
|
||||||
|
info.domainRuleIdx = uint16(ruleCurr)
|
||||||
|
rule := ns.OriginalRules[ruleCurr]
|
||||||
|
if ruleCurr >= len(rules) {
|
||||||
|
rules = append(rules, rule.Rule)
|
||||||
|
}
|
||||||
|
ruleIter++
|
||||||
|
if ruleIter >= int(rule.Size) {
|
||||||
|
ruleIter = 0
|
||||||
|
ruleCurr++
|
||||||
|
}
|
||||||
|
} else { // No original rule, generate one according to current domain matcher (majorly for compatibility with tests)
|
||||||
|
info.domainRuleIdx = uint16(len(rules))
|
||||||
|
rules = append(rules, matcher.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
domainRules[idx] = rules
|
||||||
|
|
||||||
|
// only add to ipIndexMap if GeoIP is configured
|
||||||
|
if len(ns.Geoip) > 0 {
|
||||||
|
var matchers []*router.GeoIPMatcher
|
||||||
|
for _, geoip := range ns.Geoip {
|
||||||
|
matcher, err := geoIPMatcherContainer.Add(geoip)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to create ip matcher").Base(err).AtWarning()
|
||||||
|
}
|
||||||
|
matchers = append(matchers, matcher)
|
||||||
|
}
|
||||||
|
matcher := &MultiGeoIPMatcher{matchers: matchers}
|
||||||
|
server.ipIndexMap[idx] = matcher
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.domainRules = domainRules
|
||||||
|
server.domainMatcher = domainMatcher
|
||||||
|
server.matcherInfos = matcherInfos
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(server.clients) == 0 {
|
||||||
|
server.clients = append(server.clients, NewLocalNameServer())
|
||||||
|
server.ipIndexMap = append(server.ipIndexMap, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
return server, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type implements common.HasType.
|
||||||
|
func (*Server) Type() interface{} {
|
||||||
|
return dns.ClientType()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start implements common.Runnable.
|
||||||
|
func (s *Server) Start() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close implements common.Closable.
|
||||||
|
func (s *Server) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) IsOwnLink(ctx context.Context) bool {
|
||||||
|
inbound := session.InboundFromContext(ctx)
|
||||||
|
return inbound != nil && inbound.Tag == s.tag
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match check dns ip match geoip
|
||||||
|
func (s *Server) Match(idx int, client Client, domain string, ips []net.IP) ([]net.IP, error) {
|
||||||
|
var matcher *MultiGeoIPMatcher
|
||||||
|
if idx < len(s.ipIndexMap) {
|
||||||
|
matcher = s.ipIndexMap[idx]
|
||||||
|
}
|
||||||
|
if matcher == nil {
|
||||||
|
return ips, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !matcher.HasMatcher() {
|
||||||
|
newError("domain ", domain, " server has no valid matcher: ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
|
||||||
|
return ips, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
newIps := []net.IP{}
|
||||||
|
for _, ip := range ips {
|
||||||
|
if matcher.Match(ip) {
|
||||||
|
newIps = append(newIps, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(newIps) == 0 {
|
||||||
|
return nil, errExpectedIPNonMatch
|
||||||
|
}
|
||||||
|
newError("domain ", domain, " expectIPs ", newIps, " matched at server ", client.Name(), " idx:", idx).AtDebug().WriteToLog()
|
||||||
|
return newIps, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) queryIPTimeout(idx int, client Client, domain string, option dns.IPOption) ([]net.IP, error) {
|
||||||
|
ctx, cancel := context.WithTimeout(s.ctx, time.Second*4)
|
||||||
|
if len(s.tag) > 0 {
|
||||||
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
|
Tag: s.tag,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ips, err := client.QueryIP(ctx, domain, option)
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return ips, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ips, err = s.Match(idx, client, domain, ips)
|
||||||
|
return ips, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) lookupStatic(domain string, option dns.IPOption, depth int32) []net.Address {
|
||||||
|
ips := s.hosts.LookupIP(domain, option)
|
||||||
|
if ips == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if ips[0].Family().IsDomain() && depth < 5 {
|
||||||
|
if newIPs := s.lookupStatic(ips[0].Domain(), option, depth+1); newIPs != nil {
|
||||||
|
return newIPs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ips
|
||||||
|
}
|
||||||
|
|
||||||
|
func toNetIP(ips []net.Address) []net.IP {
|
||||||
|
if len(ips) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
netips := make([]net.IP, 0, len(ips))
|
||||||
|
for _, ip := range ips {
|
||||||
|
netips = append(netips, ip.IP())
|
||||||
|
}
|
||||||
|
return netips
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupIP implements dns.Client.
|
||||||
|
func (s *Server) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
|
||||||
|
if domain == "" {
|
||||||
|
return nil, newError("empty domain name")
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize the FQDN form query
|
||||||
|
if strings.HasSuffix(domain, ".") {
|
||||||
|
domain = domain[:len(domain)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
ips := s.lookupStatic(domain, option, 0)
|
||||||
|
if ips != nil && ips[0].Family().IsIP() {
|
||||||
|
newError("returning ", len(ips), " IPs for domain ", domain).WriteToLog()
|
||||||
|
return toNetIP(ips), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if ips != nil && ips[0].Family().IsDomain() {
|
||||||
|
newdomain := ips[0].Domain()
|
||||||
|
newError("domain replaced: ", domain, " -> ", newdomain).WriteToLog()
|
||||||
|
domain = newdomain
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastErr error
|
||||||
|
var matchedClient Client
|
||||||
|
if s.domainMatcher != nil {
|
||||||
|
indices := s.domainMatcher.Match(domain)
|
||||||
|
domainRules := []string{}
|
||||||
|
matchingDNS := []string{}
|
||||||
|
for _, idx := range indices {
|
||||||
|
info := s.matcherInfos[idx]
|
||||||
|
rule := s.domainRules[info.clientIdx][info.domainRuleIdx]
|
||||||
|
domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", rule, info.clientIdx))
|
||||||
|
matchingDNS = append(matchingDNS, s.clients[info.clientIdx].Name())
|
||||||
|
}
|
||||||
|
if len(domainRules) > 0 {
|
||||||
|
newError("domain ", domain, " matches following rules: ", domainRules).AtDebug().WriteToLog()
|
||||||
|
}
|
||||||
|
if len(matchingDNS) > 0 {
|
||||||
|
newError("domain ", domain, " uses following DNS first: ", matchingDNS).AtDebug().WriteToLog()
|
||||||
|
}
|
||||||
|
for _, idx := range indices {
|
||||||
|
clientIdx := int(s.matcherInfos[idx].clientIdx)
|
||||||
|
matchedClient = s.clients[clientIdx]
|
||||||
|
if !option.FakeEnable && strings.EqualFold(matchedClient.Name(), "FakeDNS") {
|
||||||
|
newError("skip DNS resolution for domain ", domain, " at server ", matchedClient.Name()).AtDebug().WriteToLog()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ips, err := s.queryIPTimeout(clientIdx, matchedClient, domain, option)
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return ips, nil
|
||||||
|
}
|
||||||
|
if err == dns.ErrEmptyResponse {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
newError("failed to lookup ip for domain ", domain, " at server ", matchedClient.Name()).Base(err).WriteToLog()
|
||||||
|
lastErr = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for idx, client := range s.clients {
|
||||||
|
if client == matchedClient {
|
||||||
|
newError("domain ", domain, " at server ", client.Name(), " idx:", idx, " already lookup failed, just ignore").AtDebug().WriteToLog()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
||||||
|
newError("skip DNS resolution for domain ", domain, " at server ", client.Name()).AtDebug().WriteToLog()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ips, err := s.queryIPTimeout(idx, client, domain, option)
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return ips, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
|
||||||
|
lastErr = err
|
||||||
|
}
|
||||||
|
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, newError("returning nil for domain ", domain).Base(lastErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
|
return New(ctx, config.(*Config))
|
||||||
|
}))
|
||||||
|
}
|
@@ -12,9 +12,8 @@ import (
|
|||||||
"github.com/xtls/xray-core/app/policy"
|
"github.com/xtls/xray-core/app/policy"
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
_ "github.com/xtls/xray-core/app/proxyman/outbound"
|
_ "github.com/xtls/xray-core/app/proxyman/outbound"
|
||||||
|
"github.com/xtls/xray-core/app/router"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
@@ -155,7 +154,11 @@ func TestUDPServerSubnet(t *testing.T) {
|
|||||||
|
|
||||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
|
|
||||||
ips, err := client.LookupIP("google.com")
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -210,7 +213,11 @@ func TestUDPServer(t *testing.T) {
|
|||||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, err := client.LookupIP("google.com")
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -221,7 +228,11 @@ func TestUDPServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, err := client.LookupIP("facebook.com")
|
ips, err := client.LookupIP("facebook.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -232,7 +243,11 @@ func TestUDPServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
_, err := client.LookupIP("notexist.google.com")
|
_, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("nil error")
|
t.Fatal("nil error")
|
||||||
}
|
}
|
||||||
@@ -242,8 +257,11 @@ func TestUDPServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
clientv6 := client.(feature_dns.IPv6Lookup)
|
ips, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{
|
||||||
ips, err := clientv6.LookupIPv6("ipv4only.google.com")
|
IPv4Enable: false,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != feature_dns.ErrEmptyResponse {
|
if err != feature_dns.ErrEmptyResponse {
|
||||||
t.Fatal("error: ", err)
|
t.Fatal("error: ", err)
|
||||||
}
|
}
|
||||||
@@ -255,7 +273,11 @@ func TestUDPServer(t *testing.T) {
|
|||||||
dnsServer.Shutdown()
|
dnsServer.Shutdown()
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, err := client.LookupIP("google.com")
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -304,10 +326,10 @@ func TestPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*domain.Domain{
|
PrioritizedDomain: []*NameServer_PriorityDomain{
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Full,
|
Type: DomainMatchingType_Full,
|
||||||
Value: "google.com",
|
Domain: "google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -332,7 +354,11 @@ func TestPrioritizedDomain(t *testing.T) {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, err := client.LookupIP("google.com")
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -391,9 +417,12 @@ func TestUDPServerIPv6(t *testing.T) {
|
|||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
client6 := client.(feature_dns.IPv6Lookup)
|
|
||||||
{
|
{
|
||||||
ips, err := client6.LookupIPv6("ipv6.google.com")
|
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: false,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -433,7 +462,7 @@ func TestStaticHostDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
StaticHosts: []*Config_HostMapping{
|
StaticHosts: []*Config_HostMapping{
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Full,
|
Type: DomainMatchingType_Full,
|
||||||
Domain: "example.com",
|
Domain: "example.com",
|
||||||
ProxiedDomain: "google.com",
|
ProxiedDomain: "google.com",
|
||||||
},
|
},
|
||||||
@@ -456,7 +485,11 @@ func TestStaticHostDomain(t *testing.T) {
|
|||||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, err := client.LookupIP("example.com")
|
ips, err := client.LookupIP("example.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -497,10 +530,10 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
Geoip: []*geoip.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{
|
{
|
||||||
CountryCode: "local",
|
CountryCode: "local",
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{
|
{
|
||||||
// inner ip, will not match
|
// inner ip, will not match
|
||||||
Ip: []byte{192, 168, 11, 1},
|
Ip: []byte{192, 168, 11, 1},
|
||||||
@@ -521,10 +554,10 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
Geoip: []*geoip.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{
|
{
|
||||||
CountryCode: "test",
|
CountryCode: "test",
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{
|
{
|
||||||
Ip: []byte{8, 8, 8, 8},
|
Ip: []byte{8, 8, 8, 8},
|
||||||
Prefix: 32,
|
Prefix: 32,
|
||||||
@@ -533,7 +566,7 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
CountryCode: "test",
|
CountryCode: "test",
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{
|
{
|
||||||
Ip: []byte{8, 8, 8, 4},
|
Ip: []byte{8, 8, 8, 4},
|
||||||
Prefix: 32,
|
Prefix: 32,
|
||||||
@@ -563,7 +596,11 @@ func TestIPMatch(t *testing.T) {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, err := client.LookupIP("google.com")
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -617,14 +654,14 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*domain.Domain{
|
PrioritizedDomain: []*NameServer_PriorityDomain{
|
||||||
// Equivalent of dotless:localhost
|
// Equivalent of dotless:localhost
|
||||||
{Type: domain.MatchingType_Regex, Value: "^[^.]*localhost[^.]*$"},
|
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
|
||||||
},
|
},
|
||||||
Geoip: []*geoip.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // Will match localhost, localhost-a and localhost-b,
|
{ // Will match localhost, localhost-a and localhost-b,
|
||||||
CountryCode: "local",
|
CountryCode: "local",
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{127, 0, 0, 2}, Prefix: 32},
|
{Ip: []byte{127, 0, 0, 2}, Prefix: 32},
|
||||||
{Ip: []byte{127, 0, 0, 3}, Prefix: 32},
|
{Ip: []byte{127, 0, 0, 3}, Prefix: 32},
|
||||||
{Ip: []byte{127, 0, 0, 4}, Prefix: 32},
|
{Ip: []byte{127, 0, 0, 4}, Prefix: 32},
|
||||||
@@ -642,22 +679,22 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*domain.Domain{
|
PrioritizedDomain: []*NameServer_PriorityDomain{
|
||||||
// Equivalent of dotless: and domain:local
|
// Equivalent of dotless: and domain:local
|
||||||
{Type: domain.MatchingType_Regex, Value: "^[^.]*$"},
|
{Type: DomainMatchingType_Regex, Domain: "^[^.]*$"},
|
||||||
{Type: domain.MatchingType_Subdomain, Value: "local"},
|
{Type: DomainMatchingType_Subdomain, Domain: "local"},
|
||||||
{Type: domain.MatchingType_Subdomain, Value: "localdomain"},
|
{Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StaticHosts: []*Config_HostMapping{
|
StaticHosts: []*Config_HostMapping{
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Full,
|
Type: DomainMatchingType_Full,
|
||||||
Domain: "hostnamestatic",
|
Domain: "hostnamestatic",
|
||||||
Ip: [][]byte{{127, 0, 0, 53}},
|
Ip: [][]byte{{127, 0, 0, 53}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Full,
|
Type: DomainMatchingType_Full,
|
||||||
Domain: "hostnamealias",
|
Domain: "hostnamealias",
|
||||||
ProxiedDomain: "hostname.localdomain",
|
ProxiedDomain: "hostname.localdomain",
|
||||||
},
|
},
|
||||||
@@ -682,7 +719,11 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
{ // Will match dotless:
|
{ // Will match dotless:
|
||||||
ips, err := client.LookupIP("hostname")
|
ips, err := client.LookupIP("hostname", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -693,7 +734,11 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match domain:local
|
{ // Will match domain:local
|
||||||
ips, err := client.LookupIP("hostname.local")
|
ips, err := client.LookupIP("hostname.local", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -704,7 +749,11 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match static ip
|
{ // Will match static ip
|
||||||
ips, err := client.LookupIP("hostnamestatic")
|
ips, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -715,7 +764,11 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match domain replacing
|
{ // Will match domain replacing
|
||||||
ips, err := client.LookupIP("hostnamealias")
|
ips, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -726,7 +779,11 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
|
{ // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
|
||||||
ips, err := client.LookupIP("localhost")
|
ips, err := client.LookupIP("localhost", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -737,7 +794,11 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
||||||
ips, err := client.LookupIP("localhost-a")
|
ips, err := client.LookupIP("localhost-a", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -748,7 +809,11 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
||||||
ips, err := client.LookupIP("localhost-b")
|
ips, err := client.LookupIP("localhost-b", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -759,7 +824,11 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match dotless:
|
{ // Will match dotless:
|
||||||
ips, err := client.LookupIP("Mijia Cloud")
|
ips, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -813,15 +882,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*domain.Domain{
|
PrioritizedDomain: []*NameServer_PriorityDomain{
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Subdomain,
|
Type: DomainMatchingType_Subdomain,
|
||||||
Value: "google.com",
|
Domain: "google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Geoip: []*geoip.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // Will only match 8.8.8.8 and 8.8.4.4
|
{ // Will only match 8.8.8.8 and 8.8.4.4
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
||||||
{Ip: []byte{8, 8, 4, 4}, Prefix: 32},
|
{Ip: []byte{8, 8, 4, 4}, Prefix: 32},
|
||||||
},
|
},
|
||||||
@@ -838,15 +907,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*domain.Domain{
|
PrioritizedDomain: []*NameServer_PriorityDomain{
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Subdomain,
|
Type: DomainMatchingType_Subdomain,
|
||||||
Value: "google.com",
|
Domain: "google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Geoip: []*geoip.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // Will match 8.8.8.8 and 8.8.8.7, etc
|
{ // Will match 8.8.8.8 and 8.8.8.7, etc
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
|
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -862,15 +931,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*domain.Domain{
|
PrioritizedDomain: []*NameServer_PriorityDomain{
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Subdomain,
|
Type: DomainMatchingType_Subdomain,
|
||||||
Value: "api.google.com",
|
Domain: "api.google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Geoip: []*geoip.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // Will only match 8.8.7.7 (api.google.com)
|
{ // Will only match 8.8.7.7 (api.google.com)
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
|
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -886,15 +955,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*domain.Domain{
|
PrioritizedDomain: []*NameServer_PriorityDomain{
|
||||||
{
|
{
|
||||||
Type: domain.MatchingType_Full,
|
Type: DomainMatchingType_Full,
|
||||||
Value: "v2.api.google.com",
|
Domain: "v2.api.google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Geoip: []*geoip.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // Will only match 8.8.7.8 (v2.api.google.com)
|
{ // Will only match 8.8.7.8 (v2.api.google.com)
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
|
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -921,7 +990,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
{ // Will match server 1,2 and server 1 returns expected ip
|
{ // Will match server 1,2 and server 1 returns expected ip
|
||||||
ips, err := client.LookupIP("google.com")
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -932,8 +1005,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
|
{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
|
||||||
clientv4 := client.(feature_dns.IPv4Lookup)
|
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
||||||
ips, err := clientv4.LookupIPv4("ipv6.google.com")
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: false,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -944,7 +1020,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match server 3,1,2 and server 3 returns expected one
|
{ // Will match server 3,1,2 and server 3 returns expected one
|
||||||
ips, err := client.LookupIP("api.google.com")
|
ips, err := client.LookupIP("api.google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
||||||
@@ -955,7 +1035,11 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match server 4,3,1,2 and server 4 returns expected one
|
{ // Will match server 4,3,1,2 and server 4 returns expected one
|
||||||
ips, err := client.LookupIP("v2.api.google.com")
|
ips, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("unexpected error: ", err)
|
t.Fatal("unexpected error: ", err)
|
||||||
}
|
}
|
@@ -7,6 +7,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -18,7 +20,6 @@ import (
|
|||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet/udp"
|
"github.com/xtls/xray-core/transport/internet/udp"
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClassicNameServer struct {
|
type ClassicNameServer struct {
|
||||||
@@ -31,10 +32,10 @@ type ClassicNameServer struct {
|
|||||||
udpServer *udp.Dispatcher
|
udpServer *udp.Dispatcher
|
||||||
cleanup *task.Periodic
|
cleanup *task.Periodic
|
||||||
reqID uint32
|
reqID uint32
|
||||||
|
clientIP net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClassicNameServer creates udp server object for remote resolving.
|
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, clientIP net.IP) *ClassicNameServer {
|
||||||
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher) *ClassicNameServer {
|
|
||||||
// default to 53 if unspecific
|
// default to 53 if unspecific
|
||||||
if address.Port == 0 {
|
if address.Port == 0 {
|
||||||
address.Port = net.Port(53)
|
address.Port = net.Port(53)
|
||||||
@@ -44,6 +45,7 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
|
|||||||
address: address,
|
address: address,
|
||||||
ips: make(map[string]record),
|
ips: make(map[string]record),
|
||||||
requests: make(map[uint16]dnsRequest),
|
requests: make(map[uint16]dnsRequest),
|
||||||
|
clientIP: clientIP,
|
||||||
pub: pubsub.NewService(),
|
pub: pubsub.NewService(),
|
||||||
name: strings.ToUpper(address.String()),
|
name: strings.ToUpper(address.String()),
|
||||||
}
|
}
|
||||||
@@ -56,12 +58,10 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name implements Server.
|
|
||||||
func (s *ClassicNameServer) Name() string {
|
func (s *ClassicNameServer) Name() string {
|
||||||
return s.name
|
return s.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup clears expired items from cache
|
|
||||||
func (s *ClassicNameServer) Cleanup() error {
|
func (s *ClassicNameServer) Cleanup() error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
s.Lock()
|
s.Lock()
|
||||||
@@ -103,7 +103,6 @@ func (s *ClassicNameServer) Cleanup() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleResponse handles udp response packet from remote DNS server.
|
|
||||||
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
|
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
|
||||||
ipRec, err := parseResponse(packet.Payload.Bytes())
|
ipRec, err := parseResponse(packet.Payload.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -181,10 +180,10 @@ func (s *ClassicNameServer) addPendingRequest(req *dnsRequest) {
|
|||||||
s.requests[id] = *req
|
s.requests[id] = *req
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, option dns_feature.IPOption) {
|
||||||
newError(s.name, " querying DNS for: ", domain).AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
newError(s.name, " querying DNS for: ", domain).AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP))
|
||||||
|
|
||||||
for _, req := range reqs {
|
for _, req := range reqs {
|
||||||
s.addPendingRequest(req)
|
s.addPendingRequest(req)
|
||||||
@@ -193,6 +192,7 @@ func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, client
|
|||||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
udpCtx = session.ContextWithInbound(udpCtx, inbound)
|
udpCtx = session.ContextWithInbound(udpCtx, inbound)
|
||||||
}
|
}
|
||||||
|
|
||||||
udpCtx = session.ContextWithContent(udpCtx, &session.Content{
|
udpCtx = session.ContextWithContent(udpCtx, &session.Content{
|
||||||
Protocol: "dns",
|
Protocol: "dns",
|
||||||
})
|
})
|
||||||
@@ -234,7 +234,7 @@ func (s *ClassicNameServer) findIPsForDomain(domain string, option dns_feature.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
return toNetIP(ips)
|
return toNetIP(ips), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if lastErr != nil {
|
if lastErr != nil {
|
||||||
@@ -245,20 +245,14 @@ func (s *ClassicNameServer) findIPsForDomain(domain string, option dns_feature.I
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, cs CacheStrategy) ([]net.IP, error) {
|
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
||||||
fqdn := Fqdn(domain)
|
fqdn := Fqdn(domain)
|
||||||
|
|
||||||
if cs == CacheStrategy_Cache_DISABLE {
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
newError("DNS cache is disabled. Querying IP for ", domain, " at ", s.name).AtDebug().WriteToLog()
|
if err != errRecordNotFound {
|
||||||
} else {
|
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
||||||
ips, err := s.findIPsForDomain(fqdn, option)
|
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
|
||||||
if err != errRecordNotFound {
|
return ips, err
|
||||||
if cs == CacheStrategy_Cache_NOERROR && err == nil {
|
|
||||||
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
|
||||||
log.Record(&log.DNSLog{s.name, domain, ips, log.DNSCacheHit, 0, err})
|
|
||||||
return ips, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ipv4 and ipv6 belong to different subscription groups
|
// ipv4 and ipv6 belong to different subscription groups
|
||||||
@@ -287,7 +281,7 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP
|
|||||||
}
|
}
|
||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
s.sendQuery(ctx, fqdn, clientIP, option)
|
s.sendQuery(ctx, fqdn, option)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
for {
|
for {
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/log/command/config.proto
|
// source: app/log/command/config.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/log/config.proto
|
// source: app/log/config.proto
|
||||||
|
|
||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
log "github.com/xtls/xray-core/common/log"
|
log "github.com/xtls/xray-core/common/log"
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
@@ -22,10 +21,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type LogType int32
|
type LogType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -134,7 +129,7 @@ func (x *Config) GetErrorLogLevel() log.Severity {
|
|||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ErrorLogLevel
|
return x.ErrorLogLevel
|
||||||
}
|
}
|
||||||
return log.Severity_Unknown
|
return log.Severity(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetErrorLogPath() string {
|
func (x *Config) GetErrorLogPath() string {
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/log"
|
"github.com/xtls/xray-core/app/log"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
clog "github.com/xtls/xray-core/common/log"
|
clog "github.com/xtls/xray-core/common/log"
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/policy/config.proto
|
// source: app/policy/config.proto
|
||||||
|
|
||||||
package policy
|
package policy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type Second struct {
|
type Second struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/proxyman/command/command.proto
|
// source: app/proxyman/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protocol "github.com/xtls/xray-core/common/protocol"
|
protocol "github.com/xtls/xray-core/common/protocol"
|
||||||
serial "github.com/xtls/xray-core/common/serial"
|
serial "github.com/xtls/xray-core/common/serial"
|
||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
@@ -24,10 +23,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type AddUserOperation struct {
|
type AddUserOperation struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@@ -1,12 +1,5 @@
|
|||||||
package proxyman
|
package proxyman
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
|
||||||
|
|
||||||
func (s *AllocationStrategy) GetConcurrencyValue() uint32 {
|
func (s *AllocationStrategy) GetConcurrencyValue() uint32 {
|
||||||
if s == nil || s.Concurrency == nil {
|
if s == nil || s.Concurrency == nil {
|
||||||
return 3
|
return 3
|
||||||
@@ -44,32 +37,3 @@ func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type SniffingMatcher struct {
|
|
||||||
ExDomain *domain.DomainMatcher
|
|
||||||
ExIP *geoip.MultiGeoIPMatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSniffingMatcher(sc *SniffingConfig) (*SniffingMatcher, error) {
|
|
||||||
m := new(SniffingMatcher)
|
|
||||||
|
|
||||||
if sc == nil {
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if sc.DomainsExcluded != nil {
|
|
||||||
exDomain, err := domain.NewDomainMatcher(sc.DomainsExcluded)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to parse domain").Base(err)
|
|
||||||
}
|
|
||||||
m.ExDomain = exDomain
|
|
||||||
}
|
|
||||||
if sc.IpsExcluded != nil {
|
|
||||||
exIP, err := geoip.NewMultiGeoIPMatcher(sc.IpsExcluded, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to parse ip").Base(err)
|
|
||||||
}
|
|
||||||
m.ExIP = exIP
|
|
||||||
}
|
|
||||||
return m, nil
|
|
||||||
}
|
|
||||||
|
@@ -1,15 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.15.6
|
// protoc v3.18.0
|
||||||
// source: app/proxyman/config.proto
|
// source: app/proxyman/config.proto
|
||||||
|
|
||||||
package proxyman
|
package proxyman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
domain "github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
geoip "github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
net "github.com/xtls/xray-core/common/net"
|
net "github.com/xtls/xray-core/common/net"
|
||||||
serial "github.com/xtls/xray-core/common/serial"
|
serial "github.com/xtls/xray-core/common/serial"
|
||||||
internet "github.com/xtls/xray-core/transport/internet"
|
internet "github.com/xtls/xray-core/transport/internet"
|
||||||
@@ -26,10 +23,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type KnownProtocols int32
|
type KnownProtocols int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -242,9 +235,8 @@ type SniffingConfig struct {
|
|||||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||||
// Override target destination if sniff'ed protocol is in the given list.
|
// Override target destination if sniff'ed protocol is in the given list.
|
||||||
// Supported values are "http", "tls", "fakedns".
|
// Supported values are "http", "tls", "fakedns".
|
||||||
DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
||||||
DomainsExcluded []*domain.Domain `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"`
|
DomainsExcluded []string `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"`
|
||||||
IpsExcluded []*geoip.GeoIP `protobuf:"bytes,5,rep,name=ips_excluded,json=ipsExcluded,proto3" json:"ips_excluded,omitempty"`
|
|
||||||
// Whether should only try to sniff metadata without waiting for client input.
|
// Whether should only try to sniff metadata without waiting for client input.
|
||||||
// Can be used to support SMTP like protocol where server send the first message.
|
// Can be used to support SMTP like protocol where server send the first message.
|
||||||
MetadataOnly bool `protobuf:"varint,4,opt,name=metadata_only,json=metadataOnly,proto3" json:"metadata_only,omitempty"`
|
MetadataOnly bool `protobuf:"varint,4,opt,name=metadata_only,json=metadataOnly,proto3" json:"metadata_only,omitempty"`
|
||||||
@@ -296,20 +288,13 @@ func (x *SniffingConfig) GetDestinationOverride() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) GetDomainsExcluded() []*domain.Domain {
|
func (x *SniffingConfig) GetDomainsExcluded() []string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.DomainsExcluded
|
return x.DomainsExcluded
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) GetIpsExcluded() []*geoip.GeoIP {
|
|
||||||
if x != nil {
|
|
||||||
return x.IpsExcluded
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SniffingConfig) GetMetadataOnly() bool {
|
func (x *SniffingConfig) GetMetadataOnly() bool {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.MetadataOnly
|
return x.MetadataOnly
|
||||||
@@ -748,144 +733,133 @@ var File_app_proxyman_config_proto protoreflect.FileDescriptor
|
|||||||
var file_app_proxyman_config_proto_rawDesc = []byte{
|
var file_app_proxyman_config_proto_rawDesc = []byte{
|
||||||
0x0a, 0x19, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63,
|
0x0a, 0x19, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x78, 0x72, 0x61,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x78, 0x72, 0x61,
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x1a, 0x22,
|
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x1a, 0x18,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x64,
|
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||||
0x74, 0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68,
|
0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
|
||||||
0x65, 0x72, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x70,
|
0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15,
|
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x2e,
|
0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f,
|
||||||
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
0x6e, 0x66, 0x69, 0x67, 0x22, 0xae, 0x03, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73,
|
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x3e, 0x0a, 0x04, 0x74,
|
||||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73,
|
0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62,
|
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xae, 0x03, 0x0a, 0x12, 0x41,
|
|
||||||
0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
|
||||||
0x79, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32,
|
|
||||||
0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
|
||||||
0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74,
|
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70,
|
|
||||||
0x65, 0x12, 0x65, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79,
|
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
|
||||||
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
|
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c,
|
|
||||||
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
|
||||||
0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e,
|
|
||||||
0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x59, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72,
|
|
||||||
0x65, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c,
|
||||||
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
|
0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x65, 0x0a, 0x0b, 0x63,
|
||||||
0x65, 0x67, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72,
|
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x65, 0x73, 0x68, 0x1a, 0x35, 0x0a, 0x1d, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f,
|
0x32, 0x43, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72,
|
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53,
|
||||||
0x65, 0x6e, 0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
||||||
0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x31, 0x0a, 0x19, 0x41, 0x6c,
|
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72,
|
||||||
|
0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
||||||
|
0x63, 0x79, 0x12, 0x59, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20,
|
||||||
|
0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
|
||||||
|
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
||||||
|
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
|
||||||
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66,
|
||||||
|
0x72, 0x65, 0x73, 0x68, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x1a, 0x35, 0x0a,
|
||||||
|
0x1d, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
|
||||||
|
0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x14,
|
||||||
|
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76,
|
||||||
|
0x61, 0x6c, 0x75, 0x65, 0x1a, 0x31, 0x0a, 0x19, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
||||||
|
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73,
|
||||||
|
0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
|
||||||
|
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
|
||||||
|
0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52,
|
||||||
|
0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72,
|
||||||
|
0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0xad, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69,
|
||||||
|
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
||||||
|
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||||
|
0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
|
||||||
|
0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
|
||||||
|
0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65,
|
||||||
|
0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73,
|
||||||
|
0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
|
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64,
|
||||||
|
0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c,
|
||||||
|
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||||
|
0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76,
|
||||||
|
0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74,
|
||||||
|
0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78,
|
||||||
|
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50,
|
||||||
|
0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61,
|
||||||
|
0x6e, 0x67, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20,
|
||||||
|
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||||
|
0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
|
0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f,
|
||||||
|
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18,
|
||||||
|
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||||
|
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
|
||||||
|
0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c,
|
||||||
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
0x52, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a,
|
0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10,
|
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||||
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a,
|
0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x08, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0x96, 0x02, 0x0a, 0x0e,
|
0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18,
|
0x12, 0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67,
|
||||||
0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
|
0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74,
|
0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f,
|
||||||
0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
|
||||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65,
|
||||||
0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4d, 0x0a, 0x10, 0x64,
|
0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18,
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e,
|
||||||
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02,
|
||||||
0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61,
|
0x18, 0x01, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
|
||||||
0x69, 0x6e, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
0x64, 0x65, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73,
|
||||||
0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x0c, 0x69, 0x70,
|
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
|
||||||
0x73, 0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||||
0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d,
|
0x6e, 0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x47, 0x65, 0x6f,
|
0x52, 0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||||
0x49, 0x50, 0x52, 0x0b, 0x69, 0x70, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x12,
|
0x67, 0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62,
|
||||||
0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, 0x79,
|
0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
||||||
0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
0x74, 0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f,
|
||||||
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f,
|
0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
|
||||||
0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f,
|
0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||||
0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e,
|
0x52, 0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||||
0x67, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01,
|
0x67, 0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74,
|
||||||
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
|
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e,
|
||||||
0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63,
|
0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03,
|
0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02,
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
|
0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d,
|
||||||
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c,
|
0x0a, 0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72,
|
||||||
0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12,
|
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50,
|
||||||
0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a,
|
||||||
0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72,
|
||||||
0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
|
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||||
0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12,
|
0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73,
|
||||||
0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69,
|
0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a,
|
||||||
0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18,
|
0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
||||||
0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72,
|
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
||||||
0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
|
|
||||||
0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72,
|
|
||||||
0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b,
|
|
||||||
0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18,
|
|
||||||
0x01, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
|
||||||
0x65, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65,
|
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
|
|
||||||
0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52,
|
|
||||||
0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
|
|
||||||
0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f,
|
|
||||||
0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
|
|
||||||
0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73,
|
|
||||||
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
|
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
|
||||||
0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52,
|
|
||||||
0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67,
|
|
||||||
0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
|
||||||
0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54,
|
|
||||||
0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f,
|
|
||||||
0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75,
|
|
||||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a,
|
|
||||||
0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a,
|
|
||||||
0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f,
|
|
||||||
0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f,
|
|
||||||
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
|
||||||
0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
|
||||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
||||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74,
|
0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f,
|
||||||
0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e,
|
0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75,
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03,
|
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x50,
|
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69,
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78,
|
0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d,
|
||||||
0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c,
|
0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
0x22, 0x50, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67,
|
||||||
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70,
|
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
|
||||||
0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75,
|
0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18,
|
||||||
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22,
|
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
||||||
0x50, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43,
|
0x63, 0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
|
0x63, 0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12,
|
0x0a, 0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||||
0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
|
||||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
|
0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
||||||
0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70,
|
||||||
0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a,
|
0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61,
|
||||||
0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
|
|
||||||
0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70,
|
|
||||||
0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79,
|
|
||||||
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70,
|
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -915,37 +889,33 @@ var file_app_proxyman_config_proto_goTypes = []interface{}{
|
|||||||
(*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig
|
(*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig
|
||||||
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
||||||
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
||||||
(*domain.Domain)(nil), // 12: xray.common.matcher.domain.Domain
|
(*net.PortRange)(nil), // 12: xray.common.net.PortRange
|
||||||
(*geoip.GeoIP)(nil), // 13: xray.common.matcher.geoip.GeoIP
|
(*net.IPOrDomain)(nil), // 13: xray.common.net.IPOrDomain
|
||||||
(*net.PortRange)(nil), // 14: xray.common.net.PortRange
|
(*internet.StreamConfig)(nil), // 14: xray.transport.internet.StreamConfig
|
||||||
(*net.IPOrDomain)(nil), // 15: xray.common.net.IPOrDomain
|
(*serial.TypedMessage)(nil), // 15: xray.common.serial.TypedMessage
|
||||||
(*internet.StreamConfig)(nil), // 16: xray.transport.internet.StreamConfig
|
(*internet.ProxyConfig)(nil), // 16: xray.transport.internet.ProxyConfig
|
||||||
(*serial.TypedMessage)(nil), // 17: xray.common.serial.TypedMessage
|
|
||||||
(*internet.ProxyConfig)(nil), // 18: xray.transport.internet.ProxyConfig
|
|
||||||
}
|
}
|
||||||
var file_app_proxyman_config_proto_depIdxs = []int32{
|
var file_app_proxyman_config_proto_depIdxs = []int32{
|
||||||
1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
||||||
10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
||||||
11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
||||||
12, // 3: xray.app.proxyman.SniffingConfig.domains_excluded:type_name -> xray.common.matcher.domain.Domain
|
12, // 3: xray.app.proxyman.ReceiverConfig.port_range:type_name -> xray.common.net.PortRange
|
||||||
13, // 4: xray.app.proxyman.SniffingConfig.ips_excluded:type_name -> xray.common.matcher.geoip.GeoIP
|
13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
||||||
14, // 5: xray.app.proxyman.ReceiverConfig.port_range:type_name -> xray.common.net.PortRange
|
3, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
|
||||||
15, // 6: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
3, // 7: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
|
0, // 7: xray.app.proxyman.ReceiverConfig.domain_override:type_name -> xray.app.proxyman.KnownProtocols
|
||||||
16, // 8: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
4, // 8: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
||||||
0, // 9: xray.app.proxyman.ReceiverConfig.domain_override:type_name -> xray.app.proxyman.KnownProtocols
|
15, // 9: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
4, // 10: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
15, // 10: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
17, // 11: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
13, // 11: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
||||||
17, // 12: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
14, // 12: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
15, // 13: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
16, // 13: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
||||||
16, // 14: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
9, // 14: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
||||||
18, // 15: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
15, // [15:15] is the sub-list for method output_type
|
||||||
9, // 16: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
15, // [15:15] is the sub-list for method input_type
|
||||||
17, // [17:17] is the sub-list for method output_type
|
15, // [15:15] is the sub-list for extension type_name
|
||||||
17, // [17:17] is the sub-list for method input_type
|
15, // [15:15] is the sub-list for extension extendee
|
||||||
17, // [17:17] is the sub-list for extension type_name
|
0, // [0:15] is the sub-list for field type_name
|
||||||
17, // [17:17] is the sub-list for extension extendee
|
|
||||||
0, // [0:17] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_proxyman_config_proto_init() }
|
func init() { file_app_proxyman_config_proto_init() }
|
||||||
|
@@ -6,8 +6,6 @@ option go_package = "github.com/xtls/xray-core/app/proxyman";
|
|||||||
option java_package = "com.xray.app.proxyman";
|
option java_package = "com.xray.app.proxyman";
|
||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
|
|
||||||
import "common/matcher/domain/domain.proto";
|
|
||||||
import "common/matcher/geoip/geoip.proto";
|
|
||||||
import "common/net/address.proto";
|
import "common/net/address.proto";
|
||||||
import "common/net/port.proto";
|
import "common/net/port.proto";
|
||||||
import "transport/internet/config.proto";
|
import "transport/internet/config.proto";
|
||||||
@@ -58,9 +56,7 @@ message SniffingConfig {
|
|||||||
// Override target destination if sniff'ed protocol is in the given list.
|
// Override target destination if sniff'ed protocol is in the given list.
|
||||||
// Supported values are "http", "tls", "fakedns".
|
// Supported values are "http", "tls", "fakedns".
|
||||||
repeated string destination_override = 2;
|
repeated string destination_override = 2;
|
||||||
|
repeated string domains_excluded = 3;
|
||||||
repeated xray.common.matcher.domain.Domain domains_excluded = 3;
|
|
||||||
repeated xray.common.matcher.geoip.GeoIP ips_excluded = 5;
|
|
||||||
|
|
||||||
// Whether should only try to sniff metadata without waiting for client input.
|
// Whether should only try to sniff metadata without waiting for client input.
|
||||||
// Can be used to support SMTP like protocol where server send the first message.
|
// Can be used to support SMTP like protocol where server send the first message.
|
||||||
|
@@ -1,9 +0,0 @@
|
|||||||
package proxyman
|
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
|
||||||
}
|
|
@@ -91,20 +91,13 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
if net.HasNetwork(nl, net.Network_UNIX) {
|
if net.HasNetwork(nl, net.Network_UNIX) {
|
||||||
newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog()
|
newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog()
|
||||||
|
|
||||||
sc := receiverConfig.GetEffectiveSniffingSettings()
|
|
||||||
sm, err := proxyman.NewSniffingMatcher(sc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
worker := &dsWorker{
|
worker := &dsWorker{
|
||||||
address: address,
|
address: address,
|
||||||
proxy: p,
|
proxy: p,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: sc,
|
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
||||||
sniffingMatcher: sm,
|
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -117,12 +110,6 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
if net.HasNetwork(nl, net.Network_TCP) {
|
if net.HasNetwork(nl, net.Network_TCP) {
|
||||||
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
|
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
|
||||||
|
|
||||||
sc := receiverConfig.GetEffectiveSniffingSettings()
|
|
||||||
sm, err := proxyman.NewSniffingMatcher(sc)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
worker := &tcpWorker{
|
worker := &tcpWorker{
|
||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
@@ -131,8 +118,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: sc,
|
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
||||||
sniffingMatcher: sm,
|
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
@@ -6,6 +6,8 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
@@ -39,7 +41,6 @@ type tcpWorker struct {
|
|||||||
tag string
|
tag string
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
sniffingConfig *proxyman.SniffingConfig
|
sniffingConfig *proxyman.SniffingConfig
|
||||||
sniffingMatcher *proxyman.SniffingMatcher
|
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ func getTProxyType(s *internet.MemoryStreamConfig) internet.SocketConfig_TProxyM
|
|||||||
return s.SocketSettings.Tproxy
|
return s.SocketSettings.Tproxy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *tcpWorker) callback(conn internet.Connection) {
|
func (w *tcpWorker) callback(conn stat.Connection) {
|
||||||
ctx, cancel := context.WithCancel(w.ctx)
|
ctx, cancel := context.WithCancel(w.ctx)
|
||||||
sid := session.NewID()
|
sid := session.NewID()
|
||||||
ctx = session.ContextWithID(ctx, sid)
|
ctx = session.ContextWithID(ctx, sid)
|
||||||
@@ -81,7 +82,7 @@ func (w *tcpWorker) callback(conn internet.Connection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if w.uplinkCounter != nil || w.downlinkCounter != nil {
|
if w.uplinkCounter != nil || w.downlinkCounter != nil {
|
||||||
conn = &internet.StatCouterConnection{
|
conn = &stat.CounterConnection{
|
||||||
Connection: conn,
|
Connection: conn,
|
||||||
ReadCounter: w.uplinkCounter,
|
ReadCounter: w.uplinkCounter,
|
||||||
WriteCounter: w.downlinkCounter,
|
WriteCounter: w.downlinkCounter,
|
||||||
@@ -98,8 +99,7 @@ func (w *tcpWorker) callback(conn internet.Connection) {
|
|||||||
if w.sniffingConfig != nil {
|
if w.sniffingConfig != nil {
|
||||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||||
content.SniffingRequest.ExcludedDomainMatcher = w.sniffingMatcher.ExDomain
|
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
||||||
content.SniffingRequest.ExcludedIPMatcher = w.sniffingMatcher.ExIP
|
|
||||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
@@ -119,7 +119,7 @@ func (w *tcpWorker) Proxy() proxy.Inbound {
|
|||||||
|
|
||||||
func (w *tcpWorker) Start() error {
|
func (w *tcpWorker) Start() error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
hub, err := internet.ListenTCP(ctx, w.address, w.port, w.stream, func(conn internet.Connection) {
|
hub, err := internet.ListenTCP(ctx, w.address, w.port, w.stream, func(conn stat.Connection) {
|
||||||
go w.callback(conn)
|
go w.callback(conn)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -430,7 +430,6 @@ type dsWorker struct {
|
|||||||
tag string
|
tag string
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
sniffingConfig *proxyman.SniffingConfig
|
sniffingConfig *proxyman.SniffingConfig
|
||||||
sniffingMatcher *proxyman.SniffingMatcher
|
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
@@ -439,13 +438,13 @@ type dsWorker struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *dsWorker) callback(conn internet.Connection) {
|
func (w *dsWorker) callback(conn stat.Connection) {
|
||||||
ctx, cancel := context.WithCancel(w.ctx)
|
ctx, cancel := context.WithCancel(w.ctx)
|
||||||
sid := session.NewID()
|
sid := session.NewID()
|
||||||
ctx = session.ContextWithID(ctx, sid)
|
ctx = session.ContextWithID(ctx, sid)
|
||||||
|
|
||||||
if w.uplinkCounter != nil || w.downlinkCounter != nil {
|
if w.uplinkCounter != nil || w.downlinkCounter != nil {
|
||||||
conn = &internet.StatCouterConnection{
|
conn = &stat.CounterConnection{
|
||||||
Connection: conn,
|
Connection: conn,
|
||||||
ReadCounter: w.uplinkCounter,
|
ReadCounter: w.uplinkCounter,
|
||||||
WriteCounter: w.downlinkCounter,
|
WriteCounter: w.downlinkCounter,
|
||||||
@@ -462,8 +461,7 @@ func (w *dsWorker) callback(conn internet.Connection) {
|
|||||||
if w.sniffingConfig != nil {
|
if w.sniffingConfig != nil {
|
||||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||||
content.SniffingRequest.ExcludedDomainMatcher = w.sniffingMatcher.ExDomain
|
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
||||||
content.SniffingRequest.ExcludedIPMatcher = w.sniffingMatcher.ExIP
|
|
||||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
@@ -486,7 +484,7 @@ func (w *dsWorker) Port() net.Port {
|
|||||||
}
|
}
|
||||||
func (w *dsWorker) Start() error {
|
func (w *dsWorker) Start() error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
hub, err := internet.ListenUnix(ctx, w.address, w.stream, func(conn internet.Connection) {
|
hub, err := internet.ListenUnix(ctx, w.address, w.stream, func(conn stat.Connection) {
|
||||||
go w.callback(conn)
|
go w.callback(conn)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -3,6 +3,8 @@ package outbound
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
@@ -158,7 +160,7 @@ func (h *Handler) Address() net.Address {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dial implements internet.Dialer.
|
// Dial implements internet.Dialer.
|
||||||
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Connection, error) {
|
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
||||||
if h.senderSettings != nil {
|
if h.senderSettings != nil {
|
||||||
if h.senderSettings.ProxySettings.HasTag() {
|
if h.senderSettings.ProxySettings.HasTag() {
|
||||||
tag := h.senderSettings.ProxySettings.Tag
|
tag := h.senderSettings.ProxySettings.Tag
|
||||||
@@ -201,9 +203,9 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (internet.Conn
|
|||||||
return h.getStatCouterConnection(conn), err
|
return h.getStatCouterConnection(conn), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) getStatCouterConnection(conn internet.Connection) internet.Connection {
|
func (h *Handler) getStatCouterConnection(conn stat.Connection) stat.Connection {
|
||||||
if h.uplinkCounter != nil || h.downlinkCounter != nil {
|
if h.uplinkCounter != nil || h.downlinkCounter != nil {
|
||||||
return &internet.StatCouterConnection{
|
return &stat.CounterConnection{
|
||||||
Connection: conn,
|
Connection: conn,
|
||||||
ReadCounter: h.downlinkCounter,
|
ReadCounter: h.downlinkCounter,
|
||||||
WriteCounter: h.uplinkCounter,
|
WriteCounter: h.uplinkCounter,
|
||||||
|
@@ -4,6 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/policy"
|
"github.com/xtls/xray-core/app/policy"
|
||||||
. "github.com/xtls/xray-core/app/proxyman/outbound"
|
. "github.com/xtls/xray-core/app/proxyman/outbound"
|
||||||
"github.com/xtls/xray-core/app/stats"
|
"github.com/xtls/xray-core/app/stats"
|
||||||
@@ -12,7 +14,6 @@ import (
|
|||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/proxy/freedom"
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInterfaces(t *testing.T) {
|
func TestInterfaces(t *testing.T) {
|
||||||
@@ -44,9 +45,9 @@ func TestOutboundWithoutStatCounter(t *testing.T) {
|
|||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||||
})
|
})
|
||||||
conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
|
conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
|
||||||
_, ok := conn.(*internet.StatCouterConnection)
|
_, ok := conn.(*stat.CounterConnection)
|
||||||
if ok {
|
if ok {
|
||||||
t.Errorf("Expected conn to not be StatCouterConnection")
|
t.Errorf("Expected conn to not be CounterConnection")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +74,8 @@ func TestOutboundWithStatCounter(t *testing.T) {
|
|||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||||
})
|
})
|
||||||
conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
|
conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
|
||||||
_, ok := conn.(*internet.StatCouterConnection)
|
_, ok := conn.(*stat.CounterConnection)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("Expected conn to be StatCouterConnection")
|
t.Errorf("Expected conn to be CounterConnection")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/reverse/config.proto
|
// source: app/reverse/config.proto
|
||||||
|
|
||||||
package reverse
|
package reverse
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type Control_State int32
|
type Control_State int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/router/command/command.proto
|
// source: app/router/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
net "github.com/xtls/xray-core/common/net"
|
net "github.com/xtls/xray-core/common/net"
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
@@ -22,10 +21,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
// RoutingContext is the context with information relative to routing process.
|
// RoutingContext is the context with information relative to routing process.
|
||||||
// It conforms to the structure of xray.features.routing.Context and
|
// It conforms to the structure of xray.features.routing.Context and
|
||||||
// xray.features.routing.Route.
|
// xray.features.routing.Route.
|
||||||
@@ -91,7 +86,7 @@ func (x *RoutingContext) GetNetwork() net.Network {
|
|||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Network
|
return x.Network
|
||||||
}
|
}
|
||||||
return net.Network_Unknown
|
return net.Network(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingContext) GetSourceIPs() [][]byte {
|
func (x *RoutingContext) GetSourceIPs() [][]byte {
|
||||||
|
@@ -8,17 +8,16 @@ import (
|
|||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/test/bufconn"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/router"
|
"github.com/xtls/xray-core/app/router"
|
||||||
. "github.com/xtls/xray-core/app/router/command"
|
. "github.com/xtls/xray-core/app/router/command"
|
||||||
"github.com/xtls/xray-core/app/stats"
|
"github.com/xtls/xray-core/app/stats"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/testing/mocks"
|
"github.com/xtls/xray-core/testing/mocks"
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/test/bufconn"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServiceSubscribeRoutingStats(t *testing.T) {
|
func TestServiceSubscribeRoutingStats(t *testing.T) {
|
||||||
@@ -233,11 +232,11 @@ func TestSerivceTestRoute(t *testing.T) {
|
|||||||
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Domain: []*domain.Domain{{Type: domain.MatchingType_Subdomain, Value: "com"}},
|
Domain: []*router.Domain{{Type: router.Domain_Domain, Value: "com"}},
|
||||||
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SourceGeoip: []*geoip.GeoIP{{CountryCode: "private", Cidr: []*geoip.CIDR{{Ip: []byte{127, 0, 0, 0}, Prefix: 8}}}},
|
SourceGeoip: []*router.GeoIP{{CountryCode: "private", Cidr: []*router.CIDR{{Ip: []byte{127, 0, 0, 0}, Prefix: 8}}}},
|
||||||
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -28,12 +28,6 @@ func (c routingContext) GetTargetPort() net.Port {
|
|||||||
return net.Port(c.RoutingContext.GetTargetPort())
|
return net.Port(c.RoutingContext.GetTargetPort())
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSkipDNSResolve is a mock implementation here to match the interface,
|
|
||||||
// SkipDNSResolve is set from dns module, no use if coming from a protobuf object?
|
|
||||||
func (c routingContext) GetSkipDNSResolve() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// AsRoutingContext converts a protobuf RoutingContext into an implementation of routing.Context.
|
// AsRoutingContext converts a protobuf RoutingContext into an implementation of routing.Context.
|
||||||
func AsRoutingContext(r *RoutingContext) routing.Context {
|
func AsRoutingContext(r *RoutingContext) routing.Context {
|
||||||
return routingContext{r}
|
return routingContext{r}
|
||||||
|
@@ -7,6 +7,7 @@ import (
|
|||||||
"go.starlark.net/syntax"
|
"go.starlark.net/syntax"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -40,6 +41,118 @@ func (v *ConditionChan) Len() int {
|
|||||||
return len(*v)
|
return len(*v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var matcherTypeMap = map[Domain_Type]strmatcher.Type{
|
||||||
|
Domain_Plain: strmatcher.Substr,
|
||||||
|
Domain_Regex: strmatcher.Regex,
|
||||||
|
Domain_Domain: strmatcher.Domain,
|
||||||
|
Domain_Full: strmatcher.Full,
|
||||||
|
}
|
||||||
|
|
||||||
|
func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) {
|
||||||
|
matcherType, f := matcherTypeMap[domain.Type]
|
||||||
|
if !f {
|
||||||
|
return nil, newError("unsupported domain type", domain.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
matcher, err := matcherType.New(domain.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("failed to create domain matcher").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return matcher, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainMatcher struct {
|
||||||
|
matchers strmatcher.IndexMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
|
||||||
|
g := strmatcher.NewMphMatcherGroup()
|
||||||
|
for _, d := range domains {
|
||||||
|
matcherType, f := matcherTypeMap[d.Type]
|
||||||
|
if !f {
|
||||||
|
return nil, newError("unsupported domain type", d.Type)
|
||||||
|
}
|
||||||
|
_, err := g.AddPattern(d.Value, matcherType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.Build()
|
||||||
|
return &DomainMatcher{
|
||||||
|
matchers: g,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) {
|
||||||
|
g := new(strmatcher.MatcherGroup)
|
||||||
|
for _, d := range domains {
|
||||||
|
m, err := domainToMatcher(d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
g.Add(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DomainMatcher{
|
||||||
|
matchers: g,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *DomainMatcher) ApplyDomain(domain string) bool {
|
||||||
|
return len(m.matchers.Match(strings.ToLower(domain))) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply implements Condition.
|
||||||
|
func (m *DomainMatcher) Apply(ctx routing.Context) bool {
|
||||||
|
domain := ctx.GetTargetDomain()
|
||||||
|
if len(domain) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return m.ApplyDomain(domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MultiGeoIPMatcher struct {
|
||||||
|
matchers []*GeoIPMatcher
|
||||||
|
onSource bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
||||||
|
var matchers []*GeoIPMatcher
|
||||||
|
for _, geoip := range geoips {
|
||||||
|
matcher, err := globalGeoIPContainer.Add(geoip)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
matchers = append(matchers, matcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
matcher := &MultiGeoIPMatcher{
|
||||||
|
matchers: matchers,
|
||||||
|
onSource: onSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
return matcher, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply implements Condition.
|
||||||
|
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
||||||
|
var ips []net.IP
|
||||||
|
if m.onSource {
|
||||||
|
ips = ctx.GetSourceIPs()
|
||||||
|
} else {
|
||||||
|
ips = ctx.GetTargetIPs()
|
||||||
|
}
|
||||||
|
for _, ip := range ips {
|
||||||
|
for _, matcher := range m.matchers {
|
||||||
|
if matcher.Match(ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type PortMatcher struct {
|
type PortMatcher struct {
|
||||||
port net.MemoryPortList
|
port net.MemoryPortList
|
||||||
onSource bool
|
onSource bool
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
package geoip
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@@ -7,24 +7,17 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
|
||||||
|
|
||||||
type ipv6 struct {
|
type ipv6 struct {
|
||||||
a uint64
|
a uint64
|
||||||
b uint64
|
b uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type GeoIPMatcher struct {
|
type GeoIPMatcher struct {
|
||||||
countryCode string
|
countryCode string
|
||||||
reverseMatch bool
|
ip4 []uint32
|
||||||
ip4 []uint32
|
prefix4 []uint8
|
||||||
prefix4 []uint8
|
ip6 []ipv6
|
||||||
ip6 []ipv6
|
prefix6 []uint8
|
||||||
prefix6 []uint8
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *GeoIPMatcher) SetReverseMatch(isReverseMatch bool) {
|
|
||||||
m.reverseMatch = isReverseMatch
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalize4(ip uint32, prefix uint8) uint32 {
|
func normalize4(ip uint32, prefix uint8) uint32 {
|
||||||
@@ -154,17 +147,8 @@ func (m *GeoIPMatcher) match6(ip ipv6) bool {
|
|||||||
func (m *GeoIPMatcher) Match(ip net.IP) bool {
|
func (m *GeoIPMatcher) Match(ip net.IP) bool {
|
||||||
switch len(ip) {
|
switch len(ip) {
|
||||||
case 4:
|
case 4:
|
||||||
if m.reverseMatch {
|
|
||||||
return !m.match4(binary.BigEndian.Uint32(ip))
|
|
||||||
}
|
|
||||||
return m.match4(binary.BigEndian.Uint32(ip))
|
return m.match4(binary.BigEndian.Uint32(ip))
|
||||||
case 16:
|
case 16:
|
||||||
if m.reverseMatch {
|
|
||||||
return !m.match6(ipv6{
|
|
||||||
a: binary.BigEndian.Uint64(ip[0:8]),
|
|
||||||
b: binary.BigEndian.Uint64(ip[8:16]),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return m.match6(ipv6{
|
return m.match6(ipv6{
|
||||||
a: binary.BigEndian.Uint64(ip[0:8]),
|
a: binary.BigEndian.Uint64(ip[0:8]),
|
||||||
b: binary.BigEndian.Uint64(ip[8:16]),
|
b: binary.BigEndian.Uint64(ip[8:16]),
|
||||||
@@ -184,15 +168,14 @@ type GeoIPMatcherContainer struct {
|
|||||||
func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
|
func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
|
||||||
if len(geoip.CountryCode) > 0 {
|
if len(geoip.CountryCode) > 0 {
|
||||||
for _, m := range c.matchers {
|
for _, m := range c.matchers {
|
||||||
if m.countryCode == geoip.CountryCode && m.reverseMatch == geoip.ReverseMatch {
|
if m.countryCode == geoip.CountryCode {
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m := &GeoIPMatcher{
|
m := &GeoIPMatcher{
|
||||||
countryCode: geoip.CountryCode,
|
countryCode: geoip.CountryCode,
|
||||||
reverseMatch: geoip.ReverseMatch,
|
|
||||||
}
|
}
|
||||||
if err := m.Init(geoip.Cidr); err != nil {
|
if err := m.Init(geoip.Cidr); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -204,5 +187,5 @@ func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GlobalGeoIPContainer GeoIPMatcherContainer
|
globalGeoIPContainer GeoIPMatcherContainer
|
||||||
)
|
)
|
@@ -1,16 +1,17 @@
|
|||||||
package geoip_test
|
package router_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/app/router"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
. "github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
"github.com/xtls/xray-core/common/platform"
|
||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -18,47 +19,27 @@ func init() {
|
|||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
|
||||||
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "..", "resources", "geoip.dat")))
|
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
|
||||||
}
|
|
||||||
if _, err := os.Stat(platform.GetAssetLocation("geoiptestrouter.dat")); err != nil && os.IsNotExist(err) {
|
|
||||||
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoiptestrouter.dat"), filepath.Join(wd, "..", "..", "..", "resources", "geoip.dat")))
|
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
|
||||||
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "..", "resources", "geosite.dat")))
|
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat")))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseIPList(t *testing.T) {
|
|
||||||
ips := []string{
|
|
||||||
"geoip:us",
|
|
||||||
"geoip:cn",
|
|
||||||
"geoip:!cn",
|
|
||||||
"ext:geoiptestrouter.dat:!cn",
|
|
||||||
"ext:geoiptestrouter.dat:ca",
|
|
||||||
"ext-ip:geoiptestrouter.dat:!cn",
|
|
||||||
"ext-ip:geoiptestrouter.dat:!ca",
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := ParseIPList(ips)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to parse geoip list, got %s", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGeoIPMatcherContainer(t *testing.T) {
|
func TestGeoIPMatcherContainer(t *testing.T) {
|
||||||
container := &GeoIPMatcherContainer{}
|
container := &router.GeoIPMatcherContainer{}
|
||||||
|
|
||||||
m1, err := container.Add(&GeoIP{
|
m1, err := container.Add(&router.GeoIP{
|
||||||
CountryCode: "CN",
|
CountryCode: "CN",
|
||||||
})
|
})
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
m2, err := container.Add(&GeoIP{
|
m2, err := container.Add(&router.GeoIP{
|
||||||
CountryCode: "US",
|
CountryCode: "US",
|
||||||
})
|
})
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
m3, err := container.Add(&GeoIP{
|
m3, err := container.Add(&router.GeoIP{
|
||||||
CountryCode: "CN",
|
CountryCode: "CN",
|
||||||
})
|
})
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
@@ -73,7 +54,7 @@ func TestGeoIPMatcherContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGeoIPMatcher(t *testing.T) {
|
func TestGeoIPMatcher(t *testing.T) {
|
||||||
cidrList := CIDRList{
|
cidrList := router.CIDRList{
|
||||||
{Ip: []byte{0, 0, 0, 0}, Prefix: 8},
|
{Ip: []byte{0, 0, 0, 0}, Prefix: 8},
|
||||||
{Ip: []byte{10, 0, 0, 0}, Prefix: 8},
|
{Ip: []byte{10, 0, 0, 0}, Prefix: 8},
|
||||||
{Ip: []byte{100, 64, 0, 0}, Prefix: 10},
|
{Ip: []byte{100, 64, 0, 0}, Prefix: 10},
|
||||||
@@ -90,7 +71,7 @@ func TestGeoIPMatcher(t *testing.T) {
|
|||||||
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher := &GeoIPMatcher{}
|
matcher := &router.GeoIPMatcher{}
|
||||||
common.Must(matcher.Init(cidrList))
|
common.Must(matcher.Init(cidrList))
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@@ -143,47 +124,11 @@ func TestGeoIPMatcher(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGeoIPReverseMatcher(t *testing.T) {
|
|
||||||
cidrList := CIDRList{
|
|
||||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
|
||||||
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
|
||||||
}
|
|
||||||
matcher := &GeoIPMatcher{}
|
|
||||||
matcher.SetReverseMatch(true) // Reverse match
|
|
||||||
common.Must(matcher.Init(cidrList))
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
Input string
|
|
||||||
Output bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Input: "8.8.8.8",
|
|
||||||
Output: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "2001:cdba::3257:9652",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "91.108.255.254",
|
|
||||||
Output: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
ip := net.ParseAddress(testCase.Input).IP()
|
|
||||||
actual := matcher.Match(ip)
|
|
||||||
if actual != testCase.Output {
|
|
||||||
t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGeoIPMatcher4CN(t *testing.T) {
|
func TestGeoIPMatcher4CN(t *testing.T) {
|
||||||
ips, err := loadGeoIP("CN")
|
ips, err := loadGeoIP("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher := &GeoIPMatcher{}
|
matcher := &router.GeoIPMatcher{}
|
||||||
common.Must(matcher.Init(ips))
|
common.Must(matcher.Init(ips))
|
||||||
|
|
||||||
if matcher.Match([]byte{8, 8, 8, 8}) {
|
if matcher.Match([]byte{8, 8, 8, 8}) {
|
||||||
@@ -195,7 +140,7 @@ func TestGeoIPMatcher6US(t *testing.T) {
|
|||||||
ips, err := loadGeoIP("US")
|
ips, err := loadGeoIP("US")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher := &GeoIPMatcher{}
|
matcher := &router.GeoIPMatcher{}
|
||||||
common.Must(matcher.Init(ips))
|
common.Must(matcher.Init(ips))
|
||||||
|
|
||||||
if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
|
if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
|
||||||
@@ -203,12 +148,12 @@ func TestGeoIPMatcher6US(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadGeoIP(country string) ([]*CIDR, error) {
|
func loadGeoIP(country string) ([]*router.CIDR, error) {
|
||||||
geoipBytes, err := filesystem.ReadAsset("geoip.dat")
|
geoipBytes, err := filesystem.ReadAsset("geoip.dat")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var geoipList GeoIPList
|
var geoipList router.GeoIPList
|
||||||
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
|
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -226,7 +171,7 @@ func BenchmarkGeoIPMatcher4CN(b *testing.B) {
|
|||||||
ips, err := loadGeoIP("CN")
|
ips, err := loadGeoIP("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher := &GeoIPMatcher{}
|
matcher := &router.GeoIPMatcher{}
|
||||||
common.Must(matcher.Init(ips))
|
common.Must(matcher.Init(ips))
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
@@ -240,7 +185,7 @@ func BenchmarkGeoIPMatcher6US(b *testing.B) {
|
|||||||
ips, err := loadGeoIP("US")
|
ips, err := loadGeoIP("US")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher := &GeoIPMatcher{}
|
matcher := &router.GeoIPMatcher{}
|
||||||
common.Must(matcher.Init(ips))
|
common.Must(matcher.Init(ips))
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
@@ -11,9 +11,6 @@ import (
|
|||||||
. "github.com/xtls/xray-core/app/router"
|
. "github.com/xtls/xray-core/app/router"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geosite"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
"github.com/xtls/xray-core/common/platform"
|
||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||||
@@ -29,10 +26,10 @@ func init() {
|
|||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(platform.GetAssetLocation("geoip.dat")); err != nil && os.IsNotExist(err) {
|
||||||
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "resources", "geoip.dat")))
|
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geoip.dat"), filepath.Join(wd, "..", "..", "release", "config", "geoip.dat")))
|
||||||
}
|
}
|
||||||
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
|
if _, err := os.Stat(platform.GetAssetLocation("geosite.dat")); err != nil && os.IsNotExist(err) {
|
||||||
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "resources", "geosite.dat")))
|
common.Must(filesystem.CopyFile(platform.GetAssetLocation("geosite.dat"), filepath.Join(wd, "..", "..", "release", "config", "geosite.dat")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,18 +61,18 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
rule: &RoutingRule{
|
rule: &RoutingRule{
|
||||||
Domain: []*domain.Domain{
|
Domain: []*Domain{
|
||||||
{
|
{
|
||||||
Value: "example.com",
|
Value: "example.com",
|
||||||
Type: domain.MatchingType_Keyword,
|
Type: Domain_Plain,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Value: "google.com",
|
Value: "google.com",
|
||||||
Type: domain.MatchingType_Subdomain,
|
Type: Domain_Domain,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Value: "^facebook\\.com$",
|
Value: "^facebook\\.com$",
|
||||||
Type: domain.MatchingType_Regex,
|
Type: Domain_Regex,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -112,7 +109,7 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
rule: &RoutingRule{
|
rule: &RoutingRule{
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*CIDR{
|
||||||
{
|
{
|
||||||
Ip: []byte{8, 8, 8, 8},
|
Ip: []byte{8, 8, 8, 8},
|
||||||
Prefix: 32,
|
Prefix: 32,
|
||||||
@@ -148,9 +145,9 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
rule: &RoutingRule{
|
rule: &RoutingRule{
|
||||||
Geoip: []*geoip.GeoIP{
|
Geoip: []*GeoIP{
|
||||||
{
|
{
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*CIDR{
|
||||||
{
|
{
|
||||||
Ip: []byte{8, 8, 8, 8},
|
Ip: []byte{8, 8, 8, 8},
|
||||||
Prefix: 32,
|
Prefix: 32,
|
||||||
@@ -188,7 +185,7 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
rule: &RoutingRule{
|
rule: &RoutingRule{
|
||||||
SourceCidr: []*geoip.CIDR{
|
SourceCidr: []*CIDR{
|
||||||
{
|
{
|
||||||
Ip: []byte{192, 168, 0, 0},
|
Ip: []byte{192, 168, 0, 0},
|
||||||
Prefix: 16,
|
Prefix: 16,
|
||||||
@@ -336,19 +333,19 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadGeoSite(country string) ([]*domain.Domain, error) {
|
func loadGeoSite(country string) ([]*Domain, error) {
|
||||||
geositeBytes, err := filesystem.ReadAsset("geosite.dat")
|
geositeBytes, err := filesystem.ReadAsset("geosite.dat")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var geositeList geosite.GeoSiteList
|
var geositeList GeoSiteList
|
||||||
if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
|
if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, site := range geositeList.Entry {
|
for _, site := range geositeList.Entry {
|
||||||
if site.CountryCode == country {
|
if site.CountryCode == country {
|
||||||
return geosite.ToDomains(site.Domain), nil
|
return site.Domain, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,10 +356,10 @@ func TestChinaSites(t *testing.T) {
|
|||||||
domains, err := loadGeoSite("CN")
|
domains, err := loadGeoSite("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher, err := domain.NewDomainMatcher(domains)
|
matcher, err := NewDomainMatcher(domains)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
acMatcher, err := domain.NewMphMatcherGroup(domains)
|
acMatcher, err := NewMphMatcherGroup(domains)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
@@ -407,7 +404,7 @@ func BenchmarkMphDomainMatcher(b *testing.B) {
|
|||||||
domains, err := loadGeoSite("CN")
|
domains, err := loadGeoSite("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher, err := domain.NewMphMatcherGroup(domains)
|
matcher, err := NewMphMatcherGroup(domains)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
@@ -449,7 +446,7 @@ func BenchmarkDomainMatcher(b *testing.B) {
|
|||||||
domains, err := loadGeoSite("CN")
|
domains, err := loadGeoSite("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher, err := domain.NewDomainMatcher(domains)
|
matcher, err := NewDomainMatcher(domains)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
@@ -487,32 +484,13 @@ func BenchmarkDomainMatcher(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadGeoIP(country string) ([]*geoip.CIDR, error) {
|
|
||||||
geoipBytes, err := filesystem.ReadAsset("dat")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var geoipList geoip.GeoIPList
|
|
||||||
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, geoip := range geoipList.Entry {
|
|
||||||
if geoip.CountryCode == country {
|
|
||||||
return geoip.Cidr, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("country not found: " + country)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
||||||
var geoips []*geoip.GeoIP
|
var geoips []*GeoIP
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, err := loadGeoIP("CN")
|
ips, err := loadGeoIP("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
geoips = append(geoips, &geoip.GeoIP{
|
geoips = append(geoips, &GeoIP{
|
||||||
CountryCode: "CN",
|
CountryCode: "CN",
|
||||||
Cidr: ips,
|
Cidr: ips,
|
||||||
})
|
})
|
||||||
@@ -521,7 +499,7 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
|||||||
{
|
{
|
||||||
ips, err := loadGeoIP("JP")
|
ips, err := loadGeoIP("JP")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
geoips = append(geoips, &geoip.GeoIP{
|
geoips = append(geoips, &GeoIP{
|
||||||
CountryCode: "JP",
|
CountryCode: "JP",
|
||||||
Cidr: ips,
|
Cidr: ips,
|
||||||
})
|
})
|
||||||
@@ -530,7 +508,7 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
|||||||
{
|
{
|
||||||
ips, err := loadGeoIP("CA")
|
ips, err := loadGeoIP("CA")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
geoips = append(geoips, &geoip.GeoIP{
|
geoips = append(geoips, &GeoIP{
|
||||||
CountryCode: "CA",
|
CountryCode: "CA",
|
||||||
Cidr: ips,
|
Cidr: ips,
|
||||||
})
|
})
|
||||||
@@ -539,13 +517,13 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
|||||||
{
|
{
|
||||||
ips, err := loadGeoIP("US")
|
ips, err := loadGeoIP("US")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
geoips = append(geoips, &geoip.GeoIP{
|
geoips = append(geoips, &GeoIP{
|
||||||
CountryCode: "US",
|
CountryCode: "US",
|
||||||
Cidr: ips,
|
Cidr: ips,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher, err := geoip.NewMultiGeoIPMatcher(geoips, false)
|
matcher, err := NewMultiGeoIPMatcher(geoips, false)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
||||||
|
@@ -1,13 +1,50 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
dm "github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// CIDRList is an alias of []*CIDR to provide sort.Interface.
|
||||||
|
type CIDRList []*CIDR
|
||||||
|
|
||||||
|
// Len implements sort.Interface.
|
||||||
|
func (l *CIDRList) Len() int {
|
||||||
|
return len(*l)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Less implements sort.Interface.
|
||||||
|
func (l *CIDRList) Less(i int, j int) bool {
|
||||||
|
ci := (*l)[i]
|
||||||
|
cj := (*l)[j]
|
||||||
|
|
||||||
|
if len(ci.Ip) < len(cj.Ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ci.Ip) > len(cj.Ip) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
for k := 0; k < len(ci.Ip); k++ {
|
||||||
|
if ci.Ip[k] < cj.Ip[k] {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ci.Ip[k] > cj.Ip[k] {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ci.Prefix < cj.Prefix
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap implements sort.Interface.
|
||||||
|
func (l *CIDRList) Swap(i int, j int) {
|
||||||
|
(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
|
||||||
|
}
|
||||||
|
|
||||||
type Rule struct {
|
type Rule struct {
|
||||||
Tag string
|
Tag string
|
||||||
Balancer *Balancer
|
Balancer *Balancer
|
||||||
@@ -32,7 +69,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
if len(rr.Domain) > 0 {
|
if len(rr.Domain) > 0 {
|
||||||
switch rr.DomainMatcher {
|
switch rr.DomainMatcher {
|
||||||
case "linear":
|
case "linear":
|
||||||
matcher, err := dm.NewDomainMatcher(rr.Domain)
|
matcher, err := NewDomainMatcher(rr.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to build domain condition").Base(err)
|
return nil, newError("failed to build domain condition").Base(err)
|
||||||
}
|
}
|
||||||
@@ -40,7 +77,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
case "mph", "hybrid":
|
case "mph", "hybrid":
|
||||||
fallthrough
|
fallthrough
|
||||||
default:
|
default:
|
||||||
matcher, err := dm.NewMphMatcherGroup(rr.Domain)
|
matcher, err := NewMphMatcherGroup(rr.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, newError("failed to build domain condition with MphDomainMatcher").Base(err)
|
return nil, newError("failed to build domain condition with MphDomainMatcher").Base(err)
|
||||||
}
|
}
|
||||||
@@ -75,13 +112,13 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Geoip) > 0 {
|
if len(rr.Geoip) > 0 {
|
||||||
cond, err := geoip.NewMultiGeoIPMatcher(rr.Geoip, false)
|
cond, err := NewMultiGeoIPMatcher(rr.Geoip, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conds.Add(cond)
|
conds.Add(cond)
|
||||||
} else if len(rr.Cidr) > 0 {
|
} else if len(rr.Cidr) > 0 {
|
||||||
cond, err := geoip.NewMultiGeoIPMatcher([]*geoip.GeoIP{{Cidr: rr.Cidr}}, false)
|
cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.Cidr}}, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -89,13 +126,13 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.SourceGeoip) > 0 {
|
if len(rr.SourceGeoip) > 0 {
|
||||||
cond, err := geoip.NewMultiGeoIPMatcher(rr.SourceGeoip, true)
|
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conds.Add(cond)
|
conds.Add(cond)
|
||||||
} else if len(rr.SourceCidr) > 0 {
|
} else if len(rr.SourceCidr) > 0 {
|
||||||
cond, err := geoip.NewMultiGeoIPMatcher([]*geoip.GeoIP{{Cidr: rr.SourceCidr}}, true)
|
cond, err := NewMultiGeoIPMatcher([]*GeoIP{{Cidr: rr.SourceCidr}}, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,66 @@ option java_multiple_files = true;
|
|||||||
|
|
||||||
import "common/net/port.proto";
|
import "common/net/port.proto";
|
||||||
import "common/net/network.proto";
|
import "common/net/network.proto";
|
||||||
import "common/matcher/domain/domain.proto";
|
|
||||||
import "common/matcher/geoip/geoip.proto";
|
// Domain for routing decision.
|
||||||
|
message Domain {
|
||||||
|
// Type of domain value.
|
||||||
|
enum Type {
|
||||||
|
// The value is used as is.
|
||||||
|
Plain = 0;
|
||||||
|
// The value is used as a regular expression.
|
||||||
|
Regex = 1;
|
||||||
|
// The value is a root domain.
|
||||||
|
Domain = 2;
|
||||||
|
// The value is a domain.
|
||||||
|
Full = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Domain matching type.
|
||||||
|
Type type = 1;
|
||||||
|
|
||||||
|
// Domain value.
|
||||||
|
string value = 2;
|
||||||
|
|
||||||
|
message Attribute {
|
||||||
|
string key = 1;
|
||||||
|
|
||||||
|
oneof typed_value {
|
||||||
|
bool bool_value = 2;
|
||||||
|
int64 int_value = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attributes of this domain. May be used for filtering.
|
||||||
|
repeated Attribute attribute = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IP for routing decision, in CIDR form.
|
||||||
|
message CIDR {
|
||||||
|
// IP address, should be either 4 or 16 bytes.
|
||||||
|
bytes ip = 1;
|
||||||
|
|
||||||
|
// Number of leading ones in the network mask.
|
||||||
|
uint32 prefix = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoIP {
|
||||||
|
string country_code = 1;
|
||||||
|
repeated CIDR cidr = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoIPList {
|
||||||
|
repeated GeoIP entry = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoSite {
|
||||||
|
string country_code = 1;
|
||||||
|
repeated Domain domain = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoSiteList {
|
||||||
|
repeated GeoSite entry = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message RoutingRule {
|
message RoutingRule {
|
||||||
oneof target_tag {
|
oneof target_tag {
|
||||||
@@ -21,17 +79,17 @@ message RoutingRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// List of domains for target domain matching.
|
// List of domains for target domain matching.
|
||||||
repeated xray.common.matcher.domain.Domain domain = 2;
|
repeated Domain domain = 2;
|
||||||
|
|
||||||
// List of CIDRs for target IP address matching.
|
// List of CIDRs for target IP address matching.
|
||||||
// Deprecated. Use geoip below.
|
// Deprecated. Use geoip below.
|
||||||
repeated xray.common.matcher.geoip.CIDR cidr = 3 [deprecated = true];
|
repeated CIDR cidr = 3 [deprecated = true];
|
||||||
|
|
||||||
// List of GeoIPs for target IP address matching. If this entry exists, the
|
// 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
|
// cidr above will have no effect. GeoIP fields with the same country code are
|
||||||
// supposed to contain exactly same content. They will be merged during
|
// supposed to contain exactly same content. They will be merged during
|
||||||
// runtime. For customized GeoIPs, please leave country code empty.
|
// runtime. For customized GeoIPs, please leave country code empty.
|
||||||
repeated xray.common.matcher.geoip.GeoIP geoip = 10;
|
repeated GeoIP geoip = 10;
|
||||||
|
|
||||||
// A range of port [from, to]. If the destination port is in this range, this
|
// A range of port [from, to]. If the destination port is in this range, this
|
||||||
// rule takes effect. Deprecated. Use port_list.
|
// rule takes effect. Deprecated. Use port_list.
|
||||||
@@ -47,11 +105,11 @@ message RoutingRule {
|
|||||||
repeated xray.common.net.Network networks = 13;
|
repeated xray.common.net.Network networks = 13;
|
||||||
|
|
||||||
// List of CIDRs for source IP address matching.
|
// List of CIDRs for source IP address matching.
|
||||||
repeated xray.common.matcher.geoip.CIDR source_cidr = 6 [deprecated = true];
|
repeated CIDR source_cidr = 6 [deprecated = true];
|
||||||
|
|
||||||
// List of GeoIPs for source IP address matching. If this entry exists, the
|
// List of GeoIPs for source IP address matching. If this entry exists, the
|
||||||
// source_cidr above will have no effect.
|
// source_cidr above will have no effect.
|
||||||
repeated xray.common.matcher.geoip.GeoIP source_geoip = 11;
|
repeated GeoIP source_geoip = 11;
|
||||||
|
|
||||||
// List of ports for source port matching.
|
// List of ports for source port matching.
|
||||||
xray.common.net.PortList source_port_list = 16;
|
xray.common.net.PortList source_port_list = 16;
|
||||||
|
@@ -80,13 +80,7 @@ func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) {
|
func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context, error) {
|
||||||
|
if r.domainStrategy == Config_IpOnDemand {
|
||||||
// SkipDNSResolve is set from DNS module.
|
|
||||||
// the DOH remote server maybe a domain name,
|
|
||||||
// this prevents cycle resolving dead loop
|
|
||||||
skipDNSResolve := ctx.GetSkipDNSResolve()
|
|
||||||
|
|
||||||
if r.domainStrategy == Config_IpOnDemand && !skipDNSResolve {
|
|
||||||
ctx = routing_dns.ContextWithDNSClient(ctx, r.dns)
|
ctx = routing_dns.ContextWithDNSClient(ctx, r.dns)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +90,7 @@ func (r *Router) pickRouteInternal(ctx routing.Context) (*Rule, routing.Context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.domainStrategy != Config_IpIfNonMatch || len(ctx.GetTargetDomain()) == 0 || skipDNSResolve {
|
if r.domainStrategy != Config_IpIfNonMatch || len(ctx.GetTargetDomain()) == 0 {
|
||||||
return nil, ctx, common.ErrNoClue
|
return nil, ctx, common.ErrNoClue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,11 +5,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/router"
|
. "github.com/xtls/xray-core/app/router"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/matcher/geoip"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
routing_session "github.com/xtls/xray-core/features/routing/session"
|
routing_session "github.com/xtls/xray-core/features/routing/session"
|
||||||
"github.com/xtls/xray-core/testing/mocks"
|
"github.com/xtls/xray-core/testing/mocks"
|
||||||
@@ -102,7 +103,7 @@ func TestIPOnDemand(t *testing.T) {
|
|||||||
TargetTag: &RoutingRule_Tag{
|
TargetTag: &RoutingRule_Tag{
|
||||||
Tag: "test",
|
Tag: "test",
|
||||||
},
|
},
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*CIDR{
|
||||||
{
|
{
|
||||||
Ip: []byte{192, 168, 0, 0},
|
Ip: []byte{192, 168, 0, 0},
|
||||||
Prefix: 16,
|
Prefix: 16,
|
||||||
@@ -116,7 +117,11 @@ func TestIPOnDemand(t *testing.T) {
|
|||||||
defer mockCtl.Finish()
|
defer mockCtl.Finish()
|
||||||
|
|
||||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||||
mockDNS.EXPECT().LookupIP(gomock.Eq("example.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
mockDNS.EXPECT().LookupIP(gomock.Eq("example.com"), dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(config, mockDNS, nil))
|
common.Must(r.Init(config, mockDNS, nil))
|
||||||
@@ -137,7 +142,7 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
|||||||
TargetTag: &RoutingRule_Tag{
|
TargetTag: &RoutingRule_Tag{
|
||||||
Tag: "test",
|
Tag: "test",
|
||||||
},
|
},
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*CIDR{
|
||||||
{
|
{
|
||||||
Ip: []byte{192, 168, 0, 0},
|
Ip: []byte{192, 168, 0, 0},
|
||||||
Prefix: 16,
|
Prefix: 16,
|
||||||
@@ -151,7 +156,11 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
|||||||
defer mockCtl.Finish()
|
defer mockCtl.Finish()
|
||||||
|
|
||||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||||
mockDNS.EXPECT().LookupIP(gomock.Eq("example.com")).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
mockDNS.EXPECT().LookupIP(gomock.Eq("example.com"), dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(config, mockDNS, nil))
|
common.Must(r.Init(config, mockDNS, nil))
|
||||||
@@ -172,7 +181,7 @@ func TestIPIfNonMatchIP(t *testing.T) {
|
|||||||
TargetTag: &RoutingRule_Tag{
|
TargetTag: &RoutingRule_Tag{
|
||||||
Tag: "test",
|
Tag: "test",
|
||||||
},
|
},
|
||||||
Cidr: []*geoip.CIDR{
|
Cidr: []*CIDR{
|
||||||
{
|
{
|
||||||
Ip: []byte{127, 0, 0, 0},
|
Ip: []byte{127, 0, 0, 0},
|
||||||
Prefix: 8,
|
Prefix: 8,
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/app/stats"
|
"github.com/xtls/xray-core/app/stats"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/matcher/str"
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
feature_stats "github.com/xtls/xray-core/features/stats"
|
feature_stats "github.com/xtls/xray-core/features/stats"
|
||||||
)
|
)
|
||||||
@@ -49,7 +49,7 @@ func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
|
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
|
||||||
matcher, err := str.Substr.New(request.Pattern)
|
matcher, err := strmatcher.Substr.New(request.Pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/stats/command/command.proto
|
// source: app/stats/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type GetStatsRequest struct {
|
type GetStatsRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: app/stats/config.proto
|
// source: app/stats/config.proto
|
||||||
|
|
||||||
package stats
|
package stats
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@@ -24,10 +24,17 @@ type Buffer struct {
|
|||||||
UDP *net.Destination
|
UDP *net.Destination
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a Buffer with 0 length and 2K capacity.
|
// New creates a Buffer with 0 length and 8K capacity.
|
||||||
func New() *Buffer {
|
func New() *Buffer {
|
||||||
|
buf := pool.Get().([]byte)
|
||||||
|
if cap(buf) >= Size {
|
||||||
|
buf = buf[:Size]
|
||||||
|
} else {
|
||||||
|
buf = make([]byte, Size)
|
||||||
|
}
|
||||||
|
|
||||||
return &Buffer{
|
return &Buffer{
|
||||||
v: pool.Get().([]byte),
|
v: buf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,8 +57,15 @@ func NewExisted(b []byte) *Buffer {
|
|||||||
// StackNew creates a new Buffer object on stack.
|
// StackNew creates a new Buffer object on stack.
|
||||||
// This method is for buffers that is released in the same function.
|
// This method is for buffers that is released in the same function.
|
||||||
func StackNew() Buffer {
|
func StackNew() Buffer {
|
||||||
|
buf := pool.Get().([]byte)
|
||||||
|
if cap(buf) >= Size {
|
||||||
|
buf = buf[:Size]
|
||||||
|
} else {
|
||||||
|
buf = make([]byte, Size)
|
||||||
|
}
|
||||||
|
|
||||||
return Buffer{
|
return Buffer{
|
||||||
v: pool.Get().([]byte),
|
v: buf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +78,10 @@ func (b *Buffer) Release() {
|
|||||||
p := b.v
|
p := b.v
|
||||||
b.v = nil
|
b.v = nil
|
||||||
b.Clear()
|
b.Clear()
|
||||||
pool.Put(p)
|
|
||||||
|
if cap(p) == Size {
|
||||||
|
pool.Put(p)
|
||||||
|
}
|
||||||
b.UDP = nil
|
b.UDP = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,6 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
. "github.com/xtls/xray-core/common/buf"
|
. "github.com/xtls/xray-core/common/buf"
|
||||||
)
|
)
|
||||||
|
@@ -6,6 +6,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/features/stats"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Reader extends io.Reader with MultiBuffer.
|
// Reader extends io.Reader with MultiBuffer.
|
||||||
@@ -29,9 +32,17 @@ type Writer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WriteAllBytes ensures all bytes are written into the given writer.
|
// WriteAllBytes ensures all bytes are written into the given writer.
|
||||||
func WriteAllBytes(writer io.Writer, payload []byte) error {
|
func WriteAllBytes(writer io.Writer, payload []byte, c stats.Counter) error {
|
||||||
|
wc := 0
|
||||||
|
defer func() {
|
||||||
|
if c != nil {
|
||||||
|
c.Add(int64(wc))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
for len(payload) > 0 {
|
for len(payload) > 0 {
|
||||||
n, err := writer.Write(payload)
|
n, err := writer.Write(payload)
|
||||||
|
wc += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -65,7 +76,13 @@ func NewReader(reader io.Reader) Reader {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
newError("failed to get sysconn").Base(err).WriteToLog()
|
newError("failed to get sysconn").Base(err).WriteToLog()
|
||||||
} else {
|
} else {
|
||||||
return NewReadVReader(reader, rawConn)
|
var counter stats.Counter
|
||||||
|
|
||||||
|
if statConn, ok := reader.(*stat.CounterConnection); ok {
|
||||||
|
reader = statConn.Connection
|
||||||
|
counter = statConn.ReadCounter
|
||||||
|
}
|
||||||
|
return NewReadVReader(reader, rawConn, counter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,13 +121,24 @@ func NewWriter(writer io.Writer) Writer {
|
|||||||
return mw
|
return mw
|
||||||
}
|
}
|
||||||
|
|
||||||
if isPacketWriter(writer) {
|
var iConn = writer
|
||||||
|
if statConn, ok := writer.(*stat.CounterConnection); ok {
|
||||||
|
iConn = statConn.Connection
|
||||||
|
}
|
||||||
|
|
||||||
|
if isPacketWriter(iConn) {
|
||||||
return &SequentialWriter{
|
return &SequentialWriter{
|
||||||
Writer: writer,
|
Writer: writer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var counter stats.Counter
|
||||||
|
|
||||||
|
if statConn, ok := writer.(*stat.CounterConnection); ok {
|
||||||
|
counter = statConn.WriteCounter
|
||||||
|
}
|
||||||
return &BufferToBytesWriter{
|
return &BufferToBytesWriter{
|
||||||
Writer: writer,
|
Writer: iConn,
|
||||||
|
counter: counter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,6 +9,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
. "github.com/xtls/xray-core/common/buf"
|
. "github.com/xtls/xray-core/common/buf"
|
||||||
)
|
)
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
// +build !windows
|
//go:build !windows && !wasm && !illumos
|
||||||
// +build !wasm
|
// +build !windows,!wasm,!illumos
|
||||||
// +build !illumos
|
|
||||||
|
|
||||||
package buf
|
package buf
|
||||||
|
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
|
//go:build !wasm
|
||||||
// +build !wasm
|
// +build !wasm
|
||||||
|
|
||||||
package buf
|
package buf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"runtime"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/features/stats"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/platform"
|
"github.com/xtls/xray-core/common/platform"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -54,17 +56,19 @@ type ReadVReader struct {
|
|||||||
rawConn syscall.RawConn
|
rawConn syscall.RawConn
|
||||||
mr multiReader
|
mr multiReader
|
||||||
alloc allocStrategy
|
alloc allocStrategy
|
||||||
|
counter stats.Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewReadVReader creates a new ReadVReader.
|
// NewReadVReader creates a new ReadVReader.
|
||||||
func NewReadVReader(reader io.Reader, rawConn syscall.RawConn) *ReadVReader {
|
func NewReadVReader(reader io.Reader, rawConn syscall.RawConn, counter stats.Counter) *ReadVReader {
|
||||||
return &ReadVReader{
|
return &ReadVReader{
|
||||||
Reader: reader,
|
Reader: reader,
|
||||||
rawConn: rawConn,
|
rawConn: rawConn,
|
||||||
alloc: allocStrategy{
|
alloc: allocStrategy{
|
||||||
current: 1,
|
current: 1,
|
||||||
},
|
},
|
||||||
mr: newMultiReader(),
|
mr: newMultiReader(),
|
||||||
|
counter: counter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,10 +127,16 @@ func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) {
|
|||||||
if b.IsFull() {
|
if b.IsFull() {
|
||||||
r.alloc.Adjust(1)
|
r.alloc.Adjust(1)
|
||||||
}
|
}
|
||||||
|
if r.counter != nil && b != nil {
|
||||||
|
r.counter.Add(int64(b.Len()))
|
||||||
|
}
|
||||||
return MultiBuffer{b}, err
|
return MultiBuffer{b}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mb, err := r.readMulti()
|
mb, err := r.readMulti()
|
||||||
|
if r.counter != nil && mb != nil {
|
||||||
|
r.counter.Add(int64(mb.Len()))
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -134,17 +144,13 @@ func (r *ReadVReader) ReadMultiBuffer() (MultiBuffer, error) {
|
|||||||
return mb, nil
|
return mb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var useReadv = true
|
var useReadv bool
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
const defaultFlagValue = "NOT_DEFINED_AT_ALL"
|
const defaultFlagValue = "NOT_DEFINED_AT_ALL"
|
||||||
value := platform.NewEnvFlag("xray.buf.readv").GetValue(func() string { return defaultFlagValue })
|
value := platform.NewEnvFlag("xray.buf.readv").GetValue(func() string { return defaultFlagValue })
|
||||||
switch value {
|
switch value {
|
||||||
case defaultFlagValue, "auto":
|
case defaultFlagValue, "auto", "enable":
|
||||||
if (runtime.GOARCH == "386" || runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x") && (runtime.GOOS == "linux" || runtime.GOOS == "darwin" || runtime.GOOS == "windows") {
|
|
||||||
useReadv = true
|
|
||||||
}
|
|
||||||
case "enable":
|
|
||||||
useReadv = true
|
useReadv = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build wasm
|
||||||
// +build wasm
|
// +build wasm
|
||||||
|
|
||||||
package buf
|
package buf
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !wasm
|
||||||
// +build !wasm
|
// +build !wasm
|
||||||
|
|
||||||
package buf_test
|
package buf_test
|
||||||
@@ -9,10 +10,11 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
. "github.com/xtls/xray-core/common/buf"
|
. "github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/testing/servers/tcp"
|
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestReadvReader(t *testing.T) {
|
func TestReadvReader(t *testing.T) {
|
||||||
@@ -50,7 +52,7 @@ func TestReadvReader(t *testing.T) {
|
|||||||
rawConn, err := conn.(*net.TCPConn).SyscallConn()
|
rawConn, err := conn.(*net.TCPConn).SyscallConn()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
reader := NewReadVReader(conn, rawConn)
|
reader := NewReadVReader(conn, rawConn, nil)
|
||||||
var rmb MultiBuffer
|
var rmb MultiBuffer
|
||||||
for {
|
for {
|
||||||
mb, err := reader.ReadMultiBuffer()
|
mb, err := reader.ReadMultiBuffer()
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build illumos
|
||||||
// +build illumos
|
// +build illumos
|
||||||
|
|
||||||
package buf
|
package buf
|
||||||
|
@@ -5,6 +5,8 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/features/stats"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
)
|
)
|
||||||
@@ -13,7 +15,8 @@ import (
|
|||||||
type BufferToBytesWriter struct {
|
type BufferToBytesWriter struct {
|
||||||
io.Writer
|
io.Writer
|
||||||
|
|
||||||
cache [][]byte
|
counter stats.Counter
|
||||||
|
cache [][]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMultiBuffer implements Writer. This method takes ownership of the given buffer.
|
// WriteMultiBuffer implements Writer. This method takes ownership of the given buffer.
|
||||||
@@ -26,7 +29,7 @@ func (w *BufferToBytesWriter) WriteMultiBuffer(mb MultiBuffer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(mb) == 1 {
|
if len(mb) == 1 {
|
||||||
return WriteAllBytes(w.Writer, mb[0].Bytes())
|
return WriteAllBytes(w.Writer, mb[0].Bytes(), w.counter)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cap(w.cache) < len(mb) {
|
if cap(w.cache) < len(mb) {
|
||||||
@@ -45,9 +48,15 @@ func (w *BufferToBytesWriter) WriteMultiBuffer(mb MultiBuffer) error {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
nb := net.Buffers(bs)
|
nb := net.Buffers(bs)
|
||||||
|
wc := int64(0)
|
||||||
|
defer func() {
|
||||||
|
if w.counter != nil {
|
||||||
|
w.counter.Add(wc)
|
||||||
|
}
|
||||||
|
}()
|
||||||
for size > 0 {
|
for size > 0 {
|
||||||
n, err := nb.WriteTo(w.Writer)
|
n, err := nb.WriteTo(w.Writer)
|
||||||
|
wc += n
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -173,7 +182,7 @@ func (w *BufferedWriter) flushInternal() error {
|
|||||||
w.buffer = nil
|
w.buffer = nil
|
||||||
|
|
||||||
if writer, ok := w.writer.(io.Writer); ok {
|
if writer, ok := w.writer.(io.Writer); ok {
|
||||||
err := WriteAllBytes(writer, b.Bytes())
|
err := WriteAllBytes(writer, b.Bytes(), nil)
|
||||||
b.Release()
|
b.Release()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build generate
|
||||||
// +build generate
|
// +build generate
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
@@ -50,7 +50,7 @@ func NewCryptionWriter(stream cipher.Stream, writer io.Writer) *CryptionWriter {
|
|||||||
func (w *CryptionWriter) Write(data []byte) (int, error) {
|
func (w *CryptionWriter) Write(data []byte) (int, error) {
|
||||||
w.stream.XORKeyStream(data, data)
|
w.stream.XORKeyStream(data, data)
|
||||||
|
|
||||||
if err := buf.WriteAllBytes(w.writer, data); err != nil {
|
if err := buf.WriteAllBytes(w.writer, data, nil); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
return len(data), nil
|
return len(data), nil
|
||||||
|
@@ -2,11 +2,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -20,26 +17,21 @@ func main() {
|
|||||||
pkg = "core"
|
pkg = "core"
|
||||||
}
|
}
|
||||||
|
|
||||||
moduleName, gmnErr := common.GetModuleName(pwd)
|
|
||||||
if gmnErr != nil {
|
|
||||||
fmt.Println("can not get module path", gmnErr)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.OpenFile("errors.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
file, err := os.OpenFile("errors.generated.go", os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to generate errors.generated.go: %v", err)
|
fmt.Printf("Failed to generate errors.generated.go: %v", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
fmt.Fprintln(file, "package", pkg)
|
fmt.Fprintf(file, `package %s
|
||||||
fmt.Fprintln(file, "")
|
|
||||||
fmt.Fprintln(file, "import \""+moduleName+"/common/errors\"")
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
fmt.Fprintln(file, "")
|
|
||||||
fmt.Fprintln(file, "type errPathObjHolder struct{}")
|
type errPathObjHolder struct{}
|
||||||
fmt.Fprintln(file, "")
|
|
||||||
fmt.Fprintln(file, "func newError(values ...interface{}) *errors.Error {")
|
func newError(values ...interface{}) *errors.Error {
|
||||||
fmt.Fprintln(file, " return errors.New(values...).WithPathObj(errPathObjHolder{})")
|
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||||
fmt.Fprintln(file, "}")
|
}
|
||||||
|
`, pkg)
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: common/log/log.proto
|
// source: common/log/log.proto
|
||||||
|
|
||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type Severity int32
|
type Severity int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
package conf
|
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
|
@@ -1,94 +0,0 @@
|
|||||||
package conf
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
dm "github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
"github.com/xtls/xray-core/common/matcher/geosite"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ParseDomainRule(domain string) ([]*dm.Domain, error) {
|
|
||||||
if strings.HasPrefix(domain, "geosite:") {
|
|
||||||
country := strings.ToUpper(domain[8:])
|
|
||||||
domains, err := geosite.LoadGeositeWithAttr("geosite.dat", country)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to load geosite: ", country).Base(err)
|
|
||||||
}
|
|
||||||
return domains, nil
|
|
||||||
}
|
|
||||||
var isExtDatFile = 0
|
|
||||||
{
|
|
||||||
const prefix = "ext:"
|
|
||||||
if strings.HasPrefix(domain, prefix) {
|
|
||||||
isExtDatFile = len(prefix)
|
|
||||||
}
|
|
||||||
const prefixQualified = "ext-domain:"
|
|
||||||
if strings.HasPrefix(domain, prefixQualified) {
|
|
||||||
isExtDatFile = len(prefixQualified)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isExtDatFile != 0 {
|
|
||||||
kv := strings.Split(domain[isExtDatFile:], ":")
|
|
||||||
if len(kv) != 2 {
|
|
||||||
return nil, newError("invalid external resource: ", domain)
|
|
||||||
}
|
|
||||||
filename := kv[0]
|
|
||||||
country := kv[1]
|
|
||||||
domains, err := geosite.LoadGeositeWithAttr(filename, country)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to load external sites: ", country, " from ", filename).Base(err)
|
|
||||||
}
|
|
||||||
return domains, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
domainRule := new(dm.Domain)
|
|
||||||
switch {
|
|
||||||
case strings.HasPrefix(domain, "regexp:"):
|
|
||||||
regexpVal := domain[7:]
|
|
||||||
if len(regexpVal) == 0 {
|
|
||||||
return nil, newError("empty regexp type of rule: ", domain)
|
|
||||||
}
|
|
||||||
domainRule.Type = dm.MatchingType_Regex
|
|
||||||
domainRule.Value = regexpVal
|
|
||||||
|
|
||||||
case strings.HasPrefix(domain, "domain:"):
|
|
||||||
domainName := domain[7:]
|
|
||||||
if len(domainName) == 0 {
|
|
||||||
return nil, newError("empty domain type of rule: ", domain)
|
|
||||||
}
|
|
||||||
domainRule.Type = dm.MatchingType_Subdomain
|
|
||||||
domainRule.Value = domainName
|
|
||||||
|
|
||||||
case strings.HasPrefix(domain, "full:"):
|
|
||||||
fullVal := domain[5:]
|
|
||||||
if len(fullVal) == 0 {
|
|
||||||
return nil, newError("empty full domain type of rule: ", domain)
|
|
||||||
}
|
|
||||||
domainRule.Type = dm.MatchingType_Full
|
|
||||||
domainRule.Value = fullVal
|
|
||||||
|
|
||||||
case strings.HasPrefix(domain, "keyword:"):
|
|
||||||
keywordVal := domain[8:]
|
|
||||||
if len(keywordVal) == 0 {
|
|
||||||
return nil, newError("empty keyword type of rule: ", domain)
|
|
||||||
}
|
|
||||||
domainRule.Type = dm.MatchingType_Keyword
|
|
||||||
domainRule.Value = keywordVal
|
|
||||||
|
|
||||||
case strings.HasPrefix(domain, "dotless:"):
|
|
||||||
domainRule.Type = dm.MatchingType_Regex
|
|
||||||
switch substr := domain[8:]; {
|
|
||||||
case substr == "":
|
|
||||||
domainRule.Value = "^[^.]*$"
|
|
||||||
case !strings.Contains(substr, "."):
|
|
||||||
domainRule.Value = "^[^.]*" + substr + "[^.]*$"
|
|
||||||
default:
|
|
||||||
return nil, newError("substr in dotless rule should not contain a dot: ", substr)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
domainRule.Type = dm.MatchingType_Keyword
|
|
||||||
domainRule.Value = domain
|
|
||||||
}
|
|
||||||
return []*dm.Domain{domainRule}, nil
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
package conf
|
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
|
||||||
}
|
|
@@ -1,3 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
|
@@ -1,229 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.25.0
|
|
||||||
// protoc v3.15.6
|
|
||||||
// source: common/matcher/domain/domain.proto
|
|
||||||
|
|
||||||
package domain
|
|
||||||
|
|
||||||
import (
|
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
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)
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type MatchingType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
MatchingType_Full MatchingType = 0
|
|
||||||
MatchingType_Subdomain MatchingType = 1
|
|
||||||
MatchingType_Keyword MatchingType = 2
|
|
||||||
MatchingType_Regex MatchingType = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for MatchingType.
|
|
||||||
var (
|
|
||||||
MatchingType_name = map[int32]string{
|
|
||||||
0: "Full",
|
|
||||||
1: "Subdomain",
|
|
||||||
2: "Keyword",
|
|
||||||
3: "Regex",
|
|
||||||
}
|
|
||||||
MatchingType_value = map[string]int32{
|
|
||||||
"Full": 0,
|
|
||||||
"Subdomain": 1,
|
|
||||||
"Keyword": 2,
|
|
||||||
"Regex": 3,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x MatchingType) Enum() *MatchingType {
|
|
||||||
p := new(MatchingType)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x MatchingType) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (MatchingType) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_common_matcher_domain_domain_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (MatchingType) Type() protoreflect.EnumType {
|
|
||||||
return &file_common_matcher_domain_domain_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x MatchingType) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use MatchingType.Descriptor instead.
|
|
||||||
func (MatchingType) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_domain_domain_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Domain struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// Domain matching type.
|
|
||||||
Type MatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.common.matcher.domain.MatchingType" json:"type,omitempty"`
|
|
||||||
// Domain value.
|
|
||||||
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) Reset() {
|
|
||||||
*x = Domain{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_matcher_domain_domain_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Domain) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *Domain) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_matcher_domain_domain_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 Domain.ProtoReflect.Descriptor instead.
|
|
||||||
func (*Domain) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_domain_domain_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) GetType() MatchingType {
|
|
||||||
if x != nil {
|
|
||||||
return x.Type
|
|
||||||
}
|
|
||||||
return MatchingType_Full
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) GetValue() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Value
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_common_matcher_domain_domain_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_common_matcher_domain_domain_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x22, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
|
|
||||||
0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x70,
|
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
|
||||||
0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
|
||||||
0x22, 0x5c, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3c, 0x0a, 0x04, 0x74, 0x79,
|
|
||||||
0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64,
|
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 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, 0x2a, 0x3f,
|
|
||||||
0x0a, 0x0c, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08,
|
|
||||||
0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64,
|
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f,
|
|
||||||
0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x42,
|
|
||||||
0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
|
||||||
0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
|
||||||
0x6e, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
|
||||||
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63,
|
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x64, 0x6f,
|
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0xaa, 0x02, 0x1a, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
|
||||||
0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
|
||||||
0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_common_matcher_domain_domain_proto_rawDescOnce sync.Once
|
|
||||||
file_common_matcher_domain_domain_proto_rawDescData = file_common_matcher_domain_domain_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_common_matcher_domain_domain_proto_rawDescGZIP() []byte {
|
|
||||||
file_common_matcher_domain_domain_proto_rawDescOnce.Do(func() {
|
|
||||||
file_common_matcher_domain_domain_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_matcher_domain_domain_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_common_matcher_domain_domain_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_common_matcher_domain_domain_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
|
||||||
var file_common_matcher_domain_domain_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
|
||||||
var file_common_matcher_domain_domain_proto_goTypes = []interface{}{
|
|
||||||
(MatchingType)(0), // 0: xray.common.matcher.domain.MatchingType
|
|
||||||
(*Domain)(nil), // 1: xray.common.matcher.domain.Domain
|
|
||||||
}
|
|
||||||
var file_common_matcher_domain_domain_proto_depIdxs = []int32{
|
|
||||||
0, // 0: xray.common.matcher.domain.Domain.type:type_name -> xray.common.matcher.domain.MatchingType
|
|
||||||
1, // [1:1] is the sub-list for method output_type
|
|
||||||
1, // [1:1] is the sub-list for method input_type
|
|
||||||
1, // [1:1] is the sub-list for extension type_name
|
|
||||||
1, // [1:1] is the sub-list for extension extendee
|
|
||||||
0, // [0:1] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_common_matcher_domain_domain_proto_init() }
|
|
||||||
func file_common_matcher_domain_domain_proto_init() {
|
|
||||||
if File_common_matcher_domain_domain_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_common_matcher_domain_domain_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Domain); 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_common_matcher_domain_domain_proto_rawDesc,
|
|
||||||
NumEnums: 1,
|
|
||||||
NumMessages: 1,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 0,
|
|
||||||
},
|
|
||||||
GoTypes: file_common_matcher_domain_domain_proto_goTypes,
|
|
||||||
DependencyIndexes: file_common_matcher_domain_domain_proto_depIdxs,
|
|
||||||
EnumInfos: file_common_matcher_domain_domain_proto_enumTypes,
|
|
||||||
MessageInfos: file_common_matcher_domain_domain_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_common_matcher_domain_domain_proto = out.File
|
|
||||||
file_common_matcher_domain_domain_proto_rawDesc = nil
|
|
||||||
file_common_matcher_domain_domain_proto_goTypes = nil
|
|
||||||
file_common_matcher_domain_domain_proto_depIdxs = nil
|
|
||||||
}
|
|
@@ -1,39 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package xray.common.matcher.domain;
|
|
||||||
option csharp_namespace = "Xray.Common.Matcher.Domain";
|
|
||||||
option go_package = "github.com/xtls/xray-core/common/matcher/domain";
|
|
||||||
option java_package = "com.xray.common.matcher.domain";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
|
|
||||||
enum MatchingType {
|
|
||||||
Full = 0;
|
|
||||||
Subdomain = 1;
|
|
||||||
Keyword = 2;
|
|
||||||
Regex = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Domain {
|
|
||||||
// Domain matching type.
|
|
||||||
MatchingType type = 1;
|
|
||||||
|
|
||||||
// Domain value.
|
|
||||||
string value = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
func toDomainMatchingType(t router.Domain_Type) dns.DomainMatchingType {
|
|
||||||
switch t {
|
|
||||||
case router.Domain_Domain:
|
|
||||||
return dns.DomainMatchingType_Subdomain
|
|
||||||
case router.Domain_Full:
|
|
||||||
return dns.DomainMatchingType_Full
|
|
||||||
case router.Domain_Plain:
|
|
||||||
return dns.DomainMatchingType_Keyword
|
|
||||||
case router.Domain_Regex:
|
|
||||||
return dns.DomainMatchingType_Regex
|
|
||||||
default:
|
|
||||||
panic("unknown domain type")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
@@ -1,9 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
|
||||||
}
|
|
@@ -1,79 +0,0 @@
|
|||||||
package domain
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/matcher/str"
|
|
||||||
"github.com/xtls/xray-core/features/routing"
|
|
||||||
)
|
|
||||||
|
|
||||||
var matcherTypeMap = map[MatchingType]str.Type{
|
|
||||||
MatchingType_Keyword: str.Substr,
|
|
||||||
MatchingType_Regex: str.Regex,
|
|
||||||
MatchingType_Subdomain: str.Domain,
|
|
||||||
MatchingType_Full: str.Full,
|
|
||||||
}
|
|
||||||
|
|
||||||
func domainToMatcher(domain *Domain) (str.Matcher, error) {
|
|
||||||
matcherType, f := matcherTypeMap[domain.Type]
|
|
||||||
if !f {
|
|
||||||
return nil, newError("unsupported domain type", domain.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher, err := matcherType.New(domain.Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to create domain matcher").Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return matcher, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainMatcher struct {
|
|
||||||
matchers str.IndexMatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
|
|
||||||
g := str.NewMphMatcherGroup()
|
|
||||||
for _, d := range domains {
|
|
||||||
matcherType, f := matcherTypeMap[d.Type]
|
|
||||||
if !f {
|
|
||||||
return nil, newError("unsupported domain type", d.Type)
|
|
||||||
}
|
|
||||||
_, err := g.AddPattern(d.Value, matcherType)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g.Build()
|
|
||||||
return &DomainMatcher{
|
|
||||||
matchers: g,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) {
|
|
||||||
g := new(str.MatcherGroup)
|
|
||||||
for _, d := range domains {
|
|
||||||
m, err := domainToMatcher(d)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
g.Add(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DomainMatcher{
|
|
||||||
matchers: g,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *DomainMatcher) ApplyDomain(domain string) bool {
|
|
||||||
return len(m.matchers.Match(strings.ToLower(domain))) > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply implements Condition.
|
|
||||||
func (m *DomainMatcher) Apply(ctx routing.Context) bool {
|
|
||||||
domain := ctx.GetTargetDomain()
|
|
||||||
if len(domain) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return m.ApplyDomain(domain)
|
|
||||||
}
|
|
@@ -1,224 +0,0 @@
|
|||||||
package geoip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
FileCache = make(map[string][]byte)
|
|
||||||
IPCache = make(map[string]*GeoIP)
|
|
||||||
)
|
|
||||||
|
|
||||||
func LoadGeoIP(code string) ([]*CIDR, error) {
|
|
||||||
return LoadIPFile("geoip.dat", code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoadIPFile(file, code string) ([]*CIDR, error) {
|
|
||||||
index := file + ":" + code
|
|
||||||
if IPCache[index] == nil {
|
|
||||||
bs, err := loadFile(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to load file: ", file).Base(err)
|
|
||||||
}
|
|
||||||
bs = find(bs, []byte(code))
|
|
||||||
if bs == nil {
|
|
||||||
return nil, newError("code not found in ", file, ": ", code)
|
|
||||||
}
|
|
||||||
var geoipdat GeoIP
|
|
||||||
if err := proto.Unmarshal(bs, &geoipdat); err != nil {
|
|
||||||
return nil, newError("error unmarshal IP in ", file, ": ", code).Base(err)
|
|
||||||
}
|
|
||||||
defer runtime.GC() // or debug.FreeOSMemory()
|
|
||||||
return geoipdat.Cidr, nil // do not cache geoip
|
|
||||||
// IPCache[index] = &geoipdat
|
|
||||||
}
|
|
||||||
return IPCache[index].Cidr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadFile(file string) ([]byte, error) {
|
|
||||||
if FileCache[file] == nil {
|
|
||||||
bs, err := filesystem.ReadAsset(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to open file: ", file).Base(err)
|
|
||||||
}
|
|
||||||
if len(bs) == 0 {
|
|
||||||
return nil, newError("empty file: ", file)
|
|
||||||
}
|
|
||||||
// Do not cache file, may save RAM when there
|
|
||||||
// are many files, but consume CPU each time.
|
|
||||||
return bs, nil
|
|
||||||
// FileCache[file] = bs
|
|
||||||
}
|
|
||||||
return FileCache[file], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func find(data, code []byte) []byte {
|
|
||||||
codeL := len(code)
|
|
||||||
if codeL == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
dataL := len(data)
|
|
||||||
if dataL < 2 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
x, y := proto.DecodeVarint(data[1:])
|
|
||||||
if x == 0 && y == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
headL, bodyL := 1+y, int(x)
|
|
||||||
dataL -= headL
|
|
||||||
if dataL < bodyL {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = data[headL:]
|
|
||||||
if int(data[1]) == codeL {
|
|
||||||
for i := 0; i < codeL && data[2+i] == code[i]; i++ {
|
|
||||||
if i+1 == codeL {
|
|
||||||
return data[:bodyL]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dataL == bodyL {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = data[bodyL:]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseIPList(ips []string) ([]*GeoIP, error) {
|
|
||||||
var geoipList []*GeoIP
|
|
||||||
var customCidrs []*CIDR
|
|
||||||
|
|
||||||
for _, ip := range ips {
|
|
||||||
if strings.HasPrefix(ip, "geoip:") {
|
|
||||||
country := ip[6:]
|
|
||||||
isReverseMatch := false
|
|
||||||
if strings.HasPrefix(country, "!") {
|
|
||||||
country = country[1:]
|
|
||||||
isReverseMatch = true
|
|
||||||
}
|
|
||||||
|
|
||||||
geoipc, err := LoadGeoIP(strings.ToUpper(country))
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to load GeoIP: ", country).Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
geoipList = append(geoipList, &GeoIP{
|
|
||||||
CountryCode: strings.ToUpper(country),
|
|
||||||
Cidr: geoipc,
|
|
||||||
ReverseMatch: isReverseMatch,
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var isExtDatFile = 0
|
|
||||||
{
|
|
||||||
const prefix = "ext:"
|
|
||||||
if strings.HasPrefix(ip, prefix) {
|
|
||||||
isExtDatFile = len(prefix)
|
|
||||||
}
|
|
||||||
const prefixQualified = "ext-ip:"
|
|
||||||
if strings.HasPrefix(ip, prefixQualified) {
|
|
||||||
isExtDatFile = len(prefixQualified)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isExtDatFile != 0 {
|
|
||||||
kv := strings.Split(ip[isExtDatFile:], ":")
|
|
||||||
if len(kv) != 2 {
|
|
||||||
return nil, newError("invalid external resource: ", ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
filename := kv[0]
|
|
||||||
country := kv[1]
|
|
||||||
if len(filename) == 0 || len(country) == 0 {
|
|
||||||
return nil, newError("empty filename or empty country in rule")
|
|
||||||
}
|
|
||||||
|
|
||||||
isReverseMatch := false
|
|
||||||
if strings.HasPrefix(country, "!") {
|
|
||||||
country = country[1:]
|
|
||||||
isReverseMatch = true
|
|
||||||
}
|
|
||||||
geoipc, err := LoadIPFile(filename, strings.ToUpper(country))
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to load IPs: ", country, " from ", filename).Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
geoipList = append(geoipList, &GeoIP{
|
|
||||||
CountryCode: strings.ToUpper(filename + "_" + country),
|
|
||||||
Cidr: geoipc,
|
|
||||||
ReverseMatch: isReverseMatch,
|
|
||||||
})
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ipRule, err := ParseIP(ip)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("invalid IP: ", ip).Base(err)
|
|
||||||
}
|
|
||||||
customCidrs = append(customCidrs, ipRule)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(customCidrs) > 0 {
|
|
||||||
geoipList = append(geoipList, &GeoIP{
|
|
||||||
Cidr: customCidrs,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return geoipList, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseIP(s string) (*CIDR, error) {
|
|
||||||
var addr, mask string
|
|
||||||
i := strings.Index(s, "/")
|
|
||||||
if i < 0 {
|
|
||||||
addr = s
|
|
||||||
} else {
|
|
||||||
addr = s[:i]
|
|
||||||
mask = s[i+1:]
|
|
||||||
}
|
|
||||||
ip := net.ParseAddress(addr)
|
|
||||||
switch ip.Family() {
|
|
||||||
case net.AddressFamilyIPv4:
|
|
||||||
bits := uint32(32)
|
|
||||||
if len(mask) > 0 {
|
|
||||||
bits64, err := strconv.ParseUint(mask, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("invalid network mask for router: ", mask).Base(err)
|
|
||||||
}
|
|
||||||
bits = uint32(bits64)
|
|
||||||
}
|
|
||||||
if bits > 32 {
|
|
||||||
return nil, newError("invalid network mask for router: ", bits)
|
|
||||||
}
|
|
||||||
return &CIDR{
|
|
||||||
Ip: ip.IP(),
|
|
||||||
Prefix: bits,
|
|
||||||
}, nil
|
|
||||||
case net.AddressFamilyIPv6:
|
|
||||||
bits := uint32(128)
|
|
||||||
if len(mask) > 0 {
|
|
||||||
bits64, err := strconv.ParseUint(mask, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("invalid network mask for router: ", mask).Base(err)
|
|
||||||
}
|
|
||||||
bits = uint32(bits64)
|
|
||||||
}
|
|
||||||
if bits > 128 {
|
|
||||||
return nil, newError("invalid network mask for router: ", bits)
|
|
||||||
}
|
|
||||||
return &CIDR{
|
|
||||||
Ip: ip.IP(),
|
|
||||||
Prefix: bits,
|
|
||||||
}, nil
|
|
||||||
default:
|
|
||||||
return nil, newError("unsupported address for router: ", s)
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,40 +0,0 @@
|
|||||||
package geoip
|
|
||||||
|
|
||||||
// CIDRList is an alias of []*CIDR to provide sort.Interface.
|
|
||||||
type CIDRList []*CIDR
|
|
||||||
|
|
||||||
// Len implements sort.Interface.
|
|
||||||
func (l *CIDRList) Len() int {
|
|
||||||
return len(*l)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Less implements sort.Interface.
|
|
||||||
func (l *CIDRList) Less(i int, j int) bool {
|
|
||||||
ci := (*l)[i]
|
|
||||||
cj := (*l)[j]
|
|
||||||
|
|
||||||
if len(ci.Ip) < len(cj.Ip) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(ci.Ip) > len(cj.Ip) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
for k := 0; k < len(ci.Ip); k++ {
|
|
||||||
if ci.Ip[k] < cj.Ip[k] {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if ci.Ip[k] > cj.Ip[k] {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ci.Prefix < cj.Prefix
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap implements sort.Interface.
|
|
||||||
func (l *CIDRList) Swap(i int, j int) {
|
|
||||||
(*l)[i], (*l)[j] = (*l)[j], (*l)[i]
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
package geoip
|
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
|
||||||
}
|
|
@@ -1,317 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.25.0
|
|
||||||
// protoc v3.15.7
|
|
||||||
// source: common/matcher/geoip/geoip.proto
|
|
||||||
|
|
||||||
package geoip
|
|
||||||
|
|
||||||
import (
|
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
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)
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
// IP for routing decision, in CIDR form.
|
|
||||||
type CIDR struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// IP address, should be either 4 or 16 bytes.
|
|
||||||
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
|
|
||||||
// Number of leading ones in the network mask.
|
|
||||||
Prefix uint32 `protobuf:"varint,2,opt,name=prefix,proto3" json:"prefix,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CIDR) Reset() {
|
|
||||||
*x = CIDR{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CIDR) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*CIDR) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *CIDR) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_matcher_geoip_geoip_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 CIDR.ProtoReflect.Descriptor instead.
|
|
||||||
func (*CIDR) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_geoip_geoip_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CIDR) GetIp() []byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.Ip
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CIDR) GetPrefix() uint32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Prefix
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type GeoIP struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
|
||||||
Cidr []*CIDR `protobuf:"bytes,2,rep,name=cidr,proto3" json:"cidr,omitempty"`
|
|
||||||
ReverseMatch bool `protobuf:"varint,3,opt,name=reverse_match,json=reverseMatch,proto3" json:"reverse_match,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) Reset() {
|
|
||||||
*x = GeoIP{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[1]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GeoIP) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *GeoIP) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_matcher_geoip_geoip_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 GeoIP.ProtoReflect.Descriptor instead.
|
|
||||||
func (*GeoIP) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_geoip_geoip_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) GetCountryCode() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.CountryCode
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) GetCidr() []*CIDR {
|
|
||||||
if x != nil {
|
|
||||||
return x.Cidr
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIP) GetReverseMatch() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.ReverseMatch
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type GeoIPList struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Entry []*GeoIP `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIPList) Reset() {
|
|
||||||
*x = GeoIPList{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_matcher_geoip_geoip_proto_msgTypes[2]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIPList) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GeoIPList) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *GeoIPList) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_matcher_geoip_geoip_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 GeoIPList.ProtoReflect.Descriptor instead.
|
|
||||||
func (*GeoIPList) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_geoip_geoip_proto_rawDescGZIP(), []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoIPList) GetEntry() []*GeoIP {
|
|
||||||
if x != nil {
|
|
||||||
return x.Entry
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_common_matcher_geoip_geoip_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_common_matcher_geoip_geoip_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
|
|
||||||
0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x70, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x12, 0x19, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
|
||||||
0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x69, 0x70, 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, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67,
|
|
||||||
0x65, 0x6f, 0x69, 0x70, 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, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d,
|
|
||||||
0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x2e, 0x47, 0x65, 0x6f,
|
|
||||||
0x49, 0x50, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d,
|
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74,
|
|
||||||
0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69,
|
|
||||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72,
|
|
||||||
0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d,
|
|
||||||
0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0xaa, 0x02, 0x19, 0x58,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x63, 0x68,
|
|
||||||
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_common_matcher_geoip_geoip_proto_rawDescOnce sync.Once
|
|
||||||
file_common_matcher_geoip_geoip_proto_rawDescData = file_common_matcher_geoip_geoip_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_common_matcher_geoip_geoip_proto_rawDescGZIP() []byte {
|
|
||||||
file_common_matcher_geoip_geoip_proto_rawDescOnce.Do(func() {
|
|
||||||
file_common_matcher_geoip_geoip_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_matcher_geoip_geoip_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_common_matcher_geoip_geoip_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_common_matcher_geoip_geoip_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
|
||||||
var file_common_matcher_geoip_geoip_proto_goTypes = []interface{}{
|
|
||||||
(*CIDR)(nil), // 0: xray.common.matcher.geoip.CIDR
|
|
||||||
(*GeoIP)(nil), // 1: xray.common.matcher.geoip.GeoIP
|
|
||||||
(*GeoIPList)(nil), // 2: xray.common.matcher.geoip.GeoIPList
|
|
||||||
}
|
|
||||||
var file_common_matcher_geoip_geoip_proto_depIdxs = []int32{
|
|
||||||
0, // 0: xray.common.matcher.geoip.GeoIP.cidr:type_name -> xray.common.matcher.geoip.CIDR
|
|
||||||
1, // 1: xray.common.matcher.geoip.GeoIPList.entry:type_name -> xray.common.matcher.geoip.GeoIP
|
|
||||||
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_common_matcher_geoip_geoip_proto_init() }
|
|
||||||
func file_common_matcher_geoip_geoip_proto_init() {
|
|
||||||
if File_common_matcher_geoip_geoip_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_common_matcher_geoip_geoip_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*CIDR); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_common_matcher_geoip_geoip_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*GeoIP); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_common_matcher_geoip_geoip_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*GeoIPList); 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_common_matcher_geoip_geoip_proto_rawDesc,
|
|
||||||
NumEnums: 0,
|
|
||||||
NumMessages: 3,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 0,
|
|
||||||
},
|
|
||||||
GoTypes: file_common_matcher_geoip_geoip_proto_goTypes,
|
|
||||||
DependencyIndexes: file_common_matcher_geoip_geoip_proto_depIdxs,
|
|
||||||
MessageInfos: file_common_matcher_geoip_geoip_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_common_matcher_geoip_geoip_proto = out.File
|
|
||||||
file_common_matcher_geoip_geoip_proto_rawDesc = nil
|
|
||||||
file_common_matcher_geoip_geoip_proto_goTypes = nil
|
|
||||||
file_common_matcher_geoip_geoip_proto_depIdxs = nil
|
|
||||||
}
|
|
@@ -1,26 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package xray.common.matcher.geoip;
|
|
||||||
option csharp_namespace = "Xray.Common.Matcher.GeoIP";
|
|
||||||
option go_package = "github.com/xtls/xray-core/common/matcher/geoip";
|
|
||||||
option java_package = "com.xray.common.matcher.geoip";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
|
|
||||||
// IP for routing decision, in CIDR form.
|
|
||||||
message CIDR {
|
|
||||||
// IP address, should be either 4 or 16 bytes.
|
|
||||||
bytes ip = 1;
|
|
||||||
|
|
||||||
// Number of leading ones in the network mask.
|
|
||||||
uint32 prefix = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoIP {
|
|
||||||
string country_code = 1;
|
|
||||||
repeated CIDR cidr = 2;
|
|
||||||
bool reverse_match =3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoIPList {
|
|
||||||
repeated GeoIP entry = 1;
|
|
||||||
}
|
|
@@ -1,57 +0,0 @@
|
|||||||
package geoip
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/features/routing"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MultiGeoIPMatcher struct {
|
|
||||||
matchers []*GeoIPMatcher
|
|
||||||
onSource bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
|
||||||
var matchers []*GeoIPMatcher
|
|
||||||
for _, geoip := range geoips {
|
|
||||||
matcher, err := GlobalGeoIPContainer.Add(geoip)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
matchers = append(matchers, matcher)
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher := &MultiGeoIPMatcher{
|
|
||||||
matchers: matchers,
|
|
||||||
onSource: onSource,
|
|
||||||
}
|
|
||||||
|
|
||||||
return matcher, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply implements Condition.
|
|
||||||
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
|
||||||
var ips []net.IP
|
|
||||||
if m.onSource {
|
|
||||||
ips = ctx.GetSourceIPs()
|
|
||||||
} else {
|
|
||||||
ips = ctx.GetTargetIPs()
|
|
||||||
}
|
|
||||||
for _, ip := range ips {
|
|
||||||
for _, matcher := range m.matchers {
|
|
||||||
if matcher.Match(ip) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchIP match given ip.
|
|
||||||
func (m *MultiGeoIPMatcher) MatchIP(ip net.IP) bool {
|
|
||||||
for _, matcher := range m.matchers {
|
|
||||||
if matcher.Match(ip) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
@@ -1,35 +0,0 @@
|
|||||||
package geosite
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
type AttributeList struct {
|
|
||||||
matcher []AttributeMatcher
|
|
||||||
}
|
|
||||||
|
|
||||||
func (al *AttributeList) Match(domain *Domain) bool {
|
|
||||||
for _, matcher := range al.matcher {
|
|
||||||
if !matcher.Match(domain) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (al *AttributeList) IsEmpty() bool {
|
|
||||||
return len(al.matcher) == 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type AttributeMatcher interface {
|
|
||||||
Match(*Domain) bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type BooleanMatcher string
|
|
||||||
|
|
||||||
func (m BooleanMatcher) Match(domain *Domain) bool {
|
|
||||||
for _, attr := range domain.Attribute {
|
|
||||||
if strings.EqualFold(attr.GetKey(), string(m)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
@@ -1,42 +0,0 @@
|
|||||||
package geosite
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
dm "github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
)
|
|
||||||
|
|
||||||
func LoadGeositeWithAttr(file string, siteWithAttr string) ([]*dm.Domain, error) {
|
|
||||||
parts := strings.Split(siteWithAttr, "@")
|
|
||||||
if len(parts) == 0 {
|
|
||||||
return nil, newError("empty site")
|
|
||||||
}
|
|
||||||
country := strings.ToUpper(parts[0])
|
|
||||||
attrs := parseAttrs(parts[1:])
|
|
||||||
domains, err := loadSite(file, country)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if attrs.IsEmpty() {
|
|
||||||
return ToDomains(domains), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
filteredDomains := make([]*dm.Domain, 0, len(domains))
|
|
||||||
for _, domain := range domains {
|
|
||||||
if attrs.Match(domain) {
|
|
||||||
filteredDomains = append(filteredDomains, domain.ToDomain())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filteredDomains, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAttrs(attrs []string) *AttributeList {
|
|
||||||
al := new(AttributeList)
|
|
||||||
for _, attr := range attrs {
|
|
||||||
lc := strings.ToLower(attr)
|
|
||||||
al.matcher = append(al.matcher, BooleanMatcher(lc))
|
|
||||||
}
|
|
||||||
return al
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
package geosite
|
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
|
||||||
}
|
|
@@ -1,86 +0,0 @@
|
|||||||
package geosite
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
SiteCache = make(map[string]*GeoSite)
|
|
||||||
FileCache = make(map[string][]byte)
|
|
||||||
)
|
|
||||||
|
|
||||||
func loadFile(file string) ([]byte, error) {
|
|
||||||
if FileCache[file] == nil {
|
|
||||||
bs, err := filesystem.ReadAsset(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to open file: ", file).Base(err)
|
|
||||||
}
|
|
||||||
if len(bs) == 0 {
|
|
||||||
return nil, newError("empty file: ", file)
|
|
||||||
}
|
|
||||||
// Do not cache file, may save RAM when there
|
|
||||||
// are many files, but consume CPU each time.
|
|
||||||
return bs, nil
|
|
||||||
FileCache[file] = bs
|
|
||||||
}
|
|
||||||
return FileCache[file], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadSite(file, code string) ([]*Domain, error) {
|
|
||||||
index := file + ":" + code
|
|
||||||
if SiteCache[index] == nil {
|
|
||||||
bs, err := loadFile(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to load file: ", file).Base(err)
|
|
||||||
}
|
|
||||||
bs = find(bs, []byte(code))
|
|
||||||
if bs == nil {
|
|
||||||
return nil, newError("list not found in ", file, ": ", code)
|
|
||||||
}
|
|
||||||
var ges GeoSite
|
|
||||||
if err := proto.Unmarshal(bs, &ges); err != nil {
|
|
||||||
return nil, newError("error unmarshal Site in ", file, ": ", code).Base(err)
|
|
||||||
}
|
|
||||||
defer runtime.GC() // or debug.FreeOSMemory()
|
|
||||||
return ges.Domain, nil // do not cache geosite
|
|
||||||
SiteCache[index] = &ges
|
|
||||||
}
|
|
||||||
return SiteCache[index].Domain, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func find(data, code []byte) []byte {
|
|
||||||
codeL := len(code)
|
|
||||||
if codeL == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
dataL := len(data)
|
|
||||||
if dataL < 2 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
x, y := proto.DecodeVarint(data[1:])
|
|
||||||
if x == 0 && y == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
headL, bodyL := 1+y, int(x)
|
|
||||||
dataL -= headL
|
|
||||||
if dataL < bodyL {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = data[headL:]
|
|
||||||
if int(data[1]) == codeL {
|
|
||||||
for i := 0; i < codeL && data[2+i] == code[i]; i++ {
|
|
||||||
if i+1 == codeL {
|
|
||||||
return data[:bodyL]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if dataL == bodyL {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
data = data[bodyL:]
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,33 +0,0 @@
|
|||||||
package geosite
|
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/common/matcher/domain"
|
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
|
||||||
|
|
||||||
func ToDomains(dms []*Domain) []*domain.Domain {
|
|
||||||
dm := make([]*domain.Domain, len(dms))
|
|
||||||
|
|
||||||
for idx, entry := range dms {
|
|
||||||
dm[idx] = entry.ToDomain()
|
|
||||||
}
|
|
||||||
|
|
||||||
return dm
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Domain) ToDomain() *domain.Domain {
|
|
||||||
return &domain.Domain{Type: d.Type.ToMatchingType(), Value: d.Value}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t Domain_Type) ToMatchingType() domain.MatchingType {
|
|
||||||
switch t {
|
|
||||||
case Domain_Plain:
|
|
||||||
return domain.MatchingType_Keyword
|
|
||||||
case Domain_Regex:
|
|
||||||
return domain.MatchingType_Regex
|
|
||||||
case Domain_Domain:
|
|
||||||
return domain.MatchingType_Subdomain
|
|
||||||
case Domain_Full:
|
|
||||||
return domain.MatchingType_Full
|
|
||||||
}
|
|
||||||
panic("impossible")
|
|
||||||
}
|
|
@@ -1,501 +0,0 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.25.0
|
|
||||||
// protoc v3.15.6
|
|
||||||
// source: common/matcher/geosite/geosite.proto
|
|
||||||
|
|
||||||
package geosite
|
|
||||||
|
|
||||||
import (
|
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
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)
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type Domain_Type int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
// The value is used as is.
|
|
||||||
Domain_Plain Domain_Type = 0
|
|
||||||
// The value is used as a regular expression.
|
|
||||||
Domain_Regex Domain_Type = 1
|
|
||||||
// The value is a root domain.
|
|
||||||
Domain_Domain Domain_Type = 2
|
|
||||||
// The value is a domain.
|
|
||||||
Domain_Full Domain_Type = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for Domain_Type.
|
|
||||||
var (
|
|
||||||
Domain_Type_name = map[int32]string{
|
|
||||||
0: "Plain",
|
|
||||||
1: "Regex",
|
|
||||||
2: "Domain",
|
|
||||||
3: "Full",
|
|
||||||
}
|
|
||||||
Domain_Type_value = map[string]int32{
|
|
||||||
"Plain": 0,
|
|
||||||
"Regex": 1,
|
|
||||||
"Domain": 2,
|
|
||||||
"Full": 3,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x Domain_Type) Enum() *Domain_Type {
|
|
||||||
p := new(Domain_Type)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Domain_Type) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Domain_Type) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_common_matcher_geosite_geosite_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Domain_Type) Type() protoreflect.EnumType {
|
|
||||||
return &file_common_matcher_geosite_geosite_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Domain_Type) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use Domain_Type.Descriptor instead.
|
|
||||||
func (Domain_Type) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Domain struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// Domain matching type.
|
|
||||||
Type Domain_Type `protobuf:"varint,1,opt,name=type,proto3,enum=xray.common.matcher.geosite.Domain_Type" json:"type,omitempty"`
|
|
||||||
// Domain value.
|
|
||||||
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
|
||||||
// Attributes of this domain. May be used for filtering.
|
|
||||||
Attribute []*Domain_Attribute `protobuf:"bytes,3,rep,name=attribute,proto3" json:"attribute,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) Reset() {
|
|
||||||
*x = Domain{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Domain) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *Domain) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_matcher_geosite_geosite_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 Domain.ProtoReflect.Descriptor instead.
|
|
||||||
func (*Domain) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) GetType() Domain_Type {
|
|
||||||
if x != nil {
|
|
||||||
return x.Type
|
|
||||||
}
|
|
||||||
return Domain_Plain
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) GetValue() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Value
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain) GetAttribute() []*Domain_Attribute {
|
|
||||||
if x != nil {
|
|
||||||
return x.Attribute
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GeoSite struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
|
||||||
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoSite) Reset() {
|
|
||||||
*x = GeoSite{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[1]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoSite) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GeoSite) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *GeoSite) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_matcher_geosite_geosite_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 GeoSite.ProtoReflect.Descriptor instead.
|
|
||||||
func (*GeoSite) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoSite) GetCountryCode() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.CountryCode
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoSite) GetDomain() []*Domain {
|
|
||||||
if x != nil {
|
|
||||||
return x.Domain
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GeoSiteList struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Entry []*GeoSite `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoSiteList) Reset() {
|
|
||||||
*x = GeoSiteList{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[2]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoSiteList) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*GeoSiteList) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *GeoSiteList) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_matcher_geosite_geosite_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 GeoSiteList.ProtoReflect.Descriptor instead.
|
|
||||||
func (*GeoSiteList) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{2}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *GeoSiteList) GetEntry() []*GeoSite {
|
|
||||||
if x != nil {
|
|
||||||
return x.Entry
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Domain_Attribute struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
|
||||||
// Types that are assignable to TypedValue:
|
|
||||||
// *Domain_Attribute_BoolValue
|
|
||||||
// *Domain_Attribute_IntValue
|
|
||||||
TypedValue isDomain_Attribute_TypedValue `protobuf_oneof:"typed_value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain_Attribute) Reset() {
|
|
||||||
*x = Domain_Attribute{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_common_matcher_geosite_geosite_proto_msgTypes[3]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain_Attribute) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Domain_Attribute) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_common_matcher_geosite_geosite_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 Domain_Attribute.ProtoReflect.Descriptor instead.
|
|
||||||
func (*Domain_Attribute) Descriptor() ([]byte, []int) {
|
|
||||||
return file_common_matcher_geosite_geosite_proto_rawDescGZIP(), []int{0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain_Attribute) GetKey() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Key
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Domain_Attribute) GetTypedValue() isDomain_Attribute_TypedValue {
|
|
||||||
if m != nil {
|
|
||||||
return m.TypedValue
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain_Attribute) GetBoolValue() bool {
|
|
||||||
if x, ok := x.GetTypedValue().(*Domain_Attribute_BoolValue); ok {
|
|
||||||
return x.BoolValue
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Domain_Attribute) GetIntValue() int64 {
|
|
||||||
if x, ok := x.GetTypedValue().(*Domain_Attribute_IntValue); ok {
|
|
||||||
return x.IntValue
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type isDomain_Attribute_TypedValue interface {
|
|
||||||
isDomain_Attribute_TypedValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
type Domain_Attribute_BoolValue struct {
|
|
||||||
BoolValue bool `protobuf:"varint,2,opt,name=bool_value,json=boolValue,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Domain_Attribute_IntValue struct {
|
|
||||||
IntValue int64 `protobuf:"varint,3,opt,name=int_value,json=intValue,proto3,oneof"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Domain_Attribute_BoolValue) isDomain_Attribute_TypedValue() {}
|
|
||||||
|
|
||||||
func (*Domain_Attribute_IntValue) isDomain_Attribute_TypedValue() {}
|
|
||||||
|
|
||||||
var File_common_matcher_geosite_geosite_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_common_matcher_geosite_geosite_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x24, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
|
|
||||||
0x2f, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2f, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65,
|
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1b, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73,
|
|
||||||
0x69, 0x74, 0x65, 0x22, 0xcb, 0x02, 0x0a, 0x06, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3c,
|
|
||||||
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68,
|
|
||||||
0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 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, 0x4b, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x18,
|
|
||||||
0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73,
|
|
||||||
0x69, 0x74, 0x65, 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, 0x69, 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,
|
|
||||||
0x3b, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
|
||||||
0x23, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61,
|
|
||||||
0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2e, 0x44, 0x6f,
|
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x49, 0x0a, 0x0b,
|
|
||||||
0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3a, 0x0a, 0x05, 0x65,
|
|
||||||
0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
|
|
||||||
0x2e, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65,
|
|
||||||
0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x73, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68,
|
|
||||||
0x65, 0x72, 0x2e, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69,
|
|
||||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72,
|
|
||||||
0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6d,
|
|
||||||
0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2f, 0x67, 0x65, 0x6f, 0x73, 0x69, 0x74, 0x65, 0xaa, 0x02,
|
|
||||||
0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74,
|
|
||||||
0x63, 0x68, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x62, 0x06, 0x70, 0x72,
|
|
||||||
0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_common_matcher_geosite_geosite_proto_rawDescOnce sync.Once
|
|
||||||
file_common_matcher_geosite_geosite_proto_rawDescData = file_common_matcher_geosite_geosite_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_common_matcher_geosite_geosite_proto_rawDescGZIP() []byte {
|
|
||||||
file_common_matcher_geosite_geosite_proto_rawDescOnce.Do(func() {
|
|
||||||
file_common_matcher_geosite_geosite_proto_rawDescData = protoimpl.X.CompressGZIP(file_common_matcher_geosite_geosite_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_common_matcher_geosite_geosite_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_common_matcher_geosite_geosite_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
|
||||||
var file_common_matcher_geosite_geosite_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
|
||||||
var file_common_matcher_geosite_geosite_proto_goTypes = []interface{}{
|
|
||||||
(Domain_Type)(0), // 0: xray.common.matcher.geosite.Domain.Type
|
|
||||||
(*Domain)(nil), // 1: xray.common.matcher.geosite.Domain
|
|
||||||
(*GeoSite)(nil), // 2: xray.common.matcher.geosite.GeoSite
|
|
||||||
(*GeoSiteList)(nil), // 3: xray.common.matcher.geosite.GeoSiteList
|
|
||||||
(*Domain_Attribute)(nil), // 4: xray.common.matcher.geosite.Domain.Attribute
|
|
||||||
}
|
|
||||||
var file_common_matcher_geosite_geosite_proto_depIdxs = []int32{
|
|
||||||
0, // 0: xray.common.matcher.geosite.Domain.type:type_name -> xray.common.matcher.geosite.Domain.Type
|
|
||||||
4, // 1: xray.common.matcher.geosite.Domain.attribute:type_name -> xray.common.matcher.geosite.Domain.Attribute
|
|
||||||
1, // 2: xray.common.matcher.geosite.GeoSite.domain:type_name -> xray.common.matcher.geosite.Domain
|
|
||||||
2, // 3: xray.common.matcher.geosite.GeoSiteList.entry:type_name -> xray.common.matcher.geosite.GeoSite
|
|
||||||
4, // [4:4] is the sub-list for method output_type
|
|
||||||
4, // [4:4] is the sub-list for method input_type
|
|
||||||
4, // [4:4] is the sub-list for extension type_name
|
|
||||||
4, // [4:4] is the sub-list for extension extendee
|
|
||||||
0, // [0:4] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_common_matcher_geosite_geosite_proto_init() }
|
|
||||||
func file_common_matcher_geosite_geosite_proto_init() {
|
|
||||||
if File_common_matcher_geosite_geosite_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_common_matcher_geosite_geosite_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Domain); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_common_matcher_geosite_geosite_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*GeoSite); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_common_matcher_geosite_geosite_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*GeoSiteList); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_common_matcher_geosite_geosite_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Domain_Attribute); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_common_matcher_geosite_geosite_proto_msgTypes[3].OneofWrappers = []interface{}{
|
|
||||||
(*Domain_Attribute_BoolValue)(nil),
|
|
||||||
(*Domain_Attribute_IntValue)(nil),
|
|
||||||
}
|
|
||||||
type x struct{}
|
|
||||||
out := protoimpl.TypeBuilder{
|
|
||||||
File: protoimpl.DescBuilder{
|
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
||||||
RawDescriptor: file_common_matcher_geosite_geosite_proto_rawDesc,
|
|
||||||
NumEnums: 1,
|
|
||||||
NumMessages: 4,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 0,
|
|
||||||
},
|
|
||||||
GoTypes: file_common_matcher_geosite_geosite_proto_goTypes,
|
|
||||||
DependencyIndexes: file_common_matcher_geosite_geosite_proto_depIdxs,
|
|
||||||
EnumInfos: file_common_matcher_geosite_geosite_proto_enumTypes,
|
|
||||||
MessageInfos: file_common_matcher_geosite_geosite_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_common_matcher_geosite_geosite_proto = out.File
|
|
||||||
file_common_matcher_geosite_geosite_proto_rawDesc = nil
|
|
||||||
file_common_matcher_geosite_geosite_proto_goTypes = nil
|
|
||||||
file_common_matcher_geosite_geosite_proto_depIdxs = nil
|
|
||||||
}
|
|
@@ -1,46 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package xray.common.matcher.geosite;
|
|
||||||
option csharp_namespace = "Xray.Common.Matcher.GeoSite";
|
|
||||||
option go_package = "github.com/xtls/xray-core/common/matcher/geosite";
|
|
||||||
option java_package = "com.xray.common.matcher.geosite";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
|
|
||||||
message Domain {
|
|
||||||
enum Type {
|
|
||||||
// The value is used as is.
|
|
||||||
Plain = 0;
|
|
||||||
// The value is used as a regular expression.
|
|
||||||
Regex = 1;
|
|
||||||
// The value is a root domain.
|
|
||||||
Domain = 2;
|
|
||||||
// The value is a domain.
|
|
||||||
Full = 3;
|
|
||||||
}
|
|
||||||
// Domain matching type.
|
|
||||||
Type type = 1;
|
|
||||||
|
|
||||||
// Domain value.
|
|
||||||
string value = 2;
|
|
||||||
|
|
||||||
message Attribute {
|
|
||||||
string key = 1;
|
|
||||||
|
|
||||||
oneof typed_value {
|
|
||||||
bool bool_value = 2;
|
|
||||||
int64 int_value = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attributes of this domain. May be used for filtering.
|
|
||||||
repeated Attribute attribute = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoSite {
|
|
||||||
string country_code = 1;
|
|
||||||
repeated Domain domain = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoSiteList {
|
|
||||||
repeated GeoSite entry = 1;
|
|
||||||
}
|
|
@@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: common/net/address.proto
|
// source: common/net/address.proto
|
||||||
|
|
||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
// Address of a network host. It may be either an IP address or a domain
|
// Address of a network host. It may be either an IP address or a domain
|
||||||
// address.
|
// address.
|
||||||
type IPOrDomain struct {
|
type IPOrDomain struct {
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: common/net/destination.proto
|
// source: common/net/destination.proto
|
||||||
|
|
||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
// Endpoint of a network connection.
|
// Endpoint of a network connection.
|
||||||
type Endpoint struct {
|
type Endpoint struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: common/net/network.proto
|
// source: common/net/network.proto
|
||||||
|
|
||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
type Network int32
|
type Network int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@@ -1,13 +1,12 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.25.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.14.0
|
// protoc v3.18.0
|
||||||
// source: common/net/port.proto
|
// source: common/net/port.proto
|
||||||
|
|
||||||
package net
|
package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
proto "github.com/golang/protobuf/proto"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -21,10 +20,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
|
||||||
// of the legacy proto package is being used.
|
|
||||||
const _ = proto.ProtoPackageIsVersion4
|
|
||||||
|
|
||||||
// PortRange represents a range of ports.
|
// PortRange represents a range of ports.
|
||||||
type PortRange struct {
|
type PortRange struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package ctlcmd
|
package ctlcmd
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user