mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-12-19 05:34:36 +03:00
Compare commits
22 Commits
fix-router
...
optimistic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99e736ac61 | ||
|
|
cd4f1cd4a5 | ||
|
|
b63c35b9fe | ||
|
|
79787a0176 | ||
|
|
b69a376aa1 | ||
|
|
12f4a014e0 | ||
|
|
9cc7907234 | ||
|
|
21a9658519 | ||
|
|
7f436f5318 | ||
|
|
dcfde8dc92 | ||
|
|
898db92d51 | ||
|
|
8dd0e388a2 | ||
|
|
40f0a541bf | ||
|
|
1762d6c8cc | ||
|
|
195248801d | ||
|
|
4a825c0260 | ||
|
|
514c9e5a22 | ||
|
|
2f366aed2e | ||
|
|
c0c88f3d73 | ||
|
|
d0344bcff8 | ||
|
|
a6ebb3061c | ||
|
|
fe57507fd9 |
@@ -45,6 +45,7 @@
|
|||||||
- [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
|
- [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
|
||||||
- Web Panel - **WARNING: Please DO NOT USE plain HTTP panels like 3X-UI**, as they are believed to be bribed by Iran GFW for supporting plain HTTP by default and refused to change (https://github.com/XTLS/Xray-core/pull/3884#issuecomment-2439595331), which has already put many users' data security in danger in the past few years. **If you are already using 3X-UI, please switch to the following panels, which are verified to support HTTPS and SSH port forwarding only:**
|
- Web Panel - **WARNING: Please DO NOT USE plain HTTP panels like 3X-UI**, as they are believed to be bribed by Iran GFW for supporting plain HTTP by default and refused to change (https://github.com/XTLS/Xray-core/pull/3884#issuecomment-2439595331), which has already put many users' data security in danger in the past few years. **If you are already using 3X-UI, please switch to the following panels, which are verified to support HTTPS and SSH port forwarding only:**
|
||||||
- [X-Panel](https://github.com/xeefei/X-Panel)
|
- [X-Panel](https://github.com/xeefei/X-Panel)
|
||||||
|
- [PasarGuard](https://github.com/PasarGuard/panel)
|
||||||
- [Remnawave](https://github.com/remnawave/panel)
|
- [Remnawave](https://github.com/remnawave/panel)
|
||||||
- [Marzban](https://github.com/Gozargah/Marzban)
|
- [Marzban](https://github.com/Gozargah/Marzban)
|
||||||
- [Xray-UI](https://github.com/qist/xray-ui)
|
- [Xray-UI](https://github.com/qist/xray-ui)
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
go_errors "errors"
|
go_errors "errors"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"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"
|
||||||
@@ -10,25 +13,27 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type CacheController struct {
|
type CacheController struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
ips map[string]*record
|
ips map[string]*record
|
||||||
pub *pubsub.Service
|
pub *pubsub.Service
|
||||||
cacheCleanup *task.Periodic
|
cacheCleanup *task.Periodic
|
||||||
name string
|
name string
|
||||||
disableCache bool
|
disableCache bool
|
||||||
|
serveStale bool
|
||||||
|
serveExpiredTTL int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCacheController(name string, disableCache bool) *CacheController {
|
func NewCacheController(name string, disableCache bool, serveStale bool, serveExpiredTTL uint32) *CacheController {
|
||||||
c := &CacheController{
|
c := &CacheController{
|
||||||
name: name,
|
name: name,
|
||||||
disableCache: disableCache,
|
disableCache: disableCache,
|
||||||
ips: make(map[string]*record),
|
serveStale: serveStale,
|
||||||
pub: pubsub.NewService(),
|
serveExpiredTTL: -int32(serveExpiredTTL),
|
||||||
|
ips: make(map[string]*record),
|
||||||
|
pub: pubsub.NewService(),
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cacheCleanup = &task.Periodic{
|
c.cacheCleanup = &task.Periodic{
|
||||||
@@ -41,6 +46,10 @@ func NewCacheController(name string, disableCache bool) *CacheController {
|
|||||||
// CacheCleanup clears expired items from cache
|
// CacheCleanup clears expired items from cache
|
||||||
func (c *CacheController) CacheCleanup() error {
|
func (c *CacheController) CacheCleanup() error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
if c.serveStale && c.serveExpiredTTL != 0 {
|
||||||
|
now = now.Add(time.Duration(c.serveExpiredTTL) * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
c.Lock()
|
c.Lock()
|
||||||
defer c.Unlock()
|
defer c.Unlock()
|
||||||
|
|
||||||
@@ -93,78 +102,80 @@ func (c *CacheController) updateIP(req *dnsRequest, ipRec *IPRecord) {
|
|||||||
switch req.reqType {
|
switch req.reqType {
|
||||||
case dnsmessage.TypeA:
|
case dnsmessage.TypeA:
|
||||||
c.pub.Publish(req.domain+"4", nil)
|
c.pub.Publish(req.domain+"4", nil)
|
||||||
if !c.disableCache {
|
|
||||||
_, _, err := rec.AAAA.getIPs()
|
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
|
||||||
c.pub.Publish(req.domain+"6", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case dnsmessage.TypeAAAA:
|
case dnsmessage.TypeAAAA:
|
||||||
c.pub.Publish(req.domain+"6", nil)
|
c.pub.Publish(req.domain+"6", nil)
|
||||||
if !c.disableCache {
|
|
||||||
_, _, err := rec.A.getIPs()
|
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
|
||||||
c.pub.Publish(req.domain+"4", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Unlock()
|
c.Unlock()
|
||||||
common.Must(c.cacheCleanup.Start())
|
if !c.serveStale || c.serveExpiredTTL != 0 {
|
||||||
|
common.Must(c.cacheCleanup.Start())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheController) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
func (c *CacheController) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, int32, bool, bool, error) {
|
||||||
c.RLock()
|
c.RLock()
|
||||||
record, found := c.ips[domain]
|
record, found := c.ips[domain]
|
||||||
c.RUnlock()
|
c.RUnlock()
|
||||||
|
|
||||||
if !found {
|
if !found {
|
||||||
return nil, 0, errRecordNotFound
|
return nil, 0, true, true, errRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
var errs []error
|
var errs []error
|
||||||
var allIPs []net.IP
|
var allIPs []net.IP
|
||||||
var rTTL uint32 = dns_feature.DefaultTTL
|
var rTTL int32 = dns_feature.DefaultTTL
|
||||||
|
|
||||||
mergeReq := option.IPv4Enable && option.IPv6Enable
|
mergeReq := option.IPv4Enable && option.IPv6Enable
|
||||||
|
|
||||||
|
isARecordExpired := true
|
||||||
if option.IPv4Enable {
|
if option.IPv4Enable {
|
||||||
ips, ttl, err := record.A.getIPs()
|
ips, ttl, err := record.A.getIPs()
|
||||||
if !mergeReq || go_errors.Is(err, errRecordNotFound) {
|
if ttl > 0 {
|
||||||
return ips, ttl, err
|
isARecordExpired = false
|
||||||
|
}
|
||||||
|
if !mergeReq {
|
||||||
|
return ips, ttl, isARecordExpired, true, err
|
||||||
}
|
}
|
||||||
if ttl < rTTL {
|
if ttl < rTTL {
|
||||||
rTTL = ttl
|
rTTL = ttl
|
||||||
}
|
}
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
allIPs = append(allIPs, ips...)
|
allIPs = append(allIPs, ips...)
|
||||||
} else {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isAAAARecordExpired := true
|
||||||
if option.IPv6Enable {
|
if option.IPv6Enable {
|
||||||
ips, ttl, err := record.AAAA.getIPs()
|
ips, ttl, err := record.AAAA.getIPs()
|
||||||
if !mergeReq || go_errors.Is(err, errRecordNotFound) {
|
if ttl > 0 {
|
||||||
return ips, ttl, err
|
isAAAARecordExpired = false
|
||||||
|
}
|
||||||
|
if !mergeReq {
|
||||||
|
return ips, ttl, true, isAAAARecordExpired, err
|
||||||
}
|
}
|
||||||
if ttl < rTTL {
|
if ttl < rTTL {
|
||||||
rTTL = ttl
|
rTTL = ttl
|
||||||
}
|
}
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
allIPs = append(allIPs, ips...)
|
allIPs = append(allIPs, ips...)
|
||||||
} else {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if go_errors.Is(errs[0], errRecordNotFound) || go_errors.Is(errs[1], errRecordNotFound) {
|
||||||
|
return nil, 0, isARecordExpired, isAAAARecordExpired, errRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(allIPs) > 0 {
|
if len(allIPs) > 0 {
|
||||||
return allIPs, rTTL, nil
|
return allIPs, rTTL, isARecordExpired, isAAAARecordExpired, nil
|
||||||
}
|
}
|
||||||
if go_errors.Is(errs[0], errs[1]) {
|
if go_errors.Is(errs[0], errs[1]) {
|
||||||
return nil, rTTL, errs[0]
|
return nil, rTTL, isARecordExpired, isAAAARecordExpired, errs[0]
|
||||||
}
|
}
|
||||||
return nil, rTTL, errors.Combine(errs...)
|
return nil, rTTL, isARecordExpired, isAAAARecordExpired, errors.Combine(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheController) registerSubscribers(domain string, option dns_feature.IPOption) (sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
|
func (c *CacheController) registerSubscribers(domain string, option dns_feature.IPOption) (sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.35.1
|
// protoc-gen-go v1.35.1
|
||||||
// protoc v5.28.2
|
// protoc v5.29.4
|
||||||
// source: app/dns/config.proto
|
// source: app/dns/config.proto
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
@@ -142,6 +142,8 @@ type NameServer struct {
|
|||||||
Tag string `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
|
Tag string `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
TimeoutMs uint64 `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
|
TimeoutMs uint64 `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
|
||||||
DisableCache bool `protobuf:"varint,11,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
|
DisableCache bool `protobuf:"varint,11,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
|
||||||
|
ServeStale bool `protobuf:"varint,15,opt,name=serveStale,proto3" json:"serveStale,omitempty"`
|
||||||
|
ServeExpiredTTL *uint32 `protobuf:"varint,16,opt,name=serveExpiredTTL,proto3,oneof" json:"serveExpiredTTL,omitempty"`
|
||||||
FinalQuery bool `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
|
FinalQuery bool `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
|
||||||
UnexpectedGeoip []*router.GeoIP `protobuf:"bytes,13,rep,name=unexpected_geoip,json=unexpectedGeoip,proto3" json:"unexpected_geoip,omitempty"`
|
UnexpectedGeoip []*router.GeoIP `protobuf:"bytes,13,rep,name=unexpected_geoip,json=unexpectedGeoip,proto3" json:"unexpected_geoip,omitempty"`
|
||||||
ActUnprior bool `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
|
ActUnprior bool `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
|
||||||
@@ -254,6 +256,20 @@ func (x *NameServer) GetDisableCache() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *NameServer) GetServeStale() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.ServeStale
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NameServer) GetServeExpiredTTL() uint32 {
|
||||||
|
if x != nil && x.ServeExpiredTTL != nil {
|
||||||
|
return *x.ServeExpiredTTL
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetFinalQuery() bool {
|
func (x *NameServer) GetFinalQuery() bool {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.FinalQuery
|
return x.FinalQuery
|
||||||
@@ -291,6 +307,8 @@ type Config struct {
|
|||||||
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
|
// DisableCache disables DNS cache
|
||||||
DisableCache bool `protobuf:"varint,8,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
|
DisableCache bool `protobuf:"varint,8,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
|
||||||
|
ServeStale bool `protobuf:"varint,12,opt,name=serveStale,proto3" json:"serveStale,omitempty"`
|
||||||
|
ServeExpiredTTL uint32 `protobuf:"varint,13,opt,name=serveExpiredTTL,proto3" json:"serveExpiredTTL,omitempty"`
|
||||||
QueryStrategy QueryStrategy `protobuf:"varint,9,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_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"`
|
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
|
||||||
DisableFallbackIfMatch bool `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
|
DisableFallbackIfMatch bool `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
|
||||||
@@ -361,6 +379,20 @@ func (x *Config) GetDisableCache() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetServeStale() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.ServeStale
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetServeExpiredTTL() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.ServeExpiredTTL
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (x *Config) GetQueryStrategy() QueryStrategy {
|
func (x *Config) GetQueryStrategy() QueryStrategy {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.QueryStrategy
|
return x.QueryStrategy
|
||||||
@@ -567,7 +599,7 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
|||||||
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 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,
|
0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb6, 0x06, 0x0a, 0x0a,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x99, 0x07, 0x0a, 0x0a,
|
||||||
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
|
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
|
||||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
||||||
@@ -601,72 +633,83 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
|||||||
0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
||||||
0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
||||||
0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73,
|
0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73,
|
||||||
0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6e,
|
0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72,
|
||||||
0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66,
|
0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73,
|
||||||
0x69, 0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x41, 0x0a, 0x10, 0x75, 0x6e, 0x65,
|
0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x2d, 0x0a, 0x0f, 0x73, 0x65, 0x72,
|
||||||
0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0d, 0x20,
|
0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x10, 0x20, 0x01,
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
0x28, 0x0d, 0x48, 0x00, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72,
|
||||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65,
|
0x65, 0x64, 0x54, 0x54, 0x4c, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6e, 0x61,
|
||||||
0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a,
|
0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66, 0x69,
|
||||||
0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08,
|
0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x41, 0x0a, 0x10, 0x75, 0x6e, 0x65, 0x78,
|
||||||
0x52, 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x1a, 0x5e, 0x0a, 0x0e,
|
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0d, 0x20, 0x03,
|
||||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34,
|
0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||||
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78,
|
0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65, 0x78,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61,
|
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x61,
|
||||||
0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
|
0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02,
|
0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x1a, 0x5e, 0x0a, 0x0e, 0x50,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c,
|
0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a,
|
||||||
0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72,
|
||||||
0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04,
|
0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
|
||||||
0x73, 0x69, 0x7a, 0x65, 0x22, 0x9c, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20,
|
||||||
0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05,
|
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f,
|
||||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72,
|
||||||
0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a,
|
0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12,
|
||||||
0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
|
0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73,
|
||||||
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63,
|
0x69, 0x7a, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70,
|
||||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69,
|
0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x22, 0xe6, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
||||||
0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e,
|
0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e,
|
0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||||
0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52,
|
0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||||
0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
|
0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a,
|
||||||
0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22,
|
0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
||||||
0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08,
|
0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74,
|
||||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63,
|
0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x68, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61,
|
0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e,
|
||||||
0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
|
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69,
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
|
0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
|
0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61,
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68,
|
||||||
0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52,
|
0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
||||||
0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74,
|
||||||
0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62,
|
0x61, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||||
0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08,
|
0x53, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78,
|
||||||
0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63,
|
0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f,
|
||||||
0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73,
|
0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x12,
|
||||||
0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
|
0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||||
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63,
|
0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61,
|
||||||
0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16,
|
0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74,
|
||||||
0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03,
|
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69,
|
||||||
0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65,
|
0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a,
|
||||||
0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08,
|
0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x64,
|
||||||
0x07, 0x10, 0x08, 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74,
|
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66,
|
||||||
0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c,
|
0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61,
|
||||||
0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20,
|
||||||
0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12,
|
0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64,
|
||||||
0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75,
|
0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e,
|
||||||
0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55,
|
0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64,
|
||||||
0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d,
|
||||||
0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10,
|
0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52,
|
||||||
0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x10, 0x03, 0x42, 0x46,
|
0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64,
|
||||||
0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64,
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f,
|
||||||
0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08,
|
||||||
0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f,
|
0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69,
|
||||||
0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41,
|
0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00,
|
||||||
0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
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, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79,
|
||||||
|
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f,
|
||||||
|
0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10,
|
||||||
|
0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x12, 0x0b,
|
||||||
|
0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x53, 0x59, 0x53, 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 (
|
||||||
@@ -718,6 +761,7 @@ func file_app_dns_config_proto_init() {
|
|||||||
if File_app_dns_config_proto != nil {
|
if File_app_dns_config_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
file_app_dns_config_proto_msgTypes[0].OneofWrappers = []any{}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ message NameServer {
|
|||||||
string tag = 9;
|
string tag = 9;
|
||||||
uint64 timeoutMs = 10;
|
uint64 timeoutMs = 10;
|
||||||
bool disableCache = 11;
|
bool disableCache = 11;
|
||||||
|
bool serveStale = 15;
|
||||||
|
optional uint32 serveExpiredTTL = 16;
|
||||||
bool finalQuery = 12;
|
bool finalQuery = 12;
|
||||||
repeated xray.app.router.GeoIP unexpected_geoip = 13;
|
repeated xray.app.router.GeoIP unexpected_geoip = 13;
|
||||||
bool actUnprior = 14;
|
bool actUnprior = 14;
|
||||||
@@ -80,6 +82,8 @@ message Config {
|
|||||||
|
|
||||||
// DisableCache disables DNS cache
|
// DisableCache disables DNS cache
|
||||||
bool disableCache = 8;
|
bool disableCache = 8;
|
||||||
|
bool serveStale = 12;
|
||||||
|
uint32 serveExpiredTTL = 13;
|
||||||
|
|
||||||
QueryStrategy query_strategy = 9;
|
QueryStrategy query_strategy = 9;
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,11 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disableCache := config.DisableCache || ns.DisableCache
|
disableCache := config.DisableCache || ns.DisableCache
|
||||||
|
serveStale := config.ServeStale || ns.ServeStale
|
||||||
|
serveExpiredTTL := config.ServeExpiredTTL
|
||||||
|
if ns.ServeExpiredTTL != nil {
|
||||||
|
serveExpiredTTL = *ns.ServeExpiredTTL
|
||||||
|
}
|
||||||
|
|
||||||
var tag = defaultTag
|
var tag = defaultTag
|
||||||
if len(ns.Tag) > 0 {
|
if len(ns.Tag) > 0 {
|
||||||
@@ -128,7 +133,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
return nil, errors.New("no QueryStrategy available for ", ns.Address)
|
return nil, errors.New("no QueryStrategy available for ", ns.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := NewClient(ctx, ns, myClientIP, disableCache, tag, clientIPOption, &matcherInfos, updateDomain)
|
client, err := NewClient(ctx, ns, myClientIP, disableCache, serveStale, serveExpiredTTL, tag, clientIPOption, &matcherInfos, updateDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to create client").Base(err)
|
return nil, errors.New("failed to create client").Base(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -38,19 +39,14 @@ type IPRecord struct {
|
|||||||
RawHeader *dnsmessage.Header
|
RawHeader *dnsmessage.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *IPRecord) getIPs() ([]net.IP, uint32, error) {
|
func (r *IPRecord) getIPs() ([]net.IP, int32, error) {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, 0, errRecordNotFound
|
return nil, 0, errRecordNotFound
|
||||||
}
|
}
|
||||||
untilExpire := time.Until(r.Expire).Seconds()
|
|
||||||
if untilExpire <= 0 {
|
|
||||||
return nil, 0, errRecordNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
ttl := uint32(untilExpire) + 1
|
untilExpire := time.Until(r.Expire).Seconds()
|
||||||
if ttl == 1 {
|
ttl := int32(math.Ceil(untilExpire))
|
||||||
r.Expire = time.Now().Add(time.Second) // To ensure that two consecutive requests get the same result
|
|
||||||
}
|
|
||||||
if r.RCode != dnsmessage.RCodeSuccess {
|
if r.RCode != dnsmessage.RCodeSuccess {
|
||||||
return nil, ttl, dns_feature.RCodeError(r.RCode)
|
return nil, ttl, dns_feature.RCodeError(r.RCode)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ type Client struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a name server object according to the network destination url.
|
// NewServer creates a name server object according to the network destination url.
|
||||||
func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, disableCache bool, clientIP net.IP) (Server, error) {
|
func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (Server, error) {
|
||||||
if address := dest.Address; address.Family().IsDomain() {
|
if address := dest.Address; address.Family().IsDomain() {
|
||||||
u, err := url.Parse(address.Domain())
|
u, err := url.Parse(address.Domain())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -51,19 +51,19 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
|||||||
case strings.EqualFold(u.String(), "localhost"):
|
case strings.EqualFold(u.String(), "localhost"):
|
||||||
return NewLocalNameServer(), nil
|
return NewLocalNameServer(), nil
|
||||||
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
|
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
|
||||||
return NewDoHNameServer(u, dispatcher, false, disableCache, clientIP), nil
|
return NewDoHNameServer(u, dispatcher, false, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
|
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
|
||||||
return NewDoHNameServer(u, dispatcher, true, disableCache, clientIP), nil
|
return NewDoHNameServer(u, dispatcher, true, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
|
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
|
||||||
return NewDoHNameServer(u, nil, false, disableCache, clientIP), nil
|
return NewDoHNameServer(u, nil, false, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
case strings.EqualFold(u.Scheme, "h2c+local"): // DNS-over-HTTPS h2c Local mode
|
case strings.EqualFold(u.Scheme, "h2c+local"): // DNS-over-HTTPS h2c Local mode
|
||||||
return NewDoHNameServer(u, nil, true, disableCache, clientIP), nil
|
return NewDoHNameServer(u, nil, true, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
||||||
return NewQUICNameServer(u, disableCache, clientIP)
|
return NewQUICNameServer(u, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
|
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
|
||||||
return NewTCPNameServer(u, dispatcher, disableCache, clientIP)
|
return NewTCPNameServer(u, dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
|
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
|
||||||
return NewTCPLocalNameServer(u, disableCache, clientIP)
|
return NewTCPLocalNameServer(u, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
case strings.EqualFold(u.String(), "fakedns"):
|
case strings.EqualFold(u.String(), "fakedns"):
|
||||||
var fd dns.FakeDNSEngine
|
var fd dns.FakeDNSEngine
|
||||||
err = core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
err = core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||||
@@ -79,7 +79,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
|||||||
dest.Network = net.Network_UDP
|
dest.Network = net.Network_UDP
|
||||||
}
|
}
|
||||||
if dest.Network == net.Network_UDP { // UDP classic DNS mode
|
if dest.Network == net.Network_UDP { // UDP classic DNS mode
|
||||||
return NewClassicNameServer(dest, dispatcher, disableCache, clientIP), nil
|
return NewClassicNameServer(dest, dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("No available name server could be created from ", dest).AtWarning()
|
return nil, errors.New("No available name server could be created from ", dest).AtWarning()
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ func NewClient(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
ns *NameServer,
|
ns *NameServer,
|
||||||
clientIP net.IP,
|
clientIP net.IP,
|
||||||
disableCache bool,
|
disableCache bool, serveStale bool, serveExpiredTTL uint32,
|
||||||
tag string,
|
tag string,
|
||||||
ipOption dns.IPOption,
|
ipOption dns.IPOption,
|
||||||
matcherInfos *[]*DomainMatcherInfo,
|
matcherInfos *[]*DomainMatcherInfo,
|
||||||
@@ -99,7 +99,7 @@ func NewClient(
|
|||||||
|
|
||||||
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
||||||
// Create a new server for each client for now
|
// Create a new server for each client for now
|
||||||
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, clientIP)
|
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ type DoHNameServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewDoHNameServer creates DOH/DOHL client object for remote/local resolving.
|
// NewDoHNameServer creates DOH/DOHL client object for remote/local resolving.
|
||||||
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, disableCache bool, clientIP net.IP) *DoHNameServer {
|
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) *DoHNameServer {
|
||||||
url.Scheme = "https"
|
url.Scheme = "https"
|
||||||
mode := "DOH"
|
mode := "DOH"
|
||||||
if dispatcher == nil {
|
if dispatcher == nil {
|
||||||
@@ -46,7 +46,7 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, dis
|
|||||||
}
|
}
|
||||||
errors.LogInfo(context.Background(), "DNS: created ", mode, " client for ", url.String(), ", with h2c ", h2c)
|
errors.LogInfo(context.Background(), "DNS: created ", mode, " client for ", url.String(), ", with h2c ", h2c)
|
||||||
s := &DoHNameServer{
|
s := &DoHNameServer{
|
||||||
cacheController: NewCacheController(mode+"//"+url.Host, disableCache),
|
cacheController: NewCacheController(mode+"//"+url.Host, disableCache, serveStale, serveExpiredTTL),
|
||||||
dohURL: url.String(),
|
dohURL: url.String(),
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,9 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
|
|
||||||
if s.Name()+"." == "DOH//"+domain {
|
if s.Name()+"." == "DOH//"+domain {
|
||||||
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead.")
|
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead.")
|
||||||
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,19 +169,25 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain)
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
|
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain)
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rec, err := parseResponse(resp)
|
rec, err := parseResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain)
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.cacheController.updateIP(r, rec)
|
s.cacheController.updateIP(r, rec)
|
||||||
@@ -221,19 +229,38 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option dns_f
|
|||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
||||||
defer closeSubscribers(sub4, sub6)
|
defer closeSubscribers(sub4, sub6)
|
||||||
|
|
||||||
|
queryOption := option
|
||||||
|
|
||||||
if s.cacheController.disableCache {
|
if s.cacheController.disableCache {
|
||||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
||||||
} else {
|
} else {
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, ttl, isARecordExpired, isAAAARecordExpired, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||||
|
if sub4 != nil && !isARecordExpired {
|
||||||
|
sub4.Close()
|
||||||
|
sub4 = nil
|
||||||
|
queryOption.IPv4Enable = false
|
||||||
|
}
|
||||||
|
if sub6 != nil && !isAAAARecordExpired {
|
||||||
|
sub6.Close()
|
||||||
|
sub6 = nil
|
||||||
|
queryOption.IPv6Enable = false
|
||||||
|
}
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if !go_errors.Is(err, errRecordNotFound) {
|
||||||
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
if ttl > 0 {
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
||||||
return ips, ttl, err
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
|
return ips, uint32(ttl), err
|
||||||
|
}
|
||||||
|
if s.cacheController.serveStale && (s.cacheController.serveExpiredTTL == 0 || s.cacheController.serveExpiredTTL < ttl) {
|
||||||
|
errors.LogDebugInner(ctx, err, s.Name(), " cache OPTIMISTE ", domain, " -> ", ips)
|
||||||
|
s.sendQuery(ctx, nil, fqdn, queryOption)
|
||||||
|
return ips, 1, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
noResponseErrCh := make(chan error, 2)
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
s.sendQuery(ctx, noResponseErrCh, fqdn, queryOption)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if sub4 != nil {
|
if sub4 != nil {
|
||||||
@@ -257,8 +284,13 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option dns_f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, ttl, _, _, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
return ips, ttl, err
|
var rTTL uint32
|
||||||
|
if ttl <= 0 {
|
||||||
|
rTTL = 1
|
||||||
|
} else {
|
||||||
|
rTTL = uint32(ttl)
|
||||||
|
}
|
||||||
|
return ips, rTTL, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func TestDOHNameServer(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, nil, false, false, false, 0, net.IP(nil))
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
@@ -34,7 +34,7 @@ func TestDOHNameServerWithCache(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, nil, false, false, false, 0, net.IP(nil))
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
@@ -62,7 +62,7 @@ func TestDOHNameServerWithIPv4Override(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, nil, false, false, false, 0, net.IP(nil))
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
@@ -85,7 +85,7 @@ func TestDOHNameServerWithIPv6Override(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, nil, false, false, false, 0, net.IP(nil))
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: false,
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ type QUICNameServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
||||||
func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICNameServer, error) {
|
func NewQUICNameServer(url *url.URL, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (*QUICNameServer, error) {
|
||||||
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
|
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@@ -51,7 +51,7 @@ func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICN
|
|||||||
dest := net.UDPDestination(net.ParseAddress(url.Hostname()), port)
|
dest := net.UDPDestination(net.ParseAddress(url.Hostname()), port)
|
||||||
|
|
||||||
s := &QUICNameServer{
|
s := &QUICNameServer{
|
||||||
cacheController: NewCacheController(url.String(), disableCache),
|
cacheController: NewCacheController(url.String(), disableCache, serveStale, serveExpiredTTL),
|
||||||
destination: &dest,
|
destination: &dest,
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,9 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,13 +113,17 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "binary write failed")
|
errors.LogErrorInner(ctx, err, "binary write failed")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = dnsReqBuf.Write(b.Bytes())
|
_, err = dnsReqBuf.Write(b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "buffer write failed")
|
errors.LogErrorInner(ctx, err, "buffer write failed")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.Release()
|
b.Release()
|
||||||
@@ -125,14 +131,18 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
conn, err := s.openStream(dnsCtx)
|
conn, err := s.openStream(dnsCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to open quic connection")
|
errors.LogErrorInner(ctx, err, "failed to open quic connection")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to send query")
|
errors.LogErrorInner(ctx, err, "failed to send query")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,28 +153,36 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var length int16
|
var length int16
|
||||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
respBuf.Clear()
|
respBuf.Clear()
|
||||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rec, err := parseResponse(respBuf.Bytes())
|
rec, err := parseResponse(respBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to handle response")
|
errors.LogErrorInner(ctx, err, "failed to handle response")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.cacheController.updateIP(r, rec)
|
s.cacheController.updateIP(r, rec)
|
||||||
@@ -178,19 +196,38 @@ func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, option dns_
|
|||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
||||||
defer closeSubscribers(sub4, sub6)
|
defer closeSubscribers(sub4, sub6)
|
||||||
|
|
||||||
|
queryOption := option
|
||||||
|
|
||||||
if s.cacheController.disableCache {
|
if s.cacheController.disableCache {
|
||||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
||||||
} else {
|
} else {
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, ttl, isARecordExpired, isAAAARecordExpired, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||||
|
if sub4 != nil && !isARecordExpired {
|
||||||
|
sub4.Close()
|
||||||
|
sub4 = nil
|
||||||
|
queryOption.IPv4Enable = false
|
||||||
|
}
|
||||||
|
if sub6 != nil && !isAAAARecordExpired {
|
||||||
|
sub6.Close()
|
||||||
|
sub6 = nil
|
||||||
|
queryOption.IPv6Enable = false
|
||||||
|
}
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if !go_errors.Is(err, errRecordNotFound) {
|
||||||
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
if ttl > 0 {
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
||||||
return ips, ttl, err
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
|
return ips, uint32(ttl), err
|
||||||
|
}
|
||||||
|
if s.cacheController.serveStale && (s.cacheController.serveExpiredTTL == 0 || s.cacheController.serveExpiredTTL < ttl) {
|
||||||
|
errors.LogDebugInner(ctx, err, s.Name(), " cache OPTIMISTE ", domain, " -> ", ips)
|
||||||
|
s.sendQuery(ctx, nil, fqdn, queryOption)
|
||||||
|
return ips, 1, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
noResponseErrCh := make(chan error, 2)
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
s.sendQuery(ctx, noResponseErrCh, fqdn, queryOption)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if sub4 != nil {
|
if sub4 != nil {
|
||||||
@@ -214,10 +251,15 @@ func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, option dns_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, ttl, _, _, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
return ips, ttl, err
|
var rTTL uint32
|
||||||
|
if ttl <= 0 {
|
||||||
|
rTTL = 1
|
||||||
|
} else {
|
||||||
|
rTTL = uint32(ttl)
|
||||||
|
}
|
||||||
|
return ips, rTTL, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func isActive(s *quic.Conn) bool {
|
func isActive(s *quic.Conn) bool {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
func TestQUICNameServer(t *testing.T) {
|
func TestQUICNameServer(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
||||||
@@ -43,7 +43,7 @@ func TestQUICNameServer(t *testing.T) {
|
|||||||
func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
||||||
@@ -66,7 +66,7 @@ func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
|||||||
func TestQUICNameServerWithIPv6Override(t *testing.T) {
|
func TestQUICNameServerWithIPv6Override(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
||||||
|
|||||||
@@ -34,10 +34,10 @@ type TCPNameServer struct {
|
|||||||
func NewTCPNameServer(
|
func NewTCPNameServer(
|
||||||
url *url.URL,
|
url *url.URL,
|
||||||
dispatcher routing.Dispatcher,
|
dispatcher routing.Dispatcher,
|
||||||
disableCache bool,
|
disableCache bool, serveStale bool, serveExpiredTTL uint32,
|
||||||
clientIP net.IP,
|
clientIP net.IP,
|
||||||
) (*TCPNameServer, error) {
|
) (*TCPNameServer, error) {
|
||||||
s, err := baseTCPNameServer(url, "TCP", disableCache, clientIP)
|
s, err := baseTCPNameServer(url, "TCP", disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -58,8 +58,8 @@ func NewTCPNameServer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPLocalNameServer creates DNS over TCP client object for local resolving
|
// NewTCPLocalNameServer creates DNS over TCP client object for local resolving
|
||||||
func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
|
func NewTCPLocalNameServer(url *url.URL, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (*TCPNameServer, error) {
|
||||||
s, err := baseTCPNameServer(url, "TCPL", disableCache, clientIP)
|
s, err := baseTCPNameServer(url, "TCPL", disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*T
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
|
func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (*TCPNameServer, error) {
|
||||||
port := net.Port(53)
|
port := net.Port(53)
|
||||||
if url.Port() != "" {
|
if url.Port() != "" {
|
||||||
var err error
|
var err error
|
||||||
@@ -82,7 +82,7 @@ func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP
|
|||||||
dest := net.TCPDestination(net.ParseAddress(url.Hostname()), port)
|
dest := net.TCPDestination(net.ParseAddress(url.Hostname()), port)
|
||||||
|
|
||||||
s := &TCPNameServer{
|
s := &TCPNameServer{
|
||||||
cacheController: NewCacheController(prefix+"//"+dest.NetAddr(), disableCache),
|
cacheController: NewCacheController(prefix+"//"+dest.NetAddr(), disableCache, serveStale, serveExpiredTTL),
|
||||||
destination: &dest,
|
destination: &dest,
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
}
|
}
|
||||||
@@ -131,14 +131,18 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := s.dial(dnsCtx)
|
conn, err := s.dial(dnsCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to dial namesever")
|
errors.LogErrorInner(ctx, err, "failed to dial namesever")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
@@ -146,13 +150,17 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "binary write failed")
|
errors.LogErrorInner(ctx, err, "binary write failed")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = dnsReqBuf.Write(b.Bytes())
|
_, err = dnsReqBuf.Write(b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "buffer write failed")
|
errors.LogErrorInner(ctx, err, "buffer write failed")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.Release()
|
b.Release()
|
||||||
@@ -160,7 +168,9 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to send query")
|
errors.LogErrorInner(ctx, err, "failed to send query")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dnsReqBuf.Release()
|
dnsReqBuf.Release()
|
||||||
@@ -170,28 +180,36 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var length int16
|
var length int16
|
||||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
respBuf.Clear()
|
respBuf.Clear()
|
||||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rec, err := parseResponse(respBuf.Bytes())
|
rec, err := parseResponse(respBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
|
errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,19 +224,38 @@ func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, option dns_f
|
|||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
||||||
defer closeSubscribers(sub4, sub6)
|
defer closeSubscribers(sub4, sub6)
|
||||||
|
|
||||||
|
queryOption := option
|
||||||
|
|
||||||
if s.cacheController.disableCache {
|
if s.cacheController.disableCache {
|
||||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
||||||
} else {
|
} else {
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, ttl, isARecordExpired, isAAAARecordExpired, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||||
|
if sub4 != nil && !isARecordExpired {
|
||||||
|
sub4.Close()
|
||||||
|
sub4 = nil
|
||||||
|
queryOption.IPv4Enable = false
|
||||||
|
}
|
||||||
|
if sub6 != nil && !isAAAARecordExpired {
|
||||||
|
sub6.Close()
|
||||||
|
sub6 = nil
|
||||||
|
queryOption.IPv6Enable = false
|
||||||
|
}
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if !go_errors.Is(err, errRecordNotFound) {
|
||||||
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
if ttl > 0 {
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
||||||
return ips, ttl, err
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
|
return ips, uint32(ttl), err
|
||||||
|
}
|
||||||
|
if s.cacheController.serveStale && (s.cacheController.serveExpiredTTL == 0 || s.cacheController.serveExpiredTTL < ttl) {
|
||||||
|
errors.LogDebugInner(ctx, err, s.Name(), " cache OPTIMISTE ", domain, " -> ", ips)
|
||||||
|
s.sendQuery(ctx, nil, fqdn, queryOption)
|
||||||
|
return ips, 1, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
noResponseErrCh := make(chan error, 2)
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
s.sendQuery(ctx, noResponseErrCh, fqdn, queryOption)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if sub4 != nil {
|
if sub4 != nil {
|
||||||
@@ -242,8 +279,13 @@ func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, option dns_f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, ttl, _, _, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
return ips, ttl, err
|
var rTTL uint32
|
||||||
|
if ttl <= 0 {
|
||||||
|
rTTL = 1
|
||||||
|
} else {
|
||||||
|
rTTL = uint32(ttl)
|
||||||
|
}
|
||||||
|
return ips, rTTL, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
func TestTCPLocalNameServer(t *testing.T) {
|
func TestTCPLocalNameServer(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
@@ -33,7 +33,7 @@ func TestTCPLocalNameServer(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithCache(t *testing.T) {
|
func TestTCPLocalNameServerWithCache(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
@@ -61,7 +61,7 @@ func TestTCPLocalNameServerWithCache(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
@@ -85,7 +85,7 @@ func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {
|
func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
|
|||||||
@@ -39,14 +39,14 @@ type udpDnsRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewClassicNameServer creates udp server object for remote resolving.
|
// NewClassicNameServer creates udp server object for remote resolving.
|
||||||
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, disableCache bool, clientIP net.IP) *ClassicNameServer {
|
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) *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)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &ClassicNameServer{
|
s := &ClassicNameServer{
|
||||||
cacheController: NewCacheController(strings.ToUpper(address.String()), disableCache),
|
cacheController: NewCacheController(strings.ToUpper(address.String()), disableCache, serveStale, serveExpiredTTL),
|
||||||
address: &address,
|
address: &address,
|
||||||
requests: make(map[uint16]*udpDnsRequest),
|
requests: make(map[uint16]*udpDnsRequest),
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
@@ -174,19 +174,38 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option d
|
|||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
||||||
defer closeSubscribers(sub4, sub6)
|
defer closeSubscribers(sub4, sub6)
|
||||||
|
|
||||||
|
queryOption := option
|
||||||
|
|
||||||
if s.cacheController.disableCache {
|
if s.cacheController.disableCache {
|
||||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
||||||
} else {
|
} else {
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, ttl, isARecordExpired, isAAAARecordExpired, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||||
|
if sub4 != nil && !isARecordExpired {
|
||||||
|
sub4.Close()
|
||||||
|
sub4 = nil
|
||||||
|
queryOption.IPv4Enable = false
|
||||||
|
}
|
||||||
|
if sub6 != nil && !isAAAARecordExpired {
|
||||||
|
sub6.Close()
|
||||||
|
sub6 = nil
|
||||||
|
queryOption.IPv6Enable = false
|
||||||
|
}
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if !go_errors.Is(err, errRecordNotFound) {
|
||||||
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
if ttl > 0 {
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
||||||
return ips, ttl, err
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
|
return ips, uint32(ttl), err
|
||||||
|
}
|
||||||
|
if s.cacheController.serveStale && (s.cacheController.serveExpiredTTL == 0 || s.cacheController.serveExpiredTTL < ttl) {
|
||||||
|
errors.LogDebugInner(ctx, err, s.Name(), " cache OPTIMISTE ", domain, " -> ", ips)
|
||||||
|
s.sendQuery(ctx, nil, fqdn, queryOption)
|
||||||
|
return ips, 1, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
noResponseErrCh := make(chan error, 2)
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
s.sendQuery(ctx, noResponseErrCh, fqdn, queryOption)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
if sub4 != nil {
|
if sub4 != nil {
|
||||||
@@ -210,8 +229,13 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option d
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, ttl, _, _, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
return ips, ttl, err
|
var rTTL uint32
|
||||||
|
if ttl <= 0 {
|
||||||
|
rTTL = 1
|
||||||
|
} else {
|
||||||
|
rTTL = uint32(ttl)
|
||||||
|
}
|
||||||
|
return ips, rTTL, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1 @@
|
|||||||
package proxyman
|
package proxyman
|
||||||
|
|
||||||
func (s *AllocationStrategy) GetConcurrencyValue() uint32 {
|
|
||||||
if s == nil || s.Concurrency == nil {
|
|
||||||
return 3
|
|
||||||
}
|
|
||||||
return s.Concurrency.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AllocationStrategy) GetRefreshValue() uint32 {
|
|
||||||
if s == nil || s.Refresh == nil {
|
|
||||||
return 5
|
|
||||||
}
|
|
||||||
return s.Refresh.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig {
|
|
||||||
if c.SniffingSettings != nil {
|
|
||||||
return c.SniffingSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -23,58 +23,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
type AllocationStrategy_Type int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Always allocate all connection handlers.
|
|
||||||
AllocationStrategy_Always AllocationStrategy_Type = 0
|
|
||||||
// Randomly allocate specific range of handlers.
|
|
||||||
AllocationStrategy_Random AllocationStrategy_Type = 1
|
|
||||||
// External. Not supported yet.
|
|
||||||
AllocationStrategy_External AllocationStrategy_Type = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for AllocationStrategy_Type.
|
|
||||||
var (
|
|
||||||
AllocationStrategy_Type_name = map[int32]string{
|
|
||||||
0: "Always",
|
|
||||||
1: "Random",
|
|
||||||
2: "External",
|
|
||||||
}
|
|
||||||
AllocationStrategy_Type_value = map[string]int32{
|
|
||||||
"Always": 0,
|
|
||||||
"Random": 1,
|
|
||||||
"External": 2,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x AllocationStrategy_Type) Enum() *AllocationStrategy_Type {
|
|
||||||
p := new(AllocationStrategy_Type)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x AllocationStrategy_Type) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (AllocationStrategy_Type) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_app_proxyman_config_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (AllocationStrategy_Type) Type() protoreflect.EnumType {
|
|
||||||
return &file_app_proxyman_config_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x AllocationStrategy_Type) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use AllocationStrategy_Type.Descriptor instead.
|
|
||||||
func (AllocationStrategy_Type) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InboundConfig struct {
|
type InboundConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -111,71 +59,6 @@ func (*InboundConfig) Descriptor() ([]byte, []int) {
|
|||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{0}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
type AllocationStrategy struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Type AllocationStrategy_Type `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.proxyman.AllocationStrategy_Type" json:"type,omitempty"`
|
|
||||||
// Number of handlers (ports) running in parallel.
|
|
||||||
// Default value is 3 if unset.
|
|
||||||
Concurrency *AllocationStrategy_AllocationStrategyConcurrency `protobuf:"bytes,2,opt,name=concurrency,proto3" json:"concurrency,omitempty"`
|
|
||||||
// Number of minutes before a handler is regenerated.
|
|
||||||
// Default value is 5 if unset.
|
|
||||||
Refresh *AllocationStrategy_AllocationStrategyRefresh `protobuf:"bytes,3,opt,name=refresh,proto3" json:"refresh,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) Reset() {
|
|
||||||
*x = AllocationStrategy{}
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[1]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*AllocationStrategy) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[1]
|
|
||||||
if x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use AllocationStrategy.ProtoReflect.Descriptor instead.
|
|
||||||
func (*AllocationStrategy) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) GetType() AllocationStrategy_Type {
|
|
||||||
if x != nil {
|
|
||||||
return x.Type
|
|
||||||
}
|
|
||||||
return AllocationStrategy_Always
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) GetConcurrency() *AllocationStrategy_AllocationStrategyConcurrency {
|
|
||||||
if x != nil {
|
|
||||||
return x.Concurrency
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) GetRefresh() *AllocationStrategy_AllocationStrategyRefresh {
|
|
||||||
if x != nil {
|
|
||||||
return x.Refresh
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SniffingConfig struct {
|
type SniffingConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -196,7 +79,7 @@ type SniffingConfig struct {
|
|||||||
|
|
||||||
func (x *SniffingConfig) Reset() {
|
func (x *SniffingConfig) Reset() {
|
||||||
*x = SniffingConfig{}
|
*x = SniffingConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[2]
|
mi := &file_app_proxyman_config_proto_msgTypes[1]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -208,7 +91,7 @@ func (x *SniffingConfig) String() string {
|
|||||||
func (*SniffingConfig) ProtoMessage() {}
|
func (*SniffingConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *SniffingConfig) ProtoReflect() protoreflect.Message {
|
func (x *SniffingConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[2]
|
mi := &file_app_proxyman_config_proto_msgTypes[1]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -221,7 +104,7 @@ func (x *SniffingConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use SniffingConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use SniffingConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*SniffingConfig) Descriptor() ([]byte, []int) {
|
func (*SniffingConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{2}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) GetEnabled() bool {
|
func (x *SniffingConfig) GetEnabled() bool {
|
||||||
@@ -268,15 +151,14 @@ type ReceiverConfig struct {
|
|||||||
PortList *net.PortList `protobuf:"bytes,1,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
PortList *net.PortList `protobuf:"bytes,1,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
||||||
// Listen specifies the IP address that the Receiver should listen on.
|
// Listen specifies the IP address that the Receiver should listen on.
|
||||||
Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
||||||
AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"`
|
StreamSettings *internet.StreamConfig `protobuf:"bytes,3,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
||||||
StreamSettings *internet.StreamConfig `protobuf:"bytes,4,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
ReceiveOriginalDestination bool `protobuf:"varint,4,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"`
|
||||||
ReceiveOriginalDestination bool `protobuf:"varint,5,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"`
|
SniffingSettings *SniffingConfig `protobuf:"bytes,6,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
|
||||||
SniffingSettings *SniffingConfig `protobuf:"bytes,7,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReceiverConfig) Reset() {
|
func (x *ReceiverConfig) Reset() {
|
||||||
*x = ReceiverConfig{}
|
*x = ReceiverConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[3]
|
mi := &file_app_proxyman_config_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -288,7 +170,7 @@ func (x *ReceiverConfig) String() string {
|
|||||||
func (*ReceiverConfig) ProtoMessage() {}
|
func (*ReceiverConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ReceiverConfig) ProtoReflect() protoreflect.Message {
|
func (x *ReceiverConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[3]
|
mi := &file_app_proxyman_config_proto_msgTypes[2]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -301,7 +183,7 @@ func (x *ReceiverConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use ReceiverConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use ReceiverConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*ReceiverConfig) Descriptor() ([]byte, []int) {
|
func (*ReceiverConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{3}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReceiverConfig) GetPortList() *net.PortList {
|
func (x *ReceiverConfig) GetPortList() *net.PortList {
|
||||||
@@ -318,13 +200,6 @@ func (x *ReceiverConfig) GetListen() *net.IPOrDomain {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReceiverConfig) GetAllocationStrategy() *AllocationStrategy {
|
|
||||||
if x != nil {
|
|
||||||
return x.AllocationStrategy
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ReceiverConfig) GetStreamSettings() *internet.StreamConfig {
|
func (x *ReceiverConfig) GetStreamSettings() *internet.StreamConfig {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.StreamSettings
|
return x.StreamSettings
|
||||||
@@ -358,7 +233,7 @@ type InboundHandlerConfig struct {
|
|||||||
|
|
||||||
func (x *InboundHandlerConfig) Reset() {
|
func (x *InboundHandlerConfig) Reset() {
|
||||||
*x = InboundHandlerConfig{}
|
*x = InboundHandlerConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[4]
|
mi := &file_app_proxyman_config_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -370,7 +245,7 @@ func (x *InboundHandlerConfig) String() string {
|
|||||||
func (*InboundHandlerConfig) ProtoMessage() {}
|
func (*InboundHandlerConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message {
|
func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[4]
|
mi := &file_app_proxyman_config_proto_msgTypes[3]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -383,7 +258,7 @@ func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use InboundHandlerConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use InboundHandlerConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*InboundHandlerConfig) Descriptor() ([]byte, []int) {
|
func (*InboundHandlerConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{4}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *InboundHandlerConfig) GetTag() string {
|
func (x *InboundHandlerConfig) GetTag() string {
|
||||||
@@ -415,7 +290,7 @@ type OutboundConfig struct {
|
|||||||
|
|
||||||
func (x *OutboundConfig) Reset() {
|
func (x *OutboundConfig) Reset() {
|
||||||
*x = OutboundConfig{}
|
*x = OutboundConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[5]
|
mi := &file_app_proxyman_config_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -427,7 +302,7 @@ func (x *OutboundConfig) String() string {
|
|||||||
func (*OutboundConfig) ProtoMessage() {}
|
func (*OutboundConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *OutboundConfig) ProtoReflect() protoreflect.Message {
|
func (x *OutboundConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[5]
|
mi := &file_app_proxyman_config_proto_msgTypes[4]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -440,7 +315,7 @@ func (x *OutboundConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use OutboundConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use OutboundConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*OutboundConfig) Descriptor() ([]byte, []int) {
|
func (*OutboundConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{5}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SenderConfig struct {
|
type SenderConfig struct {
|
||||||
@@ -459,7 +334,7 @@ type SenderConfig struct {
|
|||||||
|
|
||||||
func (x *SenderConfig) Reset() {
|
func (x *SenderConfig) Reset() {
|
||||||
*x = SenderConfig{}
|
*x = SenderConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[6]
|
mi := &file_app_proxyman_config_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -471,7 +346,7 @@ func (x *SenderConfig) String() string {
|
|||||||
func (*SenderConfig) ProtoMessage() {}
|
func (*SenderConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *SenderConfig) ProtoReflect() protoreflect.Message {
|
func (x *SenderConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[6]
|
mi := &file_app_proxyman_config_proto_msgTypes[5]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -484,7 +359,7 @@ func (x *SenderConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use SenderConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use SenderConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*SenderConfig) Descriptor() ([]byte, []int) {
|
func (*SenderConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{6}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SenderConfig) GetVia() *net.IPOrDomain {
|
func (x *SenderConfig) GetVia() *net.IPOrDomain {
|
||||||
@@ -546,7 +421,7 @@ type MultiplexingConfig struct {
|
|||||||
|
|
||||||
func (x *MultiplexingConfig) Reset() {
|
func (x *MultiplexingConfig) Reset() {
|
||||||
*x = MultiplexingConfig{}
|
*x = MultiplexingConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[7]
|
mi := &file_app_proxyman_config_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -558,7 +433,7 @@ func (x *MultiplexingConfig) String() string {
|
|||||||
func (*MultiplexingConfig) ProtoMessage() {}
|
func (*MultiplexingConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message {
|
func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[7]
|
mi := &file_app_proxyman_config_proto_msgTypes[6]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -571,7 +446,7 @@ func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use MultiplexingConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use MultiplexingConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*MultiplexingConfig) Descriptor() ([]byte, []int) {
|
func (*MultiplexingConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{7}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *MultiplexingConfig) GetEnabled() bool {
|
func (x *MultiplexingConfig) GetEnabled() bool {
|
||||||
@@ -602,96 +477,6 @@ func (x *MultiplexingConfig) GetXudpProxyUDP443() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type AllocationStrategy_AllocationStrategyConcurrency struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyConcurrency) Reset() {
|
|
||||||
*x = AllocationStrategy_AllocationStrategyConcurrency{}
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[8]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyConcurrency) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*AllocationStrategy_AllocationStrategyConcurrency) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyConcurrency) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[8]
|
|
||||||
if x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use AllocationStrategy_AllocationStrategyConcurrency.ProtoReflect.Descriptor instead.
|
|
||||||
func (*AllocationStrategy_AllocationStrategyConcurrency) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyConcurrency) GetValue() uint32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Value
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type AllocationStrategy_AllocationStrategyRefresh struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyRefresh) Reset() {
|
|
||||||
*x = AllocationStrategy_AllocationStrategyRefresh{}
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[9]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyRefresh) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*AllocationStrategy_AllocationStrategyRefresh) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyRefresh) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[9]
|
|
||||||
if x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use AllocationStrategy_AllocationStrategyRefresh.ProtoReflect.Descriptor instead.
|
|
||||||
func (*AllocationStrategy_AllocationStrategyRefresh) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyRefresh) GetValue() uint32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Value
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_app_proxyman_config_proto protoreflect.FileDescriptor
|
var File_app_proxyman_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_proxyman_config_proto_rawDesc = []byte{
|
var file_app_proxyman_config_proto_rawDesc = []byte{
|
||||||
@@ -706,130 +491,98 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
|||||||
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f,
|
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f,
|
||||||
0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72,
|
0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72,
|
||||||
0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f,
|
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,
|
0x6e, 0x66, 0x69, 0x67, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e,
|
||||||
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x3e, 0x0a, 0x04, 0x74,
|
0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||||
0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c,
|
0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x65, 0x0a, 0x0b, 0x63,
|
0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72,
|
||||||
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x5f,
|
||||||
0x32, 0x43, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f,
|
||||||
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53,
|
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x12,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, 0x79,
|
||||||
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||||
0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f, 0x6e,
|
||||||
0x63, 0x79, 0x12, 0x59, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20,
|
0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x4f,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
|
0x6e, 0x6c, 0x79, 0x22, 0xe5, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72,
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c,
|
||||||
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
|
0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66,
|
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74,
|
||||||
0x72, 0x65, 0x73, 0x68, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x1a, 0x35, 0x0a,
|
0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33,
|
||||||
0x1d, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
|
0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
|
||||||
0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x14,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
|
||||||
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76,
|
0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69, 0x73,
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x1a, 0x31, 0x0a, 0x19, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
0x74, 0x65, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65,
|
||||||
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73,
|
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78,
|
||||||
0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
|
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
||||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
|
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e,
|
||||||
0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52,
|
0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72,
|
0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f,
|
||||||
0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69,
|
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
||||||
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69,
|
||||||
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e,
|
||||||
0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e,
|
||||||
0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
|
0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65,
|
0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73,
|
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
||||||
0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74,
|
||||||
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64,
|
0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0xc0, 0x01, 0x0a, 0x14,
|
||||||
0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c,
|
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f,
|
||||||
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f,
|
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76,
|
||||||
0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x4f, 0x6e, 0x6c, 0x79, 0x22, 0xbd, 0x03, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||||
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f,
|
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73,
|
||||||
0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61,
|
0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74,
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72,
|
0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73,
|
||||||
0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12,
|
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
|
||||||
0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
||||||
0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
|
0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52,
|
||||||
0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69,
|
0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10,
|
||||||
0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
|
0x22, 0x9d, 0x03, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f,
|
0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
|
||||||
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
|
||||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
|
0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4e, 0x0a, 0x0f,
|
0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74,
|
0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c,
|
0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||||
0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
|
0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
|
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||||
0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69,
|
0x65, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d,
|
||||||
0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e,
|
0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a,
|
||||||
0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x6e, 0x67, 0x73, 0x18, 0x04, 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, 0x53, 0x6e,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75,
|
||||||
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, 0x9d, 0x03, 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, 0x53, 0x74, 0x72,
|
|
||||||
0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61,
|
|
||||||
0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f,
|
|
||||||
0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
|
|
||||||
0x0b, 0x32, 0x24, 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, 0x50, 0x72, 0x6f, 0x78,
|
|
||||||
0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65,
|
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
|
|
||||||
0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 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, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78,
|
|
||||||
0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69,
|
|
||||||
0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08,
|
|
||||||
0x76, 0x69, 0x61, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
|
||||||
0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x12, 0x50, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65,
|
|
||||||
0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e,
|
|
||||||
0x32, 0x27, 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, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
|
||||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65,
|
|
||||||
0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75,
|
|
||||||
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 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,
|
0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f,
|
0x6e, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x69, 0x61, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18,
|
||||||
0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
|
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x12, 0x50,
|
||||||
0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f,
|
0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18,
|
0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
|
||||||
0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75,
|
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
||||||
0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72,
|
0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
|
0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 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, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79,
|
||||||
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65,
|
||||||
|
0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75,
|
||||||
|
0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75,
|
||||||
|
0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a,
|
||||||
0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33,
|
0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33,
|
||||||
0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74,
|
0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
|
||||||
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
||||||
0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50,
|
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70,
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
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 (
|
||||||
@@ -844,48 +597,39 @@ func file_app_proxyman_config_proto_rawDescGZIP() []byte {
|
|||||||
return file_app_proxyman_config_proto_rawDescData
|
return file_app_proxyman_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||||
var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
|
||||||
var file_app_proxyman_config_proto_goTypes = []any{
|
var file_app_proxyman_config_proto_goTypes = []any{
|
||||||
(AllocationStrategy_Type)(0), // 0: xray.app.proxyman.AllocationStrategy.Type
|
(*InboundConfig)(nil), // 0: xray.app.proxyman.InboundConfig
|
||||||
(*InboundConfig)(nil), // 1: xray.app.proxyman.InboundConfig
|
(*SniffingConfig)(nil), // 1: xray.app.proxyman.SniffingConfig
|
||||||
(*AllocationStrategy)(nil), // 2: xray.app.proxyman.AllocationStrategy
|
(*ReceiverConfig)(nil), // 2: xray.app.proxyman.ReceiverConfig
|
||||||
(*SniffingConfig)(nil), // 3: xray.app.proxyman.SniffingConfig
|
(*InboundHandlerConfig)(nil), // 3: xray.app.proxyman.InboundHandlerConfig
|
||||||
(*ReceiverConfig)(nil), // 4: xray.app.proxyman.ReceiverConfig
|
(*OutboundConfig)(nil), // 4: xray.app.proxyman.OutboundConfig
|
||||||
(*InboundHandlerConfig)(nil), // 5: xray.app.proxyman.InboundHandlerConfig
|
(*SenderConfig)(nil), // 5: xray.app.proxyman.SenderConfig
|
||||||
(*OutboundConfig)(nil), // 6: xray.app.proxyman.OutboundConfig
|
(*MultiplexingConfig)(nil), // 6: xray.app.proxyman.MultiplexingConfig
|
||||||
(*SenderConfig)(nil), // 7: xray.app.proxyman.SenderConfig
|
(*net.PortList)(nil), // 7: xray.common.net.PortList
|
||||||
(*MultiplexingConfig)(nil), // 8: xray.app.proxyman.MultiplexingConfig
|
(*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain
|
||||||
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 9: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
(*internet.StreamConfig)(nil), // 9: xray.transport.internet.StreamConfig
|
||||||
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
(*serial.TypedMessage)(nil), // 10: xray.common.serial.TypedMessage
|
||||||
(*net.PortList)(nil), // 11: xray.common.net.PortList
|
(*internet.ProxyConfig)(nil), // 11: xray.transport.internet.ProxyConfig
|
||||||
(*net.IPOrDomain)(nil), // 12: xray.common.net.IPOrDomain
|
(internet.DomainStrategy)(0), // 12: xray.transport.internet.DomainStrategy
|
||||||
(*internet.StreamConfig)(nil), // 13: xray.transport.internet.StreamConfig
|
|
||||||
(*serial.TypedMessage)(nil), // 14: xray.common.serial.TypedMessage
|
|
||||||
(*internet.ProxyConfig)(nil), // 15: xray.transport.internet.ProxyConfig
|
|
||||||
(internet.DomainStrategy)(0), // 16: xray.transport.internet.DomainStrategy
|
|
||||||
}
|
}
|
||||||
var file_app_proxyman_config_proto_depIdxs = []int32{
|
var file_app_proxyman_config_proto_depIdxs = []int32{
|
||||||
0, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
7, // 0: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
||||||
9, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
8, // 1: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
||||||
10, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
9, // 2: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
11, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
1, // 3: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
||||||
12, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
10, // 4: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
2, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
|
10, // 5: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
13, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
8, // 6: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
||||||
3, // 7: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
9, // 7: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
14, // 8: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
11, // 8: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
||||||
14, // 9: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
6, // 9: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
||||||
12, // 10: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
12, // 10: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||||
13, // 11: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
11, // [11:11] is the sub-list for method output_type
|
||||||
15, // 12: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
11, // [11:11] is the sub-list for method input_type
|
||||||
8, // 13: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
16, // 14: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy
|
11, // [11:11] is the sub-list for extension extendee
|
||||||
15, // [15:15] is the sub-list for method output_type
|
0, // [0:11] is the sub-list for field type_name
|
||||||
15, // [15:15] is the sub-list for method input_type
|
|
||||||
15, // [15:15] is the sub-list for extension type_name
|
|
||||||
15, // [15:15] is the sub-list for extension extendee
|
|
||||||
0, // [0:15] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_proxyman_config_proto_init() }
|
func init() { file_app_proxyman_config_proto_init() }
|
||||||
@@ -898,14 +642,13 @@ func file_app_proxyman_config_proto_init() {
|
|||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_proxyman_config_proto_rawDesc,
|
RawDescriptor: file_app_proxyman_config_proto_rawDesc,
|
||||||
NumEnums: 1,
|
NumEnums: 0,
|
||||||
NumMessages: 10,
|
NumMessages: 7,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
GoTypes: file_app_proxyman_config_proto_goTypes,
|
GoTypes: file_app_proxyman_config_proto_goTypes,
|
||||||
DependencyIndexes: file_app_proxyman_config_proto_depIdxs,
|
DependencyIndexes: file_app_proxyman_config_proto_depIdxs,
|
||||||
EnumInfos: file_app_proxyman_config_proto_enumTypes,
|
|
||||||
MessageInfos: file_app_proxyman_config_proto_msgTypes,
|
MessageInfos: file_app_proxyman_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_proxyman_config_proto = out.File
|
File_app_proxyman_config_proto = out.File
|
||||||
|
|||||||
@@ -13,33 +13,6 @@ import "common/serial/typed_message.proto";
|
|||||||
|
|
||||||
message InboundConfig {}
|
message InboundConfig {}
|
||||||
|
|
||||||
message AllocationStrategy {
|
|
||||||
enum Type {
|
|
||||||
// Always allocate all connection handlers.
|
|
||||||
Always = 0;
|
|
||||||
|
|
||||||
// Randomly allocate specific range of handlers.
|
|
||||||
Random = 1;
|
|
||||||
|
|
||||||
// External. Not supported yet.
|
|
||||||
External = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type = 1;
|
|
||||||
|
|
||||||
message AllocationStrategyConcurrency { uint32 value = 1; }
|
|
||||||
|
|
||||||
// Number of handlers (ports) running in parallel.
|
|
||||||
// Default value is 3 if unset.
|
|
||||||
AllocationStrategyConcurrency concurrency = 2;
|
|
||||||
|
|
||||||
message AllocationStrategyRefresh { uint32 value = 1; }
|
|
||||||
|
|
||||||
// Number of minutes before a handler is regenerated.
|
|
||||||
// Default value is 5 if unset.
|
|
||||||
AllocationStrategyRefresh refresh = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SniffingConfig {
|
message SniffingConfig {
|
||||||
// Whether or not to enable content sniffing on an inbound connection.
|
// Whether or not to enable content sniffing on an inbound connection.
|
||||||
bool enabled = 1;
|
bool enabled = 1;
|
||||||
@@ -62,11 +35,10 @@ message ReceiverConfig {
|
|||||||
xray.common.net.PortList port_list = 1;
|
xray.common.net.PortList port_list = 1;
|
||||||
// Listen specifies the IP address that the Receiver should listen on.
|
// Listen specifies the IP address that the Receiver should listen on.
|
||||||
xray.common.net.IPOrDomain listen = 2;
|
xray.common.net.IPOrDomain listen = 2;
|
||||||
AllocationStrategy allocation_strategy = 3;
|
xray.transport.internet.StreamConfig stream_settings = 3;
|
||||||
xray.transport.internet.StreamConfig stream_settings = 4;
|
bool receive_original_destination = 4;
|
||||||
bool receive_original_destination = 5;
|
reserved 5;
|
||||||
reserved 6;
|
SniffingConfig sniffing_settings = 6;
|
||||||
SniffingConfig sniffing_settings = 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message InboundHandlerConfig {
|
message InboundHandlerConfig {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"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/dice"
|
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -103,7 +102,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
stream: mss,
|
stream: mss,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.SniffingSettings,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -125,7 +124,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: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.SniffingSettings,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -140,7 +139,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.SniffingSettings,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
@@ -178,14 +177,6 @@ func (h *AlwaysOnInboundHandler) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *AlwaysOnInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
|
|
||||||
if len(h.workers) == 0 {
|
|
||||||
return nil, 0, 0
|
|
||||||
}
|
|
||||||
w := h.workers[dice.Roll(len(h.workers))]
|
|
||||||
return w.Proxy(), w.Port(), 9999
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *AlwaysOnInboundHandler) Tag() string {
|
func (h *AlwaysOnInboundHandler) Tag() string {
|
||||||
return h.tag
|
return h.tag
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,222 +0,0 @@
|
|||||||
package inbound
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/mux"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/common/task"
|
|
||||||
"github.com/xtls/xray-core/core"
|
|
||||||
"github.com/xtls/xray-core/proxy"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DynamicInboundHandler struct {
|
|
||||||
tag string
|
|
||||||
v *core.Instance
|
|
||||||
proxyConfig interface{}
|
|
||||||
receiverConfig *proxyman.ReceiverConfig
|
|
||||||
streamSettings *internet.MemoryStreamConfig
|
|
||||||
portMutex sync.Mutex
|
|
||||||
portsInUse map[net.Port]struct{}
|
|
||||||
workerMutex sync.RWMutex
|
|
||||||
worker []worker
|
|
||||||
lastRefresh time.Time
|
|
||||||
mux *mux.Server
|
|
||||||
task *task.Periodic
|
|
||||||
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*DynamicInboundHandler, error) {
|
|
||||||
v := core.MustFromContext(ctx)
|
|
||||||
h := &DynamicInboundHandler{
|
|
||||||
tag: tag,
|
|
||||||
proxyConfig: proxyConfig,
|
|
||||||
receiverConfig: receiverConfig,
|
|
||||||
portsInUse: make(map[net.Port]struct{}),
|
|
||||||
mux: mux.NewServer(ctx),
|
|
||||||
v: v,
|
|
||||||
ctx: ctx,
|
|
||||||
}
|
|
||||||
|
|
||||||
mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to parse stream settings").Base(err).AtWarning()
|
|
||||||
}
|
|
||||||
if receiverConfig.ReceiveOriginalDestination {
|
|
||||||
if mss.SocketSettings == nil {
|
|
||||||
mss.SocketSettings = &internet.SocketConfig{}
|
|
||||||
}
|
|
||||||
if mss.SocketSettings.Tproxy == internet.SocketConfig_Off {
|
|
||||||
mss.SocketSettings.Tproxy = internet.SocketConfig_Redirect
|
|
||||||
}
|
|
||||||
mss.SocketSettings.ReceiveOriginalDestAddress = true
|
|
||||||
}
|
|
||||||
|
|
||||||
h.streamSettings = mss
|
|
||||||
|
|
||||||
h.task = &task.Periodic{
|
|
||||||
Interval: time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()),
|
|
||||||
Execute: h.refresh,
|
|
||||||
}
|
|
||||||
|
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) allocatePort() net.Port {
|
|
||||||
allPorts := []int32{}
|
|
||||||
for _, pr := range h.receiverConfig.PortList.Range {
|
|
||||||
for i := pr.From; i <= pr.To; i++ {
|
|
||||||
allPorts = append(allPorts, int32(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.portMutex.Lock()
|
|
||||||
defer h.portMutex.Unlock()
|
|
||||||
|
|
||||||
for {
|
|
||||||
r := dice.Roll(len(allPorts))
|
|
||||||
port := net.Port(allPorts[r])
|
|
||||||
_, used := h.portsInUse[port]
|
|
||||||
if !used {
|
|
||||||
h.portsInUse[port] = struct{}{}
|
|
||||||
return port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) closeWorkers(workers []worker) {
|
|
||||||
ports2Del := make([]net.Port, len(workers))
|
|
||||||
for idx, worker := range workers {
|
|
||||||
ports2Del[idx] = worker.Port()
|
|
||||||
if err := worker.Close(); err != nil {
|
|
||||||
errors.LogInfoInner(h.ctx, err, "failed to close worker")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h.portMutex.Lock()
|
|
||||||
for _, port := range ports2Del {
|
|
||||||
delete(h.portsInUse, port)
|
|
||||||
}
|
|
||||||
h.portMutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) refresh() error {
|
|
||||||
h.lastRefresh = time.Now()
|
|
||||||
|
|
||||||
timeout := time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()) * 2
|
|
||||||
concurrency := h.receiverConfig.AllocationStrategy.GetConcurrencyValue()
|
|
||||||
workers := make([]worker, 0, concurrency)
|
|
||||||
|
|
||||||
address := h.receiverConfig.Listen.AsAddress()
|
|
||||||
if address == nil {
|
|
||||||
address = net.AnyIP
|
|
||||||
}
|
|
||||||
|
|
||||||
uplinkCounter, downlinkCounter := getStatCounter(h.v, h.tag)
|
|
||||||
|
|
||||||
for i := uint32(0); i < concurrency; i++ {
|
|
||||||
port := h.allocatePort()
|
|
||||||
rawProxy, err := core.CreateObject(h.v, h.proxyConfig)
|
|
||||||
if err != nil {
|
|
||||||
errors.LogWarningInner(h.ctx, err, "failed to create proxy instance")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p := rawProxy.(proxy.Inbound)
|
|
||||||
nl := p.Network()
|
|
||||||
if net.HasNetwork(nl, net.Network_TCP) {
|
|
||||||
worker := &tcpWorker{
|
|
||||||
tag: h.tag,
|
|
||||||
address: address,
|
|
||||||
port: port,
|
|
||||||
proxy: p,
|
|
||||||
stream: h.streamSettings,
|
|
||||||
recvOrigDest: h.receiverConfig.ReceiveOriginalDestination,
|
|
||||||
dispatcher: h.mux,
|
|
||||||
sniffingConfig: h.receiverConfig.GetEffectiveSniffingSettings(),
|
|
||||||
uplinkCounter: uplinkCounter,
|
|
||||||
downlinkCounter: downlinkCounter,
|
|
||||||
ctx: h.ctx,
|
|
||||||
}
|
|
||||||
if err := worker.Start(); err != nil {
|
|
||||||
errors.LogWarningInner(h.ctx, err, "failed to create TCP worker")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
workers = append(workers, worker)
|
|
||||||
}
|
|
||||||
|
|
||||||
if net.HasNetwork(nl, net.Network_UDP) {
|
|
||||||
worker := &udpWorker{
|
|
||||||
tag: h.tag,
|
|
||||||
proxy: p,
|
|
||||||
address: address,
|
|
||||||
port: port,
|
|
||||||
dispatcher: h.mux,
|
|
||||||
sniffingConfig: h.receiverConfig.GetEffectiveSniffingSettings(),
|
|
||||||
uplinkCounter: uplinkCounter,
|
|
||||||
downlinkCounter: downlinkCounter,
|
|
||||||
stream: h.streamSettings,
|
|
||||||
ctx: h.ctx,
|
|
||||||
}
|
|
||||||
if err := worker.Start(); err != nil {
|
|
||||||
errors.LogWarningInner(h.ctx, err, "failed to create UDP worker")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
workers = append(workers, worker)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h.workerMutex.Lock()
|
|
||||||
h.worker = workers
|
|
||||||
h.workerMutex.Unlock()
|
|
||||||
|
|
||||||
time.AfterFunc(timeout, func() {
|
|
||||||
h.closeWorkers(workers)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) Start() error {
|
|
||||||
return h.task.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) Close() error {
|
|
||||||
return h.task.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
|
|
||||||
h.workerMutex.RLock()
|
|
||||||
defer h.workerMutex.RUnlock()
|
|
||||||
|
|
||||||
if len(h.worker) == 0 {
|
|
||||||
return nil, 0, 0
|
|
||||||
}
|
|
||||||
w := h.worker[dice.Roll(len(h.worker))]
|
|
||||||
expire := h.receiverConfig.AllocationStrategy.GetRefreshValue() - uint32(time.Since(h.lastRefresh)/time.Minute)
|
|
||||||
return w.Proxy(), w.Port(), int(expire)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) Tag() string {
|
|
||||||
return h.tag
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReceiverSettings implements inbound.Handler.
|
|
||||||
func (h *DynamicInboundHandler) ReceiverSettings() *serial.TypedMessage {
|
|
||||||
return serial.ToTypedMessage(h.receiverConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProxySettings implements inbound.Handler.
|
|
||||||
func (h *DynamicInboundHandler) ProxySettings() *serial.TypedMessage {
|
|
||||||
if v, ok := h.proxyConfig.(proto.Message); ok {
|
|
||||||
return serial.ToTypedMessage(v)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -178,15 +178,7 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
|
|||||||
ctx = session.ContextWithAllowedNetwork(ctx, net.Network_UDP)
|
ctx = session.ContextWithAllowedNetwork(ctx, net.Network_UDP)
|
||||||
}
|
}
|
||||||
|
|
||||||
allocStrategy := receiverSettings.AllocationStrategy
|
return NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings)
|
||||||
if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always {
|
|
||||||
return NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings)
|
|
||||||
}
|
|
||||||
|
|
||||||
if allocStrategy.Type == proxyman.AllocationStrategy_Random {
|
|
||||||
return NewDynamicInboundHandler(ctx, tag, receiverSettings, proxySettings)
|
|
||||||
}
|
|
||||||
return nil, errors.New("unknown allocation strategy: ", receiverSettings.AllocationStrategy.Type).AtError()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
|
|||||||
}
|
}
|
||||||
h.proxyConfig = proxyConfig
|
h.proxyConfig = proxyConfig
|
||||||
|
|
||||||
ctx = session.ContextWithHandler(ctx, h)
|
ctx = session.ContextWithFullHandler(ctx, h)
|
||||||
|
|
||||||
rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
|
rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -198,9 +198,11 @@ func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
|
|||||||
|
|
||||||
func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error) {
|
func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error) {
|
||||||
if !isInternalDomain(dest) {
|
if !isInternalDomain(dest) {
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
if session.InboundFromContext(ctx) == nil {
|
||||||
Tag: w.Tag,
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
})
|
Tag: w.Tag,
|
||||||
|
})
|
||||||
|
}
|
||||||
return w.Dispatcher.Dispatch(ctx, dest)
|
return w.Dispatcher.Dispatch(ctx, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,9 +223,11 @@ func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*tra
|
|||||||
|
|
||||||
func (w *BridgeWorker) DispatchLink(ctx context.Context, dest net.Destination, link *transport.Link) error {
|
func (w *BridgeWorker) DispatchLink(ctx context.Context, dest net.Destination, link *transport.Link) error {
|
||||||
if !isInternalDomain(dest) {
|
if !isInternalDomain(dest) {
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
if session.InboundFromContext(ctx) == nil {
|
||||||
Tag: w.Tag,
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
})
|
Tag: w.Tag,
|
||||||
|
})
|
||||||
|
}
|
||||||
return w.Dispatcher.DispatchLink(ctx, dest, link)
|
return w.Dispatcher.DispatchLink(ctx, dest, link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -264,7 +264,11 @@ func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
|
|||||||
transferType = protocol.TransferTypePacket
|
transferType = protocol.TransferTypePacket
|
||||||
}
|
}
|
||||||
s.transferType = transferType
|
s.transferType = transferType
|
||||||
writer := NewWriter(s.ID, ob.Target, output, transferType, xudp.GetGlobalID(ctx))
|
var inbound *session.Inbound
|
||||||
|
if session.IsReverseMuxFromContext(ctx) {
|
||||||
|
inbound = session.InboundFromContext(ctx)
|
||||||
|
}
|
||||||
|
writer := NewWriter(s.ID, ob.Target, output, transferType, xudp.GetGlobalID(ctx), inbound)
|
||||||
defer s.Close(false)
|
defer s.Close(false)
|
||||||
defer writer.Close()
|
defer writer.Close()
|
||||||
|
|
||||||
@@ -384,7 +388,7 @@ func (m *ClientWorker) fetchOutput() {
|
|||||||
|
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
for {
|
for {
|
||||||
err := meta.Unmarshal(reader)
|
err := meta.Unmarshal(reader, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) != io.EOF {
|
if errors.Cause(err) != io.EOF {
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to read metadata")
|
errors.LogInfoInner(context.Background(), err, "failed to read metadata")
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SessionStatus byte
|
type SessionStatus byte
|
||||||
@@ -60,6 +61,7 @@ type FrameMetadata struct {
|
|||||||
Option bitmask.Byte
|
Option bitmask.Byte
|
||||||
SessionStatus SessionStatus
|
SessionStatus SessionStatus
|
||||||
GlobalID [8]byte
|
GlobalID [8]byte
|
||||||
|
Inbound *session.Inbound
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
||||||
@@ -79,11 +81,23 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
|||||||
case net.Network_UDP:
|
case net.Network_UDP:
|
||||||
common.Must(b.WriteByte(byte(TargetNetworkUDP)))
|
common.Must(b.WriteByte(byte(TargetNetworkUDP)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
|
if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if b.UDP != nil { // make sure it's user's proxy request
|
if f.Inbound != nil {
|
||||||
|
if f.Inbound.Source.Network == net.Network_TCP || f.Inbound.Source.Network == net.Network_UDP {
|
||||||
|
common.Must(b.WriteByte(byte(f.Inbound.Source.Network - 1)))
|
||||||
|
if err := addrParser.WriteAddressPort(b, f.Inbound.Source.Address, f.Inbound.Source.Port); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if f.Inbound.Local.Network == net.Network_TCP || f.Inbound.Local.Network == net.Network_UDP {
|
||||||
|
common.Must(b.WriteByte(byte(f.Inbound.Local.Network - 1)))
|
||||||
|
if err := addrParser.WriteAddressPort(b, f.Inbound.Local.Address, f.Inbound.Local.Port); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if b.UDP != nil { // make sure it's user's proxy request
|
||||||
b.Write(f.GlobalID[:]) // no need to check whether it's empty
|
b.Write(f.GlobalID[:]) // no need to check whether it's empty
|
||||||
}
|
}
|
||||||
} else if b.UDP != nil {
|
} else if b.UDP != nil {
|
||||||
@@ -97,7 +111,7 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal reads FrameMetadata from the given reader.
|
// Unmarshal reads FrameMetadata from the given reader.
|
||||||
func (f *FrameMetadata) Unmarshal(reader io.Reader) error {
|
func (f *FrameMetadata) Unmarshal(reader io.Reader, readSourceAndLocal bool) error {
|
||||||
metaLen, err := serial.ReadUint16(reader)
|
metaLen, err := serial.ReadUint16(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -112,12 +126,12 @@ func (f *FrameMetadata) Unmarshal(reader io.Reader) error {
|
|||||||
if _, err := b.ReadFullFrom(reader, int32(metaLen)); err != nil {
|
if _, err := b.ReadFullFrom(reader, int32(metaLen)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return f.UnmarshalFromBuffer(b)
|
return f.UnmarshalFromBuffer(b, readSourceAndLocal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalFromBuffer reads a FrameMetadata from the given buffer.
|
// UnmarshalFromBuffer reads a FrameMetadata from the given buffer.
|
||||||
// Visible for testing only.
|
// Visible for testing only.
|
||||||
func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
|
func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer, readSourceAndLocal bool) error {
|
||||||
if b.Len() < 4 {
|
if b.Len() < 4 {
|
||||||
return errors.New("insufficient buffer: ", b.Len())
|
return errors.New("insufficient buffer: ", b.Len())
|
||||||
}
|
}
|
||||||
@@ -150,6 +164,54 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.SessionStatus == SessionStatusNew && readSourceAndLocal {
|
||||||
|
f.Inbound = &session.Inbound{}
|
||||||
|
|
||||||
|
if b.Len() == 0 {
|
||||||
|
return nil // for heartbeat, etc.
|
||||||
|
}
|
||||||
|
network := TargetNetwork(b.Byte(0))
|
||||||
|
if network == 0 {
|
||||||
|
return nil // may be padding
|
||||||
|
}
|
||||||
|
b.Advance(1)
|
||||||
|
addr, port, err := addrParser.ReadAddressPort(nil, b)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("reading source: failed to parse address and port").Base(err)
|
||||||
|
}
|
||||||
|
switch network {
|
||||||
|
case TargetNetworkTCP:
|
||||||
|
f.Inbound.Source = net.TCPDestination(addr, port)
|
||||||
|
case TargetNetworkUDP:
|
||||||
|
f.Inbound.Source = net.UDPDestination(addr, port)
|
||||||
|
default:
|
||||||
|
return errors.New("reading source: unknown network type: ", network)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Len() == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
network = TargetNetwork(b.Byte(0))
|
||||||
|
if network == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b.Advance(1)
|
||||||
|
addr, port, err = addrParser.ReadAddressPort(nil, b)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("reading local: failed to parse address and port").Base(err)
|
||||||
|
}
|
||||||
|
switch network {
|
||||||
|
case TargetNetworkTCP:
|
||||||
|
f.Inbound.Local = net.TCPDestination(addr, port)
|
||||||
|
case TargetNetworkUDP:
|
||||||
|
f.Inbound.Local = net.UDPDestination(addr, port)
|
||||||
|
default:
|
||||||
|
return errors.New("reading local: unknown network type: ", network)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Application data is essential, to test whether the pipe is closed.
|
// Application data is essential, to test whether the pipe is closed.
|
||||||
if f.SessionStatus == SessionStatusNew && f.Option.Has(OptionData) &&
|
if f.SessionStatus == SessionStatusNew && f.Option.Has(OptionData) &&
|
||||||
f.Target.Network == net.Network_UDP && b.Len() >= 8 {
|
f.Target.Network == net.Network_UDP && b.Len() >= 8 {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
. "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/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/transport/pipe"
|
"github.com/xtls/xray-core/transport/pipe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,13 +33,13 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
pReader, pWriter := pipe.New(pipe.WithSizeLimit(1024))
|
pReader, pWriter := pipe.New(pipe.WithSizeLimit(1024))
|
||||||
|
|
||||||
dest := net.TCPDestination(net.DomainAddress("example.com"), 80)
|
dest := net.TCPDestination(net.DomainAddress("example.com"), 80)
|
||||||
writer := NewWriter(1, dest, pWriter, protocol.TransferTypeStream, [8]byte{})
|
writer := NewWriter(1, dest, pWriter, protocol.TransferTypeStream, [8]byte{}, &session.Inbound{})
|
||||||
|
|
||||||
dest2 := net.TCPDestination(net.LocalHostIP, 443)
|
dest2 := net.TCPDestination(net.LocalHostIP, 443)
|
||||||
writer2 := NewWriter(2, dest2, pWriter, protocol.TransferTypeStream, [8]byte{})
|
writer2 := NewWriter(2, dest2, pWriter, protocol.TransferTypeStream, [8]byte{}, &session.Inbound{})
|
||||||
|
|
||||||
dest3 := net.TCPDestination(net.LocalHostIPv6, 18374)
|
dest3 := net.TCPDestination(net.LocalHostIPv6, 18374)
|
||||||
writer3 := NewWriter(3, dest3, pWriter, protocol.TransferTypeStream, [8]byte{})
|
writer3 := NewWriter(3, dest3, pWriter, protocol.TransferTypeStream, [8]byte{}, &session.Inbound{})
|
||||||
|
|
||||||
writePayload := func(writer *Writer, payload ...byte) error {
|
writePayload := func(writer *Writer, payload ...byte) error {
|
||||||
b := buf.New()
|
b := buf.New()
|
||||||
@@ -62,7 +63,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 1,
|
SessionID: 1,
|
||||||
SessionStatus: SessionStatusNew,
|
SessionStatus: SessionStatusNew,
|
||||||
@@ -81,7 +82,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionStatus: SessionStatusNew,
|
SessionStatus: SessionStatusNew,
|
||||||
SessionID: 2,
|
SessionID: 2,
|
||||||
@@ -94,7 +95,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 1,
|
SessionID: 1,
|
||||||
SessionStatus: SessionStatusKeep,
|
SessionStatus: SessionStatusKeep,
|
||||||
@@ -112,7 +113,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 3,
|
SessionID: 3,
|
||||||
SessionStatus: SessionStatusNew,
|
SessionStatus: SessionStatusNew,
|
||||||
@@ -131,7 +132,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 1,
|
SessionID: 1,
|
||||||
SessionStatus: SessionStatusEnd,
|
SessionStatus: SessionStatusEnd,
|
||||||
@@ -143,7 +144,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 3,
|
SessionID: 3,
|
||||||
SessionStatus: SessionStatusEnd,
|
SessionStatus: SessionStatusEnd,
|
||||||
@@ -155,7 +156,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 2,
|
SessionID: 2,
|
||||||
SessionStatus: SessionStatusKeep,
|
SessionStatus: SessionStatusKeep,
|
||||||
@@ -173,7 +174,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 2,
|
SessionID: 2,
|
||||||
SessionStatus: SessionStatusEnd,
|
SessionStatus: SessionStatusEnd,
|
||||||
@@ -187,7 +188,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
err := meta.Unmarshal(bytesReader)
|
err := meta.Unmarshal(bytesReader, false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("nil error")
|
t.Error("nil error")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,6 +166,14 @@ func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.Bu
|
|||||||
|
|
||||||
func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error {
|
func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error {
|
||||||
ctx = session.SubContextFromMuxInbound(ctx)
|
ctx = session.SubContextFromMuxInbound(ctx)
|
||||||
|
if meta.Inbound != nil && meta.Inbound.Source.IsValid() && meta.Inbound.Local.IsValid() {
|
||||||
|
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
|
newInbound := *inbound
|
||||||
|
newInbound.Source = meta.Inbound.Source
|
||||||
|
newInbound.Local = meta.Inbound.Local
|
||||||
|
ctx = session.ContextWithInbound(ctx, &newInbound)
|
||||||
|
}
|
||||||
|
}
|
||||||
errors.LogInfo(ctx, "received request for ", meta.Target)
|
errors.LogInfo(ctx, "received request for ", meta.Target)
|
||||||
{
|
{
|
||||||
msg := &log.AccessMessage{
|
msg := &log.AccessMessage{
|
||||||
@@ -329,7 +337,7 @@ func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.Buffered
|
|||||||
|
|
||||||
func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error {
|
func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error {
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
err := meta.Unmarshal(reader)
|
err := meta.Unmarshal(reader, session.IsReverseMuxFromContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to read metadata").Base(err)
|
return errors.New("failed to read metadata").Base(err)
|
||||||
}
|
}
|
||||||
@@ -340,7 +348,7 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
|
|||||||
case SessionStatusEnd:
|
case SessionStatusEnd:
|
||||||
err = w.handleStatusEnd(&meta, reader)
|
err = w.handleStatusEnd(&meta, reader)
|
||||||
case SessionStatusNew:
|
case SessionStatusNew:
|
||||||
err = w.handleStatusNew(ctx, &meta, reader)
|
err = w.handleStatusNew(session.ContextWithIsReverseMux(ctx, false), &meta, reader)
|
||||||
case SessionStatusKeep:
|
case SessionStatusKeep:
|
||||||
err = w.handleStatusKeep(&meta, reader)
|
err = w.handleStatusKeep(&meta, reader)
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Writer struct {
|
type Writer struct {
|
||||||
@@ -16,9 +17,10 @@ type Writer struct {
|
|||||||
hasError bool
|
hasError bool
|
||||||
transferType protocol.TransferType
|
transferType protocol.TransferType
|
||||||
globalID [8]byte
|
globalID [8]byte
|
||||||
|
inbound *session.Inbound
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWriter(id uint16, dest net.Destination, writer buf.Writer, transferType protocol.TransferType, globalID [8]byte) *Writer {
|
func NewWriter(id uint16, dest net.Destination, writer buf.Writer, transferType protocol.TransferType, globalID [8]byte, inbound *session.Inbound) *Writer {
|
||||||
return &Writer{
|
return &Writer{
|
||||||
id: id,
|
id: id,
|
||||||
dest: dest,
|
dest: dest,
|
||||||
@@ -26,6 +28,7 @@ func NewWriter(id uint16, dest net.Destination, writer buf.Writer, transferType
|
|||||||
followup: false,
|
followup: false,
|
||||||
transferType: transferType,
|
transferType: transferType,
|
||||||
globalID: globalID,
|
globalID: globalID,
|
||||||
|
inbound: inbound,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +46,7 @@ func (w *Writer) getNextFrameMeta() FrameMetadata {
|
|||||||
SessionID: w.id,
|
SessionID: w.id,
|
||||||
Target: w.dest,
|
Target: w.dest,
|
||||||
GlobalID: w.globalID,
|
GlobalID: w.globalID,
|
||||||
|
Inbound: w.inbound,
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.followup {
|
if w.followup {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common/bitmask"
|
"github.com/xtls/xray-core/common/bitmask"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
|
||||||
"golang.org/x/sys/cpu"
|
"golang.org/x/sys/cpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -71,18 +70,10 @@ type ResponseHeader struct {
|
|||||||
Command ResponseCommand
|
Command ResponseCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandSwitchAccount struct {
|
|
||||||
Host net.Address
|
|
||||||
Port net.Port
|
|
||||||
ID uuid.UUID
|
|
||||||
Level uint32
|
|
||||||
ValidMin byte
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Keep in sync with crypto/tls/cipher_suites.go.
|
// Keep in sync with crypto/tls/cipher_suites.go.
|
||||||
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3
|
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3
|
||||||
hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
|
hasGCMAsmARM64 = (cpu.ARM64.HasAES && cpu.ARM64.HasPMULL) || (runtime.GOOS == "darwin" && runtime.GOARCH == "arm64")
|
||||||
hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCTR && cpu.S390X.HasGHASH
|
hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCTR && cpu.S390X.HasGHASH
|
||||||
hasGCMAsmPPC64 = runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le"
|
hasGCMAsmPPC64 = runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le"
|
||||||
|
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
package protocol
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ServerList struct {
|
|
||||||
sync.RWMutex
|
|
||||||
servers []*ServerSpec
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewServerList() *ServerList {
|
|
||||||
return &ServerList{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sl *ServerList) AddServer(server *ServerSpec) {
|
|
||||||
sl.Lock()
|
|
||||||
defer sl.Unlock()
|
|
||||||
|
|
||||||
sl.servers = append(sl.servers, server)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sl *ServerList) Size() uint32 {
|
|
||||||
sl.RLock()
|
|
||||||
defer sl.RUnlock()
|
|
||||||
|
|
||||||
return uint32(len(sl.servers))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sl *ServerList) GetServer(idx uint32) *ServerSpec {
|
|
||||||
sl.Lock()
|
|
||||||
defer sl.Unlock()
|
|
||||||
|
|
||||||
for {
|
|
||||||
if idx >= uint32(len(sl.servers)) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
server := sl.servers[idx]
|
|
||||||
if !server.IsValid() {
|
|
||||||
sl.removeServer(idx)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return server
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sl *ServerList) removeServer(idx uint32) {
|
|
||||||
n := len(sl.servers)
|
|
||||||
sl.servers[idx] = sl.servers[n-1]
|
|
||||||
sl.servers = sl.servers[:n-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerPicker interface {
|
|
||||||
PickServer() *ServerSpec
|
|
||||||
}
|
|
||||||
|
|
||||||
type RoundRobinServerPicker struct {
|
|
||||||
sync.Mutex
|
|
||||||
serverlist *ServerList
|
|
||||||
nextIndex uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRoundRobinServerPicker(serverlist *ServerList) *RoundRobinServerPicker {
|
|
||||||
return &RoundRobinServerPicker{
|
|
||||||
serverlist: serverlist,
|
|
||||||
nextIndex: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *RoundRobinServerPicker) PickServer() *ServerSpec {
|
|
||||||
p.Lock()
|
|
||||||
defer p.Unlock()
|
|
||||||
|
|
||||||
next := p.nextIndex
|
|
||||||
server := p.serverlist.GetServer(next)
|
|
||||||
if server == nil {
|
|
||||||
next = 0
|
|
||||||
server = p.serverlist.GetServer(0)
|
|
||||||
}
|
|
||||||
next++
|
|
||||||
if next >= p.serverlist.Size() {
|
|
||||||
next = 0
|
|
||||||
}
|
|
||||||
p.nextIndex = next
|
|
||||||
|
|
||||||
return server
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
package protocol_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
. "github.com/xtls/xray-core/common/protocol"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestServerList(t *testing.T) {
|
|
||||||
list := NewServerList()
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(1)), AlwaysValid()))
|
|
||||||
if list.Size() != 1 {
|
|
||||||
t.Error("list size: ", list.Size())
|
|
||||||
}
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
|
|
||||||
if list.Size() != 2 {
|
|
||||||
t.Error("list.size: ", list.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
server := list.GetServer(1)
|
|
||||||
if server.Destination().Port != 2 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
server = list.GetServer(1)
|
|
||||||
if server != nil {
|
|
||||||
t.Error("server: ", server)
|
|
||||||
}
|
|
||||||
|
|
||||||
server = list.GetServer(0)
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestServerPicker(t *testing.T) {
|
|
||||||
list := NewServerList()
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(1)), AlwaysValid()))
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(3)), BeforeTime(time.Now().Add(time.Second))))
|
|
||||||
|
|
||||||
picker := NewRoundRobinServerPicker(list)
|
|
||||||
server := picker.PickServer()
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 2 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 3 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +1,30 @@
|
|||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValidationStrategy interface {
|
|
||||||
IsValid() bool
|
|
||||||
Invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
type alwaysValidStrategy struct{}
|
|
||||||
|
|
||||||
func AlwaysValid() ValidationStrategy {
|
|
||||||
return alwaysValidStrategy{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (alwaysValidStrategy) IsValid() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (alwaysValidStrategy) Invalidate() {}
|
|
||||||
|
|
||||||
type timeoutValidStrategy struct {
|
|
||||||
until time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func BeforeTime(t time.Time) ValidationStrategy {
|
|
||||||
return &timeoutValidStrategy{
|
|
||||||
until: t,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *timeoutValidStrategy) IsValid() bool {
|
|
||||||
return s.until.After(time.Now())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *timeoutValidStrategy) Invalidate() {
|
|
||||||
s.until = time.Time{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerSpec struct {
|
type ServerSpec struct {
|
||||||
sync.RWMutex
|
Destination net.Destination
|
||||||
dest net.Destination
|
User *MemoryUser
|
||||||
users []*MemoryUser
|
|
||||||
valid ValidationStrategy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerSpec(dest net.Destination, valid ValidationStrategy, users ...*MemoryUser) *ServerSpec {
|
func NewServerSpec(dest net.Destination, user *MemoryUser) *ServerSpec {
|
||||||
return &ServerSpec{
|
return &ServerSpec{
|
||||||
dest: dest,
|
Destination: dest,
|
||||||
users: users,
|
User: user,
|
||||||
valid: valid,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerSpecFromPB(spec *ServerEndpoint) (*ServerSpec, error) {
|
func NewServerSpecFromPB(spec *ServerEndpoint) (*ServerSpec, error) {
|
||||||
dest := net.TCPDestination(spec.Address.AsAddress(), net.Port(spec.Port))
|
dest := net.TCPDestination(spec.Address.AsAddress(), net.Port(spec.Port))
|
||||||
mUsers := make([]*MemoryUser, len(spec.User))
|
var dUser *MemoryUser
|
||||||
for idx, u := range spec.User {
|
if spec.User != nil {
|
||||||
mUser, err := u.ToMemoryUser()
|
user, err := spec.User.ToMemoryUser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
mUsers[idx] = mUser
|
dUser = user
|
||||||
}
|
}
|
||||||
return NewServerSpec(dest, AlwaysValid(), mUsers...), nil
|
return NewServerSpec(dest, dUser), nil
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) Destination() net.Destination {
|
|
||||||
return s.dest
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) HasUser(user *MemoryUser) bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
for _, u := range s.users {
|
|
||||||
if u.Account.Equals(user.Account) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) AddUser(user *MemoryUser) {
|
|
||||||
if s.HasUser(user) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.users = append(s.users, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) PickUser() *MemoryUser {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
userCount := len(s.users)
|
|
||||||
switch userCount {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case 1:
|
|
||||||
return s.users[0]
|
|
||||||
default:
|
|
||||||
return s.users[dice.Roll(userCount)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) IsValid() bool {
|
|
||||||
return s.valid.IsValid()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) Invalidate() {
|
|
||||||
s.valid.Invalidate()
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ type ServerEndpoint struct {
|
|||||||
|
|
||||||
Address *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
Address *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||||
Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
|
Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
|
||||||
User []*User `protobuf:"bytes,3,rep,name=user,proto3" json:"user,omitempty"`
|
User *User `protobuf:"bytes,3,opt,name=user,proto3" json:"user,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ServerEndpoint) Reset() {
|
func (x *ServerEndpoint) Reset() {
|
||||||
@@ -75,7 +75,7 @@ func (x *ServerEndpoint) GetPort() uint32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ServerEndpoint) GetUser() []*User {
|
func (x *ServerEndpoint) GetUser() *User {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.User
|
return x.User
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ var file_common_protocol_server_spec_proto_rawDesc = []byte{
|
|||||||
0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72,
|
0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72,
|
||||||
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2e, 0x0a,
|
0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x2e, 0x0a,
|
||||||
0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72,
|
0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
||||||
0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x42, 0x5e, 0x0a,
|
0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x42, 0x5e, 0x0a,
|
||||||
0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||||
|
|||||||
@@ -12,5 +12,5 @@ import "common/protocol/user.proto";
|
|||||||
message ServerEndpoint {
|
message ServerEndpoint {
|
||||||
xray.common.net.IPOrDomain address = 1;
|
xray.common.net.IPOrDomain address = 1;
|
||||||
uint32 port = 2;
|
uint32 port = 2;
|
||||||
repeated xray.common.protocol.User user = 3;
|
xray.common.protocol.User user = 3;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
package protocol_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
. "github.com/xtls/xray-core/common/protocol"
|
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
|
||||||
"github.com/xtls/xray-core/proxy/vmess"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestAlwaysValidStrategy(t *testing.T) {
|
|
||||||
strategy := AlwaysValid()
|
|
||||||
if !strategy.IsValid() {
|
|
||||||
t.Error("strategy not valid")
|
|
||||||
}
|
|
||||||
strategy.Invalidate()
|
|
||||||
if !strategy.IsValid() {
|
|
||||||
t.Error("strategy not valid")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTimeoutValidStrategy(t *testing.T) {
|
|
||||||
strategy := BeforeTime(time.Now().Add(2 * time.Second))
|
|
||||||
if !strategy.IsValid() {
|
|
||||||
t.Error("strategy not valid")
|
|
||||||
}
|
|
||||||
time.Sleep(3 * time.Second)
|
|
||||||
if strategy.IsValid() {
|
|
||||||
t.Error("strategy is valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
strategy = BeforeTime(time.Now().Add(2 * time.Second))
|
|
||||||
strategy.Invalidate()
|
|
||||||
if strategy.IsValid() {
|
|
||||||
t.Error("strategy is valid")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestUserInServerSpec(t *testing.T) {
|
|
||||||
uuid1 := uuid.New()
|
|
||||||
uuid2 := uuid.New()
|
|
||||||
|
|
||||||
toAccount := func(a *vmess.Account) Account {
|
|
||||||
account, err := a.AsAccount()
|
|
||||||
common.Must(err)
|
|
||||||
return account
|
|
||||||
}
|
|
||||||
|
|
||||||
spec := NewServerSpec(net.Destination{}, AlwaysValid(), &MemoryUser{
|
|
||||||
Email: "test1@example.com",
|
|
||||||
Account: toAccount(&vmess.Account{Id: uuid1.String()}),
|
|
||||||
})
|
|
||||||
if spec.HasUser(&MemoryUser{
|
|
||||||
Email: "test1@example.com",
|
|
||||||
Account: toAccount(&vmess.Account{Id: uuid2.String()}),
|
|
||||||
}) {
|
|
||||||
t.Error("has user: ", uuid2)
|
|
||||||
}
|
|
||||||
|
|
||||||
spec.AddUser(&MemoryUser{Email: "test2@example.com"})
|
|
||||||
if !spec.HasUser(&MemoryUser{
|
|
||||||
Email: "test1@example.com",
|
|
||||||
Account: toAccount(&vmess.Account{Id: uuid1.String()}),
|
|
||||||
}) {
|
|
||||||
t.Error("not having user: ", uuid1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPickUser(t *testing.T) {
|
|
||||||
spec := NewServerSpec(net.Destination{}, AlwaysValid(), &MemoryUser{Email: "test1@example.com"}, &MemoryUser{Email: "test2@example.com"}, &MemoryUser{Email: "test3@example.com"})
|
|
||||||
user := spec.PickUser()
|
|
||||||
if !strings.HasSuffix(user.Email, "@example.com") {
|
|
||||||
t.Error("user: ", user.Email)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -17,13 +17,13 @@ const (
|
|||||||
inboundSessionKey ctx.SessionKey = 1
|
inboundSessionKey ctx.SessionKey = 1
|
||||||
outboundSessionKey ctx.SessionKey = 2
|
outboundSessionKey ctx.SessionKey = 2
|
||||||
contentSessionKey ctx.SessionKey = 3
|
contentSessionKey ctx.SessionKey = 3
|
||||||
muxPreferredSessionKey ctx.SessionKey = 4 // unused
|
isReverseMuxKey ctx.SessionKey = 4 // is reverse mux
|
||||||
sockoptSessionKey ctx.SessionKey = 5 // used by dokodemo to only receive sockopt.Mark
|
sockoptSessionKey ctx.SessionKey = 5 // used by dokodemo to only receive sockopt.Mark
|
||||||
trackedConnectionErrorKey ctx.SessionKey = 6 // used by observer to get outbound error
|
trackedConnectionErrorKey ctx.SessionKey = 6 // used by observer to get outbound error
|
||||||
dispatcherKey ctx.SessionKey = 7 // used by ss2022 inbounds to get dispatcher
|
dispatcherKey ctx.SessionKey = 7 // used by ss2022 inbounds to get dispatcher
|
||||||
timeoutOnlyKey ctx.SessionKey = 8 // mux context's child contexts to only cancel when its own traffic times out
|
timeoutOnlyKey ctx.SessionKey = 8 // mux context's child contexts to only cancel when its own traffic times out
|
||||||
allowedNetworkKey ctx.SessionKey = 9 // muxcool server control incoming request tcp/udp
|
allowedNetworkKey ctx.SessionKey = 9 // muxcool server control incoming request tcp/udp
|
||||||
handlerSessionKey ctx.SessionKey = 10 // outbound gets full handler
|
fullHandlerKey ctx.SessionKey = 10 // outbound gets full handler
|
||||||
mitmAlpn11Key ctx.SessionKey = 11 // used by TLS dialer
|
mitmAlpn11Key ctx.SessionKey = 11 // used by TLS dialer
|
||||||
mitmServerNameKey ctx.SessionKey = 12 // used by TLS dialer
|
mitmServerNameKey ctx.SessionKey = 12 // used by TLS dialer
|
||||||
)
|
)
|
||||||
@@ -75,25 +75,21 @@ func ContentFromContext(ctx context.Context) *Content {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextWithMuxPreferred returns a new context with the given bool
|
func ContextWithIsReverseMux(ctx context.Context, isReverseMux bool) context.Context {
|
||||||
func ContextWithMuxPreferred(ctx context.Context, forced bool) context.Context {
|
return context.WithValue(ctx, isReverseMuxKey, isReverseMux)
|
||||||
return context.WithValue(ctx, muxPreferredSessionKey, forced)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MuxPreferredFromContext returns value in this context, or false if not contained.
|
func IsReverseMuxFromContext(ctx context.Context) bool {
|
||||||
func MuxPreferredFromContext(ctx context.Context) bool {
|
if val, ok := ctx.Value(isReverseMuxKey).(bool); ok {
|
||||||
if val, ok := ctx.Value(muxPreferredSessionKey).(bool); ok {
|
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContextWithSockopt returns a new context with Socket configs included
|
|
||||||
func ContextWithSockopt(ctx context.Context, s *Sockopt) context.Context {
|
func ContextWithSockopt(ctx context.Context, s *Sockopt) context.Context {
|
||||||
return context.WithValue(ctx, sockoptSessionKey, s)
|
return context.WithValue(ctx, sockoptSessionKey, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SockoptFromContext returns Socket configs in this context, or nil if not contained.
|
|
||||||
func SockoptFromContext(ctx context.Context) *Sockopt {
|
func SockoptFromContext(ctx context.Context) *Sockopt {
|
||||||
if sockopt, ok := ctx.Value(sockoptSessionKey).(*Sockopt); ok {
|
if sockopt, ok := ctx.Value(sockoptSessionKey).(*Sockopt); ok {
|
||||||
return sockopt
|
return sockopt
|
||||||
@@ -164,12 +160,12 @@ func AllowedNetworkFromContext(ctx context.Context) net.Network {
|
|||||||
return net.Network_Unknown
|
return net.Network_Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
func ContextWithHandler(ctx context.Context, handler outbound.Handler) context.Context {
|
func ContextWithFullHandler(ctx context.Context, handler outbound.Handler) context.Context {
|
||||||
return context.WithValue(ctx, handlerSessionKey, handler)
|
return context.WithValue(ctx, fullHandlerKey, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandlerFromContext(ctx context.Context) outbound.Handler {
|
func FullHandlerFromContext(ctx context.Context) outbound.Handler {
|
||||||
if val, ok := ctx.Value(handlerSessionKey).(outbound.Handler); ok {
|
if val, ok := ctx.Value(fullHandlerKey).(outbound.Handler); ok {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
"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/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
)
|
)
|
||||||
@@ -33,8 +35,26 @@ func (w *PipeConnWrapper) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This Read implemented a timeout to avoid goroutine leak.
|
||||||
|
// as a temporarily solution
|
||||||
func (w *PipeConnWrapper) Read(b []byte) (n int, err error) {
|
func (w *PipeConnWrapper) Read(b []byte) (n int, err error) {
|
||||||
return w.R.Read(b)
|
type readResult struct {
|
||||||
|
n int
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
c := make(chan readResult, 1)
|
||||||
|
go func() {
|
||||||
|
n, err := w.R.Read(b)
|
||||||
|
c <- readResult{n: n, err: err}
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case result := <-c:
|
||||||
|
return result.n, result.err
|
||||||
|
case <-time.After(300 * time.Second):
|
||||||
|
common.Close(w.R)
|
||||||
|
common.Interrupt(w.R)
|
||||||
|
return 0, buf.ErrReadTimeout
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *PipeConnWrapper) Write(p []byte) (n int, err error) {
|
func (w *PipeConnWrapper) Write(p []byte) (n int, err error) {
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
Version_x byte = 25
|
Version_x byte = 25
|
||||||
Version_y byte = 9
|
Version_y byte = 10
|
||||||
Version_z byte = 11
|
Version_z byte = 15
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -63,17 +63,13 @@ func TestXrayClose(t *testing.T) {
|
|||||||
Outbound: []*OutboundHandlerConfig{
|
Outbound: []*OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(0),
|
||||||
Port: uint32(0),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"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/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/features"
|
"github.com/xtls/xray-core/features"
|
||||||
)
|
)
|
||||||
@@ -20,9 +19,6 @@ type Handler interface {
|
|||||||
ReceiverSettings() *serial.TypedMessage
|
ReceiverSettings() *serial.TypedMessage
|
||||||
// Returns the active proxy settings.
|
// Returns the active proxy settings.
|
||||||
ProxySettings() *serial.TypedMessage
|
ProxySettings() *serial.TypedMessage
|
||||||
|
|
||||||
// Deprecated: Do not use in new code.
|
|
||||||
GetRandomInboundProxy() (interface{}, net.Port, int)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manager is a feature that manages InboundHandlers.
|
// Manager is a feature that manages InboundHandlers.
|
||||||
|
|||||||
@@ -12,14 +12,19 @@ import (
|
|||||||
// ResolvableContext is an implementation of routing.Context, with domain resolving capability.
|
// ResolvableContext is an implementation of routing.Context, with domain resolving capability.
|
||||||
type ResolvableContext struct {
|
type ResolvableContext struct {
|
||||||
routing.Context
|
routing.Context
|
||||||
dnsClient dns.Client
|
dnsClient dns.Client
|
||||||
resolvedIPs []net.IP
|
cacheIPs []net.IP
|
||||||
|
hasError bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTargetIPs overrides original routing.Context's implementation.
|
// GetTargetIPs overrides original routing.Context's implementation.
|
||||||
func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
|
func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
|
||||||
if len(ctx.resolvedIPs) > 0 {
|
if len(ctx.cacheIPs) > 0 {
|
||||||
return ctx.resolvedIPs
|
return ctx.cacheIPs
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.hasError {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if domain := ctx.GetTargetDomain(); len(domain) != 0 {
|
if domain := ctx.GetTargetDomain(); len(domain) != 0 {
|
||||||
@@ -29,16 +34,18 @@ func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
|
|||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
})
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ctx.resolvedIPs = ips
|
ctx.cacheIPs = ips
|
||||||
return ips
|
return ips
|
||||||
}
|
}
|
||||||
errors.LogInfoInner(context.Background(), err, "resolve ip for ", domain)
|
errors.LogInfoInner(context.Background(), err, "resolve ip for ", domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ips := ctx.Context.GetTargetIPs(); len(ips) != 0 {
|
if ips := ctx.Context.GetTargetIPs(); len(ips) != 0 {
|
||||||
|
ctx.cacheIPs = ips
|
||||||
return ips
|
return ips
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.hasError = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
25
go.mod
25
go.mod
@@ -11,23 +11,23 @@ require (
|
|||||||
github.com/miekg/dns v1.1.68
|
github.com/miekg/dns v1.1.68
|
||||||
github.com/pelletier/go-toml v1.9.5
|
github.com/pelletier/go-toml v1.9.5
|
||||||
github.com/pires/go-proxyproto v0.8.1
|
github.com/pires/go-proxyproto v0.8.1
|
||||||
github.com/quic-go/quic-go v0.54.0
|
github.com/quic-go/quic-go v0.55.0
|
||||||
github.com/refraction-networking/utls v1.8.0
|
github.com/refraction-networking/utls v1.8.1
|
||||||
github.com/sagernet/sing v0.5.1
|
github.com/sagernet/sing v0.5.1
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771
|
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||||
github.com/vishvananda/netlink v1.3.1
|
github.com/vishvananda/netlink v1.3.1
|
||||||
github.com/xtls/reality v0.0.0-20250904214705-431b6ff8c67c
|
github.com/xtls/reality v0.0.0-20251014195629-e4eec4520535
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/crypto v0.42.0
|
golang.org/x/crypto v0.43.0
|
||||||
golang.org/x/net v0.44.0
|
golang.org/x/net v0.46.0
|
||||||
golang.org/x/sync v0.17.0
|
golang.org/x/sync v0.17.0
|
||||||
golang.org/x/sys v0.36.0
|
golang.org/x/sys v0.37.0
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||||
google.golang.org/grpc v1.75.1
|
google.golang.org/grpc v1.76.0
|
||||||
google.golang.org/protobuf v1.36.9
|
google.golang.org/protobuf v1.36.10
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
||||||
h12.io/socks v1.0.3
|
h12.io/socks v1.0.3
|
||||||
lukechampine.com/blake3 v1.4.1
|
lukechampine.com/blake3 v1.4.1
|
||||||
@@ -46,13 +46,12 @@ require (
|
|||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
github.com/vishvananda/netns v0.0.5 // indirect
|
github.com/vishvananda/netns v0.0.5 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
golang.org/x/mod v0.28.0 // indirect
|
||||||
golang.org/x/mod v0.27.0 // indirect
|
golang.org/x/text v0.30.0 // indirect
|
||||||
golang.org/x/text v0.29.0 // indirect
|
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.36.0 // indirect
|
golang.org/x/tools v0.37.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
52
go.sum
52
go.sum
@@ -51,10 +51,10 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
github.com/quic-go/quic-go v0.55.0 h1:zccPQIqYCXDt5NmcEabyYvOnomjs8Tlwl7tISjJh9Mk=
|
||||||
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
github.com/quic-go/quic-go v0.55.0/go.mod h1:DR51ilwU1uE164KuWXhinFcKWGlEjzys2l8zUl5Ss1U=
|
||||||
github.com/refraction-networking/utls v1.8.0 h1:L38krhiTAyj9EeiQQa2sg+hYb4qwLCqdMcpZrRfbONE=
|
github.com/refraction-networking/utls v1.8.1 h1:yNY1kapmQU8JeM1sSw2H2asfTIwWxIkrMJI0pRUOCAo=
|
||||||
github.com/refraction-networking/utls v1.8.0/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
|
github.com/refraction-networking/utls v1.8.1/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
@@ -75,8 +75,8 @@ github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW
|
|||||||
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
|
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
|
||||||
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
||||||
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/xtls/reality v0.0.0-20250904214705-431b6ff8c67c h1:LHLhQY3mKXSpTcQAkjFR4/6ar3rXjQryNeM7khK3AHU=
|
github.com/xtls/reality v0.0.0-20251014195629-e4eec4520535 h1:nwobseOLLRtdbP6z7Z2aVI97u8ZptTgD1ofovhAKmeU=
|
||||||
github.com/xtls/reality v0.0.0-20250904214705-431b6ff8c67c/go.mod h1:XxvnCCgBee4WWE0bc4E+a7wbk8gkJ/rS0vNVNtC5qp0=
|
github.com/xtls/reality v0.0.0-20251014195629-e4eec4520535/go.mod h1:vbHCV/3VWUvy1oKvTxxWJRPEWSeR1sYgQHIh6u/JiZQ=
|
||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
@@ -90,22 +90,22 @@ go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFh
|
|||||||
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
||||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
||||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
@@ -117,21 +117,21 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -141,12 +141,12 @@ golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uI
|
|||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b h1:zPKJod4w6F1+nRGDI9ubnXYhU9NSWoFAijkHkUXeTK8=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
|
google.golang.org/grpc v1.76.0 h1:UnVkv1+uMLYXoIz6o7chp59WfQUYA2ex/BXQ9rHZu7A=
|
||||||
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
google.golang.org/grpc v1.76.0/go.mod h1:Ju12QI8M6iQJtbcsV+awF5a4hfJMLi4X0JLo94ULZ6c=
|
||||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
|||||||
@@ -16,19 +16,21 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type NameServerConfig struct {
|
type NameServerConfig struct {
|
||||||
Address *Address `json:"address"`
|
Address *Address `json:"address"`
|
||||||
ClientIP *Address `json:"clientIp"`
|
ClientIP *Address `json:"clientIp"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
SkipFallback bool `json:"skipFallback"`
|
SkipFallback bool `json:"skipFallback"`
|
||||||
Domains []string `json:"domains"`
|
Domains []string `json:"domains"`
|
||||||
ExpectedIPs StringList `json:"expectedIPs"`
|
ExpectedIPs StringList `json:"expectedIPs"`
|
||||||
ExpectIPs StringList `json:"expectIPs"`
|
ExpectIPs StringList `json:"expectIPs"`
|
||||||
QueryStrategy string `json:"queryStrategy"`
|
QueryStrategy string `json:"queryStrategy"`
|
||||||
Tag string `json:"tag"`
|
Tag string `json:"tag"`
|
||||||
TimeoutMs uint64 `json:"timeoutMs"`
|
TimeoutMs uint64 `json:"timeoutMs"`
|
||||||
DisableCache bool `json:"disableCache"`
|
DisableCache bool `json:"disableCache"`
|
||||||
FinalQuery bool `json:"finalQuery"`
|
ServeStale bool `json:"serveStale"`
|
||||||
UnexpectedIPs StringList `json:"unexpectedIPs"`
|
ServeExpiredTTL uint32 `json:"serveExpiredTTL"`
|
||||||
|
FinalQuery bool `json:"finalQuery"`
|
||||||
|
UnexpectedIPs StringList `json:"unexpectedIPs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
@@ -40,19 +42,21 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var advanced struct {
|
var advanced struct {
|
||||||
Address *Address `json:"address"`
|
Address *Address `json:"address"`
|
||||||
ClientIP *Address `json:"clientIp"`
|
ClientIP *Address `json:"clientIp"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
SkipFallback bool `json:"skipFallback"`
|
SkipFallback bool `json:"skipFallback"`
|
||||||
Domains []string `json:"domains"`
|
Domains []string `json:"domains"`
|
||||||
ExpectedIPs StringList `json:"expectedIPs"`
|
ExpectedIPs StringList `json:"expectedIPs"`
|
||||||
ExpectIPs StringList `json:"expectIPs"`
|
ExpectIPs StringList `json:"expectIPs"`
|
||||||
QueryStrategy string `json:"queryStrategy"`
|
QueryStrategy string `json:"queryStrategy"`
|
||||||
Tag string `json:"tag"`
|
Tag string `json:"tag"`
|
||||||
TimeoutMs uint64 `json:"timeoutMs"`
|
TimeoutMs uint64 `json:"timeoutMs"`
|
||||||
DisableCache bool `json:"disableCache"`
|
DisableCache bool `json:"disableCache"`
|
||||||
FinalQuery bool `json:"finalQuery"`
|
ServeStale bool `json:"serveStale"`
|
||||||
UnexpectedIPs StringList `json:"unexpectedIPs"`
|
ServeExpiredTTL uint32 `json:"serveExpiredTTL"`
|
||||||
|
FinalQuery bool `json:"finalQuery"`
|
||||||
|
UnexpectedIPs StringList `json:"unexpectedIPs"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(data, &advanced); err == nil {
|
if err := json.Unmarshal(data, &advanced); err == nil {
|
||||||
c.Address = advanced.Address
|
c.Address = advanced.Address
|
||||||
@@ -66,6 +70,8 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
|||||||
c.Tag = advanced.Tag
|
c.Tag = advanced.Tag
|
||||||
c.TimeoutMs = advanced.TimeoutMs
|
c.TimeoutMs = advanced.TimeoutMs
|
||||||
c.DisableCache = advanced.DisableCache
|
c.DisableCache = advanced.DisableCache
|
||||||
|
c.ServeStale = advanced.ServeStale
|
||||||
|
c.ServeExpiredTTL = advanced.ServeExpiredTTL
|
||||||
c.FinalQuery = advanced.FinalQuery
|
c.FinalQuery = advanced.FinalQuery
|
||||||
c.UnexpectedIPs = advanced.UnexpectedIPs
|
c.UnexpectedIPs = advanced.UnexpectedIPs
|
||||||
return nil
|
return nil
|
||||||
@@ -173,6 +179,8 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
|
|||||||
Tag: c.Tag,
|
Tag: c.Tag,
|
||||||
TimeoutMs: c.TimeoutMs,
|
TimeoutMs: c.TimeoutMs,
|
||||||
DisableCache: c.DisableCache,
|
DisableCache: c.DisableCache,
|
||||||
|
ServeStale: c.ServeStale,
|
||||||
|
ServeExpiredTTL: &c.ServeExpiredTTL,
|
||||||
FinalQuery: c.FinalQuery,
|
FinalQuery: c.FinalQuery,
|
||||||
UnexpectedGeoip: unexpectedGeoipList,
|
UnexpectedGeoip: unexpectedGeoipList,
|
||||||
ActUnprior: actUnprior,
|
ActUnprior: actUnprior,
|
||||||
@@ -194,6 +202,8 @@ type DNSConfig struct {
|
|||||||
Tag string `json:"tag"`
|
Tag string `json:"tag"`
|
||||||
QueryStrategy string `json:"queryStrategy"`
|
QueryStrategy string `json:"queryStrategy"`
|
||||||
DisableCache bool `json:"disableCache"`
|
DisableCache bool `json:"disableCache"`
|
||||||
|
ServeStale bool `json:"serveStale"`
|
||||||
|
ServeExpiredTTL uint32 `json:"serveExpiredTTL"`
|
||||||
DisableFallback bool `json:"disableFallback"`
|
DisableFallback bool `json:"disableFallback"`
|
||||||
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
|
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
|
||||||
UseSystemHosts bool `json:"useSystemHosts"`
|
UseSystemHosts bool `json:"useSystemHosts"`
|
||||||
@@ -391,6 +401,8 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
|
|||||||
config := &dns.Config{
|
config := &dns.Config{
|
||||||
Tag: c.Tag,
|
Tag: c.Tag,
|
||||||
DisableCache: c.DisableCache,
|
DisableCache: c.DisableCache,
|
||||||
|
ServeStale: c.ServeStale,
|
||||||
|
ServeExpiredTTL: c.ServeExpiredTTL,
|
||||||
DisableFallback: c.DisableFallback,
|
DisableFallback: c.DisableFallback,
|
||||||
DisableFallbackIfMatch: c.DisableFallbackIfMatch,
|
DisableFallbackIfMatch: c.DisableFallbackIfMatch,
|
||||||
QueryStrategy: resolveQueryStrategy(c.QueryStrategy),
|
QueryStrategy: resolveQueryStrategy(c.QueryStrategy),
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ func TestDNSConfigParsing(t *testing.T) {
|
|||||||
return config.Build()
|
return config.Build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
expectedServeExpiredTTL := uint32(172800)
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
Input: `{
|
Input: `{
|
||||||
@@ -28,7 +28,9 @@ func TestDNSConfigParsing(t *testing.T) {
|
|||||||
"address": "8.8.8.8",
|
"address": "8.8.8.8",
|
||||||
"port": 5353,
|
"port": 5353,
|
||||||
"skipFallback": true,
|
"skipFallback": true,
|
||||||
"domains": ["domain:example.com"]
|
"domains": ["domain:example.com"],
|
||||||
|
"serveStale": true,
|
||||||
|
"serveExpiredTTL": 172800
|
||||||
}],
|
}],
|
||||||
"hosts": {
|
"hosts": {
|
||||||
"domain:example.com": "google.com",
|
"domain:example.com": "google.com",
|
||||||
@@ -40,6 +42,8 @@ func TestDNSConfigParsing(t *testing.T) {
|
|||||||
"clientIp": "10.0.0.1",
|
"clientIp": "10.0.0.1",
|
||||||
"queryStrategy": "UseIPv4",
|
"queryStrategy": "UseIPv4",
|
||||||
"disableCache": true,
|
"disableCache": true,
|
||||||
|
"serveStale": false,
|
||||||
|
"serveExpiredTTL": 86400,
|
||||||
"disableFallback": true
|
"disableFallback": true
|
||||||
}`,
|
}`,
|
||||||
Parser: parserCreator(),
|
Parser: parserCreator(),
|
||||||
@@ -68,6 +72,8 @@ func TestDNSConfigParsing(t *testing.T) {
|
|||||||
Size: 1,
|
Size: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ServeStale: true,
|
||||||
|
ServeExpiredTTL: &expectedServeExpiredTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StaticHosts: []*dns.Config_HostMapping{
|
StaticHosts: []*dns.Config_HostMapping{
|
||||||
@@ -100,6 +106,8 @@ func TestDNSConfigParsing(t *testing.T) {
|
|||||||
ClientIp: []byte{10, 0, 0, 1},
|
ClientIp: []byte{10, 0, 0, 1},
|
||||||
QueryStrategy: dns.QueryStrategy_USE_IP4,
|
QueryStrategy: dns.QueryStrategy_USE_IP4,
|
||||||
DisableCache: true,
|
DisableCache: true,
|
||||||
|
ServeStale: false,
|
||||||
|
ServeExpiredTTL: 86400,
|
||||||
DisableFallback: true,
|
DisableFallback: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -68,12 +68,19 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) {
|
|||||||
{
|
{
|
||||||
Address: v.Address,
|
Address: v.Address,
|
||||||
Port: v.Port,
|
Port: v.Port,
|
||||||
Users: []json.RawMessage{{}},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if len(v.Username) > 0 {
|
||||||
|
v.Servers[0].Users = []json.RawMessage{{}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
config.Server = make([]*protocol.ServerEndpoint, len(v.Servers))
|
if len(v.Servers) != 1 {
|
||||||
for idx, serverConfig := range v.Servers {
|
return nil, errors.New(`HTTP settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple HTTP outbounds and routing balancer instead`)
|
||||||
|
}
|
||||||
|
for _, serverConfig := range v.Servers {
|
||||||
|
if len(serverConfig.Users) > 1 {
|
||||||
|
return nil, errors.New(`HTTP servers: "users" should have one member at most. Multiple members in "users" should use multiple HTTP outbounds and routing balancer instead`)
|
||||||
|
}
|
||||||
server := &protocol.ServerEndpoint{
|
server := &protocol.ServerEndpoint{
|
||||||
Address: serverConfig.Address.Build(),
|
Address: serverConfig.Address.Build(),
|
||||||
Port: uint32(serverConfig.Port),
|
Port: uint32(serverConfig.Port),
|
||||||
@@ -98,9 +105,11 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
user.Account = serial.ToTypedMessage(account.Build())
|
user.Account = serial.ToTypedMessage(account.Build())
|
||||||
server.User = append(server.User, user)
|
server.User = user
|
||||||
|
break
|
||||||
}
|
}
|
||||||
config.Server[idx] = server
|
config.Server = server
|
||||||
|
break
|
||||||
}
|
}
|
||||||
config.Header = make([]*http.Header, 0, 32)
|
config.Header = make([]*http.Header, 0, 32)
|
||||||
for key, value := range v.Headers {
|
for key, value := range v.Headers {
|
||||||
|
|||||||
@@ -172,16 +172,16 @@ type ShadowsocksServerTarget struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ShadowsocksClientConfig struct {
|
type ShadowsocksClientConfig struct {
|
||||||
Address *Address `json:"address"`
|
Address *Address `json:"address"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
Level byte `json:"level"`
|
Level byte `json:"level"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Cipher string `json:"method"`
|
Cipher string `json:"method"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
IVCheck bool `json:"ivCheck"`
|
IVCheck bool `json:"ivCheck"`
|
||||||
UoT bool `json:"uot"`
|
UoT bool `json:"uot"`
|
||||||
UoTVersion int `json:"uotVersion"`
|
UoTVersion int `json:"uotVersion"`
|
||||||
Servers []*ShadowsocksServerTarget `json:"servers"`
|
Servers []*ShadowsocksServerTarget `json:"servers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
|
func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
|
||||||
@@ -200,8 +200,8 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(v.Servers) == 0 {
|
if len(v.Servers) != 1 {
|
||||||
return nil, errors.New("0 Shadowsocks server configured.")
|
return nil, errors.New(`Shadowsocks settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple Shadowsocks outbounds and routing balancer instead`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(v.Servers) == 1 {
|
if len(v.Servers) == 1 {
|
||||||
@@ -229,8 +229,7 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
config := new(shadowsocks.ClientConfig)
|
config := new(shadowsocks.ClientConfig)
|
||||||
serverSpecs := make([]*protocol.ServerEndpoint, len(v.Servers))
|
for _, server := range v.Servers {
|
||||||
for idx, server := range v.Servers {
|
|
||||||
if C.Contains(shadowaead_2022.List, server.Cipher) {
|
if C.Contains(shadowaead_2022.List, server.Cipher) {
|
||||||
return nil, errors.New("Shadowsocks 2022 accept no multi servers")
|
return nil, errors.New("Shadowsocks 2022 accept no multi servers")
|
||||||
}
|
}
|
||||||
@@ -256,19 +255,16 @@ func (v *ShadowsocksClientConfig) Build() (proto.Message, error) {
|
|||||||
ss := &protocol.ServerEndpoint{
|
ss := &protocol.ServerEndpoint{
|
||||||
Address: server.Address.Build(),
|
Address: server.Address.Build(),
|
||||||
Port: uint32(server.Port),
|
Port: uint32(server.Port),
|
||||||
User: []*protocol.User{
|
User: &protocol.User{
|
||||||
{
|
Level: uint32(server.Level),
|
||||||
Level: uint32(server.Level),
|
Email: server.Email,
|
||||||
Email: server.Email,
|
Account: serial.ToTypedMessage(account),
|
||||||
Account: serial.ToTypedMessage(account),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
serverSpecs[idx] = ss
|
config.Server = ss
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Server = serverSpecs
|
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,12 +86,19 @@ func (v *SocksClientConfig) Build() (proto.Message, error) {
|
|||||||
{
|
{
|
||||||
Address: v.Address,
|
Address: v.Address,
|
||||||
Port: v.Port,
|
Port: v.Port,
|
||||||
Users: []json.RawMessage{{}},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
if len(v.Username) > 0 {
|
||||||
|
v.Servers[0].Users = []json.RawMessage{{}}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
config.Server = make([]*protocol.ServerEndpoint, len(v.Servers))
|
if len(v.Servers) != 1 {
|
||||||
for idx, serverConfig := range v.Servers {
|
return nil, errors.New(`SOCKS settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple SOCKS outbounds and routing balancer instead`)
|
||||||
|
}
|
||||||
|
for _, serverConfig := range v.Servers {
|
||||||
|
if len(serverConfig.Users) > 1 {
|
||||||
|
return nil, errors.New(`SOCKS servers: "users" should have one member at most. Multiple members in "users" should use multiple SOCKS outbounds and routing balancer instead`)
|
||||||
|
}
|
||||||
server := &protocol.ServerEndpoint{
|
server := &protocol.ServerEndpoint{
|
||||||
Address: serverConfig.Address.Build(),
|
Address: serverConfig.Address.Build(),
|
||||||
Port: uint32(serverConfig.Port),
|
Port: uint32(serverConfig.Port),
|
||||||
@@ -116,9 +123,11 @@ func (v *SocksClientConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
user.Account = serial.ToTypedMessage(account.Build())
|
user.Account = serial.ToTypedMessage(account.Build())
|
||||||
server.User = append(server.User, user)
|
server.User = user
|
||||||
|
break
|
||||||
}
|
}
|
||||||
config.Server[idx] = server
|
config.Server = server
|
||||||
|
break
|
||||||
}
|
}
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,24 +65,20 @@ func TestSocksOutboundConfig(t *testing.T) {
|
|||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &socks.ClientConfig{
|
Output: &socks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: &net.IPOrDomain{
|
||||||
Address: &net.IPOrDomain{
|
Address: &net.IPOrDomain_Ip{
|
||||||
Address: &net.IPOrDomain_Ip{
|
Ip: []byte{127, 0, 0, 1},
|
||||||
Ip: []byte{127, 0, 0, 1},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Port: 1234,
|
|
||||||
User: []*protocol.User{
|
|
||||||
{
|
|
||||||
Email: "test@email.com",
|
|
||||||
Account: serial.ToTypedMessage(&socks.Account{
|
|
||||||
Username: "test user",
|
|
||||||
Password: "test pass",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Port: 1234,
|
||||||
|
User: &protocol.User{
|
||||||
|
Email: "test@email.com",
|
||||||
|
Account: serial.ToTypedMessage(&socks.Account{
|
||||||
|
Username: "test user",
|
||||||
|
Password: "test pass",
|
||||||
|
}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -96,24 +92,20 @@ func TestSocksOutboundConfig(t *testing.T) {
|
|||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &socks.ClientConfig{
|
Output: &socks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: &net.IPOrDomain{
|
||||||
Address: &net.IPOrDomain{
|
Address: &net.IPOrDomain_Ip{
|
||||||
Address: &net.IPOrDomain_Ip{
|
Ip: []byte{127, 0, 0, 1},
|
||||||
Ip: []byte{127, 0, 0, 1},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Port: 1234,
|
|
||||||
User: []*protocol.User{
|
|
||||||
{
|
|
||||||
Email: "test@email.com",
|
|
||||||
Account: serial.ToTypedMessage(&socks.Account{
|
|
||||||
Username: "test user",
|
|
||||||
Password: "test pass",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Port: 1234,
|
||||||
|
User: &protocol.User{
|
||||||
|
Email: "test@email.com",
|
||||||
|
Account: serial.ToTypedMessage(&socks.Account{
|
||||||
|
Username: "test user",
|
||||||
|
Password: "test pass",
|
||||||
|
}),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -289,8 +289,8 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
|||||||
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
|
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
|
||||||
}
|
}
|
||||||
if c.Xmux == (XmuxConfig{}) {
|
if c.Xmux == (XmuxConfig{}) {
|
||||||
c.Xmux.MaxConcurrency.From = 16
|
c.Xmux.MaxConcurrency.From = 1
|
||||||
c.Xmux.MaxConcurrency.To = 32
|
c.Xmux.MaxConcurrency.To = 1
|
||||||
c.Xmux.HMaxRequestTimes.From = 600
|
c.Xmux.HMaxRequestTimes.From = 600
|
||||||
c.Xmux.HMaxRequestTimes.To = 900
|
c.Xmux.HMaxRequestTimes.To = 900
|
||||||
c.Xmux.HMaxReusableSecs.From = 1800
|
c.Xmux.HMaxReusableSecs.From = 1800
|
||||||
|
|||||||
@@ -28,13 +28,13 @@ type TrojanServerTarget struct {
|
|||||||
|
|
||||||
// TrojanClientConfig is configuration of trojan servers
|
// TrojanClientConfig is configuration of trojan servers
|
||||||
type TrojanClientConfig struct {
|
type TrojanClientConfig struct {
|
||||||
Address *Address `json:"address"`
|
Address *Address `json:"address"`
|
||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
Level byte `json:"level"`
|
Level byte `json:"level"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Flow string `json:"flow"`
|
Flow string `json:"flow"`
|
||||||
Servers []*TrojanServerTarget `json:"servers"`
|
Servers []*TrojanServerTarget `json:"servers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable
|
// Build implements Buildable
|
||||||
@@ -51,15 +51,13 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(c.Servers) == 0 {
|
if len(c.Servers) != 1 {
|
||||||
return nil, errors.New("0 Trojan server configured.")
|
return nil, errors.New(`Trojan settings: "servers" should have one and only one member. Multiple endpoints in "servers" should use multiple Trojan outbounds and routing balancer instead`)
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &trojan.ClientConfig{
|
config := &trojan.ClientConfig{}
|
||||||
Server: make([]*protocol.ServerEndpoint, len(c.Servers)),
|
|
||||||
}
|
|
||||||
|
|
||||||
for idx, rec := range c.Servers {
|
for _, rec := range c.Servers {
|
||||||
if rec.Address == nil {
|
if rec.Address == nil {
|
||||||
return nil, errors.New("Trojan server address is not set.")
|
return nil, errors.New("Trojan server address is not set.")
|
||||||
}
|
}
|
||||||
@@ -73,19 +71,19 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
|
|||||||
return nil, errors.PrintRemovedFeatureError(`Flow for Trojan`, ``)
|
return nil, errors.PrintRemovedFeatureError(`Flow for Trojan`, ``)
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Server[idx] = &protocol.ServerEndpoint{
|
config.Server = &protocol.ServerEndpoint{
|
||||||
Address: rec.Address.Build(),
|
Address: rec.Address.Build(),
|
||||||
Port: uint32(rec.Port),
|
Port: uint32(rec.Port),
|
||||||
User: []*protocol.User{
|
User: &protocol.User{
|
||||||
{
|
Level: uint32(rec.Level),
|
||||||
Level: uint32(rec.Level),
|
Email: rec.Email,
|
||||||
Email: rec.Email,
|
Account: serial.ToTypedMessage(&trojan.Account{
|
||||||
Account: serial.ToTypedMessage(&trojan.Account{
|
Password: rec.Password,
|
||||||
Password: rec.Password,
|
}),
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
|
|||||||
@@ -228,22 +228,20 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(c.Vnext) != 1 {
|
if len(c.Vnext) != 1 {
|
||||||
return nil, errors.New(`VLESS settings: "vnext" should have one and only one member`)
|
return nil, errors.New(`VLESS settings: "vnext" should have one and only one member. Multiple endpoints in "vnext" should use multiple VLESS outbounds and routing balancer instead`)
|
||||||
}
|
}
|
||||||
config.Vnext = make([]*protocol.ServerEndpoint, len(c.Vnext))
|
for _, rec := range c.Vnext {
|
||||||
for idx, rec := range c.Vnext {
|
|
||||||
if rec.Address == nil {
|
if rec.Address == nil {
|
||||||
return nil, errors.New(`VLESS vnext: "address" is not set`)
|
return nil, errors.New(`VLESS vnext: "address" is not set`)
|
||||||
}
|
}
|
||||||
if len(rec.Users) != 1 {
|
if len(rec.Users) != 1 {
|
||||||
return nil, errors.New(`VLESS vnext: "users" should have one and only one member`)
|
return nil, errors.New(`VLESS vnext: "users" should have one and only one member. Multiple members in "users" should use multiple VLESS outbounds and routing balancer instead`)
|
||||||
}
|
}
|
||||||
spec := &protocol.ServerEndpoint{
|
spec := &protocol.ServerEndpoint{
|
||||||
Address: rec.Address.Build(),
|
Address: rec.Address.Build(),
|
||||||
Port: uint32(rec.Port),
|
Port: uint32(rec.Port),
|
||||||
User: make([]*protocol.User, len(rec.Users)),
|
|
||||||
}
|
}
|
||||||
for idx, rawUser := range rec.Users {
|
for _, rawUser := range rec.Users {
|
||||||
user := new(protocol.User)
|
user := new(protocol.User)
|
||||||
if c.Address != nil {
|
if c.Address != nil {
|
||||||
user.Level = c.Level
|
user.Level = c.Level
|
||||||
@@ -327,9 +325,11 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
user.Account = serial.ToTypedMessage(account)
|
user.Account = serial.ToTypedMessage(account)
|
||||||
spec.User[idx] = user
|
spec.User = user
|
||||||
|
break
|
||||||
}
|
}
|
||||||
config.Vnext[idx] = spec
|
config.Vnext = spec
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
|
|||||||
@@ -35,25 +35,21 @@ func TestVLessOutbound(t *testing.T) {
|
|||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &outbound.Config{
|
Output: &outbound.Config{
|
||||||
Vnext: []*protocol.ServerEndpoint{
|
Vnext: &protocol.ServerEndpoint{
|
||||||
{
|
Address: &net.IPOrDomain{
|
||||||
Address: &net.IPOrDomain{
|
Address: &net.IPOrDomain_Domain{
|
||||||
Address: &net.IPOrDomain_Domain{
|
Domain: "example.com",
|
||||||
Domain: "example.com",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Port: 443,
|
|
||||||
User: []*protocol.User{
|
|
||||||
{
|
|
||||||
Account: serial.ToTypedMessage(&vless.Account{
|
|
||||||
Id: "27848739-7e62-4138-9fd3-098a63964b6b",
|
|
||||||
Flow: "xtls-rprx-vision-udp443",
|
|
||||||
Encryption: "none",
|
|
||||||
}),
|
|
||||||
Level: 0,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Port: 443,
|
||||||
|
User: &protocol.User{
|
||||||
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
|
Id: "27848739-7e62-4138-9fd3-098a63964b6b",
|
||||||
|
Flow: "xtls-rprx-vision-udp443",
|
||||||
|
Encryption: "none",
|
||||||
|
}),
|
||||||
|
Level: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -68,25 +64,21 @@ func TestVLessOutbound(t *testing.T) {
|
|||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &outbound.Config{
|
Output: &outbound.Config{
|
||||||
Vnext: []*protocol.ServerEndpoint{
|
Vnext: &protocol.ServerEndpoint{
|
||||||
{
|
Address: &net.IPOrDomain{
|
||||||
Address: &net.IPOrDomain{
|
Address: &net.IPOrDomain_Domain{
|
||||||
Address: &net.IPOrDomain_Domain{
|
Domain: "example.com",
|
||||||
Domain: "example.com",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Port: 443,
|
|
||||||
User: []*protocol.User{
|
|
||||||
{
|
|
||||||
Account: serial.ToTypedMessage(&vless.Account{
|
|
||||||
Id: "27848739-7e62-4138-9fd3-098a63964b6b",
|
|
||||||
Flow: "xtls-rprx-vision-udp443",
|
|
||||||
Encryption: "none",
|
|
||||||
}),
|
|
||||||
Level: 0,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Port: 443,
|
||||||
|
User: &protocol.User{
|
||||||
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
|
Id: "27848739-7e62-4138-9fd3-098a63964b6b",
|
||||||
|
Flow: "xtls-rprx-vision-udp443",
|
||||||
|
Encryption: "none",
|
||||||
|
}),
|
||||||
|
Level: 0,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -46,17 +46,6 @@ func (a *VMessAccount) Build() *vmess.Account {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type VMessDetourConfig struct {
|
|
||||||
ToTag string `json:"to"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build implements Buildable
|
|
||||||
func (c *VMessDetourConfig) Build() *inbound.DetourConfig {
|
|
||||||
return &inbound.DetourConfig{
|
|
||||||
To: c.ToTag,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type VMessDefaultConfig struct {
|
type VMessDefaultConfig struct {
|
||||||
Level byte `json:"level"`
|
Level byte `json:"level"`
|
||||||
}
|
}
|
||||||
@@ -71,7 +60,6 @@ func (c *VMessDefaultConfig) Build() *inbound.DefaultConfig {
|
|||||||
type VMessInboundConfig struct {
|
type VMessInboundConfig struct {
|
||||||
Users []json.RawMessage `json:"clients"`
|
Users []json.RawMessage `json:"clients"`
|
||||||
Defaults *VMessDefaultConfig `json:"default"`
|
Defaults *VMessDefaultConfig `json:"default"`
|
||||||
DetourConfig *VMessDetourConfig `json:"detour"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable
|
// Build implements Buildable
|
||||||
@@ -82,10 +70,6 @@ func (c *VMessInboundConfig) Build() (proto.Message, error) {
|
|||||||
config.Default = c.Defaults.Build()
|
config.Default = c.Defaults.Build()
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.DetourConfig != nil {
|
|
||||||
config.Detour = c.DetourConfig.Build()
|
|
||||||
}
|
|
||||||
|
|
||||||
config.User = make([]*protocol.User, len(c.Users))
|
config.User = make([]*protocol.User, len(c.Users))
|
||||||
for idx, rawData := range c.Users {
|
for idx, rawData := range c.Users {
|
||||||
user := new(protocol.User)
|
user := new(protocol.User)
|
||||||
@@ -139,16 +123,15 @@ func (c *VMessOutboundConfig) Build() (proto.Message, error) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(c.Receivers) == 0 {
|
if len(c.Receivers) != 1 {
|
||||||
return nil, errors.New("0 VMess receiver configured")
|
return nil, errors.New(`VMess settings: "vnext" should have one and only one member. Multiple endpoints in "vnext" should use multiple VMess outbounds and routing balancer instead`)
|
||||||
}
|
}
|
||||||
serverSpecs := make([]*protocol.ServerEndpoint, len(c.Receivers))
|
for _, rec := range c.Receivers {
|
||||||
for idx, rec := range c.Receivers {
|
if len(rec.Users) != 1 {
|
||||||
if len(rec.Users) == 0 {
|
return nil, errors.New(`VMess vnext: "users" should have one and only one member. Multiple members in "users" should use multiple VMess outbounds and routing balancer instead`)
|
||||||
return nil, errors.New("0 user configured for VMess outbound")
|
|
||||||
}
|
}
|
||||||
if rec.Address == nil {
|
if rec.Address == nil {
|
||||||
return nil, errors.New("address is not set in VMess outbound config")
|
return nil, errors.New(`VMess vnext: "address" is not set`)
|
||||||
}
|
}
|
||||||
spec := &protocol.ServerEndpoint{
|
spec := &protocol.ServerEndpoint{
|
||||||
Address: rec.Address.Build(),
|
Address: rec.Address.Build(),
|
||||||
@@ -182,10 +165,11 @@ func (c *VMessOutboundConfig) Build() (proto.Message, error) {
|
|||||||
account.ID = u.String()
|
account.ID = u.String()
|
||||||
|
|
||||||
user.Account = serial.ToTypedMessage(account.Build())
|
user.Account = serial.ToTypedMessage(account.Build())
|
||||||
spec.User = append(spec.User, user)
|
spec.User = user
|
||||||
|
break
|
||||||
}
|
}
|
||||||
serverSpecs[idx] = spec
|
config.Receiver = spec
|
||||||
|
break
|
||||||
}
|
}
|
||||||
config.Receiver = serverSpecs
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,26 +34,22 @@ func TestVMessOutbound(t *testing.T) {
|
|||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &outbound.Config{
|
Output: &outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: &net.IPOrDomain{
|
||||||
Address: &net.IPOrDomain{
|
Address: &net.IPOrDomain_Ip{
|
||||||
Address: &net.IPOrDomain_Ip{
|
Ip: []byte{127, 0, 0, 1},
|
||||||
Ip: []byte{127, 0, 0, 1},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Port: 80,
|
},
|
||||||
User: []*protocol.User{
|
Port: 80,
|
||||||
{
|
User: &protocol.User{
|
||||||
Email: "love@example.com",
|
Email: "love@example.com",
|
||||||
Level: 255,
|
Level: 255,
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019",
|
Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019",
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Type: protocol.SecurityType_AUTO,
|
Type: protocol.SecurityType_AUTO,
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -68,26 +64,22 @@ func TestVMessOutbound(t *testing.T) {
|
|||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &outbound.Config{
|
Output: &outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: &net.IPOrDomain{
|
||||||
Address: &net.IPOrDomain{
|
Address: &net.IPOrDomain_Ip{
|
||||||
Address: &net.IPOrDomain_Ip{
|
Ip: []byte{127, 0, 0, 1},
|
||||||
Ip: []byte{127, 0, 0, 1},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Port: 80,
|
},
|
||||||
User: []*protocol.User{
|
Port: 80,
|
||||||
{
|
User: &protocol.User{
|
||||||
Email: "love@example.com",
|
Email: "love@example.com",
|
||||||
Level: 255,
|
Level: 255,
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019",
|
Id: "e641f5ad-9397-41e3-bf1a-e8740dfed019",
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Type: protocol.SecurityType_AUTO,
|
Type: protocol.SecurityType_AUTO,
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -113,11 +105,7 @@ func TestVMessInbound(t *testing.T) {
|
|||||||
],
|
],
|
||||||
"default": {
|
"default": {
|
||||||
"level": 0
|
"level": 0
|
||||||
},
|
}
|
||||||
"detour": {
|
|
||||||
"to": "tag_to_detour"
|
|
||||||
},
|
|
||||||
"disableInsecureEncryption": true
|
|
||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &inbound.Config{
|
Output: &inbound.Config{
|
||||||
@@ -136,9 +124,6 @@ func TestVMessInbound(t *testing.T) {
|
|||||||
Default: &inbound.DefaultConfig{
|
Default: &inbound.DefaultConfig{
|
||||||
Level: 0,
|
Level: 0,
|
||||||
},
|
},
|
||||||
Detour: &inbound.DetourConfig{
|
|
||||||
To: "tag_to_detour",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package conf
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -120,47 +119,12 @@ func (m *MuxConfig) Build() (*proxyman.MultiplexingConfig, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type InboundDetourAllocationConfig struct {
|
|
||||||
Strategy string `json:"strategy"`
|
|
||||||
Concurrency *uint32 `json:"concurrency"`
|
|
||||||
RefreshMin *uint32 `json:"refresh"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build implements Buildable.
|
|
||||||
func (c *InboundDetourAllocationConfig) Build() (*proxyman.AllocationStrategy, error) {
|
|
||||||
config := new(proxyman.AllocationStrategy)
|
|
||||||
switch strings.ToLower(c.Strategy) {
|
|
||||||
case "always":
|
|
||||||
config.Type = proxyman.AllocationStrategy_Always
|
|
||||||
case "random":
|
|
||||||
config.Type = proxyman.AllocationStrategy_Random
|
|
||||||
case "external":
|
|
||||||
config.Type = proxyman.AllocationStrategy_External
|
|
||||||
default:
|
|
||||||
return nil, errors.New("unknown allocation strategy: ", c.Strategy)
|
|
||||||
}
|
|
||||||
if c.Concurrency != nil {
|
|
||||||
config.Concurrency = &proxyman.AllocationStrategy_AllocationStrategyConcurrency{
|
|
||||||
Value: *c.Concurrency,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.RefreshMin != nil {
|
|
||||||
config.Refresh = &proxyman.AllocationStrategy_AllocationStrategyRefresh{
|
|
||||||
Value: *c.RefreshMin,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type InboundDetourConfig struct {
|
type InboundDetourConfig struct {
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
PortList *PortList `json:"port"`
|
PortList *PortList `json:"port"`
|
||||||
ListenOn *Address `json:"listen"`
|
ListenOn *Address `json:"listen"`
|
||||||
Settings *json.RawMessage `json:"settings"`
|
Settings *json.RawMessage `json:"settings"`
|
||||||
Tag string `json:"tag"`
|
Tag string `json:"tag"`
|
||||||
Allocation *InboundDetourAllocationConfig `json:"allocate"`
|
|
||||||
StreamSetting *StreamConfig `json:"streamSettings"`
|
StreamSetting *StreamConfig `json:"streamSettings"`
|
||||||
SniffingConfig *SniffingConfig `json:"sniffing"`
|
SniffingConfig *SniffingConfig `json:"sniffing"`
|
||||||
}
|
}
|
||||||
@@ -197,30 +161,6 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Allocation != nil {
|
|
||||||
concurrency := -1
|
|
||||||
if c.Allocation.Concurrency != nil && c.Allocation.Strategy == "random" {
|
|
||||||
concurrency = int(*c.Allocation.Concurrency)
|
|
||||||
}
|
|
||||||
portRange := 0
|
|
||||||
|
|
||||||
for _, pr := range c.PortList.Range {
|
|
||||||
portRange += int(pr.To - pr.From + 1)
|
|
||||||
}
|
|
||||||
if concurrency >= 0 && concurrency >= portRange {
|
|
||||||
var ports strings.Builder
|
|
||||||
for _, pr := range c.PortList.Range {
|
|
||||||
fmt.Fprintf(&ports, "%d-%d ", pr.From, pr.To)
|
|
||||||
}
|
|
||||||
return nil, errors.New("not enough ports. concurrency = ", concurrency, " ports: ", ports.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
as, err := c.Allocation.Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
receiverSettings.AllocationStrategy = as
|
|
||||||
}
|
|
||||||
if c.StreamSetting != nil {
|
if c.StreamSetting != nil {
|
||||||
ss, err := c.StreamSetting.Build()
|
ss, err := c.StreamSetting.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -58,10 +58,6 @@ func TestXrayConfig(t *testing.T) {
|
|||||||
},
|
},
|
||||||
"protocol": "vmess",
|
"protocol": "vmess",
|
||||||
"port": "443-500",
|
"port": "443-500",
|
||||||
"allocate": {
|
|
||||||
"strategy": "random",
|
|
||||||
"concurrency": 3
|
|
||||||
},
|
|
||||||
"settings": {
|
"settings": {
|
||||||
"clients": [
|
"clients": [
|
||||||
{
|
{
|
||||||
@@ -123,12 +119,6 @@ func TestXrayConfig(t *testing.T) {
|
|||||||
From: 443,
|
From: 443,
|
||||||
To: 500,
|
To: 500,
|
||||||
}}},
|
}}},
|
||||||
AllocationStrategy: &proxyman.AllocationStrategy{
|
|
||||||
Type: proxyman.AllocationStrategy_Random,
|
|
||||||
Concurrency: &proxyman.AllocationStrategy_AllocationStrategyConcurrency{
|
|
||||||
Value: 3,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
StreamSettings: &internet.StreamConfig{
|
StreamSettings: &internet.StreamConfig{
|
||||||
ProtocolName: "websocket",
|
ProtocolName: "websocket",
|
||||||
TransportSettings: []*internet.TransportConfig{
|
TransportSettings: []*internet.TransportConfig{
|
||||||
|
|||||||
59
main/confloader/external/external.go
vendored
59
main/confloader/external/external.go
vendored
@@ -2,6 +2,8 @@ package external
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -18,6 +20,9 @@ import (
|
|||||||
func ConfigLoader(arg string) (out io.Reader, err error) {
|
func ConfigLoader(arg string) (out io.Reader, err error) {
|
||||||
var data []byte
|
var data []byte
|
||||||
switch {
|
switch {
|
||||||
|
case strings.HasPrefix(arg, "http+unix://"):
|
||||||
|
data, err = FetchUnixSocketHTTPContent(arg)
|
||||||
|
|
||||||
case strings.HasPrefix(arg, "http://"), strings.HasPrefix(arg, "https://"):
|
case strings.HasPrefix(arg, "http://"), strings.HasPrefix(arg, "https://"):
|
||||||
data, err = FetchHTTPContent(arg)
|
data, err = FetchHTTPContent(arg)
|
||||||
|
|
||||||
@@ -70,6 +75,60 @@ func FetchHTTPContent(target string) ([]byte, error) {
|
|||||||
return content, nil
|
return content, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Format: http+unix:///path/to/socket.sock/api/endpoint
|
||||||
|
func FetchUnixSocketHTTPContent(target string) ([]byte, error) {
|
||||||
|
path := strings.TrimPrefix(target, "http+unix://")
|
||||||
|
|
||||||
|
if !strings.HasPrefix(path, "/") {
|
||||||
|
return nil, errors.New("unix socket path must be absolute")
|
||||||
|
}
|
||||||
|
|
||||||
|
var socketPath, httpPath string
|
||||||
|
|
||||||
|
sockIdx := strings.Index(path, ".sock")
|
||||||
|
if sockIdx != -1 {
|
||||||
|
socketPath = path[:sockIdx+5]
|
||||||
|
httpPath = path[sockIdx+5:]
|
||||||
|
if httpPath == "" {
|
||||||
|
httpPath = "/"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("cannot determine socket path, socket file should have .sock extension")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(socketPath); err != nil {
|
||||||
|
return nil, errors.New("socket file not found: ", socketPath).Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
Transport: &http.Transport{
|
||||||
|
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||||
|
var d net.Dialer
|
||||||
|
return d.DialContext(ctx, "unix", socketPath)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
defer client.CloseIdleConnections()
|
||||||
|
|
||||||
|
resp, err := client.Get("http://localhost" + httpPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to fetch from unix socket: ", socketPath).Base(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return nil, errors.New("unexpected HTTP status code: ", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
content, err := buf.ReadAllToBytes(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to read response").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ExtConfigLoader(files []string, reader io.Reader) (io.Reader, error) {
|
func ExtConfigLoader(files []string, reader io.Reader) (io.Reader, error) {
|
||||||
buf, err := ctlcmd.Run(append([]string{"convert"}, files...), reader)
|
buf, err := ctlcmd.Run(append([]string{"convert"}, files...), reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
serverPicker protocol.ServerPicker
|
server *protocol.ServerSpec
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
header []*Header
|
header []*Header
|
||||||
}
|
}
|
||||||
@@ -48,21 +48,17 @@ var (
|
|||||||
|
|
||||||
// NewClient create a new http client based on the given config.
|
// NewClient create a new http client based on the given config.
|
||||||
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||||
serverList := protocol.NewServerList()
|
if config.Server == nil {
|
||||||
for _, rec := range config.Server {
|
return nil, errors.New(`no target server found`)
|
||||||
s, err := protocol.NewServerSpecFromPB(rec)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to get server spec").Base(err)
|
|
||||||
}
|
|
||||||
serverList.AddServer(s)
|
|
||||||
}
|
}
|
||||||
if serverList.Size() == 0 {
|
server, err := protocol.NewServerSpecFromPB(config.Server)
|
||||||
return nil, errors.New("0 target server")
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to get server spec").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
return &Client{
|
return &Client{
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
server: server,
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
header: config.Header,
|
header: config.Header,
|
||||||
}, nil
|
}, nil
|
||||||
@@ -84,7 +80,9 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
return errors.New("UDP is not supported by HTTP outbound")
|
return errors.New("UDP is not supported by HTTP outbound")
|
||||||
}
|
}
|
||||||
|
|
||||||
var user *protocol.MemoryUser
|
server := c.server
|
||||||
|
dest := server.Destination
|
||||||
|
user := server.User
|
||||||
var conn stat.Connection
|
var conn stat.Connection
|
||||||
|
|
||||||
mbuf, _ := link.Reader.ReadMultiBuffer()
|
mbuf, _ := link.Reader.ReadMultiBuffer()
|
||||||
@@ -102,10 +100,6 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := retry.ExponentialBackoff(5, 100).On(func() error {
|
if err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||||
server := c.serverPicker.PickServer()
|
|
||||||
dest := server.Destination()
|
|
||||||
user = server.PickUser()
|
|
||||||
|
|
||||||
netConn, err := setUpHTTPTunnel(ctx, dest, targetAddr, user, dialer, header, firstPayload)
|
netConn, err := setUpHTTPTunnel(ctx, dest, targetAddr, user, dialer, header, firstPayload)
|
||||||
if netConn != nil {
|
if netConn != nil {
|
||||||
if _, ok := netConn.(*http2Conn); !ok {
|
if _, ok := netConn.(*http2Conn); !ok {
|
||||||
|
|||||||
@@ -196,8 +196,8 @@ type ClientConfig struct {
|
|||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// Sever is a list of HTTP server addresses.
|
// Sever is a list of HTTP server addresses.
|
||||||
Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"`
|
Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"`
|
||||||
Header []*Header `protobuf:"bytes,2,rep,name=header,proto3" json:"header,omitempty"`
|
Header []*Header `protobuf:"bytes,2,rep,name=header,proto3" json:"header,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientConfig) Reset() {
|
func (x *ClientConfig) Reset() {
|
||||||
@@ -230,7 +230,7 @@ func (*ClientConfig) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_http_config_proto_rawDescGZIP(), []int{3}
|
return file_proxy_http_config_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint {
|
func (x *ClientConfig) GetServer() *protocol.ServerEndpoint {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Server
|
return x.Server
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ var file_proxy_http_config_proto_rawDesc = []byte{
|
|||||||
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x7d, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43,
|
0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x7d, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18,
|
||||||
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72,
|
0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72,
|
||||||
0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72,
|
0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72,
|
||||||
0x76, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20,
|
0x76, 0x65, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20,
|
||||||
|
|||||||
@@ -28,6 +28,6 @@ message Header {
|
|||||||
// ClientConfig is the protobuf config for HTTP proxy client.
|
// ClientConfig is the protobuf config for HTTP proxy client.
|
||||||
message ClientConfig {
|
message ClientConfig {
|
||||||
// Sever is a list of HTTP server addresses.
|
// Sever is a list of HTTP server addresses.
|
||||||
repeated xray.common.protocol.ServerEndpoint server = 1;
|
xray.common.protocol.ServerEndpoint server = 1;
|
||||||
repeated Header header = 2;
|
repeated Header header = 2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,27 +22,23 @@ import (
|
|||||||
|
|
||||||
// Client is a inbound handler for Shadowsocks protocol
|
// Client is a inbound handler for Shadowsocks protocol
|
||||||
type Client struct {
|
type Client struct {
|
||||||
serverPicker protocol.ServerPicker
|
server *protocol.ServerSpec
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient create a new Shadowsocks client.
|
// NewClient create a new Shadowsocks client.
|
||||||
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||||
serverList := protocol.NewServerList()
|
if config.Server == nil {
|
||||||
for _, rec := range config.Server {
|
return nil, errors.New(`no target server found`)
|
||||||
s, err := protocol.NewServerSpecFromPB(rec)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to parse server spec").Base(err)
|
|
||||||
}
|
|
||||||
serverList.AddServer(s)
|
|
||||||
}
|
}
|
||||||
if serverList.Size() == 0 {
|
server, err := protocol.NewServerSpecFromPB(config.Server)
|
||||||
return nil, errors.New("0 server")
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to get server spec").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
client := &Client{
|
client := &Client{
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
server: server,
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
return client, nil
|
return client, nil
|
||||||
@@ -60,13 +56,12 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
destination := ob.Target
|
destination := ob.Target
|
||||||
network := destination.Network
|
network := destination.Network
|
||||||
|
|
||||||
var server *protocol.ServerSpec
|
server := c.server
|
||||||
|
dest := server.Destination
|
||||||
|
dest.Network = network
|
||||||
var conn stat.Connection
|
var conn stat.Connection
|
||||||
|
|
||||||
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||||
server = c.serverPicker.PickServer()
|
|
||||||
dest := server.Destination()
|
|
||||||
dest.Network = network
|
|
||||||
rawConn, err := dialer.Dial(ctx, dest)
|
rawConn, err := dialer.Dial(ctx, dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -78,7 +73,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to find an available destination").AtWarning().Base(err)
|
return errors.New("failed to find an available destination").AtWarning().Base(err)
|
||||||
}
|
}
|
||||||
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", network, ":", server.Destination().NetAddr())
|
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", network, ":", server.Destination.NetAddr())
|
||||||
|
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
@@ -93,7 +88,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
request.Command = protocol.RequestCommandUDP
|
request.Command = protocol.RequestCommandUDP
|
||||||
}
|
}
|
||||||
|
|
||||||
user := server.PickUser()
|
user := server.User
|
||||||
_, ok := user.Account.(*MemoryAccount)
|
_, ok := user.Account.(*MemoryAccount)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("user account is not valid")
|
return errors.New("user account is not valid")
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ type ClientConfig struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"`
|
Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientConfig) Reset() {
|
func (x *ClientConfig) Reset() {
|
||||||
@@ -232,7 +232,7 @@ func (*ClientConfig) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_shadowsocks_config_proto_rawDescGZIP(), []int{2}
|
return file_proxy_shadowsocks_config_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint {
|
func (x *ClientConfig) GetServer() *protocol.ServerEndpoint {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Server
|
return x.Server
|
||||||
}
|
}
|
||||||
@@ -268,7 +268,7 @@ var file_proxy_shadowsocks_config_proto_rawDesc = []byte{
|
|||||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e,
|
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e,
|
||||||
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22,
|
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x22,
|
||||||
0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||||
0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72,
|
0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72,
|
||||||
0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64,
|
0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64,
|
||||||
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2a, 0x74, 0x0a,
|
0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2a, 0x74, 0x0a,
|
||||||
|
|||||||
@@ -32,5 +32,5 @@ message ServerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ClientConfig {
|
message ClientConfig {
|
||||||
repeated xray.common.protocol.ServerEndpoint server = 1;
|
xray.common.protocol.ServerEndpoint server = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,27 +22,23 @@ import (
|
|||||||
|
|
||||||
// Client is a Socks5 client.
|
// Client is a Socks5 client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
serverPicker protocol.ServerPicker
|
server *protocol.ServerSpec
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient create a new Socks5 client based on the given config.
|
// NewClient create a new Socks5 client based on the given config.
|
||||||
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||||
serverList := protocol.NewServerList()
|
if config.Server == nil {
|
||||||
for _, rec := range config.Server {
|
return nil, errors.New(`no target server found`)
|
||||||
s, err := protocol.NewServerSpecFromPB(rec)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to get server spec").Base(err)
|
|
||||||
}
|
|
||||||
serverList.AddServer(s)
|
|
||||||
}
|
}
|
||||||
if serverList.Size() == 0 {
|
server, err := protocol.NewServerSpecFromPB(config.Server)
|
||||||
return nil, errors.New("0 target server")
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to get server spec").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
c := &Client{
|
c := &Client{
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
server: server,
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,15 +58,12 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
destination := ob.Target
|
destination := ob.Target
|
||||||
|
|
||||||
// Outbound server.
|
// Outbound server.
|
||||||
var server *protocol.ServerSpec
|
server := c.server
|
||||||
// Outbound server's destination.
|
dest := server.Destination
|
||||||
var dest net.Destination
|
|
||||||
// Connection to the outbound server.
|
// Connection to the outbound server.
|
||||||
var conn stat.Connection
|
var conn stat.Connection
|
||||||
|
|
||||||
if err := retry.ExponentialBackoff(5, 100).On(func() error {
|
if err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||||
server = c.serverPicker.PickServer()
|
|
||||||
dest = server.Destination()
|
|
||||||
rawConn, err := dialer.Dial(ctx, dest)
|
rawConn, err := dialer.Dial(ctx, dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -101,7 +94,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
request.Command = protocol.RequestCommandUDP
|
request.Command = protocol.RequestCommandUDP
|
||||||
}
|
}
|
||||||
|
|
||||||
user := server.PickUser()
|
user := server.User
|
||||||
if user != nil {
|
if user != nil {
|
||||||
request.User = user
|
request.User = user
|
||||||
p = c.policyManager.ForLevel(user.Level)
|
p = c.policyManager.ForLevel(user.Level)
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ type ClientConfig struct {
|
|||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// Sever is a list of Socks server addresses.
|
// Sever is a list of Socks server addresses.
|
||||||
Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"`
|
Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientConfig) Reset() {
|
func (x *ClientConfig) Reset() {
|
||||||
@@ -243,7 +243,7 @@ func (*ClientConfig) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_socks_config_proto_rawDescGZIP(), []int{2}
|
return file_proxy_socks_config_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint {
|
func (x *ClientConfig) GetServer() *protocol.ServerEndpoint {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Server
|
return x.Server
|
||||||
}
|
}
|
||||||
@@ -286,7 +286,7 @@ var file_proxy_socks_config_proto_rawDesc = []byte{
|
|||||||
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
|
0x3a, 0x02, 0x38, 0x01, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01,
|
0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01,
|
||||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||||
0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76,
|
0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76,
|
||||||
0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76,
|
0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76,
|
||||||
0x65, 0x72, 0x2a, 0x25, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b,
|
0x65, 0x72, 0x2a, 0x25, 0x0a, 0x08, 0x41, 0x75, 0x74, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b,
|
||||||
|
|||||||
@@ -35,5 +35,5 @@ message ServerConfig {
|
|||||||
// ClientConfig is the protobuf config for Socks client.
|
// ClientConfig is the protobuf config for Socks client.
|
||||||
message ClientConfig {
|
message ClientConfig {
|
||||||
// Sever is a list of Socks server addresses.
|
// Sever is a list of Socks server addresses.
|
||||||
repeated xray.common.protocol.ServerEndpoint server = 1;
|
xray.common.protocol.ServerEndpoint server = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,27 +22,23 @@ import (
|
|||||||
|
|
||||||
// Client is a inbound handler for trojan protocol
|
// Client is a inbound handler for trojan protocol
|
||||||
type Client struct {
|
type Client struct {
|
||||||
serverPicker protocol.ServerPicker
|
server *protocol.ServerSpec
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient create a new trojan client.
|
// NewClient create a new trojan client.
|
||||||
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||||
serverList := protocol.NewServerList()
|
if config.Server == nil {
|
||||||
for _, rec := range config.Server {
|
return nil, errors.New(`no target server found`)
|
||||||
s, err := protocol.NewServerSpecFromPB(rec)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to parse server spec").Base(err)
|
|
||||||
}
|
|
||||||
serverList.AddServer(s)
|
|
||||||
}
|
}
|
||||||
if serverList.Size() == 0 {
|
server, err := protocol.NewServerSpecFromPB(config.Server)
|
||||||
return nil, errors.New("0 server")
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to get server spec").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
client := &Client{
|
client := &Client{
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
server: server,
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
}
|
}
|
||||||
return client, nil
|
return client, nil
|
||||||
@@ -60,12 +56,11 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
destination := ob.Target
|
destination := ob.Target
|
||||||
network := destination.Network
|
network := destination.Network
|
||||||
|
|
||||||
var server *protocol.ServerSpec
|
server := c.server
|
||||||
var conn stat.Connection
|
var conn stat.Connection
|
||||||
|
|
||||||
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||||
server = c.serverPicker.PickServer()
|
rawConn, err := dialer.Dial(ctx, server.Destination)
|
||||||
rawConn, err := dialer.Dial(ctx, server.Destination())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -76,11 +71,11 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to find an available destination").AtWarning().Base(err)
|
return errors.New("failed to find an available destination").AtWarning().Base(err)
|
||||||
}
|
}
|
||||||
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", server.Destination().NetAddr())
|
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", server.Destination.NetAddr())
|
||||||
|
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
user := server.PickUser()
|
user := server.User
|
||||||
account, ok := user.Account.(*MemoryAccount)
|
account, ok := user.Account.(*MemoryAccount)
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.New("user account is not valid")
|
return errors.New("user account is not valid")
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ type ClientConfig struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"`
|
Server *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientConfig) Reset() {
|
func (x *ClientConfig) Reset() {
|
||||||
@@ -189,7 +189,7 @@ func (*ClientConfig) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_trojan_config_proto_rawDescGZIP(), []int{2}
|
return file_proxy_trojan_config_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint {
|
func (x *ClientConfig) GetServer() *protocol.ServerEndpoint {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Server
|
return x.Server
|
||||||
}
|
}
|
||||||
@@ -271,7 +271,7 @@ var file_proxy_trojan_config_proto_rawDesc = []byte{
|
|||||||
0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20,
|
0x04, 0x64, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x78, 0x76, 0x65, 0x72, 0x18, 0x06, 0x20,
|
||||||
0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69,
|
0x01, 0x28, 0x04, 0x52, 0x04, 0x78, 0x76, 0x65, 0x72, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69,
|
||||||
0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72,
|
0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72,
|
||||||
0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||||
0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52,
|
0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52,
|
||||||
0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65,
|
0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x7b, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ message Fallback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message ClientConfig {
|
message ClientConfig {
|
||||||
repeated xray.common.protocol.ServerEndpoint server = 1;
|
xray.common.protocol.ServerEndpoint server = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ServerConfig {
|
message ServerConfig {
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ func (r *Reverse) Dispatch(ctx context.Context, link *transport.Link) {
|
|||||||
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
||||||
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
||||||
}
|
}
|
||||||
r.client.Dispatch(ctx, link)
|
r.client.Dispatch(session.ContextWithIsReverseMux(ctx, true), link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type Config struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Vnext []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=vnext,proto3" json:"vnext,omitempty"`
|
Vnext *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=vnext,proto3" json:"vnext,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -59,7 +59,7 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_vless_outbound_config_proto_rawDescGZIP(), []int{0}
|
return file_proxy_vless_outbound_config_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetVnext() []*protocol.ServerEndpoint {
|
func (x *Config) GetVnext() *protocol.ServerEndpoint {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Vnext
|
return x.Vnext
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ var file_proxy_vless_outbound_config_proto_rawDesc = []byte{
|
|||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f,
|
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f,
|
||||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x6f, 0x22, 0x44, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x05, 0x76,
|
0x6f, 0x22, 0x44, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3a, 0x0a, 0x05, 0x76,
|
||||||
0x6e, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
|
0x6e, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||||
0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
0x52, 0x05, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
0x52, 0x05, 0x76, 0x6e, 0x65, 0x78, 0x74, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ option java_multiple_files = true;
|
|||||||
import "common/protocol/server_spec.proto";
|
import "common/protocol/server_spec.proto";
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
repeated xray.common.protocol.ServerEndpoint vnext = 1;
|
xray.common.protocol.ServerEndpoint vnext = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ func init() {
|
|||||||
|
|
||||||
// Handler is an outbound connection handler for VLess protocol.
|
// Handler is an outbound connection handler for VLess protocol.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
serverList *protocol.ServerList
|
server *protocol.ServerSpec
|
||||||
serverPicker protocol.ServerPicker
|
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
cone bool
|
cone bool
|
||||||
encryption *encryption.ClientInstance
|
encryption *encryption.ClientInstance
|
||||||
@@ -57,24 +56,22 @@ type Handler struct {
|
|||||||
|
|
||||||
// New creates a new VLess outbound handler.
|
// New creates a new VLess outbound handler.
|
||||||
func New(ctx context.Context, config *Config) (*Handler, error) {
|
func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||||
serverList := protocol.NewServerList()
|
if config.Vnext == nil {
|
||||||
for _, rec := range config.Vnext {
|
return nil, errors.New(`no vnext found`)
|
||||||
s, err := protocol.NewServerSpecFromPB(rec)
|
}
|
||||||
if err != nil {
|
server, err := protocol.NewServerSpecFromPB(config.Vnext)
|
||||||
return nil, errors.New("failed to parse server spec").Base(err).AtError()
|
if err != nil {
|
||||||
}
|
return nil, errors.New("failed to get server spec").Base(err).AtError()
|
||||||
serverList.AddServer(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
handler := &Handler{
|
handler := &Handler{
|
||||||
serverList: serverList,
|
server: server,
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
cone: ctx.Value("cone").(bool),
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
a := handler.serverPicker.PickServer().PickUser().Account.(*vless.MemoryAccount)
|
a := handler.server.User.Account.(*vless.MemoryAccount)
|
||||||
if a.Encryption != "" && a.Encryption != "none" {
|
if a.Encryption != "" && a.Encryption != "none" {
|
||||||
s := strings.Split(a.Encryption, ".")
|
s := strings.Split(a.Encryption, ".")
|
||||||
var nfsPKeysBytes [][]byte
|
var nfsPKeysBytes [][]byte
|
||||||
@@ -92,8 +89,11 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
|||||||
handler.reverse = &Reverse{
|
handler.reverse = &Reverse{
|
||||||
tag: a.Reverse.Tag,
|
tag: a.Reverse.Tag,
|
||||||
dispatcher: v.GetFeature(routing.DispatcherType()).(routing.Dispatcher),
|
dispatcher: v.GetFeature(routing.DispatcherType()).(routing.Dispatcher),
|
||||||
ctx: ctx,
|
ctx: session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
handler: handler,
|
Tag: a.Reverse.Tag,
|
||||||
|
User: handler.server.User, // TODO: email
|
||||||
|
}),
|
||||||
|
handler: handler,
|
||||||
}
|
}
|
||||||
handler.reverse.monitorTask = &task.Periodic{
|
handler.reverse.monitorTask = &task.Periodic{
|
||||||
Execute: handler.reverse.monitor,
|
Execute: handler.reverse.monitor,
|
||||||
@@ -125,12 +125,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
}
|
}
|
||||||
ob.Name = "vless"
|
ob.Name = "vless"
|
||||||
|
|
||||||
var rec *protocol.ServerSpec
|
rec := h.server
|
||||||
var conn stat.Connection
|
var conn stat.Connection
|
||||||
|
|
||||||
if err := retry.ExponentialBackoff(5, 200).On(func() error {
|
if err := retry.ExponentialBackoff(5, 200).On(func() error {
|
||||||
rec = h.serverPicker.PickServer()
|
|
||||||
var err error
|
var err error
|
||||||
conn, err = dialer.Dial(ctx, rec.Destination())
|
conn, err = dialer.Dial(ctx, rec.Destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
iConn = statConn.Connection
|
iConn = statConn.Connection
|
||||||
}
|
}
|
||||||
target := ob.Target
|
target := ob.Target
|
||||||
errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination().NetAddr())
|
errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination.NetAddr())
|
||||||
|
|
||||||
if h.encryption != nil {
|
if h.encryption != nil {
|
||||||
var err error
|
var err error
|
||||||
@@ -172,7 +172,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
|
|
||||||
request := &protocol.RequestHeader{
|
request := &protocol.RequestHeader{
|
||||||
Version: encoding.Version,
|
Version: encoding.Version,
|
||||||
User: rec.PickUser(),
|
User: rec.User,
|
||||||
Command: command,
|
Command: command,
|
||||||
Address: target.Address,
|
Address: target.Address,
|
||||||
Port: target.Port,
|
Port: target.Port,
|
||||||
@@ -201,7 +201,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
}
|
}
|
||||||
case protocol.RequestCommandMux:
|
case protocol.RequestCommandMux:
|
||||||
fallthrough // let server break Mux connections that contain TCP requests
|
fallthrough // let server break Mux connections that contain TCP requests
|
||||||
case protocol.RequestCommandTCP:
|
case protocol.RequestCommandTCP, protocol.RequestCommandRvs:
|
||||||
var t reflect.Type
|
var t reflect.Type
|
||||||
var p uintptr
|
var p uintptr
|
||||||
if commonConn, ok := conn.(*encryption.CommonConn); ok {
|
if commonConn, ok := conn.(*encryption.CommonConn); ok {
|
||||||
@@ -226,6 +226,8 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
r, _ := t.FieldByName("rawInput")
|
r, _ := t.FieldByName("rawInput")
|
||||||
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
|
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
|
||||||
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
|
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
|
||||||
|
default:
|
||||||
|
panic("unknown VLESS request command")
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ob.CanSpliceCopy = 3
|
ob.CanSpliceCopy = 3
|
||||||
@@ -398,7 +400,7 @@ func (r *Reverse) monitor() error {
|
|||||||
Tag: r.tag,
|
Tag: r.tag,
|
||||||
Dispatcher: r.dispatcher,
|
Dispatcher: r.dispatcher,
|
||||||
}
|
}
|
||||||
worker, err := mux.NewServerWorker(r.ctx, w, link1)
|
worker, err := mux.NewServerWorker(session.ContextWithIsReverseMux(r.ctx, true), w, link1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogWarningInner(r.ctx, err, "failed to create mux server worker")
|
errors.LogWarningInner(r.ctx, err, "failed to create mux server worker")
|
||||||
return nil
|
return nil
|
||||||
@@ -409,7 +411,7 @@ func (r *Reverse) monitor() error {
|
|||||||
ctx := session.ContextWithOutbounds(r.ctx, []*session.Outbound{{
|
ctx := session.ContextWithOutbounds(r.ctx, []*session.Outbound{{
|
||||||
Target: net.Destination{Address: net.DomainAddress("v1.rvs.cool")},
|
Target: net.Destination{Address: net.DomainAddress("v1.rvs.cool")},
|
||||||
}})
|
}})
|
||||||
r.handler.Process(ctx, link2, session.HandlerFromContext(ctx).(*proxyman.Handler))
|
r.handler.Process(ctx, link2, session.FullHandlerFromContext(ctx).(*proxyman.Handler))
|
||||||
common.Interrupt(reader1)
|
common.Interrupt(reader1)
|
||||||
common.Interrupt(reader2)
|
common.Interrupt(reader2)
|
||||||
}()
|
}()
|
||||||
|
|||||||
@@ -7,10 +7,7 @@ import (
|
|||||||
"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/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -29,9 +26,6 @@ func MarshalCommand(command interface{}, writer io.Writer) error {
|
|||||||
var cmdID byte
|
var cmdID byte
|
||||||
var factory CommandFactory
|
var factory CommandFactory
|
||||||
switch command.(type) {
|
switch command.(type) {
|
||||||
case *protocol.CommandSwitchAccount:
|
|
||||||
factory = new(CommandSwitchAccountFactory)
|
|
||||||
cmdID = 1
|
|
||||||
default:
|
default:
|
||||||
return ErrUnknownCommand
|
return ErrUnknownCommand
|
||||||
}
|
}
|
||||||
@@ -67,8 +61,6 @@ func UnmarshalCommand(cmdID byte, data []byte) (protocol.ResponseCommand, error)
|
|||||||
|
|
||||||
var factory CommandFactory
|
var factory CommandFactory
|
||||||
switch cmdID {
|
switch cmdID {
|
||||||
case 1:
|
|
||||||
factory = new(CommandSwitchAccountFactory)
|
|
||||||
default:
|
default:
|
||||||
return nil, ErrUnknownCommand
|
return nil, ErrUnknownCommand
|
||||||
}
|
}
|
||||||
@@ -79,67 +71,3 @@ type CommandFactory interface {
|
|||||||
Marshal(command interface{}, writer io.Writer) error
|
Marshal(command interface{}, writer io.Writer) error
|
||||||
Unmarshal(data []byte) (interface{}, error)
|
Unmarshal(data []byte) (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandSwitchAccountFactory struct{}
|
|
||||||
|
|
||||||
func (f *CommandSwitchAccountFactory) Marshal(command interface{}, writer io.Writer) error {
|
|
||||||
cmd, ok := command.(*protocol.CommandSwitchAccount)
|
|
||||||
if !ok {
|
|
||||||
return ErrCommandTypeMismatch
|
|
||||||
}
|
|
||||||
|
|
||||||
hostStr := ""
|
|
||||||
if cmd.Host != nil {
|
|
||||||
hostStr = cmd.Host.String()
|
|
||||||
}
|
|
||||||
common.Must2(writer.Write([]byte{byte(len(hostStr))}))
|
|
||||||
|
|
||||||
if len(hostStr) > 0 {
|
|
||||||
common.Must2(writer.Write([]byte(hostStr)))
|
|
||||||
}
|
|
||||||
|
|
||||||
common.Must2(serial.WriteUint16(writer, cmd.Port.Value()))
|
|
||||||
|
|
||||||
idBytes := cmd.ID.Bytes()
|
|
||||||
common.Must2(writer.Write(idBytes))
|
|
||||||
common.Must2(serial.WriteUint16(writer, 0)) // compatible with legacy alterId
|
|
||||||
common.Must2(writer.Write([]byte{byte(cmd.Level)}))
|
|
||||||
|
|
||||||
common.Must2(writer.Write([]byte{cmd.ValidMin}))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *CommandSwitchAccountFactory) Unmarshal(data []byte) (interface{}, error) {
|
|
||||||
cmd := new(protocol.CommandSwitchAccount)
|
|
||||||
if len(data) == 0 {
|
|
||||||
return nil, ErrInsufficientLength
|
|
||||||
}
|
|
||||||
lenHost := int(data[0])
|
|
||||||
if len(data) < lenHost+1 {
|
|
||||||
return nil, ErrInsufficientLength
|
|
||||||
}
|
|
||||||
if lenHost > 0 {
|
|
||||||
cmd.Host = net.ParseAddress(string(data[1 : 1+lenHost]))
|
|
||||||
}
|
|
||||||
portStart := 1 + lenHost
|
|
||||||
if len(data) < portStart+2 {
|
|
||||||
return nil, ErrInsufficientLength
|
|
||||||
}
|
|
||||||
cmd.Port = net.PortFromBytes(data[portStart : portStart+2])
|
|
||||||
idStart := portStart + 2
|
|
||||||
if len(data) < idStart+16 {
|
|
||||||
return nil, ErrInsufficientLength
|
|
||||||
}
|
|
||||||
cmd.ID, _ = uuid.ParseBytes(data[idStart : idStart+16])
|
|
||||||
levelStart := idStart + 16 + 2
|
|
||||||
if len(data) < levelStart+1 {
|
|
||||||
return nil, ErrInsufficientLength
|
|
||||||
}
|
|
||||||
cmd.Level = uint32(data[levelStart])
|
|
||||||
timeStart := levelStart + 1
|
|
||||||
if len(data) < timeStart+1 {
|
|
||||||
return nil, ErrInsufficientLength
|
|
||||||
}
|
|
||||||
cmd.ValidMin = data[timeStart]
|
|
||||||
return cmd, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
package encoding_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
|
||||||
. "github.com/xtls/xray-core/proxy/vmess/encoding"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestSwitchAccount(t *testing.T) {
|
|
||||||
sa := &protocol.CommandSwitchAccount{
|
|
||||||
Port: 1234,
|
|
||||||
ID: uuid.New(),
|
|
||||||
Level: 128,
|
|
||||||
ValidMin: 16,
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := buf.New()
|
|
||||||
common.Must(MarshalCommand(sa, buffer))
|
|
||||||
|
|
||||||
cmd, err := UnmarshalCommand(1, buffer.BytesFrom(2))
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
sa2, ok := cmd.(*protocol.CommandSwitchAccount)
|
|
||||||
if !ok {
|
|
||||||
t.Fatal("failed to convert command to CommandSwitchAccount")
|
|
||||||
}
|
|
||||||
if r := cmp.Diff(sa2, sa); r != "" {
|
|
||||||
t.Error(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSwitchAccountBugOffByOne(t *testing.T) {
|
|
||||||
sa := &protocol.CommandSwitchAccount{
|
|
||||||
Port: 1234,
|
|
||||||
ID: uuid.New(),
|
|
||||||
Level: 128,
|
|
||||||
ValidMin: 16,
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer := buf.New()
|
|
||||||
csaf := CommandSwitchAccountFactory{}
|
|
||||||
common.Must(csaf.Marshal(sa, buffer))
|
|
||||||
|
|
||||||
Payload := buffer.Bytes()
|
|
||||||
|
|
||||||
cmd, err := csaf.Unmarshal(Payload[:len(Payload)-1])
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Nil(t, cmd)
|
|
||||||
}
|
|
||||||
@@ -118,7 +118,6 @@ type Config struct {
|
|||||||
|
|
||||||
User []*protocol.User `protobuf:"bytes,1,rep,name=user,proto3" json:"user,omitempty"`
|
User []*protocol.User `protobuf:"bytes,1,rep,name=user,proto3" json:"user,omitempty"`
|
||||||
Default *DefaultConfig `protobuf:"bytes,2,opt,name=default,proto3" json:"default,omitempty"`
|
Default *DefaultConfig `protobuf:"bytes,2,opt,name=default,proto3" json:"default,omitempty"`
|
||||||
Detour *DetourConfig `protobuf:"bytes,3,opt,name=detour,proto3" json:"detour,omitempty"` // 4 is for legacy setting
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -165,13 +164,6 @@ func (x *Config) GetDefault() *DefaultConfig {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetDetour() *DetourConfig {
|
|
||||||
if x != nil {
|
|
||||||
return x.Detour
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_proxy_vmess_inbound_config_proto protoreflect.FileDescriptor
|
var File_proxy_vmess_inbound_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_proxy_vmess_inbound_config_proto_rawDesc = []byte{
|
var file_proxy_vmess_inbound_config_proto_rawDesc = []byte{
|
||||||
@@ -185,26 +177,21 @@ var file_proxy_vmess_inbound_config_proto_rawDesc = []byte{
|
|||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x25, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f, 0x22, 0x25, 0x0a, 0x0d, 0x44, 0x65, 0x66, 0x61,
|
||||||
0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76,
|
0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76,
|
||||||
0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22,
|
0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22,
|
||||||
0xbb, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x04, 0x75, 0x73,
|
0x7b, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2e, 0x0a, 0x04, 0x75, 0x73, 0x65,
|
||||||
0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e,
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55,
|
||||||
0x55, 0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x07, 0x64, 0x65,
|
0x73, 0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x07, 0x64, 0x65, 0x66,
|
||||||
0x66, 0x61, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72,
|
0x61, 0x75, 0x6c, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69,
|
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e,
|
||||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f,
|
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x3e, 0x0a,
|
0x66, 0x69, 0x67, 0x52, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x42, 0x6a, 0x0a, 0x1c,
|
||||||
0x06, 0x64, 0x65, 0x74, 0x6f, 0x75, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e,
|
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x76, 0x6d, 0x65, 0x73, 0x73,
|
0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2d,
|
||||||
0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x2e, 0x44, 0x65, 0x74, 0x6f, 0x75, 0x72, 0x43,
|
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x64, 0x65, 0x74, 0x6f, 0x75, 0x72, 0x42, 0x6a, 0x0a,
|
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
|
||||||
0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
0x76, 0x6d, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02, 0x18,
|
||||||
0x76, 0x6d, 0x65, 0x73, 0x73, 0x2e, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x50, 0x01, 0x5a,
|
0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6d, 0x65, 0x73, 0x73,
|
||||||
0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73,
|
0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
|
||||||
0x2f, 0x76, 0x6d, 0x65, 0x73, 0x73, 0x2f, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0xaa, 0x02,
|
|
||||||
0x18, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x56, 0x6d, 0x65, 0x73,
|
|
||||||
0x73, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
|
||||||
0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -229,12 +216,11 @@ var file_proxy_vmess_inbound_config_proto_goTypes = []any{
|
|||||||
var file_proxy_vmess_inbound_config_proto_depIdxs = []int32{
|
var file_proxy_vmess_inbound_config_proto_depIdxs = []int32{
|
||||||
3, // 0: xray.proxy.vmess.inbound.Config.user:type_name -> xray.common.protocol.User
|
3, // 0: xray.proxy.vmess.inbound.Config.user:type_name -> xray.common.protocol.User
|
||||||
1, // 1: xray.proxy.vmess.inbound.Config.default:type_name -> xray.proxy.vmess.inbound.DefaultConfig
|
1, // 1: xray.proxy.vmess.inbound.Config.default:type_name -> xray.proxy.vmess.inbound.DefaultConfig
|
||||||
0, // 2: xray.proxy.vmess.inbound.Config.detour:type_name -> xray.proxy.vmess.inbound.DetourConfig
|
2, // [2:2] is the sub-list for method output_type
|
||||||
3, // [3:3] is the sub-list for method output_type
|
2, // [2:2] is the sub-list for method input_type
|
||||||
3, // [3:3] is the sub-list for method input_type
|
2, // [2:2] is the sub-list for extension type_name
|
||||||
3, // [3:3] is the sub-list for extension type_name
|
2, // [2:2] is the sub-list for extension extendee
|
||||||
3, // [3:3] is the sub-list for extension extendee
|
0, // [0:2] is the sub-list for field type_name
|
||||||
0, // [0:3] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_proxy_vmess_inbound_config_proto_init() }
|
func init() { file_proxy_vmess_inbound_config_proto_init() }
|
||||||
|
|||||||
@@ -19,6 +19,4 @@ message DefaultConfig {
|
|||||||
message Config {
|
message Config {
|
||||||
repeated xray.common.protocol.User user = 1;
|
repeated xray.common.protocol.User user = 1;
|
||||||
DefaultConfig default = 2;
|
DefaultConfig default = 2;
|
||||||
DetourConfig detour = 3;
|
|
||||||
// 4 is for legacy setting
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,6 @@ type Handler struct {
|
|||||||
inboundHandlerManager feature_inbound.Manager
|
inboundHandlerManager feature_inbound.Manager
|
||||||
clients *vmess.TimedUserValidator
|
clients *vmess.TimedUserValidator
|
||||||
usersByEmail *userByEmail
|
usersByEmail *userByEmail
|
||||||
detours *DetourConfig
|
|
||||||
sessionHistory *encoding.SessionHistory
|
sessionHistory *encoding.SessionHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +116,6 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
|||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
inboundHandlerManager: v.GetFeature(feature_inbound.ManagerType()).(feature_inbound.Manager),
|
inboundHandlerManager: v.GetFeature(feature_inbound.ManagerType()).(feature_inbound.Manager),
|
||||||
clients: vmess.NewTimedUserValidator(),
|
clients: vmess.NewTimedUserValidator(),
|
||||||
detours: config.Detour,
|
|
||||||
usersByEmail: newUserByEmail(config.GetDefaultValue()),
|
usersByEmail: newUserByEmail(config.GetDefaultValue()),
|
||||||
sessionHistory: encoding.NewSessionHistory(),
|
sessionHistory: encoding.NewSessionHistory(),
|
||||||
}
|
}
|
||||||
@@ -323,38 +321,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stub command generator
|
||||||
func (h *Handler) generateCommand(ctx context.Context, request *protocol.RequestHeader) protocol.ResponseCommand {
|
func (h *Handler) generateCommand(ctx context.Context, request *protocol.RequestHeader) protocol.ResponseCommand {
|
||||||
if h.detours != nil {
|
|
||||||
tag := h.detours.To
|
|
||||||
if h.inboundHandlerManager != nil {
|
|
||||||
handler, err := h.inboundHandlerManager.GetHandler(ctx, tag)
|
|
||||||
if err != nil {
|
|
||||||
errors.LogWarningInner(ctx, err, "failed to get detour handler: ", tag)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
proxyHandler, port, availableMin := handler.GetRandomInboundProxy()
|
|
||||||
inboundHandler, ok := proxyHandler.(*Handler)
|
|
||||||
if ok && inboundHandler != nil {
|
|
||||||
if availableMin > 255 {
|
|
||||||
availableMin = 255
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.LogDebug(ctx, "pick detour handler for port ", port, " for ", availableMin, " minutes.")
|
|
||||||
user := inboundHandler.GetOrGenerateUser(request.User.Email)
|
|
||||||
if user == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
account := user.Account.(*vmess.MemoryAccount)
|
|
||||||
return &protocol.CommandSwitchAccount{
|
|
||||||
Port: port,
|
|
||||||
ID: account.ID.UUID(),
|
|
||||||
Level: user.Level,
|
|
||||||
ValidMin: byte(availableMin),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,41 +1,14 @@
|
|||||||
package outbound
|
package outbound
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/proxy/vmess"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Handler) handleSwitchAccount(cmd *protocol.CommandSwitchAccount) {
|
// As a stub command consumer.
|
||||||
rawAccount := &vmess.Account{
|
|
||||||
Id: cmd.ID.String(),
|
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AUTO,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
account, err := rawAccount.AsAccount()
|
|
||||||
common.Must(err)
|
|
||||||
user := &protocol.MemoryUser{
|
|
||||||
Email: "",
|
|
||||||
Level: cmd.Level,
|
|
||||||
Account: account,
|
|
||||||
}
|
|
||||||
dest := net.TCPDestination(cmd.Host, cmd.Port)
|
|
||||||
until := time.Now().Add(time.Duration(cmd.ValidMin) * time.Minute)
|
|
||||||
h.serverList.AddServer(protocol.NewServerSpec(dest, protocol.BeforeTime(until), user))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) handleCommand(dest net.Destination, cmd protocol.ResponseCommand) {
|
func (h *Handler) handleCommand(dest net.Destination, cmd protocol.ResponseCommand) {
|
||||||
switch typedCommand := cmd.(type) {
|
switch cmd.(type) {
|
||||||
case *protocol.CommandSwitchAccount:
|
|
||||||
if typedCommand.Host == nil {
|
|
||||||
typedCommand.Host = dest.Address
|
|
||||||
}
|
|
||||||
h.handleSwitchAccount(typedCommand)
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type Config struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Receiver []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=Receiver,proto3" json:"Receiver,omitempty"`
|
Receiver *protocol.ServerEndpoint `protobuf:"bytes,1,opt,name=Receiver,proto3" json:"Receiver,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -59,7 +59,7 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_vmess_outbound_config_proto_rawDescGZIP(), []int{0}
|
return file_proxy_vmess_outbound_config_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetReceiver() []*protocol.ServerEndpoint {
|
func (x *Config) GetReceiver() *protocol.ServerEndpoint {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Receiver
|
return x.Receiver
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ var file_proxy_vmess_outbound_config_proto_rawDesc = []byte{
|
|||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f,
|
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f,
|
||||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x6f, 0x22, 0x4a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x08, 0x52,
|
0x6f, 0x22, 0x4a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x40, 0x0a, 0x08, 0x52,
|
||||||
0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e,
|
0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||||
0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f,
|
0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f,
|
||||||
0x69, 0x6e, 0x74, 0x52, 0x08, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x42, 0x6d, 0x0a,
|
0x69, 0x6e, 0x74, 0x52, 0x08, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x42, 0x6d, 0x0a,
|
||||||
|
|||||||
@@ -9,5 +9,5 @@ option java_multiple_files = true;
|
|||||||
import "common/protocol/server_spec.proto";
|
import "common/protocol/server_spec.proto";
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
repeated xray.common.protocol.ServerEndpoint Receiver = 1;
|
xray.common.protocol.ServerEndpoint Receiver = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,27 +29,24 @@ import (
|
|||||||
|
|
||||||
// Handler is an outbound connection handler for VMess protocol.
|
// Handler is an outbound connection handler for VMess protocol.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
serverList *protocol.ServerList
|
server *protocol.ServerSpec
|
||||||
serverPicker protocol.ServerPicker
|
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
cone bool
|
cone bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new VMess outbound handler.
|
// New creates a new VMess outbound handler.
|
||||||
func New(ctx context.Context, config *Config) (*Handler, error) {
|
func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||||
serverList := protocol.NewServerList()
|
if config.Receiver == nil {
|
||||||
for _, rec := range config.Receiver {
|
return nil, errors.New(`no vnext found`)
|
||||||
s, err := protocol.NewServerSpecFromPB(rec)
|
}
|
||||||
if err != nil {
|
server, err := protocol.NewServerSpecFromPB(config.Receiver)
|
||||||
return nil, errors.New("failed to parse server spec").Base(err)
|
if err != nil {
|
||||||
}
|
return nil, errors.New("failed to get server spec").Base(err)
|
||||||
serverList.AddServer(s)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
handler := &Handler{
|
handler := &Handler{
|
||||||
serverList: serverList,
|
server: server,
|
||||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
|
||||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||||
cone: ctx.Value("cone").(bool),
|
cone: ctx.Value("cone").(bool),
|
||||||
}
|
}
|
||||||
@@ -67,11 +64,11 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
ob.Name = "vmess"
|
ob.Name = "vmess"
|
||||||
ob.CanSpliceCopy = 3
|
ob.CanSpliceCopy = 3
|
||||||
|
|
||||||
var rec *protocol.ServerSpec
|
rec := h.server
|
||||||
var conn stat.Connection
|
var conn stat.Connection
|
||||||
|
|
||||||
err := retry.ExponentialBackoff(5, 200).On(func() error {
|
err := retry.ExponentialBackoff(5, 200).On(func() error {
|
||||||
rec = h.serverPicker.PickServer()
|
rawConn, err := dialer.Dial(ctx, rec.Destination)
|
||||||
rawConn, err := dialer.Dial(ctx, rec.Destination())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -85,7 +82,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
target := ob.Target
|
target := ob.Target
|
||||||
errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination().NetAddr())
|
errors.LogInfo(ctx, "tunneling request to ", target, " via ", rec.Destination.NetAddr())
|
||||||
|
|
||||||
command := protocol.RequestCommandTCP
|
command := protocol.RequestCommandTCP
|
||||||
if target.Network == net.Network_UDP {
|
if target.Network == net.Network_UDP {
|
||||||
@@ -95,7 +92,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
command = protocol.RequestCommandMux
|
command = protocol.RequestCommandMux
|
||||||
}
|
}
|
||||||
|
|
||||||
user := rec.PickUser()
|
user := rec.User
|
||||||
request := &protocol.RequestHeader{
|
request := &protocol.RequestHeader{
|
||||||
Version: encoding.Version,
|
Version: encoding.Version,
|
||||||
User: user,
|
User: user,
|
||||||
@@ -202,7 +199,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to read header").Base(err)
|
return errors.New("failed to read header").Base(err)
|
||||||
}
|
}
|
||||||
h.handleCommand(rec.Destination(), header.Command)
|
h.handleCommand(rec.Destination, header.Command)
|
||||||
|
|
||||||
bodyReader, err := session.DecodeResponseBody(request, reader)
|
bodyReader, err := session.DecodeResponseBody(request, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -423,20 +423,16 @@ func TestCommanderAddRemoveUser(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: u2.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: u2.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -600,20 +596,16 @@ func TestCommanderStats(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -94,17 +94,13 @@ func TestDokodemoTCP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -190,17 +186,13 @@ func TestDokodemoUDP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -170,17 +170,13 @@ func TestProxy(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: serverUserID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: serverUserID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -193,17 +189,13 @@ func TestProxy(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Tag: "proxy",
|
Tag: "proxy",
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(proxyPort),
|
||||||
Port: uint32(proxyPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: proxyUserID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: proxyUserID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -308,17 +300,13 @@ func TestProxyOverKCP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: serverUserID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: serverUserID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -334,17 +322,13 @@ func TestProxyOverKCP(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Tag: "proxy",
|
Tag: "proxy",
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(proxyPort),
|
||||||
Port: uint32(proxyPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: proxyUserID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: proxyUserID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -685,20 +669,16 @@ func TestDialXray(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -119,20 +119,16 @@ func TestVMessClosing(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -223,20 +219,16 @@ func TestZeroBuffer(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -155,20 +155,16 @@ func TestReverseProxy(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Tag: "reverse",
|
Tag: "reverse",
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(reversePort),
|
||||||
Port: uint32(reversePort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -348,20 +344,16 @@ func TestReverseProxyLongRunning(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Tag: "reverse",
|
Tag: "reverse",
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(reversePort),
|
||||||
Port: uint32(reversePort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -75,15 +75,11 @@ func TestShadowsocksChaCha20Poly1305TCP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: account,
|
||||||
{
|
|
||||||
Account: account,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -171,15 +167,11 @@ func TestShadowsocksAES256GCMTCP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: account,
|
||||||
{
|
|
||||||
Account: account,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -268,15 +260,11 @@ func TestShadowsocksAES128GCMUDP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: account,
|
||||||
{
|
|
||||||
Account: account,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -370,15 +358,11 @@ func TestShadowsocksAES128GCMUDPMux(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: account,
|
||||||
{
|
|
||||||
Account: account,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -455,15 +439,11 @@ func TestShadowsocksNone(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&shadowsocks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: account,
|
||||||
{
|
|
||||||
Account: account,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -73,18 +73,14 @@ func TestSocksBridgeTCP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&socks.Account{
|
||||||
{
|
Username: "Test Account",
|
||||||
Account: serial.ToTypedMessage(&socks.Account{
|
Password: "Test Password",
|
||||||
Username: "Test Account",
|
}),
|
||||||
Password: "Test Password",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -152,18 +148,14 @@ func TestSocksWithHttpRequest(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&http.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&http.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&http.Account{
|
||||||
{
|
Username: "Test Account",
|
||||||
Account: serial.ToTypedMessage(&http.Account{
|
Password: "Test Password",
|
||||||
Username: "Test Account",
|
}),
|
||||||
Password: "Test Password",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -256,18 +248,14 @@ func TestSocksBridageUDP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&socks.Account{
|
||||||
{
|
Username: "Test Account",
|
||||||
Account: serial.ToTypedMessage(&socks.Account{
|
Password: "Test Password",
|
||||||
Username: "Test Account",
|
}),
|
||||||
Password: "Test Password",
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -375,11 +363,9 @@ func TestSocksBridageUDPWithRouting(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
|
ProxySettings: serial.ToTypedMessage(&socks.ClientConfig{
|
||||||
Server: []*protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -89,17 +89,13 @@ func TestSimpleTLSConnection(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -204,17 +200,13 @@ func TestAutoIssuingCertificate(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -309,17 +301,13 @@ func TestTLSOverKCP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -409,17 +397,13 @@ func TestTLSOverWebSocket(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -525,17 +509,13 @@ func TestGRPC(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -641,17 +621,13 @@ func TestGRPCMultiMode(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -752,17 +728,13 @@ func TestSimpleTLSConnectionPinned(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -854,17 +826,13 @@ func TestSimpleTLSConnectionPinnedWrongCert(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -955,17 +923,13 @@ func TestUTLSConnectionPinned(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -1058,17 +1022,13 @@ func TestUTLSConnectionPinnedWrongCert(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -85,17 +85,13 @@ func TestHTTPConnectionHeader(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -94,17 +94,13 @@ func TestVless(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Vnext: []*protocol.ServerEndpoint{
|
Vnext: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vless.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -199,17 +195,13 @@ func TestVlessTls(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Vnext: []*protocol.ServerEndpoint{
|
Vnext: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vless.Account{
|
}),
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -322,18 +314,14 @@ func TestVlessXtlsVision(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Vnext: []*protocol.ServerEndpoint{
|
Vnext: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vless.Account{
|
Flow: vless.XRV,
|
||||||
Id: userID.String(),
|
}),
|
||||||
Flow: vless.XRV,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -456,18 +444,14 @@ func TestVlessXtlsVisionReality(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Vnext: []*protocol.ServerEndpoint{
|
Vnext: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vless.Account{
|
Flow: vless.XRV,
|
||||||
Id: userID.String(),
|
}),
|
||||||
Flow: vless.XRV,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -26,147 +26,6 @@ import (
|
|||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestVMessDynamicPort(t *testing.T) {
|
|
||||||
tcpServer := tcp.Server{
|
|
||||||
MsgProcessor: xor,
|
|
||||||
}
|
|
||||||
dest, err := tcpServer.Start()
|
|
||||||
common.Must(err)
|
|
||||||
defer tcpServer.Close()
|
|
||||||
|
|
||||||
userID := protocol.NewID(uuid.New())
|
|
||||||
|
|
||||||
retry := 1
|
|
||||||
serverPort := tcp.PickPort()
|
|
||||||
for {
|
|
||||||
serverConfig := &core.Config{
|
|
||||||
App: []*serial.TypedMessage{
|
|
||||||
serial.ToTypedMessage(&log.Config{
|
|
||||||
ErrorLogLevel: clog.Severity_Debug,
|
|
||||||
ErrorLogType: log.LogType_Console,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
Inbound: []*core.InboundHandlerConfig{
|
|
||||||
{
|
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
|
||||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
|
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&inbound.Config{
|
|
||||||
User: []*protocol.User{
|
|
||||||
{
|
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Detour: &inbound.DetourConfig{
|
|
||||||
To: "detour",
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
|
||||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort + 100)}},
|
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
|
||||||
Address: net.NewIPOrDomain(dest.Address),
|
|
||||||
Port: uint32(dest.Port),
|
|
||||||
Networks: []net.Network{net.Network_TCP},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
|
||||||
PortList: &net.PortList{
|
|
||||||
Range: []*net.PortRange{{From: uint32(serverPort + 1), To: uint32(serverPort + 99)}},
|
|
||||||
},
|
|
||||||
|
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
AllocationStrategy: &proxyman.AllocationStrategy{
|
|
||||||
Type: proxyman.AllocationStrategy_Random,
|
|
||||||
Concurrency: &proxyman.AllocationStrategy_AllocationStrategyConcurrency{
|
|
||||||
Value: 2,
|
|
||||||
},
|
|
||||||
Refresh: &proxyman.AllocationStrategy_AllocationStrategyRefresh{
|
|
||||||
Value: 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&inbound.Config{}),
|
|
||||||
Tag: "detour",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
|
||||||
{
|
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
server, _ := InitializeServerConfig(serverConfig)
|
|
||||||
if server != nil && WaitConnAvailableWithTest(t, testTCPConn(serverPort+100, 1024, time.Second*2)) {
|
|
||||||
defer CloseServer(server)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
retry += 1
|
|
||||||
if retry > 5 {
|
|
||||||
t.Fatal("All attempts failed to start server")
|
|
||||||
}
|
|
||||||
serverPort = tcp.PickPort()
|
|
||||||
}
|
|
||||||
|
|
||||||
clientPort := tcp.PickPort()
|
|
||||||
clientConfig := &core.Config{
|
|
||||||
App: []*serial.TypedMessage{
|
|
||||||
serial.ToTypedMessage(&log.Config{
|
|
||||||
ErrorLogLevel: clog.Severity_Debug,
|
|
||||||
ErrorLogType: log.LogType_Console,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
Inbound: []*core.InboundHandlerConfig{
|
|
||||||
{
|
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
|
||||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
|
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
|
||||||
Address: net.NewIPOrDomain(dest.Address),
|
|
||||||
Port: uint32(dest.Port),
|
|
||||||
Networks: []net.Network{net.Network_TCP},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
|
||||||
{
|
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
|
||||||
{
|
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
Port: uint32(serverPort),
|
|
||||||
User: []*protocol.User{
|
|
||||||
{
|
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
|
||||||
Id: userID.String(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
server, err := InitializeServerConfig(clientConfig)
|
|
||||||
common.Must(err)
|
|
||||||
defer CloseServer(server)
|
|
||||||
|
|
||||||
if !WaitConnAvailableWithTest(t, testTCPConn(clientPort, 1024, time.Second*2)) {
|
|
||||||
t.Fail()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVMessGCM(t *testing.T) {
|
func TestVMessGCM(t *testing.T) {
|
||||||
tcpServer := tcp.Server{
|
tcpServer := tcp.Server{
|
||||||
MsgProcessor: xor,
|
MsgProcessor: xor,
|
||||||
@@ -232,20 +91,16 @@ func TestVMessGCM(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -334,20 +189,16 @@ func TestVMessGCMReadv(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -439,20 +290,16 @@ func TestVMessGCMUDP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -538,20 +385,16 @@ func TestVMessChacha20(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_CHACHA20_POLY1305,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_CHACHA20_POLY1305,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -638,20 +481,16 @@ func TestVMessNone(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_NONE,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_NONE,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -740,20 +579,16 @@ func TestVMessKCP(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -866,20 +701,16 @@ func TestVMessKCPLarge(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -999,20 +830,16 @@ func TestVMessGCMMux(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -1126,20 +953,16 @@ func TestVMessGCMMuxUDP(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -1233,20 +1056,16 @@ func TestVMessZero(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_ZERO,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_ZERO,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -1332,21 +1151,17 @@ func TestVMessGCMLengthAuth(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
TestsEnabled: "AuthenticatedLength",
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
TestsEnabled: "AuthenticatedLength",
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -1436,21 +1251,17 @@ func TestVMessGCMLengthAuthPlusNoTerminationSignal(t *testing.T) {
|
|||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||||
Receiver: []*protocol.ServerEndpoint{
|
Receiver: &protocol.ServerEndpoint{
|
||||||
{
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
Port: uint32(serverPort),
|
||||||
Port: uint32(serverPort),
|
User: &protocol.User{
|
||||||
User: []*protocol.User{
|
Account: serial.ToTypedMessage(&vmess.Account{
|
||||||
{
|
Id: userID.String(),
|
||||||
Account: serial.ToTypedMessage(&vmess.Account{
|
SecuritySettings: &protocol.SecurityConfig{
|
||||||
Id: userID.String(),
|
Type: protocol.SecurityType_AES128_GCM,
|
||||||
SecuritySettings: &protocol.SecurityConfig{
|
|
||||||
Type: protocol.SecurityType_AES128_GCM,
|
|
||||||
},
|
|
||||||
TestsEnabled: "AuthenticatedLength|NoTerminationSignal",
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
TestsEnabled: "AuthenticatedLength|NoTerminationSignal",
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -75,8 +75,7 @@ func (c *UConn) HandshakeAddress() net.Address {
|
|||||||
func (c *UConn) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
func (c *UConn) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
||||||
if c.Config.Show {
|
if c.Config.Show {
|
||||||
localAddr := c.LocalAddr().String()
|
localAddr := c.LocalAddr().String()
|
||||||
curveID := *(*utls.CurveID)(unsafe.Pointer(reflect.ValueOf(c).Elem().FieldByName("curveID").UnsafeAddr()))
|
fmt.Printf("REALITY localAddr: %v\tis using X25519MLKEM768 for TLS' communication: %v\n", localAddr, c.HandshakeState.ServerHello.ServerShare.Group == utls.X25519MLKEM768)
|
||||||
fmt.Printf("REALITY localAddr: %v\tis using X25519MLKEM768 for TLS' communication: %v\n", localAddr, curveID == utls.X25519MLKEM768)
|
|
||||||
fmt.Printf("REALITY localAddr: %v\tis using ML-DSA-65 for cert's extra verification: %v\n", localAddr, len(c.Config.Mldsa65Verify) > 0)
|
fmt.Printf("REALITY localAddr: %v\tis using ML-DSA-65 for cert's extra verification: %v\n", localAddr, len(c.Config.Mldsa65Verify) > 0)
|
||||||
}
|
}
|
||||||
p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates")
|
p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates")
|
||||||
|
|||||||
Reference in New Issue
Block a user