mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 17:46:48 +08:00
Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a35d5719f4 | ||
![]() |
363e86c585 | ||
![]() |
b1c6471eeb | ||
![]() |
a931507dd6 | ||
![]() |
67c2a29065 | ||
![]() |
5f0642a671 | ||
![]() |
3fed0c773f | ||
![]() |
d7c5a0fc5f | ||
![]() |
781aaee21f | ||
![]() |
7970f240de | ||
![]() |
88ae774cce | ||
![]() |
c259e4e4a6 | ||
![]() |
3a8c5f38e8 | ||
![]() |
12c3908e8c | ||
![]() |
1919a1e86f | ||
![]() |
1b607ff874 | ||
![]() |
7496413e5c | ||
![]() |
297a9ae7bd | ||
![]() |
a247997e38 | ||
![]() |
6b1bf312d7 | ||
![]() |
c90affe7db | ||
![]() |
3d0feae462 | ||
![]() |
f04cb0b288 | ||
![]() |
9438517130 |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -28,3 +28,6 @@ errorgen
|
||||
*.dat
|
||||
.vscode
|
||||
/build_assets
|
||||
|
||||
# Output from dlv test
|
||||
**/debug.*
|
||||
|
@@ -77,6 +77,7 @@
|
||||
- Android
|
||||
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
||||
- [X-flutter](https://github.com/XTLS/X-flutter)
|
||||
- [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
|
||||
- iOS & macOS arm64
|
||||
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
||||
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
||||
|
@@ -10,8 +10,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/log"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
@@ -41,8 +41,14 @@ func (r *cachedReader) Cache(b *buf.Buffer) {
|
||||
if !mb.IsEmpty() {
|
||||
r.cache, _ = buf.MergeMulti(r.cache, mb)
|
||||
}
|
||||
b.Clear()
|
||||
rawBytes := b.Extend(buf.Size)
|
||||
cacheLen := r.cache.Len()
|
||||
if cacheLen <= b.Cap() {
|
||||
b.Clear()
|
||||
} else {
|
||||
b.Release()
|
||||
*b = *buf.NewWithSize(cacheLen)
|
||||
}
|
||||
rawBytes := b.Extend(cacheLen)
|
||||
n := r.cache.Copy(rawBytes)
|
||||
b.Resize(0, int32(n))
|
||||
r.Unlock()
|
||||
@@ -421,7 +427,11 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
|
||||
outTag := route.GetOutboundTag()
|
||||
if h := d.ohm.GetHandler(outTag); h != nil {
|
||||
isPickRoute = 2
|
||||
errors.LogInfo(ctx, "taking detour [", outTag, "] for [", destination, "]")
|
||||
if route.GetRuleTag() == "" {
|
||||
errors.LogInfo(ctx, "taking detour [", outTag, "] for [", destination, "]")
|
||||
} else {
|
||||
errors.LogInfo(ctx, "Hit route rule: [", route.GetRuleTag(), "] so taking detour [", outTag, "] for [", destination, "]")
|
||||
}
|
||||
handler = h
|
||||
} else {
|
||||
errors.LogWarning(ctx, "non existing outTag: ", outTag)
|
||||
|
@@ -35,7 +35,7 @@ type Sniffer struct {
|
||||
func NewSniffer(ctx context.Context) *Sniffer {
|
||||
ret := &Sniffer{
|
||||
sniffer: []protocolSnifferWithMetadata{
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b) }, false, net.Network_TCP},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b, c) }, false, net.Network_TCP},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
|
||||
|
@@ -15,7 +15,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/common/strmatcher"
|
||||
"github.com/xtls/xray-core/features"
|
||||
"github.com/xtls/xray-core/features/dns"
|
||||
)
|
||||
|
||||
@@ -96,7 +95,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
||||
geoipContainer := router.GeoIPMatcherContainer{}
|
||||
|
||||
for _, endpoint := range config.NameServers {
|
||||
features.PrintDeprecatedFeatureWarning("simple DNS server")
|
||||
errors.PrintDeprecatedFeatureWarning("simple DNS server", "")
|
||||
client, err := NewSimpleClient(ctx, endpoint, clientIP)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to create client").Base(err)
|
||||
|
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/strmatcher"
|
||||
"github.com/xtls/xray-core/features"
|
||||
"github.com/xtls/xray-core/features/dns"
|
||||
)
|
||||
|
||||
@@ -26,7 +25,7 @@ func NewStaticHosts(hosts []*Config_HostMapping, legacy map[string]*net.IPOrDoma
|
||||
}
|
||||
|
||||
if legacy != nil {
|
||||
features.PrintDeprecatedFeatureWarning("simple host mapping")
|
||||
errors.PrintDeprecatedFeatureWarning("simple host mapping", "")
|
||||
|
||||
for domain, ip := range legacy {
|
||||
matcher, err := strmatcher.Full.New(domain)
|
||||
|
@@ -365,7 +365,7 @@ func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||
} else {
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
if err != errRecordNotFound {
|
||||
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
|
||||
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||
return ips, err
|
||||
|
@@ -300,7 +300,7 @@ func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP ne
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||
} else {
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
if err != errRecordNotFound {
|
||||
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
|
||||
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||
return ips, err
|
||||
|
@@ -323,7 +323,7 @@ func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, clientIP net
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||
} else {
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
if err != errRecordNotFound {
|
||||
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
|
||||
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||
return ips, err
|
||||
|
@@ -250,7 +250,7 @@ func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||
} else {
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
if err != errRecordNotFound {
|
||||
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
|
||||
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||
return ips, err
|
||||
|
@@ -84,6 +84,7 @@ type Config struct {
|
||||
AccessLogType LogType `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,proto3,enum=xray.app.log.LogType" json:"access_log_type,omitempty"`
|
||||
AccessLogPath string `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath,proto3" json:"access_log_path,omitempty"`
|
||||
EnableDnsLog bool `protobuf:"varint,6,opt,name=enable_dns_log,json=enableDnsLog,proto3" json:"enable_dns_log,omitempty"`
|
||||
MaskAddress string `protobuf:"bytes,7,opt,name=mask_address,json=maskAddress,proto3" json:"mask_address,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
@@ -160,13 +161,20 @@ func (x *Config) GetEnableDnsLog() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *Config) GetMaskAddress() string {
|
||||
if x != nil {
|
||||
return x.MaskAddress
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_app_log_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_app_log_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x6c, 0x6f, 0x67, 0x1a, 0x14, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6c, 0x6f, 0x67,
|
||||
0x2f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x02, 0x0a, 0x06, 0x43,
|
||||
0x2f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xde, 0x02, 0x0a, 0x06, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6c,
|
||||
0x6f, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x4c, 0x6f, 0x67,
|
||||
@@ -186,15 +194,18 @@ var file_app_log_config_proto_rawDesc = []byte{
|
||||
0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x50, 0x61,
|
||||
0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x6e, 0x73,
|
||||
0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x65, 0x6e, 0x61, 0x62,
|
||||
0x6c, 0x65, 0x44, 0x6e, 0x73, 0x4c, 0x6f, 0x67, 0x2a, 0x35, 0x0a, 0x07, 0x4c, 0x6f, 0x67, 0x54,
|
||||
0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x0b, 0x0a,
|
||||
0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x69,
|
||||
0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x10, 0x03, 0x42,
|
||||
0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x6c, 0x6f, 0x67, 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, 0x6c, 0x6f, 0x67, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x6c, 0x65, 0x44, 0x6e, 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x73, 0x6b,
|
||||
0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
|
||||
0x6d, 0x61, 0x73, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2a, 0x35, 0x0a, 0x07, 0x4c,
|
||||
0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00,
|
||||
0x12, 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a,
|
||||
0x04, 0x46, 0x69, 0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
||||
0x10, 0x03, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||
0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 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, 0x6c, 0x6f, 0x67, 0xaa, 0x02, 0x0c, 0x58, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -23,4 +23,5 @@ message Config {
|
||||
LogType access_log_type = 4;
|
||||
string access_log_path = 5;
|
||||
bool enable_dns_log = 6;
|
||||
string mask_address= 7;
|
||||
}
|
||||
|
@@ -4,6 +4,9 @@ package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
@@ -101,18 +104,25 @@ func (g *Instance) Handle(msg log.Message) {
|
||||
return
|
||||
}
|
||||
|
||||
var Msg log.Message
|
||||
if g.config.MaskAddress != "" {
|
||||
Msg = &MaskedMsgWrapper{Message: msg, config: g.config}
|
||||
} else {
|
||||
Msg = msg
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case *log.AccessMessage:
|
||||
if g.accessLogger != nil {
|
||||
g.accessLogger.Handle(msg)
|
||||
g.accessLogger.Handle(Msg)
|
||||
}
|
||||
case *log.DNSLog:
|
||||
if g.dns && g.accessLogger != nil {
|
||||
g.accessLogger.Handle(msg)
|
||||
g.accessLogger.Handle(Msg)
|
||||
}
|
||||
case *log.GeneralMessage:
|
||||
if g.errorLogger != nil && msg.Severity <= g.config.ErrorLogLevel {
|
||||
g.errorLogger.Handle(msg)
|
||||
g.errorLogger.Handle(Msg)
|
||||
}
|
||||
default:
|
||||
// Swallow
|
||||
@@ -141,6 +151,56 @@ func (g *Instance) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MaskedMsgWrapper is to wrap the string() method to mask IP addresses in the log.
|
||||
type MaskedMsgWrapper struct {
|
||||
log.Message
|
||||
config *Config
|
||||
}
|
||||
|
||||
func (m *MaskedMsgWrapper) String() string {
|
||||
str := m.Message.String()
|
||||
|
||||
ipv4Regex := regexp.MustCompile(`(\d{1,3}\.){3}\d{1,3}`)
|
||||
ipv6Regex := regexp.MustCompile(`((?:[\da-fA-F]{0,4}:[\da-fA-F]{0,4}){2,7})(?:[\/\\%](\d{1,3}))?`)
|
||||
|
||||
// Process ipv4
|
||||
maskedMsg := ipv4Regex.ReplaceAllStringFunc(str, func(ip string) string {
|
||||
parts := strings.Split(ip, ".")
|
||||
switch m.config.MaskAddress {
|
||||
case "half":
|
||||
return fmt.Sprintf("%s.%s.*.*", parts[0], parts[1])
|
||||
case "quarter":
|
||||
return fmt.Sprintf("%s.*.*.*", parts[0])
|
||||
case "full":
|
||||
return "[Masked IPv4]"
|
||||
default:
|
||||
return ip
|
||||
}
|
||||
})
|
||||
|
||||
// process ipv6
|
||||
maskedMsg = ipv6Regex.ReplaceAllStringFunc(maskedMsg, func(ip string) string {
|
||||
parts := strings.Split(ip, ":")
|
||||
switch m.config.MaskAddress {
|
||||
case "half":
|
||||
if len(parts) >= 2 {
|
||||
return fmt.Sprintf("%s:%s::/32", parts[0], parts[1])
|
||||
}
|
||||
case "quarter":
|
||||
if len(parts) >= 1 {
|
||||
return fmt.Sprintf("%s::/16", parts[0])
|
||||
}
|
||||
case "full":
|
||||
return "Masked IPv6" // Do not use [Masked IPv6] like ipv4, or you will get "[[Masked IPv6]]" (v6 address already has [])
|
||||
default:
|
||||
return ip
|
||||
}
|
||||
return ip
|
||||
})
|
||||
|
||||
return maskedMsg
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return New(ctx, config.(*Config))
|
||||
|
@@ -156,7 +156,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
|
||||
for i := 0; i < rounds; i++ {
|
||||
delay := time.Duration(0)
|
||||
if duration > 0 {
|
||||
delay = time.Duration(dice.Roll(int(duration)))
|
||||
delay = time.Duration(dice.RollInt63n(int64(duration)))
|
||||
}
|
||||
time.AfterFunc(delay, func() {
|
||||
errors.LogDebug(h.ctx, "checking ", handler)
|
||||
|
@@ -19,21 +19,5 @@ func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig {
|
||||
return c.SniffingSettings
|
||||
}
|
||||
|
||||
if len(c.DomainOverride) > 0 {
|
||||
var p []string
|
||||
for _, kd := range c.DomainOverride {
|
||||
switch kd {
|
||||
case KnownProtocols_HTTP:
|
||||
p = append(p, "http")
|
||||
case KnownProtocols_TLS:
|
||||
p = append(p, "tls")
|
||||
}
|
||||
}
|
||||
return &SniffingConfig{
|
||||
Enabled: true,
|
||||
DestinationOverride: p,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.34.2
|
||||
// protoc v5.27.0
|
||||
// protoc v5.28.0
|
||||
// source: app/proxyman/config.proto
|
||||
|
||||
package proxyman
|
||||
@@ -23,52 +23,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type KnownProtocols int32
|
||||
|
||||
const (
|
||||
KnownProtocols_HTTP KnownProtocols = 0
|
||||
KnownProtocols_TLS KnownProtocols = 1
|
||||
)
|
||||
|
||||
// Enum value maps for KnownProtocols.
|
||||
var (
|
||||
KnownProtocols_name = map[int32]string{
|
||||
0: "HTTP",
|
||||
1: "TLS",
|
||||
}
|
||||
KnownProtocols_value = map[string]int32{
|
||||
"HTTP": 0,
|
||||
"TLS": 1,
|
||||
}
|
||||
)
|
||||
|
||||
func (x KnownProtocols) Enum() *KnownProtocols {
|
||||
p := new(KnownProtocols)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x KnownProtocols) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (KnownProtocols) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_app_proxyman_config_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (KnownProtocols) Type() protoreflect.EnumType {
|
||||
return &file_app_proxyman_config_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x KnownProtocols) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use KnownProtocols.Descriptor instead.
|
||||
func (KnownProtocols) EnumDescriptor() ([]byte, []int) {
|
||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type AllocationStrategy_Type int32
|
||||
|
||||
const (
|
||||
@@ -105,11 +59,11 @@ func (x AllocationStrategy_Type) String() string {
|
||||
}
|
||||
|
||||
func (AllocationStrategy_Type) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_app_proxyman_config_proto_enumTypes[1].Descriptor()
|
||||
return file_app_proxyman_config_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (AllocationStrategy_Type) Type() protoreflect.EnumType {
|
||||
return &file_app_proxyman_config_proto_enumTypes[1]
|
||||
return &file_app_proxyman_config_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x AllocationStrategy_Type) Number() protoreflect.EnumNumber {
|
||||
@@ -323,12 +277,7 @@ type ReceiverConfig struct {
|
||||
AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"`
|
||||
StreamSettings *internet.StreamConfig `protobuf:"bytes,4,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
||||
ReceiveOriginalDestination bool `protobuf:"varint,5,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"`
|
||||
// Override domains for the given protocol.
|
||||
// Deprecated. Use sniffing_settings.
|
||||
//
|
||||
// Deprecated: Marked as deprecated in app/proxyman/config.proto.
|
||||
DomainOverride []KnownProtocols `protobuf:"varint,7,rep,packed,name=domain_override,json=domainOverride,proto3,enum=xray.app.proxyman.KnownProtocols" json:"domain_override,omitempty"`
|
||||
SniffingSettings *SniffingConfig `protobuf:"bytes,8,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() {
|
||||
@@ -398,14 +347,6 @@ func (x *ReceiverConfig) GetReceiveOriginalDestination() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Deprecated: Marked as deprecated in app/proxyman/config.proto.
|
||||
func (x *ReceiverConfig) GetDomainOverride() []KnownProtocols {
|
||||
if x != nil {
|
||||
return x.DomainOverride
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ReceiverConfig) GetSniffingSettings() *SniffingConfig {
|
||||
if x != nil {
|
||||
return x.SniffingSettings
|
||||
@@ -817,7 +758,7 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
||||
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||
0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f,
|
||||
0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x8d, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
||||
0x4f, 0x6e, 0x6c, 0x79, 0x22, 0xbd, 0x03, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
||||
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f,
|
||||
0x6c, 0x69, 0x73, 0x74, 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, 0x50, 0x6f, 0x72,
|
||||
@@ -840,13 +781,8 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
||||
0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69,
|
||||
0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e,
|
||||
0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
||||
0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||
0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b, 0x6e, 0x6f, 0x77,
|
||||
0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e,
|
||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4e,
|
||||
0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
||||
0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e,
|
||||
0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e,
|
||||
0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04,
|
||||
@@ -894,16 +830,13 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
||||
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, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78,
|
||||
0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x2a, 0x23,
|
||||
0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73,
|
||||
0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x4c,
|
||||
0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26,
|
||||
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
|
||||
0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
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, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
||||
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||
0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -918,48 +851,46 @@ func file_app_proxyman_config_proto_rawDescGZIP() []byte {
|
||||
return file_app_proxyman_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
||||
var file_app_proxyman_config_proto_goTypes = []any{
|
||||
(KnownProtocols)(0), // 0: xray.app.proxyman.KnownProtocols
|
||||
(AllocationStrategy_Type)(0), // 1: xray.app.proxyman.AllocationStrategy.Type
|
||||
(*InboundConfig)(nil), // 2: xray.app.proxyman.InboundConfig
|
||||
(*AllocationStrategy)(nil), // 3: xray.app.proxyman.AllocationStrategy
|
||||
(*SniffingConfig)(nil), // 4: xray.app.proxyman.SniffingConfig
|
||||
(*ReceiverConfig)(nil), // 5: xray.app.proxyman.ReceiverConfig
|
||||
(*InboundHandlerConfig)(nil), // 6: xray.app.proxyman.InboundHandlerConfig
|
||||
(*OutboundConfig)(nil), // 7: xray.app.proxyman.OutboundConfig
|
||||
(*SenderConfig)(nil), // 8: xray.app.proxyman.SenderConfig
|
||||
(*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig
|
||||
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
||||
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
||||
(*net.PortList)(nil), // 12: xray.common.net.PortList
|
||||
(*net.IPOrDomain)(nil), // 13: xray.common.net.IPOrDomain
|
||||
(*internet.StreamConfig)(nil), // 14: xray.transport.internet.StreamConfig
|
||||
(*serial.TypedMessage)(nil), // 15: xray.common.serial.TypedMessage
|
||||
(*internet.ProxyConfig)(nil), // 16: xray.transport.internet.ProxyConfig
|
||||
(AllocationStrategy_Type)(0), // 0: xray.app.proxyman.AllocationStrategy.Type
|
||||
(*InboundConfig)(nil), // 1: xray.app.proxyman.InboundConfig
|
||||
(*AllocationStrategy)(nil), // 2: xray.app.proxyman.AllocationStrategy
|
||||
(*SniffingConfig)(nil), // 3: xray.app.proxyman.SniffingConfig
|
||||
(*ReceiverConfig)(nil), // 4: xray.app.proxyman.ReceiverConfig
|
||||
(*InboundHandlerConfig)(nil), // 5: xray.app.proxyman.InboundHandlerConfig
|
||||
(*OutboundConfig)(nil), // 6: xray.app.proxyman.OutboundConfig
|
||||
(*SenderConfig)(nil), // 7: xray.app.proxyman.SenderConfig
|
||||
(*MultiplexingConfig)(nil), // 8: xray.app.proxyman.MultiplexingConfig
|
||||
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 9: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
||||
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
||||
(*net.PortList)(nil), // 11: xray.common.net.PortList
|
||||
(*net.IPOrDomain)(nil), // 12: xray.common.net.IPOrDomain
|
||||
(*internet.StreamConfig)(nil), // 13: xray.transport.internet.StreamConfig
|
||||
(*serial.TypedMessage)(nil), // 14: xray.common.serial.TypedMessage
|
||||
(*internet.ProxyConfig)(nil), // 15: xray.transport.internet.ProxyConfig
|
||||
}
|
||||
var file_app_proxyman_config_proto_depIdxs = []int32{
|
||||
1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
||||
10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
||||
11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
||||
12, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
||||
13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
||||
3, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
|
||||
14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||
0, // 7: xray.app.proxyman.ReceiverConfig.domain_override:type_name -> xray.app.proxyman.KnownProtocols
|
||||
4, // 8: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
||||
15, // 9: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||
15, // 10: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||
13, // 11: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
||||
14, // 12: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||
16, // 13: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
||||
9, // 14: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
||||
15, // [15:15] is the sub-list for method output_type
|
||||
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
|
||||
0, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
||||
9, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
||||
10, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
||||
11, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
||||
12, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
||||
2, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
|
||||
13, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||
3, // 7: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
||||
14, // 8: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||
14, // 9: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||
12, // 10: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
||||
13, // 11: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||
15, // 12: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
||||
8, // 13: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
||||
14, // [14:14] is the sub-list for method output_type
|
||||
14, // [14:14] is the sub-list for method input_type
|
||||
14, // [14:14] is the sub-list for extension type_name
|
||||
14, // [14:14] is the sub-list for extension extendee
|
||||
0, // [0:14] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_app_proxyman_config_proto_init() }
|
||||
@@ -1094,7 +1025,7 @@ func file_app_proxyman_config_proto_init() {
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_app_proxyman_config_proto_rawDesc,
|
||||
NumEnums: 2,
|
||||
NumEnums: 1,
|
||||
NumMessages: 10,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
|
@@ -40,11 +40,6 @@ message AllocationStrategy {
|
||||
AllocationStrategyRefresh refresh = 3;
|
||||
}
|
||||
|
||||
enum KnownProtocols {
|
||||
HTTP = 0;
|
||||
TLS = 1;
|
||||
}
|
||||
|
||||
message SniffingConfig {
|
||||
// Whether or not to enable content sniffing on an inbound connection.
|
||||
bool enabled = 1;
|
||||
@@ -71,10 +66,7 @@ message ReceiverConfig {
|
||||
xray.transport.internet.StreamConfig stream_settings = 4;
|
||||
bool receive_original_destination = 5;
|
||||
reserved 6;
|
||||
// Override domains for the given protocol.
|
||||
// Deprecated. Use sniffing_settings.
|
||||
repeated KnownProtocols domain_override = 7 [ deprecated = true ];
|
||||
SniffingConfig sniffing_settings = 8;
|
||||
SniffingConfig sniffing_settings = 7;
|
||||
}
|
||||
|
||||
message InboundHandlerConfig {
|
||||
|
@@ -28,6 +28,10 @@ func (c routingContext) GetTargetPort() net.Port {
|
||||
return net.Port(c.RoutingContext.GetTargetPort())
|
||||
}
|
||||
|
||||
func (c routingContext) GetRuleTag() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetSkipDNSResolve is a mock implementation here to match the interface,
|
||||
// SkipDNSResolve is set from dns module, no use if coming from a protobuf object?
|
||||
// TODO: please confirm @Vigilans
|
||||
|
@@ -192,18 +192,28 @@ func (v NetworkMatcher) Apply(ctx routing.Context) bool {
|
||||
}
|
||||
|
||||
type UserMatcher struct {
|
||||
user []string
|
||||
user []string
|
||||
pattern []*regexp.Regexp
|
||||
}
|
||||
|
||||
func NewUserMatcher(users []string) *UserMatcher {
|
||||
usersCopy := make([]string, 0, len(users))
|
||||
patternsCopy := make([]*regexp.Regexp, 0, len(users))
|
||||
for _, user := range users {
|
||||
if len(user) > 0 {
|
||||
if len(user) > 7 && strings.HasPrefix(user, "regexp:") {
|
||||
if re, err := regexp.Compile(user[7:]); err != nil {
|
||||
patternsCopy = append(patternsCopy, re)
|
||||
}
|
||||
// Items of users slice with an invalid regexp syntax are ignored.
|
||||
continue
|
||||
}
|
||||
usersCopy = append(usersCopy, user)
|
||||
}
|
||||
}
|
||||
return &UserMatcher{
|
||||
user: usersCopy,
|
||||
user: usersCopy,
|
||||
pattern: patternsCopy,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +228,11 @@ func (v *UserMatcher) Apply(ctx routing.Context) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, re := range v.pattern {
|
||||
if re.MatchString(user) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
@@ -34,6 +34,7 @@ type Route struct {
|
||||
routing.Context
|
||||
outboundGroupTags []string
|
||||
outboundTag string
|
||||
ruleTag string
|
||||
}
|
||||
|
||||
// Init initializes the Router.
|
||||
@@ -89,7 +90,7 @@ func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Route{Context: ctx, outboundTag: tag}, nil
|
||||
return &Route{Context: ctx, outboundTag: tag, ruleTag: rule.RuleTag}, nil
|
||||
}
|
||||
|
||||
// AddRule implements routing.Router.
|
||||
@@ -239,6 +240,10 @@ func (r *Route) GetOutboundTag() string {
|
||||
return r.outboundTag
|
||||
}
|
||||
|
||||
func (r *Route) GetRuleTag() string {
|
||||
return r.ruleTag
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
r := new(Router)
|
||||
|
@@ -207,6 +207,21 @@ func (b *Buffer) Len() int32 {
|
||||
return b.end - b.start
|
||||
}
|
||||
|
||||
// Cap returns the capacity of the buffer content.
|
||||
func (b *Buffer) Cap() int32 {
|
||||
if b == nil {
|
||||
return 0
|
||||
}
|
||||
return int32(len(b.v))
|
||||
}
|
||||
|
||||
// NewWithSize creates a Buffer with 0 length and capacity with at least the given size.
|
||||
func NewWithSize(size int32) *Buffer {
|
||||
return &Buffer{
|
||||
v: bytespool.Alloc(size),
|
||||
}
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the buffer is empty.
|
||||
func (b *Buffer) IsEmpty() bool {
|
||||
return b.Len() == 0
|
||||
|
@@ -14,6 +14,14 @@ func Roll(n int) int {
|
||||
return rand.Intn(n)
|
||||
}
|
||||
|
||||
// RollInt63n returns a non-negative number between 0 (inclusive) and n (exclusive).
|
||||
func RollInt63n(n int64) int64 {
|
||||
if n == 1 {
|
||||
return 0
|
||||
}
|
||||
return rand.Int63n(n)
|
||||
}
|
||||
|
||||
// Roll returns a non-negative number between 0 (inclusive) and n (exclusive).
|
||||
func RollDeterministic(n int, seed int64) int {
|
||||
if n == 1 {
|
||||
|
25
common/errors/feature_errors.go
Normal file
25
common/errors/feature_errors.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// PrintDeprecatedFeatureWarning prints a warning for deprecated and going to be removed feature.
|
||||
// Do not remove this function even there is no reference to it.
|
||||
func PrintDeprecatedFeatureWarning(feature string, migrateFeature string) {
|
||||
if len(migrateFeature) > 0 {
|
||||
LogWarning(context.Background(), "This feature " + feature + " is deprecated and being migrated to " + migrateFeature + ". Please update your config(s) according to release note and documentation before removal.")
|
||||
} else {
|
||||
LogWarning(context.Background(), "This feature " + feature + " is deprecated. Please update your config(s) according to release note and documentation before removal.")
|
||||
}
|
||||
}
|
||||
|
||||
// PrintRemovedFeatureError prints an error message for removed feature then return an error. And after long enough time the message can also be removed, uses as an indicator.
|
||||
// Do not remove this function even there is no reference to it.
|
||||
func PrintRemovedFeatureError(feature string, migrateFeature string) (error) {
|
||||
if len(migrateFeature) > 0 {
|
||||
return New("The feature " + feature + " has been removed and migrated to " + migrateFeature + ". Please update your config(s) according to release note and documentation.")
|
||||
} else {
|
||||
return New("The feature " + feature + " has been removed. Please update your config(s) according to release note and documentation.")
|
||||
}
|
||||
}
|
@@ -2,11 +2,13 @@ package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
)
|
||||
|
||||
type version byte
|
||||
@@ -56,7 +58,14 @@ func beginWithHTTPMethod(b []byte) error {
|
||||
return errNotHTTPMethod
|
||||
}
|
||||
|
||||
func SniffHTTP(b []byte) (*SniffHeader, error) {
|
||||
func SniffHTTP(b []byte, c context.Context) (*SniffHeader, error) {
|
||||
content := session.ContentFromContext(c)
|
||||
ShouldSniffAttr := true
|
||||
// If content.Attributes have information, that means it comes from HTTP inbound PlainHTTP mode.
|
||||
// It will set attributes, so skip it.
|
||||
if content == nil || len(content.Attributes) != 0 {
|
||||
ShouldSniffAttr = false
|
||||
}
|
||||
if err := beginWithHTTPMethod(b); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -76,8 +85,12 @@ func SniffHTTP(b []byte) (*SniffHeader, error) {
|
||||
continue
|
||||
}
|
||||
key := strings.ToLower(string(parts[0]))
|
||||
value := string(bytes.TrimSpace(parts[1]))
|
||||
if ShouldSniffAttr {
|
||||
content.SetAttribute(key, value) // Put header in attribute
|
||||
}
|
||||
if key == "host" {
|
||||
rawHost := strings.ToLower(string(bytes.TrimSpace(parts[1])))
|
||||
rawHost := strings.ToLower(value)
|
||||
dest, err := ParseHost(rawHost, net.Port(80))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -85,6 +98,16 @@ func SniffHTTP(b []byte) (*SniffHeader, error) {
|
||||
sh.host = dest.Address.String()
|
||||
}
|
||||
}
|
||||
// Parse request line
|
||||
// Request line is like this
|
||||
// "GET /homo/114514 HTTP/1.1"
|
||||
if len(headers) > 0 && ShouldSniffAttr {
|
||||
RequestLineParts := bytes.Split(headers[0], []byte{' '})
|
||||
if len(RequestLineParts) == 3 {
|
||||
content.SetAttribute(":method", string(RequestLineParts[0]))
|
||||
content.SetAttribute(":path", string(RequestLineParts[1]))
|
||||
}
|
||||
}
|
||||
|
||||
if len(sh.host) > 0 {
|
||||
return sh, nil
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package http_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/xtls/xray-core/common/protocol/http"
|
||||
@@ -88,7 +89,7 @@ first_name=John&last_name=Doe&action=Submit`,
|
||||
}
|
||||
|
||||
for _, test := range cases {
|
||||
header, err := SniffHTTP([]byte(test.input))
|
||||
header, err := SniffHTTP([]byte(test.input), context.TODO())
|
||||
if test.err {
|
||||
if err == nil {
|
||||
t.Errorf("Expect error but nil, in test: %v", test)
|
||||
|
@@ -47,206 +47,224 @@ var (
|
||||
)
|
||||
|
||||
func SniffQUIC(b []byte) (*SniffHeader, error) {
|
||||
buffer := buf.FromBytes(b)
|
||||
typeByte, err := buffer.ReadByte()
|
||||
if err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
isLongHeader := typeByte&0x80 > 0
|
||||
if !isLongHeader || typeByte&0x40 == 0 {
|
||||
return nil, errNotQuicInitial
|
||||
}
|
||||
// Crypto data separated across packets
|
||||
cryptoLen := 0
|
||||
cryptoData := bytespool.Alloc(int32(len(b)))
|
||||
defer bytespool.Free(cryptoData)
|
||||
|
||||
vb, err := buffer.ReadBytes(4)
|
||||
if err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
// Parse QUIC packets
|
||||
for len(b) > 0 {
|
||||
buffer := buf.FromBytes(b)
|
||||
typeByte, err := buffer.ReadByte()
|
||||
if err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
versionNumber := binary.BigEndian.Uint32(vb)
|
||||
isLongHeader := typeByte&0x80 > 0
|
||||
if !isLongHeader || typeByte&0x40 == 0 {
|
||||
return nil, errNotQuicInitial
|
||||
}
|
||||
|
||||
if versionNumber != 0 && typeByte&0x40 == 0 {
|
||||
return nil, errNotQuic
|
||||
} else if versionNumber != versionDraft29 && versionNumber != version1 {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
vb, err := buffer.ReadBytes(4)
|
||||
if err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
if (typeByte&0x30)>>4 != 0x0 {
|
||||
return nil, errNotQuicInitial
|
||||
}
|
||||
versionNumber := binary.BigEndian.Uint32(vb)
|
||||
if versionNumber != 0 && typeByte&0x40 == 0 {
|
||||
return nil, errNotQuic
|
||||
} else if versionNumber != versionDraft29 && versionNumber != version1 {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
var destConnID []byte
|
||||
if l, err := buffer.ReadByte(); err != nil {
|
||||
return nil, errNotQuic
|
||||
} else if destConnID, err = buffer.ReadBytes(int32(l)); err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
packetType := (typeByte & 0x30) >> 4
|
||||
isQuicInitial := packetType == 0x0
|
||||
|
||||
if l, err := buffer.ReadByte(); err != nil {
|
||||
return nil, errNotQuic
|
||||
} else if common.Error2(buffer.ReadBytes(int32(l))) != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
var destConnID []byte
|
||||
if l, err := buffer.ReadByte(); err != nil {
|
||||
return nil, errNotQuic
|
||||
} else if destConnID, err = buffer.ReadBytes(int32(l)); err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
tokenLen, err := quicvarint.Read(buffer)
|
||||
if err != nil || tokenLen > uint64(len(b)) {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
if l, err := buffer.ReadByte(); err != nil {
|
||||
return nil, errNotQuic
|
||||
} else if common.Error2(buffer.ReadBytes(int32(l))) != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
if _, err = buffer.ReadBytes(int32(tokenLen)); err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
tokenLen, err := quicvarint.Read(buffer)
|
||||
if err != nil || tokenLen > uint64(len(b)) {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
packetLen, err := quicvarint.Read(buffer)
|
||||
if err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
if _, err = buffer.ReadBytes(int32(tokenLen)); err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
hdrLen := len(b) - int(buffer.Len())
|
||||
packetLen, err := quicvarint.Read(buffer)
|
||||
if err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
origPNBytes := make([]byte, 4)
|
||||
copy(origPNBytes, b[hdrLen:hdrLen+4])
|
||||
hdrLen := len(b) - int(buffer.Len())
|
||||
if len(b) < hdrLen+int(packetLen) {
|
||||
return nil, common.ErrNoClue // Not enough data to read as a QUIC packet. QUIC is UDP-based, so this is unlikely to happen.
|
||||
}
|
||||
|
||||
var salt []byte
|
||||
if versionNumber == version1 {
|
||||
salt = quicSalt
|
||||
} else {
|
||||
salt = quicSaltOld
|
||||
}
|
||||
initialSecret := hkdf.Extract(crypto.SHA256.New, destConnID, salt)
|
||||
secret := hkdfExpandLabel(crypto.SHA256, initialSecret, []byte{}, "client in", crypto.SHA256.Size())
|
||||
hpKey := hkdfExpandLabel(initialSuite.Hash, secret, []byte{}, "quic hp", initialSuite.KeyLen)
|
||||
block, err := aes.NewCipher(hpKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
restPayload := b[hdrLen+int(packetLen):]
|
||||
if !isQuicInitial { // Skip this packet if it's not initial packet
|
||||
b = restPayload
|
||||
continue
|
||||
}
|
||||
|
||||
cache := buf.New()
|
||||
defer cache.Release()
|
||||
origPNBytes := make([]byte, 4)
|
||||
copy(origPNBytes, b[hdrLen:hdrLen+4])
|
||||
|
||||
mask := cache.Extend(int32(block.BlockSize()))
|
||||
block.Encrypt(mask, b[hdrLen+4:hdrLen+4+16])
|
||||
b[0] ^= mask[0] & 0xf
|
||||
for i := range b[hdrLen : hdrLen+4] {
|
||||
b[hdrLen+i] ^= mask[i+1]
|
||||
}
|
||||
packetNumberLength := b[0]&0x3 + 1
|
||||
if packetNumberLength != 1 {
|
||||
return nil, errNotQuicInitial
|
||||
}
|
||||
var packetNumber uint32
|
||||
{
|
||||
n, err := buffer.ReadByte()
|
||||
var salt []byte
|
||||
if versionNumber == version1 {
|
||||
salt = quicSalt
|
||||
} else {
|
||||
salt = quicSaltOld
|
||||
}
|
||||
initialSecret := hkdf.Extract(crypto.SHA256.New, destConnID, salt)
|
||||
secret := hkdfExpandLabel(crypto.SHA256, initialSecret, []byte{}, "client in", crypto.SHA256.Size())
|
||||
hpKey := hkdfExpandLabel(initialSuite.Hash, secret, []byte{}, "quic hp", initialSuite.KeyLen)
|
||||
block, err := aes.NewCipher(hpKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packetNumber = uint32(n)
|
||||
}
|
||||
|
||||
if packetNumber != 0 && packetNumber != 1 {
|
||||
return nil, errNotQuicInitial
|
||||
}
|
||||
cache := buf.New()
|
||||
defer cache.Release()
|
||||
|
||||
extHdrLen := hdrLen + int(packetNumberLength)
|
||||
copy(b[extHdrLen:hdrLen+4], origPNBytes[packetNumberLength:])
|
||||
data := b[extHdrLen : int(packetLen)+hdrLen]
|
||||
|
||||
key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
|
||||
iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
|
||||
cipher := AEADAESGCMTLS13(key, iv)
|
||||
nonce := cache.Extend(int32(cipher.NonceSize()))
|
||||
binary.BigEndian.PutUint64(nonce[len(nonce)-8:], uint64(packetNumber))
|
||||
decrypted, err := cipher.Open(b[extHdrLen:extHdrLen], nonce, data, b[:extHdrLen])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer = buf.FromBytes(decrypted)
|
||||
|
||||
cryptoLen := uint(0)
|
||||
cryptoData := bytespool.Alloc(buffer.Len())
|
||||
defer bytespool.Free(cryptoData)
|
||||
for i := 0; !buffer.IsEmpty(); i++ {
|
||||
frameType := byte(0x0) // Default to PADDING frame
|
||||
for frameType == 0x0 && !buffer.IsEmpty() {
|
||||
frameType, _ = buffer.ReadByte()
|
||||
mask := cache.Extend(int32(block.BlockSize()))
|
||||
block.Encrypt(mask, b[hdrLen+4:hdrLen+4+16])
|
||||
b[0] ^= mask[0] & 0xf
|
||||
for i := range b[hdrLen : hdrLen+4] {
|
||||
b[hdrLen+i] ^= mask[i+1]
|
||||
}
|
||||
switch frameType {
|
||||
case 0x00: // PADDING frame
|
||||
case 0x01: // PING frame
|
||||
case 0x02, 0x03: // ACK frame
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: Largest Acknowledged
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ACK Delay
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
ackRangeCount, err := quicvarint.Read(buffer) // Field: ACK Range Count
|
||||
if err != nil {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: First ACK Range
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
for i := 0; i < int(ackRangeCount); i++ { // Field: ACK Range
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ACK Range -> Gap
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ACK Range -> ACK Range Length
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
if frameType == 0x03 {
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ECN Counts -> ECT0 Count
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ECN Counts -> ECT1 Count
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { //nolint:misspell // Field: ECN Counts -> ECT-CE Count
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
case 0x06: // CRYPTO frame, we will use this frame
|
||||
offset, err := quicvarint.Read(buffer) // Field: Offset
|
||||
if err != nil {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
length, err := quicvarint.Read(buffer) // Field: Length
|
||||
if err != nil || length > uint64(buffer.Len()) {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if cryptoLen < uint(offset+length) {
|
||||
cryptoLen = uint(offset + length)
|
||||
}
|
||||
if _, err := buffer.Read(cryptoData[offset : offset+length]); err != nil { // Field: Crypto Data
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
case 0x1c: // CONNECTION_CLOSE frame, only 0x1c is permitted in initial packet
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: Error Code
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: Frame Type
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
length, err := quicvarint.Read(buffer) // Field: Reason Phrase Length
|
||||
if err != nil {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err := buffer.ReadBytes(int32(length)); err != nil { // Field: Reason Phrase
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
default:
|
||||
// Only above frame types are permitted in initial packet.
|
||||
// See https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2.2-8
|
||||
packetNumberLength := b[0]&0x3 + 1
|
||||
if packetNumberLength != 1 {
|
||||
return nil, errNotQuicInitial
|
||||
}
|
||||
}
|
||||
var packetNumber uint32
|
||||
{
|
||||
n, err := buffer.ReadByte()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
packetNumber = uint32(n)
|
||||
}
|
||||
|
||||
tlsHdr := &ptls.SniffHeader{}
|
||||
err = ptls.ReadClientHello(cryptoData[:cryptoLen], tlsHdr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
extHdrLen := hdrLen + int(packetNumberLength)
|
||||
copy(b[extHdrLen:hdrLen+4], origPNBytes[packetNumberLength:])
|
||||
data := b[extHdrLen : int(packetLen)+hdrLen]
|
||||
|
||||
key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
|
||||
iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
|
||||
cipher := AEADAESGCMTLS13(key, iv)
|
||||
nonce := cache.Extend(int32(cipher.NonceSize()))
|
||||
binary.BigEndian.PutUint64(nonce[len(nonce)-8:], uint64(packetNumber))
|
||||
decrypted, err := cipher.Open(b[extHdrLen:extHdrLen], nonce, data, b[:extHdrLen])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer = buf.FromBytes(decrypted)
|
||||
for i := 0; !buffer.IsEmpty(); i++ {
|
||||
frameType := byte(0x0) // Default to PADDING frame
|
||||
for frameType == 0x0 && !buffer.IsEmpty() {
|
||||
frameType, _ = buffer.ReadByte()
|
||||
}
|
||||
switch frameType {
|
||||
case 0x00: // PADDING frame
|
||||
case 0x01: // PING frame
|
||||
case 0x02, 0x03: // ACK frame
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: Largest Acknowledged
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ACK Delay
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
ackRangeCount, err := quicvarint.Read(buffer) // Field: ACK Range Count
|
||||
if err != nil {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: First ACK Range
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
for i := 0; i < int(ackRangeCount); i++ { // Field: ACK Range
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ACK Range -> Gap
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ACK Range -> ACK Range Length
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
if frameType == 0x03 {
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ECN Counts -> ECT0 Count
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: ECN Counts -> ECT1 Count
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { //nolint:misspell // Field: ECN Counts -> ECT-CE Count
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
}
|
||||
case 0x06: // CRYPTO frame, we will use this frame
|
||||
offset, err := quicvarint.Read(buffer) // Field: Offset
|
||||
if err != nil {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
length, err := quicvarint.Read(buffer) // Field: Length
|
||||
if err != nil || length > uint64(buffer.Len()) {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if cryptoLen < int(offset+length) {
|
||||
cryptoLen = int(offset + length)
|
||||
if len(cryptoData) < cryptoLen {
|
||||
newCryptoData := bytespool.Alloc(int32(cryptoLen))
|
||||
copy(newCryptoData, cryptoData)
|
||||
bytespool.Free(cryptoData)
|
||||
cryptoData = newCryptoData
|
||||
}
|
||||
}
|
||||
if _, err := buffer.Read(cryptoData[offset : offset+length]); err != nil { // Field: Crypto Data
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
case 0x1c: // CONNECTION_CLOSE frame, only 0x1c is permitted in initial packet
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: Error Code
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err = quicvarint.Read(buffer); err != nil { // Field: Frame Type
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
length, err := quicvarint.Read(buffer) // Field: Reason Phrase Length
|
||||
if err != nil {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
if _, err := buffer.ReadBytes(int32(length)); err != nil { // Field: Reason Phrase
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
default:
|
||||
// Only above frame types are permitted in initial packet.
|
||||
// See https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2.2-8
|
||||
return nil, errNotQuicInitial
|
||||
}
|
||||
}
|
||||
|
||||
tlsHdr := &ptls.SniffHeader{}
|
||||
err = ptls.ReadClientHello(cryptoData[:cryptoLen], tlsHdr)
|
||||
if err != nil {
|
||||
// The crypto data may have not been fully recovered in current packets,
|
||||
// So we continue to sniff rest packets.
|
||||
b = restPayload
|
||||
continue
|
||||
}
|
||||
return &SniffHeader{domain: tlsHdr.Domain()}, nil
|
||||
}
|
||||
return &SniffHeader{domain: tlsHdr.Domain()}, nil
|
||||
return nil, common.ErrNoClue
|
||||
}
|
||||
|
||||
func hkdfExpandLabel(hash crypto.Hash, secret, context []byte, label string, length int) []byte {
|
||||
|
@@ -1,14 +1,13 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.34.2
|
||||
// protoc v5.27.0
|
||||
// protoc v5.28.0
|
||||
// source: core/config.proto
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
serial "github.com/xtls/xray-core/common/serial"
|
||||
global "github.com/xtls/xray-core/transport/global"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
@@ -38,12 +37,6 @@ type Config struct {
|
||||
// implement the Feature interface, and its config type must be registered
|
||||
// through common.RegisterConfig.
|
||||
App []*serial.TypedMessage `protobuf:"bytes,4,rep,name=app,proto3" json:"app,omitempty"`
|
||||
// Transport settings.
|
||||
// Deprecated. Each inbound and outbound should choose their own transport
|
||||
// config. Date to remove: 2020-01-13
|
||||
//
|
||||
// Deprecated: Marked as deprecated in core/config.proto.
|
||||
Transport *global.Config `protobuf:"bytes,5,opt,name=transport,proto3" json:"transport,omitempty"`
|
||||
// Configuration for extensions. The config may not work if corresponding
|
||||
// extension is not loaded into Xray. Xray will ignore such config during
|
||||
// initialization.
|
||||
@@ -103,14 +96,6 @@ func (x *Config) GetApp() []*serial.TypedMessage {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated: Marked as deprecated in core/config.proto.
|
||||
func (x *Config) GetTransport() *global.Config {
|
||||
if x != nil {
|
||||
return x.Transport
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetExtension() []*serial.TypedMessage {
|
||||
if x != nil {
|
||||
return x.Extension
|
||||
@@ -278,60 +263,54 @@ var file_core_config_proto_rawDesc = []byte{
|
||||
0x6f, 0x74, 0x6f, 0x12, 0x09, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 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, 0x6f, 0x74,
|
||||
0x6f, 0x1a, 0x1d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x6c, 0x6f,
|
||||
0x62, 0x61, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x22, 0xb5, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x07, 0x69,
|
||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x69,
|
||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e,
|
||||
0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x62,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x12, 0x32, 0x0a, 0x03, 0x61, 0x70, 0x70, 0x18, 0x04, 0x20, 0x03, 0x28,
|
||||
0x6f, 0x22, 0xfb, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x07,
|
||||
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07,
|
||||
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61,
|
||||
0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74,
|
||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x32, 0x0a, 0x03, 0x61, 0x70, 0x70, 0x18, 0x04, 0x20, 0x03,
|
||||
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, 0x03, 0x61, 0x70, 0x70, 0x12, 0x3e, 0x0a, 0x09, 0x65, 0x78, 0x74,
|
||||
0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x03, 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, 0x09,
|
||||
0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 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, 0x03, 0x61, 0x70, 0x70, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e,
|
||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
||||
0x72, 0x74, 0x12, 0x3e, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18,
|
||||
0x06, 0x20, 0x03, 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, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69,
|
||||
0x6f, 0x6e, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 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, 0xef, 0x01, 0x0a, 0x15,
|
||||
0x4f, 0x75, 0x74, 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, 0x49, 0x0a, 0x0f, 0x73, 0x65, 0x6e, 0x64, 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, 0x0e, 0x73, 0x65, 0x6e, 0x64, 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, 0x12, 0x16, 0x0a, 0x06, 0x65,
|
||||
0x78, 0x70, 0x69, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x65, 0x78, 0x70,
|
||||
0x69, 0x72, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x3d, 0x0a,
|
||||
0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x50, 0x01,
|
||||
0x5a, 0x1e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c,
|
||||
0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x72, 0x65,
|
||||
0xaa, 0x02, 0x09, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||
0x67, 0x73, 0x22, 0xef, 0x01, 0x0a, 0x15, 0x4f, 0x75, 0x74, 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, 0x49,
|
||||
0x0a, 0x0f, 0x73, 0x65, 0x6e, 0x64, 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, 0x0e, 0x73, 0x65, 0x6e, 0x64, 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, 0x12, 0x16, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x06, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x42, 0x3d, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x63, 0x6f, 0x72, 0x65, 0x50, 0x01, 0x5a, 0x1e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x2f, 0x63, 0x6f, 0x72, 0x65, 0xaa, 0x02, 0x09, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x43,
|
||||
0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -352,23 +331,21 @@ var file_core_config_proto_goTypes = []any{
|
||||
(*InboundHandlerConfig)(nil), // 1: xray.core.InboundHandlerConfig
|
||||
(*OutboundHandlerConfig)(nil), // 2: xray.core.OutboundHandlerConfig
|
||||
(*serial.TypedMessage)(nil), // 3: xray.common.serial.TypedMessage
|
||||
(*global.Config)(nil), // 4: xray.transport.Config
|
||||
}
|
||||
var file_core_config_proto_depIdxs = []int32{
|
||||
1, // 0: xray.core.Config.inbound:type_name -> xray.core.InboundHandlerConfig
|
||||
2, // 1: xray.core.Config.outbound:type_name -> xray.core.OutboundHandlerConfig
|
||||
3, // 2: xray.core.Config.app:type_name -> xray.common.serial.TypedMessage
|
||||
4, // 3: xray.core.Config.transport:type_name -> xray.transport.Config
|
||||
3, // 4: xray.core.Config.extension:type_name -> xray.common.serial.TypedMessage
|
||||
3, // 5: xray.core.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||
3, // 6: xray.core.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||
3, // 7: xray.core.OutboundHandlerConfig.sender_settings:type_name -> xray.common.serial.TypedMessage
|
||||
3, // 8: xray.core.OutboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||
9, // [9:9] is the sub-list for method output_type
|
||||
9, // [9:9] is the sub-list for method input_type
|
||||
9, // [9:9] is the sub-list for extension type_name
|
||||
9, // [9:9] is the sub-list for extension extendee
|
||||
0, // [0:9] is the sub-list for field type_name
|
||||
3, // 3: xray.core.Config.extension:type_name -> xray.common.serial.TypedMessage
|
||||
3, // 4: xray.core.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||
3, // 5: xray.core.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||
3, // 6: xray.core.OutboundHandlerConfig.sender_settings:type_name -> xray.common.serial.TypedMessage
|
||||
3, // 7: xray.core.OutboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||
8, // [8:8] is the sub-list for method output_type
|
||||
8, // [8:8] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_core_config_proto_init() }
|
||||
|
@@ -7,7 +7,6 @@ option java_package = "com.xray.core";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "common/serial/typed_message.proto";
|
||||
import "transport/global/config.proto";
|
||||
|
||||
// Config is the master config of Xray. Xray takes this config as input and
|
||||
// functions accordingly.
|
||||
@@ -26,15 +25,15 @@ message Config {
|
||||
// through common.RegisterConfig.
|
||||
repeated xray.common.serial.TypedMessage app = 4;
|
||||
|
||||
// Transport settings.
|
||||
// Deprecated. Each inbound and outbound should choose their own transport
|
||||
// config. Date to remove: 2020-01-13
|
||||
xray.transport.Config transport = 5 [deprecated = true];
|
||||
|
||||
// Configuration for extensions. The config may not work if corresponding
|
||||
// extension is not loaded into Xray. Xray will ignore such config during
|
||||
// initialization.
|
||||
repeated xray.common.serial.TypedMessage extension = 6;
|
||||
|
||||
// Transport settings.
|
||||
// Deprecated. Each inbound and outbound should choose their own transport
|
||||
// config. Date to remove: 2020-01-13
|
||||
// xray.transport.Config transport = 5 [deprecated = true];
|
||||
}
|
||||
|
||||
// InboundHandlerConfig is the configuration for inbound handler.
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
var (
|
||||
Version_x byte = 24
|
||||
Version_y byte = 9
|
||||
Version_z byte = 7
|
||||
Version_z byte = 16
|
||||
)
|
||||
|
||||
var (
|
||||
|
@@ -185,13 +185,6 @@ func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
|
||||
server.ctx = context.WithValue(server.ctx, "cone",
|
||||
platform.NewEnvFlag(platform.UseCone).GetValue(func() string { return "" }) != "true")
|
||||
|
||||
if config.Transport != nil {
|
||||
features.PrintDeprecatedFeatureWarning("global transport settings")
|
||||
}
|
||||
if err := config.Transport.Apply(); err != nil {
|
||||
return true, err
|
||||
}
|
||||
|
||||
for _, appSettings := range config.App {
|
||||
settings, err := appSettings.GetInstance()
|
||||
if err != nil {
|
||||
|
@@ -1,22 +1,12 @@
|
||||
package features
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||
|
||||
// Feature is the interface for Xray features. All features must implement this interface.
|
||||
// All existing features have an implementation in app directory. These features can be replaced by third-party ones.
|
||||
type Feature interface {
|
||||
common.HasType
|
||||
common.Runnable
|
||||
}
|
||||
|
||||
// PrintDeprecatedFeatureWarning prints a warning for deprecated feature.
|
||||
func PrintDeprecatedFeatureWarning(feature string) {
|
||||
errors.LogInfo(context.Background(), "You are using a deprecated feature: " + feature + ". Please update your config file with latest configuration format, or update your client software.")
|
||||
}
|
||||
|
@@ -30,6 +30,9 @@ type Route interface {
|
||||
|
||||
// GetOutboundTag returns the tag of the outbound the connection was dispatched to.
|
||||
GetOutboundTag() string
|
||||
|
||||
// GetRuleTag returns the matching rule tag for debugging if exists
|
||||
GetRuleTag() string
|
||||
}
|
||||
|
||||
// RouterType return the type of Router interface. Can be used to implement common.HasType.
|
||||
|
4
go.mod
4
go.mod
@@ -14,7 +14,7 @@ require (
|
||||
github.com/pires/go-proxyproto v0.7.0
|
||||
github.com/quic-go/quic-go v0.46.0
|
||||
github.com/refraction-networking/utls v1.6.7
|
||||
github.com/sagernet/sing v0.4.1
|
||||
github.com/sagernet/sing v0.4.3
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771
|
||||
github.com/stretchr/testify v1.9.0
|
||||
@@ -27,7 +27,7 @@ require (
|
||||
golang.org/x/sync v0.8.0
|
||||
golang.org/x/sys v0.25.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
google.golang.org/grpc v1.66.0
|
||||
google.golang.org/grpc v1.66.2
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489
|
||||
h12.io/socks v1.0.3
|
||||
|
8
go.sum
8
go.sum
@@ -54,8 +54,8 @@ github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B
|
||||
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
||||
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/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk=
|
||||
github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
|
||||
github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8=
|
||||
github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4=
|
||||
@@ -127,8 +127,8 @@ 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=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||
google.golang.org/grpc v1.66.0 h1:DibZuoBznOxbDQxRINckZcUvnCEvrW9pcWIE2yF9r1c=
|
||||
google.golang.org/grpc v1.66.0/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/grpc v1.66.2 h1:3QdXkuq3Bkh7w+ywLdLvM56cmGvQHUMZpiCzt6Rqaoo=
|
||||
google.golang.org/grpc v1.66.2/go.mod h1:s3/l6xSSCURdVfAnL+TqCNMyTDAGN6+lZeVxnZR128Y=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
|
@@ -13,6 +13,7 @@ type DNSOutboundConfig struct {
|
||||
Port uint16 `json:"port"`
|
||||
UserLevel uint32 `json:"userLevel"`
|
||||
NonIPQuery string `json:"nonIPQuery"`
|
||||
BlockTypes []int32 `json:"blockTypes"`
|
||||
}
|
||||
|
||||
func (c *DNSOutboundConfig) Build() (proto.Message, error) {
|
||||
@@ -34,5 +35,6 @@ func (c *DNSOutboundConfig) Build() (proto.Message, error) {
|
||||
return nil, errors.New(`unknown "nonIPQuery": `, c.NonIPQuery)
|
||||
}
|
||||
config.Non_IPQuery = c.NonIPQuery
|
||||
config.BlockTypes = c.BlockTypes
|
||||
return config, nil
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -19,6 +20,7 @@ type FreedomConfig struct {
|
||||
UserLevel uint32 `json:"userLevel"`
|
||||
Fragment *Fragment `json:"fragment"`
|
||||
Noise *Noise `json:"noise"`
|
||||
Noises []*Noise `json:"noises"`
|
||||
ProxyProtocol uint32 `json:"proxyProtocol"`
|
||||
}
|
||||
|
||||
@@ -29,8 +31,9 @@ type Fragment struct {
|
||||
}
|
||||
|
||||
type Noise struct {
|
||||
Packet string `json:"packet"`
|
||||
Delay string `json:"delay"`
|
||||
Type string `json:"type"`
|
||||
Packet string `json:"packet"`
|
||||
Delay *Int32Range `json:"delay"`
|
||||
}
|
||||
|
||||
// Build implements Buildable
|
||||
@@ -149,74 +152,18 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c.Noise != nil {
|
||||
config.Noise = new(freedom.Noise)
|
||||
var err, err2 error
|
||||
p := strings.Split(strings.ToLower(c.Noise.Packet), ":")
|
||||
if len(p) != 2 {
|
||||
return nil, errors.New("invalid type for packet")
|
||||
}
|
||||
switch p[0] {
|
||||
case "rand":
|
||||
randValue := strings.Split(p[1], "-")
|
||||
if len(randValue) > 2 {
|
||||
return nil, errors.New("Only 2 values are allowed for rand")
|
||||
}
|
||||
if len(randValue) == 2 {
|
||||
config.Noise.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64)
|
||||
config.Noise.LengthMax, err2 = strconv.ParseUint(randValue[1], 10, 64)
|
||||
}
|
||||
if len(randValue) == 1 {
|
||||
config.Noise.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64)
|
||||
config.Noise.LengthMax = config.Noise.LengthMin
|
||||
}
|
||||
return nil, errors.PrintRemovedFeatureError("noise = { ... }", "noises = [ { ... } ]")
|
||||
}
|
||||
|
||||
if c.Noises != nil {
|
||||
for _, n := range c.Noises {
|
||||
NConfig, err := ParseNoise(n)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid value for rand LengthMin").Base(err)
|
||||
return nil, err
|
||||
}
|
||||
if err2 != nil {
|
||||
return nil, errors.New("invalid value for rand LengthMax").Base(err2)
|
||||
}
|
||||
if config.Noise.LengthMin > config.Noise.LengthMax {
|
||||
config.Noise.LengthMin, config.Noise.LengthMax = config.Noise.LengthMax, config.Noise.LengthMin
|
||||
}
|
||||
if config.Noise.LengthMin == 0 {
|
||||
return nil, errors.New("rand lengthMin or lengthMax cannot be 0")
|
||||
}
|
||||
|
||||
case "str":
|
||||
//user input string
|
||||
config.Noise.StrNoise = strings.TrimSpace(p[1])
|
||||
|
||||
default:
|
||||
return nil, errors.New("Invalid packet,only rand and str are supported")
|
||||
}
|
||||
if c.Noise.Delay != "" {
|
||||
d := strings.Split(strings.ToLower(c.Noise.Delay), "-")
|
||||
if len(d) > 2 {
|
||||
return nil, errors.New("Invalid delay value")
|
||||
}
|
||||
if len(d) == 2 {
|
||||
config.Noise.DelayMin, err = strconv.ParseUint(d[0], 10, 64)
|
||||
config.Noise.DelayMax, err2 = strconv.ParseUint(d[1], 10, 64)
|
||||
|
||||
} else {
|
||||
config.Noise.DelayMin, err = strconv.ParseUint(d[0], 10, 64)
|
||||
config.Noise.DelayMax = config.Noise.DelayMin
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid value for DelayMin").Base(err)
|
||||
}
|
||||
if err2 != nil {
|
||||
return nil, errors.New("Invalid value for DelayMax").Base(err2)
|
||||
}
|
||||
if config.Noise.DelayMin > config.Noise.DelayMax {
|
||||
config.Noise.DelayMin, config.Noise.DelayMax = config.Noise.DelayMax, config.Noise.DelayMin
|
||||
}
|
||||
if config.Noise.DelayMin == 0 {
|
||||
return nil, errors.New("DelayMin or DelayMax cannot be 0")
|
||||
}
|
||||
} else {
|
||||
config.Noise.DelayMin = 0
|
||||
config.Noises = append(config.Noises, NConfig)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,3 +195,67 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func ParseNoise(noise *Noise) (*freedom.Noise, error) {
|
||||
var err, err2 error
|
||||
NConfig := new(freedom.Noise)
|
||||
|
||||
switch strings.ToLower(noise.Type) {
|
||||
case "rand":
|
||||
randValue := strings.Split(noise.Packet, "-")
|
||||
if len(randValue) > 2 {
|
||||
return nil, errors.New("Only 2 values are allowed for rand")
|
||||
}
|
||||
if len(randValue) == 2 {
|
||||
NConfig.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64)
|
||||
NConfig.LengthMax, err2 = strconv.ParseUint(randValue[1], 10, 64)
|
||||
}
|
||||
if len(randValue) == 1 {
|
||||
NConfig.LengthMin, err = strconv.ParseUint(randValue[0], 10, 64)
|
||||
NConfig.LengthMax = NConfig.LengthMin
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid value for rand LengthMin").Base(err)
|
||||
}
|
||||
if err2 != nil {
|
||||
return nil, errors.New("invalid value for rand LengthMax").Base(err2)
|
||||
}
|
||||
if NConfig.LengthMin > NConfig.LengthMax {
|
||||
NConfig.LengthMin, NConfig.LengthMax = NConfig.LengthMax, NConfig.LengthMin
|
||||
}
|
||||
if NConfig.LengthMin == 0 {
|
||||
return nil, errors.New("rand lengthMin or lengthMax cannot be 0")
|
||||
}
|
||||
|
||||
case "str":
|
||||
//user input string
|
||||
NConfig.StrNoise = []byte(strings.TrimSpace(noise.Packet))
|
||||
|
||||
case "base64":
|
||||
//user input base64
|
||||
NConfig.StrNoise, err = base64.StdEncoding.DecodeString(strings.TrimSpace(noise.Packet))
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid base64 string")
|
||||
}
|
||||
|
||||
default:
|
||||
return nil, errors.New("Invalid packet,only rand,str,base64 are supported")
|
||||
}
|
||||
|
||||
if noise.Delay != nil {
|
||||
if noise.Delay.From != 0 && noise.Delay.To != 0 {
|
||||
NConfig.DelayMin = uint64(noise.Delay.From)
|
||||
NConfig.DelayMax = uint64(noise.Delay.To)
|
||||
if NConfig.DelayMin > NConfig.LengthMax {
|
||||
NConfig.DelayMin, NConfig.DelayMax = NConfig.LengthMax, NConfig.DelayMin
|
||||
}
|
||||
} else {
|
||||
return nil, errors.New("DelayMin or DelayMax cannot be zero")
|
||||
}
|
||||
|
||||
} else {
|
||||
NConfig.DelayMin = 0
|
||||
NConfig.DelayMax = 0
|
||||
}
|
||||
return NConfig, nil
|
||||
}
|
||||
|
@@ -16,10 +16,11 @@ func DefaultLogConfig() *log.Config {
|
||||
}
|
||||
|
||||
type LogConfig struct {
|
||||
AccessLog string `json:"access"`
|
||||
ErrorLog string `json:"error"`
|
||||
LogLevel string `json:"loglevel"`
|
||||
DNSLog bool `json:"dnsLog"`
|
||||
AccessLog string `json:"access"`
|
||||
ErrorLog string `json:"error"`
|
||||
LogLevel string `json:"loglevel"`
|
||||
DNSLog bool `json:"dnsLog"`
|
||||
MaskAddress string `json:"maskAddress"`
|
||||
}
|
||||
|
||||
func (v *LogConfig) Build() *log.Config {
|
||||
@@ -59,5 +60,6 @@ func (v *LogConfig) Build() *log.Config {
|
||||
default:
|
||||
config.ErrorLogLevel = clog.Severity_Warning
|
||||
}
|
||||
config.MaskAddress = v.MaskAddress
|
||||
return config
|
||||
}
|
||||
|
@@ -14,11 +14,6 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type RouterRulesConfig struct {
|
||||
RuleList []json.RawMessage `json:"rules"`
|
||||
DomainStrategy string `json:"domainStrategy"`
|
||||
}
|
||||
|
||||
// StrategyConfig represents a strategy config
|
||||
type StrategyConfig struct {
|
||||
Type string `json:"type"`
|
||||
@@ -76,7 +71,6 @@ func (r *BalancingRule) Build() (*router.BalancingRule, error) {
|
||||
}
|
||||
|
||||
type RouterConfig struct {
|
||||
Settings *RouterRulesConfig `json:"settings"` // Deprecated
|
||||
RuleList []json.RawMessage `json:"rules"`
|
||||
DomainStrategy *string `json:"domainStrategy"`
|
||||
Balancers []*BalancingRule `json:"balancers"`
|
||||
@@ -88,8 +82,6 @@ func (c *RouterConfig) getDomainStrategy() router.Config_DomainStrategy {
|
||||
ds := ""
|
||||
if c.DomainStrategy != nil {
|
||||
ds = *c.DomainStrategy
|
||||
} else if c.Settings != nil {
|
||||
ds = c.Settings.DomainStrategy
|
||||
}
|
||||
|
||||
switch strings.ToLower(ds) {
|
||||
@@ -111,10 +103,6 @@ func (c *RouterConfig) Build() (*router.Config, error) {
|
||||
var rawRuleList []json.RawMessage
|
||||
if c != nil {
|
||||
rawRuleList = c.RuleList
|
||||
if c.Settings != nil {
|
||||
c.RuleList = append(c.RuleList, c.Settings.RuleList...)
|
||||
rawRuleList = c.RuleList
|
||||
}
|
||||
}
|
||||
|
||||
for _, rawRule := range rawRuleList {
|
||||
|
@@ -64,36 +64,33 @@ func TestRouterConfig(t *testing.T) {
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{
|
||||
Input: `{
|
||||
"strategy": "rules",
|
||||
"settings": {
|
||||
"domainStrategy": "AsIs",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"domain": [
|
||||
"baidu.com",
|
||||
"qq.com"
|
||||
],
|
||||
"outboundTag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"ip": [
|
||||
"10.0.0.0/8",
|
||||
"::1/128"
|
||||
],
|
||||
"outboundTag": "test"
|
||||
},{
|
||||
"type": "field",
|
||||
"port": "53, 443, 1000-2000",
|
||||
"outboundTag": "test"
|
||||
},{
|
||||
"type": "field",
|
||||
"port": 123,
|
||||
"outboundTag": "test"
|
||||
}
|
||||
]
|
||||
},
|
||||
"domainStrategy": "AsIs",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"domain": [
|
||||
"baidu.com",
|
||||
"qq.com"
|
||||
],
|
||||
"outboundTag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"ip": [
|
||||
"10.0.0.0/8",
|
||||
"::1/128"
|
||||
],
|
||||
"outboundTag": "test"
|
||||
},{
|
||||
"type": "field",
|
||||
"port": "53, 443, 1000-2000",
|
||||
"outboundTag": "test"
|
||||
},{
|
||||
"type": "field",
|
||||
"port": 123,
|
||||
"outboundTag": "test"
|
||||
}
|
||||
],
|
||||
"balancers": [
|
||||
{
|
||||
"tag": "b1",
|
||||
@@ -225,28 +222,25 @@ func TestRouterConfig(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Input: `{
|
||||
"strategy": "rules",
|
||||
"settings": {
|
||||
"domainStrategy": "IPIfNonMatch",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"domain": [
|
||||
"baidu.com",
|
||||
"qq.com"
|
||||
],
|
||||
"outboundTag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"ip": [
|
||||
"10.0.0.0/8",
|
||||
"::1/128"
|
||||
],
|
||||
"outboundTag": "test"
|
||||
}
|
||||
]
|
||||
}
|
||||
"domainStrategy": "IPIfNonMatch",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"domain": [
|
||||
"baidu.com",
|
||||
"qq.com"
|
||||
],
|
||||
"outboundTag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"ip": [
|
||||
"10.0.0.0/8",
|
||||
"::1/128"
|
||||
],
|
||||
"outboundTag": "test"
|
||||
}
|
||||
]
|
||||
}`,
|
||||
Parser: createParser(),
|
||||
Output: &router.Config{
|
||||
@@ -289,68 +283,5 @@ func TestRouterConfig(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Input: `{
|
||||
"domainStrategy": "AsIs",
|
||||
"rules": [
|
||||
{
|
||||
"type": "field",
|
||||
"domain": [
|
||||
"baidu.com",
|
||||
"qq.com"
|
||||
],
|
||||
"outboundTag": "direct"
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
"ip": [
|
||||
"10.0.0.0/8",
|
||||
"::1/128"
|
||||
],
|
||||
"outboundTag": "test"
|
||||
}
|
||||
]
|
||||
}`,
|
||||
Parser: createParser(),
|
||||
Output: &router.Config{
|
||||
DomainStrategy: router.Config_AsIs,
|
||||
Rule: []*router.RoutingRule{
|
||||
{
|
||||
Domain: []*router.Domain{
|
||||
{
|
||||
Type: router.Domain_Plain,
|
||||
Value: "baidu.com",
|
||||
},
|
||||
{
|
||||
Type: router.Domain_Plain,
|
||||
Value: "qq.com",
|
||||
},
|
||||
},
|
||||
TargetTag: &router.RoutingRule_Tag{
|
||||
Tag: "direct",
|
||||
},
|
||||
},
|
||||
{
|
||||
Geoip: []*router.GeoIP{
|
||||
{
|
||||
Cidr: []*router.CIDR{
|
||||
{
|
||||
Ip: []byte{10, 0, 0, 0},
|
||||
Prefix: 8,
|
||||
},
|
||||
{
|
||||
Ip: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||
Prefix: 128,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
TargetTag: &router.RoutingRule_Tag{
|
||||
Tag: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
@@ -231,6 +231,14 @@ type SplitHTTPConfig struct {
|
||||
ScMinPostsIntervalMs *Int32Range `json:"scMinPostsIntervalMs"`
|
||||
NoSSEHeader bool `json:"noSSEHeader"`
|
||||
XPaddingBytes *Int32Range `json:"xPaddingBytes"`
|
||||
Xmux Xmux `json:"xmux"`
|
||||
}
|
||||
|
||||
type Xmux struct {
|
||||
maxConnections *Int32Range `json:"maxConnections"`
|
||||
maxConcurrency *Int32Range `json:"maxConcurrency"`
|
||||
cMaxReuseTimes *Int32Range `json:"cMaxReuseTimes"`
|
||||
cMaxLifetimeMs *Int32Range `json:"cMaxLifetimeMs"`
|
||||
}
|
||||
|
||||
func splithttpNewRandRangeConfig(input *Int32Range) *splithttp.RandRangeConfig {
|
||||
@@ -254,6 +262,19 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
||||
} else if c.Host == "" && c.Headers["Host"] != "" {
|
||||
c.Host = c.Headers["Host"]
|
||||
}
|
||||
|
||||
if c.Xmux.maxConnections != nil && c.Xmux.maxConcurrency != nil {
|
||||
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
|
||||
}
|
||||
|
||||
// Multiplexing config
|
||||
muxProtobuf := splithttp.Multiplexing{
|
||||
MaxConnections: splithttpNewRandRangeConfig(c.Xmux.maxConnections),
|
||||
MaxConcurrency: splithttpNewRandRangeConfig(c.Xmux.maxConcurrency),
|
||||
CMaxReuseTimes: splithttpNewRandRangeConfig(c.Xmux.cMaxReuseTimes),
|
||||
CMaxLifetimeMs: splithttpNewRandRangeConfig(c.Xmux.cMaxLifetimeMs),
|
||||
}
|
||||
|
||||
config := &splithttp.Config{
|
||||
Path: c.Path,
|
||||
Host: c.Host,
|
||||
@@ -263,6 +284,7 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
||||
ScMinPostsIntervalMs: splithttpNewRandRangeConfig(c.ScMinPostsIntervalMs),
|
||||
NoSSEHeader: c.NoSSEHeader,
|
||||
XPaddingBytes: splithttpNewRandRangeConfig(c.XPaddingBytes),
|
||||
Xmux: &muxProtobuf,
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
@@ -813,7 +835,7 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
config.SecuritySettings = append(config.SecuritySettings, tm)
|
||||
config.SecurityType = tm.Type
|
||||
case "xtls":
|
||||
return nil, errors.New(`Please use VLESS flow "xtls-rprx-vision" with TLS or REALITY.`)
|
||||
return nil, errors.PrintRemovedFeatureError(`Legacy XTLS`, `xtls-rprx-vision with TLS or REALITY`)
|
||||
default:
|
||||
return nil, errors.New(`Unknown security "` + c.Security + `".`)
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
|
||||
return nil, errors.New("Trojan password is not specified.")
|
||||
}
|
||||
if rec.Flow != "" {
|
||||
return nil, errors.New(`Trojan doesn't support "flow" anymore.`)
|
||||
return nil, errors.PrintRemovedFeatureError(`Flow for Trojan`, ``)
|
||||
}
|
||||
|
||||
config.Server[idx] = &protocol.ServerEndpoint{
|
||||
@@ -106,7 +106,7 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
|
||||
|
||||
for idx, rawUser := range c.Clients {
|
||||
if rawUser.Flow != "" {
|
||||
return nil, errors.New(`Trojan doesn't support "flow" anymore.`)
|
||||
return nil, errors.PrintRemovedFeatureError(`Flow for Trojan`, ``)
|
||||
}
|
||||
|
||||
config.Users[idx] = &protocol.User{
|
||||
|
@@ -57,10 +57,6 @@ func (c *VMessDetourConfig) Build() *inbound.DetourConfig {
|
||||
}
|
||||
}
|
||||
|
||||
type FeaturesConfig struct {
|
||||
Detour *VMessDetourConfig `json:"detour"`
|
||||
}
|
||||
|
||||
type VMessDefaultConfig struct {
|
||||
Level byte `json:"level"`
|
||||
}
|
||||
@@ -74,7 +70,6 @@ func (c *VMessDefaultConfig) Build() *inbound.DefaultConfig {
|
||||
|
||||
type VMessInboundConfig struct {
|
||||
Users []json.RawMessage `json:"clients"`
|
||||
Features *FeaturesConfig `json:"features"`
|
||||
Defaults *VMessDefaultConfig `json:"default"`
|
||||
DetourConfig *VMessDetourConfig `json:"detour"`
|
||||
}
|
||||
@@ -89,8 +84,6 @@ func (c *VMessInboundConfig) Build() (proto.Message, error) {
|
||||
|
||||
if c.DetourConfig != nil {
|
||||
config.Detour = c.DetourConfig.Build()
|
||||
} else if c.Features != nil && c.Features.Detour != nil {
|
||||
config.Detour = c.Features.Detour.Build()
|
||||
}
|
||||
|
||||
config.User = make([]*protocol.User, len(c.Users))
|
||||
|
@@ -48,21 +48,6 @@ var (
|
||||
ctllog = log.New(os.Stderr, "xctl> ", 0)
|
||||
)
|
||||
|
||||
func toProtocolList(s []string) ([]proxyman.KnownProtocols, error) {
|
||||
kp := make([]proxyman.KnownProtocols, 0, 8)
|
||||
for _, p := range s {
|
||||
switch strings.ToLower(p) {
|
||||
case "http":
|
||||
kp = append(kp, proxyman.KnownProtocols_HTTP)
|
||||
case "https", "tls", "ssl":
|
||||
kp = append(kp, proxyman.KnownProtocols_TLS)
|
||||
default:
|
||||
return nil, errors.New("Unknown protocol: ", p)
|
||||
}
|
||||
}
|
||||
return kp, nil
|
||||
}
|
||||
|
||||
type SniffingConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
DestOverride *StringList `json:"destOverride"`
|
||||
@@ -175,7 +160,6 @@ type InboundDetourConfig struct {
|
||||
Tag string `json:"tag"`
|
||||
Allocation *InboundDetourAllocationConfig `json:"allocate"`
|
||||
StreamSetting *StreamConfig `json:"streamSettings"`
|
||||
DomainOverride *StringList `json:"domainOverride"`
|
||||
SniffingConfig *SniffingConfig `json:"sniffing"`
|
||||
}
|
||||
|
||||
@@ -249,13 +233,6 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
|
||||
}
|
||||
receiverSettings.SniffingSettings = s
|
||||
}
|
||||
if c.DomainOverride != nil {
|
||||
kp, err := toProtocolList(*c.DomainOverride)
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to parse inbound detour config").Base(err)
|
||||
}
|
||||
receiverSettings.DomainOverride = kp
|
||||
}
|
||||
|
||||
settings := []byte("{}")
|
||||
if c.Settings != nil {
|
||||
@@ -384,11 +361,6 @@ func (c *StatsConfig) Build() (*stats.Config, error) {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
// Port of this Point server.
|
||||
// Deprecated: Port exists for historical compatibility
|
||||
// and should not be used.
|
||||
Port uint16 `json:"port"`
|
||||
|
||||
// Deprecated: Global transport config is no longer used
|
||||
// left for returning error
|
||||
Transport map[string]json.RawMessage `json:"transport"`
|
||||
@@ -620,16 +592,8 @@ func (c *Config) Build() (*core.Config, error) {
|
||||
inbounds = append(inbounds, c.InboundConfigs...)
|
||||
}
|
||||
|
||||
// Backward compatibility.
|
||||
if len(inbounds) > 0 && inbounds[0].PortList == nil && c.Port > 0 {
|
||||
inbounds[0].PortList = &PortList{[]PortRange{{
|
||||
From: uint32(c.Port),
|
||||
To: uint32(c.Port),
|
||||
}}}
|
||||
}
|
||||
|
||||
if len(c.Transport) > 0 {
|
||||
return nil, errors.New("Global transport config is deprecated")
|
||||
return nil, errors.PrintRemovedFeatureError("Global transport config", "streamSettings in inbounds and outbounds")
|
||||
}
|
||||
|
||||
for _, rawInboundConfig := range inbounds {
|
||||
|
@@ -74,18 +74,15 @@ func TestXrayConfig(t *testing.T) {
|
||||
}
|
||||
}],
|
||||
"routing": {
|
||||
"strategy": "rules",
|
||||
"settings": {
|
||||
"rules": [
|
||||
{
|
||||
"ip": [
|
||||
"10.0.0.0/8"
|
||||
],
|
||||
"type": "field",
|
||||
"outboundTag": "blocked"
|
||||
}
|
||||
]
|
||||
}
|
||||
"rules": [
|
||||
{
|
||||
"ip": [
|
||||
"10.0.0.0/8"
|
||||
],
|
||||
"type": "field",
|
||||
"outboundTag": "blocked"
|
||||
}
|
||||
]
|
||||
}
|
||||
}`,
|
||||
Parser: createParser(),
|
||||
|
@@ -31,6 +31,7 @@ type Config struct {
|
||||
Server *net.Endpoint `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"`
|
||||
UserLevel uint32 `protobuf:"varint,2,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"`
|
||||
Non_IPQuery string `protobuf:"bytes,3,opt,name=non_IP_query,json=nonIPQuery,proto3" json:"non_IP_query,omitempty"`
|
||||
BlockTypes []int32 `protobuf:"varint,4,rep,packed,name=block_types,json=blockTypes,proto3" json:"block_types,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
@@ -86,6 +87,13 @@ func (x *Config) GetNon_IPQuery() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetBlockTypes() []int32 {
|
||||
if x != nil {
|
||||
return x.BlockTypes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_proxy_dns_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proxy_dns_config_proto_rawDesc = []byte{
|
||||
@@ -93,20 +101,22 @@ var file_proxy_dns_config_proto_rawDesc = []byte{
|
||||
0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x78, 0x79, 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, 0x74, 0x6f, 0x22, 0x7c, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x12, 0x31, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 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, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72,
|
||||
0x76, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65,
|
||||
0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76,
|
||||
0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0c, 0x6e, 0x6f, 0x6e, 0x5f, 0x49, 0x50, 0x5f, 0x71, 0x75, 0x65,
|
||||
0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x6f, 0x6e, 0x49, 0x50, 0x51,
|
||||
0x75, 0x65, 0x72, 0x79, 0x42, 0x4c, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x23, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x64, 0x6e,
|
||||
0x73, 0xaa, 0x02, 0x0e, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x44,
|
||||
0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9d, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 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, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76,
|
||||
0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65,
|
||||
0x76, 0x65, 0x6c, 0x12, 0x20, 0x0a, 0x0c, 0x6e, 0x6f, 0x6e, 0x5f, 0x49, 0x50, 0x5f, 0x71, 0x75,
|
||||
0x65, 0x72, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x6f, 0x6e, 0x49, 0x50,
|
||||
0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x74,
|
||||
0x79, 0x70, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0a, 0x62, 0x6c, 0x6f, 0x63,
|
||||
0x6b, 0x54, 0x79, 0x70, 0x65, 0x73, 0x42, 0x4c, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x23,
|
||||
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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
|
||||
0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0e, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -14,4 +14,5 @@ message Config {
|
||||
xray.common.net.Endpoint server = 1;
|
||||
uint32 user_level = 2;
|
||||
string non_IP_query = 3;
|
||||
repeated int32 block_types = 4;
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ type Handler struct {
|
||||
server net.Destination
|
||||
timeout time.Duration
|
||||
nonIPQuery string
|
||||
blockTypes []int32
|
||||
}
|
||||
|
||||
func (h *Handler) Init(config *Config, dnsClient dns.Client, policyManager policy.Manager) error {
|
||||
@@ -63,6 +64,7 @@ func (h *Handler) Init(config *Config, dnsClient dns.Client, policyManager polic
|
||||
h.server = config.Server.AsDestination()
|
||||
}
|
||||
h.nonIPQuery = config.Non_IPQuery
|
||||
h.blockTypes = config.BlockTypes
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -84,12 +86,12 @@ func parseIPQuery(b []byte) (r bool, domain string, id uint16, qType dnsmessage.
|
||||
errors.LogInfoInner(context.Background(), err, "question")
|
||||
return
|
||||
}
|
||||
domain = q.Name.String()
|
||||
qType = q.Type
|
||||
if qType != dnsmessage.TypeA && qType != dnsmessage.TypeAAAA {
|
||||
return
|
||||
}
|
||||
|
||||
domain = q.Name.String()
|
||||
r = true
|
||||
return
|
||||
}
|
||||
@@ -181,10 +183,18 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet.
|
||||
|
||||
if !h.isOwnLink(ctx) {
|
||||
isIPQuery, domain, id, qType := parseIPQuery(b.Bytes())
|
||||
if len(h.blockTypes) > 0 {
|
||||
for _, blocktype := range h.blockTypes {
|
||||
if blocktype == int32(qType) {
|
||||
errors.LogInfo(ctx, "blocked type ", qType, " query for domain ", domain)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if isIPQuery {
|
||||
go h.handleIPQuery(id, qType, domain, writer)
|
||||
}
|
||||
if isIPQuery || h.nonIPQuery == "drop" || qType == 65 {
|
||||
if isIPQuery || h.nonIPQuery == "drop" {
|
||||
b.Release()
|
||||
continue
|
||||
}
|
||||
|
@@ -237,7 +237,7 @@ type Noise struct {
|
||||
LengthMax uint64 `protobuf:"varint,2,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"`
|
||||
DelayMin uint64 `protobuf:"varint,3,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,omitempty"`
|
||||
DelayMax uint64 `protobuf:"varint,4,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"`
|
||||
StrNoise string `protobuf:"bytes,5,opt,name=str_noise,json=strNoise,proto3" json:"str_noise,omitempty"`
|
||||
StrNoise []byte `protobuf:"bytes,5,opt,name=str_noise,json=strNoise,proto3" json:"str_noise,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Noise) Reset() {
|
||||
@@ -300,11 +300,11 @@ func (x *Noise) GetDelayMax() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Noise) GetStrNoise() string {
|
||||
func (x *Noise) GetStrNoise() []byte {
|
||||
if x != nil {
|
||||
return x.StrNoise
|
||||
}
|
||||
return ""
|
||||
return nil
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -319,7 +319,7 @@ type Config struct {
|
||||
UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"`
|
||||
Fragment *Fragment `protobuf:"bytes,5,opt,name=fragment,proto3" json:"fragment,omitempty"`
|
||||
ProxyProtocol uint32 `protobuf:"varint,6,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"`
|
||||
Noise *Noise `protobuf:"bytes,7,opt,name=noise,proto3" json:"noise,omitempty"`
|
||||
Noises []*Noise `protobuf:"bytes,7,rep,name=noises,proto3" json:"noises,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
@@ -397,9 +397,9 @@ func (x *Config) GetProxyProtocol() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Config) GetNoise() *Noise {
|
||||
func (x *Config) GetNoises() []*Noise {
|
||||
if x != nil {
|
||||
return x.Noise
|
||||
return x.Noises
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -439,8 +439,8 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e,
|
||||
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a,
|
||||
0x09, 0x73, 0x74, 0x72, 0x5f, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x08, 0x73, 0x74, 0x72, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x22, 0xb3, 0x04, 0x0a, 0x06, 0x43,
|
||||
0x09, 0x73, 0x74, 0x72, 0x5f, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x08, 0x73, 0x74, 0x72, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x22, 0xb5, 0x04, 0x0a, 0x06, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
|
||||
0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29,
|
||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65,
|
||||
@@ -462,27 +462,27 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
|
||||
0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e,
|
||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x63, 0x6f, 0x6c, 0x12, 0x2f, 0x0a, 0x05, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
||||
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x05, 0x6e,
|
||||
0x6f, 0x69, 0x73, 0x65, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53,
|
||||
0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b,
|
||||
0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55,
|
||||
0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10,
|
||||
0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08,
|
||||
0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09,
|
||||
0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a,
|
||||
0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x66, 0x72,
|
||||
0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
0x63, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06,
|
||||
0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f,
|
||||
0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01,
|
||||
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a,
|
||||
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53,
|
||||
0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36,
|
||||
0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36,
|
||||
0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34,
|
||||
0x10, 0x0a, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27,
|
||||
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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
|
||||
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50,
|
||||
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -512,7 +512,7 @@ var file_proxy_freedom_config_proto_depIdxs = []int32{
|
||||
0, // 1: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.proxy.freedom.Config.DomainStrategy
|
||||
1, // 2: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
||||
2, // 3: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
||||
3, // 4: xray.proxy.freedom.Config.noise:type_name -> xray.proxy.freedom.Noise
|
||||
3, // 4: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
||||
5, // [5:5] is the sub-list for method output_type
|
||||
5, // [5:5] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
|
@@ -25,7 +25,7 @@ message Noise {
|
||||
uint64 length_max = 2;
|
||||
uint64 delay_min = 3;
|
||||
uint64 delay_max = 4;
|
||||
string str_noise = 5;
|
||||
bytes str_noise = 5;
|
||||
}
|
||||
|
||||
message Config {
|
||||
@@ -48,5 +48,5 @@ message Config {
|
||||
uint32 user_level = 4;
|
||||
Fragment fragment = 5;
|
||||
uint32 proxy_protocol = 6;
|
||||
Noise noise = 7;
|
||||
repeated Noise noises = 7;
|
||||
}
|
||||
|
@@ -208,12 +208,11 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
}
|
||||
} else {
|
||||
writer = NewPacketWriter(conn, h, ctx, UDPOverride)
|
||||
if h.config.Noise != nil {
|
||||
errors.LogDebug(ctx, "NOISE", h.config.Noise.StrNoise, h.config.Noise.LengthMin, h.config.Noise.LengthMax,
|
||||
h.config.Noise.DelayMin, h.config.Noise.DelayMax)
|
||||
if h.config.Noises != nil {
|
||||
errors.LogDebug(ctx, "NOISE", h.config.Noises)
|
||||
writer = &NoisePacketWriter{
|
||||
Writer: writer,
|
||||
noise: h.config.Noise,
|
||||
noises: h.config.Noises,
|
||||
firstWrite: true,
|
||||
UDPOverride: UDPOverride,
|
||||
}
|
||||
@@ -396,12 +395,12 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
|
||||
type NoisePacketWriter struct {
|
||||
buf.Writer
|
||||
noise *Noise
|
||||
noises []*Noise
|
||||
firstWrite bool
|
||||
UDPOverride net.Destination
|
||||
}
|
||||
|
||||
// MultiBuffer writer with Noise in first packet
|
||||
// MultiBuffer writer with Noise before first packet
|
||||
func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
if w.firstWrite {
|
||||
w.firstWrite = false
|
||||
@@ -411,22 +410,23 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
}
|
||||
var noise []byte
|
||||
var err error
|
||||
//User input string
|
||||
if w.noise.StrNoise != "" {
|
||||
noise = []byte(w.noise.StrNoise)
|
||||
} else {
|
||||
//Random noise
|
||||
noise, err = GenerateRandomBytes(randBetween(int64(w.noise.LengthMin),
|
||||
int64(w.noise.LengthMax)))
|
||||
}
|
||||
for _, n := range w.noises {
|
||||
//User input string or base64 encoded string
|
||||
if n.StrNoise != nil {
|
||||
noise = n.StrNoise
|
||||
} else {
|
||||
//Random noise
|
||||
noise, err = GenerateRandomBytes(randBetween(int64(n.LengthMin),
|
||||
int64(n.LengthMax)))
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
|
||||
|
||||
if w.noise.DelayMin != 0 {
|
||||
time.Sleep(time.Duration(randBetween(int64(w.noise.DelayMin), int64(w.noise.DelayMax))) * time.Millisecond)
|
||||
if n.DelayMin != 0 {
|
||||
time.Sleep(time.Duration(randBetween(int64(n.DelayMin), int64(n.DelayMax))) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/signal"
|
||||
"github.com/xtls/xray-core/common/task"
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features"
|
||||
"github.com/xtls/xray-core/features/policy"
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"github.com/xtls/xray-core/proxy/http"
|
||||
@@ -56,7 +55,7 @@ func (s *Server) policy() policy.Session {
|
||||
config := s.config
|
||||
p := s.policyManager.ForLevel(config.UserLevel)
|
||||
if config.Timeout > 0 {
|
||||
features.PrintDeprecatedFeatureWarning("Socks timeout")
|
||||
errors.PrintDeprecatedFeatureWarning("Socks timeout", "Policy level")
|
||||
}
|
||||
if config.Timeout > 0 && config.UserLevel == 0 {
|
||||
p.Timeouts.ConnectionIdle = time.Duration(config.Timeout) * time.Second
|
||||
|
@@ -64,7 +64,7 @@ func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requ
|
||||
}
|
||||
|
||||
// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
|
||||
func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator *vless.Validator) (*protocol.RequestHeader, *Addons, bool, error) {
|
||||
func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator vless.Validator) (*protocol.RequestHeader, *Addons, bool, error) {
|
||||
buffer := buf.StackNew()
|
||||
defer buffer.Release()
|
||||
|
||||
|
@@ -42,7 +42,7 @@ func TestRequestSerialization(t *testing.T) {
|
||||
buffer := buf.StackNew()
|
||||
common.Must(EncodeRequestHeader(&buffer, expectedRequest, expectedAddons))
|
||||
|
||||
Validator := new(vless.Validator)
|
||||
Validator := new(vless.MemoryValidator)
|
||||
Validator.Add(user)
|
||||
|
||||
actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
@@ -83,7 +83,7 @@ func TestInvalidRequest(t *testing.T) {
|
||||
buffer := buf.StackNew()
|
||||
common.Must(EncodeRequestHeader(&buffer, expectedRequest, expectedAddons))
|
||||
|
||||
Validator := new(vless.Validator)
|
||||
Validator := new(vless.MemoryValidator)
|
||||
Validator.Add(user)
|
||||
|
||||
_, _, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
@@ -114,7 +114,7 @@ func TestMuxRequest(t *testing.T) {
|
||||
buffer := buf.StackNew()
|
||||
common.Must(EncodeRequestHeader(&buffer, expectedRequest, expectedAddons))
|
||||
|
||||
Validator := new(vless.Validator)
|
||||
Validator := new(vless.MemoryValidator)
|
||||
Validator.Add(user)
|
||||
|
||||
actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||
|
@@ -45,7 +45,21 @@ func init() {
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return New(ctx, config.(*Config), dc)
|
||||
|
||||
c := config.(*Config)
|
||||
|
||||
validator := new(vless.MemoryValidator)
|
||||
for _, user := range c.Clients {
|
||||
u, err := user.ToMemoryUser()
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to get VLESS user").Base(err).AtError()
|
||||
}
|
||||
if err := validator.Add(u); err != nil {
|
||||
return nil, errors.New("failed to initiate user").Base(err).AtError()
|
||||
}
|
||||
}
|
||||
|
||||
return New(ctx, c, dc, validator)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -53,30 +67,20 @@ func init() {
|
||||
type Handler struct {
|
||||
inboundHandlerManager feature_inbound.Manager
|
||||
policyManager policy.Manager
|
||||
validator *vless.Validator
|
||||
validator vless.Validator
|
||||
dns dns.Client
|
||||
fallbacks map[string]map[string]map[string]*Fallback // or nil
|
||||
// regexps map[string]*regexp.Regexp // or nil
|
||||
}
|
||||
|
||||
// New creates a new VLess inbound handler.
|
||||
func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) {
|
||||
func New(ctx context.Context, config *Config, dc dns.Client, validator vless.Validator) (*Handler, error) {
|
||||
v := core.MustFromContext(ctx)
|
||||
handler := &Handler{
|
||||
inboundHandlerManager: v.GetFeature(feature_inbound.ManagerType()).(feature_inbound.Manager),
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
validator: new(vless.Validator),
|
||||
dns: dc,
|
||||
}
|
||||
|
||||
for _, user := range config.Clients {
|
||||
u, err := user.ToMemoryUser()
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to get VLESS user").Base(err).AtError()
|
||||
}
|
||||
if err := handler.AddUser(ctx, u); err != nil {
|
||||
return nil, errors.New("failed to initiate user").Base(err).AtError()
|
||||
}
|
||||
validator: validator,
|
||||
}
|
||||
|
||||
if config.Fallbacks != nil {
|
||||
|
@@ -9,15 +9,21 @@ import (
|
||||
"github.com/xtls/xray-core/common/uuid"
|
||||
)
|
||||
|
||||
// Validator stores valid VLESS users.
|
||||
type Validator struct {
|
||||
type Validator interface {
|
||||
Get(id uuid.UUID) *protocol.MemoryUser
|
||||
Add(u *protocol.MemoryUser) error
|
||||
Del(email string) error
|
||||
}
|
||||
|
||||
// MemoryValidator stores valid VLESS users.
|
||||
type MemoryValidator struct {
|
||||
// Considering email's usage here, map + sync.Mutex/RWMutex may have better performance.
|
||||
email sync.Map
|
||||
users sync.Map
|
||||
}
|
||||
|
||||
// Add a VLESS user, Email must be empty or unique.
|
||||
func (v *Validator) Add(u *protocol.MemoryUser) error {
|
||||
func (v *MemoryValidator) Add(u *protocol.MemoryUser) error {
|
||||
if u.Email != "" {
|
||||
_, loaded := v.email.LoadOrStore(strings.ToLower(u.Email), u)
|
||||
if loaded {
|
||||
@@ -29,7 +35,7 @@ func (v *Validator) Add(u *protocol.MemoryUser) error {
|
||||
}
|
||||
|
||||
// Del a VLESS user with a non-empty Email.
|
||||
func (v *Validator) Del(e string) error {
|
||||
func (v *MemoryValidator) Del(e string) error {
|
||||
if e == "" {
|
||||
return errors.New("Email must not be empty.")
|
||||
}
|
||||
@@ -44,7 +50,7 @@ func (v *Validator) Del(e string) error {
|
||||
}
|
||||
|
||||
// Get a VLESS user with UUID, nil if user doesn't exist.
|
||||
func (v *Validator) Get(id uuid.UUID) *protocol.MemoryUser {
|
||||
func (v *MemoryValidator) Get(id uuid.UUID) *protocol.MemoryUser {
|
||||
u, _ := v.users.Load(id)
|
||||
if u != nil {
|
||||
return u.(*protocol.MemoryUser)
|
||||
|
@@ -39,7 +39,10 @@ func (v *TimedUserValidator) Add(u *protocol.MemoryUser) error {
|
||||
|
||||
v.users = append(v.users, u)
|
||||
|
||||
account := u.Account.(*MemoryAccount)
|
||||
account, ok := u.Account.(*MemoryAccount)
|
||||
if !ok {
|
||||
return errors.New("account type is incorrect")
|
||||
}
|
||||
if !v.behaviorFused {
|
||||
hashkdf := hmac.New(sha256.New, []byte("VMESSBSKDF"))
|
||||
hashkdf.Write(account.ID.Bytes())
|
||||
|
@@ -560,8 +560,9 @@ func TestDomainSniffing(t *testing.T) {
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(sniffingPort)}},
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
DomainOverride: []proxyman.KnownProtocols{
|
||||
proxyman.KnownProtocols_TLS,
|
||||
SniffingSettings: &proxyman.SniffingConfig{
|
||||
Enabled: true,
|
||||
DestinationOverride: []string{"tls"},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
|
@@ -1,13 +0,0 @@
|
||||
package global
|
||||
|
||||
import (
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
|
||||
// Apply applies this Config.
|
||||
func (c *Config) Apply() error {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return internet.ApplyGlobalTransportSettings(c.TransportSettings)
|
||||
}
|
@@ -1,162 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.34.2
|
||||
// protoc v5.27.0
|
||||
// source: transport/global/config.proto
|
||||
|
||||
package global
|
||||
|
||||
import (
|
||||
internet "github.com/xtls/xray-core/transport/internet"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// Global transport settings. This affects all type of connections that go
|
||||
// through Xray. Deprecated. Use each settings in StreamConfig.
|
||||
//
|
||||
// Deprecated: Marked as deprecated in transport/global/config.proto.
|
||||
type Config struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
TransportSettings []*internet.TransportConfig `protobuf:"bytes,1,rep,name=transport_settings,json=transportSettings,proto3" json:"transport_settings,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
*x = Config{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_transport_global_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Config) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Config) ProtoMessage() {}
|
||||
|
||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_global_config_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||
func (*Config) Descriptor() ([]byte, []int) {
|
||||
return file_transport_global_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Config) GetTransportSettings() []*internet.TransportConfig {
|
||||
if x != nil {
|
||||
return x.TransportSettings
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_transport_global_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_transport_global_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x1d, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x6c, 0x6f, 0x62,
|
||||
0x61, 0x6c, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
|
||||
0x0e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x1a,
|
||||
0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x22, 0x65, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x57, 0x0a, 0x12, 0x74, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 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, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x52, 0x11, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69,
|
||||
0x6e, 0x67, 0x73, 0x3a, 0x02, 0x18, 0x01, 0x42, 0x61, 0x0a, 0x19, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x67, 0x6c,
|
||||
0x6f, 0x62, 0x61, 0x6c, 0x50, 0x01, 0x5a, 0x2a, 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, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x6c, 0x6f, 0x62,
|
||||
0x61, 0x6c, 0xaa, 0x02, 0x15, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x2e, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_transport_global_config_proto_rawDescOnce sync.Once
|
||||
file_transport_global_config_proto_rawDescData = file_transport_global_config_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_transport_global_config_proto_rawDescGZIP() []byte {
|
||||
file_transport_global_config_proto_rawDescOnce.Do(func() {
|
||||
file_transport_global_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_global_config_proto_rawDescData)
|
||||
})
|
||||
return file_transport_global_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_transport_global_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_transport_global_config_proto_goTypes = []any{
|
||||
(*Config)(nil), // 0: xray.transport.Config
|
||||
(*internet.TransportConfig)(nil), // 1: xray.transport.internet.TransportConfig
|
||||
}
|
||||
var file_transport_global_config_proto_depIdxs = []int32{
|
||||
1, // 0: xray.transport.Config.transport_settings:type_name -> xray.transport.internet.TransportConfig
|
||||
1, // [1:1] is the sub-list for method output_type
|
||||
1, // [1:1] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_transport_global_config_proto_init() }
|
||||
func file_transport_global_config_proto_init() {
|
||||
if File_transport_global_config_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_transport_global_config_proto_msgTypes[0].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*Config); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_transport_global_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_transport_global_config_proto_goTypes,
|
||||
DependencyIndexes: file_transport_global_config_proto_depIdxs,
|
||||
MessageInfos: file_transport_global_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_transport_global_config_proto = out.File
|
||||
file_transport_global_config_proto_rawDesc = nil
|
||||
file_transport_global_config_proto_goTypes = nil
|
||||
file_transport_global_config_proto_depIdxs = nil
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package xray.transport;
|
||||
option csharp_namespace = "Xray.Transport.Global";
|
||||
option go_package = "github.com/xtls/xray-core/transport/global";
|
||||
option java_package = "com.xray.transport.global";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "transport/internet/config.proto";
|
||||
|
||||
// Global transport settings. This affects all type of connections that go
|
||||
// through Xray. Deprecated. Use each settings in StreamConfig.
|
||||
message Config {
|
||||
option deprecated = true;
|
||||
repeated xray.transport.internet.TransportConfig transport_settings = 1;
|
||||
}
|
@@ -3,14 +3,12 @@ package internet
|
||||
import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/features"
|
||||
)
|
||||
|
||||
type ConfigCreator func() interface{}
|
||||
|
||||
var (
|
||||
globalTransportConfigCreatorCache = make(map[string]ConfigCreator)
|
||||
globalTransportSettings []*TransportConfig
|
||||
)
|
||||
|
||||
var strategy = [][]byte{
|
||||
@@ -105,12 +103,6 @@ func (c *StreamConfig) GetTransportSettingsFor(protocol string) (interface{}, er
|
||||
}
|
||||
}
|
||||
|
||||
for _, settings := range globalTransportSettings {
|
||||
if settings.GetUnifiedProtocolName() == protocol {
|
||||
return settings.GetTypedSettings()
|
||||
}
|
||||
}
|
||||
|
||||
return CreateTransportConfig(protocol)
|
||||
}
|
||||
|
||||
@@ -127,12 +119,6 @@ func (c *StreamConfig) HasSecuritySettings() bool {
|
||||
return len(c.SecurityType) > 0
|
||||
}
|
||||
|
||||
func ApplyGlobalTransportSettings(settings []*TransportConfig) error {
|
||||
features.PrintDeprecatedFeatureWarning("global transport settings")
|
||||
globalTransportSettings = settings
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ProxyConfig) HasTag() bool {
|
||||
return c != nil && len(c.Tag) > 0
|
||||
}
|
||||
|
@@ -140,6 +140,9 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
|
||||
if err != nil {
|
||||
return nil, errors.New("REALITY: publicKey == nil")
|
||||
}
|
||||
if uConn.HandshakeState.State13.EcdheKey == nil {
|
||||
return nil, errors.New("Current fingerprint ", uConn.ClientHelloID.Client, uConn.ClientHelloID.Version, " does not support TLS 1.3, REALITY handshake cannot establish.")
|
||||
}
|
||||
uConn.AuthKey, _ = uConn.HandshakeState.State13.EcdheKey.ECDH(publicKey)
|
||||
if uConn.AuthKey == nil {
|
||||
return nil, errors.New("REALITY: SharedKey == nil")
|
||||
|
@@ -3,6 +3,7 @@ package splithttp
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
gonet "net"
|
||||
"net/http"
|
||||
@@ -29,8 +30,7 @@ type DialerClient interface {
|
||||
// implements splithttp.DialerClient in terms of direct network connections
|
||||
type DefaultDialerClient struct {
|
||||
transportConfig *Config
|
||||
download *http.Client
|
||||
upload *http.Client
|
||||
client *http.Client
|
||||
isH2 bool
|
||||
isH3 bool
|
||||
// pool of net.Conn, created using dialUploadConn
|
||||
@@ -79,7 +79,7 @@ func (c *DefaultDialerClient) OpenDownload(ctx context.Context, baseURL string)
|
||||
|
||||
req.Header = c.transportConfig.GetRequestHeader()
|
||||
|
||||
response, err := c.download.Do(req)
|
||||
response, err := c.client.Do(req)
|
||||
gotConn.Close()
|
||||
if err != nil {
|
||||
errors.LogInfoInner(ctx, err, "failed to send download http request")
|
||||
@@ -137,7 +137,7 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string,
|
||||
req.Header = c.transportConfig.GetRequestHeader()
|
||||
|
||||
if c.isH2 || c.isH3 {
|
||||
resp, err := c.upload.Do(req)
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -152,23 +152,39 @@ func (c *DefaultDialerClient) SendUploadRequest(ctx context.Context, url string,
|
||||
// safely retried. if instead req.Write is called multiple
|
||||
// times, the body is already drained after the first
|
||||
// request
|
||||
requestBytes := new(bytes.Buffer)
|
||||
common.Must(req.Write(requestBytes))
|
||||
requestBuff := new(bytes.Buffer)
|
||||
common.Must(req.Write(requestBuff))
|
||||
|
||||
var uploadConn any
|
||||
var h1UploadConn *H1Conn
|
||||
|
||||
for {
|
||||
uploadConn = c.uploadRawPool.Get()
|
||||
newConnection := uploadConn == nil
|
||||
if newConnection {
|
||||
uploadConn, err = c.dialUploadConn(context.WithoutCancel(ctx))
|
||||
newConn, err := c.dialUploadConn(context.WithoutCancel(ctx))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h1UploadConn = NewH1Conn(newConn)
|
||||
uploadConn = h1UploadConn
|
||||
} else {
|
||||
h1UploadConn = uploadConn.(*H1Conn)
|
||||
|
||||
// TODO: Replace 0 here with a config value later
|
||||
// Or add some other condition for optimization purposes
|
||||
if h1UploadConn.UnreadedResponsesCount > 0 {
|
||||
resp, err := http.ReadResponse(h1UploadConn.RespBufReader, req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while reading response: %s", err.Error())
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("got non-200 error response code: %d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, err = uploadConn.(net.Conn).Write(requestBytes.Bytes())
|
||||
|
||||
_, err := h1UploadConn.Write(requestBuff.Bytes())
|
||||
// if the write failed, we try another connection from
|
||||
// the pool, until the write on a new connection fails.
|
||||
// failed writes to a pooled connection are normal when
|
||||
|
@@ -105,6 +105,49 @@ func (c *Config) GetNormalizedXPaddingBytes() RandRangeConfig {
|
||||
return *c.XPaddingBytes
|
||||
}
|
||||
|
||||
func (m *Multiplexing) GetNormalizedCMaxReuseTimes() RandRangeConfig {
|
||||
if m.CMaxReuseTimes == nil {
|
||||
return RandRangeConfig{
|
||||
From: 0,
|
||||
To: 0,
|
||||
}
|
||||
}
|
||||
|
||||
return *m.CMaxReuseTimes
|
||||
}
|
||||
|
||||
func (m *Multiplexing) GetNormalizedCMaxLifetimeMs() RandRangeConfig {
|
||||
if m.CMaxLifetimeMs == nil || m.CMaxLifetimeMs.To == 0 {
|
||||
return RandRangeConfig{
|
||||
From: 0,
|
||||
To: 0,
|
||||
}
|
||||
}
|
||||
return *m.CMaxLifetimeMs
|
||||
}
|
||||
|
||||
func (m *Multiplexing) GetNormalizedMaxConnections() RandRangeConfig {
|
||||
if m.MaxConnections == nil {
|
||||
return RandRangeConfig{
|
||||
From: 0,
|
||||
To: 0,
|
||||
}
|
||||
}
|
||||
|
||||
return *m.MaxConnections
|
||||
}
|
||||
|
||||
func (m *Multiplexing) GetNormalizedMaxConcurrency() RandRangeConfig {
|
||||
if m.MaxConcurrency == nil {
|
||||
return RandRangeConfig{
|
||||
From: 0,
|
||||
To: 0,
|
||||
}
|
||||
}
|
||||
|
||||
return *m.MaxConcurrency
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
|
||||
return new(Config)
|
||||
|
@@ -33,6 +33,7 @@ type Config struct {
|
||||
ScMinPostsIntervalMs *RandRangeConfig `protobuf:"bytes,6,opt,name=scMinPostsIntervalMs,proto3" json:"scMinPostsIntervalMs,omitempty"`
|
||||
NoSSEHeader bool `protobuf:"varint,7,opt,name=noSSEHeader,proto3" json:"noSSEHeader,omitempty"`
|
||||
XPaddingBytes *RandRangeConfig `protobuf:"bytes,8,opt,name=xPaddingBytes,proto3" json:"xPaddingBytes,omitempty"`
|
||||
Xmux *Multiplexing `protobuf:"bytes,9,opt,name=xmux,proto3" json:"xmux,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
@@ -123,6 +124,13 @@ func (x *Config) GetXPaddingBytes() *RandRangeConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetXmux() *Multiplexing {
|
||||
if x != nil {
|
||||
return x.Xmux
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RandRangeConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -178,6 +186,77 @@ func (x *RandRangeConfig) GetTo() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
type Multiplexing struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
MaxConnections *RandRangeConfig `protobuf:"bytes,1,opt,name=maxConnections,proto3" json:"maxConnections,omitempty"`
|
||||
MaxConcurrency *RandRangeConfig `protobuf:"bytes,2,opt,name=maxConcurrency,proto3" json:"maxConcurrency,omitempty"`
|
||||
CMaxReuseTimes *RandRangeConfig `protobuf:"bytes,3,opt,name=cMaxReuseTimes,proto3" json:"cMaxReuseTimes,omitempty"`
|
||||
CMaxLifetimeMs *RandRangeConfig `protobuf:"bytes,4,opt,name=cMaxLifetimeMs,proto3" json:"cMaxLifetimeMs,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Multiplexing) Reset() {
|
||||
*x = Multiplexing{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_transport_internet_splithttp_config_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Multiplexing) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Multiplexing) ProtoMessage() {}
|
||||
|
||||
func (x *Multiplexing) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_splithttp_config_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Multiplexing.ProtoReflect.Descriptor instead.
|
||||
func (*Multiplexing) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_splithttp_config_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *Multiplexing) GetMaxConnections() *RandRangeConfig {
|
||||
if x != nil {
|
||||
return x.MaxConnections
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Multiplexing) GetMaxConcurrency() *RandRangeConfig {
|
||||
if x != nil {
|
||||
return x.MaxConcurrency
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Multiplexing) GetCMaxReuseTimes() *RandRangeConfig {
|
||||
if x != nil {
|
||||
return x.CMaxReuseTimes
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Multiplexing) GetCMaxLifetimeMs() *RandRangeConfig {
|
||||
if x != nil {
|
||||
return x.CMaxLifetimeMs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_transport_internet_splithttp_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_transport_internet_splithttp_config_proto_rawDesc = []byte{
|
||||
@@ -185,8 +264,8 @@ var file_transport_internet_splithttp_config_proto_rawDesc = []byte{
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2f, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x22, 0xea,
|
||||
0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x22, 0xaf,
|
||||
0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73,
|
||||
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74,
|
||||
0x68, 0x12, 0x4d, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28,
|
||||
@@ -221,23 +300,51 @@ var file_transport_internet_splithttp_config_proto_rawDesc = []byte{
|
||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74,
|
||||
0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x52, 0x0d, 0x78, 0x50, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x42, 0x79, 0x74, 0x65, 0x73,
|
||||
0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
||||
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
|
||||
0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x35, 0x0a, 0x0f, 0x52,
|
||||
0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12,
|
||||
0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x66, 0x72,
|
||||
0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02,
|
||||
0x74, 0x6f, 0x42, 0x85, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x12, 0x43, 0x0a, 0x04, 0x78, 0x6d, 0x75, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f,
|
||||
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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74,
|
||||
0x74, 0x70, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x52,
|
||||
0x04, 0x78, 0x6d, 0x75, 0x78, 0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45,
|
||||
0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
|
||||
0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
|
||||
0x22, 0x35, 0x0a, 0x0f, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x05, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x05, 0x52, 0x02, 0x74, 0x6f, 0x22, 0xfe, 0x02, 0x0a, 0x0c, 0x4d, 0x75, 0x6c, 0x74,
|
||||
0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x12, 0x5a, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x43,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x32, 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, 0x73, 0x70, 0x6c, 0x69, 0x74,
|
||||
0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5a, 0x0a, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75,
|
||||
0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70,
|
||||
0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x52, 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79,
|
||||
0x12, 0x5a, 0x0a, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x52, 0x65, 0x75, 0x73, 0x65, 0x54, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x50, 0x01, 0x5a, 0x36,
|
||||
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, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
||||
0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x73, 0x70, 0x6c,
|
||||
0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0xaa, 0x02, 0x21, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||
0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x48, 0x74, 0x74, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x33,
|
||||
0x65, 0x74, 0x2e, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e,
|
||||
0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x63, 0x4d,
|
||||
0x61, 0x78, 0x52, 0x65, 0x75, 0x73, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x0e,
|
||||
0x63, 0x4d, 0x61, 0x78, 0x4c, 0x69, 0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 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, 0x73,
|
||||
0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0x2e, 0x52, 0x61, 0x6e, 0x64, 0x52, 0x61, 0x6e,
|
||||
0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x63, 0x4d, 0x61, 0x78, 0x4c, 0x69,
|
||||
0x66, 0x65, 0x74, 0x69, 0x6d, 0x65, 0x4d, 0x73, 0x42, 0x85, 0x01, 0x0a, 0x25, 0x63, 0x6f, 0x6d,
|
||||
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, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74,
|
||||
0x74, 0x70, 0x50, 0x01, 0x5a, 0x36, 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,
|
||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x65, 0x74, 0x2f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x68, 0x74, 0x74, 0x70, 0xaa, 0x02, 0x21, 0x58,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x48, 0x74, 0x74, 0x70,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -252,23 +359,29 @@ func file_transport_internet_splithttp_config_proto_rawDescGZIP() []byte {
|
||||
return file_transport_internet_splithttp_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_transport_internet_splithttp_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_transport_internet_splithttp_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_transport_internet_splithttp_config_proto_goTypes = []any{
|
||||
(*Config)(nil), // 0: xray.transport.internet.splithttp.Config
|
||||
(*RandRangeConfig)(nil), // 1: xray.transport.internet.splithttp.RandRangeConfig
|
||||
nil, // 2: xray.transport.internet.splithttp.Config.HeaderEntry
|
||||
(*Multiplexing)(nil), // 2: xray.transport.internet.splithttp.Multiplexing
|
||||
nil, // 3: xray.transport.internet.splithttp.Config.HeaderEntry
|
||||
}
|
||||
var file_transport_internet_splithttp_config_proto_depIdxs = []int32{
|
||||
2, // 0: xray.transport.internet.splithttp.Config.header:type_name -> xray.transport.internet.splithttp.Config.HeaderEntry
|
||||
1, // 1: xray.transport.internet.splithttp.Config.scMaxConcurrentPosts:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 2: xray.transport.internet.splithttp.Config.scMaxEachPostBytes:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 3: xray.transport.internet.splithttp.Config.scMinPostsIntervalMs:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 4: xray.transport.internet.splithttp.Config.xPaddingBytes:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
5, // [5:5] is the sub-list for method output_type
|
||||
5, // [5:5] is the sub-list for method input_type
|
||||
5, // [5:5] is the sub-list for extension type_name
|
||||
5, // [5:5] is the sub-list for extension extendee
|
||||
0, // [0:5] is the sub-list for field type_name
|
||||
3, // 0: xray.transport.internet.splithttp.Config.header:type_name -> xray.transport.internet.splithttp.Config.HeaderEntry
|
||||
1, // 1: xray.transport.internet.splithttp.Config.scMaxConcurrentPosts:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 2: xray.transport.internet.splithttp.Config.scMaxEachPostBytes:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 3: xray.transport.internet.splithttp.Config.scMinPostsIntervalMs:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 4: xray.transport.internet.splithttp.Config.xPaddingBytes:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
2, // 5: xray.transport.internet.splithttp.Config.xmux:type_name -> xray.transport.internet.splithttp.Multiplexing
|
||||
1, // 6: xray.transport.internet.splithttp.Multiplexing.maxConnections:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 7: xray.transport.internet.splithttp.Multiplexing.maxConcurrency:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 8: xray.transport.internet.splithttp.Multiplexing.cMaxReuseTimes:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
1, // 9: xray.transport.internet.splithttp.Multiplexing.cMaxLifetimeMs:type_name -> xray.transport.internet.splithttp.RandRangeConfig
|
||||
10, // [10:10] is the sub-list for method output_type
|
||||
10, // [10:10] is the sub-list for method input_type
|
||||
10, // [10:10] is the sub-list for extension type_name
|
||||
10, // [10:10] is the sub-list for extension extendee
|
||||
0, // [0:10] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_transport_internet_splithttp_config_proto_init() }
|
||||
@@ -301,6 +414,18 @@ func file_transport_internet_splithttp_config_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_transport_internet_splithttp_config_proto_msgTypes[2].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*Multiplexing); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
@@ -308,7 +433,7 @@ func file_transport_internet_splithttp_config_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_transport_internet_splithttp_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 3,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
@@ -15,9 +15,17 @@ message Config {
|
||||
RandRangeConfig scMinPostsIntervalMs = 6;
|
||||
bool noSSEHeader = 7;
|
||||
RandRangeConfig xPaddingBytes = 8;
|
||||
Multiplexing xmux = 9;
|
||||
}
|
||||
|
||||
message RandRangeConfig {
|
||||
int32 from = 1;
|
||||
int32 to = 2;
|
||||
}
|
||||
|
||||
message Multiplexing {
|
||||
RandRangeConfig maxConnections = 1;
|
||||
RandRangeConfig maxConcurrency = 2;
|
||||
RandRangeConfig cMaxReuseTimes = 3;
|
||||
RandRangeConfig cMaxLifetimeMs = 4;
|
||||
}
|
||||
|
@@ -11,6 +11,7 @@ type splitConn struct {
|
||||
reader io.ReadCloser
|
||||
remoteAddr net.Addr
|
||||
localAddr net.Addr
|
||||
onClose func()
|
||||
}
|
||||
|
||||
func (c *splitConn) Write(b []byte) (int, error) {
|
||||
@@ -22,6 +23,10 @@ func (c *splitConn) Read(b []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (c *splitConn) Close() error {
|
||||
if c.onClose != nil {
|
||||
c.onClose()
|
||||
}
|
||||
|
||||
err := c.writer.Close()
|
||||
err2 := c.reader.Close()
|
||||
if err != nil {
|
||||
|
@@ -41,32 +41,51 @@ type dialerConf struct {
|
||||
}
|
||||
|
||||
var (
|
||||
globalDialerMap map[dialerConf]DialerClient
|
||||
globalDialerMap map[dialerConf]*muxManager
|
||||
globalDialerAccess sync.Mutex
|
||||
)
|
||||
|
||||
func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) DialerClient {
|
||||
func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (DialerClient, *muxResource) {
|
||||
if browser_dialer.HasBrowserDialer() {
|
||||
return &BrowserDialerClient{}
|
||||
return &BrowserDialerClient{}, nil
|
||||
}
|
||||
|
||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||
isH2 := tlsConfig != nil && !(len(tlsConfig.NextProtocol) == 1 && tlsConfig.NextProtocol[0] == "http/1.1")
|
||||
isH3 := tlsConfig != nil && (len(tlsConfig.NextProtocol) == 1 && tlsConfig.NextProtocol[0] == "h3")
|
||||
|
||||
globalDialerAccess.Lock()
|
||||
defer globalDialerAccess.Unlock()
|
||||
|
||||
if globalDialerMap == nil {
|
||||
globalDialerMap = make(map[dialerConf]DialerClient)
|
||||
globalDialerMap = make(map[dialerConf]*muxManager)
|
||||
}
|
||||
|
||||
key := dialerConf{dest, streamSettings}
|
||||
|
||||
muxManager, found := globalDialerMap[key]
|
||||
|
||||
if !found {
|
||||
transportConfig := streamSettings.ProtocolSettings.(*Config)
|
||||
var mux Multiplexing
|
||||
if transportConfig.Xmux != nil {
|
||||
mux = *transportConfig.Xmux
|
||||
}
|
||||
|
||||
muxManager = NewMuxManager(mux, func() interface{} {
|
||||
return createHTTPClient(dest, streamSettings)
|
||||
})
|
||||
globalDialerMap[key] = muxManager
|
||||
}
|
||||
|
||||
res := muxManager.GetResource(ctx)
|
||||
return res.Resource.(DialerClient), res
|
||||
}
|
||||
|
||||
func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStreamConfig) DialerClient {
|
||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||
isH2 := tlsConfig != nil && !(len(tlsConfig.NextProtocol) == 1 && tlsConfig.NextProtocol[0] == "http/1.1")
|
||||
isH3 := tlsConfig != nil && (len(tlsConfig.NextProtocol) == 1 && tlsConfig.NextProtocol[0] == "h3")
|
||||
|
||||
if isH3 {
|
||||
dest.Network = net.Network_UDP
|
||||
}
|
||||
if client, found := globalDialerMap[dialerConf{dest, streamSettings}]; found {
|
||||
return client
|
||||
}
|
||||
|
||||
var gotlsConfig *gotls.Config
|
||||
|
||||
@@ -74,6 +93,8 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||
gotlsConfig = tlsConfig.GetTLSConfig(tls.WithDestination(dest))
|
||||
}
|
||||
|
||||
transportConfig := streamSettings.ProtocolSettings.(*Config)
|
||||
|
||||
dialContext := func(ctxInner context.Context) (net.Conn, error) {
|
||||
conn, err := internet.DialSystem(ctxInner, dest, streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
@@ -94,8 +115,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
var downloadTransport http.RoundTripper
|
||||
var uploadTransport http.RoundTripper
|
||||
var transport http.RoundTripper
|
||||
|
||||
if isH3 {
|
||||
quicConfig := &quic.Config{
|
||||
@@ -107,7 +127,7 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||
MaxIncomingStreams: -1,
|
||||
KeepAlivePeriod: h3KeepalivePeriod,
|
||||
}
|
||||
roundTripper := &http3.RoundTripper{
|
||||
transport = &http3.RoundTripper{
|
||||
QUICConfig: quicConfig,
|
||||
TLSClientConfig: gotlsConfig,
|
||||
Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
||||
@@ -147,23 +167,20 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||
return quic.DialEarly(ctx, udpConn, udpAddr, tlsCfg, cfg)
|
||||
},
|
||||
}
|
||||
downloadTransport = roundTripper
|
||||
uploadTransport = roundTripper
|
||||
} else if isH2 {
|
||||
downloadTransport = &http2.Transport{
|
||||
transport = &http2.Transport{
|
||||
DialTLSContext: func(ctxInner context.Context, network string, addr string, cfg *gotls.Config) (net.Conn, error) {
|
||||
return dialContext(ctxInner)
|
||||
},
|
||||
IdleConnTimeout: connIdleTimeout,
|
||||
ReadIdleTimeout: h2KeepalivePeriod,
|
||||
}
|
||||
uploadTransport = downloadTransport
|
||||
} else {
|
||||
httpDialContext := func(ctxInner context.Context, network string, addr string) (net.Conn, error) {
|
||||
return dialContext(ctxInner)
|
||||
}
|
||||
|
||||
downloadTransport = &http.Transport{
|
||||
transport = &http.Transport{
|
||||
DialTLSContext: httpDialContext,
|
||||
DialContext: httpDialContext,
|
||||
IdleConnTimeout: connIdleTimeout,
|
||||
@@ -171,17 +188,12 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||
// http.Client and our custom dial context.
|
||||
DisableKeepAlives: true,
|
||||
}
|
||||
// we use uploadRawPool for that
|
||||
uploadTransport = nil
|
||||
}
|
||||
|
||||
client := &DefaultDialerClient{
|
||||
transportConfig: streamSettings.ProtocolSettings.(*Config),
|
||||
download: &http.Client{
|
||||
Transport: downloadTransport,
|
||||
},
|
||||
upload: &http.Client{
|
||||
Transport: uploadTransport,
|
||||
transportConfig: transportConfig,
|
||||
client: &http.Client{
|
||||
Transport: transport,
|
||||
},
|
||||
isH2: isH2,
|
||||
isH3: isH3,
|
||||
@@ -189,7 +201,6 @@ func getHTTPClient(ctx context.Context, dest net.Destination, streamSettings *in
|
||||
dialUploadConn: dialContext,
|
||||
}
|
||||
|
||||
globalDialerMap[dialerConf{dest, streamSettings}] = client
|
||||
return client
|
||||
}
|
||||
|
||||
@@ -223,7 +234,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
||||
requestURL.Path = transportConfiguration.GetNormalizedPath() + sessionIdUuid.String()
|
||||
requestURL.RawQuery = transportConfiguration.GetNormalizedQuery()
|
||||
|
||||
httpClient := getHTTPClient(ctx, dest, streamSettings)
|
||||
httpClient, muxResource := getHTTPClient(ctx, dest, streamSettings)
|
||||
|
||||
maxUploadSize := scMaxEachPostBytes.roll()
|
||||
// WithSizeLimit(0) will still allow single bytes to pass, and a lot of
|
||||
@@ -231,7 +242,15 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
||||
// uploadWriter wrapper, exact size limits can be enforced
|
||||
uploadPipeReader, uploadPipeWriter := pipe.New(pipe.WithSizeLimit(maxUploadSize - 1))
|
||||
|
||||
if muxResource != nil {
|
||||
muxResource.OpenRequests.Add(1)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if muxResource != nil {
|
||||
defer muxResource.OpenRequests.Add(-1)
|
||||
}
|
||||
|
||||
requestsLimiter := semaphore.New(int(scMaxConcurrentPosts.roll()))
|
||||
var requestCounter int64
|
||||
|
||||
@@ -267,7 +286,6 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
||||
&buf.MultiBufferContainer{MultiBuffer: chunk},
|
||||
int64(chunk.Len()),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
errors.LogInfoInner(ctx, err, "failed to send upload")
|
||||
uploadPipeReader.Interrupt()
|
||||
|
19
transport/internet/splithttp/h1_conn.go
Normal file
19
transport/internet/splithttp/h1_conn.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package splithttp
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
)
|
||||
|
||||
type H1Conn struct {
|
||||
UnreadedResponsesCount int
|
||||
RespBufReader *bufio.Reader
|
||||
net.Conn
|
||||
}
|
||||
|
||||
func NewH1Conn(conn net.Conn) *H1Conn {
|
||||
return &H1Conn{
|
||||
RespBufReader: bufio.NewReader(conn),
|
||||
Conn: conn,
|
||||
}
|
||||
}
|
102
transport/internet/splithttp/mux.go
Normal file
102
transport/internet/splithttp/mux.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package splithttp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
)
|
||||
|
||||
type muxResource struct {
|
||||
Resource interface{}
|
||||
OpenRequests atomic.Int32
|
||||
leftUsage int32
|
||||
expirationTime time.Time
|
||||
}
|
||||
|
||||
type muxManager struct {
|
||||
newResourceFn func() interface{}
|
||||
config Multiplexing
|
||||
concurrency int32
|
||||
connections int32
|
||||
instances []*muxResource
|
||||
}
|
||||
|
||||
func NewMuxManager(config Multiplexing, newResource func() interface{}) *muxManager {
|
||||
return &muxManager{
|
||||
config: config,
|
||||
concurrency: config.GetNormalizedMaxConcurrency().roll(),
|
||||
connections: config.GetNormalizedMaxConnections().roll(),
|
||||
newResourceFn: newResource,
|
||||
instances: make([]*muxResource, 0),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *muxManager) GetResource(ctx context.Context) *muxResource {
|
||||
m.removeExpiredConnections(ctx)
|
||||
|
||||
if m.connections > 0 && len(m.instances) < int(m.connections) {
|
||||
errors.LogDebug(ctx, "xmux: creating client, connections=", len(m.instances))
|
||||
return m.newResource()
|
||||
}
|
||||
|
||||
if len(m.instances) == 0 {
|
||||
errors.LogDebug(ctx, "xmux: creating client because instances is empty, connections=", len(m.instances))
|
||||
return m.newResource()
|
||||
}
|
||||
|
||||
clients := make([]*muxResource, 0)
|
||||
if m.concurrency > 0 {
|
||||
for _, client := range m.instances {
|
||||
openRequests := client.OpenRequests.Load()
|
||||
if openRequests < m.concurrency {
|
||||
clients = append(clients, client)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
clients = m.instances
|
||||
}
|
||||
|
||||
if len(clients) == 0 {
|
||||
errors.LogDebug(ctx, "xmux: creating client because concurrency was hit, total clients=", len(m.instances))
|
||||
return m.newResource()
|
||||
}
|
||||
|
||||
client := clients[rand.Intn(len(clients))]
|
||||
if client.leftUsage > 0 {
|
||||
client.leftUsage -= 1
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func (m *muxManager) newResource() *muxResource {
|
||||
leftUsage := int32(-1)
|
||||
if x := m.config.GetNormalizedCMaxReuseTimes().roll(); x > 0 {
|
||||
leftUsage = x - 1
|
||||
}
|
||||
expirationTime := time.UnixMilli(0)
|
||||
if x := m.config.GetNormalizedCMaxLifetimeMs().roll(); x > 0 {
|
||||
expirationTime = time.Now().Add(time.Duration(x) * time.Millisecond)
|
||||
}
|
||||
|
||||
client := &muxResource{
|
||||
Resource: m.newResourceFn(),
|
||||
leftUsage: leftUsage,
|
||||
expirationTime: expirationTime,
|
||||
}
|
||||
m.instances = append(m.instances, client)
|
||||
return client
|
||||
}
|
||||
|
||||
func (m *muxManager) removeExpiredConnections(ctx context.Context) {
|
||||
for i := 0; i < len(m.instances); i++ {
|
||||
client := m.instances[i]
|
||||
if client.leftUsage == 0 || (client.expirationTime != time.UnixMilli(0) && time.Now().After(client.expirationTime)) {
|
||||
errors.LogDebug(ctx, "xmux: removing client, leftUsage = ", client.leftUsage, ", expirationTime = ", client.expirationTime)
|
||||
m.instances = append(m.instances[:i], m.instances[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
88
transport/internet/splithttp/mux_test.go
Normal file
88
transport/internet/splithttp/mux_test.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package splithttp_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
. "github.com/xtls/xray-core/transport/internet/splithttp"
|
||||
)
|
||||
|
||||
type fakeRoundTripper struct{}
|
||||
|
||||
func TestMaxConnections(t *testing.T) {
|
||||
config := Multiplexing{
|
||||
MaxConnections: &RandRangeConfig{From: 4, To: 4},
|
||||
}
|
||||
|
||||
mux := NewMuxManager(config, func() interface{} {
|
||||
return &fakeRoundTripper{}
|
||||
})
|
||||
|
||||
clients := make(map[interface{}]struct{})
|
||||
for i := 0; i < 8; i++ {
|
||||
clients[mux.GetResource(context.Background())] = struct{}{}
|
||||
}
|
||||
|
||||
if len(clients) != 4 {
|
||||
t.Error("did not get 4 distinct clients, got ", len(clients))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCMaxReuseTimes(t *testing.T) {
|
||||
config := Multiplexing{
|
||||
CMaxReuseTimes: &RandRangeConfig{From: 2, To: 2},
|
||||
}
|
||||
|
||||
mux := NewMuxManager(config, func() interface{} {
|
||||
return &fakeRoundTripper{}
|
||||
})
|
||||
|
||||
clients := make(map[interface{}]struct{})
|
||||
for i := 0; i < 64; i++ {
|
||||
clients[mux.GetResource(context.Background())] = struct{}{}
|
||||
}
|
||||
|
||||
if len(clients) != 32 {
|
||||
t.Error("did not get 32 distinct clients, got ", len(clients))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMaxConcurrency(t *testing.T) {
|
||||
config := Multiplexing{
|
||||
MaxConcurrency: &RandRangeConfig{From: 2, To: 2},
|
||||
}
|
||||
|
||||
mux := NewMuxManager(config, func() interface{} {
|
||||
return &fakeRoundTripper{}
|
||||
})
|
||||
|
||||
clients := make(map[interface{}]struct{})
|
||||
for i := 0; i < 64; i++ {
|
||||
client := mux.GetResource(context.Background())
|
||||
client.OpenRequests.Add(1)
|
||||
clients[client] = struct{}{}
|
||||
}
|
||||
|
||||
if len(clients) != 32 {
|
||||
t.Error("did not get 32 distinct clients, got ", len(clients))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
config := Multiplexing{}
|
||||
|
||||
mux := NewMuxManager(config, func() interface{} {
|
||||
return &fakeRoundTripper{}
|
||||
})
|
||||
|
||||
clients := make(map[interface{}]struct{})
|
||||
for i := 0; i < 64; i++ {
|
||||
client := mux.GetResource(context.Background())
|
||||
client.OpenRequests.Add(1)
|
||||
clients[client] = struct{}{}
|
||||
}
|
||||
|
||||
if len(clients) != 1 {
|
||||
t.Error("did not get 1 distinct clients, got ", len(clients))
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user