mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-22 00:56:53 +00:00
https://github.com/XTLS/Xray-core/issues/6376#issuecomment-4817591444 https://github.com/XTLS/Xray-core/pull/6426#issuecomment-4899048255 --------- Co-authored-by: RPRX <63339210+RPRX@users.noreply.github.com>
188 lines
6.6 KiB
Go
188 lines
6.6 KiB
Go
package conf
|
|
|
|
import (
|
|
"encoding/json"
|
|
"math"
|
|
"strings"
|
|
|
|
"github.com/xtls/xray-core/common/errors"
|
|
"github.com/xtls/xray-core/transport/internet"
|
|
)
|
|
|
|
type CustomSockoptConfig struct {
|
|
Syetem string `json:"system"`
|
|
Network string `json:"network"`
|
|
Level string `json:"level"`
|
|
Opt string `json:"opt"`
|
|
Value string `json:"value"`
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
type HappyEyeballsConfig struct {
|
|
PrioritizeIPv6 bool `json:"prioritizeIPv6"`
|
|
TryDelayMs uint64 `json:"tryDelayMs"`
|
|
Interleave uint32 `json:"interleave"`
|
|
MaxConcurrentTry uint32 `json:"maxConcurrentTry"`
|
|
}
|
|
|
|
func (h *HappyEyeballsConfig) UnmarshalJSON(data []byte) error {
|
|
innerHappyEyeballsConfig := struct {
|
|
PrioritizeIPv6 bool `json:"prioritizeIPv6"`
|
|
TryDelayMs uint64 `json:"tryDelayMs"`
|
|
Interleave uint32 `json:"interleave"`
|
|
MaxConcurrentTry uint32 `json:"maxConcurrentTry"`
|
|
}{PrioritizeIPv6: false, Interleave: 1, TryDelayMs: 0, MaxConcurrentTry: 4}
|
|
if err := json.Unmarshal(data, &innerHappyEyeballsConfig); err != nil {
|
|
return err
|
|
}
|
|
h.PrioritizeIPv6 = innerHappyEyeballsConfig.PrioritizeIPv6
|
|
h.TryDelayMs = innerHappyEyeballsConfig.TryDelayMs
|
|
h.Interleave = innerHappyEyeballsConfig.Interleave
|
|
h.MaxConcurrentTry = innerHappyEyeballsConfig.MaxConcurrentTry
|
|
return nil
|
|
}
|
|
|
|
type SocketConfig struct {
|
|
Mark int32 `json:"mark"`
|
|
TFO interface{} `json:"tcpFastOpen"`
|
|
TProxy string `json:"tproxy"`
|
|
AcceptProxyProtocol bool `json:"acceptProxyProtocol"`
|
|
DomainStrategy string `json:"domainStrategy"`
|
|
DialerProxy string `json:"dialerProxy"`
|
|
TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"`
|
|
TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"`
|
|
TCPCongestion string `json:"tcpCongestion"`
|
|
TCPWindowClamp int32 `json:"tcpWindowClamp"`
|
|
TCPMaxSeg int32 `json:"tcpMaxSeg"`
|
|
Penetrate bool `json:"penetrate"`
|
|
TCPUserTimeout int32 `json:"tcpUserTimeout"`
|
|
V6only bool `json:"v6only"`
|
|
Interface string `json:"interface"`
|
|
TcpMptcp bool `json:"tcpMptcp"`
|
|
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
|
|
AddressPortStrategy string `json:"addressPortStrategy"`
|
|
HappyEyeballsSettings *HappyEyeballsConfig `json:"happyEyeballs"`
|
|
TrustedXForwardedFor []string `json:"trustedXForwardedFor"`
|
|
}
|
|
|
|
// Build implements Buildable.
|
|
func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|
tfo := int32(0) // don't invoke setsockopt() for TFO
|
|
if c.TFO != nil {
|
|
switch v := c.TFO.(type) {
|
|
case bool:
|
|
if v {
|
|
tfo = 256
|
|
} else {
|
|
tfo = -1 // TFO need to be disabled
|
|
}
|
|
case float64:
|
|
tfo = int32(math.Min(v, math.MaxInt32))
|
|
default:
|
|
return nil, errors.New("tcpFastOpen: only boolean and integer value is acceptable")
|
|
}
|
|
}
|
|
var tproxy internet.SocketConfig_TProxyMode
|
|
switch strings.ToLower(c.TProxy) {
|
|
case "tproxy":
|
|
tproxy = internet.SocketConfig_TProxy
|
|
case "redirect":
|
|
tproxy = internet.SocketConfig_Redirect
|
|
default:
|
|
tproxy = internet.SocketConfig_Off
|
|
}
|
|
|
|
dStrategy := internet.DomainStrategy_AS_IS
|
|
switch strings.ToLower(c.DomainStrategy) {
|
|
case "asis", "":
|
|
dStrategy = internet.DomainStrategy_AS_IS
|
|
case "useip":
|
|
dStrategy = internet.DomainStrategy_USE_IP
|
|
case "useipv4":
|
|
dStrategy = internet.DomainStrategy_USE_IP4
|
|
case "useipv6":
|
|
dStrategy = internet.DomainStrategy_USE_IP6
|
|
case "useipv4v6":
|
|
dStrategy = internet.DomainStrategy_USE_IP46
|
|
case "useipv6v4":
|
|
dStrategy = internet.DomainStrategy_USE_IP64
|
|
case "forceip":
|
|
dStrategy = internet.DomainStrategy_FORCE_IP
|
|
case "forceipv4":
|
|
dStrategy = internet.DomainStrategy_FORCE_IP4
|
|
case "forceipv6":
|
|
dStrategy = internet.DomainStrategy_FORCE_IP6
|
|
case "forceipv4v6":
|
|
dStrategy = internet.DomainStrategy_FORCE_IP46
|
|
case "forceipv6v4":
|
|
dStrategy = internet.DomainStrategy_FORCE_IP64
|
|
default:
|
|
return nil, errors.New("unsupported domain strategy: ", c.DomainStrategy)
|
|
}
|
|
|
|
var customSockopts []*internet.CustomSockopt
|
|
|
|
for _, copt := range c.CustomSockopt {
|
|
customSockopt := &internet.CustomSockopt{
|
|
System: copt.Syetem,
|
|
Network: copt.Network,
|
|
Level: copt.Level,
|
|
Opt: copt.Opt,
|
|
Value: copt.Value,
|
|
Type: copt.Type,
|
|
}
|
|
customSockopts = append(customSockopts, customSockopt)
|
|
}
|
|
|
|
addressPortStrategy := internet.AddressPortStrategy_None
|
|
switch strings.ToLower(c.AddressPortStrategy) {
|
|
case "none", "":
|
|
addressPortStrategy = internet.AddressPortStrategy_None
|
|
case "srvportonly":
|
|
addressPortStrategy = internet.AddressPortStrategy_SrvPortOnly
|
|
case "srvaddressonly":
|
|
addressPortStrategy = internet.AddressPortStrategy_SrvAddressOnly
|
|
case "srvportandaddress":
|
|
addressPortStrategy = internet.AddressPortStrategy_SrvPortAndAddress
|
|
case "txtportonly":
|
|
addressPortStrategy = internet.AddressPortStrategy_TxtPortOnly
|
|
case "txtaddressonly":
|
|
addressPortStrategy = internet.AddressPortStrategy_TxtAddressOnly
|
|
case "txtportandaddress":
|
|
addressPortStrategy = internet.AddressPortStrategy_TxtPortAndAddress
|
|
default:
|
|
return nil, errors.New("unsupported address and port strategy: ", c.AddressPortStrategy)
|
|
}
|
|
|
|
happyEyeballs := &internet.HappyEyeballsConfig{Interleave: 1, PrioritizeIpv6: false, TryDelayMs: 0, MaxConcurrentTry: 4}
|
|
if c.HappyEyeballsSettings != nil {
|
|
happyEyeballs.PrioritizeIpv6 = c.HappyEyeballsSettings.PrioritizeIPv6
|
|
happyEyeballs.Interleave = c.HappyEyeballsSettings.Interleave
|
|
happyEyeballs.TryDelayMs = c.HappyEyeballsSettings.TryDelayMs
|
|
happyEyeballs.MaxConcurrentTry = c.HappyEyeballsSettings.MaxConcurrentTry
|
|
}
|
|
|
|
return &internet.SocketConfig{
|
|
Mark: c.Mark,
|
|
Tfo: tfo,
|
|
Tproxy: tproxy,
|
|
DomainStrategy: dStrategy,
|
|
AcceptProxyProtocol: c.AcceptProxyProtocol,
|
|
DialerProxy: c.DialerProxy,
|
|
TcpKeepAliveInterval: c.TCPKeepAliveInterval,
|
|
TcpKeepAliveIdle: c.TCPKeepAliveIdle,
|
|
TcpCongestion: c.TCPCongestion,
|
|
TcpWindowClamp: c.TCPWindowClamp,
|
|
TcpMaxSeg: c.TCPMaxSeg,
|
|
Penetrate: c.Penetrate,
|
|
TcpUserTimeout: c.TCPUserTimeout,
|
|
V6Only: c.V6only,
|
|
Interface: c.Interface,
|
|
TcpMptcp: c.TcpMptcp,
|
|
CustomSockopt: customSockopts,
|
|
AddressPortStrategy: addressPortStrategy,
|
|
HappyEyeballs: happyEyeballs,
|
|
TrustedXForwardedFor: c.TrustedXForwardedFor,
|
|
}, nil
|
|
}
|