Compare commits

...
7 Commits
Author SHA1 Message Date
Fangliding c84753dae6 fmt 2026-09-20 17:09:02 +08:00
Fangliding d17906c2f1 Optimize logger 2026-09-20 17:00:49 +08:00
RPRX 52a412d9e2 Xray-core v26.9.9
Sponsor & Donation & NFTs: https://github.com/XTLS/Xray-core/issues/3668
Project X Channel: https://t.me/projectXtls

Announcement of NFTs by Project X: https://github.com/XTLS/Xray-core/discussions/3633
Project X NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1

VLESS Post-Quantum Encryption: https://github.com/XTLS/Xray-core/pull/5067
VLESS NFT: https://opensea.io/collection/vless

XHTTP: Beyond REALITY: https://github.com/XTLS/Xray-core/discussions/4113
REALITY NFT: https://opensea.io/assets/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2
2026-09-08 22:25:43 +00:00
LjhAUMEMandRPRX 18a1b5042a Finalmask: Make "udpHop" a new UDP mask (#6327)
https://github.com/XTLS/Xray-core/pull/6327#issuecomment-5592421364

---------

Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
2026-09-08 22:15:02 +00:00
patterniha c26d2eda24 Direct/Freedom outbound: Skip domain resolution and finalRules when using sockopt.dialerProxy (#6742)
https://github.com/XTLS/Xray-core/pull/6058#issuecomment-5578800461
2026-09-08 18:45:38 +00:00
风扇滑翔翼 a1bf968be9 VLESS config: Fix validateOutboundTransportSecurity() (#6741)
Fixes https://github.com/XTLS/Xray-core/issues/6737#issuecomment-5587270250
2026-09-08 18:18:12 +00:00
风扇滑翔翼 c037ccd98d infra/vformat/main.go: Refactor (#6739)
https://github.com/XTLS/Xray-core/pull/6327#issuecomment-5581733848
2026-09-08 17:19:15 +00:00
100 changed files with 1341 additions and 1111 deletions
+1 -3
View File
@@ -67,9 +67,7 @@ jobs:
check-latest: true check-latest: true
cache: false cache: false
- name: Check Format - name: Check Format
run: | run: go run ./infra/vformat/main.go -mode check -pwd ./
go install -v mvdan.cc/gofumpt@latest
go run ./infra/vformat/main.go -mode check -pwd ./
test: test:
needs: check-assets needs: check-assets
+1 -1
View File
@@ -23,7 +23,7 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
} }
if fakeDNSEngine == nil { if fakeDNSEngine == nil {
errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used").AtError() errNotInit := errors.New("FakeDNSEngine is not initialized, but such a sniffer is used")
return protocolSnifferWithMetadata{}, errNotInit return protocolSnifferWithMetadata{}, errNotInit
} }
return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) { return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
+1 -1
View File
@@ -28,7 +28,7 @@ func toNetIP(addrs []net.Address) ([]net.IP, error) {
if addr.Family().IsIP() { if addr.Family().IsIP() {
ips = append(ips, addr.IP()) ips = append(ips, addr.IP())
} else { } else {
return nil, errors.New("Failed to convert address", addr, "to Net IP.").AtWarning() return nil, errors.New("Failed to convert address", addr, "to Net IP.")
} }
} }
return ips, nil return ips, nil
+2 -2
View File
@@ -188,10 +188,10 @@ func parseResponse(payload []byte) (*IPRecord, error) {
var parser dnsmessage.Parser var parser dnsmessage.Parser
h, err := parser.Start(payload) h, err := parser.Start(payload)
if err != nil { if err != nil {
return nil, errors.New("failed to parse DNS response").Base(err).AtWarning() return nil, errors.New("failed to parse DNS response").Base(err)
} }
if err := parser.SkipAllQuestions(); err != nil { if err := parser.SkipAllQuestions(); err != nil {
return nil, errors.New("failed to skip questions in DNS response").Base(err).AtWarning() return nil, errors.New("failed to skip questions in DNS response").Base(err)
} }
now := time.Now() now := time.Now()
+3 -3
View File
@@ -58,7 +58,7 @@ func NewFakeDNSHolder() (*Holder, error) {
var err error var err error
if fkdns, err = NewFakeDNSHolderConfigOnly(nil); err != nil { if fkdns, err = NewFakeDNSHolderConfigOnly(nil); err != nil {
return nil, errors.New("Unable to create Fake Dns Engine").Base(err).AtError() return nil, errors.New("Unable to create Fake Dns Engine").Base(err)
} }
err = fkdns.initialize(dns.FakeIPv4Pool, 65535) err = fkdns.initialize(dns.FakeIPv4Pool, 65535)
if err != nil { if err != nil {
@@ -80,13 +80,13 @@ func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
var err error var err error
if _, ipRange, err = net.ParseCIDR(ipPoolCidr); err != nil { if _, ipRange, err = net.ParseCIDR(ipPoolCidr); err != nil {
return errors.New("Unable to parse CIDR for Fake DNS IP assignment").Base(err).AtError() return errors.New("Unable to parse CIDR for Fake DNS IP assignment").Base(err)
} }
ones, bits := ipRange.Mask.Size() ones, bits := ipRange.Mask.Size()
rooms := bits - ones rooms := bits - ones
if math.Log2(float64(lruSize)) >= float64(rooms) { if math.Log2(float64(lruSize)) >= float64(rooms) {
return errors.New("LRU size is bigger than subnet size").AtError() return errors.New("LRU size is bigger than subnet size")
} }
fkdns.domainToIP = cache.NewLru(lruSize) fkdns.domainToIP = cache.NewLru(lruSize)
fkdns.ipRange = ipRange fkdns.ipRange = ipRange
+4 -4
View File
@@ -84,7 +84,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
if dest.Network == net.Network_UDP { // UDP classic DNS mode if dest.Network == net.Network_UDP { // UDP classic DNS mode
return NewClassicNameServer(dest, dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP), nil return NewClassicNameServer(dest, dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP), nil
} }
return nil, errors.New("No available name server could be created from ", dest).AtWarning() return nil, errors.New("No available name server could be created from ", dest)
} }
// NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs. // NewClient creates a DNS client managing a name server with client IP, domain rules and expected IPs.
@@ -102,7 +102,7 @@ func NewClient(
// Create a new server for each client for now // Create a new server for each client for now
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP) server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
if err != nil { if err != nil {
return errors.New("failed to create nameserver").Base(err).AtWarning() return errors.New("failed to create nameserver").Base(err)
} }
_, isLocalDNS := server.(*LocalNameServer) _, isLocalDNS := server.(*LocalNameServer)
@@ -113,7 +113,7 @@ func NewClient(
if len(ns.ExpectedIp) > 0 { if len(ns.ExpectedIp) > 0 {
expectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.ExpectedIp) expectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.ExpectedIp)
if err != nil { if err != nil {
return errors.New("failed to create expected ip matcher").Base(err).AtWarning() return errors.New("failed to create expected ip matcher").Base(err)
} }
} }
@@ -122,7 +122,7 @@ func NewClient(
if len(ns.UnexpectedIp) > 0 { if len(ns.UnexpectedIp) > 0 {
unexpectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.UnexpectedIp) unexpectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.UnexpectedIp)
if err != nil { if err != nil {
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning() return errors.New("failed to create unexpected ip matcher").Base(err)
} }
} }
+2 -2
View File
@@ -27,7 +27,7 @@ func (s *FakeDNSServer) IsDisableCache() bool {
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOption) ([]net.IP, uint32, error) { func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOption) ([]net.IP, uint32, error) {
if f.fakeDNSEngine == nil { if f.fakeDNSEngine == nil {
return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError() return nil, 0, errors.New("Unable to locate a fake DNS Engine")
} }
var ips []net.Address var ips []net.Address
@@ -39,7 +39,7 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOp
netIP, err := toNetIP(ips) netIP, err := toNetIP(ips)
if err != nil { if err != nil {
return nil, 0, errors.New("Unable to convert IP to net ip").Base(err).AtError() return nil, 0, errors.New("Unable to convert IP to net ip").Base(err)
} }
errors.LogInfo(ctx, f.Name(), " got answer: ", domain, " -> ", ips) errors.LogInfo(ctx, f.Name(), " got answer: ", domain, " -> ", ips)
+6 -2
View File
@@ -89,10 +89,10 @@ func (g *Instance) startInternal() error {
g.active = true g.active = true
if err := g.initAccessLogger(); err != nil { if err := g.initAccessLogger(); err != nil {
return errors.New("failed to initialize access logger").Base(err).AtWarning() return errors.New("failed to initialize access logger").Base(err)
} }
if err := g.initErrorLogger(); err != nil { if err := g.initErrorLogger(); err != nil {
return errors.New("failed to initialize error logger").Base(err).AtWarning() return errors.New("failed to initialize error logger").Base(err)
} }
return nil return nil
@@ -141,6 +141,10 @@ func (g *Instance) Handle(msg log.Message) {
} }
} }
func (g *Instance) Severity() log.Severity {
return g.config.ErrorLogLevel
}
// Close implements common.Closable.Close(). // Close implements common.Closable.Close().
func (g *Instance) Close() error { func (g *Instance) Close() error {
errors.LogDebug(context.Background(), "Logger closing") errors.LogDebug(context.Background(), "Logger closing")
+1 -1
View File
@@ -66,7 +66,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
} }
mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings) mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings)
if err != nil { if err != nil {
return nil, errors.New("failed to parse stream config").Base(err).AtWarning() return nil, errors.New("failed to parse stream config").Base(err)
} }
newCtx := session.ContextWithInbound(ctx, &session.Inbound{Tag: tag, Source: src}) newCtx := session.ContextWithInbound(ctx, &session.Inbound{Tag: tag, Source: src})
+1 -1
View File
@@ -165,7 +165,7 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
receiverSettings, ok := rawReceiverSettings.(*proxyman.ReceiverConfig) receiverSettings, ok := rawReceiverSettings.(*proxyman.ReceiverConfig)
if !ok { if !ok {
return nil, errors.New("not a ReceiverConfig").AtError() return nil, errors.New("not a ReceiverConfig")
} }
streamSettings := receiverSettings.StreamSettings streamSettings := receiverSettings.StreamSettings
+2 -2
View File
@@ -142,7 +142,7 @@ func (w *tcpWorker) Start() error {
go w.callback(conn) go w.callback(conn)
}) })
if err != nil { if err != nil {
return errors.New("failed to listen TCP on ", w.port).AtWarning().Base(err) return errors.New("failed to listen TCP on ", w.port).Base(err)
} }
w.hub = hub w.hub = hub
return nil return nil
@@ -528,7 +528,7 @@ func (w *dsWorker) Start() error {
go w.callback(conn) go w.callback(conn)
}) })
if err != nil { if err != nil {
return errors.New("failed to listen Unix Domain Socket on ", w.address).AtWarning().Base(err) return errors.New("failed to listen Unix Domain Socket on ", w.address).Base(err)
} }
w.hub = hub w.hub = hub
return nil return nil
+2 -2
View File
@@ -87,7 +87,7 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
h.senderSettings = s h.senderSettings = s
mss, err := internet.ToMemoryStreamConfig(s.StreamSettings) mss, err := internet.ToMemoryStreamConfig(s.StreamSettings)
if err != nil { if err != nil {
return nil, errors.New("failed to parse stream settings").Base(err).AtWarning() return nil, errors.New("failed to parse stream settings").Base(err)
} }
h.streamSettings = mss h.streamSettings = mss
default: default:
@@ -217,7 +217,7 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 { if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 {
switch h.udp443 { switch h.udp443 {
case "reject": case "reject":
test(errors.New("XUDP rejected UDP/443 traffic").AtInfo()) test(errors.New("XUDP rejected UDP/443 traffic"))
return return
case "skip": case "skip":
goto out goto out
+2 -2
View File
@@ -68,13 +68,13 @@ func (p *Portal) HandleConnection(ctx context.Context, link *transport.Link) err
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1] ob := outbounds[len(outbounds)-1]
if ob == nil { if ob == nil {
return errors.New("outbound metadata not found").AtError() return errors.New("outbound metadata not found")
} }
if isDomain(ob.Target, p.domain) { if isDomain(ob.Target, p.domain) {
muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{}) muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{})
if err != nil { if err != nil {
return errors.New("failed to create mux client worker").Base(err).AtWarning() return errors.New("failed to create mux client worker").Base(err)
} }
worker, err := NewPortalWorker(muxClient) worker, err := NewPortalWorker(muxClient)
+2 -2
View File
@@ -115,7 +115,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
} }
if conds.Len() == 0 { if conds.Len() == 0 {
return nil, errors.New("this rule has no effective fields").AtWarning() return nil, errors.New("this rule has no effective fields")
} }
return conds, nil return conds, nil
@@ -145,7 +145,7 @@ func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatch
} }
s, ok := i.(*StrategyLeastLoadConfig) s, ok := i.(*StrategyLeastLoadConfig)
if !ok { if !ok {
return nil, errors.New("not a StrategyLeastLoadConfig").AtError() return nil, errors.New("not a StrategyLeastLoadConfig")
} }
leastLoadStrategy := NewLeastLoadStrategy(s) leastLoadStrategy := NewLeastLoadStrategy(s)
return &Balancer{ return &Balancer{
+3 -3
View File
@@ -10,12 +10,12 @@ import (
// [,) // [,)
func RandBetween(from int64, to int64) int64 { func RandBetween(from int64, to int64) int64 {
if from == to {
return from
}
if from > to { if from > to {
from, to = to, from from, to = to, from
} }
if d := to - from; d == 0 || d == 1 {
return from
}
bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from)) bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from))
return from + bigInt.Int64() return from + bigInt.Int64()
} }
+13 -65
View File
@@ -18,17 +18,12 @@ type hasInnerError interface {
Unwrap() error Unwrap() error
} }
type hasSeverity interface {
Severity() log.Severity
}
// Error is an error object with underlying error. // Error is an error object with underlying error.
type Error struct { type Error struct {
prefix []interface{} prefix []interface{}
message []interface{} message []interface{}
caller string caller string
inner error inner error
severity log.Severity
} }
// Error implements error.Error(). // Error implements error.Error().
@@ -69,46 +64,6 @@ func (err *Error) Base(e error) *Error {
return err return err
} }
func (err *Error) atSeverity(s log.Severity) *Error {
err.severity = s
return err
}
func (err *Error) Severity() log.Severity {
if err.inner == nil {
return err.severity
}
if s, ok := err.inner.(hasSeverity); ok {
as := s.Severity()
if as < err.severity {
return as
}
}
return err.severity
}
// AtDebug sets the severity to debug.
func (err *Error) AtDebug() *Error {
return err.atSeverity(log.Severity_Debug)
}
// AtInfo sets the severity to info.
func (err *Error) AtInfo() *Error {
return err.atSeverity(log.Severity_Info)
}
// AtWarning sets the severity to warning.
func (err *Error) AtWarning() *Error {
return err.atSeverity(log.Severity_Warning)
}
// AtError sets the severity to error.
func (err *Error) AtError() *Error {
return err.atSeverity(log.Severity_Error)
}
// String returns the string representation of this error. // String returns the string representation of this error.
func (err *Error) String() string { func (err *Error) String() string {
return err.Error() return err.Error()
@@ -132,9 +87,8 @@ func New(msg ...interface{}) *Error {
details = details[:i] details = details[:i]
} }
return &Error{ return &Error{
message: msg, message: msg,
severity: log.Severity_Info, caller: details,
caller: details,
} }
} }
@@ -171,6 +125,9 @@ func LogErrorInner(ctx context.Context, inner error, msg ...interface{}) {
} }
func doLog(ctx context.Context, inner error, severity log.Severity, msg ...interface{}) { func doLog(ctx context.Context, inner error, severity log.Severity, msg ...interface{}) {
if log.GetSeverity() < severity {
return
}
pc, _, _, _ := runtime.Caller(2) pc, _, _, _ := runtime.Caller(2)
details := runtime.FuncForPC(pc).Name() details := runtime.FuncForPC(pc).Name()
if len(details) >= trim { if len(details) >= trim {
@@ -181,10 +138,9 @@ func doLog(ctx context.Context, inner error, severity log.Severity, msg ...inter
details = details[:i] details = details[:i]
} }
err := &Error{ err := &Error{
message: msg, message: msg,
severity: severity, caller: details,
caller: details, inner: inner,
inner: inner,
} }
if ctx != nil && ctx != context.Background() { if ctx != nil && ctx != context.Background() {
id := uint32(c.IDFromContext(ctx)) id := uint32(c.IDFromContext(ctx))
@@ -193,7 +149,7 @@ func doLog(ctx context.Context, inner error, severity log.Severity, msg ...inter
} }
} }
log.Record(&log.GeneralMessage{ log.Record(&log.GeneralMessage{
Severity: GetSeverity(err), Severity: severity,
Content: err, Content: err,
}) })
} }
@@ -217,11 +173,3 @@ L:
} }
return err return err
} }
// GetSeverity returns the actual severity of the error, including inner errors.
func GetSeverity(err error) log.Severity {
if s, ok := err.(hasSeverity); ok {
return s.Severity()
}
return log.Severity_Info
}
+6 -15
View File
@@ -7,30 +7,21 @@ import (
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
. "github.com/xtls/xray-core/common/errors" . "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log"
) )
func TestError(t *testing.T) { func TestError(t *testing.T) {
err := New("TestError") err := New("TestError")
if v := GetSeverity(err); v != log.Severity_Info { if v := err.Error(); !strings.Contains(v, "TestError") {
t.Error("severity: ", v) t.Error("error: ", v)
} }
err = New("TestError2").Base(io.EOF) err = New("TestError2").Base(io.EOF)
if v := GetSeverity(err); v != log.Severity_Info { if v := err.Error(); !strings.Contains(v, "EOF") {
t.Error("severity: ", v) t.Error("error: ", v)
} }
err = New("TestError3").Base(io.EOF).AtWarning() err = New("TestError3").Base(io.EOF)
if v := GetSeverity(err); v != log.Severity_Warning { err = New("TestError4").Base(err)
t.Error("severity: ", v)
}
err = New("TestError4").Base(io.EOF).AtWarning()
err = New("TestError5").Base(err)
if v := GetSeverity(err); v != log.Severity_Warning {
t.Error("severity: ", v)
}
if v := err.Error(); !strings.Contains(v, "EOF") { if v := err.Error(); !strings.Contains(v, "EOF") {
t.Error("error: ", v) t.Error("error: ", v)
} }
+21 -25
View File
@@ -1,7 +1,7 @@
package log // import "github.com/xtls/xray-core/common/log" package log // import "github.com/xtls/xray-core/common/log"
import ( import (
"sync" "sync/atomic"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
) )
@@ -29,36 +29,32 @@ func (m *GeneralMessage) String() string {
// Record writes a message into log stream. // Record writes a message into log stream.
func Record(msg Message) { func Record(msg Message) {
logHandler.Handle(msg) if h := logHandler.Load(); h != nil {
(*h).Handle(msg)
}
} }
var logHandler syncHandler type SeverityLogger interface {
Handler
Severity() Severity
}
func GetSeverity() Severity {
if h := logHandler.Load(); h != nil {
if sh, ok := (*h).(SeverityLogger); ok {
return sh.Severity()
}
}
// log everything by default
return Severity_Debug
}
var logHandler atomic.Pointer[Handler]
// RegisterHandler registers a new handler as current log handler. Previous registered handler will be discarded. // RegisterHandler registers a new handler as current log handler. Previous registered handler will be discarded.
func RegisterHandler(handler Handler) { func RegisterHandler(handler Handler) {
if handler == nil { if handler == nil {
panic("Log handler is nil") panic("Log handler is nil")
} }
logHandler.Set(handler) logHandler.Store(&handler)
}
type syncHandler struct {
sync.RWMutex
Handler
}
func (h *syncHandler) Handle(msg Message) {
h.RLock()
defer h.RUnlock()
if h.Handler != nil {
h.Handler.Handle(msg)
}
}
func (h *syncHandler) Set(handler Handler) {
h.Lock()
defer h.Unlock()
h.Handler = handler
} }
+4
View File
@@ -68,6 +68,10 @@ func (l *serverityLogger) Handle(msg Message) {
} }
} }
func (l *serverityLogger) Severity() Severity {
return l.logLevel
}
func (l *generalLogger) run() { func (l *generalLogger) run() {
defer l.access.Signal() defer l.access.Signal()
+1 -1
View File
@@ -38,7 +38,7 @@ func (m *ClientManager) Dispatch(ctx context.Context, link *transport.Link) erro
} }
} }
return errors.New("unable to find an available mux client").AtWarning() return errors.New("unable to find an available mux client")
} }
type WorkerPicker interface { type WorkerPicker interface {
+1 -1
View File
@@ -117,7 +117,7 @@ func (f *FrameMetadata) Unmarshal(reader io.Reader, readSourceAndLocal bool) err
return err return err
} }
if metaLen > 512 { if metaLen > 512 {
return errors.New("invalid metalen ", metaLen).AtError() return errors.New("invalid metalen ", metaLen)
} }
b := buf.New() b := buf.New()
+1 -1
View File
@@ -351,7 +351,7 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
err = w.handleStatusKeep(&meta, reader) err = w.handleStatusKeep(&meta, reader)
default: default:
status := meta.SessionStatus status := meta.SessionStatus
return errors.New("unknown status: ", status).AtError() return errors.New("unknown status: ", status)
} }
if err != nil { if err != nil {
+1 -1
View File
@@ -7,7 +7,7 @@ import (
func (u *User) GetTypedAccount() (Account, error) { func (u *User) GetTypedAccount() (Account, error) {
if u.GetAccount() == nil { if u.GetAccount() == nil {
return nil, errors.New("Account is missing").AtWarning() return nil, errors.New("Account is missing")
} }
rawAccount, err := u.Account.GetInstance() rawAccount, err := u.Account.GetInstance()
+2 -2
View File
@@ -16,7 +16,7 @@ var typeCreatorRegistry = make(map[reflect.Type]ConfigCreator)
func RegisterConfig(config interface{}, configCreator ConfigCreator) error { func RegisterConfig(config interface{}, configCreator ConfigCreator) error {
configType := reflect.TypeOf(config) configType := reflect.TypeOf(config)
if _, found := typeCreatorRegistry[configType]; found { if _, found := typeCreatorRegistry[configType]; found {
return errors.New(configType.Name() + " is already registered").AtError() return errors.New(configType.Name() + " is already registered")
} }
typeCreatorRegistry[configType] = configCreator typeCreatorRegistry[configType] = configCreator
return nil return nil
@@ -27,7 +27,7 @@ func CreateObject(ctx context.Context, config interface{}) (interface{}, error)
configType := reflect.TypeOf(config) configType := reflect.TypeOf(config)
creator, found := typeCreatorRegistry[configType] creator, found := typeCreatorRegistry[configType]
if !found { if !found {
return nil, errors.New(configType.String() + " is not registered").AtError() return nil, errors.New(configType.String() + " is not registered")
} }
return creator(ctx, config) return creator(ctx, config)
} }
+4 -4
View File
@@ -125,7 +125,7 @@ func LoadConfig(formatName string, input interface{}) (*Config, error) {
} }
if f == "" { if f == "" {
return nil, errors.New("Failed to get format of ", file).AtWarning() return nil, errors.New("Failed to get format of ", file)
} }
if f == "protobuf" { if f == "protobuf" {
@@ -142,7 +142,7 @@ func LoadConfig(formatName string, input interface{}) (*Config, error) {
if len(v) == 1 { if len(v) == 1 {
return configLoaderByName["protobuf"].Loader(v) return configLoaderByName["protobuf"].Loader(v)
} else { } else {
return nil, errors.New("Only one protobuf config file is allowed").AtWarning() return nil, errors.New("Only one protobuf config file is allowed")
} }
} }
@@ -152,11 +152,11 @@ func LoadConfig(formatName string, input interface{}) (*Config, error) {
if f, found := configLoaderByName[formatName]; found { if f, found := configLoaderByName[formatName]; found {
return f.Loader(v) return f.Loader(v)
} else { } else {
return nil, errors.New("Unable to load config in", formatName).AtWarning() return nil, errors.New("Unable to load config in", formatName)
} }
} }
return nil, errors.New("Unable to load config").AtWarning() return nil, errors.New("Unable to load config")
} }
func loadProtobufConfig(data []byte) (*Config, error) { func loadProtobufConfig(data []byte) (*Config, error) {
+1 -1
View File
@@ -20,7 +20,7 @@ import (
var ( var (
Version_x byte = 26 Version_x byte = 26
Version_y byte = 9 Version_y byte = 9
Version_z byte = 8 Version_z byte = 9
) )
var ( var (
+2 -1
View File
@@ -37,6 +37,7 @@ require (
gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0 gvisor.dev/gvisor v0.0.0-20260122175437-89a5d21be8f0
h12.io/socks v1.0.3 h12.io/socks v1.0.3
lukechampine.com/blake3 v1.4.1 lukechampine.com/blake3 v1.4.1
mvdan.cc/gofumpt v0.12.0
) )
require ( require (
@@ -48,7 +49,6 @@ require (
github.com/juju/ratelimit v1.0.2 // indirect github.com/juju/ratelimit v1.0.2 // indirect
github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/compress v1.17.4 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect github.com/koron/go-ssdp v0.0.4 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/libp2p/go-netroute v0.2.1 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect
github.com/pion/dtls/v3 v3.1.5 // indirect github.com/pion/dtls/v3 v3.1.5 // indirect
github.com/pion/logging v0.2.4 // indirect github.com/pion/logging v0.2.4 // indirect
@@ -59,6 +59,7 @@ require (
go.yaml.in/yaml/v3 v3.0.5 // indirect go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/text v0.41.0 // indirect golang.org/x/text v0.41.0 // indirect
golang.org/x/time v0.14.0 // indirect golang.org/x/time v0.14.0 // indirect
golang.org/x/tools v0.49.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )
+8 -3
View File
@@ -6,13 +6,14 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/circl v1.6.5 h1:O64F26HEqNhznd/hrC5KZXVKYuKM2rx4deZDTc4ihQA= github.com/cloudflare/circl v1.6.5 h1:O64F26HEqNhznd/hrC5KZXVKYuKM2rx4deZDTc4ihQA=
github.com/cloudflare/circl v1.6.5/go.mod h1:h5LNyxAc5nTue9DS5jT+48en2PSDYt3zdGnz5OstK6c= github.com/cloudflare/circl v1.6.5/go.mod h1:h5LNyxAc5nTue9DS5jT+48en2PSDYt3zdGnz5OstK6c=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-quicktest/qt v1.102.0 h1:HSQxCeh5YZH3EL3W39ixjtyaEhcWSXQHtHnMBzSs474=
github.com/go-quicktest/qt v1.102.0/go.mod h1:p4lGIVX+8Wa6ZPNDvqcxq36XpUDLh42FLetFU7odllI=
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U= github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs= github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
@@ -73,8 +74,8 @@ github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af h1:er
github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM= github.com/refraction-networking/utls v1.8.3-0.20260301010127-aa6edf4b11af/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y= github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y=
github.com/sagernet/sing v0.5.1/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sagernet/sing v0.5.1/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
@@ -147,6 +148,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.49.0 h1:3NI7VXzL9+1WZD52Dx2ttoPwD5DWrFGpl9mFZDlmisI=
golang.org/x/tools v0.49.0/go.mod h1:SJNXV9DBKT0UbdttsQjbfJlAE/q+y36++zo3uL3N0Oo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -176,3 +179,5 @@ h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck= h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg= lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo= lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
mvdan.cc/gofumpt v0.12.0 h1:1Lbudkz2kpM9Cjz2pL4M19u7q+GaEhCTNf7N9mfpcho=
mvdan.cc/gofumpt v0.12.0/go.mod h1:SmBHHrljiZu/uoypeKup3rFzP6eoC9UwCp2iH5E3jZA=
+2 -2
View File
@@ -97,7 +97,7 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) {
user.Email = v.Email user.Email = v.Email
} else { } else {
if err := json.Unmarshal(rawUser, user); err != nil { if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New("failed to parse HTTP user").Base(err).AtError() return nil, errors.New("failed to parse HTTP user").Base(err)
} }
} }
account := new(HTTPAccount) account := new(HTTPAccount)
@@ -106,7 +106,7 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) {
account.Password = v.Password account.Password = v.Password
} else { } else {
if err := json.Unmarshal(rawUser, account); err != nil { if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New("failed to parse HTTP account").Base(err).AtError() return nil, errors.New("failed to parse HTTP account").Base(err)
} }
} }
user.Account = serial.ToTypedMessage(account.Build()) user.Account = serial.ToTypedMessage(account.Build())
+1 -1
View File
@@ -18,7 +18,7 @@ func RegisterConfigureFilePostProcessingStage(name string, stage ConfigureFilePo
func PostProcessConfigureFile(conf *Config) error { func PostProcessConfigureFile(conf *Config) error {
for k, v := range configureFilePostProcessingStages { for k, v := range configureFilePostProcessingStages {
if err := v.Process(conf); err != nil { if err := v.Process(conf); err != nil {
return errors.New("Rejected by Postprocessing Stage ", k).AtError().Base(err) return errors.New("Rejected by Postprocessing Stage ", k).Base(err)
} }
} }
return nil return nil
+2 -2
View File
@@ -13,7 +13,7 @@ type ConfigCreatorCache map[string]ConfigCreator
func (v ConfigCreatorCache) RegisterCreator(id string, creator ConfigCreator) error { func (v ConfigCreatorCache) RegisterCreator(id string, creator ConfigCreator) error {
if _, found := v[id]; found { if _, found := v[id]; found {
return errors.New(id, " already registered.").AtError() return errors.New(id, " already registered.")
} }
v[id] = creator v[id] = creator
@@ -61,7 +61,7 @@ func (v *JSONConfigLoader) Load(raw []byte) (interface{}, string, error) {
} }
rawID, found := obj[v.idKey] rawID, found := obj[v.idKey]
if !found { if !found {
return nil, "", errors.New(v.idKey, " not found in JSON context").AtError() return nil, "", errors.New(v.idKey, " not found in JSON context")
} }
var id string var id string
if err := json.Unmarshal(rawID, &id); err != nil { if err := json.Unmarshal(rawID, &id); err != nil {
+1 -1
View File
@@ -30,7 +30,7 @@ func MergeConfigFromFiles(files []*core.ConfigSource) (string, error) {
if j, ok := creflect.MarshalToJson(c, true); ok { if j, ok := creflect.MarshalToJson(c, true); ok {
return j, nil return j, nil
} }
return "", errors.New("marshal to json failed.").AtError() return "", errors.New("marshal to json failed.")
} }
func mergeConfigs(files []*core.ConfigSource) (*conf.Config, error) { func mergeConfigs(files []*core.ConfigSource) (*conf.Config, error) {
+2 -3
View File
@@ -44,7 +44,6 @@ func (v *SocksServerConfig) Build() (proto.Message, error) {
case AuthMethodUserPass: case AuthMethodUserPass:
config.AuthType = socks.AuthType_PASSWORD config.AuthType = socks.AuthType_PASSWORD
default: default:
// errors.New("unknown socks auth method: ", v.AuthMethod, ". Default to noauth.").AtWarning().WriteToLog()
config.AuthType = socks.AuthType_NO_AUTH config.AuthType = socks.AuthType_NO_AUTH
} }
@@ -115,7 +114,7 @@ func (v *SocksClientConfig) Build() (proto.Message, error) {
user.Email = v.Email user.Email = v.Email
} else { } else {
if err := json.Unmarshal(rawUser, user); err != nil { if err := json.Unmarshal(rawUser, user); err != nil {
return nil, errors.New("failed to parse Socks user").Base(err).AtError() return nil, errors.New("failed to parse Socks user").Base(err)
} }
} }
account := new(SocksAccount) account := new(SocksAccount)
@@ -124,7 +123,7 @@ func (v *SocksClientConfig) Build() (proto.Message, error) {
account.Password = v.Password account.Password = v.Password
} else { } else {
if err := json.Unmarshal(rawUser, account); err != nil { if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New("failed to parse socks account").Base(err).AtError() return nil, errors.New("failed to parse socks account").Base(err)
} }
} }
user.Account = serial.ToTypedMessage(account.Build()) user.Account = serial.ToTypedMessage(account.Build())
+59 -1
View File
@@ -14,6 +14,7 @@ import (
googleuuid "github.com/google/uuid" googleuuid "github.com/google/uuid"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/finalmask/fragment" "github.com/xtls/xray-core/transport/internet/finalmask/fragment"
"github.com/xtls/xray-core/transport/internet/finalmask/header/custom" "github.com/xtls/xray-core/transport/internet/finalmask/header/custom"
"github.com/xtls/xray-core/transport/internet/finalmask/mkcp/aes128gcm" "github.com/xtls/xray-core/transport/internet/finalmask/mkcp/aes128gcm"
@@ -23,6 +24,7 @@ import (
"github.com/xtls/xray-core/transport/internet/finalmask/realm" "github.com/xtls/xray-core/transport/internet/finalmask/realm"
"github.com/xtls/xray-core/transport/internet/finalmask/salamander" "github.com/xtls/xray-core/transport/internet/finalmask/salamander"
"github.com/xtls/xray-core/transport/internet/finalmask/sudoku" "github.com/xtls/xray-core/transport/internet/finalmask/sudoku"
"github.com/xtls/xray-core/transport/internet/finalmask/udphop"
"github.com/xtls/xray-core/transport/internet/finalmask/xdns" "github.com/xtls/xray-core/transport/internet/finalmask/xdns"
"github.com/xtls/xray-core/transport/internet/finalmask/xicmp" "github.com/xtls/xray-core/transport/internet/finalmask/xicmp"
"github.com/xtls/xray-core/transport/internet/finalmask/xmc" "github.com/xtls/xray-core/transport/internet/finalmask/xmc"
@@ -83,6 +85,7 @@ var (
"xdns": func() interface{} { return new(Xdns) }, "xdns": func() interface{} { return new(Xdns) },
"xicmp": func() interface{} { return new(Xicmp) }, "xicmp": func() interface{} { return new(Xicmp) },
"realm": func() interface{} { return new(Realm) }, "realm": func() interface{} { return new(Realm) },
"udphop": func() interface{} { return new(UDPHop) },
}, "type", "settings") }, "type", "settings")
) )
@@ -905,6 +908,62 @@ func (c *Realm) Build() (proto.Message, error) {
}, nil }, nil
} }
type UDPHop struct {
Sockopt *SocketConfig `json:"sockopt"`
Mode string `json:"mode"`
Interval Int32Range `json:"interval"`
RemotePorts PortList `json:"remotePorts"`
RemoteIPs []string `json:"remoteIPs"`
}
func (c *UDPHop) Build() (proto.Message, error) {
var sockopt *internet.SocketConfig
if c.Sockopt != nil {
var err error
sockopt, err = c.Sockopt.Build()
if err != nil {
return nil, err
}
}
var local, remote, remoteOnce bool
for _, mode := range strings.Split(c.Mode, ",") {
switch strings.ToLower(mode) {
case "intervallocal":
local = true
case "intervalremote":
remote = true
case "perconnremote":
remoteOnce = true
default:
return nil, errors.New("invalid mode ", mode)
}
}
var remoteIPs []string
for _, ip := range c.RemoteIPs {
prefix, err := netip.ParsePrefix(ip)
if err == nil {
remoteIPs = append(remoteIPs, prefix.String())
continue
}
addr, err := netip.ParseAddr(ip)
if err == nil {
remoteIPs = append(remoteIPs, netip.PrefixFrom(addr, addr.BitLen()).String())
continue
}
return nil, errors.New("invalid ip ", ip)
}
return &udphop.Config{
Sockopt: sockopt,
Local: local,
Remote: remote,
RemoteOnce: remoteOnce,
IntervalMin: int64(c.Interval.From),
IntervalMax: int64(c.Interval.To),
RemotePorts: c.RemotePorts.Build().Ports(),
RemoteIPs: remoteIPs,
}, nil
}
type Mask struct { type Mask struct {
Type string `json:"type"` Type string `json:"type"`
Settings *json.RawMessage `json:"settings"` Settings *json.RawMessage `json:"settings"`
@@ -938,7 +997,6 @@ type QuicParamsConfig struct {
BrutalUp Bandwidth `json:"brutalUp"` BrutalUp Bandwidth `json:"brutalUp"`
BrutalDown Bandwidth `json:"brutalDown"` BrutalDown Bandwidth `json:"brutalDown"`
BrutalDisableLossCompensation bool `json:"brutalDisableLossCompensation"` BrutalDisableLossCompensation bool `json:"brutalDisableLossCompensation"`
UdpHop UdpHop `json:"udpHop"`
InitStreamReceiveWindow uint64 `json:"initStreamReceiveWindow"` InitStreamReceiveWindow uint64 `json:"initStreamReceiveWindow"`
MaxStreamReceiveWindow uint64 `json:"maxStreamReceiveWindow"` MaxStreamReceiveWindow uint64 `json:"maxStreamReceiveWindow"`
InitConnectionReceiveWindow uint64 `json:"initConnectionReceiveWindow"` InitConnectionReceiveWindow uint64 `json:"initConnectionReceiveWindow"`
+11 -20
View File
@@ -253,10 +253,6 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
return nil, errors.New("unknown congestion control: ", c.FinalMask.QuicParams.Congestion, ", valid values: reno, bbr, brutal, force-brutal") return nil, errors.New("unknown congestion control: ", c.FinalMask.QuicParams.Congestion, ", valid values: reno, bbr, brutal, force-brutal")
} }
if (c.FinalMask.QuicParams.UdpHop.Interval.From != 0 && c.FinalMask.QuicParams.UdpHop.Interval.From < 5) || (c.FinalMask.QuicParams.UdpHop.Interval.To != 0 && c.FinalMask.QuicParams.UdpHop.Interval.To < 5) {
return nil, errors.New("Interval must be at least 5")
}
if c.FinalMask.QuicParams.InitStreamReceiveWindow > 0 && c.FinalMask.QuicParams.InitStreamReceiveWindow < 16384 { if c.FinalMask.QuicParams.InitStreamReceiveWindow > 0 && c.FinalMask.QuicParams.InitStreamReceiveWindow < 16384 {
return nil, errors.New("InitStreamReceiveWindow must be at least 16384") return nil, errors.New("InitStreamReceiveWindow must be at least 16384")
} }
@@ -290,22 +286,17 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
BrutalUp: up, BrutalUp: up,
BrutalDown: down, BrutalDown: down,
BrutalDisableLossCompensation: c.FinalMask.QuicParams.BrutalDisableLossCompensation, BrutalDisableLossCompensation: c.FinalMask.QuicParams.BrutalDisableLossCompensation,
UdpHop: &internet.UdpHop{ InitStreamReceiveWindow: c.FinalMask.QuicParams.InitStreamReceiveWindow,
Ports: c.FinalMask.QuicParams.UdpHop.PortList.Build().Ports(), MaxStreamReceiveWindow: c.FinalMask.QuicParams.MaxStreamReceiveWindow,
IntervalMin: int64(c.FinalMask.QuicParams.UdpHop.Interval.From), InitConnReceiveWindow: c.FinalMask.QuicParams.InitConnectionReceiveWindow,
IntervalMax: int64(c.FinalMask.QuicParams.UdpHop.Interval.To), MaxConnReceiveWindow: c.FinalMask.QuicParams.MaxConnectionReceiveWindow,
}, MaxIdleTimeout: c.FinalMask.QuicParams.MaxIdleTimeout,
InitStreamReceiveWindow: c.FinalMask.QuicParams.InitStreamReceiveWindow, KeepAlivePeriod: c.FinalMask.QuicParams.KeepAlivePeriod,
MaxStreamReceiveWindow: c.FinalMask.QuicParams.MaxStreamReceiveWindow, DisablePathMtuDiscovery: c.FinalMask.QuicParams.DisablePathMTUDiscovery,
InitConnReceiveWindow: c.FinalMask.QuicParams.InitConnectionReceiveWindow, DisableChromeParrot: c.FinalMask.QuicParams.DisableChromeParrot,
MaxConnReceiveWindow: c.FinalMask.QuicParams.MaxConnectionReceiveWindow, DisableGSO: c.FinalMask.QuicParams.DisableGSO,
MaxIdleTimeout: c.FinalMask.QuicParams.MaxIdleTimeout, MaxIncomingStreams: c.FinalMask.QuicParams.MaxIncomingStreams,
KeepAlivePeriod: c.FinalMask.QuicParams.KeepAlivePeriod, DisableStatelessReset: c.FinalMask.QuicParams.DisableStatelessReset,
DisablePathMtuDiscovery: c.FinalMask.QuicParams.DisablePathMTUDiscovery,
DisableChromeParrot: c.FinalMask.QuicParams.DisableChromeParrot,
DisableGSO: c.FinalMask.QuicParams.DisableGSO,
MaxIncomingStreams: c.FinalMask.QuicParams.MaxIncomingStreams,
DisableStatelessReset: c.FinalMask.QuicParams.DisableStatelessReset,
} }
} }
} }
+10 -30
View File
@@ -1,7 +1,6 @@
package conf package conf
import ( import (
"context"
"encoding/json" "encoding/json"
"math/big" "math/big"
"net/url" "net/url"
@@ -122,7 +121,7 @@ func (v *AuthenticatorRequest) Build() (*http.RequestConfig, error) {
for _, key := range headerNames { for _, key := range headerNames {
value := v.Headers[key] value := v.Headers[key]
if value == nil { if value == nil {
return nil, errors.New("empty HTTP header value: " + key).AtError() return nil, errors.New("empty HTTP header value: " + key)
} }
config.Header = append(config.Header, &http.Header{ config.Header = append(config.Header, &http.Header{
Name: key, Name: key,
@@ -190,7 +189,7 @@ func (v *AuthenticatorResponse) Build() (*http.ResponseConfig, error) {
for _, key := range headerNames { for _, key := range headerNames {
value := v.Headers[key] value := v.Headers[key]
if value == nil { if value == nil {
return nil, errors.New("empty HTTP header value: " + key).AtError() return nil, errors.New("empty HTTP header value: " + key)
} }
config.Header = append(config.Header, &http.Header{ config.Header = append(config.Header, &http.Header{
Name: key, Name: key,
@@ -240,11 +239,11 @@ func (c *TCPConfig) Build() (proto.Message, error) {
if len(c.HeaderConfig) > 0 { if len(c.HeaderConfig) > 0 {
headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig) headerConfig, _, err := tcpHeaderLoader.Load(c.HeaderConfig)
if err != nil { if err != nil {
return nil, errors.New("invalid TCP header config").Base(err).AtError() return nil, errors.New("invalid TCP header config").Base(err)
} }
ts, err := headerConfig.(Buildable).Build() ts, err := headerConfig.(Buildable).Build()
if err != nil { if err != nil {
return nil, errors.New("invalid TCP header config").Base(err).AtError() return nil, errors.New("invalid TCP header config").Base(err)
} }
config.HeaderSettings = serial.ToTypedMessage(ts) config.HeaderSettings = serial.ToTypedMessage(ts)
} }
@@ -534,10 +533,6 @@ type KCPConfig struct {
// Build implements Buildable. // Build implements Buildable.
func (c *KCPConfig) Build() (proto.Message, error) { func (c *KCPConfig) Build() (proto.Message, error) {
if c.HeaderConfig != nil || c.Seed != nil {
return nil, errors.PrintRemovedFeatureError("mkcp header & seed", "finalmask/udp header-* & mkcp-original & mkcp-aes128gcm")
}
config := common.Must2(internet.CreateTransportConfig(kcp.ProtocolName)).(*kcp.Config) config := common.Must2(internet.CreateTransportConfig(kcp.ProtocolName)).(*kcp.Config)
if c.Mtu != nil { if c.Mtu != nil {
@@ -560,16 +555,16 @@ func (c *KCPConfig) Build() (proto.Message, error) {
} }
if config.Mtu < 21 { if config.Mtu < 21 {
return nil, errors.New("Mtu must be at least 21").AtError() return nil, errors.New("MTU must be at least 21")
} }
if config.Tti < 10 || config.Tti > 1000 { if config.Tti < 10 || config.Tti > 1000 {
return nil, errors.New("invalid mKCP TTI: ", c.Tti).AtError() return nil, errors.New("TTI must be between 10 and 1000")
} }
if config.CwndMultiplier < 1 { if config.CwndMultiplier < 1 {
return nil, errors.New("CwndMultiplier must be at least 1").AtError() return nil, errors.New("CwndMultiplier must be at least 1")
} }
if config.GetSendingBufferSize() == 0 { if config.GetSendingBufferSize() == 0 {
return nil, errors.New("MaxSendingWindow must be >= Mtu").AtError() return nil, errors.New("MaxSendingWindow must be at least ", config.Mtu)
} }
return config, nil return config, nil
@@ -739,11 +734,6 @@ func (b Bandwidth) Bps() (uint64, error) {
return uint64(val*float64(mul)) / 8, nil return uint64(val*float64(mul)) / 8, nil
} }
type UdpHop struct {
PortList PortList `json:"ports"`
Interval Int32Range `json:"interval"`
}
type Masquerade struct { type Masquerade struct {
Type string `json:"type"` Type string `json:"type"`
@@ -760,14 +750,8 @@ type Masquerade struct {
} }
type HysteriaConfig struct { type HysteriaConfig struct {
Version int32 `json:"version"` Version int32 `json:"version"`
Auth string `json:"auth"` Auth string `json:"auth"`
Congestion *string `json:"congestion"`
Up *Bandwidth `json:"up"`
Down *Bandwidth `json:"down"`
UdpHop *UdpHop `json:"udphop"`
UdpIdleTimeout int64 `json:"udpIdleTimeout"` UdpIdleTimeout int64 `json:"udpIdleTimeout"`
Masquerade Masquerade `json:"masquerade"` Masquerade Masquerade `json:"masquerade"`
} }
@@ -777,10 +761,6 @@ func (c *HysteriaConfig) Build() (proto.Message, error) {
return nil, errors.New("version != 2") return nil, errors.New("version != 2")
} }
if c.Congestion != nil || c.Up != nil || c.Down != nil || c.UdpHop != nil {
errors.LogWarning(context.Background(), "congestion & up & down & udphop move to finalmask/quicParams")
}
if c.UdpIdleTimeout != 0 && (c.UdpIdleTimeout < 2 || c.UdpIdleTimeout > 600) { if c.UdpIdleTimeout != 0 && (c.UdpIdleTimeout < 2 || c.UdpIdleTimeout > 600) {
return nil, errors.New("UdpIdleTimeout must be between 2 and 600") return nil, errors.New("UdpIdleTimeout must be between 2 and 600")
} }
+3
View File
@@ -312,6 +312,9 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
if err := json.Unmarshal(rawUser, account); err != nil { if err := json.Unmarshal(rawUser, account); err != nil {
return nil, errors.New(`VLESS users: invalid user`).Base(err) return nil, errors.New(`VLESS users: invalid user`).Base(err)
} }
// validateOutboundTransportSecurity needs to see these
c.Encryption = account.Encryption
c.Address = rec.Address
if account.Reverse != nil { // may not be reached: error json unmarshal if account.Reverse != nil { // may not be reached: error json unmarshal
return nil, errors.New(`VLESS users: please use simplified outbound's config style to use "reverse"`) return nil, errors.New(`VLESS users: please use simplified outbound's config style to use "reverse"`)
} }
+1 -1
View File
@@ -242,7 +242,7 @@ func validateOutboundTransportSecurity(rawConfig interface{}, senderSettings *pr
if vlessCfg.Encryption != "" && vlessCfg.Encryption != "none" { if vlessCfg.Encryption != "" && vlessCfg.Encryption != "none" {
return nil return nil
} }
if requiresTransportSecurity(vlessCfg.Vnext[0].Address) { if requiresTransportSecurity(vlessCfg.Address) {
return errors.New("vless without TLS or other encryption is prohibited unless the server address is a private IP or domain") return errors.New("vless without TLS or other encryption is prohibited unless the server address is a private IP or domain")
} }
} }
+273 -139
View File
@@ -1,15 +1,18 @@
package main package main
import ( import (
"errors" "bytes"
"flag" "flag"
"fmt" "fmt"
"go/build"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"sort"
"strings" "strings"
"sync"
"sync/atomic"
"mvdan.cc/gofumpt/format"
) )
var ( var (
@@ -23,101 +26,27 @@ var (
isFormat bool isFormat bool
) )
// envFile returns the name of the Go environment configuration file. func getModuleInfo(pwd string) (modPath, langVersion string, err error) {
// Copy from https://github.com/golang/go/blob/c4f2a9788a7be04daf931ac54382fbe2cb754938/src/cmd/go/internal/cfg/cfg.go#L150-L166 data, err := os.ReadFile(filepath.Join(pwd, "go.mod"))
func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" {
if file == "off" {
return "", errors.New("GOENV=off")
}
return file, nil
}
dir, err := os.UserConfigDir()
if err != nil { if err != nil {
return "", err return "", "", err
} }
if dir == "" { for _, line := range strings.Split(string(data), "\n") {
return "", errors.New("missing user-config dir") fields := strings.Fields(line)
} if len(fields) >= 2 {
return filepath.Join(dir, "go", "env"), nil switch fields[0] {
} case "module":
modPath = fields[1]
// GetRuntimeEnv returns the value of runtime environment variable, case "go":
// that is set by running following command: `go env -w key=value`. langVersion = "go" + strings.TrimPrefix(fields[1], "go")
func GetRuntimeEnv(key string) (string, error) {
file, err := envFile()
if err != nil {
return "", err
}
if file == "" {
return "", errors.New("missing runtime env file")
}
var data []byte
var runtimeEnv string
data, readErr := os.ReadFile(file)
if readErr != nil {
return "", readErr
}
envStrings := strings.Split(string(data), "\n")
for _, envItem := range envStrings {
envItem = strings.TrimSuffix(envItem, "\r")
envKeyValue := strings.Split(envItem, "=")
if len(envKeyValue) == 2 && strings.TrimSpace(envKeyValue[0]) == key {
runtimeEnv = strings.TrimSpace(envKeyValue[1])
}
}
return runtimeEnv, nil
}
// GetGOBIN returns GOBIN environment variable as a string. It will NOT be empty.
func GetGOBIN() string {
// The one set by user explicitly by `export GOBIN=/path` or `env GOBIN=/path command`
GOBIN := os.Getenv("GOBIN")
if GOBIN == "" {
var err error
// The one set by user by running `go env -w GOBIN=/path`
GOBIN, err = GetRuntimeEnv("GOBIN")
if err != nil {
// The default one that Golang uses
return filepath.Join(build.Default.GOPATH, "bin")
}
if GOBIN == "" {
return filepath.Join(build.Default.GOPATH, "bin")
}
return GOBIN
}
return GOBIN
}
func Run(binary string, args []string) ([]byte, error) {
cmd := exec.Command(binary, args...)
cmd.Env = append(cmd.Env, os.Environ()...)
output, cmdErr := cmd.CombinedOutput()
if cmdErr != nil {
return nil, cmdErr
}
return output, nil
}
func RunMany(binary string, args, files []string) bool {
fmt.Println("Processing with", binary, args, "...")
formatRequired := false
maxTasks := make(chan struct{}, runtime.NumCPU())
for _, file := range files {
maxTasks <- struct{}{}
go func(file string) {
output, err := Run(binary, append(args, file))
if err != nil {
fmt.Println(err)
} else if len(output) > 0 {
fmt.Println(string(output))
formatRequired = true
} }
<-maxTasks }
}(file)
} }
return formatRequired return modPath, langVersion, nil
}
func formatGoSource(src []byte, opts format.Options) ([]byte, error) {
return format.Source(src, opts)
} }
func main() { func main() {
@@ -150,26 +79,76 @@ func main() {
} }
pwd := *directory pwd := *directory
GOBIN := GetGOBIN() modPath, langVersion, modErr := getModuleInfo(pwd)
binPath := os.Getenv("PATH") if modErr != nil {
pathSlice := []string{pwd, GOBIN, binPath} fmt.Println("Error reading go.mod:", modErr)
binPath = strings.Join(pathSlice, string(os.PathListSeparator))
os.Setenv("PATH", binPath)
suffix := ""
if runtime.GOOS == "windows" {
suffix = ".exe"
}
gofmt := "gofumpt" + suffix
if gofmtPath, err := exec.LookPath(gofmt); err != nil {
fmt.Println("Can not find", gofmt, "in system path or current working directory.")
os.Exit(1) os.Exit(1)
} else { }
gofmt = gofmtPath opts := format.Options{
LangVersion: langVersion,
ModulePath: modPath,
}
if isFormat {
fmt.Println("Formatting Go source files...")
} else if isCheck {
fmt.Println("Checking files thar are not properly formatted...")
}
jobs := make(chan string, runtime.NumCPU())
var wg sync.WaitGroup
var formatRequired atomic.Bool
var hasErrors atomic.Bool
for i := 0; i < runtime.NumCPU(); i++ {
wg.Go(func() {
for path := range jobs {
src, err := os.ReadFile(path)
if err != nil {
fmt.Fprintf(os.Stderr, "Error reading %s: %v\n", path, err)
hasErrors.Store(true)
continue
}
formatted, err := formatGoSource(src, opts)
if err != nil {
fmt.Fprintf(os.Stderr, "Error formatting %s: %v\n", path, err)
hasErrors.Store(true)
continue
}
if !bytes.Equal(src, formatted) {
var diffText []byte
if isDryrun {
newName := filepath.ToSlash(path)
oldName := newName + ".orig"
diffText = diff(oldName, src, newName, formatted)
}
if isFormat {
info, statErr := os.Stat(path)
if statErr != nil {
fmt.Fprintf(os.Stderr, "Error stating %s: %v\n", path, statErr)
hasErrors.Store(true)
continue
}
if writeErr := os.WriteFile(path, formatted, info.Mode().Perm()); writeErr != nil {
fmt.Fprintf(os.Stderr, "Error writing %s: %v\n", path, writeErr)
hasErrors.Store(true)
continue
}
}
formatRequired.Store(true)
if isDryrun && len(diffText) > 0 {
fmt.Printf("%s\n%s", path, diffText)
} else {
fmt.Println(path)
}
}
}
})
} }
rawFilesSlice := make([]string, 0, 1000)
walkErr := filepath.Walk(pwd, func(path string, info os.FileInfo, err error) error { walkErr := filepath.Walk(pwd, func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
@@ -186,51 +165,206 @@ func main() {
!strings.HasSuffix(filename, ".pb.go") && !strings.HasSuffix(filename, ".pb.go") &&
!strings.Contains(dir, filepath.Join("testing", "mocks")) && !strings.Contains(dir, filepath.Join("testing", "mocks")) &&
!strings.Contains(path, filepath.Join("main", "distro", "all", "all.go")) { !strings.Contains(path, filepath.Join("main", "distro", "all", "all.go")) {
rawFilesSlice = append(rawFilesSlice, path) jobs <- path
} }
return nil return nil
}) })
close(jobs)
wg.Wait()
if walkErr != nil { if walkErr != nil {
fmt.Println(walkErr) fmt.Println(walkErr)
os.Exit(1) os.Exit(1)
} }
if isFormat { if hasErrors.Load() {
gofmtArgs := []string{ os.Exit(1)
"-l", "-e", "-w", }
}
fmt.Println("Formatting Go source files...") if isFormat {
RunMany(gofmt, gofmtArgs, rawFilesSlice) if formatRequired.Load() {
fmt.Println("Do NOT forget to commit file changes.") fmt.Println("Do NOT forget to commit file changes.")
}
} }
if isCheck { if isCheck {
gofmtListArgs := []string{ if formatRequired.Load() {
"-l", "-e",
}
fmt.Println("Checking files thar are not properly formatted...")
formatRequired := RunMany(gofmt, gofmtListArgs, rawFilesSlice)
if formatRequired {
fmt.Println("Format problem(s) found.") fmt.Println("Format problem(s) found.")
} fmt.Println("Please run 'go run ./infra/vformat/main.go' to format the Go source files.")
if isDryrun {
if formatRequired {
gofmtShowArgs := []string{
"-d", "-e",
}
RunMany(gofmt, gofmtShowArgs, rawFilesSlice)
}
}
if formatRequired {
fmt.Println("Please run 'go install -v mvdan.cc/gofumpt@latest', then run 'go run ./infra/vformat/main.go' to format the Go source files.")
os.Exit(1) os.Exit(1)
} else { } else {
fmt.Println("All Go source file format check has been passed.") fmt.Println("All Go source file format check has been passed.")
} }
} }
} }
// diff algorithm copied from mvdan.cc/gofumpt/internal/govendor/diff
type pair struct{ x, y int }
func diff(oldName string, old []byte, newName string, new []byte) []byte {
if bytes.Equal(old, new) {
return nil
}
x := diffLines(old)
y := diffLines(new)
var out bytes.Buffer
fmt.Fprintf(&out, "diff %s %s\n", oldName, newName)
fmt.Fprintf(&out, "--- %s\n", oldName)
fmt.Fprintf(&out, "+++ %s\n", newName)
var (
done pair
chunk pair
count pair
ctext []string
)
for _, m := range diffTgs(x, y) {
if m.x < done.x {
continue
}
start := m
for start.x > done.x && start.y > done.y && x[start.x-1] == y[start.y-1] {
start.x--
start.y--
}
end := m
for end.x < len(x) && end.y < len(y) && x[end.x] == y[end.y] {
end.x++
end.y++
}
for _, s := range x[done.x:start.x] {
ctext = append(ctext, "-"+s)
count.x++
}
for _, s := range y[done.y:start.y] {
ctext = append(ctext, "+"+s)
count.y++
}
const C = 3
if (end.x < len(x) || end.y < len(y)) &&
(end.x-start.x < C || (len(ctext) > 0 && end.x-start.x < 2*C)) {
for _, s := range x[start.x:end.x] {
ctext = append(ctext, " "+s)
count.x++
count.y++
}
done = end
continue
}
if len(ctext) > 0 {
n := end.x - start.x
if n > C {
n = C
}
for _, s := range x[start.x : start.x+n] {
ctext = append(ctext, " "+s)
count.x++
count.y++
}
done = pair{start.x + n, start.y + n}
if count.x > 0 {
chunk.x++
}
if count.y > 0 {
chunk.y++
}
fmt.Fprintf(&out, "@@ -%d,%d +%d,%d @@\n", chunk.x, count.x, chunk.y, count.y)
for _, s := range ctext {
out.WriteString(s)
}
count.x = 0
count.y = 0
ctext = ctext[:0]
}
if end.x >= len(x) && end.y >= len(y) {
break
}
chunk = pair{end.x - C, end.y - C}
for _, s := range x[chunk.x:end.x] {
ctext = append(ctext, " "+s)
count.x++
count.y++
}
done = end
}
return out.Bytes()
}
func diffLines(x []byte) []string {
l := strings.SplitAfter(string(x), "\n")
if l[len(l)-1] == "" {
l = l[:len(l)-1]
} else {
l[len(l)-1] += "\n\\ No newline at end of file\n"
}
return l
}
func diffTgs(x, y []string) []pair {
m := make(map[string]int)
for _, s := range x {
if c := m[s]; c > -2 {
m[s] = c - 1
}
}
for _, s := range y {
if c := m[s]; c > -8 {
m[s] = c - 4
}
}
var xi, yi, inv []int
for i, s := range y {
if m[s] == -5 {
m[s] = len(yi)
yi = append(yi, i)
}
}
for i, s := range x {
if j, ok := m[s]; ok && j >= 0 {
xi = append(xi, i)
inv = append(inv, j)
}
}
J := inv
n := len(xi)
T := make([]int, n)
L := make([]int, n)
for i := range T {
T[i] = n + 1
}
for i := 0; i < n; i++ {
k := sort.Search(n, func(k int) bool {
return T[k] >= J[i]
})
T[k] = J[i]
L[i] = k + 1
}
k := 0
for _, v := range L {
if k < v {
k = v
}
}
seq := make([]pair, 2+k)
seq[1+k] = pair{len(x), len(y)}
lastj := n
for i := n - 1; i >= 0; i-- {
if L[i] == k && J[i] < lastj {
seq[k] = pair{xi[i], yi[J[i]]}
k--
}
}
seq[0] = pair{0, 0}
return seq
}
+15 -10
View File
@@ -190,6 +190,12 @@ func (h *Handler) matchFinalRule(network net.Network, address net.Address, port
func (h *Handler) Init(config *Config, pm policy.Manager) error { func (h *Handler) Init(config *Config, pm policy.Manager) error {
h.config = config h.config = config
h.policyManager = pm h.policyManager = pm
if h.usesDialerProxy { // freedom is not the final outbound, final rules do not apply
if len(config.FinalRules) > 0 {
errors.LogWarning(context.Background(), `The "finalRules" setting is ignored when "sockopt.dialerProxy" is set, since freedom is not the final outbound.`)
}
return nil
}
h.finalRules = make([]*FinalRule, 0, len(config.FinalRules)) h.finalRules = make([]*FinalRule, 0, len(config.FinalRules))
for _, rc := range config.FinalRules { for _, rc := range config.FinalRules {
rule, err := buildFinalRule(rc) rule, err := buildFinalRule(rc)
@@ -253,7 +259,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
ob.Name = "freedom" ob.Name = "freedom"
ob.CanSpliceCopy = 1 ob.CanSpliceCopy = 1
inbound := session.InboundFromContext(ctx) inbound := session.InboundFromContext(ctx)
defaultRule := getDefaultFinalRule(inbound) var defaultRule *FinalRule
if !h.usesDialerProxy { // freedom is not the final outbound, final rules do not apply (and the domain is not resolved)
defaultRule = getDefaultFinalRule(inbound)
}
destination := ob.Target destination := ob.Target
origTargetAddr := ob.OriginalTarget.Address origTargetAddr := ob.OriginalTarget.Address
@@ -342,15 +351,11 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
return h.blackhole(ctx, input, output, blockedRule, blockedDest) return h.blackhole(ctx, input, output, blockedRule, blockedDest)
} }
if destination.Address.Family().IsDomain() && (defaultRule != nil || len(h.finalRules) > 0) { if destination.Address.Family().IsDomain() && (defaultRule != nil || len(h.finalRules) > 0) {
if h.usesDialerProxy { // pre-check may fail or dialer may select another IP
errors.LogInfo(ctx, "skipping final rule check for proxied remote endpoint, original target: ", destination) remoteDest := net.DestinationFromAddr(conn.RemoteAddr())
} else { if rule := h.matchFinalRule(remoteDest.Network, remoteDest.Address, remoteDest.Port, defaultRule); rule != nil && rule.action == RuleAction_Block {
// pre-check may fail or dialer may select another IP conn.Close()
remoteDest := net.DestinationFromAddr(conn.RemoteAddr()) return h.blackhole(ctx, input, output, rule, &remoteDest)
if rule := h.matchFinalRule(remoteDest.Network, remoteDest.Address, remoteDest.Port, defaultRule); rule != nil && rule.action == RuleAction_Block {
conn.Close()
return h.blackhole(ctx, input, output, rule, &remoteDest)
}
} }
} }
+4 -8
View File
@@ -115,11 +115,7 @@ Start:
request, err := http.ReadRequest(reader) request, err := http.ReadRequest(reader)
if err != nil { if err != nil {
trace := errors.New("failed to read http request").Base(err) return errors.New("failed to read http request").Base(err)
if errors.Cause(err) != io.EOF && !isTimeout(errors.Cause(err)) {
trace.AtWarning()
}
return trace
} }
if len(s.config.Accounts) > 0 { if len(s.config.Accounts) > 0 {
@@ -147,7 +143,7 @@ Start:
} }
dest, err := http_proto.ParseHost(host, defaultPort) dest, err := http_proto.ParseHost(host, defaultPort)
if err != nil { if err != nil {
return errors.New("malformed proxy host: ", host).AtWarning().Base(err) return errors.New("malformed proxy host: ", host).Base(err)
} }
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{ ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
From: conn.RemoteAddr(), From: conn.RemoteAddr(),
@@ -262,7 +258,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
requestWriter := buf.NewBufferedWriter(link.Writer) requestWriter := buf.NewBufferedWriter(link.Writer)
common.Must(requestWriter.SetBuffered(false)) common.Must(requestWriter.SetBuffered(false))
if err := request.Write(requestWriter); err != nil { if err := request.Write(requestWriter); err != nil {
return errors.New("failed to write whole request").Base(err).AtWarning() return errors.New("failed to write whole request").Base(err)
} }
return nil return nil
} }
@@ -299,7 +295,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
response.Header.Set("Proxy-Connection", "close") response.Header.Set("Proxy-Connection", "close")
} }
if err := response.Write(writer); err != nil { if err := response.Write(writer); err != nil {
return errors.New("failed to write response").Base(err).AtWarning() return errors.New("failed to write response").Base(err)
} }
return nil return nil
} }
+1 -1
View File
@@ -62,7 +62,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
conn, err := dialer.Dial(hysteria.ContextWithDatagram(ctx, target.Network == net.Network_UDP), c.server.Destination) conn, err := dialer.Dial(hysteria.ContextWithDatagram(ctx, target.Network == net.Network_UDP), c.server.Destination)
if err != nil { if err != nil {
return errors.New("failed to find an available destination").AtWarning().Base(err) return errors.New("failed to find an available destination").Base(err)
} }
defer conn.Close() defer conn.Close()
errors.LogInfo(ctx, "tunneling request to ", target, " via ", target.Network, ":", c.server.Destination.NetAddr()) errors.LogInfo(ctx, "tunneling request to ", target, " via ", target.Network, ":", c.server.Destination.NetAddr())
+2 -2
View File
@@ -40,11 +40,11 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
for _, user := range config.Users { for _, user := range config.Users {
u, err := user.ToMemoryUser() u, err := user.ToMemoryUser()
if err != nil { if err != nil {
return nil, errors.New("failed to get hysteria user").Base(err).AtError() return nil, errors.New("failed to get hysteria user").Base(err)
} }
if err := validator.Add(u); err != nil { if err := validator.Add(u); err != nil {
return nil, errors.New("failed to add user").Base(err).AtError() return nil, errors.New("failed to add user").Base(err)
} }
} }
+1 -1
View File
@@ -56,7 +56,7 @@ func (l *Loopback) init(config *Config, dispatcherInstance routing.Dispatcher) e
if config.Sniffing.GetEnabled() { if config.Sniffing.GetEnabled() {
request, err := proxyman.BuildSniffingRequest(config.Sniffing) request, err := proxyman.BuildSniffingRequest(config.Sniffing)
if err != nil { if err != nil {
return errors.New("failed to build loopback sniffing request").Base(err).AtError() return errors.New("failed to build loopback sniffing request").Base(err)
} }
l.sniffingRequest = request l.sniffingRequest = request
} }
+2 -2
View File
@@ -71,7 +71,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return nil return nil
}) })
if err != nil { if err != nil {
return errors.New("failed to find an available destination").AtWarning().Base(err) return errors.New("failed to find an available destination").Base(err)
} }
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", network, ":", server.Destination.NetAddr()) errors.LogInfo(ctx, "tunneling request to ", destination, " via ", network, ":", server.Destination.NetAddr())
@@ -124,7 +124,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
} }
if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout { if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
return errors.New("failed to write A request payload").Base(err).AtWarning() return errors.New("failed to write A request payload").Base(err)
} }
if err := bufferedWriter.SetBuffered(false); err != nil { if err := bufferedWriter.SetBuffered(false); err != nil {
+2 -2
View File
@@ -98,7 +98,7 @@ func ReadTCPSession(validator *Validator, reader io.Reader) (*protocol.RequestHe
iv := append([]byte(nil), buffer.BytesTo(ivLen)...) iv := append([]byte(nil), buffer.BytesTo(ivLen)...)
r, err = account.Cipher.NewDecryptionReader(account.Key, iv, reader) r, err = account.Cipher.NewDecryptionReader(account.Key, iv, reader)
if err != nil { if err != nil {
return nil, nil, drain.WithError(drainer, reader, errors.New("failed to initialize decoding stream").Base(err).AtError()) return nil, nil, drain.WithError(drainer, reader, errors.New("failed to initialize decoding stream").Base(err))
} }
} }
} }
@@ -146,7 +146,7 @@ func WriteTCPRequest(request *protocol.RequestHeader, writer io.Writer) (buf.Wri
w, err := account.Cipher.NewEncryptionWriter(account.Key, iv, writer) w, err := account.Cipher.NewEncryptionWriter(account.Key, iv, writer)
if err != nil { if err != nil {
return nil, errors.New("failed to create encoding stream").Base(err).AtError() return nil, errors.New("failed to create encoding stream").Base(err)
} }
header := buf.New() header := buf.New()
+3 -3
View File
@@ -34,11 +34,11 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
for _, user := range config.Users { for _, user := range config.Users {
u, err := user.ToMemoryUser() u, err := user.ToMemoryUser()
if err != nil { if err != nil {
return nil, errors.New("failed to get shadowsocks user").Base(err).AtError() return nil, errors.New("failed to get shadowsocks user").Base(err)
} }
if err := validator.Add(u); err != nil { if err := validator.Add(u); err != nil {
return nil, errors.New("failed to add user").Base(err).AtError() return nil, errors.New("failed to add user").Base(err)
} }
} }
@@ -200,7 +200,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis
func (s *Server) handleConnection(ctx context.Context, conn stat.Connection, dispatcher routing.Dispatcher) error { func (s *Server) handleConnection(ctx context.Context, conn stat.Connection, dispatcher routing.Dispatcher) error {
sessionPolicy := s.policyManager.ForLevel(0) sessionPolicy := s.policyManager.ForLevel(0)
if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning() return errors.New("unable to set read deadline").Base(err)
} }
bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)} bufferedReader := buf.BufferedReader{Reader: buf.NewReader(conn)}
+1 -1
View File
@@ -59,7 +59,7 @@ func NewMultiServer(ctx context.Context, config *MultiUserServerConfig) (*MultiU
} }
u, err := user.ToMemoryUser() u, err := user.ToMemoryUser()
if err != nil { if err != nil {
return nil, errors.New("failed to get shadowsocks user").Base(err).AtError() return nil, errors.New("failed to get shadowsocks user").Base(err)
} }
memUsers = append(memUsers, u) memUsers = append(memUsers, u)
} }
+1 -1
View File
@@ -105,7 +105,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
} }
udpRequest, err := ClientHandshake(request, conn, conn) udpRequest, err := ClientHandshake(request, conn, conn)
if err != nil { if err != nil {
return errors.New("failed to establish connection to server").AtWarning().Base(err) return errors.New("failed to establish connection to server").Base(err)
} }
if udpRequest != nil { if udpRequest != nil {
if udpRequest.Address == net.AnyIP || udpRequest.Address == net.AnyIPv6 { if udpRequest.Address == net.AnyIP || udpRequest.Address == net.AnyIPv6 {
+2 -2
View File
@@ -458,10 +458,10 @@ func ClientHandshake(request *protocol.RequestHeader, reader io.Reader, writer i
} }
if b.Byte(0) != socks5Version { if b.Byte(0) != socks5Version {
return nil, errors.New("unexpected server version: ", b.Byte(0)).AtWarning() return nil, errors.New("unexpected server version: ", b.Byte(0))
} }
if b.Byte(1) != authByte { if b.Byte(1) != authByte {
return nil, errors.New("auth method not supported.").AtWarning() return nil, errors.New("auth method not supported.")
} }
if authByte == authPassword { if authByte == authPassword {
+5 -5
View File
@@ -69,7 +69,7 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return nil return nil
}) })
if err != nil { if err != nil {
return errors.New("failed to find an available destination").AtWarning().Base(err) return errors.New("failed to find an available destination").Base(err)
} }
errors.LogInfo(ctx, "tunneling request to ", destination, " via ", server.Destination.NetAddr()) errors.LogInfo(ctx, "tunneling request to ", destination, " via ", server.Destination.NetAddr())
@@ -116,21 +116,21 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
// write some request payload to buffer // write some request payload to buffer
if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout { if err = buf.CopyOnceTimeout(link.Reader, bodyWriter, time.Millisecond*100); err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
return errors.New("failed to write A request payload").Base(err).AtWarning() return errors.New("failed to write A request payload").Base(err)
} }
// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer // Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer
if err = bufferWriter.SetBuffered(false); err != nil { if err = bufferWriter.SetBuffered(false); err != nil {
return errors.New("failed to flush payload").Base(err).AtWarning() return errors.New("failed to flush payload").Base(err)
} }
// Send header if not sent yet // Send header if not sent yet
if _, err = connWriter.Write([]byte{}); err != nil { if _, err = connWriter.Write([]byte{}); err != nil {
return err.(*errors.Error).AtWarning() return err
} }
if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil { if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to transfer request payload").Base(err).AtInfo() return errors.New("failed to transfer request payload").Base(err)
} }
return nil return nil
+12 -12
View File
@@ -47,11 +47,11 @@ func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
for _, user := range config.Users { for _, user := range config.Users {
u, err := user.ToMemoryUser() u, err := user.ToMemoryUser()
if err != nil { if err != nil {
return nil, errors.New("failed to get trojan user").Base(err).AtError() return nil, errors.New("failed to get trojan user").Base(err)
} }
if err := validator.Add(u); err != nil { if err := validator.Add(u); err != nil {
return nil, errors.New("failed to add user").Base(err).AtError() return nil, errors.New("failed to add user").Base(err)
} }
} }
@@ -151,7 +151,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
sessionPolicy := s.policyManager.ForLevel(0) sessionPolicy := s.policyManager.ForLevel(0)
if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning() return errors.New("unable to set read deadline").Base(err)
} }
first := buf.FromBytes(make([]byte, buf.Size)) first := buf.FromBytes(make([]byte, buf.Size))
@@ -219,7 +219,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
destination := clientReader.Target destination := clientReader.Target
if err := conn.SetReadDeadline(time.Time{}); err != nil { if err := conn.SetReadDeadline(time.Time{}); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning() return errors.New("unable to set read deadline").Base(err)
} }
inbound := session.InboundFromContext(ctx) inbound := session.InboundFromContext(ctx)
@@ -402,7 +402,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
} }
apfb := napfb[name] apfb := napfb[name]
if apfb == nil { if apfb == nil {
return errors.New(`failed to find the default "name" config`).AtWarning() return errors.New(`failed to find the default "name" config`)
} }
if apfb[alpn] == nil { if apfb[alpn] == nil {
@@ -410,7 +410,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
} }
pfb := apfb[alpn] pfb := apfb[alpn]
if pfb == nil { if pfb == nil {
return errors.New(`failed to find the default "alpn" config`).AtWarning() return errors.New(`failed to find the default "alpn" config`)
} }
path := "" path := ""
@@ -444,7 +444,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
} }
fb := pfb[path] fb := pfb[path]
if fb == nil { if fb == nil {
return errors.New(`failed to find the default "path" config`).AtWarning() return errors.New(`failed to find the default "path" config`)
} }
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
@@ -460,7 +460,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
} }
return nil return nil
}); err != nil { }); err != nil {
return errors.New("failed to dial to " + fb.Dest).Base(err).AtWarning() return errors.New("failed to dial to " + fb.Dest).Base(err)
} }
defer conn.Close() defer conn.Close()
@@ -520,11 +520,11 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
common.Must2(pro.Write([]byte{byte(p1 >> 8), byte(p1), byte(p2 >> 8), byte(p2)})) common.Must2(pro.Write([]byte{byte(p1 >> 8), byte(p1), byte(p2 >> 8), byte(p2)}))
} }
if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil { if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil {
return errors.New("failed to set PROXY protocol v", fb.Xver).Base(err).AtWarning() return errors.New("failed to set PROXY protocol v", fb.Xver).Base(err)
} }
} }
if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil { if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to fallback request payload").Base(err).AtInfo() return errors.New("failed to fallback request payload").Base(err)
} }
return nil return nil
} }
@@ -534,7 +534,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
getResponse := func() error { getResponse := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly) defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
if err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil { if err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to deliver response payload").Base(err).AtInfo() return errors.New("failed to deliver response payload").Base(err)
} }
return nil return nil
} }
@@ -542,7 +542,7 @@ func (s *Server) fallback(ctx context.Context, err error, sessionPolicy policy.S
if err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), task.OnSuccess(getResponse, task.Close(writer))); err != nil { if err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), task.OnSuccess(getResponse, task.Close(writer))); err != nil {
common.Must(common.Interrupt(serverReader)) common.Must(common.Interrupt(serverReader))
common.Must(common.Interrupt(serverWriter)) common.Must(common.Interrupt(serverWriter))
return errors.New("fallback ends").Base(err).AtInfo() return errors.New("fallback ends").Base(err)
} }
return nil return nil
+1 -1
View File
@@ -12,7 +12,7 @@ import (
func (a *Account) AsAccount() (protocol.Account, error) { func (a *Account) AsAccount() (protocol.Account, error) {
id, err := uuid.ParseString(a.Id) id, err := uuid.ParseString(a.Id)
if err != nil { if err != nil {
return nil, errors.New("failed to parse ID").Base(err).AtError() return nil, errors.New("failed to parse ID").Base(err)
} }
return &MemoryAccount{ return &MemoryAccount{
ID: protocol.NewID(id), ID: protocol.NewID(id),
+25 -25
View File
@@ -61,10 +61,10 @@ func init() {
for _, user := range c.Users { for _, user := range c.Users {
u, err := user.ToMemoryUser() u, err := user.ToMemoryUser()
if err != nil { if err != nil {
return nil, errors.New("failed to get VLESS user").Base(err).AtError() return nil, errors.New("failed to get VLESS user").Base(err)
} }
if err := validator.Add(u); err != nil { if err := validator.Add(u); err != nil {
return nil, errors.New("failed to initiate user").Base(err).AtError() return nil, errors.New("failed to initiate user").Base(err)
} }
} }
@@ -110,7 +110,7 @@ func New(ctx context.Context, config *Config, dc dns.Client, validator vless.Val
} }
handler.decryption = &encryption.ServerInstance{} handler.decryption = &encryption.ServerInstance{}
if err := handler.decryption.Init(nfsSKeysBytes, config.XorMode, config.SecondsFrom, config.SecondsTo, config.Padding); err != nil { if err := handler.decryption.Init(nfsSKeysBytes, config.XorMode, config.SecondsFrom, config.SecondsTo, config.Padding); err != nil {
return nil, errors.New("failed to use decryption").Base(err).AtError() return nil, errors.New("failed to use decryption").Base(err)
} }
} }
@@ -128,7 +128,7 @@ func New(ctx context.Context, config *Config, dc dns.Client, validator vless.Val
/* /*
if fb.Path != "" { if fb.Path != "" {
if r, err := regexp.Compile(fb.Path); err != nil { if r, err := regexp.Compile(fb.Path); err != nil {
return nil, errors.New("invalid path regexp").Base(err).AtError() return nil, errors.New("invalid path regexp").Base(err)
} else { } else {
handler.regexps[fb.Path] = r handler.regexps[fb.Path] = r
} }
@@ -274,13 +274,13 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if h.decryption != nil { if h.decryption != nil {
var err error var err error
if connection, err = h.decryption.Handshake(connection, nil); err != nil { if connection, err = h.decryption.Handshake(connection, nil); err != nil {
return errors.New("ML-KEM-768 handshake failed").Base(err).AtInfo() return errors.New("ML-KEM-768 handshake failed").Base(err)
} }
} }
sessionPolicy := h.policyManager.ForLevel(0) sessionPolicy := h.policyManager.ForLevel(0)
if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning() return errors.New("unable to set read deadline").Base(err)
} }
first := buf.FromBytes(make([]byte, buf.Size)) first := buf.FromBytes(make([]byte, buf.Size))
@@ -352,7 +352,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
} }
apfb := napfb[name] apfb := napfb[name]
if apfb == nil { if apfb == nil {
return errors.New(`failed to find the default "name" config`).AtWarning() return errors.New(`failed to find the default "name" config`)
} }
if apfb[alpn] == nil { if apfb[alpn] == nil {
@@ -360,7 +360,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
} }
pfb := apfb[alpn] pfb := apfb[alpn]
if pfb == nil { if pfb == nil {
return errors.New(`failed to find the default "alpn" config`).AtWarning() return errors.New(`failed to find the default "alpn" config`)
} }
path := "" path := ""
@@ -369,7 +369,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if lines := bytes.Split(firstBytes, []byte{'\r', '\n'}); len(lines) > 1 { if lines := bytes.Split(firstBytes, []byte{'\r', '\n'}); len(lines) > 1 {
if s := bytes.Split(lines[0], []byte{' '}); len(s) == 3 { if s := bytes.Split(lines[0], []byte{' '}); len(s) == 3 {
if len(s[0]) < 8 && len(s[1]) > 0 && len(s[2]) == 8 { if len(s[0]) < 8 && len(s[1]) > 0 && len(s[2]) == 8 {
errors.New("realPath = " + string(s[1])).AtInfo().WriteToLog(sid) errors.New("realPath = " + string(s[1])).WriteToLog(sid)
for _, fb := range pfb { for _, fb := range pfb {
if fb.Path != "" && h.regexps[fb.Path].Match(s[1]) { if fb.Path != "" && h.regexps[fb.Path].Match(s[1]) {
path = fb.Path path = fb.Path
@@ -409,7 +409,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
} }
fb := pfb[path] fb := pfb[path]
if fb == nil { if fb == nil {
return errors.New(`failed to find the default "path" config`).AtWarning() return errors.New(`failed to find the default "path" config`)
} }
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
@@ -425,7 +425,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
} }
return nil return nil
}); err != nil { }); err != nil {
return errors.New("failed to dial to " + fb.Dest).Base(err).AtWarning() return errors.New("failed to dial to " + fb.Dest).Base(err)
} }
defer conn.Close() defer conn.Close()
@@ -485,11 +485,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
pro.Write([]byte{byte(p1 >> 8), byte(p1), byte(p2 >> 8), byte(p2)}) pro.Write([]byte{byte(p1 >> 8), byte(p1), byte(p2 >> 8), byte(p2)})
} }
if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil { if err := serverWriter.WriteMultiBuffer(buf.MultiBuffer{pro}); err != nil {
return errors.New("failed to set PROXY protocol v", fb.Xver).Base(err).AtWarning() return errors.New("failed to set PROXY protocol v", fb.Xver).Base(err)
} }
} }
if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil { if err := buf.Copy(reader, serverWriter, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to fallback request payload").Base(err).AtInfo() return errors.New("failed to fallback request payload").Base(err)
} }
return nil return nil
} }
@@ -499,7 +499,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
getResponse := func() error { getResponse := func() error {
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly) defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
if err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil { if err := buf.Copy(serverReader, writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to deliver response payload").Base(err).AtInfo() return errors.New("failed to deliver response payload").Base(err)
} }
return nil return nil
} }
@@ -507,7 +507,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
if err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), task.OnSuccess(getResponse, task.Close(writer))); err != nil { if err := task.Run(ctx, task.OnSuccess(postRequest, task.Close(serverWriter)), task.OnSuccess(getResponse, task.Close(writer))); err != nil {
common.Interrupt(serverReader) common.Interrupt(serverReader)
common.Interrupt(serverWriter) common.Interrupt(serverWriter)
return errors.New("fallback ends").Base(err).AtInfo() return errors.New("fallback ends").Base(err)
} }
return nil return nil
} }
@@ -519,7 +519,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
Status: log.AccessRejected, Status: log.AccessRejected,
Reason: err, Reason: err,
}) })
err = errors.New("invalid request from ", connection.RemoteAddr()).Base(err).AtInfo() err = errors.New("invalid request from ", connection.RemoteAddr()).Base(err)
} }
return err return err
} }
@@ -555,7 +555,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
inbound.CanSpliceCopy = 2 inbound.CanSpliceCopy = 2
switch request.Command { switch request.Command {
case protocol.RequestCommandUDP: case protocol.RequestCommandUDP:
return errors.New(requestAddons.Flow + " doesn't support UDP").AtWarning() return errors.New(requestAddons.Flow + " doesn't support UDP")
case protocol.RequestCommandMux, protocol.RequestCommandRvs: case protocol.RequestCommandMux, protocol.RequestCommandRvs:
inbound.CanSpliceCopy = 3 inbound.CanSpliceCopy = 3
fallthrough // we will break Mux connections that contain TCP requests fallthrough // we will break Mux connections that contain TCP requests
@@ -570,7 +570,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
p = uintptr(unsafe.Pointer(commonConn)) p = uintptr(unsafe.Pointer(commonConn))
} else if tlsConn, ok := iConn.(*tls.Conn); ok { } else if tlsConn, ok := iConn.(*tls.Conn); ok {
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 { if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning() return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version)
} }
t = reflect.TypeOf(tlsConn.Conn).Elem() t = reflect.TypeOf(tlsConn.Conn).Elem()
p = uintptr(unsafe.Pointer(tlsConn.Conn)) p = uintptr(unsafe.Pointer(tlsConn.Conn))
@@ -578,7 +578,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
t = reflect.TypeOf(realityConn.Conn).Elem() t = reflect.TypeOf(realityConn.Conn).Elem()
p = uintptr(unsafe.Pointer(realityConn.Conn)) p = uintptr(unsafe.Pointer(realityConn.Conn))
} else { } else {
return errors.New("XTLS only supports TLS and REALITY directly for now.").AtWarning() return errors.New("XTLS only supports TLS and REALITY directly for now.")
} }
i, _ := t.FieldByName("input") i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput") r, _ := t.FieldByName("rawInput")
@@ -586,15 +586,15 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset)) rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
} }
} else { } else {
return errors.New("account " + account.ID.String() + " is not able to use the flow " + requestAddons.Flow).AtWarning() return errors.New("account " + account.ID.String() + " is not able to use the flow " + requestAddons.Flow)
} }
case "": case "":
inbound.CanSpliceCopy = 3 inbound.CanSpliceCopy = 3
if account.Flow == vless.XRV && (request.Command == protocol.RequestCommandTCP || isMuxAndNotXUDP(request, first)) { if account.Flow == vless.XRV && (request.Command == protocol.RequestCommandTCP || isMuxAndNotXUDP(request, first)) {
return errors.New("account " + account.ID.String() + " is rejected since the client flow is empty. Note that the pure TLS proxy has certain TLS in TLS characters.").AtWarning() return errors.New("account " + account.ID.String() + " is rejected since the client flow is empty. Note that the pure TLS proxy has certain TLS in TLS characters.")
} }
default: default:
return errors.New("unknown request flow " + requestAddons.Flow).AtWarning() return errors.New("unknown request flow " + requestAddons.Flow)
} }
if request.Command != protocol.RequestCommandMux { if request.Command != protocol.RequestCommandMux {
@@ -617,7 +617,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(connection)) bufferWriter := buf.NewBufferedWriter(buf.NewWriter(connection))
if err := encoding.EncodeResponseHeader(bufferWriter, request, responseAddons); err != nil { if err := encoding.EncodeResponseHeader(bufferWriter, request, responseAddons); err != nil {
return errors.New("failed to encode response header").Base(err).AtWarning() return errors.New("failed to encode response header").Base(err)
} }
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, false, ctx, connection, nil) clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, false, ctx, connection, nil)
bufferWriter.SetFlushNext() bufferWriter.SetFlushNext()
@@ -654,11 +654,11 @@ func (r *Reverse) Tag() string {
func (r *Reverse) NewMux(ctx context.Context, link *transport.Link, observer features.Feature) error { func (r *Reverse) NewMux(ctx context.Context, link *transport.Link, observer features.Feature) error {
muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{}) muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{})
if err != nil { if err != nil {
return errors.New("failed to create mux client worker").Base(err).AtWarning() return errors.New("failed to create mux client worker").Base(err)
} }
worker, err := reverse.NewPortalWorker(muxClient) worker, err := reverse.NewPortalWorker(muxClient)
if err != nil { if err != nil {
return errors.New("failed to create portal worker").Base(err).AtWarning() return errors.New("failed to create portal worker").Base(err)
} }
r.picker.AddWorker(worker) r.picker.AddWorker(worker)
if burstObs, ok := observer.(extension.BurstObservatory); ok { if burstObs, ok := observer.(extension.BurstObservatory); ok {
+18 -18
View File
@@ -73,7 +73,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
} }
server, err := protocol.NewServerSpecFromPB(config.Vnext) server, err := protocol.NewServerSpecFromPB(config.Vnext)
if err != nil { if err != nil {
return nil, errors.New("failed to get server spec").Base(err).AtError() return nil, errors.New("failed to get server spec").Base(err)
} }
v := core.MustFromContext(ctx) v := core.MustFromContext(ctx)
@@ -93,7 +93,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
} }
handler.encryption = &encryption.ClientInstance{} handler.encryption = &encryption.ClientInstance{}
if err := handler.encryption.Init(nfsPKeysBytes, a.XorMode, a.Seconds, a.Padding); err != nil { if err := handler.encryption.Init(nfsPKeysBytes, a.XorMode, a.Seconds, a.Padding); err != nil {
return nil, errors.New("failed to use encryption").Base(err).AtError() return nil, errors.New("failed to use encryption").Base(err)
} }
} }
@@ -106,7 +106,7 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
if sc := a.Reverse.Sniffing; sc != nil && sc.Enabled { if sc := a.Reverse.Sniffing; sc != nil && sc.Enabled {
request, err := proxymanConfig.BuildSniffingRequest(sc) request, err := proxymanConfig.BuildSniffingRequest(sc)
if err != nil { if err != nil {
return nil, errors.New("failed to build reverse sniffing request").Base(err).AtError() return nil, errors.New("failed to build reverse sniffing request").Base(err)
} }
rvsCtx = session.ContextWithContent(rvsCtx, &session.Content{ rvsCtx = session.ContextWithContent(rvsCtx, &session.Content{
SniffingRequest: request, SniffingRequest: request,
@@ -149,7 +149,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1] ob := outbounds[len(outbounds)-1]
if !ob.Target.IsValid() && ob.Target.Address.String() != "v1.rvs.cool" { if !ob.Target.IsValid() && ob.Target.Address.String() != "v1.rvs.cool" {
return errors.New("target not specified").AtError() return errors.New("target not specified")
} }
ob.Name = "vless" ob.Name = "vless"
@@ -178,7 +178,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
for { for {
connTime := <-h.preConns connTime := <-h.preConns
if connTime == nil { if connTime == nil {
return errors.New("closed handler").AtWarning() return errors.New("closed handler")
} }
if time.Now().Before(connTime.Expire) { if time.Now().Before(connTime.Expire) {
conn = connTime.Conn conn = connTime.Conn
@@ -197,7 +197,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
} }
return nil return nil
}); err != nil { }); err != nil {
return errors.New("failed to find an available destination").Base(err).AtWarning() return errors.New("failed to find an available destination").Base(err)
} }
} }
defer conn.Close() defer conn.Close()
@@ -209,7 +209,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
if h.encryption != nil { if h.encryption != nil {
var err error var err error
if conn, err = h.encryption.Handshake(conn); err != nil { if conn, err = h.encryption.Handshake(conn); err != nil {
return errors.New("ML-KEM-768 handshake failed").Base(err).AtInfo() return errors.New("ML-KEM-768 handshake failed").Base(err)
} }
} }
@@ -223,7 +223,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
command = protocol.RequestCommandMux command = protocol.RequestCommandMux
case "v1.rvs.cool": case "v1.rvs.cool":
if target.Network != net.Network_Unknown { if target.Network != net.Network_Unknown {
return errors.New("nice try baby").AtError() return errors.New("nice try baby")
} }
command = protocol.RequestCommandRvs command = protocol.RequestCommandRvs
} }
@@ -256,7 +256,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
switch request.Command { switch request.Command {
case protocol.RequestCommandUDP: case protocol.RequestCommandUDP:
if !allowUDP443 && request.Port == 443 { if !allowUDP443 && request.Port == 443 {
return errors.New("XTLS rejected UDP/443 traffic").AtInfo() return errors.New("XTLS rejected UDP/443 traffic")
} }
case protocol.RequestCommandMux: case protocol.RequestCommandMux:
fallthrough // let server break Mux connections that contain TCP requests fallthrough // let server break Mux connections that contain TCP requests
@@ -279,7 +279,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
t = reflect.TypeOf(realityConn.Conn).Elem() t = reflect.TypeOf(realityConn.Conn).Elem()
p = uintptr(unsafe.Pointer(realityConn.Conn)) p = uintptr(unsafe.Pointer(realityConn.Conn))
} else { } else {
return errors.New("XTLS only supports TLS and REALITY directly for now.").AtWarning() return errors.New("XTLS only supports TLS and REALITY directly for now.")
} }
i, _ := t.FieldByName("input") i, _ := t.FieldByName("input")
r, _ := t.FieldByName("rawInput") r, _ := t.FieldByName("rawInput")
@@ -321,7 +321,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn)) bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
if err := encoding.EncodeRequestHeader(bufferWriter, request, requestAddons); err != nil { if err := encoding.EncodeRequestHeader(bufferWriter, request, requestAddons); err != nil {
return errors.New("failed to encode request header").Base(err).AtWarning() return errors.New("failed to encode request header").Base(err)
} }
// default: serverWriter := bufferWriter // default: serverWriter := bufferWriter
@@ -350,23 +350,23 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
} }
// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer // Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer
if err := bufferWriter.SetBuffered(false); err != nil { if err := bufferWriter.SetBuffered(false); err != nil {
return errors.New("failed to write A request payload").Base(err).AtWarning() return errors.New("failed to write A request payload").Base(err)
} }
if requestAddons.Flow == vless.XRV { if requestAddons.Flow == vless.XRV {
if tlsConn, ok := iConn.(*tls.Conn); ok { if tlsConn, ok := iConn.(*tls.Conn); ok {
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 { if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning() return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version)
} }
} else if utlsConn, ok := iConn.(*tls.UConn); ok { } else if utlsConn, ok := iConn.(*tls.UConn); ok {
if utlsConn.ConnectionState().Version != utls.VersionTLS13 { if utlsConn.ConnectionState().Version != utls.VersionTLS13 {
return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, utlsConn.ConnectionState().Version).AtWarning() return errors.New(`failed to use `+requestAddons.Flow+`, found outer tls version `, utlsConn.ConnectionState().Version)
} }
} }
} }
err := buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer)) err := buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
if err != nil { if err != nil {
return errors.New("failed to transfer request payload").Base(err).AtInfo() return errors.New("failed to transfer request payload").Base(err)
} }
// Indicates the end of request payload. // Indicates the end of request payload.
@@ -381,7 +381,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
responseAddons, err := encoding.DecodeResponseHeader(conn, request) responseAddons, err := encoding.DecodeResponseHeader(conn, request)
if err != nil { if err != nil {
return errors.New("failed to decode response header").Base(err).AtInfo() return errors.New("failed to decode response header").Base(err)
} }
// default: serverReader := buf.NewReader(conn) // default: serverReader := buf.NewReader(conn)
@@ -405,7 +405,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
} }
if err != nil { if err != nil {
return errors.New("failed to transfer response payload").Base(err).AtInfo() return errors.New("failed to transfer response payload").Base(err)
} }
return nil return nil
@@ -416,7 +416,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
} }
if err := task.Run(ctx, postRequest, task.OnSuccess(getResponse, task.Close(clientWriter))); err != nil { if err := task.Run(ctx, postRequest, task.OnSuccess(getResponse, task.Close(clientWriter))); err != nil {
return errors.New("connection ends").Base(err).AtInfo() return errors.New("connection ends").Base(err)
} }
return nil return nil
+1 -1
View File
@@ -49,7 +49,7 @@ func (a *MemoryAccount) ToProto() proto.Message {
func (a *Account) AsAccount() (protocol.Account, error) { func (a *Account) AsAccount() (protocol.Account, error) {
id, err := uuid.ParseString(a.Id) id, err := uuid.ParseString(a.Id)
if err != nil { if err != nil {
return nil, errors.New("failed to parse ID").Base(err).AtError() return nil, errors.New("failed to parse ID").Base(err)
} }
protoID := protocol.NewID(id) protoID := protocol.NewID(id)
var AuthenticatedLength, NoTerminationSignal bool var AuthenticatedLength, NoTerminationSignal bool
+1 -1
View File
@@ -209,7 +209,7 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
defer buffer.Release() defer buffer.Release()
if _, err := buffer.ReadFullFrom(c.responseReader, 4); err != nil { if _, err := buffer.ReadFullFrom(c.responseReader, 4); err != nil {
return nil, errors.New("failed to read response header").Base(err).AtWarning() return nil, errors.New("failed to read response header").Base(err)
} }
if buffer.Byte(0) != c.responseHeader { if buffer.Byte(0) != c.responseHeader {
+2 -2
View File
@@ -227,7 +227,7 @@ func transferResponse(timer signal.ActivityUpdater, session *encoding.ServerSess
func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error { func (h *Handler) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
sessionPolicy := h.policyManager.ForLevel(0) sessionPolicy := h.policyManager.ForLevel(0)
if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil { if err := connection.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
return errors.New("unable to set read deadline").Base(err).AtWarning() return errors.New("unable to set read deadline").Base(err)
} }
iConn := stat.TryUnwrapStatsConn(connection) iConn := stat.TryUnwrapStatsConn(connection)
@@ -247,7 +247,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
Status: log.AccessRejected, Status: log.AccessRejected,
Reason: err, Reason: err,
}) })
err = errors.New("invalid request from ", connection.RemoteAddr()).Base(err).AtInfo() err = errors.New("invalid request from ", connection.RemoteAddr()).Base(err)
} }
return err return err
} }
+3 -3
View File
@@ -60,7 +60,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1] ob := outbounds[len(outbounds)-1]
if !ob.Target.IsValid() { if !ob.Target.IsValid() {
return errors.New("target not specified").AtError() return errors.New("target not specified")
} }
ob.Name = "vmess" ob.Name = "vmess"
ob.CanSpliceCopy = 3 ob.CanSpliceCopy = 3
@@ -78,7 +78,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
return nil return nil
}) })
if err != nil { if err != nil {
return errors.New("failed to find an available destination").Base(err).AtWarning() return errors.New("failed to find an available destination").Base(err)
} }
defer conn.Close() defer conn.Close()
@@ -154,7 +154,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
writer := buf.NewBufferedWriter(buf.NewWriter(conn)) writer := buf.NewBufferedWriter(buf.NewWriter(conn))
if err := session.EncodeRequestHeader(request, writer); err != nil { if err := session.EncodeRequestHeader(request, writer); err != nil {
return errors.New("failed to encode request").Base(err).AtWarning() return errors.New("failed to encode request").Base(err)
} }
bodyWriter, err := session.EncodeRequestBody(request, writer) bodyWriter, err := session.EncodeRequestBody(request, writer)
+1 -1
View File
@@ -27,7 +27,7 @@ var strategy = [11][3]byte{
func RegisterProtocolConfigCreator(name string, creator ConfigCreator) error { func RegisterProtocolConfigCreator(name string, creator ConfigCreator) error {
if _, found := globalTransportConfigCreatorCache[name]; found { if _, found := globalTransportConfigCreatorCache[name]; found {
return errors.New("protocol ", name, " is already registered").AtError() return errors.New("protocol ", name, " is already registered")
} }
globalTransportConfigCreatorCache[name] = creator globalTransportConfigCreatorCache[name] = creator
return nil return nil
+63 -138
View File
@@ -206,7 +206,7 @@ func (x SocketConfig_TProxyMode) Number() protoreflect.EnumNumber {
// Deprecated: Use SocketConfig_TProxyMode.Descriptor instead. // Deprecated: Use SocketConfig_TProxyMode.Descriptor instead.
func (SocketConfig_TProxyMode) EnumDescriptor() ([]byte, []int) { func (SocketConfig_TProxyMode) EnumDescriptor() ([]byte, []int) {
return file_transport_internet_config_proto_rawDescGZIP(), []int{5, 0} return file_transport_internet_config_proto_rawDescGZIP(), []int{4, 0}
} }
type TransportConfig struct { type TransportConfig struct {
@@ -382,66 +382,6 @@ func (x *StreamConfig) GetSocketSettings() *SocketConfig {
return nil return nil
} }
type UdpHop struct {
state protoimpl.MessageState `protogen:"open.v1"`
Ports []uint32 `protobuf:"varint,1,rep,packed,name=ports,proto3" json:"ports,omitempty"`
IntervalMin int64 `protobuf:"varint,2,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
IntervalMax int64 `protobuf:"varint,3,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UdpHop) Reset() {
*x = UdpHop{}
mi := &file_transport_internet_config_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UdpHop) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UdpHop) ProtoMessage() {}
func (x *UdpHop) ProtoReflect() protoreflect.Message {
mi := &file_transport_internet_config_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UdpHop.ProtoReflect.Descriptor instead.
func (*UdpHop) Descriptor() ([]byte, []int) {
return file_transport_internet_config_proto_rawDescGZIP(), []int{2}
}
func (x *UdpHop) GetPorts() []uint32 {
if x != nil {
return x.Ports
}
return nil
}
func (x *UdpHop) GetIntervalMin() int64 {
if x != nil {
return x.IntervalMin
}
return 0
}
func (x *UdpHop) GetIntervalMax() int64 {
if x != nil {
return x.IntervalMax
}
return 0
}
type QuicParams struct { type QuicParams struct {
state protoimpl.MessageState `protogen:"open.v1"` state protoimpl.MessageState `protogen:"open.v1"`
Congestion string `protobuf:"bytes,1,opt,name=congestion,proto3" json:"congestion,omitempty"` Congestion string `protobuf:"bytes,1,opt,name=congestion,proto3" json:"congestion,omitempty"`
@@ -449,25 +389,24 @@ type QuicParams struct {
BrutalUp uint64 `protobuf:"varint,3,opt,name=brutal_up,json=brutalUp,proto3" json:"brutal_up,omitempty"` BrutalUp uint64 `protobuf:"varint,3,opt,name=brutal_up,json=brutalUp,proto3" json:"brutal_up,omitempty"`
BrutalDown uint64 `protobuf:"varint,4,opt,name=brutal_down,json=brutalDown,proto3" json:"brutal_down,omitempty"` BrutalDown uint64 `protobuf:"varint,4,opt,name=brutal_down,json=brutalDown,proto3" json:"brutal_down,omitempty"`
BrutalDisableLossCompensation bool `protobuf:"varint,5,opt,name=brutal_disable_loss_compensation,json=brutalDisableLossCompensation,proto3" json:"brutal_disable_loss_compensation,omitempty"` BrutalDisableLossCompensation bool `protobuf:"varint,5,opt,name=brutal_disable_loss_compensation,json=brutalDisableLossCompensation,proto3" json:"brutal_disable_loss_compensation,omitempty"`
UdpHop *UdpHop `protobuf:"bytes,6,opt,name=udp_hop,json=udpHop,proto3" json:"udp_hop,omitempty"` InitStreamReceiveWindow uint64 `protobuf:"varint,6,opt,name=init_stream_receive_window,json=initStreamReceiveWindow,proto3" json:"init_stream_receive_window,omitempty"`
InitStreamReceiveWindow uint64 `protobuf:"varint,7,opt,name=init_stream_receive_window,json=initStreamReceiveWindow,proto3" json:"init_stream_receive_window,omitempty"` MaxStreamReceiveWindow uint64 `protobuf:"varint,7,opt,name=max_stream_receive_window,json=maxStreamReceiveWindow,proto3" json:"max_stream_receive_window,omitempty"`
MaxStreamReceiveWindow uint64 `protobuf:"varint,8,opt,name=max_stream_receive_window,json=maxStreamReceiveWindow,proto3" json:"max_stream_receive_window,omitempty"` InitConnReceiveWindow uint64 `protobuf:"varint,8,opt,name=init_conn_receive_window,json=initConnReceiveWindow,proto3" json:"init_conn_receive_window,omitempty"`
InitConnReceiveWindow uint64 `protobuf:"varint,9,opt,name=init_conn_receive_window,json=initConnReceiveWindow,proto3" json:"init_conn_receive_window,omitempty"` MaxConnReceiveWindow uint64 `protobuf:"varint,9,opt,name=max_conn_receive_window,json=maxConnReceiveWindow,proto3" json:"max_conn_receive_window,omitempty"`
MaxConnReceiveWindow uint64 `protobuf:"varint,10,opt,name=max_conn_receive_window,json=maxConnReceiveWindow,proto3" json:"max_conn_receive_window,omitempty"` MaxIdleTimeout int64 `protobuf:"varint,10,opt,name=max_idle_timeout,json=maxIdleTimeout,proto3" json:"max_idle_timeout,omitempty"`
MaxIdleTimeout int64 `protobuf:"varint,11,opt,name=max_idle_timeout,json=maxIdleTimeout,proto3" json:"max_idle_timeout,omitempty"` KeepAlivePeriod int64 `protobuf:"varint,11,opt,name=keep_alive_period,json=keepAlivePeriod,proto3" json:"keep_alive_period,omitempty"`
KeepAlivePeriod int64 `protobuf:"varint,12,opt,name=keep_alive_period,json=keepAlivePeriod,proto3" json:"keep_alive_period,omitempty"` DisablePathMtuDiscovery bool `protobuf:"varint,12,opt,name=disable_path_mtu_discovery,json=disablePathMtuDiscovery,proto3" json:"disable_path_mtu_discovery,omitempty"`
DisablePathMtuDiscovery bool `protobuf:"varint,13,opt,name=disable_path_mtu_discovery,json=disablePathMtuDiscovery,proto3" json:"disable_path_mtu_discovery,omitempty"` DisableChromeParrot bool `protobuf:"varint,13,opt,name=disable_chrome_parrot,json=disableChromeParrot,proto3" json:"disable_chrome_parrot,omitempty"`
DisableChromeParrot bool `protobuf:"varint,14,opt,name=disable_chrome_parrot,json=disableChromeParrot,proto3" json:"disable_chrome_parrot,omitempty"` DisableGSO bool `protobuf:"varint,14,opt,name=disableGSO,proto3" json:"disableGSO,omitempty"`
DisableGSO bool `protobuf:"varint,15,opt,name=disableGSO,proto3" json:"disableGSO,omitempty"` MaxIncomingStreams int64 `protobuf:"varint,15,opt,name=max_incoming_streams,json=maxIncomingStreams,proto3" json:"max_incoming_streams,omitempty"`
MaxIncomingStreams int64 `protobuf:"varint,16,opt,name=max_incoming_streams,json=maxIncomingStreams,proto3" json:"max_incoming_streams,omitempty"` DisableStatelessReset bool `protobuf:"varint,16,opt,name=disable_stateless_reset,json=disableStatelessReset,proto3" json:"disable_stateless_reset,omitempty"`
DisableStatelessReset bool `protobuf:"varint,17,opt,name=disable_stateless_reset,json=disableStatelessReset,proto3" json:"disable_stateless_reset,omitempty"`
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
} }
func (x *QuicParams) Reset() { func (x *QuicParams) Reset() {
*x = QuicParams{} *x = QuicParams{}
mi := &file_transport_internet_config_proto_msgTypes[3] mi := &file_transport_internet_config_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -479,7 +418,7 @@ func (x *QuicParams) String() string {
func (*QuicParams) ProtoMessage() {} func (*QuicParams) ProtoMessage() {}
func (x *QuicParams) ProtoReflect() protoreflect.Message { func (x *QuicParams) ProtoReflect() protoreflect.Message {
mi := &file_transport_internet_config_proto_msgTypes[3] mi := &file_transport_internet_config_proto_msgTypes[2]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -492,7 +431,7 @@ func (x *QuicParams) ProtoReflect() protoreflect.Message {
// Deprecated: Use QuicParams.ProtoReflect.Descriptor instead. // Deprecated: Use QuicParams.ProtoReflect.Descriptor instead.
func (*QuicParams) Descriptor() ([]byte, []int) { func (*QuicParams) Descriptor() ([]byte, []int) {
return file_transport_internet_config_proto_rawDescGZIP(), []int{3} return file_transport_internet_config_proto_rawDescGZIP(), []int{2}
} }
func (x *QuicParams) GetCongestion() string { func (x *QuicParams) GetCongestion() string {
@@ -530,13 +469,6 @@ func (x *QuicParams) GetBrutalDisableLossCompensation() bool {
return false return false
} }
func (x *QuicParams) GetUdpHop() *UdpHop {
if x != nil {
return x.UdpHop
}
return nil
}
func (x *QuicParams) GetInitStreamReceiveWindow() uint64 { func (x *QuicParams) GetInitStreamReceiveWindow() uint64 {
if x != nil { if x != nil {
return x.InitStreamReceiveWindow return x.InitStreamReceiveWindow
@@ -628,7 +560,7 @@ type CustomSockopt struct {
func (x *CustomSockopt) Reset() { func (x *CustomSockopt) Reset() {
*x = CustomSockopt{} *x = CustomSockopt{}
mi := &file_transport_internet_config_proto_msgTypes[4] mi := &file_transport_internet_config_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -640,7 +572,7 @@ func (x *CustomSockopt) String() string {
func (*CustomSockopt) ProtoMessage() {} func (*CustomSockopt) ProtoMessage() {}
func (x *CustomSockopt) ProtoReflect() protoreflect.Message { func (x *CustomSockopt) ProtoReflect() protoreflect.Message {
mi := &file_transport_internet_config_proto_msgTypes[4] mi := &file_transport_internet_config_proto_msgTypes[3]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -653,7 +585,7 @@ func (x *CustomSockopt) ProtoReflect() protoreflect.Message {
// Deprecated: Use CustomSockopt.ProtoReflect.Descriptor instead. // Deprecated: Use CustomSockopt.ProtoReflect.Descriptor instead.
func (*CustomSockopt) Descriptor() ([]byte, []int) { func (*CustomSockopt) Descriptor() ([]byte, []int) {
return file_transport_internet_config_proto_rawDescGZIP(), []int{4} return file_transport_internet_config_proto_rawDescGZIP(), []int{3}
} }
func (x *CustomSockopt) GetSystem() string { func (x *CustomSockopt) GetSystem() string {
@@ -733,7 +665,7 @@ type SocketConfig struct {
func (x *SocketConfig) Reset() { func (x *SocketConfig) Reset() {
*x = SocketConfig{} *x = SocketConfig{}
mi := &file_transport_internet_config_proto_msgTypes[5] mi := &file_transport_internet_config_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -745,7 +677,7 @@ func (x *SocketConfig) String() string {
func (*SocketConfig) ProtoMessage() {} func (*SocketConfig) ProtoMessage() {}
func (x *SocketConfig) ProtoReflect() protoreflect.Message { func (x *SocketConfig) ProtoReflect() protoreflect.Message {
mi := &file_transport_internet_config_proto_msgTypes[5] mi := &file_transport_internet_config_proto_msgTypes[4]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -758,7 +690,7 @@ func (x *SocketConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use SocketConfig.ProtoReflect.Descriptor instead. // Deprecated: Use SocketConfig.ProtoReflect.Descriptor instead.
func (*SocketConfig) Descriptor() ([]byte, []int) { func (*SocketConfig) Descriptor() ([]byte, []int) {
return file_transport_internet_config_proto_rawDescGZIP(), []int{5} return file_transport_internet_config_proto_rawDescGZIP(), []int{4}
} }
func (x *SocketConfig) GetMark() int32 { func (x *SocketConfig) GetMark() int32 {
@@ -920,7 +852,7 @@ type HappyEyeballsConfig struct {
func (x *HappyEyeballsConfig) Reset() { func (x *HappyEyeballsConfig) Reset() {
*x = HappyEyeballsConfig{} *x = HappyEyeballsConfig{}
mi := &file_transport_internet_config_proto_msgTypes[6] mi := &file_transport_internet_config_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -932,7 +864,7 @@ func (x *HappyEyeballsConfig) String() string {
func (*HappyEyeballsConfig) ProtoMessage() {} func (*HappyEyeballsConfig) ProtoMessage() {}
func (x *HappyEyeballsConfig) ProtoReflect() protoreflect.Message { func (x *HappyEyeballsConfig) ProtoReflect() protoreflect.Message {
mi := &file_transport_internet_config_proto_msgTypes[6] mi := &file_transport_internet_config_proto_msgTypes[5]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -945,7 +877,7 @@ func (x *HappyEyeballsConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use HappyEyeballsConfig.ProtoReflect.Descriptor instead. // Deprecated: Use HappyEyeballsConfig.ProtoReflect.Descriptor instead.
func (*HappyEyeballsConfig) Descriptor() ([]byte, []int) { func (*HappyEyeballsConfig) Descriptor() ([]byte, []int) {
return file_transport_internet_config_proto_rawDescGZIP(), []int{6} return file_transport_internet_config_proto_rawDescGZIP(), []int{5}
} }
func (x *HappyEyeballsConfig) GetPrioritizeIpv6() bool { func (x *HappyEyeballsConfig) GetPrioritizeIpv6() bool {
@@ -996,11 +928,7 @@ const file_transport_internet_config_proto_rawDesc = "" +
"\btcpmasks\x18\v \x03(\v2 .xray.common.serial.TypedMessageR\btcpmasks\x12D\n" + "\btcpmasks\x18\v \x03(\v2 .xray.common.serial.TypedMessageR\btcpmasks\x12D\n" +
"\vquic_params\x18\f \x01(\v2#.xray.transport.internet.QuicParamsR\n" + "\vquic_params\x18\f \x01(\v2#.xray.transport.internet.QuicParamsR\n" +
"quicParams\x12N\n" + "quicParams\x12N\n" +
"\x0fsocket_settings\x18\x06 \x01(\v2%.xray.transport.internet.SocketConfigR\x0esocketSettings\"d\n" + "\x0fsocket_settings\x18\x06 \x01(\v2%.xray.transport.internet.SocketConfigR\x0esocketSettings\"\x8d\x06\n" +
"\x06UdpHop\x12\x14\n" +
"\x05ports\x18\x01 \x03(\rR\x05ports\x12!\n" +
"\finterval_min\x18\x02 \x01(\x03R\vintervalMin\x12!\n" +
"\finterval_max\x18\x03 \x01(\x03R\vintervalMax\"\xc7\x06\n" +
"\n" + "\n" +
"QuicParams\x12\x1e\n" + "QuicParams\x12\x1e\n" +
"\n" + "\n" +
@@ -1011,22 +939,21 @@ const file_transport_internet_config_proto_rawDesc = "" +
"\tbrutal_up\x18\x03 \x01(\x04R\bbrutalUp\x12\x1f\n" + "\tbrutal_up\x18\x03 \x01(\x04R\bbrutalUp\x12\x1f\n" +
"\vbrutal_down\x18\x04 \x01(\x04R\n" + "\vbrutal_down\x18\x04 \x01(\x04R\n" +
"brutalDown\x12G\n" + "brutalDown\x12G\n" +
" brutal_disable_loss_compensation\x18\x05 \x01(\bR\x1dbrutalDisableLossCompensation\x128\n" + " brutal_disable_loss_compensation\x18\x05 \x01(\bR\x1dbrutalDisableLossCompensation\x12;\n" +
"\audp_hop\x18\x06 \x01(\v2\x1f.xray.transport.internet.UdpHopR\x06udpHop\x12;\n" + "\x1ainit_stream_receive_window\x18\x06 \x01(\x04R\x17initStreamReceiveWindow\x129\n" +
"\x1ainit_stream_receive_window\x18\a \x01(\x04R\x17initStreamReceiveWindow\x129\n" + "\x19max_stream_receive_window\x18\a \x01(\x04R\x16maxStreamReceiveWindow\x127\n" +
"\x19max_stream_receive_window\x18\b \x01(\x04R\x16maxStreamReceiveWindow\x127\n" + "\x18init_conn_receive_window\x18\b \x01(\x04R\x15initConnReceiveWindow\x125\n" +
"\x18init_conn_receive_window\x18\t \x01(\x04R\x15initConnReceiveWindow\x125\n" + "\x17max_conn_receive_window\x18\t \x01(\x04R\x14maxConnReceiveWindow\x12(\n" +
"\x17max_conn_receive_window\x18\n" + "\x10max_idle_timeout\x18\n" +
" \x01(\x04R\x14maxConnReceiveWindow\x12(\n" + " \x01(\x03R\x0emaxIdleTimeout\x12*\n" +
"\x10max_idle_timeout\x18\v \x01(\x03R\x0emaxIdleTimeout\x12*\n" + "\x11keep_alive_period\x18\v \x01(\x03R\x0fkeepAlivePeriod\x12;\n" +
"\x11keep_alive_period\x18\f \x01(\x03R\x0fkeepAlivePeriod\x12;\n" + "\x1adisable_path_mtu_discovery\x18\f \x01(\bR\x17disablePathMtuDiscovery\x122\n" +
"\x1adisable_path_mtu_discovery\x18\r \x01(\bR\x17disablePathMtuDiscovery\x122\n" + "\x15disable_chrome_parrot\x18\r \x01(\bR\x13disableChromeParrot\x12\x1e\n" +
"\x15disable_chrome_parrot\x18\x0e \x01(\bR\x13disableChromeParrot\x12\x1e\n" +
"\n" + "\n" +
"disableGSO\x18\x0f \x01(\bR\n" + "disableGSO\x18\x0e \x01(\bR\n" +
"disableGSO\x120\n" + "disableGSO\x120\n" +
"\x14max_incoming_streams\x18\x10 \x01(\x03R\x12maxIncomingStreams\x126\n" + "\x14max_incoming_streams\x18\x0f \x01(\x03R\x12maxIncomingStreams\x126\n" +
"\x17disable_stateless_reset\x18\x11 \x01(\bR\x15disableStatelessReset\"\x93\x01\n" + "\x17disable_stateless_reset\x18\x10 \x01(\bR\x15disableStatelessReset\"\x93\x01\n" +
"\rCustomSockopt\x12\x16\n" + "\rCustomSockopt\x12\x16\n" +
"\x06system\x18\x01 \x01(\tR\x06system\x12\x18\n" + "\x06system\x18\x01 \x01(\tR\x06system\x12\x18\n" +
"\anetwork\x18\x02 \x01(\tR\anetwork\x12\x14\n" + "\anetwork\x18\x02 \x01(\tR\anetwork\x12\x14\n" +
@@ -1110,41 +1037,39 @@ func file_transport_internet_config_proto_rawDescGZIP() []byte {
} }
var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_transport_internet_config_proto_goTypes = []any{ var file_transport_internet_config_proto_goTypes = []any{
(DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy (DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy
(AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy (AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy
(SocketConfig_TProxyMode)(0), // 2: xray.transport.internet.SocketConfig.TProxyMode (SocketConfig_TProxyMode)(0), // 2: xray.transport.internet.SocketConfig.TProxyMode
(*TransportConfig)(nil), // 3: xray.transport.internet.TransportConfig (*TransportConfig)(nil), // 3: xray.transport.internet.TransportConfig
(*StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig (*StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig
(*UdpHop)(nil), // 5: xray.transport.internet.UdpHop (*QuicParams)(nil), // 5: xray.transport.internet.QuicParams
(*QuicParams)(nil), // 6: xray.transport.internet.QuicParams (*CustomSockopt)(nil), // 6: xray.transport.internet.CustomSockopt
(*CustomSockopt)(nil), // 7: xray.transport.internet.CustomSockopt (*SocketConfig)(nil), // 7: xray.transport.internet.SocketConfig
(*SocketConfig)(nil), // 8: xray.transport.internet.SocketConfig (*HappyEyeballsConfig)(nil), // 8: xray.transport.internet.HappyEyeballsConfig
(*HappyEyeballsConfig)(nil), // 9: xray.transport.internet.HappyEyeballsConfig (*serial.TypedMessage)(nil), // 9: xray.common.serial.TypedMessage
(*serial.TypedMessage)(nil), // 10: xray.common.serial.TypedMessage (*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
(*net.IPOrDomain)(nil), // 11: xray.common.net.IPOrDomain
} }
var file_transport_internet_config_proto_depIdxs = []int32{ var file_transport_internet_config_proto_depIdxs = []int32{
10, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage 9, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
11, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain 10, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig 3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig
10, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage 9, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
10, // 4: xray.transport.internet.StreamConfig.udpmasks:type_name -> xray.common.serial.TypedMessage 9, // 4: xray.transport.internet.StreamConfig.udpmasks:type_name -> xray.common.serial.TypedMessage
10, // 5: xray.transport.internet.StreamConfig.tcpmasks:type_name -> xray.common.serial.TypedMessage 9, // 5: xray.transport.internet.StreamConfig.tcpmasks:type_name -> xray.common.serial.TypedMessage
6, // 6: xray.transport.internet.StreamConfig.quic_params:type_name -> xray.transport.internet.QuicParams 5, // 6: xray.transport.internet.StreamConfig.quic_params:type_name -> xray.transport.internet.QuicParams
8, // 7: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig 7, // 7: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
5, // 8: xray.transport.internet.QuicParams.udp_hop:type_name -> xray.transport.internet.UdpHop 2, // 8: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
2, // 9: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode 0, // 9: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
0, // 10: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy 6, // 10: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
7, // 11: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt 1, // 11: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy
1, // 12: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy 8, // 12: xray.transport.internet.SocketConfig.happy_eyeballs:type_name -> xray.transport.internet.HappyEyeballsConfig
9, // 13: xray.transport.internet.SocketConfig.happy_eyeballs:type_name -> xray.transport.internet.HappyEyeballsConfig 13, // [13:13] is the sub-list for method output_type
14, // [14:14] is the sub-list for method output_type 13, // [13:13] is the sub-list for method input_type
14, // [14:14] is the sub-list for method input_type 13, // [13:13] is the sub-list for extension type_name
14, // [14:14] is the sub-list for extension type_name 13, // [13:13] is the sub-list for extension extendee
14, // [14:14] is the sub-list for extension extendee 0, // [0:13] is the sub-list for field type_name
0, // [0:14] is the sub-list for field type_name
} }
func init() { file_transport_internet_config_proto_init() } func init() { file_transport_internet_config_proto_init() }
@@ -1158,7 +1083,7 @@ func file_transport_internet_config_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_internet_config_proto_rawDesc), len(file_transport_internet_config_proto_rawDesc)), RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_internet_config_proto_rawDesc), len(file_transport_internet_config_proto_rawDesc)),
NumEnums: 3, NumEnums: 3,
NumMessages: 7, NumMessages: 6,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },
+11 -18
View File
@@ -64,30 +64,23 @@ message StreamConfig {
SocketConfig socket_settings = 6; SocketConfig socket_settings = 6;
} }
message UdpHop {
repeated uint32 ports = 1;
int64 interval_min = 2;
int64 interval_max = 3;
}
message QuicParams { message QuicParams {
string congestion = 1; string congestion = 1;
string bbr_profile = 2; string bbr_profile = 2;
uint64 brutal_up = 3; uint64 brutal_up = 3;
uint64 brutal_down = 4; uint64 brutal_down = 4;
bool brutal_disable_loss_compensation = 5; bool brutal_disable_loss_compensation = 5;
UdpHop udp_hop = 6; uint64 init_stream_receive_window = 6;
uint64 init_stream_receive_window = 7; uint64 max_stream_receive_window = 7;
uint64 max_stream_receive_window = 8; uint64 init_conn_receive_window = 8;
uint64 init_conn_receive_window = 9; uint64 max_conn_receive_window = 9;
uint64 max_conn_receive_window = 10; int64 max_idle_timeout = 10;
int64 max_idle_timeout = 11; int64 keep_alive_period = 11;
int64 keep_alive_period = 12; bool disable_path_mtu_discovery = 12;
bool disable_path_mtu_discovery = 13; bool disable_chrome_parrot = 13;
bool disable_chrome_parrot = 14; bool disableGSO = 14;
bool disableGSO = 15; int64 max_incoming_streams = 15;
int64 max_incoming_streams = 16; bool disable_stateless_reset = 16;
bool disable_stateless_reset = 17;
} }
message CustomSockopt { message CustomSockopt {
+6 -6
View File
@@ -38,7 +38,7 @@ var transportDialerCache = make(map[string]dialFunc)
// RegisterTransportDialer registers a Dialer with given name. // RegisterTransportDialer registers a Dialer with given name.
func RegisterTransportDialer(protocol string, dialer dialFunc) error { func RegisterTransportDialer(protocol string, dialer dialFunc) error {
if _, found := transportDialerCache[protocol]; found { if _, found := transportDialerCache[protocol]; found {
return errors.New(protocol, " dialer already registered").AtError() return errors.New(protocol, " dialer already registered")
} }
transportDialerCache[protocol] = dialer transportDialerCache[protocol] = dialer
return nil return nil
@@ -58,7 +58,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *MemoryStrea
protocol := streamSettings.ProtocolName protocol := streamSettings.ProtocolName
dialer := transportDialerCache[protocol] dialer := transportDialerCache[protocol]
if dialer == nil { if dialer == nil {
return nil, errors.New(protocol, " dialer not registered").AtError() return nil, errors.New(protocol, " dialer not registered")
} }
return dialer(ctx, dest, streamSettings) return dialer(ctx, dest, streamSettings)
} }
@@ -66,7 +66,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *MemoryStrea
if dest.Network == net.Network_UDP { if dest.Network == net.Network_UDP {
udpDialer := transportDialerCache["udp"] udpDialer := transportDialerCache["udp"]
if udpDialer == nil { if udpDialer == nil {
return nil, errors.New("UDP dialer not registered").AtError() return nil, errors.New("UDP dialer not registered")
} }
return udpDialer(ctx, dest, streamSettings) return udpDialer(ctx, dest, streamSettings)
} }
@@ -86,7 +86,7 @@ var (
func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]net.IP, error) { func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]net.IP, error) {
if dnsClient == nil { if dnsClient == nil {
return nil, errors.New("DNS client not initialized").AtError() return nil, errors.New("DNS client not initialized")
} }
ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{ ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{
@@ -269,11 +269,11 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
if len(sockopt.DialerProxy) > 0 { if len(sockopt.DialerProxy) > 0 {
if obm == nil { if obm == nil {
return nil, errors.New("there is no outbound manager for dialerProxy").AtError() return nil, errors.New("there is no outbound manager for dialerProxy")
} }
h := obm.GetHandler(sockopt.DialerProxy) h := obm.GetHandler(sockopt.DialerProxy)
if h == nil { if h == nil {
return nil, errors.New("there is no outbound handler for dialerProxy").AtError() return nil, errors.New("there is no outbound handler for dialerProxy")
} }
return redirect(ctx, dest, sockopt.DialerProxy, h), nil return redirect(ctx, dest, sockopt.DialerProxy, h), nil
} }
+8 -14
View File
@@ -10,8 +10,6 @@ import (
) )
type Udpmask interface { type Udpmask interface {
UDP()
WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error)
WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error)
} }
@@ -21,15 +19,14 @@ type UdpmaskManager struct {
} }
func NewUdpmaskManager(udpmasks []Udpmask) *UdpmaskManager { func NewUdpmaskManager(udpmasks []Udpmask) *UdpmaskManager {
return &UdpmaskManager{ slices.Reverse(udpmasks)
udpmasks: udpmasks, return &UdpmaskManager{udpmasks: udpmasks}
}
} }
func (m *UdpmaskManager) WrapPacketConnClient(raw net.PacketConn) (net.PacketConn, error) { func (m *UdpmaskManager) WrapPacketConnClient(raw net.PacketConn) (net.PacketConn, error) {
var sizes []int var sizes []int
var conns []net.PacketConn var conns []net.PacketConn
for i, mask := range slices.Backward(m.udpmasks) { for i, mask := range m.udpmasks {
if _, ok := mask.(headerConn); ok { if _, ok := mask.(headerConn); ok {
conn, err := mask.WrapPacketConnClient(nil, i, len(m.udpmasks)-1) conn, err := mask.WrapPacketConnClient(nil, i, len(m.udpmasks)-1)
if err != nil { if err != nil {
@@ -62,7 +59,7 @@ func (m *UdpmaskManager) WrapPacketConnClient(raw net.PacketConn) (net.PacketCon
func (m *UdpmaskManager) WrapPacketConnServer(raw net.PacketConn) (net.PacketConn, error) { func (m *UdpmaskManager) WrapPacketConnServer(raw net.PacketConn) (net.PacketConn, error) {
var sizes []int var sizes []int
var conns []net.PacketConn var conns []net.PacketConn
for i, mask := range slices.Backward(m.udpmasks) { for i, mask := range m.udpmasks {
if _, ok := mask.(headerConn); ok { if _, ok := mask.(headerConn); ok {
conn, err := mask.WrapPacketConnServer(nil, i, len(m.udpmasks)-1) conn, err := mask.WrapPacketConnServer(nil, i, len(m.udpmasks)-1)
if err != nil { if err != nil {
@@ -195,8 +192,6 @@ func (c *headerManagerConn) WriteTo(p []byte, addr net.Addr) (n int, err error)
} }
type Tcpmask interface { type Tcpmask interface {
TCP()
WrapConnClient(net.Conn) (net.Conn, error) WrapConnClient(net.Conn) (net.Conn, error)
WrapConnServer(net.Conn) (net.Conn, error) WrapConnServer(net.Conn) (net.Conn, error)
} }
@@ -206,14 +201,13 @@ type TcpmaskManager struct {
} }
func NewTcpmaskManager(tcpmasks []Tcpmask) *TcpmaskManager { func NewTcpmaskManager(tcpmasks []Tcpmask) *TcpmaskManager {
return &TcpmaskManager{ slices.Reverse(tcpmasks)
tcpmasks: tcpmasks, return &TcpmaskManager{tcpmasks: tcpmasks}
}
} }
func (m *TcpmaskManager) WrapConnClient(raw net.Conn) (net.Conn, error) { func (m *TcpmaskManager) WrapConnClient(raw net.Conn) (net.Conn, error) {
var err error var err error
for _, mask := range slices.Backward(m.tcpmasks) { for _, mask := range m.tcpmasks {
raw, err = mask.WrapConnClient(raw) raw, err = mask.WrapConnClient(raw)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -224,7 +218,7 @@ func (m *TcpmaskManager) WrapConnClient(raw net.Conn) (net.Conn, error) {
func (m *TcpmaskManager) WrapConnServer(raw net.Conn) (net.Conn, error) { func (m *TcpmaskManager) WrapConnServer(raw net.Conn) (net.Conn, error) {
var err error var err error
for _, mask := range slices.Backward(m.tcpmasks) { for _, mask := range m.tcpmasks {
raw, err = mask.WrapConnServer(raw) raw, err = mask.WrapConnServer(raw)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -2,9 +2,6 @@ package fragment
import "net" import "net"
func (c *Config) TCP() {
}
func (c *Config) WrapConnClient(raw net.Conn) (net.Conn, error) { func (c *Config) WrapConnClient(raw net.Conn) (net.Conn, error) {
return NewConnClient(c, raw, false) return NewConnClient(c, raw, false)
} }
@@ -4,8 +4,6 @@ import (
"net" "net"
) )
func (c *TCPConfig) TCP() {}
func (c *TCPConfig) WrapConnClient(raw net.Conn) (net.Conn, error) { func (c *TCPConfig) WrapConnClient(raw net.Conn) (net.Conn, error) {
return NewConnClientTCP(c, raw) return NewConnClientTCP(c, raw)
} }
@@ -14,8 +12,6 @@ func (c *TCPConfig) WrapConnServer(raw net.Conn) (net.Conn, error) {
return NewConnServerTCP(c, raw) return NewConnServerTCP(c, raw)
} }
func (c *UDPConfig) UDP() {}
func (c *UDPConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *UDPConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnClientUDP(c, raw) return NewConnClientUDP(c, raw)
} }
@@ -24,8 +20,6 @@ func (c *UDPConfig) WrapPacketConnServer(raw net.PacketConn, level int, levelCou
return NewConnServerUDP(c, raw) return NewConnServerUDP(c, raw)
} }
func (c *UDPStandaloneConfig) UDP() {}
func (c *UDPStandaloneConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *UDPStandaloneConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnClientUDPStandalone(c, raw) return NewConnClientUDPStandalone(c, raw)
} }
@@ -4,8 +4,6 @@ import (
"net" "net"
) )
func (c *Config) UDP() {}
func (c *Config) HeaderConn() {} func (c *Config) HeaderConn() {}
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
@@ -4,8 +4,6 @@ import (
"net" "net"
) )
func (c *Config) UDP() {}
func (c *Config) HeaderConn() {} func (c *Config) HeaderConn() {}
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
@@ -4,8 +4,6 @@ import (
"net" "net"
) )
func (c *Config) UDP() {}
func (c *Config) HeaderConn() {} func (c *Config) HeaderConn() {}
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
@@ -2,9 +2,6 @@ package noise
import "net" import "net"
func (c *Config) UDP() {
}
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewConnClient(c, raw) return NewConnClient(c, raw)
} }
+1 -5
View File
@@ -5,15 +5,11 @@ import (
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
) )
func (c *Config) UDP() {}
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
_, ok1 := raw.(*internet.FakePacketConn) _, ok1 := raw.(*internet.FakePacketConn)
_, ok2 := raw.(*udphop.UdpHopPacketConn) if level != 0 || ok1 {
if level != 0 || ok1 || ok2 {
return nil, errors.New("realm requires being at the outermost level") return nil, errors.New("realm requires being at the outermost level")
} }
return NewConnClient(c, raw) return NewConnClient(c, raw)
@@ -4,8 +4,6 @@ import (
"net" "net"
) )
func (c *Config) UDP() {}
func (c *Config) HeaderConn() {} func (c *Config) HeaderConn() {}
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
@@ -16,8 +14,6 @@ func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount
return NewSalamanderConnServer(c, raw) return NewSalamanderConnServer(c, raw)
} }
func (c *GeckoConfig) UDP() {}
func (c *GeckoConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *GeckoConfig) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return NewGeckoConnClient(c, raw) return NewGeckoConnClient(c, raw)
} }
@@ -6,12 +6,6 @@ import (
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
) )
func (c *Config) TCP() {
}
func (c *Config) UDP() {
}
// Sudoku in finalmask mode is a pure appearance transform with no standalone handshake. // Sudoku in finalmask mode is a pure appearance transform with no standalone handshake.
// TCP always keeps classic sudoku on uplink and uses packed downlink optimization on server writes. // TCP always keeps classic sudoku on uplink and uses packed downlink optimization on server writes.
func (c *Config) WrapConnClient(raw net.Conn) (net.Conn, error) { func (c *Config) WrapConnClient(raw net.Conn) (net.Conn, error) {
@@ -0,0 +1,20 @@
package udphop
import (
"net"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet"
)
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
_, ok1 := raw.(*internet.FakePacketConn)
if level != 0 || ok1 {
return nil, errors.New("udphop requires being at the outermost level")
}
return NewUDPHopConn(c, raw)
}
func (c *Config) WrapPacketConnServer(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
return nil, errors.New("udphop: client only")
}
@@ -0,0 +1,190 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.5
// source: transport/internet/finalmask/udphop/config.proto
package udphop
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"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Config struct {
state protoimpl.MessageState `protogen:"open.v1"`
Sockopt *internet.SocketConfig `protobuf:"bytes,1,opt,name=sockopt,proto3" json:"sockopt,omitempty"`
Local bool `protobuf:"varint,2,opt,name=local,proto3" json:"local,omitempty"`
Remote bool `protobuf:"varint,3,opt,name=remote,proto3" json:"remote,omitempty"`
RemoteOnce bool `protobuf:"varint,4,opt,name=remote_once,json=remoteOnce,proto3" json:"remote_once,omitempty"`
IntervalMin int64 `protobuf:"varint,5,opt,name=interval_min,json=intervalMin,proto3" json:"interval_min,omitempty"`
IntervalMax int64 `protobuf:"varint,6,opt,name=interval_max,json=intervalMax,proto3" json:"interval_max,omitempty"`
RemotePorts []uint32 `protobuf:"varint,7,rep,packed,name=remote_ports,json=remotePorts,proto3" json:"remote_ports,omitempty"`
RemoteIPs []string `protobuf:"bytes,8,rep,name=remoteIPs,proto3" json:"remoteIPs,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Config) Reset() {
*x = Config{}
mi := &file_transport_internet_finalmask_udphop_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_internet_finalmask_udphop_config_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) {
return file_transport_internet_finalmask_udphop_config_proto_rawDescGZIP(), []int{0}
}
func (x *Config) GetSockopt() *internet.SocketConfig {
if x != nil {
return x.Sockopt
}
return nil
}
func (x *Config) GetLocal() bool {
if x != nil {
return x.Local
}
return false
}
func (x *Config) GetRemote() bool {
if x != nil {
return x.Remote
}
return false
}
func (x *Config) GetRemoteOnce() bool {
if x != nil {
return x.RemoteOnce
}
return false
}
func (x *Config) GetIntervalMin() int64 {
if x != nil {
return x.IntervalMin
}
return 0
}
func (x *Config) GetIntervalMax() int64 {
if x != nil {
return x.IntervalMax
}
return 0
}
func (x *Config) GetRemotePorts() []uint32 {
if x != nil {
return x.RemotePorts
}
return nil
}
func (x *Config) GetRemoteIPs() []string {
if x != nil {
return x.RemoteIPs
}
return nil
}
var File_transport_internet_finalmask_udphop_config_proto protoreflect.FileDescriptor
const file_transport_internet_finalmask_udphop_config_proto_rawDesc = "" +
"\n" +
"0transport/internet/finalmask/udphop/config.proto\x12(xray.transport.internet.finalmask.udphop\x1a\x1ftransport/internet/config.proto\"\x9f\x02\n" +
"\x06Config\x12?\n" +
"\asockopt\x18\x01 \x01(\v2%.xray.transport.internet.SocketConfigR\asockopt\x12\x14\n" +
"\x05local\x18\x02 \x01(\bR\x05local\x12\x16\n" +
"\x06remote\x18\x03 \x01(\bR\x06remote\x12\x1f\n" +
"\vremote_once\x18\x04 \x01(\bR\n" +
"remoteOnce\x12!\n" +
"\finterval_min\x18\x05 \x01(\x03R\vintervalMin\x12!\n" +
"\finterval_max\x18\x06 \x01(\x03R\vintervalMax\x12!\n" +
"\fremote_ports\x18\a \x03(\rR\vremotePorts\x12\x1c\n" +
"\tremoteIPs\x18\b \x03(\tR\tremoteIPsB\x9a\x01\n" +
",com.xray.transport.internet.finalmask.udphopP\x01Z=github.com/xtls/xray-core/transport/internet/finalmask/udphop\xaa\x02(Xray.Transport.Internet.Finalmask.Udphopb\x06proto3"
var (
file_transport_internet_finalmask_udphop_config_proto_rawDescOnce sync.Once
file_transport_internet_finalmask_udphop_config_proto_rawDescData []byte
)
func file_transport_internet_finalmask_udphop_config_proto_rawDescGZIP() []byte {
file_transport_internet_finalmask_udphop_config_proto_rawDescOnce.Do(func() {
file_transport_internet_finalmask_udphop_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_transport_internet_finalmask_udphop_config_proto_rawDesc), len(file_transport_internet_finalmask_udphop_config_proto_rawDesc)))
})
return file_transport_internet_finalmask_udphop_config_proto_rawDescData
}
var file_transport_internet_finalmask_udphop_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_transport_internet_finalmask_udphop_config_proto_goTypes = []any{
(*Config)(nil), // 0: xray.transport.internet.finalmask.udphop.Config
(*internet.SocketConfig)(nil), // 1: xray.transport.internet.SocketConfig
}
var file_transport_internet_finalmask_udphop_config_proto_depIdxs = []int32{
1, // 0: xray.transport.internet.finalmask.udphop.Config.sockopt:type_name -> xray.transport.internet.SocketConfig
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_internet_finalmask_udphop_config_proto_init() }
func file_transport_internet_finalmask_udphop_config_proto_init() {
if File_transport_internet_finalmask_udphop_config_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_transport_internet_finalmask_udphop_config_proto_rawDesc), len(file_transport_internet_finalmask_udphop_config_proto_rawDesc)),
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_transport_internet_finalmask_udphop_config_proto_goTypes,
DependencyIndexes: file_transport_internet_finalmask_udphop_config_proto_depIdxs,
MessageInfos: file_transport_internet_finalmask_udphop_config_proto_msgTypes,
}.Build()
File_transport_internet_finalmask_udphop_config_proto = out.File
file_transport_internet_finalmask_udphop_config_proto_goTypes = nil
file_transport_internet_finalmask_udphop_config_proto_depIdxs = nil
}
@@ -0,0 +1,21 @@
syntax = "proto3";
package xray.transport.internet.finalmask.udphop;
option csharp_namespace = "Xray.Transport.Internet.Finalmask.Udphop";
option go_package = "github.com/xtls/xray-core/transport/internet/finalmask/udphop";
option java_package = "com.xray.transport.internet.finalmask.udphop";
option java_multiple_files = true;
import "transport/internet/config.proto";
message Config {
xray.transport.internet.SocketConfig sockopt = 1;
bool local = 2;
bool remote = 3;
bool remote_once = 4;
int64 interval_min = 5;
int64 interval_max = 6;
repeated uint32 remote_ports = 7;
repeated string remoteIPs = 8;
}
+305
View File
@@ -0,0 +1,305 @@
package udphop
import (
"context"
"crypto/rand"
goerrors "errors"
"io"
mrand "math/rand"
gonet "net"
"net/netip"
"reflect"
"sync"
"time"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/net/cnc"
"github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
var pool = sync.Pool{
New: func() any {
return make([]byte, finalmask.UDPSize)
},
}
type packet struct {
p []byte
addr net.Addr
err error
}
type udpHopConn struct {
conn net.PacketConn
sockopt *internet.SocketConfig
local bool
remote bool
remoteOnce bool
intervalMin int64
intervalMax int64
remotePorts []uint32
remoteIPs []netip.Prefix
deadline time.Time
readDeadline time.Time
writeDeadline time.Time
pre net.PacketConn
cur net.PacketConn
addr *net.UDPAddr
readCh chan packet
closeCh chan struct{}
wg sync.WaitGroup
mu sync.Mutex
}
func NewUDPHopConn(c *Config, raw net.PacketConn) (net.PacketConn, error) {
if c.IntervalMin < 5 || c.IntervalMax < 5 {
return nil, errors.New("invalid interval")
}
remoteIPs := make([]netip.Prefix, 0, len(c.RemoteIPs))
for _, ip := range c.RemoteIPs {
remoteIPs = append(remoteIPs, netip.MustParsePrefix(ip))
}
conn := &udpHopConn{
conn: raw,
sockopt: c.Sockopt,
local: c.Local,
remote: c.Remote,
remoteOnce: c.RemoteOnce,
intervalMin: c.IntervalMin,
intervalMax: c.IntervalMax,
remotePorts: c.RemotePorts,
remoteIPs: remoteIPs,
readCh: make(chan packet),
closeCh: make(chan struct{}),
}
return conn, nil
}
func (c *udpHopConn) closed() bool {
select {
case <-c.closeCh:
return true
default:
return false
}
}
func (c *udpHopConn) hop(addr *net.UDPAddr) {
if c.closed() {
return
}
newAddr := &net.UDPAddr{IP: addr.IP, Port: addr.Port}
newConn := c.conn
if c.remote || c.remoteOnce && c.addr == nil {
if len(c.remotePorts) > 0 {
newAddr.Port = int(c.remotePorts[mrand.Intn(len(c.remotePorts))])
}
if len(c.remoteIPs) > 0 {
newAddr.IP = randPrefix(c.remoteIPs[mrand.Intn(len(c.remoteIPs))])
}
}
if c.local {
raw, err := internet.DialSystem(context.Background(), net.UDPDestination(net.IPAddress(newAddr.IP), net.Port(newAddr.Port)), c.sockopt)
if err != nil {
errors.LogErrorInner(context.Background(), err, "hop err")
return
}
switch c := raw.(type) {
case *internet.PacketConnWrapper:
newConn = c.PacketConn
case *cnc.Connection:
newConn = &internet.FakePacketConn{Conn: c}
default:
panic(reflect.TypeOf(c))
}
newConn.SetDeadline(c.deadline)
newConn.SetReadDeadline(c.readDeadline)
newConn.SetWriteDeadline(c.writeDeadline)
if c.pre != nil {
_ = c.pre.Close()
}
c.pre = c.cur
c.wg.Add(1)
go c.recv(newConn)
}
c.addr = newAddr
c.cur = newConn
}
func (c *udpHopConn) recv(conn net.PacketConn) {
defer c.wg.Done()
for {
if c.closed() {
return
}
p := pool.Get().([]byte)
n, addr, err := conn.ReadFrom(p)
if err != nil {
pool.Put(p[:cap(p)])
if goerrors.Is(err, io.EOF) || goerrors.Is(err, io.ErrClosedPipe) || goerrors.Is(err, gonet.ErrClosed) {
break
}
var netErr net.Error
if goerrors.As(err, &netErr) && netErr.Timeout() {
select {
case c.readCh <- packet{err: err}:
case <-c.closeCh:
return
}
}
errors.LogErrorInner(context.Background(), err, "recv err")
continue
}
select {
case c.readCh <- packet{p: p[:n], addr: addr}:
case <-c.closeCh:
pool.Put(p[:cap(p)])
return
}
}
}
func (c *udpHopConn) hopLoop() {
ticker := time.NewTicker(time.Second * time.Duration(crypto.RandBetween(c.intervalMin, c.intervalMax+1)))
defer ticker.Stop()
for {
select {
case <-ticker.C:
ticker.Reset(time.Second * time.Duration(crypto.RandBetween(c.intervalMin, c.intervalMax+1)))
c.mu.Lock()
c.hop(c.addr)
c.mu.Unlock()
case <-c.closeCh:
return
}
}
}
func (c *udpHopConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
packet, ok := <-c.readCh
if ok {
if packet.p != nil {
n = copy(p, packet.p)
pool.Put(packet.p[:cap(packet.p)])
}
return n, packet.addr, packet.err
}
return 0, nil, io.EOF
}
func (c *udpHopConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
c.mu.Lock()
defer c.mu.Unlock()
if c.cur == nil {
c.hop(addr.(*net.UDPAddr))
if c.cur == nil {
return 0, nil
}
go c.hopLoop()
}
_, err = c.cur.WriteTo(p, c.addr)
if err != nil {
errors.LogErrorInner(context.Background(), err, "send err")
return 0, err
}
return len(p), nil
}
func (c *udpHopConn) Close() error {
c.mu.Lock()
defer c.mu.Unlock()
if c.closed() {
return nil
}
close(c.closeCh)
if c.pre != nil {
_ = c.pre.Close()
}
if c.cur != nil {
_ = c.cur.Close()
}
_ = c.conn.Close()
c.wg.Wait()
select {
case p := <-c.readCh:
if p.p != nil {
pool.Put(p.p[:cap(p.p)])
}
default:
}
close(c.readCh)
return nil
}
func (c *udpHopConn) LocalAddr() net.Addr {
return c.conn.LocalAddr()
}
func (c *udpHopConn) SetDeadline(t time.Time) error {
c.mu.Lock()
defer c.mu.Unlock()
c.deadline = t
if c.pre != nil {
_ = c.pre.SetDeadline(t)
}
if c.cur != nil {
_ = c.cur.SetDeadline(t)
}
return nil
}
func (c *udpHopConn) SetReadDeadline(t time.Time) error {
c.mu.Lock()
defer c.mu.Unlock()
c.readDeadline = t
if c.pre != nil {
_ = c.pre.SetReadDeadline(t)
}
if c.cur != nil {
_ = c.cur.SetReadDeadline(t)
}
return nil
}
func (c *udpHopConn) SetWriteDeadline(t time.Time) error {
c.mu.Lock()
defer c.mu.Unlock()
c.writeDeadline = t
if c.pre != nil {
_ = c.pre.SetWriteDeadline(t)
}
if c.cur != nil {
_ = c.cur.SetWriteDeadline(t)
}
return nil
}
func randPrefix(p netip.Prefix) []byte {
if p.IsSingleIP() {
return p.Addr().AsSlice()
}
b := p.Addr().AsSlice()
prefix := p.Bits()
var new [16]byte
common.Must2(rand.Read(new[:len(b)]))
i := prefix / 8
j := prefix % 8
if i+1 < len(b) {
copy(b[i+1:], new[i+1:])
}
mask := byte(0xff << (8 - j))
b[i] = (b[i] & mask) | (new[i] &^ mask)
return b
}
@@ -4,9 +4,6 @@ import (
"net" "net"
) )
func (c *Config) UDP() {
}
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
// _, ok1 := raw.(*internet.FakePacketConn) // _, ok1 := raw.(*internet.FakePacketConn)
// _, ok2 := raw.(*udphop.UdpHopPacketConn) // _, ok2 := raw.(*udphop.UdpHopPacketConn)
+30 -17
View File
@@ -45,7 +45,8 @@ type xicmpConnClient struct {
id int id int
seq int seq int
readCh chan packet readCh chan packet
closedCh chan struct{} closeCh chan struct{}
wg sync.WaitGroup
mu sync.Mutex mu sync.Mutex
} }
@@ -81,9 +82,10 @@ func NewConnClient(c *Config, raw net.PacketConn) (net.PacketConn, error) {
id: mathrand.Intn(65536), id: mathrand.Intn(65536),
seq: 1, seq: 1,
readCh: make(chan packet), readCh: make(chan packet),
closedCh: make(chan struct{}), closeCh: make(chan struct{}),
} }
conn.wg.Add(2)
go conn.recv4() go conn.recv4()
go conn.recv6() go conn.recv6()
@@ -96,7 +98,7 @@ func (c *xicmpConnClient) ring(a, b uint16) uint16 {
func (c *xicmpConnClient) closed() bool { func (c *xicmpConnClient) closed() bool {
select { select {
case <-c.closedCh: case <-c.closeCh:
return true return true
default: default:
return false return false
@@ -104,8 +106,9 @@ func (c *xicmpConnClient) closed() bool {
} }
func (c *xicmpConnClient) recv4() { func (c *xicmpConnClient) recv4() {
var b [finalmask.UDPSize]byte defer c.wg.Done()
var b [finalmask.UDPSize]byte
for { for {
if c.closed() { if c.closed() {
return return
@@ -119,10 +122,11 @@ func (c *xicmpConnClient) recv4() {
case c.readCh <- packet{ case c.readCh <- packet{
err: err, err: err,
}: }:
case <-c.closedCh: case <-c.closeCh:
return return
} }
} }
errors.LogErrorInner(context.Background(), err, "recv4 err")
continue continue
} }
@@ -166,7 +170,7 @@ func (c *xicmpConnClient) recv4() {
p: p, p: p,
addr: addr, addr: addr,
}: }:
case <-c.closedCh: case <-c.closeCh:
pool.Put(p) pool.Put(p)
return return
} }
@@ -174,11 +178,12 @@ func (c *xicmpConnClient) recv4() {
} }
func (c *xicmpConnClient) recv6() { func (c *xicmpConnClient) recv6() {
var b [finalmask.UDPSize]byte defer c.wg.Done()
var b [finalmask.UDPSize]byte
for { for {
if c.closed() { if c.closed() {
break return
} }
n, addr, err := c.icmp6.ReadFrom(b[:]) n, addr, err := c.icmp6.ReadFrom(b[:])
@@ -189,10 +194,11 @@ func (c *xicmpConnClient) recv6() {
case c.readCh <- packet{ case c.readCh <- packet{
err: err, err: err,
}: }:
case <-c.closedCh: case <-c.closeCh:
return return
} }
} }
errors.LogErrorInner(context.Background(), err, "recv6 err")
continue continue
} }
@@ -236,7 +242,7 @@ func (c *xicmpConnClient) recv6() {
p: p, p: p,
addr: addr, addr: addr,
}: }:
case <-c.closedCh: case <-c.closeCh:
pool.Put(p) pool.Put(p)
return return
} }
@@ -244,16 +250,15 @@ func (c *xicmpConnClient) recv6() {
} }
func (c *xicmpConnClient) ReadFrom(p []byte) (n int, addr net.Addr, err error) { func (c *xicmpConnClient) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
select { packet, ok := <-c.readCh
case packet := <-c.readCh: if ok {
if packet.p != nil { if packet.p != nil {
n = copy(p, packet.p) n = copy(p, packet.p)
pool.Put(packet.p) pool.Put(packet.p)
} }
return n, packet.addr, packet.err return n, packet.addr, packet.err
case <-c.closedCh:
return 0, nil, io.EOF
} }
return 0, nil, io.EOF
} }
func (c *xicmpConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) { func (c *xicmpConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
@@ -294,10 +299,9 @@ func (c *xicmpConnClient) WriteTo(p []byte, addr net.Addr) (n int, err error) {
} }
if err != nil { if err != nil {
errors.LogErrorInner(context.Background(), err, "xicmp write") errors.LogErrorInner(context.Background(), err, "send err")
return 0, err return 0, err
} }
return len(p), nil return len(p), nil
} }
@@ -307,10 +311,19 @@ func (c *xicmpConnClient) Close() error {
if c.closed() { if c.closed() {
return nil return nil
} }
close(c.closedCh) close(c.closeCh)
_ = c.icmp4.Close() _ = c.icmp4.Close()
_ = c.icmp6.Close() _ = c.icmp6.Close()
_ = c.conn.Close() _ = c.conn.Close()
c.wg.Wait()
select {
case p := <-c.readCh:
if p.p != nil {
pool.Put(p.p)
}
default:
}
close(c.readCh)
return nil return nil
} }
+1 -6
View File
@@ -5,16 +5,11 @@ import (
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
) )
func (c *Config) UDP() {
}
func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) { func (c *Config) WrapPacketConnClient(raw net.PacketConn, level int, levelCount int) (net.PacketConn, error) {
_, ok1 := raw.(*internet.FakePacketConn) _, ok1 := raw.(*internet.FakePacketConn)
_, ok2 := raw.(*udphop.UdpHopPacketConn) if level != 0 || ok1 {
if level != 0 || ok1 || ok2 {
return nil, errors.New("xicmp requires being at the outermost level") return nil, errors.New("xicmp requires being at the outermost level")
} }
return NewConnClient(c, raw) return NewConnClient(c, raw)
+43 -30
View File
@@ -37,14 +37,15 @@ type record struct {
} }
type xicmpConnServer struct { type xicmpConnServer struct {
conn net.PacketConn conn net.PacketConn
icmp4 *icmp.PacketConn icmp4 *icmp.PacketConn
icmp6 *icmp.PacketConn icmp6 *icmp.PacketConn
ips map[netip.Addr]struct{} ips map[netip.Addr]struct{}
rec map[string]record rec map[string]record
readCh chan packet readCh chan packet
closedCh chan struct{} closeCh chan struct{}
mu sync.Mutex wg sync.WaitGroup
mu sync.Mutex
} }
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) { func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
@@ -63,16 +64,17 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
} }
conn := &xicmpConnServer{ conn := &xicmpConnServer{
conn: raw, conn: raw,
icmp4: icmp4, icmp4: icmp4,
icmp6: icmp6, icmp6: icmp6,
ips: ips, ips: ips,
rec: make(map[string]record), rec: make(map[string]record),
readCh: make(chan packet), readCh: make(chan packet),
closedCh: make(chan struct{}), closeCh: make(chan struct{}),
} }
go conn.clean() go conn.clean()
conn.wg.Add(2)
go conn.recv4() go conn.recv4()
go conn.recv6() go conn.recv6()
@@ -81,7 +83,7 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
func (c *xicmpConnServer) closed() bool { func (c *xicmpConnServer) closed() bool {
select { select {
case <-c.closedCh: case <-c.closeCh:
return true return true
default: default:
return false return false
@@ -102,15 +104,16 @@ func (c *xicmpConnServer) clean() {
} }
} }
c.mu.Unlock() c.mu.Unlock()
case <-c.closedCh: case <-c.closeCh:
return return
} }
} }
} }
func (c *xicmpConnServer) recv4() { func (c *xicmpConnServer) recv4() {
var b [finalmask.UDPSize]byte defer c.wg.Done()
var b [finalmask.UDPSize]byte
for { for {
if c.closed() { if c.closed() {
return return
@@ -124,10 +127,11 @@ func (c *xicmpConnServer) recv4() {
case c.readCh <- packet{ case c.readCh <- packet{
err: err, err: err,
}: }:
case <-c.closedCh: case <-c.closeCh:
return return
} }
} }
errors.LogErrorInner(context.Background(), err, "recv4 err")
continue continue
} }
@@ -179,7 +183,7 @@ func (c *xicmpConnServer) recv4() {
p: p, p: p,
addr: cAddr, addr: cAddr,
}: }:
case <-c.closedCh: case <-c.closeCh:
pool.Put(p) pool.Put(p)
return return
} }
@@ -187,8 +191,9 @@ func (c *xicmpConnServer) recv4() {
} }
func (c *xicmpConnServer) recv6() { func (c *xicmpConnServer) recv6() {
var b [finalmask.UDPSize]byte defer c.wg.Done()
var b [finalmask.UDPSize]byte
for { for {
if c.closed() { if c.closed() {
return return
@@ -202,10 +207,11 @@ func (c *xicmpConnServer) recv6() {
case c.readCh <- packet{ case c.readCh <- packet{
err: err, err: err,
}: }:
case <-c.closedCh: case <-c.closeCh:
return return
} }
} }
errors.LogErrorInner(context.Background(), err, "recv6 err")
continue continue
} }
@@ -257,7 +263,7 @@ func (c *xicmpConnServer) recv6() {
p: p, p: p,
addr: cAddr, addr: cAddr,
}: }:
case <-c.closedCh: case <-c.closeCh:
pool.Put(p) pool.Put(p)
return return
} }
@@ -265,16 +271,15 @@ func (c *xicmpConnServer) recv6() {
} }
func (c *xicmpConnServer) ReadFrom(p []byte) (n int, addr net.Addr, err error) { func (c *xicmpConnServer) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
select { packet, ok := <-c.readCh
case packet := <-c.readCh: if ok {
if packet.p != nil { if packet.p != nil {
n = copy(p, packet.p) n = copy(p, packet.p)
pool.Put(packet.p) pool.Put(packet.p)
} }
return n, packet.addr, packet.err return n, packet.addr, packet.err
case <-c.closedCh:
return 0, nil, io.EOF
} }
return 0, nil, io.EOF
} }
func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) { func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
@@ -310,10 +315,9 @@ func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
} }
if err != nil { if err != nil {
errors.LogErrorInner(context.Background(), err, "xicmp write") errors.LogErrorInner(context.Background(), err, "send err")
return 0, err return 0, err
} }
return len(p), nil return len(p), nil
} }
@@ -323,10 +327,19 @@ func (c *xicmpConnServer) Close() error {
if c.closed() { if c.closed() {
return nil return nil
} }
close(c.closedCh) close(c.closeCh)
_ = c.icmp4.Close() _ = c.icmp4.Close()
_ = c.icmp6.Close() _ = c.icmp6.Close()
_ = c.conn.Close() _ = c.conn.Close()
c.wg.Wait()
select {
case p := <-c.readCh:
if p.p != nil {
pool.Put(p.p)
}
default:
}
close(c.readCh)
return nil return nil
} }
@@ -39,16 +39,17 @@ type record struct {
} }
type xicmpConnServer struct { type xicmpConnServer struct {
conn net.PacketConn conn net.PacketConn
icmp4 *icmp.PacketConn icmp4 *icmp.PacketConn
icmp6 *icmp.PacketConn icmp6 *icmp.PacketConn
ipv4PC *ipv4.PacketConn ipv4PC *ipv4.PacketConn
ipv6PC *ipv6.PacketConn ipv6PC *ipv6.PacketConn
ips map[netip.Addr]struct{} ips map[netip.Addr]struct{}
rec map[string]record rec map[string]record
readCh chan packet readCh chan packet
closedCh chan struct{} closeCh chan struct{}
mu sync.Mutex wg sync.WaitGroup
mu sync.Mutex
} }
func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) { func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
@@ -67,21 +68,22 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
} }
conn := &xicmpConnServer{ conn := &xicmpConnServer{
conn: raw, conn: raw,
icmp4: icmp4, icmp4: icmp4,
icmp6: icmp6, icmp6: icmp6,
ipv4PC: icmp4.IPv4PacketConn(), ipv4PC: icmp4.IPv4PacketConn(),
ipv6PC: icmp6.IPv6PacketConn(), ipv6PC: icmp6.IPv6PacketConn(),
ips: ips, ips: ips,
rec: make(map[string]record), rec: make(map[string]record),
readCh: make(chan packet), readCh: make(chan packet),
closedCh: make(chan struct{}), closeCh: make(chan struct{}),
} }
common.Must(conn.ipv4PC.SetControlMessage(ipv4.FlagDst, true)) common.Must(conn.ipv4PC.SetControlMessage(ipv4.FlagDst, true))
common.Must(conn.ipv6PC.SetControlMessage(ipv6.FlagDst, true)) common.Must(conn.ipv6PC.SetControlMessage(ipv6.FlagDst, true))
go conn.clean() go conn.clean()
conn.wg.Add(2)
go conn.recv4() go conn.recv4()
go conn.recv6() go conn.recv6()
@@ -90,7 +92,7 @@ func NewConnServer(c *Config, raw net.PacketConn) (net.PacketConn, error) {
func (c *xicmpConnServer) closed() bool { func (c *xicmpConnServer) closed() bool {
select { select {
case <-c.closedCh: case <-c.closeCh:
return true return true
default: default:
return false return false
@@ -111,15 +113,16 @@ func (c *xicmpConnServer) clean() {
} }
} }
c.mu.Unlock() c.mu.Unlock()
case <-c.closedCh: case <-c.closeCh:
return return
} }
} }
} }
func (c *xicmpConnServer) recv4() { func (c *xicmpConnServer) recv4() {
var b [finalmask.UDPSize]byte defer c.wg.Done()
var b [finalmask.UDPSize]byte
for { for {
if c.closed() { if c.closed() {
return return
@@ -133,10 +136,11 @@ func (c *xicmpConnServer) recv4() {
case c.readCh <- packet{ case c.readCh <- packet{
err: err, err: err,
}: }:
case <-c.closedCh: case <-c.closeCh:
return return
} }
} }
errors.LogErrorInner(context.Background(), err, "recv4 err")
continue continue
} }
@@ -189,7 +193,7 @@ func (c *xicmpConnServer) recv4() {
p: p, p: p,
addr: cAddr, addr: cAddr,
}: }:
case <-c.closedCh: case <-c.closeCh:
pool.Put(p) pool.Put(p)
return return
} }
@@ -197,8 +201,9 @@ func (c *xicmpConnServer) recv4() {
} }
func (c *xicmpConnServer) recv6() { func (c *xicmpConnServer) recv6() {
var b [finalmask.UDPSize]byte defer c.wg.Done()
var b [finalmask.UDPSize]byte
for { for {
if c.closed() { if c.closed() {
return return
@@ -212,10 +217,11 @@ func (c *xicmpConnServer) recv6() {
case c.readCh <- packet{ case c.readCh <- packet{
err: err, err: err,
}: }:
case <-c.closedCh: case <-c.closeCh:
return return
} }
} }
errors.LogErrorInner(context.Background(), err, "recv6 err")
continue continue
} }
@@ -268,7 +274,7 @@ func (c *xicmpConnServer) recv6() {
p: p, p: p,
addr: cAddr, addr: cAddr,
}: }:
case <-c.closedCh: case <-c.closeCh:
pool.Put(p) pool.Put(p)
return return
} }
@@ -276,16 +282,15 @@ func (c *xicmpConnServer) recv6() {
} }
func (c *xicmpConnServer) ReadFrom(p []byte) (n int, addr net.Addr, err error) { func (c *xicmpConnServer) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
select { packet, ok := <-c.readCh
case packet := <-c.readCh: if ok {
if packet.p != nil { if packet.p != nil {
n = copy(p, packet.p) n = copy(p, packet.p)
pool.Put(packet.p) pool.Put(packet.p)
} }
return n, packet.addr, packet.err return n, packet.addr, packet.err
case <-c.closedCh:
return 0, nil, io.EOF
} }
return 0, nil, io.EOF
} }
func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) { func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
@@ -321,10 +326,9 @@ func (c *xicmpConnServer) WriteTo(p []byte, addr net.Addr) (n int, err error) {
} }
if err != nil { if err != nil {
errors.LogErrorInner(context.Background(), err, "xicmp write") errors.LogErrorInner(context.Background(), err, "send err")
return 0, err return 0, err
} }
return len(p), nil return len(p), nil
} }
@@ -334,10 +338,19 @@ func (c *xicmpConnServer) Close() error {
if c.closed() { if c.closed() {
return nil return nil
} }
close(c.closedCh) close(c.closeCh)
_ = c.icmp4.Close() _ = c.icmp4.Close()
_ = c.icmp6.Close() _ = c.icmp6.Close()
_ = c.conn.Close() _ = c.conn.Close()
c.wg.Wait()
select {
case p := <-c.readCh:
if p.p != nil {
pool.Put(p.p)
}
default:
}
close(c.readCh)
return nil return nil
} }
@@ -5,9 +5,6 @@ import (
"net" "net"
) )
func (c *Config) TCP() {
}
func (c *Config) WrapConnClient(conn net.Conn) (net.Conn, error) { func (c *Config) WrapConnClient(conn net.Conn) (net.Conn, error) {
profiles, err := profilesFromConfig(c.Profiles) profiles, err := profilesFromConfig(c.Profiles)
if err != nil { if err != nil {
+4 -7
View File
@@ -103,14 +103,11 @@ func (c *InterConn) Update() {
func (c *InterConn) Read(p []byte) (int, error) { func (c *InterConn) Read(p []byte) (int, error) {
b, ok := <-c.ch b, ok := <-c.ch
if !ok { if ok {
return 0, io.EOF c.Update()
return copy(p, b), nil
} }
if len(p) < len(b) { return 0, io.EOF
return 0, io.ErrShortBuffer
}
c.Update()
return copy(p, b), nil
} }
func (c *InterConn) Write(p []byte) (int, error) { func (c *InterConn) Write(p []byte) (int, error) {
-34
View File
@@ -3,7 +3,6 @@ package hysteria
import ( import (
"context" "context"
go_tls "crypto/tls" go_tls "crypto/tls"
"math/rand"
"net/http" "net/http"
"net/url" "net/url"
"reflect" "reflect"
@@ -22,7 +21,6 @@ import (
"github.com/xtls/xray-core/transport/internet/finalmask" "github.com/xtls/xray-core/transport/internet/finalmask"
"github.com/xtls/xray-core/transport/internet/hysteria/congestion" "github.com/xtls/xray-core/transport/internet/hysteria/congestion"
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr" "github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
"github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
) )
@@ -78,7 +76,6 @@ func (c *client) dial(ctx context.Context) error {
if quicParams == nil { if quicParams == nil {
quicParams = &internet.QuicParams{ quicParams = &internet.QuicParams{
BbrProfile: string(bbr.ProfileStandard), BbrProfile: string(bbr.ProfileStandard),
UdpHop: &internet.UdpHop{},
} }
} }
@@ -115,35 +112,8 @@ func (c *client) dial(ctx context.Context) error {
// quicConfig.KeepAlivePeriod = 10 * time.Second // quicConfig.KeepAlivePeriod = 10 * time.Second
// } // }
udpHopDialer := func(addr *net.UDPAddr) (net.PacketConn, error) {
conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), c.socketConfig)
if err != nil {
errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest")
return nil, errors.New("")
}
var pktConn net.PacketConn
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
default:
panic(reflect.TypeOf(c))
}
return pktConn, nil
}
var pktConn net.PacketConn var pktConn net.PacketConn
var udpAddr *net.UDPAddr var udpAddr *net.UDPAddr
var index int
if len(quicParams.UdpHop.Ports) > 0 {
index = rand.Intn(len(quicParams.UdpHop.Ports))
c.dest.Port = net.Port(quicParams.UdpHop.Ports[index])
}
raw, err := internet.DialSystem(ctx, c.dest, c.socketConfig) raw, err := internet.DialSystem(ctx, c.dest, c.socketConfig)
if err != nil { if err != nil {
@@ -160,10 +130,6 @@ func (c *client) dial(ctx context.Context) error {
panic(reflect.TypeOf(c)) panic(reflect.TypeOf(c))
} }
if len(quicParams.UdpHop.Ports) > 0 {
pktConn = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer, pktConn, index)
}
if c.udpmaskManager != nil { if c.udpmaskManager != nil {
newConn, err := c.udpmaskManager.WrapPacketConnClient(pktConn) newConn, err := c.udpmaskManager.WrapPacketConnClient(pktConn)
if err != nil { if err != nil {
-1
View File
@@ -281,7 +281,6 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
if quicParams == nil { if quicParams == nil {
quicParams = &internet.QuicParams{ quicParams = &internet.QuicParams{
BbrProfile: string(bbr.ProfileStandard), BbrProfile: string(bbr.ProfileStandard),
UdpHop: &internet.UdpHop{},
} }
} }
-254
View File
@@ -1,254 +0,0 @@
package udphop
import (
"errors"
"math/rand"
"net"
"sync"
"time"
"github.com/xtls/xray-core/transport/internet/finalmask"
)
const (
packetQueueSize = 1024
udpBufferSize = finalmask.UDPSize
defaultHopInterval = 30 * time.Second
)
type UdpHopPacketConn struct {
Addrs []net.Addr
HopIntervalMin time.Duration
HopIntervalMax time.Duration
ListenUDPFunc func(addr *net.UDPAddr) (net.PacketConn, error)
connMutex sync.RWMutex
prevConn net.PacketConn
currentConn net.PacketConn
addrIndex int
deadline time.Time
readDeadline time.Time
writeDeadline time.Time
recvQueue chan *udpPacket
closeChan chan struct{}
closed bool
bufPool sync.Pool
}
type udpPacket struct {
Buf []byte
N int
Addr net.Addr
Err error
}
func NewUDPHopPacketConn(addrs []net.Addr, hopIntervalMin time.Duration, hopIntervalMax time.Duration, listenUDPFunc func(addr *net.UDPAddr) (net.PacketConn, error), currentConn net.PacketConn, addrIndex int) net.PacketConn {
if len(addrs) == 0 {
panic("len(addrs) == 0")
}
if hopIntervalMin == 0 {
hopIntervalMin = defaultHopInterval
}
if hopIntervalMax == 0 {
hopIntervalMax = defaultHopInterval
}
if hopIntervalMin < 5*time.Second {
panic("hopIntervalMin < 5*time.Second")
}
if hopIntervalMax < 5*time.Second {
panic("hopIntervalMax < 5*time.Second")
}
if hopIntervalMax < hopIntervalMin {
panic("hopIntervalMax < hopIntervalMin")
}
if listenUDPFunc == nil {
panic("listenUDPFunc is nil")
}
hConn := &UdpHopPacketConn{
Addrs: addrs,
HopIntervalMin: hopIntervalMin,
HopIntervalMax: hopIntervalMax,
ListenUDPFunc: listenUDPFunc,
prevConn: nil,
currentConn: currentConn,
addrIndex: addrIndex,
recvQueue: make(chan *udpPacket, packetQueueSize),
closeChan: make(chan struct{}),
bufPool: sync.Pool{
New: func() interface{} {
return make([]byte, udpBufferSize)
},
},
}
go hConn.recvLoop(hConn.currentConn)
go hConn.hopLoop()
return hConn
}
func (u *UdpHopPacketConn) recvLoop(conn net.PacketConn) {
for {
buf := u.bufPool.Get().([]byte)
n, addr, err := conn.ReadFrom(buf)
if err != nil {
u.bufPool.Put(buf)
var netErr net.Error
if errors.As(err, &netErr) && netErr.Timeout() {
u.recvQueue <- &udpPacket{nil, 0, nil, netErr}
continue
}
return
}
select {
case u.recvQueue <- &udpPacket{buf, n, addr, nil}:
default:
u.bufPool.Put(buf)
}
}
}
func (u *UdpHopPacketConn) hopLoop() {
timer := time.NewTimer(u.nextHopInterval())
defer timer.Stop()
for {
select {
case <-timer.C:
u.hop()
timer.Reset(u.nextHopInterval())
case <-u.closeChan:
return
}
}
}
func (u *UdpHopPacketConn) nextHopInterval() time.Duration {
if u.HopIntervalMin == u.HopIntervalMax {
return u.HopIntervalMin
}
return u.HopIntervalMin + time.Duration(rand.Int63n(int64(u.HopIntervalMax-u.HopIntervalMin)+1))
}
func (u *UdpHopPacketConn) hop() {
u.connMutex.Lock()
defer u.connMutex.Unlock()
if u.closed {
return
}
addrIndex := rand.Intn(len(u.Addrs))
newConn, err := u.ListenUDPFunc(u.Addrs[addrIndex].(*net.UDPAddr))
if err != nil {
return
}
if u.prevConn != nil {
_ = u.prevConn.Close()
}
u.prevConn = u.currentConn
u.addrIndex = addrIndex
u.currentConn = newConn
if !u.deadline.IsZero() {
_ = u.currentConn.SetDeadline(u.deadline)
}
if !u.readDeadline.IsZero() {
_ = u.currentConn.SetReadDeadline(u.readDeadline)
}
if !u.writeDeadline.IsZero() {
_ = u.currentConn.SetWriteDeadline(u.writeDeadline)
}
go u.recvLoop(newConn)
}
func (u *UdpHopPacketConn) ReadFrom(b []byte) (n int, addr net.Addr, err error) {
for {
select {
case p := <-u.recvQueue:
if p.Err != nil {
return 0, nil, p.Err
}
n := copy(b, p.Buf[:p.N])
u.bufPool.Put(p.Buf)
return n, p.Addr, nil
case <-u.closeChan:
return 0, nil, net.ErrClosed
}
}
}
func (u *UdpHopPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) {
u.connMutex.RLock()
defer u.connMutex.RUnlock()
if u.closed {
return 0, net.ErrClosed
}
return u.currentConn.WriteTo(b, u.Addrs[u.addrIndex])
}
func (u *UdpHopPacketConn) Close() error {
u.connMutex.Lock()
defer u.connMutex.Unlock()
if u.closed {
return nil
}
if u.prevConn != nil {
_ = u.prevConn.Close()
}
err := u.currentConn.Close()
close(u.closeChan)
u.closed = true
u.Addrs = nil
return err
}
func (u *UdpHopPacketConn) LocalAddr() net.Addr {
u.connMutex.RLock()
defer u.connMutex.RUnlock()
return u.currentConn.LocalAddr()
}
func (u *UdpHopPacketConn) SetDeadline(t time.Time) error {
u.connMutex.Lock()
defer u.connMutex.Unlock()
u.deadline = t
u.readDeadline = t
u.writeDeadline = t
if u.prevConn != nil {
_ = u.prevConn.SetDeadline(t)
}
return u.currentConn.SetDeadline(t)
}
func (u *UdpHopPacketConn) SetReadDeadline(t time.Time) error {
u.connMutex.Lock()
defer u.connMutex.Unlock()
u.deadline = time.Time{}
u.readDeadline = t
if u.prevConn != nil {
_ = u.prevConn.SetReadDeadline(t)
}
return u.currentConn.SetReadDeadline(t)
}
func (u *UdpHopPacketConn) SetWriteDeadline(t time.Time) error {
u.connMutex.Lock()
defer u.connMutex.Unlock()
u.deadline = time.Time{}
u.writeDeadline = t
if u.prevConn != nil {
_ = u.prevConn.SetWriteDeadline(t)
}
return u.currentConn.SetWriteDeadline(t)
}
func ToAddrs(ip net.IP, ports []uint32) []net.Addr {
var addrs []net.Addr
for _, port := range ports {
addr := &net.UDPAddr{
IP: ip,
Port: int(port),
}
addrs = append(addrs, addr)
}
return addrs
}
+1 -1
View File
@@ -53,7 +53,7 @@ func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet
conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings) conn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil { if err != nil {
return nil, errors.New("failed to dial to dest: ", err).AtWarning().Base(err) return nil, errors.New("failed to dial to dest: ", err).Base(err)
} }
if streamSettings.UdpmaskManager != nil { if streamSettings.UdpmaskManager != nil {
+2 -2
View File
@@ -132,7 +132,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
uConn.ServerName = utlsConfig.ServerName uConn.ServerName = utlsConfig.ServerName
fingerprint := tls.GetFingerprint(config.Fingerprint) fingerprint := tls.GetFingerprint(config.Fingerprint)
if fingerprint == nil { if fingerprint == nil {
return nil, errors.New("REALITY: failed to get fingerprint").AtError() return nil, errors.New("REALITY: failed to get fingerprint")
} }
uConn.UConn = utls.UClient(c, utlsConfig, *fingerprint) uConn.UConn = utls.UClient(c, utlsConfig, *fingerprint)
{ {
@@ -271,7 +271,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
// Do not close the connection // Do not close the connection
}() }()
time.Sleep(time.Duration(crypto.RandBetween(config.SpiderY[8], config.SpiderY[9])) * time.Millisecond) // return time.Sleep(time.Duration(crypto.RandBetween(config.SpiderY[8], config.SpiderY[9])) * time.Millisecond) // return
return nil, errors.New("REALITY: processed invalid connection").AtWarning() return nil, errors.New("REALITY: processed invalid connection")
} }
return uConn, nil return uConn, nil
} }
+2 -2
View File
@@ -288,14 +288,14 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
func setReuseAddr(fd uintptr) error { func setReuseAddr(fd uintptr) error {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil { if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1); err != nil {
return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning() return errors.New("failed to set SO_REUSEADDR").Base(err)
} }
return nil return nil
} }
func setReusePort(fd uintptr) error { func setReusePort(fd uintptr) error {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
return errors.New("failed to set SO_REUSEPORT").Base(err).AtWarning() return errors.New("failed to set SO_REUSEPORT").Base(err)
} }
return nil return nil
} }
+2 -2
View File
@@ -224,7 +224,7 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
func setReuseAddr(fd uintptr) error { func setReuseAddr(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning() return errors.New("failed to set SO_REUSEADDR").Base(err)
} }
return nil return nil
} }
@@ -232,7 +232,7 @@ func setReuseAddr(fd uintptr) error {
func setReusePort(fd uintptr) error { func setReusePort(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, soReUsePortLB, 1); err != nil { if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, soReUsePortLB, 1); err != nil {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, soReUsePort, 1); err != nil { if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, soReUsePort, 1); err != nil {
return errors.New("failed to set SO_REUSEPORT").Base(err).AtWarning() return errors.New("failed to set SO_REUSEPORT").Base(err)
} }
} }
return nil return nil
+2 -2
View File
@@ -234,14 +234,14 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
func setReuseAddr(fd uintptr) error { func setReuseAddr(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning() return errors.New("failed to set SO_REUSEADDR").Base(err)
} }
return nil return nil
} }
func setReusePort(fd uintptr) error { func setReusePort(fd uintptr) error {
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
return errors.New("failed to set SO_REUSEPORT").Base(err).AtWarning() return errors.New("failed to set SO_REUSEPORT").Base(err)
} }
return nil return nil
} }
-34
View File
@@ -5,7 +5,6 @@ import (
gotls "crypto/tls" gotls "crypto/tls"
"fmt" "fmt"
"io" "io"
"math/rand"
"net/http" "net/http"
"net/http/httptrace" "net/http/httptrace"
"net/url" "net/url"
@@ -28,7 +27,6 @@ import (
"github.com/xtls/xray-core/transport/internet/browser_dialer" "github.com/xtls/xray-core/transport/internet/browser_dialer"
"github.com/xtls/xray-core/transport/internet/hysteria/congestion" "github.com/xtls/xray-core/transport/internet/hysteria/congestion"
"github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr" "github.com/xtls/xray-core/transport/internet/hysteria/congestion/bbr"
"github.com/xtls/xray-core/transport/internet/hysteria/udphop"
"github.com/xtls/xray-core/transport/internet/reality" "github.com/xtls/xray-core/transport/internet/reality"
"github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls" "github.com/xtls/xray-core/transport/internet/tls"
@@ -162,7 +160,6 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
if quicParams == nil { if quicParams == nil {
quicParams = &internet.QuicParams{ quicParams = &internet.QuicParams{
BbrProfile: string(bbr.ProfileStandard), BbrProfile: string(bbr.ProfileStandard),
UdpHop: &internet.UdpHop{},
} }
} }
@@ -198,35 +195,8 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
QUICConfig: quicConfig, QUICConfig: quicConfig,
TLSClientConfig: gotlsConfig, TLSClientConfig: gotlsConfig,
Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (*quic.Conn, error) { Dial: func(ctx context.Context, addr string, tlsCfg *gotls.Config, cfg *quic.Config) (*quic.Conn, error) {
udpHopDialer := func(addr *net.UDPAddr) (net.PacketConn, error) {
conn, err := internet.DialSystem(ctx, net.UDPDestination(net.IPAddress(addr.IP), net.Port(addr.Port)), streamSettings.SocketSettings)
if err != nil {
errors.LogInfoInner(context.Background(), err, "skip hop: failed to dial to dest")
return nil, errors.New("")
}
var pktConn net.PacketConn
switch c := conn.(type) {
case *internet.PacketConnWrapper:
pktConn = c.PacketConn
case *cnc.Connection:
pktConn = &internet.FakePacketConn{Conn: c}
default:
panic(reflect.TypeOf(c))
}
return pktConn, nil
}
var pktConn net.PacketConn var pktConn net.PacketConn
var udpAddr *net.UDPAddr var udpAddr *net.UDPAddr
var index int
if len(quicParams.UdpHop.Ports) > 0 {
index = rand.Intn(len(quicParams.UdpHop.Ports))
dest.Port = net.Port(quicParams.UdpHop.Ports[index])
}
raw, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings) raw, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil { if err != nil {
@@ -243,10 +213,6 @@ func createHTTPClient(dest net.Destination, streamSettings *internet.MemoryStrea
panic(reflect.TypeOf(c)) panic(reflect.TypeOf(c))
} }
if len(quicParams.UdpHop.Ports) > 0 {
pktConn = udphop.NewUDPHopPacketConn(udphop.ToAddrs(udpAddr.IP, quicParams.UdpHop.Ports), time.Duration(quicParams.UdpHop.IntervalMin)*time.Second, time.Duration(quicParams.UdpHop.IntervalMax)*time.Second, udpHopDialer, pktConn, index)
}
if streamSettings.UdpmaskManager != nil { if streamSettings.UdpmaskManager != nil {
newConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(pktConn) newConn, err := streamSettings.UdpmaskManager.WrapPacketConnClient(pktConn)
if err != nil { if err != nil {
-1
View File
@@ -493,7 +493,6 @@ func ListenXH(ctx context.Context, address net.Address, port net.Port, streamSet
if quicParams == nil { if quicParams == nil {
quicParams = &internet.QuicParams{ quicParams = &internet.QuicParams{
BbrProfile: string(bbr.ProfileStandard), BbrProfile: string(bbr.ProfileStandard),
UdpHop: &internet.UdpHop{},
} }
} }
+4 -4
View File
@@ -86,14 +86,14 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
} }
if err != nil { if err != nil {
if isFromMitmVerify { if isFromMitmVerify {
return nil, errors.New("MITM freedom RAW TLS: failed to verify Domain Fronting certificate from " + mitmServerName).Base(err).AtWarning() return nil, errors.New("MITM freedom RAW TLS: failed to verify Domain Fronting certificate from " + mitmServerName).Base(err)
} }
return nil, err return nil, err
} }
negotiatedProtocol := conn.(tls.Interface).NegotiatedProtocol() negotiatedProtocol := conn.(tls.Interface).NegotiatedProtocol()
if isFromMitmAlpn && !mitmAlpn11 && negotiatedProtocol != "h2" { if isFromMitmAlpn && !mitmAlpn11 && negotiatedProtocol != "h2" {
conn.Close() conn.Close()
return nil, errors.New("MITM freedom RAW TLS: unexpected Negotiated Protocol (" + negotiatedProtocol + ") with " + mitmServerName).AtWarning() return nil, errors.New("MITM freedom RAW TLS: unexpected Negotiated Protocol (" + negotiatedProtocol + ") with " + mitmServerName)
} }
} else if config := reality.ConfigFromStreamSettings(streamSettings); config != nil { } else if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
if conn, err = reality.UClient(conn, config, ctx, dest); err != nil { if conn, err = reality.UClient(conn, config, ctx, dest); err != nil {
@@ -105,11 +105,11 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
if tcpSettings.HeaderSettings != nil { if tcpSettings.HeaderSettings != nil {
headerConfig, err := tcpSettings.HeaderSettings.GetInstance() headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
if err != nil { if err != nil {
return nil, errors.New("failed to get header settings").Base(err).AtError() return nil, errors.New("failed to get header settings").Base(err)
} }
auth, err := internet.CreateConnectionAuthenticator(headerConfig) auth, err := internet.CreateConnectionAuthenticator(headerConfig)
if err != nil { if err != nil {
return nil, errors.New("failed to create header authenticator").Base(err).AtError() return nil, errors.New("failed to create header authenticator").Base(err)
} }
conn = auth.Client(conn) conn = auth.Client(conn)
} }
+2 -2
View File
@@ -82,11 +82,11 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSe
if tcpSettings.HeaderSettings != nil { if tcpSettings.HeaderSettings != nil {
headerConfig, err := tcpSettings.HeaderSettings.GetInstance() headerConfig, err := tcpSettings.HeaderSettings.GetInstance()
if err != nil { if err != nil {
return nil, errors.New("invalid header settings").Base(err).AtError() return nil, errors.New("invalid header settings").Base(err)
} }
auth, err := internet.CreateConnectionAuthenticator(headerConfig) auth, err := internet.CreateConnectionAuthenticator(headerConfig)
if err != nil { if err != nil {
return nil, errors.New("invalid header settings.").Base(err).AtError() return nil, errors.New("invalid header settings.").Base(err)
} }
l.authConfig = auth l.authConfig = auth
} }
+3 -3
View File
@@ -12,7 +12,7 @@ var transportListenerCache = make(map[string]ListenFunc)
func RegisterTransportListener(protocol string, listener ListenFunc) error { func RegisterTransportListener(protocol string, listener ListenFunc) error {
if _, found := transportListenerCache[protocol]; found { if _, found := transportListenerCache[protocol]; found {
return errors.New(protocol, " listener already registered.").AtError() return errors.New(protocol, " listener already registered.")
} }
transportListenerCache[protocol] = listener transportListenerCache[protocol] = listener
return nil return nil
@@ -40,7 +40,7 @@ func ListenUnix(ctx context.Context, address net.Address, settings *MemoryStream
protocol := settings.ProtocolName protocol := settings.ProtocolName
listenFunc := transportListenerCache[protocol] listenFunc := transportListenerCache[protocol]
if listenFunc == nil { if listenFunc == nil {
return nil, errors.New(protocol, " unix listener not registered.").AtError() return nil, errors.New(protocol, " unix listener not registered.")
} }
listener, err := listenFunc(ctx, address, net.Port(0), settings, handler) listener, err := listenFunc(ctx, address, net.Port(0), settings, handler)
if err != nil { if err != nil {
@@ -72,7 +72,7 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, settings
protocol := settings.ProtocolName protocol := settings.ProtocolName
listenFunc := transportListenerCache[protocol] listenFunc := transportListenerCache[protocol]
if listenFunc == nil { if listenFunc == nil {
return nil, errors.New(protocol, " listener not registered.").AtError() return nil, errors.New(protocol, " listener not registered.")
} }
listener, err := listenFunc(ctx, address, port, settings, handler) listener, err := listenFunc(ctx, address, port, settings, handler)
if err != nil { if err != nil {
+1 -1
View File
@@ -39,7 +39,7 @@ func (c *Config) loadSelfCertPool() (*x509.CertPool, error) {
root := x509.NewCertPool() root := x509.NewCertPool()
for _, cert := range c.Certificate { for _, cert := range c.Certificate {
if !root.AppendCertsFromPEM(cert.Certificate) { if !root.AppendCertsFromPEM(cert.Certificate) {
return nil, errors.New("failed to append cert").AtWarning() return nil, errors.New("failed to append cert")
} }
} }
return root, nil return root, nil
+2 -2
View File
@@ -44,11 +44,11 @@ func (c *Config) getCertPool() (*x509.CertPool, error) {
pool, err := x509.SystemCertPool() pool, err := x509.SystemCertPool()
if err != nil { if err != nil {
return nil, errors.New("system root").AtWarning().Base(err) return nil, errors.New("system root").Base(err)
} }
for _, cert := range c.Certificate { for _, cert := range c.Certificate {
if !pool.AppendCertsFromPEM(cert.Certificate) { if !pool.AppendCertsFromPEM(cert.Certificate) {
return nil, errors.New("append cert to root").AtWarning().Base(err) return nil, errors.New("append cert to root").Base(err)
} }
} }
return pool, nil return pool, nil
+4 -4
View File
@@ -63,8 +63,8 @@ func New(opts ...Option) (*Reader, *Writer) {
} }
return &Reader{ return &Reader{
pipe: p, pipe: p,
}, &Writer{ }, &Writer{
pipe: p, pipe: p,
} }
} }