148 lines
5.6 KiB
Go
148 lines
5.6 KiB
Go
package main
|
|
|
|
import (
|
|
"runtime"
|
|
"sync/atomic"
|
|
"time"
|
|
)
|
|
|
|
type XrayNativeTuning struct {
|
|
RuntimeGOMAXPROCS int `json:"runtime_gomaxprocs,omitempty"`
|
|
MuxGlobalSessions int `json:"mux_global_sessions,omitempty"`
|
|
MaxConcurrentConnections int `json:"max_concurrent_connections,omitempty"`
|
|
MaxConcurrentXHTTPRequests int `json:"max_concurrent_xhttp_requests,omitempty"`
|
|
XHTTPMaxSessions int `json:"xhttp_max_sessions,omitempty"`
|
|
TracePackets bool `json:"trace_packets,omitempty"`
|
|
}
|
|
|
|
const (
|
|
defaultNativeRuntimeGOMAXPROCS = 0
|
|
defaultNativeMuxGlobalSessions = 32768
|
|
defaultNativeMaxConnections = 32768
|
|
// XHTTP packet handlers are governed by HTTP/2 flow control and bounded byte
|
|
// queues, not a website-style request ceiling. A negative configured value is
|
|
// normalized to the internal unlimited representation.
|
|
defaultNativeMaxXHTTPRequests = -1
|
|
|
|
fixedNativeMuxMaxSessions = 64
|
|
fixedNativeMuxUDPIdleMS = 120000
|
|
fixedNativeMuxUDPReadBuffer = 256 * 1024
|
|
fixedNativeMuxUDPWriteBuffer = 256 * 1024
|
|
|
|
defaultNativeXHTTPMaxSessions = 32768
|
|
defaultNativeHTTP2MaxStreams = 1024
|
|
// Packet-up posts are also protected by byte budgets in xray_xhttp.go. Keep
|
|
// the default reorder queue modest so thousands of unauthenticated sessions
|
|
// cannot consume large amounts of memory merely by allocating empty channel
|
|
// buffers. Operators may request more, up to the hard cap enforced there.
|
|
defaultNativeXHTTPBufferedPosts = 64
|
|
|
|
// Do not impose an application-level lifetime on a connected XHTTP VPN
|
|
// session. The official Xray server keeps a connected session for the
|
|
// lifetime of its stream-down GET; request cancellation and I/O errors own
|
|
// cleanup. A fixed five-minute sweeper incorrectly killed healthy but idle
|
|
// VPNs. Zero disables the connected-session sweeper.
|
|
fixedNativeXHTTPIdleMS = 0
|
|
)
|
|
|
|
var (
|
|
nativeTuneRuntimeGOMAXPROCS atomic.Int64
|
|
nativeTuneMuxGlobalSessions atomic.Int64
|
|
nativeTuneMaxConnections atomic.Int64
|
|
nativeTuneMaxXHTTPRequests atomic.Int64
|
|
nativeTuneXHTTPMaxSessions atomic.Int64
|
|
nativeTuneTracePackets atomic.Bool
|
|
)
|
|
|
|
func init() {
|
|
applyNativeXrayTuning(nil)
|
|
}
|
|
|
|
func normalizeNativeXrayTuning(t *XrayNativeTuning) XrayNativeTuning {
|
|
if t == nil {
|
|
t = &XrayNativeTuning{}
|
|
}
|
|
out := *t
|
|
// Migrate the two profiles written by older panel builds. Those defaults were
|
|
// sized like a web service (4K/8K sessions and a global request cap) and cause
|
|
// valid high-volume XHTTP VPN traffic to be rejected after an upgrade unless
|
|
// the persisted values are translated here.
|
|
legacySafe := out.MaxConcurrentConnections == 4096 && out.MaxConcurrentXHTTPRequests == 8192 && out.XHTTPMaxSessions == 4096
|
|
legacy2K := out.MaxConcurrentConnections == 8192 && out.MaxConcurrentXHTTPRequests == 16384 && out.XHTTPMaxSessions == 8192
|
|
if legacySafe || legacy2K {
|
|
out.MuxGlobalSessions = defaultNativeMuxGlobalSessions
|
|
out.MaxConcurrentConnections = defaultNativeMaxConnections
|
|
out.MaxConcurrentXHTTPRequests = defaultNativeMaxXHTTPRequests
|
|
out.XHTTPMaxSessions = defaultNativeXHTTPMaxSessions
|
|
}
|
|
if out.RuntimeGOMAXPROCS < 0 {
|
|
out.RuntimeGOMAXPROCS = defaultNativeRuntimeGOMAXPROCS
|
|
}
|
|
if out.MuxGlobalSessions <= 0 {
|
|
out.MuxGlobalSessions = defaultNativeMuxGlobalSessions
|
|
}
|
|
if out.MaxConcurrentConnections == 0 {
|
|
out.MaxConcurrentConnections = defaultNativeMaxConnections
|
|
}
|
|
if out.MaxConcurrentXHTTPRequests == 0 {
|
|
out.MaxConcurrentXHTTPRequests = defaultNativeMaxXHTTPRequests
|
|
}
|
|
if out.XHTTPMaxSessions == 0 {
|
|
out.XHTTPMaxSessions = defaultNativeXHTTPMaxSessions
|
|
}
|
|
return out
|
|
}
|
|
|
|
func applyNativeXrayTuning(t *XrayNativeTuning) XrayNativeTuning {
|
|
out := normalizeNativeXrayTuning(t)
|
|
gomax := out.RuntimeGOMAXPROCS
|
|
if gomax <= 0 {
|
|
gomax = runtime.NumCPU()
|
|
}
|
|
if gomax < 1 {
|
|
gomax = 1
|
|
}
|
|
runtime.GOMAXPROCS(gomax)
|
|
nativeTuneRuntimeGOMAXPROCS.Store(int64(gomax))
|
|
nativeTuneMuxGlobalSessions.Store(int64(out.MuxGlobalSessions))
|
|
nativeTuneMaxConnections.Store(nativeLimitValue(out.MaxConcurrentConnections))
|
|
nativeTuneMaxXHTTPRequests.Store(nativeLimitValue(out.MaxConcurrentXHTTPRequests))
|
|
nativeTuneXHTTPMaxSessions.Store(nativeLimitValue(out.XHTTPMaxSessions))
|
|
nativeTuneTracePackets.Store(out.TracePackets)
|
|
return out
|
|
}
|
|
|
|
// Native tuning limits use zero internally for unlimited. In configuration,
|
|
// zero means "use the safe default" and any negative value disables the cap.
|
|
func nativeLimitValue(v int) int64 {
|
|
if v < 0 {
|
|
return 0
|
|
}
|
|
return int64(v)
|
|
}
|
|
|
|
func nativeRuntimeGOMAXPROCS() int { return int(nativeTuneRuntimeGOMAXPROCS.Load()) }
|
|
func nativeMuxGlobalSessionLimit() int { return int(nativeTuneMuxGlobalSessions.Load()) }
|
|
func nativeMaxConnectionLimit() int { return int(nativeTuneMaxConnections.Load()) }
|
|
func nativeMaxXHTTPRequestLimit() int { return int(nativeTuneMaxXHTTPRequests.Load()) }
|
|
func nativeXHTTPMaxSessionLimit() int { return int(nativeTuneXHTTPMaxSessions.Load()) }
|
|
func nativeTracePacketsEnabled() bool { return nativeTuneTracePackets.Load() }
|
|
|
|
func nativeMuxMaxSessionLimit() int { return fixedNativeMuxMaxSessions }
|
|
func nativeMuxUDPReadBufferSize() int { return fixedNativeMuxUDPReadBuffer }
|
|
func nativeMuxUDPWriteBufferSize() int { return fixedNativeMuxUDPWriteBuffer }
|
|
func nativeXHTTPBufferedPostLimit() int { return defaultNativeXHTTPBufferedPosts }
|
|
func nativeHTTP2MaxConcurrentStreams() uint32 {
|
|
limit := nativeMaxXHTTPRequestLimit()
|
|
if limit <= 0 || limit > defaultNativeHTTP2MaxStreams {
|
|
return defaultNativeHTTP2MaxStreams
|
|
}
|
|
return uint32(limit)
|
|
}
|
|
func nativeMuxUDPIdleTimeout() time.Duration {
|
|
return fixedNativeMuxUDPIdleMS * time.Millisecond
|
|
}
|
|
func nativeXHTTPIdleTimeout() time.Duration {
|
|
return fixedNativeXHTTPIdleMS * time.Millisecond
|
|
}
|