mirror of
https://github.com/XTLS/Xray-core.git
synced 2024-11-22 12:49:20 +02:00
Legends never die (#1725)
This commit is contained in:
parent
4c8ee0af50
commit
9e5bc07bf2
1
go.mod
1
go.mod
|
@ -19,7 +19,6 @@ require (
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
|
||||||
github.com/stretchr/testify v1.8.2
|
github.com/stretchr/testify v1.8.2
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3
|
|
||||||
github.com/xtls/reality v0.0.0-20230227192902-524506d97551
|
github.com/xtls/reality v0.0.0-20230227192902-524506d97551
|
||||||
go.starlark.net v0.0.0-20230128213706-3f75dec8e403
|
go.starlark.net v0.0.0-20230128213706-3f75dec8e403
|
||||||
golang.org/x/crypto v0.6.0
|
golang.org/x/crypto v0.6.0
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -189,8 +189,6 @@ github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
||||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3 h1:a3Y4WVjCxwoyO4E2xdNvq577tW8lkSBgyrA8E9+2NtM=
|
|
||||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY=
|
|
||||||
github.com/xtls/reality v0.0.0-20230227192902-524506d97551 h1:zOP9NvpCMa1Y58UmA9EhbWs5/FNKvqwD5EyDLVit2LI=
|
github.com/xtls/reality v0.0.0-20230227192902-524506d97551 h1:zOP9NvpCMa1Y58UmA9EhbWs5/FNKvqwD5EyDLVit2LI=
|
||||||
github.com/xtls/reality v0.0.0-20230227192902-524506d97551/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y=
|
github.com/xtls/reality v0.0.0-20230227192902-524506d97551/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
|
|
@ -26,7 +26,6 @@ import (
|
||||||
"github.com/xtls/xray-core/transport/internet/tcp"
|
"github.com/xtls/xray-core/transport/internet/tcp"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
"github.com/xtls/xray-core/transport/internet/websocket"
|
"github.com/xtls/xray-core/transport/internet/websocket"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -416,117 +415,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type XTLSCertConfig struct {
|
|
||||||
CertFile string `json:"certificateFile"`
|
|
||||||
CertStr []string `json:"certificate"`
|
|
||||||
KeyFile string `json:"keyFile"`
|
|
||||||
KeyStr []string `json:"key"`
|
|
||||||
Usage string `json:"usage"`
|
|
||||||
OcspStapling uint64 `json:"ocspStapling"`
|
|
||||||
OneTimeLoading bool `json:"oneTimeLoading"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build implements Buildable.
|
|
||||||
func (c *XTLSCertConfig) Build() (*xtls.Certificate, error) {
|
|
||||||
certificate := new(xtls.Certificate)
|
|
||||||
cert, err := readFileOrString(c.CertFile, c.CertStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to parse certificate").Base(err)
|
|
||||||
}
|
|
||||||
certificate.Certificate = cert
|
|
||||||
certificate.CertificatePath = c.CertFile
|
|
||||||
|
|
||||||
if len(c.KeyFile) > 0 || len(c.KeyStr) > 0 {
|
|
||||||
key, err := readFileOrString(c.KeyFile, c.KeyStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to parse key").Base(err)
|
|
||||||
}
|
|
||||||
certificate.Key = key
|
|
||||||
certificate.KeyPath = c.KeyFile
|
|
||||||
}
|
|
||||||
|
|
||||||
switch strings.ToLower(c.Usage) {
|
|
||||||
case "encipherment":
|
|
||||||
certificate.Usage = xtls.Certificate_ENCIPHERMENT
|
|
||||||
case "verify":
|
|
||||||
certificate.Usage = xtls.Certificate_AUTHORITY_VERIFY
|
|
||||||
case "issue":
|
|
||||||
certificate.Usage = xtls.Certificate_AUTHORITY_ISSUE
|
|
||||||
default:
|
|
||||||
certificate.Usage = xtls.Certificate_ENCIPHERMENT
|
|
||||||
}
|
|
||||||
if certificate.KeyPath == "" && certificate.CertificatePath == "" {
|
|
||||||
certificate.OneTimeLoading = true
|
|
||||||
} else {
|
|
||||||
certificate.OneTimeLoading = c.OneTimeLoading
|
|
||||||
}
|
|
||||||
certificate.OcspStapling = c.OcspStapling
|
|
||||||
|
|
||||||
return certificate, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type XTLSConfig struct {
|
|
||||||
Insecure bool `json:"allowInsecure"`
|
|
||||||
Certs []*XTLSCertConfig `json:"certificates"`
|
|
||||||
ServerName string `json:"serverName"`
|
|
||||||
ALPN *StringList `json:"alpn"`
|
|
||||||
EnableSessionResumption bool `json:"enableSessionResumption"`
|
|
||||||
DisableSystemRoot bool `json:"disableSystemRoot"`
|
|
||||||
MinVersion string `json:"minVersion"`
|
|
||||||
MaxVersion string `json:"maxVersion"`
|
|
||||||
CipherSuites string `json:"cipherSuites"`
|
|
||||||
PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
|
|
||||||
Fingerprint string `json:"fingerprint"`
|
|
||||||
RejectUnknownSNI bool `json:"rejectUnknownSni"`
|
|
||||||
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build implements Buildable.
|
|
||||||
func (c *XTLSConfig) Build() (proto.Message, error) {
|
|
||||||
config := new(xtls.Config)
|
|
||||||
config.Certificate = make([]*xtls.Certificate, len(c.Certs))
|
|
||||||
for idx, certConf := range c.Certs {
|
|
||||||
cert, err := certConf.Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
config.Certificate[idx] = cert
|
|
||||||
}
|
|
||||||
serverName := c.ServerName
|
|
||||||
config.AllowInsecure = c.Insecure
|
|
||||||
if len(c.ServerName) > 0 {
|
|
||||||
config.ServerName = serverName
|
|
||||||
}
|
|
||||||
if c.ALPN != nil && len(*c.ALPN) > 0 {
|
|
||||||
config.NextProtocol = []string(*c.ALPN)
|
|
||||||
}
|
|
||||||
config.EnableSessionResumption = c.EnableSessionResumption
|
|
||||||
config.DisableSystemRoot = c.DisableSystemRoot
|
|
||||||
config.MinVersion = c.MinVersion
|
|
||||||
config.MaxVersion = c.MaxVersion
|
|
||||||
config.CipherSuites = c.CipherSuites
|
|
||||||
config.PreferServerCipherSuites = c.PreferServerCipherSuites
|
|
||||||
if c.Fingerprint != "" {
|
|
||||||
return nil, newError(`Old version of XTLS does not support fingerprint. Please use flow "xtls-rprx-vision" with "tls & tlsSettings" instead.`)
|
|
||||||
}
|
|
||||||
config.RejectUnknownSni = c.RejectUnknownSNI
|
|
||||||
|
|
||||||
if c.PinnedPeerCertificateChainSha256 != nil {
|
|
||||||
config.PinnedPeerCertificateChainSha256 = [][]byte{}
|
|
||||||
for _, v := range *c.PinnedPeerCertificateChainSha256 {
|
|
||||||
hashValue, err := base64.StdEncoding.DecodeString(v)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
config.PinnedPeerCertificateChainSha256 = append(config.PinnedPeerCertificateChainSha256, hashValue)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newError(`You are using an old version of XTLS, which is deprecated now and will be removed soon. Please use flow "xtls-rprx-vision" with "tls & tlsSettings" instead.`).AtWarning().WriteToLog()
|
|
||||||
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type REALITYConfig struct {
|
type REALITYConfig struct {
|
||||||
Show bool `json:"show"`
|
Show bool `json:"show"`
|
||||||
Dest json.RawMessage `json:"dest"`
|
Dest json.RawMessage `json:"dest"`
|
||||||
|
@ -788,7 +676,6 @@ type StreamConfig struct {
|
||||||
Network *TransportProtocol `json:"network"`
|
Network *TransportProtocol `json:"network"`
|
||||||
Security string `json:"security"`
|
Security string `json:"security"`
|
||||||
TLSSettings *TLSConfig `json:"tlsSettings"`
|
TLSSettings *TLSConfig `json:"tlsSettings"`
|
||||||
XTLSSettings *XTLSConfig `json:"xtlsSettings"`
|
|
||||||
REALITYSettings *REALITYConfig `json:"realitySettings"`
|
REALITYSettings *REALITYConfig `json:"realitySettings"`
|
||||||
TCPSettings *TCPConfig `json:"tcpSettings"`
|
TCPSettings *TCPConfig `json:"tcpSettings"`
|
||||||
KCPSettings *KCPConfig `json:"kcpSettings"`
|
KCPSettings *KCPConfig `json:"kcpSettings"`
|
||||||
|
@ -816,9 +703,6 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||||
if strings.EqualFold(c.Security, "tls") {
|
if strings.EqualFold(c.Security, "tls") {
|
||||||
tlsSettings := c.TLSSettings
|
tlsSettings := c.TLSSettings
|
||||||
if tlsSettings == nil {
|
if tlsSettings == nil {
|
||||||
if c.XTLSSettings != nil {
|
|
||||||
return nil, newError(`TLS: Please use "tlsSettings" instead of "xtlsSettings".`)
|
|
||||||
}
|
|
||||||
tlsSettings = &TLSConfig{}
|
tlsSettings = &TLSConfig{}
|
||||||
}
|
}
|
||||||
ts, err := tlsSettings.Build()
|
ts, err := tlsSettings.Build()
|
||||||
|
@ -829,25 +713,6 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||||
config.SecuritySettings = append(config.SecuritySettings, tm)
|
config.SecuritySettings = append(config.SecuritySettings, tm)
|
||||||
config.SecurityType = tm.Type
|
config.SecurityType = tm.Type
|
||||||
}
|
}
|
||||||
if strings.EqualFold(c.Security, "xtls") {
|
|
||||||
if config.ProtocolName != "tcp" && config.ProtocolName != "mkcp" && config.ProtocolName != "domainsocket" {
|
|
||||||
return nil, newError("XTLS only supports TCP, mKCP and DomainSocket for now.")
|
|
||||||
}
|
|
||||||
xtlsSettings := c.XTLSSettings
|
|
||||||
if xtlsSettings == nil {
|
|
||||||
if c.TLSSettings != nil {
|
|
||||||
return nil, newError(`XTLS: Please use "xtlsSettings" instead of "tlsSettings".`)
|
|
||||||
}
|
|
||||||
xtlsSettings = &XTLSConfig{}
|
|
||||||
}
|
|
||||||
ts, err := xtlsSettings.Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("Failed to build XTLS config.").Base(err)
|
|
||||||
}
|
|
||||||
tm := serial.ToTypedMessage(ts)
|
|
||||||
config.SecuritySettings = append(config.SecuritySettings, tm)
|
|
||||||
config.SecurityType = tm.Type
|
|
||||||
}
|
|
||||||
if strings.EqualFold(c.Security, "reality") {
|
if strings.EqualFold(c.Security, "reality") {
|
||||||
if config.ProtocolName != "tcp" && config.ProtocolName != "http" && config.ProtocolName != "grpc" && config.ProtocolName != "domainsocket" {
|
if config.ProtocolName != "tcp" && config.ProtocolName != "http" && config.ProtocolName != "grpc" && config.ProtocolName != "domainsocket" {
|
||||||
return nil, newError("REALITY only supports TCP, H2, gRPC and DomainSocket for now.")
|
return nil, newError("REALITY only supports TCP, H2, gRPC and DomainSocket for now.")
|
||||||
|
|
|
@ -53,11 +53,7 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch account.Flow {
|
switch account.Flow {
|
||||||
case "", "xtls-rprx-origin", "xtls-rprx-origin-udp443", "xtls-rprx-direct", "xtls-rprx-direct-udp443":
|
case "":
|
||||||
case "xtls-rprx-splice", "xtls-rprx-splice-udp443":
|
|
||||||
if runtime.GOOS != "linux" && runtime.GOOS != "android" {
|
|
||||||
return nil, newError(`Trojan servers: "` + account.Flow + `" only support linux in this version`)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return nil, newError(`Trojan servers: "flow" doesn't support "` + account.Flow + `" in this version`)
|
return nil, newError(`Trojan servers: "flow" doesn't support "` + account.Flow + `" in this version`)
|
||||||
}
|
}
|
||||||
|
@ -119,9 +115,7 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch account.Flow {
|
switch account.Flow {
|
||||||
case "", "xtls-rprx-origin", "xtls-rprx-direct":
|
case "":
|
||||||
case "xtls-rprx-splice":
|
|
||||||
return nil, newError(`Trojan clients: inbound doesn't support "xtls-rprx-splice" in this version, please use "xtls-rprx-direct" instead`)
|
|
||||||
default:
|
default:
|
||||||
return nil, newError(`Trojan clients: "flow" doesn't support "` + account.Flow + `" in this version`)
|
return nil, newError(`Trojan clients: "flow" doesn't support "` + account.Flow + `" in this version`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,9 +62,7 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch accountFlow {
|
switch accountFlow {
|
||||||
case "", vless.XRO, vless.XRD, vless.XRV:
|
case "", vless.XRV:
|
||||||
case vless.XRS:
|
|
||||||
return nil, newError(`VLESS clients: inbound doesn't support "xtls-rprx-splice" in this version, please use "xtls-rprx-direct" instead`)
|
|
||||||
default:
|
default:
|
||||||
return nil, newError(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`)
|
return nil, newError(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`)
|
||||||
}
|
}
|
||||||
|
@ -191,11 +189,7 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
||||||
account.Id = u.String()
|
account.Id = u.String()
|
||||||
|
|
||||||
switch account.Flow {
|
switch account.Flow {
|
||||||
case "", vless.XRO, vless.XRO + "-udp443", vless.XRD, vless.XRD + "-udp443", vless.XRV, vless.XRV + "-udp443":
|
case "", vless.XRV, vless.XRV + "-udp443":
|
||||||
case vless.XRS, vless.XRS + "-udp443":
|
|
||||||
if runtime.GOOS != "linux" && runtime.GOOS != "android" {
|
|
||||||
return nil, newError(`VLESS users: "` + account.Flow + `" only support linux in this version`)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return nil, newError(`VLESS users: "flow" doesn't support "` + account.Flow + `" in this version`)
|
return nil, newError(`VLESS users: "flow" doesn't support "` + account.Flow + `" in this version`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestVLessOutbound(t *testing.T) {
|
||||||
"users": [
|
"users": [
|
||||||
{
|
{
|
||||||
"id": "27848739-7e62-4138-9fd3-098a63964b6b",
|
"id": "27848739-7e62-4138-9fd3-098a63964b6b",
|
||||||
"flow": "xtls-rprx-direct-udp443",
|
"flow": "xtls-rprx-vision-udp443",
|
||||||
"encryption": "none",
|
"encryption": "none",
|
||||||
"level": 0
|
"level": 0
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ func TestVLessOutbound(t *testing.T) {
|
||||||
{
|
{
|
||||||
Account: serial.ToTypedMessage(&vless.Account{
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
Id: "27848739-7e62-4138-9fd3-098a63964b6b",
|
Id: "27848739-7e62-4138-9fd3-098a63964b6b",
|
||||||
Flow: "xtls-rprx-direct-udp443",
|
Flow: "xtls-rprx-vision-udp443",
|
||||||
Encryption: "none",
|
Encryption: "none",
|
||||||
}),
|
}),
|
||||||
Level: 0,
|
Level: 0,
|
||||||
|
@ -71,7 +71,7 @@ func TestVLessInbound(t *testing.T) {
|
||||||
"clients": [
|
"clients": [
|
||||||
{
|
{
|
||||||
"id": "27848739-7e62-4138-9fd3-098a63964b6b",
|
"id": "27848739-7e62-4138-9fd3-098a63964b6b",
|
||||||
"flow": "xtls-rprx-direct",
|
"flow": "xtls-rprx-vision",
|
||||||
"level": 0,
|
"level": 0,
|
||||||
"email": "love@example.com"
|
"email": "love@example.com"
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func TestVLessInbound(t *testing.T) {
|
||||||
{
|
{
|
||||||
Account: serial.ToTypedMessage(&vless.Account{
|
Account: serial.ToTypedMessage(&vless.Account{
|
||||||
Id: "27848739-7e62-4138-9fd3-098a63964b6b",
|
Id: "27848739-7e62-4138-9fd3-098a63964b6b",
|
||||||
Flow: "xtls-rprx-direct",
|
Flow: "xtls-rprx-vision",
|
||||||
}),
|
}),
|
||||||
Level: 0,
|
Level: 0,
|
||||||
Email: "love@example.com",
|
Email: "love@example.com",
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -236,9 +235,6 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if ss.SecurityType == serial.GetMessageType(&xtls.Config{}) && !strings.EqualFold(c.Protocol, "vless") && !strings.EqualFold(c.Protocol, "trojan") {
|
|
||||||
return nil, newError("XTLS doesn't supports " + c.Protocol + " for now.")
|
|
||||||
}
|
|
||||||
receiverSettings.StreamSettings = ss
|
receiverSettings.StreamSettings = ss
|
||||||
}
|
}
|
||||||
if c.SniffingConfig != nil {
|
if c.SniffingConfig != nil {
|
||||||
|
@ -319,9 +315,6 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if ss.SecurityType == serial.GetMessageType(&xtls.Config{}) && !strings.EqualFold(c.Protocol, "vless") && !strings.EqualFold(c.Protocol, "trojan") {
|
|
||||||
return nil, newError("XTLS doesn't supports " + c.Protocol + " for now.")
|
|
||||||
}
|
|
||||||
senderSettings.StreamSettings = ss
|
senderSettings.StreamSettings = ss
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -346,15 +339,7 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.MuxSettings != nil {
|
if c.MuxSettings != nil {
|
||||||
ms := c.MuxSettings.Build()
|
senderSettings.MultiplexSettings = c.MuxSettings.Build()
|
||||||
if ms != nil && ms.Enabled {
|
|
||||||
if ss := senderSettings.StreamSettings; ss != nil {
|
|
||||||
if ss.SecurityType == serial.GetMessageType(&xtls.Config{}) {
|
|
||||||
return nil, newError("XTLS doesn't support Mux for now.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
senderSettings.MultiplexSettings = ms
|
|
||||||
}
|
}
|
||||||
|
|
||||||
settings := []byte("{}")
|
settings := []byte("{}")
|
||||||
|
|
|
@ -61,7 +61,6 @@ import (
|
||||||
_ "github.com/xtls/xray-core/transport/internet/tls"
|
_ "github.com/xtls/xray-core/transport/internet/tls"
|
||||||
_ "github.com/xtls/xray-core/transport/internet/udp"
|
_ "github.com/xtls/xray-core/transport/internet/udp"
|
||||||
_ "github.com/xtls/xray-core/transport/internet/websocket"
|
_ "github.com/xtls/xray-core/transport/internet/websocket"
|
||||||
_ "github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
|
|
||||||
// Transport headers
|
// Transport headers
|
||||||
_ "github.com/xtls/xray-core/transport/internet/headers/http"
|
_ "github.com/xtls/xray-core/transport/internet/headers/http"
|
||||||
|
|
|
@ -2,14 +2,12 @@ package trojan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/retry"
|
"github.com/xtls/xray-core/common/retry"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
@ -17,11 +15,9 @@ import (
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/policy"
|
"github.com/xtls/xray-core/features/policy"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Client is a inbound handler for trojan protocol
|
// Client is a inbound handler for trojan protocol
|
||||||
|
@ -97,49 +93,6 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||||
Flow: account.Flow,
|
Flow: account.Flow,
|
||||||
}
|
}
|
||||||
|
|
||||||
var rawConn syscall.RawConn
|
|
||||||
var sctx context.Context
|
|
||||||
|
|
||||||
allowUDP443 := false
|
|
||||||
switch connWriter.Flow {
|
|
||||||
case XRO + "-udp443", XRD + "-udp443", XRS + "-udp443":
|
|
||||||
allowUDP443 = true
|
|
||||||
connWriter.Flow = connWriter.Flow[:16]
|
|
||||||
fallthrough
|
|
||||||
case XRO, XRD, XRS:
|
|
||||||
if destination.Address.Family().IsDomain() && destination.Address.Domain() == muxCoolAddress {
|
|
||||||
return newError(connWriter.Flow + " doesn't support Mux").AtWarning()
|
|
||||||
}
|
|
||||||
if destination.Network == net.Network_UDP {
|
|
||||||
if !allowUDP443 && destination.Port == 443 {
|
|
||||||
return newError(connWriter.Flow + " stopped UDP/443").AtInfo()
|
|
||||||
}
|
|
||||||
connWriter.Flow = ""
|
|
||||||
} else { // enable XTLS only if making TCP request
|
|
||||||
if xtlsConn, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
xtlsConn.RPRX = true
|
|
||||||
xtlsConn.SHOW = xtls_show
|
|
||||||
xtlsConn.MARK = "XTLS"
|
|
||||||
if connWriter.Flow == XRS {
|
|
||||||
sctx = ctx
|
|
||||||
connWriter.Flow = XRD
|
|
||||||
}
|
|
||||||
if connWriter.Flow == XRD {
|
|
||||||
xtlsConn.DirectMode = true
|
|
||||||
if sc, ok := xtlsConn.NetConn().(syscall.Conn); ok {
|
|
||||||
rawConn, _ = sc.SyscallConn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return newError(`failed to use ` + connWriter.Flow + `, maybe "security" is not "xtls"`).AtWarning()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if _, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
panic(`To avoid misunderstanding, you must fill in Trojan "flow" when using XTLS.`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionPolicy := c.policyManager.ForLevel(user.Level)
|
sessionPolicy := c.policyManager.ForLevel(user.Level)
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||||
|
@ -193,13 +146,6 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||||
} else {
|
} else {
|
||||||
reader = buf.NewReader(conn)
|
reader = buf.NewReader(conn)
|
||||||
}
|
}
|
||||||
if rawConn != nil {
|
|
||||||
var counter stats.Counter
|
|
||||||
if statConn != nil {
|
|
||||||
counter = statConn.ReadCounter
|
|
||||||
}
|
|
||||||
return ReadV(reader, link.Writer, timer, iConn.(*xtls.Conn), rawConn, counter, sctx)
|
|
||||||
}
|
|
||||||
return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
|
return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,11 +161,4 @@ func init() {
|
||||||
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
return NewClient(ctx, config.(*ClientConfig))
|
return NewClient(ctx, config.(*ClientConfig))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const defaultFlagValue = "NOT_DEFINED_AT_ALL"
|
|
||||||
|
|
||||||
xtlsShow := platform.NewEnvFlag("xray.trojan.xtls.show").GetValue(func() string { return defaultFlagValue })
|
|
||||||
if xtlsShow == "true" {
|
|
||||||
xtls_show = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,12 @@
|
||||||
package trojan
|
package trojan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
fmt "fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"runtime"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/session"
|
|
||||||
"github.com/xtls/xray-core/common/signal"
|
|
||||||
"github.com/xtls/xray-core/features/stats"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -27,25 +17,13 @@ var (
|
||||||
protocol.AddressFamilyByte(0x04, net.AddressFamilyIPv6),
|
protocol.AddressFamilyByte(0x04, net.AddressFamilyIPv6),
|
||||||
protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain),
|
protocol.AddressFamilyByte(0x03, net.AddressFamilyDomain),
|
||||||
)
|
)
|
||||||
|
|
||||||
xtls_show = false
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
maxLength = 8192
|
maxLength = 8192
|
||||||
// XRS is constant for XTLS splice mode
|
|
||||||
XRS = "xtls-rprx-splice"
|
|
||||||
// XRD is constant for XTLS direct mode
|
|
||||||
XRD = "xtls-rprx-direct"
|
|
||||||
// XRO is constant for XTLS origin mode
|
|
||||||
XRO = "xtls-rprx-origin"
|
|
||||||
|
|
||||||
commandTCP byte = 1
|
commandTCP byte = 1
|
||||||
commandUDP byte = 3
|
commandUDP byte = 3
|
||||||
|
|
||||||
// for XTLS
|
|
||||||
commandXRD byte = 0xf0 // XTLS direct mode
|
|
||||||
commandXRO byte = 0xf1 // XTLS origin mode
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConnWriter is TCP Connection Writer Wrapper for trojan protocol
|
// ConnWriter is TCP Connection Writer Wrapper for trojan protocol
|
||||||
|
@ -90,10 +68,6 @@ func (c *ConnWriter) writeHeader() error {
|
||||||
command := commandTCP
|
command := commandTCP
|
||||||
if c.Target.Network == net.Network_UDP {
|
if c.Target.Network == net.Network_UDP {
|
||||||
command = commandUDP
|
command = commandUDP
|
||||||
} else if c.Flow == XRD {
|
|
||||||
command = commandXRD
|
|
||||||
} else if c.Flow == XRO {
|
|
||||||
command = commandXRO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := buffer.Write(c.Account.Key); err != nil {
|
if _, err := buffer.Write(c.Account.Key); err != nil {
|
||||||
|
@ -201,10 +175,6 @@ func (c *ConnReader) ParseHeader() error {
|
||||||
network := net.Network_TCP
|
network := net.Network_TCP
|
||||||
if command[0] == commandUDP {
|
if command[0] == commandUDP {
|
||||||
network = net.Network_UDP
|
network = net.Network_UDP
|
||||||
} else if command[0] == commandXRD {
|
|
||||||
c.Flow = XRD
|
|
||||||
} else if command[0] == commandXRO {
|
|
||||||
c.Flow = XRO
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, port, err := addrParser.ReadAddressPort(nil, c.Reader)
|
addr, port, err := addrParser.ReadAddressPort(nil, c.Reader)
|
||||||
|
@ -288,66 +258,3 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||||
|
|
||||||
return mb, nil
|
return mb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn *xtls.Conn, rawConn syscall.RawConn, counter stats.Counter, sctx context.Context) error {
|
|
||||||
err := func() error {
|
|
||||||
var ct stats.Counter
|
|
||||||
for {
|
|
||||||
if conn.DirectIn {
|
|
||||||
conn.DirectIn = false
|
|
||||||
if sctx != nil {
|
|
||||||
if inbound := session.InboundFromContext(sctx); inbound != nil && inbound.Conn != nil {
|
|
||||||
iConn := inbound.Conn
|
|
||||||
statConn, ok := iConn.(*stat.CounterConnection)
|
|
||||||
if ok {
|
|
||||||
iConn = statConn.Connection
|
|
||||||
}
|
|
||||||
if xc, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
iConn = xc.NetConn()
|
|
||||||
}
|
|
||||||
if tc, ok := iConn.(*net.TCPConn); ok {
|
|
||||||
if conn.SHOW {
|
|
||||||
fmt.Println(conn.MARK, "Splice")
|
|
||||||
}
|
|
||||||
runtime.Gosched() // necessary
|
|
||||||
w, err := tc.ReadFrom(conn.NetConn())
|
|
||||||
if counter != nil {
|
|
||||||
counter.Add(w)
|
|
||||||
}
|
|
||||||
if statConn != nil && statConn.WriteCounter != nil {
|
|
||||||
statConn.WriteCounter.Add(w)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
panic("XTLS Splice: not TCP inbound")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// panic("XTLS Splice: nil inbound or nil inbound.Conn")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader = buf.NewReadVReader(conn.NetConn(), rawConn, nil)
|
|
||||||
ct = counter
|
|
||||||
if conn.SHOW {
|
|
||||||
fmt.Println(conn.MARK, "ReadV")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer, err := reader.ReadMultiBuffer()
|
|
||||||
if !buffer.IsEmpty() {
|
|
||||||
if ct != nil {
|
|
||||||
ct.Add(int64(buffer.Len()))
|
|
||||||
}
|
|
||||||
timer.Update()
|
|
||||||
if werr := writer.WriteMultiBuffer(buffer); werr != nil {
|
|
||||||
return werr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if err != nil && errors.Cause(err) != io.EOF {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
@ -13,7 +12,6 @@ import (
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
udp_proto "github.com/xtls/xray-core/common/protocol/udp"
|
udp_proto "github.com/xtls/xray-core/common/protocol/udp"
|
||||||
"github.com/xtls/xray-core/common/retry"
|
"github.com/xtls/xray-core/common/retry"
|
||||||
|
@ -23,25 +21,16 @@ import (
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/policy"
|
"github.com/xtls/xray-core/features/policy"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/udp"
|
"github.com/xtls/xray-core/transport/internet/udp"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
return NewServer(ctx, config.(*ServerConfig))
|
return NewServer(ctx, config.(*ServerConfig))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const defaultFlagValue = "NOT_DEFINED_AT_ALL"
|
|
||||||
|
|
||||||
xtlsShow := platform.NewEnvFlag("xray.trojan.xtls.show").GetValue(func() string { return defaultFlagValue })
|
|
||||||
if xtlsShow == "true" {
|
|
||||||
xtls_show = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Server is an inbound connection handler that handles messages in trojan protocol.
|
// Server is an inbound connection handler that handles messages in trojan protocol.
|
||||||
|
@ -235,39 +224,6 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
|
||||||
return s.handleUDPPayload(ctx, &PacketReader{Reader: clientReader}, &PacketWriter{Writer: conn}, dispatcher)
|
return s.handleUDPPayload(ctx, &PacketReader{Reader: clientReader}, &PacketWriter{Writer: conn}, dispatcher)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle tcp request
|
|
||||||
account, ok := user.Account.(*MemoryAccount)
|
|
||||||
if !ok {
|
|
||||||
return newError("user account is not valid")
|
|
||||||
}
|
|
||||||
|
|
||||||
var rawConn syscall.RawConn
|
|
||||||
|
|
||||||
switch clientReader.Flow {
|
|
||||||
case XRO, XRD:
|
|
||||||
if account.Flow == clientReader.Flow {
|
|
||||||
if destination.Address.Family().IsDomain() && destination.Address.Domain() == muxCoolAddress {
|
|
||||||
return newError(clientReader.Flow + " doesn't support Mux").AtWarning()
|
|
||||||
}
|
|
||||||
if xtlsConn, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
xtlsConn.RPRX = true
|
|
||||||
xtlsConn.SHOW = xtls_show
|
|
||||||
xtlsConn.MARK = "XTLS"
|
|
||||||
if clientReader.Flow == XRD {
|
|
||||||
xtlsConn.DirectMode = true
|
|
||||||
if sc, ok := xtlsConn.NetConn().(syscall.Conn); ok {
|
|
||||||
rawConn, _ = sc.SyscallConn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return newError(`failed to use ` + clientReader.Flow + `, maybe "security" is not "xtls"`).AtWarning()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return newError(account.Password + " is not able to use " + clientReader.Flow).AtWarning()
|
|
||||||
}
|
|
||||||
case "":
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
||||||
From: conn.RemoteAddr(),
|
From: conn.RemoteAddr(),
|
||||||
To: destination,
|
To: destination,
|
||||||
|
@ -277,7 +233,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
|
||||||
})
|
})
|
||||||
|
|
||||||
newError("received request for ", destination).WriteToLog(sid)
|
newError("received request for ", destination).WriteToLog(sid)
|
||||||
return s.handleConnection(ctx, sessionPolicy, destination, clientReader, buf.NewWriter(conn), dispatcher, iConn, rawConn, statConn)
|
return s.handleConnection(ctx, sessionPolicy, destination, clientReader, buf.NewWriter(conn), dispatcher, iConn, statConn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error {
|
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error {
|
||||||
|
@ -343,7 +299,7 @@ func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReade
|
||||||
func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Session,
|
func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Session,
|
||||||
destination net.Destination,
|
destination net.Destination,
|
||||||
clientReader buf.Reader,
|
clientReader buf.Reader,
|
||||||
clientWriter buf.Writer, dispatcher routing.Dispatcher, iConn stat.Connection, rawConn syscall.RawConn, statConn *stat.CounterConnection,
|
clientWriter buf.Writer, dispatcher routing.Dispatcher, iConn stat.Connection, statConn *stat.CounterConnection,
|
||||||
) error {
|
) error {
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||||
|
@ -356,18 +312,7 @@ func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Sess
|
||||||
|
|
||||||
requestDone := func() error {
|
requestDone := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
|
if buf.Copy(clientReader, link.Writer, buf.UpdateActivity(timer)) != nil {
|
||||||
var err error
|
|
||||||
if rawConn != nil {
|
|
||||||
var counter stats.Counter
|
|
||||||
if statConn != nil {
|
|
||||||
counter = statConn.ReadCounter
|
|
||||||
}
|
|
||||||
err = ReadV(clientReader, link.Writer, timer, iConn.(*xtls.Conn), rawConn, counter, nil)
|
|
||||||
} else {
|
|
||||||
err = buf.Copy(clientReader, link.Writer, buf.UpdateActivity(timer))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return newError("failed to transfer request").Base(err)
|
return newError("failed to transfer request").Base(err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -406,12 +351,6 @@ func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err erro
|
||||||
alpn = cs.NegotiatedProtocol
|
alpn = cs.NegotiatedProtocol
|
||||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
||||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
||||||
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
cs := xtlsConn.ConnectionState()
|
|
||||||
name = cs.ServerName
|
|
||||||
alpn = cs.NegotiatedProtocol
|
|
||||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
|
||||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
|
||||||
} else if realityConn, ok := iConn.(*reality.Conn); ok {
|
} else if realityConn, ok := iConn.(*reality.Conn); ok {
|
||||||
cs := realityConn.ConnectionState()
|
cs := realityConn.ConnectionState()
|
||||||
name = cs.ServerName
|
name = cs.ServerName
|
||||||
|
|
|
@ -22,7 +22,7 @@ func (a *Account) AsAccount() (protocol.Account, error) {
|
||||||
type MemoryAccount struct {
|
type MemoryAccount struct {
|
||||||
// ID of the account.
|
// ID of the account.
|
||||||
ID *protocol.ID
|
ID *protocol.ID
|
||||||
// Flow of the account. May be "xtls-rprx-direct".
|
// Flow of the account. May be "xtls-rprx-vision".
|
||||||
Flow string
|
Flow string
|
||||||
// Encryption of the account. Used for client connections, and only accepts "none" for now.
|
// Encryption of the account. Used for client connections, and only accepts "none" for now.
|
||||||
Encryption string
|
Encryption string
|
||||||
|
|
|
@ -27,7 +27,7 @@ type Account struct {
|
||||||
|
|
||||||
// ID of the account, in the form of a UUID, e.g., "66ad4540-b58c-4ad2-9926-ea63445a9b57".
|
// ID of the account, in the form of a UUID, e.g., "66ad4540-b58c-4ad2-9926-ea63445a9b57".
|
||||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
// Flow settings. May be "xtls-rprx-direct".
|
// Flow settings. May be "xtls-rprx-vision".
|
||||||
Flow string `protobuf:"bytes,2,opt,name=flow,proto3" json:"flow,omitempty"`
|
Flow string `protobuf:"bytes,2,opt,name=flow,proto3" json:"flow,omitempty"`
|
||||||
// Encryption settings. Only applies to client side, and only accepts "none" for now.
|
// Encryption settings. Only applies to client side, and only accepts "none" for now.
|
||||||
Encryption string `protobuf:"bytes,3,opt,name=encryption,proto3" json:"encryption,omitempty"`
|
Encryption string `protobuf:"bytes,3,opt,name=encryption,proto3" json:"encryption,omitempty"`
|
||||||
|
|
|
@ -9,7 +9,7 @@ option java_multiple_files = true;
|
||||||
message Account {
|
message Account {
|
||||||
// ID of the account, in the form of a UUID, e.g., "66ad4540-b58c-4ad2-9926-ea63445a9b57".
|
// ID of the account, in the form of a UUID, e.g., "66ad4540-b58c-4ad2-9926-ea63445a9b57".
|
||||||
string id = 1;
|
string id = 1;
|
||||||
// Flow settings. May be "xtls-rprx-direct".
|
// Flow settings. May be "xtls-rprx-vision".
|
||||||
string flow = 2;
|
string flow = 2;
|
||||||
// Encryption settings. Only applies to client side, and only accepts "none" for now.
|
// Encryption settings. Only applies to client side, and only accepts "none" for now.
|
||||||
string encryption = 3;
|
string encryption = 3;
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
|
|
||||||
func EncodeHeaderAddons(buffer *buf.Buffer, addons *Addons) error {
|
func EncodeHeaderAddons(buffer *buf.Buffer, addons *Addons) error {
|
||||||
switch addons.Flow {
|
switch addons.Flow {
|
||||||
case vless.XRO, vless.XRD, vless.XRV:
|
case vless.XRV:
|
||||||
bytes, err := proto.Marshal(addons)
|
bytes, err := proto.Marshal(addons)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newError("failed to marshal addons protobuf value").Base(err)
|
return newError("failed to marshal addons protobuf value").Base(err)
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
@ -24,7 +23,6 @@ import (
|
||||||
"github.com/xtls/xray-core/proxy/vless"
|
"github.com/xtls/xray-core/proxy/vless"
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -206,65 +204,6 @@ func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*A
|
||||||
return responseAddons, nil
|
return responseAddons, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn *xtls.Conn, rawConn syscall.RawConn, counter stats.Counter, ctx context.Context) error {
|
|
||||||
err := func() error {
|
|
||||||
var ct stats.Counter
|
|
||||||
for {
|
|
||||||
if conn.DirectIn {
|
|
||||||
conn.DirectIn = false
|
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil {
|
|
||||||
iConn := inbound.Conn
|
|
||||||
statConn, ok := iConn.(*stat.CounterConnection)
|
|
||||||
if ok {
|
|
||||||
iConn = statConn.Connection
|
|
||||||
}
|
|
||||||
if xc, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
iConn = xc.NetConn()
|
|
||||||
}
|
|
||||||
if tc, ok := iConn.(*net.TCPConn); ok {
|
|
||||||
if conn.SHOW {
|
|
||||||
fmt.Println(conn.MARK, "Splice")
|
|
||||||
}
|
|
||||||
runtime.Gosched() // necessary
|
|
||||||
w, err := tc.ReadFrom(conn.NetConn())
|
|
||||||
if counter != nil {
|
|
||||||
counter.Add(w)
|
|
||||||
}
|
|
||||||
if statConn != nil && statConn.WriteCounter != nil {
|
|
||||||
statConn.WriteCounter.Add(w)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
panic("XTLS Splice: not TCP inbound")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reader = buf.NewReadVReader(conn.NetConn(), rawConn, nil)
|
|
||||||
ct = counter
|
|
||||||
if conn.SHOW {
|
|
||||||
fmt.Println(conn.MARK, "ReadV")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buffer, err := reader.ReadMultiBuffer()
|
|
||||||
if !buffer.IsEmpty() {
|
|
||||||
if ct != nil {
|
|
||||||
ct.Add(int64(buffer.Len()))
|
|
||||||
}
|
|
||||||
timer.Update()
|
|
||||||
if werr := writer.WriteMultiBuffer(buffer); werr != nil {
|
|
||||||
return werr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if err != nil && errors.Cause(err) != io.EOF {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// XtlsRead filter and read xtls protocol
|
// XtlsRead filter and read xtls protocol
|
||||||
func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn,
|
func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn,
|
||||||
input *bytes.Reader, rawInput *bytes.Buffer,
|
input *bytes.Reader, rawInput *bytes.Buffer,
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/retry"
|
"github.com/xtls/xray-core/common/retry"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
@ -37,11 +36,8 @@ import (
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var xtls_show = false
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
var dc dns.Client
|
var dc dns.Client
|
||||||
|
@ -53,13 +49,6 @@ func init() {
|
||||||
}
|
}
|
||||||
return New(ctx, config.(*Config), dc)
|
return New(ctx, config.(*Config), dc)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const defaultFlagValue = "NOT_DEFINED_AT_ALL"
|
|
||||||
|
|
||||||
xtlsShow := platform.NewEnvFlag("xray.vless.xtls.show").GetValue(func() string { return defaultFlagValue })
|
|
||||||
if xtlsShow == "true" {
|
|
||||||
xtls_show = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler is an inbound connection handler that handles messages in VLess protocol.
|
// Handler is an inbound connection handler that handles messages in VLess protocol.
|
||||||
|
@ -241,12 +230,6 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||||
alpn = cs.NegotiatedProtocol
|
alpn = cs.NegotiatedProtocol
|
||||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
||||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
||||||
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
cs := xtlsConn.ConnectionState()
|
|
||||||
name = cs.ServerName
|
|
||||||
alpn = cs.NegotiatedProtocol
|
|
||||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
|
||||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
|
||||||
} else if realityConn, ok := iConn.(*reality.Conn); ok {
|
} else if realityConn, ok := iConn.(*reality.Conn); ok {
|
||||||
cs := realityConn.ConnectionState()
|
cs := realityConn.ConnectionState()
|
||||||
name = cs.ServerName
|
name = cs.ServerName
|
||||||
|
@ -479,7 +462,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch requestAddons.Flow {
|
switch requestAddons.Flow {
|
||||||
case vless.XRO, vless.XRD, vless.XRV:
|
case vless.XRV:
|
||||||
if accountFlow == requestAddons.Flow {
|
if accountFlow == requestAddons.Flow {
|
||||||
switch request.Command {
|
switch request.Command {
|
||||||
case protocol.RequestCommandMux:
|
case protocol.RequestCommandMux:
|
||||||
|
@ -487,51 +470,35 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||||
case protocol.RequestCommandUDP:
|
case protocol.RequestCommandUDP:
|
||||||
return newError(requestAddons.Flow + " doesn't support UDP").AtWarning()
|
return newError(requestAddons.Flow + " doesn't support UDP").AtWarning()
|
||||||
case protocol.RequestCommandTCP:
|
case protocol.RequestCommandTCP:
|
||||||
if requestAddons.Flow == vless.XRV {
|
var t reflect.Type
|
||||||
var t reflect.Type
|
var p uintptr
|
||||||
var p uintptr
|
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 newError(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning()
|
||||||
return newError(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning()
|
|
||||||
}
|
|
||||||
netConn = tlsConn.NetConn()
|
|
||||||
t = reflect.TypeOf(tlsConn.Conn).Elem()
|
|
||||||
p = uintptr(unsafe.Pointer(tlsConn.Conn))
|
|
||||||
} else if realityConn, ok := iConn.(*reality.Conn); ok {
|
|
||||||
netConn = realityConn.NetConn()
|
|
||||||
t = reflect.TypeOf(realityConn.Conn).Elem()
|
|
||||||
p = uintptr(unsafe.Pointer(realityConn.Conn))
|
|
||||||
} else if _, ok := iConn.(*tls.UConn); ok {
|
|
||||||
return newError("XTLS only supports UTLS fingerprint for the outbound.").AtWarning()
|
|
||||||
} else if _, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
return newError(`failed to use ` + requestAddons.Flow + `, vision "security" must be "tls" or "reality"`).AtWarning()
|
|
||||||
} else {
|
|
||||||
return newError("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning()
|
|
||||||
}
|
|
||||||
if pc, ok := netConn.(*proxyproto.Conn); ok {
|
|
||||||
netConn = pc.Raw()
|
|
||||||
// 8192 > 4096, there is no need to process pc's bufReader
|
|
||||||
}
|
|
||||||
if sc, ok := netConn.(syscall.Conn); ok {
|
|
||||||
rawConn, _ = sc.SyscallConn()
|
|
||||||
}
|
|
||||||
i, _ := t.FieldByName("input")
|
|
||||||
r, _ := t.FieldByName("rawInput")
|
|
||||||
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
|
|
||||||
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
|
|
||||||
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
xtlsConn.RPRX = true
|
|
||||||
xtlsConn.SHOW = xtls_show
|
|
||||||
xtlsConn.MARK = "XTLS"
|
|
||||||
if requestAddons.Flow == vless.XRD {
|
|
||||||
xtlsConn.DirectMode = true
|
|
||||||
if sc, ok := xtlsConn.NetConn().(syscall.Conn); ok {
|
|
||||||
rawConn, _ = sc.SyscallConn()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
netConn = tlsConn.NetConn()
|
||||||
|
t = reflect.TypeOf(tlsConn.Conn).Elem()
|
||||||
|
p = uintptr(unsafe.Pointer(tlsConn.Conn))
|
||||||
|
} else if realityConn, ok := iConn.(*reality.Conn); ok {
|
||||||
|
netConn = realityConn.NetConn()
|
||||||
|
t = reflect.TypeOf(realityConn.Conn).Elem()
|
||||||
|
p = uintptr(unsafe.Pointer(realityConn.Conn))
|
||||||
|
} else if _, ok := iConn.(*tls.UConn); ok {
|
||||||
|
return newError("XTLS only supports UTLS fingerprint for the outbound.").AtWarning()
|
||||||
} else {
|
} else {
|
||||||
return newError(`failed to use ` + requestAddons.Flow + `, maybe "security" is not "xtls"`).AtWarning()
|
return newError("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning()
|
||||||
}
|
}
|
||||||
|
if pc, ok := netConn.(*proxyproto.Conn); ok {
|
||||||
|
netConn = pc.Raw()
|
||||||
|
// 8192 > 4096, there is no need to process pc's bufReader
|
||||||
|
}
|
||||||
|
if sc, ok := netConn.(syscall.Conn); ok {
|
||||||
|
rawConn, _ = sc.SyscallConn()
|
||||||
|
}
|
||||||
|
i, _ := t.FieldByName("input")
|
||||||
|
r, _ := t.FieldByName("rawInput")
|
||||||
|
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
|
||||||
|
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return newError(account.ID.String() + " is not able to use " + requestAddons.Flow).AtWarning()
|
return newError(account.ID.String() + " is not able to use " + requestAddons.Flow).AtWarning()
|
||||||
|
@ -589,12 +556,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||||
}
|
}
|
||||||
// TODO enable splice
|
// TODO enable splice
|
||||||
ctx = session.ContextWithInbound(ctx, nil)
|
ctx = session.ContextWithInbound(ctx, nil)
|
||||||
if requestAddons.Flow == vless.XRV {
|
err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
|
||||||
err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
|
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||||
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
|
||||||
} else {
|
|
||||||
err = encoding.ReadV(clientReader, serverWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
|
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
|
||||||
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
||||||
|
|
|
@ -15,7 +15,6 @@ import (
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/retry"
|
"github.com/xtls/xray-core/common/retry"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
@ -32,22 +31,12 @@ import (
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var xtls_show = false
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
return New(ctx, config.(*Config))
|
return New(ctx, config.(*Config))
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const defaultFlagValue = "NOT_DEFINED_AT_ALL"
|
|
||||||
|
|
||||||
xtlsShow := platform.NewEnvFlag("xray.vless.xtls.show").GetValue(func() string { return defaultFlagValue })
|
|
||||||
if xtlsShow == "true" {
|
|
||||||
xtls_show = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler is an outbound connection handler for VLess protocol.
|
// Handler is an outbound connection handler for VLess protocol.
|
||||||
|
@ -140,11 +129,11 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||||
var rawInput *bytes.Buffer
|
var rawInput *bytes.Buffer
|
||||||
allowUDP443 := false
|
allowUDP443 := false
|
||||||
switch requestAddons.Flow {
|
switch requestAddons.Flow {
|
||||||
case vless.XRO + "-udp443", vless.XRD + "-udp443", vless.XRS + "-udp443", vless.XRV + "-udp443":
|
case vless.XRV + "-udp443":
|
||||||
allowUDP443 = true
|
allowUDP443 = true
|
||||||
requestAddons.Flow = requestAddons.Flow[:16]
|
requestAddons.Flow = requestAddons.Flow[:16]
|
||||||
fallthrough
|
fallthrough
|
||||||
case vless.XRO, vless.XRD, vless.XRS, vless.XRV:
|
case vless.XRV:
|
||||||
switch request.Command {
|
switch request.Command {
|
||||||
case protocol.RequestCommandMux:
|
case protocol.RequestCommandMux:
|
||||||
return newError(requestAddons.Flow + " doesn't support Mux").AtWarning()
|
return newError(requestAddons.Flow + " doesn't support Mux").AtWarning()
|
||||||
|
@ -154,53 +143,30 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||||
}
|
}
|
||||||
requestAddons.Flow = ""
|
requestAddons.Flow = ""
|
||||||
case protocol.RequestCommandTCP:
|
case protocol.RequestCommandTCP:
|
||||||
if requestAddons.Flow == vless.XRV {
|
var t reflect.Type
|
||||||
var t reflect.Type
|
var p uintptr
|
||||||
var p uintptr
|
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
netConn = tlsConn.NetConn()
|
||||||
netConn = tlsConn.NetConn()
|
t = reflect.TypeOf(tlsConn.Conn).Elem()
|
||||||
t = reflect.TypeOf(tlsConn.Conn).Elem()
|
p = uintptr(unsafe.Pointer(tlsConn.Conn))
|
||||||
p = uintptr(unsafe.Pointer(tlsConn.Conn))
|
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
|
||||||
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
|
netConn = utlsConn.NetConn()
|
||||||
netConn = utlsConn.NetConn()
|
t = reflect.TypeOf(utlsConn.Conn).Elem()
|
||||||
t = reflect.TypeOf(utlsConn.Conn).Elem()
|
p = uintptr(unsafe.Pointer(utlsConn.Conn))
|
||||||
p = uintptr(unsafe.Pointer(utlsConn.Conn))
|
} else if realityConn, ok := iConn.(*reality.UConn); ok {
|
||||||
} else if realityConn, ok := iConn.(*reality.UConn); ok {
|
netConn = realityConn.NetConn()
|
||||||
netConn = realityConn.NetConn()
|
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 if _, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
return newError(`failed to use ` + requestAddons.Flow + `, vision "security" must be "tls" or "reality"`).AtWarning()
|
|
||||||
} else {
|
|
||||||
return newError("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning()
|
|
||||||
}
|
|
||||||
if sc, ok := netConn.(syscall.Conn); ok {
|
|
||||||
rawConn, _ = sc.SyscallConn()
|
|
||||||
}
|
|
||||||
i, _ := t.FieldByName("input")
|
|
||||||
r, _ := t.FieldByName("rawInput")
|
|
||||||
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
|
|
||||||
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
|
|
||||||
} else if xtlsConn, ok := iConn.(*xtls.Conn); ok {
|
|
||||||
xtlsConn.RPRX = true
|
|
||||||
xtlsConn.SHOW = xtls_show
|
|
||||||
xtlsConn.MARK = "XTLS"
|
|
||||||
if requestAddons.Flow == vless.XRS {
|
|
||||||
requestAddons.Flow = vless.XRD
|
|
||||||
}
|
|
||||||
if requestAddons.Flow == vless.XRD {
|
|
||||||
xtlsConn.DirectMode = true
|
|
||||||
if sc, ok := xtlsConn.NetConn().(syscall.Conn); ok {
|
|
||||||
rawConn, _ = sc.SyscallConn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return newError(`failed to use ` + requestAddons.Flow + `, maybe "security" is not "xtls"`).AtWarning()
|
return newError("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning()
|
||||||
}
|
}
|
||||||
}
|
if sc, ok := netConn.(syscall.Conn); ok {
|
||||||
default:
|
rawConn, _ = sc.SyscallConn()
|
||||||
if _, ok := iConn.(*xtls.Conn); ok {
|
}
|
||||||
panic(`To avoid misunderstanding, you must fill in VLESS "flow" when using XTLS.`)
|
i, _ := t.FieldByName("input")
|
||||||
|
r, _ := t.FieldByName("rawInput")
|
||||||
|
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
|
||||||
|
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,15 +286,8 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||||
if statConn != nil {
|
if statConn != nil {
|
||||||
counter = statConn.ReadCounter
|
counter = statConn.ReadCounter
|
||||||
}
|
}
|
||||||
if requestAddons.Flow == vless.XRV {
|
err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
|
||||||
err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
|
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||||
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
|
||||||
} else {
|
|
||||||
if requestAddons.Flow != vless.XRS {
|
|
||||||
ctx = session.ContextWithInbound(ctx, nil)
|
|
||||||
}
|
|
||||||
err = encoding.ReadV(serverReader, clientWriter, timer, iConn.(*xtls.Conn), rawConn, counter, ctx)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
|
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
|
||||||
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
||||||
|
|
|
@ -8,8 +8,5 @@ package vless
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||||
|
|
||||||
const (
|
const (
|
||||||
XRO = "xtls-rprx-origin"
|
|
||||||
XRD = "xtls-rprx-direct"
|
|
||||||
XRS = "xtls-rprx-splice"
|
|
||||||
XRV = "xtls-rprx-vision"
|
XRV = "xtls-rprx-vision"
|
||||||
)
|
)
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (stat.Connection, error) {
|
||||||
|
@ -29,8 +28,6 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
||||||
|
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
return tls.Client(conn, config.GetTLSConfig(tls.WithDestination(dest))), nil
|
return tls.Client(conn, config.GetTLSConfig(tls.WithDestination(dest))), nil
|
||||||
} else if config := xtls.ConfigFromStreamSettings(streamSettings); config != nil {
|
|
||||||
return xtls.Client(conn, config.GetXTLSConfig(xtls.WithDestination(dest))), nil
|
|
||||||
} else if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
} else if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
return reality.UClient(conn, config, ctx, dest)
|
return reality.UClient(conn, config, ctx, dest)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
goxtls "github.com/xtls/go"
|
|
||||||
goreality "github.com/xtls/reality"
|
goreality "github.com/xtls/reality"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
@ -17,7 +16,6 @@ import (
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,7 +23,6 @@ type Listener struct {
|
||||||
addr *net.UnixAddr
|
addr *net.UnixAddr
|
||||||
ln net.Listener
|
ln net.Listener
|
||||||
tlsConfig *gotls.Config
|
tlsConfig *gotls.Config
|
||||||
xtlsConfig *goxtls.Config
|
|
||||||
realityConfig *goreality.Config
|
realityConfig *goreality.Config
|
||||||
config *Config
|
config *Config
|
||||||
addConn internet.ConnHandler
|
addConn internet.ConnHandler
|
||||||
|
@ -64,9 +61,6 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
ln.tlsConfig = config.GetTLSConfig()
|
ln.tlsConfig = config.GetTLSConfig()
|
||||||
}
|
}
|
||||||
if config := xtls.ConfigFromStreamSettings(streamSettings); config != nil {
|
|
||||||
ln.xtlsConfig = config.GetXTLSConfig()
|
|
||||||
}
|
|
||||||
if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
ln.realityConfig = config.GetREALITYConfig()
|
ln.realityConfig = config.GetREALITYConfig()
|
||||||
}
|
}
|
||||||
|
@ -100,8 +94,6 @@ func (ln *Listener) run() {
|
||||||
go func() {
|
go func() {
|
||||||
if ln.tlsConfig != nil {
|
if ln.tlsConfig != nil {
|
||||||
conn = tls.Server(conn, ln.tlsConfig)
|
conn = tls.Server(conn, ln.tlsConfig)
|
||||||
} else if ln.xtlsConfig != nil {
|
|
||||||
conn = xtls.Server(conn, ln.xtlsConfig)
|
|
||||||
} else if ln.realityConfig != nil {
|
} else if ln.realityConfig != nil {
|
||||||
if conn, err = reality.Server(conn, ln.realityConfig); err != nil {
|
if conn, err = reality.Server(conn, ln.realityConfig); err != nil {
|
||||||
newError(err).AtInfo().WriteToLog()
|
newError(err).AtInfo().WriteToLog()
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var globalConv = uint32(dice.RollUint16())
|
var globalConv = uint32(dice.RollUint16())
|
||||||
|
@ -87,8 +86,6 @@ func DialKCP(ctx context.Context, dest net.Destination, streamSettings *internet
|
||||||
|
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
iConn = tls.Client(iConn, config.GetTLSConfig(tls.WithDestination(dest)))
|
iConn = tls.Client(iConn, config.GetTLSConfig(tls.WithDestination(dest)))
|
||||||
} else if config := xtls.ConfigFromStreamSettings(streamSettings); config != nil {
|
|
||||||
iConn = xtls.Client(iConn, config.GetXTLSConfig(xtls.WithDestination(dest)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return iConn, nil
|
return iConn, nil
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
gotls "crypto/tls"
|
gotls "crypto/tls"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
goxtls "github.com/xtls/go"
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
@ -14,7 +13,6 @@ import (
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/udp"
|
"github.com/xtls/xray-core/transport/internet/udp"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ConnectionID struct {
|
type ConnectionID struct {
|
||||||
|
@ -29,7 +27,6 @@ type Listener struct {
|
||||||
sessions map[ConnectionID]*Connection
|
sessions map[ConnectionID]*Connection
|
||||||
hub *udp.Hub
|
hub *udp.Hub
|
||||||
tlsConfig *gotls.Config
|
tlsConfig *gotls.Config
|
||||||
xtlsConfig *goxtls.Config
|
|
||||||
config *Config
|
config *Config
|
||||||
reader PacketReader
|
reader PacketReader
|
||||||
header internet.PacketHeader
|
header internet.PacketHeader
|
||||||
|
@ -62,9 +59,6 @@ func NewListener(ctx context.Context, address net.Address, port net.Port, stream
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
l.tlsConfig = config.GetTLSConfig()
|
l.tlsConfig = config.GetTLSConfig()
|
||||||
}
|
}
|
||||||
if config := xtls.ConfigFromStreamSettings(streamSettings); config != nil {
|
|
||||||
l.xtlsConfig = config.GetXTLSConfig()
|
|
||||||
}
|
|
||||||
|
|
||||||
hub, err := udp.ListenUDP(ctx, address, port, streamSettings, udp.HubCapacity(1024))
|
hub, err := udp.ListenUDP(ctx, address, port, streamSettings, udp.HubCapacity(1024))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -137,8 +131,6 @@ func (l *Listener) OnReceive(payload *buf.Buffer, src net.Destination) {
|
||||||
var netConn stat.Connection = conn
|
var netConn stat.Connection = conn
|
||||||
if l.tlsConfig != nil {
|
if l.tlsConfig != nil {
|
||||||
netConn = tls.Server(conn, l.tlsConfig)
|
netConn = tls.Server(conn, l.tlsConfig)
|
||||||
} else if l.xtlsConfig != nil {
|
|
||||||
netConn = xtls.Server(conn, l.xtlsConfig)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
l.addConn(netConn)
|
l.addConn(netConn)
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Dial dials a new TCP connection to the given destination.
|
// Dial dials a new TCP connection to the given destination.
|
||||||
|
@ -31,9 +30,6 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
||||||
} else {
|
} else {
|
||||||
conn = tls.Client(conn, tlsConfig)
|
conn = tls.Client(conn, tlsConfig)
|
||||||
}
|
}
|
||||||
} else if config := xtls.ConfigFromStreamSettings(streamSettings); config != nil {
|
|
||||||
xtlsConfig := config.GetXTLSConfig(xtls.WithDestination(dest))
|
|
||||||
conn = xtls.Client(conn, xtlsConfig)
|
|
||||||
} 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 {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
goxtls "github.com/xtls/go"
|
|
||||||
goreality "github.com/xtls/reality"
|
goreality "github.com/xtls/reality"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
@ -15,14 +14,12 @@ import (
|
||||||
"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"
|
||||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Listener is an internet.Listener that listens for TCP connections.
|
// Listener is an internet.Listener that listens for TCP connections.
|
||||||
type Listener struct {
|
type Listener struct {
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
tlsConfig *gotls.Config
|
tlsConfig *gotls.Config
|
||||||
xtlsConfig *goxtls.Config
|
|
||||||
realityConfig *goreality.Config
|
realityConfig *goreality.Config
|
||||||
authConfig internet.ConnectionAuthenticator
|
authConfig internet.ConnectionAuthenticator
|
||||||
config *Config
|
config *Config
|
||||||
|
@ -78,9 +75,6 @@ func ListenTCP(ctx context.Context, address net.Address, port net.Port, streamSe
|
||||||
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := tls.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
l.tlsConfig = config.GetTLSConfig()
|
l.tlsConfig = config.GetTLSConfig()
|
||||||
}
|
}
|
||||||
if config := xtls.ConfigFromStreamSettings(streamSettings); config != nil {
|
|
||||||
l.xtlsConfig = config.GetXTLSConfig()
|
|
||||||
}
|
|
||||||
if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
||||||
l.realityConfig = config.GetREALITYConfig()
|
l.realityConfig = config.GetREALITYConfig()
|
||||||
}
|
}
|
||||||
|
@ -118,8 +112,6 @@ func (v *Listener) keepAccepting() {
|
||||||
go func() {
|
go func() {
|
||||||
if v.tlsConfig != nil {
|
if v.tlsConfig != nil {
|
||||||
conn = tls.Server(conn, v.tlsConfig)
|
conn = tls.Server(conn, v.tlsConfig)
|
||||||
} else if v.xtlsConfig != nil {
|
|
||||||
conn = xtls.Server(conn, v.xtlsConfig)
|
|
||||||
} else if v.realityConfig != nil {
|
} else if v.realityConfig != nil {
|
||||||
if conn, err = reality.Server(conn, v.realityConfig); err != nil {
|
if conn, err = reality.Server(conn, v.realityConfig); err != nil {
|
||||||
newError(err).AtInfo().WriteToLog()
|
newError(err).AtInfo().WriteToLog()
|
||||||
|
|
|
@ -1,377 +0,0 @@
|
||||||
package xtls
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
xtls "github.com/xtls/go"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/ocsp"
|
|
||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
|
||||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
|
||||||
)
|
|
||||||
|
|
||||||
var globalSessionCache = xtls.NewLRUClientSessionCache(128)
|
|
||||||
|
|
||||||
// ParseCertificate converts a cert.Certificate to Certificate.
|
|
||||||
func ParseCertificate(c *cert.Certificate) *Certificate {
|
|
||||||
if c != nil {
|
|
||||||
certPEM, keyPEM := c.ToPEM()
|
|
||||||
return &Certificate{
|
|
||||||
Certificate: certPEM,
|
|
||||||
Key: keyPEM,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) loadSelfCertPool() (*x509.CertPool, error) {
|
|
||||||
root := x509.NewCertPool()
|
|
||||||
for _, cert := range c.Certificate {
|
|
||||||
if !root.AppendCertsFromPEM(cert.Certificate) {
|
|
||||||
return nil, newError("failed to append cert").AtWarning()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return root, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// BuildCertificates builds a list of TLS certificates from proto definition.
|
|
||||||
func (c *Config) BuildCertificates() []*xtls.Certificate {
|
|
||||||
certs := make([]*xtls.Certificate, 0, len(c.Certificate))
|
|
||||||
for _, entry := range c.Certificate {
|
|
||||||
if entry.Usage != Certificate_ENCIPHERMENT {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
keyPair, err := xtls.X509KeyPair(entry.Certificate, entry.Key)
|
|
||||||
if err != nil {
|
|
||||||
newError("ignoring invalid X509 key pair").Base(err).AtWarning().WriteToLog()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
keyPair.Leaf, err = x509.ParseCertificate(keyPair.Certificate[0])
|
|
||||||
if err != nil {
|
|
||||||
newError("ignoring invalid certificate").Base(err).AtWarning().WriteToLog()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
certs = append(certs, &keyPair)
|
|
||||||
if !entry.OneTimeLoading {
|
|
||||||
var isOcspstapling bool
|
|
||||||
hotReloadInterval := uint64(3600)
|
|
||||||
if entry.OcspStapling != 0 {
|
|
||||||
hotReloadInterval = entry.OcspStapling
|
|
||||||
isOcspstapling = true
|
|
||||||
}
|
|
||||||
index := len(certs) - 1
|
|
||||||
go func(entry *Certificate, cert *xtls.Certificate, index int) {
|
|
||||||
t := time.NewTicker(time.Duration(hotReloadInterval) * time.Second)
|
|
||||||
for {
|
|
||||||
if entry.CertificatePath != "" && entry.KeyPath != "" {
|
|
||||||
newCert, err := filesystem.ReadFile(entry.CertificatePath)
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to parse certificate").Base(err).AtError().WriteToLog()
|
|
||||||
<-t.C
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newKey, err := filesystem.ReadFile(entry.KeyPath)
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to parse key").Base(err).AtError().WriteToLog()
|
|
||||||
<-t.C
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if string(newCert) != string(entry.Certificate) && string(newKey) != string(entry.Key) {
|
|
||||||
newKeyPair, err := xtls.X509KeyPair(newCert, newKey)
|
|
||||||
if err != nil {
|
|
||||||
newError("ignoring invalid X509 key pair").Base(err).AtError().WriteToLog()
|
|
||||||
<-t.C
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if newKeyPair.Leaf, err = x509.ParseCertificate(newKeyPair.Certificate[0]); err != nil {
|
|
||||||
newError("ignoring invalid certificate").Base(err).AtError().WriteToLog()
|
|
||||||
<-t.C
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
cert = &newKeyPair
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isOcspstapling {
|
|
||||||
if newOCSPData, err := ocsp.GetOCSPForCert(cert.Certificate); err != nil {
|
|
||||||
newError("ignoring invalid OCSP").Base(err).AtWarning().WriteToLog()
|
|
||||||
} else if string(newOCSPData) != string(cert.OCSPStaple) {
|
|
||||||
cert.OCSPStaple = newOCSPData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
certs[index] = cert
|
|
||||||
<-t.C
|
|
||||||
}
|
|
||||||
}(entry, certs[index], index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return certs
|
|
||||||
}
|
|
||||||
|
|
||||||
func isCertificateExpired(c *xtls.Certificate) bool {
|
|
||||||
if c.Leaf == nil && len(c.Certificate) > 0 {
|
|
||||||
if pc, err := x509.ParseCertificate(c.Certificate[0]); err == nil {
|
|
||||||
c.Leaf = pc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If leaf is not there, the certificate is probably not used yet. We trust user to provide a valid certificate.
|
|
||||||
return c.Leaf != nil && c.Leaf.NotAfter.Before(time.Now().Add(-time.Minute))
|
|
||||||
}
|
|
||||||
|
|
||||||
func issueCertificate(rawCA *Certificate, domain string) (*xtls.Certificate, error) {
|
|
||||||
parent, err := cert.ParseCertificate(rawCA.Certificate, rawCA.Key)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to parse raw certificate").Base(err)
|
|
||||||
}
|
|
||||||
newCert, err := cert.Generate(parent, cert.CommonName(domain), cert.DNSNames(domain))
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("failed to generate new certificate for ", domain).Base(err)
|
|
||||||
}
|
|
||||||
newCertPEM, newKeyPEM := newCert.ToPEM()
|
|
||||||
cert, err := xtls.X509KeyPair(newCertPEM, newKeyPEM)
|
|
||||||
return &cert, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) getCustomCA() []*Certificate {
|
|
||||||
certs := make([]*Certificate, 0, len(c.Certificate))
|
|
||||||
for _, certificate := range c.Certificate {
|
|
||||||
if certificate.Usage == Certificate_AUTHORITY_ISSUE {
|
|
||||||
certs = append(certs, certificate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return certs
|
|
||||||
}
|
|
||||||
|
|
||||||
func getGetCertificateFunc(c *xtls.Config, ca []*Certificate) func(hello *xtls.ClientHelloInfo) (*xtls.Certificate, error) {
|
|
||||||
var access sync.RWMutex
|
|
||||||
|
|
||||||
return func(hello *xtls.ClientHelloInfo) (*xtls.Certificate, error) {
|
|
||||||
domain := hello.ServerName
|
|
||||||
certExpired := false
|
|
||||||
|
|
||||||
access.RLock()
|
|
||||||
certificate, found := c.NameToCertificate[domain]
|
|
||||||
access.RUnlock()
|
|
||||||
|
|
||||||
if found {
|
|
||||||
if !isCertificateExpired(certificate) {
|
|
||||||
return certificate, nil
|
|
||||||
}
|
|
||||||
certExpired = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if certExpired {
|
|
||||||
newCerts := make([]xtls.Certificate, 0, len(c.Certificates))
|
|
||||||
|
|
||||||
access.Lock()
|
|
||||||
for _, certificate := range c.Certificates {
|
|
||||||
if !isCertificateExpired(&certificate) {
|
|
||||||
newCerts = append(newCerts, certificate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Certificates = newCerts
|
|
||||||
access.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
var issuedCertificate *xtls.Certificate
|
|
||||||
|
|
||||||
// Create a new certificate from existing CA if possible
|
|
||||||
for _, rawCert := range ca {
|
|
||||||
if rawCert.Usage == Certificate_AUTHORITY_ISSUE {
|
|
||||||
newCert, err := issueCertificate(rawCert, domain)
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to issue new certificate for ", domain).Base(err).WriteToLog()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
access.Lock()
|
|
||||||
c.Certificates = append(c.Certificates, *newCert)
|
|
||||||
issuedCertificate = &c.Certificates[len(c.Certificates)-1]
|
|
||||||
access.Unlock()
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if issuedCertificate == nil {
|
|
||||||
return nil, newError("failed to create a new certificate for ", domain)
|
|
||||||
}
|
|
||||||
|
|
||||||
access.Lock()
|
|
||||||
c.BuildNameToCertificate()
|
|
||||||
access.Unlock()
|
|
||||||
|
|
||||||
return issuedCertificate, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNewGetCertificateFunc(certs []*xtls.Certificate, rejectUnknownSNI bool) func(hello *xtls.ClientHelloInfo) (*xtls.Certificate, error) {
|
|
||||||
return func(hello *xtls.ClientHelloInfo) (*xtls.Certificate, error) {
|
|
||||||
if len(certs) == 0 {
|
|
||||||
return nil, errNoCertificates
|
|
||||||
}
|
|
||||||
sni := strings.ToLower(hello.ServerName)
|
|
||||||
if !rejectUnknownSNI && (len(certs) == 1 || sni == "") {
|
|
||||||
return certs[0], nil
|
|
||||||
}
|
|
||||||
gsni := "*"
|
|
||||||
if index := strings.IndexByte(sni, '.'); index != -1 {
|
|
||||||
gsni += sni[index:]
|
|
||||||
}
|
|
||||||
for _, keyPair := range certs {
|
|
||||||
if keyPair.Leaf.Subject.CommonName == sni || keyPair.Leaf.Subject.CommonName == gsni {
|
|
||||||
return keyPair, nil
|
|
||||||
}
|
|
||||||
for _, name := range keyPair.Leaf.DNSNames {
|
|
||||||
if name == sni || name == gsni {
|
|
||||||
return keyPair, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rejectUnknownSNI {
|
|
||||||
return nil, errNoCertificates
|
|
||||||
}
|
|
||||||
return certs[0], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) parseServerName() string {
|
|
||||||
return c.ServerName
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
|
|
||||||
if c.PinnedPeerCertificateChainSha256 != nil {
|
|
||||||
hashValue := tls.GenerateCertChainHash(rawCerts)
|
|
||||||
for _, v := range c.PinnedPeerCertificateChainSha256 {
|
|
||||||
if hmac.Equal(hashValue, v) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newError("peer cert is unrecognized: ", base64.StdEncoding.EncodeToString(hashValue))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetXTLSConfig converts this Config into xtls.Config.
|
|
||||||
func (c *Config) GetXTLSConfig(opts ...Option) *xtls.Config {
|
|
||||||
root, err := c.getCertPool()
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to load system root certificate").AtError().Base(err).WriteToLog()
|
|
||||||
}
|
|
||||||
|
|
||||||
if c == nil {
|
|
||||||
return &xtls.Config{
|
|
||||||
ClientSessionCache: globalSessionCache,
|
|
||||||
RootCAs: root,
|
|
||||||
InsecureSkipVerify: false,
|
|
||||||
NextProtos: nil,
|
|
||||||
SessionTicketsDisabled: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config := &xtls.Config{
|
|
||||||
ClientSessionCache: globalSessionCache,
|
|
||||||
RootCAs: root,
|
|
||||||
InsecureSkipVerify: c.AllowInsecure,
|
|
||||||
NextProtos: c.NextProtocol,
|
|
||||||
SessionTicketsDisabled: !c.EnableSessionResumption,
|
|
||||||
VerifyPeerCertificate: c.verifyPeerCert,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, opt := range opts {
|
|
||||||
opt(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
caCerts := c.getCustomCA()
|
|
||||||
if len(caCerts) > 0 {
|
|
||||||
config.GetCertificate = getGetCertificateFunc(config, caCerts)
|
|
||||||
} else {
|
|
||||||
config.GetCertificate = getNewGetCertificateFunc(c.BuildCertificates(), c.RejectUnknownSni)
|
|
||||||
}
|
|
||||||
|
|
||||||
if sn := c.parseServerName(); len(sn) > 0 {
|
|
||||||
config.ServerName = sn
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(config.NextProtos) == 0 {
|
|
||||||
config.NextProtos = []string{"h2", "http/1.1"}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch c.MinVersion {
|
|
||||||
case "1.0":
|
|
||||||
config.MinVersion = xtls.VersionTLS10
|
|
||||||
case "1.1":
|
|
||||||
config.MinVersion = xtls.VersionTLS11
|
|
||||||
case "1.2":
|
|
||||||
config.MinVersion = xtls.VersionTLS12
|
|
||||||
case "1.3":
|
|
||||||
config.MinVersion = xtls.VersionTLS13
|
|
||||||
}
|
|
||||||
|
|
||||||
switch c.MaxVersion {
|
|
||||||
case "1.0":
|
|
||||||
config.MaxVersion = xtls.VersionTLS10
|
|
||||||
case "1.1":
|
|
||||||
config.MaxVersion = xtls.VersionTLS11
|
|
||||||
case "1.2":
|
|
||||||
config.MaxVersion = xtls.VersionTLS12
|
|
||||||
case "1.3":
|
|
||||||
config.MaxVersion = xtls.VersionTLS13
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.CipherSuites) > 0 {
|
|
||||||
id := make(map[string]uint16)
|
|
||||||
for _, s := range xtls.CipherSuites() {
|
|
||||||
id[s.Name] = s.ID
|
|
||||||
}
|
|
||||||
for _, n := range strings.Split(c.CipherSuites, ":") {
|
|
||||||
if id[n] != 0 {
|
|
||||||
config.CipherSuites = append(config.CipherSuites, id[n])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config.PreferServerCipherSuites = c.PreferServerCipherSuites
|
|
||||||
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option for building XTLS config.
|
|
||||||
type Option func(*xtls.Config)
|
|
||||||
|
|
||||||
// WithDestination sets the server name in XTLS config.
|
|
||||||
func WithDestination(dest net.Destination) Option {
|
|
||||||
return func(config *xtls.Config) {
|
|
||||||
if dest.Address.Family().IsDomain() && config.ServerName == "" {
|
|
||||||
config.ServerName = dest.Address.Domain()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithNextProto sets the ALPN values in XTLS config.
|
|
||||||
func WithNextProto(protocol ...string) Option {
|
|
||||||
return func(config *xtls.Config) {
|
|
||||||
if len(config.NextProtos) == 0 {
|
|
||||||
config.NextProtos = protocol
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ConfigFromStreamSettings fetches Config from stream settings. Nil if not found.
|
|
||||||
func ConfigFromStreamSettings(settings *internet.MemoryStreamConfig) *Config {
|
|
||||||
if settings == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
config, ok := settings.SecuritySettings.(*Config)
|
|
||||||
if !ok {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return config
|
|
||||||
}
|
|
|
@ -1,478 +0,0 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.28.1
|
|
||||||
// protoc v3.21.12
|
|
||||||
// source: transport/internet/xtls/config.proto
|
|
||||||
|
|
||||||
package xtls
|
|
||||||
|
|
||||||
import (
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Verify that this generated code is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
|
||||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
|
||||||
)
|
|
||||||
|
|
||||||
type Certificate_Usage int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
Certificate_ENCIPHERMENT Certificate_Usage = 0
|
|
||||||
Certificate_AUTHORITY_VERIFY Certificate_Usage = 1
|
|
||||||
Certificate_AUTHORITY_ISSUE Certificate_Usage = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for Certificate_Usage.
|
|
||||||
var (
|
|
||||||
Certificate_Usage_name = map[int32]string{
|
|
||||||
0: "ENCIPHERMENT",
|
|
||||||
1: "AUTHORITY_VERIFY",
|
|
||||||
2: "AUTHORITY_ISSUE",
|
|
||||||
}
|
|
||||||
Certificate_Usage_value = map[string]int32{
|
|
||||||
"ENCIPHERMENT": 0,
|
|
||||||
"AUTHORITY_VERIFY": 1,
|
|
||||||
"AUTHORITY_ISSUE": 2,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x Certificate_Usage) Enum() *Certificate_Usage {
|
|
||||||
p := new(Certificate_Usage)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Certificate_Usage) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Certificate_Usage) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_transport_internet_xtls_config_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Certificate_Usage) Type() protoreflect.EnumType {
|
|
||||||
return &file_transport_internet_xtls_config_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Certificate_Usage) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use Certificate_Usage.Descriptor instead.
|
|
||||||
func (Certificate_Usage) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_transport_internet_xtls_config_proto_rawDescGZIP(), []int{0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Certificate struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// TLS certificate in x509 format.
|
|
||||||
Certificate []byte `protobuf:"bytes,1,opt,name=certificate,proto3" json:"certificate,omitempty"`
|
|
||||||
// TLS key in x509 format.
|
|
||||||
Key []byte `protobuf:"bytes,2,opt,name=key,proto3" json:"key,omitempty"`
|
|
||||||
Usage Certificate_Usage `protobuf:"varint,3,opt,name=usage,proto3,enum=xray.transport.internet.xtls.Certificate_Usage" json:"usage,omitempty"`
|
|
||||||
OcspStapling uint64 `protobuf:"varint,4,opt,name=ocsp_stapling,json=ocspStapling,proto3" json:"ocsp_stapling,omitempty"`
|
|
||||||
// TLS certificate path
|
|
||||||
CertificatePath string `protobuf:"bytes,5,opt,name=certificate_path,json=certificatePath,proto3" json:"certificate_path,omitempty"`
|
|
||||||
// TLS Key path
|
|
||||||
KeyPath string `protobuf:"bytes,6,opt,name=key_path,json=keyPath,proto3" json:"key_path,omitempty"`
|
|
||||||
// If true, one-Time Loading
|
|
||||||
OneTimeLoading bool `protobuf:"varint,7,opt,name=One_time_loading,json=OneTimeLoading,proto3" json:"One_time_loading,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) Reset() {
|
|
||||||
*x = Certificate{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_transport_internet_xtls_config_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Certificate) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *Certificate) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_transport_internet_xtls_config_proto_msgTypes[0]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use Certificate.ProtoReflect.Descriptor instead.
|
|
||||||
func (*Certificate) Descriptor() ([]byte, []int) {
|
|
||||||
return file_transport_internet_xtls_config_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) GetCertificate() []byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.Certificate
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) GetKey() []byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.Key
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) GetUsage() Certificate_Usage {
|
|
||||||
if x != nil {
|
|
||||||
return x.Usage
|
|
||||||
}
|
|
||||||
return Certificate_ENCIPHERMENT
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) GetOcspStapling() uint64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.OcspStapling
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) GetCertificatePath() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.CertificatePath
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) GetKeyPath() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.KeyPath
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Certificate) GetOneTimeLoading() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.OneTimeLoading
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// Whether or not to allow self-signed certificates.
|
|
||||||
AllowInsecure bool `protobuf:"varint,1,opt,name=allow_insecure,json=allowInsecure,proto3" json:"allow_insecure,omitempty"`
|
|
||||||
// List of certificates to be served on server.
|
|
||||||
Certificate []*Certificate `protobuf:"bytes,2,rep,name=certificate,proto3" json:"certificate,omitempty"`
|
|
||||||
// Override server name.
|
|
||||||
ServerName string `protobuf:"bytes,3,opt,name=server_name,json=serverName,proto3" json:"server_name,omitempty"`
|
|
||||||
// Lists of string as ALPN values.
|
|
||||||
NextProtocol []string `protobuf:"bytes,4,rep,name=next_protocol,json=nextProtocol,proto3" json:"next_protocol,omitempty"`
|
|
||||||
// Whether or not to enable session (ticket) resumption.
|
|
||||||
EnableSessionResumption bool `protobuf:"varint,5,opt,name=enable_session_resumption,json=enableSessionResumption,proto3" json:"enable_session_resumption,omitempty"`
|
|
||||||
// If true, root certificates on the system will not be loaded for
|
|
||||||
// verification.
|
|
||||||
DisableSystemRoot bool `protobuf:"varint,6,opt,name=disable_system_root,json=disableSystemRoot,proto3" json:"disable_system_root,omitempty"`
|
|
||||||
// The minimum TLS version.
|
|
||||||
MinVersion string `protobuf:"bytes,7,opt,name=min_version,json=minVersion,proto3" json:"min_version,omitempty"`
|
|
||||||
// The maximum TLS version.
|
|
||||||
MaxVersion string `protobuf:"bytes,8,opt,name=max_version,json=maxVersion,proto3" json:"max_version,omitempty"`
|
|
||||||
// Specify cipher suites, except for TLS 1.3.
|
|
||||||
CipherSuites string `protobuf:"bytes,9,opt,name=cipher_suites,json=cipherSuites,proto3" json:"cipher_suites,omitempty"`
|
|
||||||
// Whether the server selects its most preferred ciphersuite.
|
|
||||||
PreferServerCipherSuites bool `protobuf:"varint,10,opt,name=prefer_server_cipher_suites,json=preferServerCipherSuites,proto3" json:"prefer_server_cipher_suites,omitempty"`
|
|
||||||
RejectUnknownSni bool `protobuf:"varint,12,opt,name=reject_unknown_sni,json=rejectUnknownSni,proto3" json:"reject_unknown_sni,omitempty"`
|
|
||||||
// @Document A pinned certificate chain sha256 hash.
|
|
||||||
// @Document If the server's hash does not match this value, the connection will be aborted.
|
|
||||||
// @Document This value replace allow_insecure.
|
|
||||||
// @Critical
|
|
||||||
PinnedPeerCertificateChainSha256 [][]byte `protobuf:"bytes,13,rep,name=pinned_peer_certificate_chain_sha256,json=pinnedPeerCertificateChainSha256,proto3" json:"pinned_peer_certificate_chain_sha256,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
|
||||||
*x = Config{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_transport_internet_xtls_config_proto_msgTypes[1]
|
|
||||||
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_xtls_config_proto_msgTypes[1]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
|
||||||
func (*Config) Descriptor() ([]byte, []int) {
|
|
||||||
return file_transport_internet_xtls_config_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetAllowInsecure() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.AllowInsecure
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetCertificate() []*Certificate {
|
|
||||||
if x != nil {
|
|
||||||
return x.Certificate
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetServerName() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.ServerName
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetNextProtocol() []string {
|
|
||||||
if x != nil {
|
|
||||||
return x.NextProtocol
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetEnableSessionResumption() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.EnableSessionResumption
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetDisableSystemRoot() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.DisableSystemRoot
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetMinVersion() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.MinVersion
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetMaxVersion() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.MaxVersion
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetCipherSuites() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.CipherSuites
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetPreferServerCipherSuites() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.PreferServerCipherSuites
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetRejectUnknownSni() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.RejectUnknownSni
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetPinnedPeerCertificateChainSha256() [][]byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.PinnedPeerCertificateChainSha256
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_transport_internet_xtls_config_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_transport_internet_xtls_config_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x24, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
|
||||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
|
||||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
|
||||||
0x78, 0x74, 0x6c, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
|
||||||
0x63, 0x61, 0x74, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
|
||||||
0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69,
|
|
||||||
0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20,
|
|
||||||
0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x45, 0x0a, 0x05, 0x75, 0x73, 0x61, 0x67,
|
|
||||||
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
|
|
||||||
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
|
||||||
0x74, 0x2e, 0x78, 0x74, 0x6c, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
|
||||||
0x74, 0x65, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x05, 0x75, 0x73, 0x61, 0x67, 0x65, 0x12,
|
|
||||||
0x23, 0x0a, 0x0d, 0x6f, 0x63, 0x73, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x70, 0x6c, 0x69, 0x6e, 0x67,
|
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x6f, 0x63, 0x73, 0x70, 0x53, 0x74, 0x61, 0x70,
|
|
||||||
0x6c, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
|
|
||||||
0x61, 0x74, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f,
|
|
||||||
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12,
|
|
||||||
0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x50, 0x61, 0x74, 0x68, 0x12, 0x28, 0x0a, 0x10, 0x4f, 0x6e,
|
|
||||||
0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x07,
|
|
||||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x4f, 0x6e, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x4c, 0x6f, 0x61,
|
|
||||||
0x64, 0x69, 0x6e, 0x67, 0x22, 0x44, 0x0a, 0x05, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a,
|
|
||||||
0x0c, 0x45, 0x4e, 0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12,
|
|
||||||
0x14, 0x0a, 0x10, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x56, 0x45, 0x52,
|
|
||||||
0x49, 0x46, 0x59, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49,
|
|
||||||
0x54, 0x59, 0x5f, 0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xd2, 0x04, 0x0a, 0x06, 0x43,
|
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69,
|
|
||||||
0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61,
|
|
||||||
0x6c, 0x6c, 0x6f, 0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4b, 0x0a, 0x0b,
|
|
||||||
0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
|
|
||||||
0x0b, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
|
||||||
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x78, 0x74, 0x6c, 0x73,
|
|
||||||
0x2e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x0b, 0x63, 0x65,
|
|
||||||
0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x72,
|
|
||||||
0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
|
|
||||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6e, 0x65,
|
|
||||||
0x78, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x03, 0x28,
|
|
||||||
0x09, 0x52, 0x0c, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12,
|
|
||||||
0x3a, 0x0a, 0x19, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
|
||||||
0x6e, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
|
|
||||||
0x28, 0x08, 0x52, 0x17, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f,
|
|
||||||
0x6e, 0x52, 0x65, 0x73, 0x75, 0x6d, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x13, 0x64,
|
|
||||||
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x72, 0x6f,
|
|
||||||
0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
|
||||||
0x65, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6d,
|
|
||||||
0x69, 0x6e, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
|
|
||||||
0x52, 0x0a, 0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b,
|
|
||||||
0x6d, 0x61, 0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x0a,
|
|
||||||
0x0d, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x09,
|
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74,
|
|
||||||
0x65, 0x73, 0x12, 0x3d, 0x0a, 0x1b, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72,
|
|
||||||
0x76, 0x65, 0x72, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65,
|
|
||||||
0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x18, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x53,
|
|
||||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65,
|
|
||||||
0x73, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x6e, 0x6b, 0x6e,
|
|
||||||
0x6f, 0x77, 0x6e, 0x5f, 0x73, 0x6e, 0x69, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x72,
|
|
||||||
0x65, 0x6a, 0x65, 0x63, 0x74, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x53, 0x6e, 0x69, 0x12,
|
|
||||||
0x4e, 0x0a, 0x24, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63,
|
|
||||||
0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e,
|
|
||||||
0x5f, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x20, 0x70,
|
|
||||||
0x69, 0x6e, 0x6e, 0x65, 0x64, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69,
|
|
||||||
0x63, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x42,
|
|
||||||
0x76, 0x0a, 0x20, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
|
||||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x78,
|
|
||||||
0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
|
||||||
0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65,
|
|
||||||
0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
|
||||||
0x6e, 0x65, 0x74, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1c, 0x58, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
|
||||||
0x65, 0x74, 0x2e, 0x58, 0x74, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_transport_internet_xtls_config_proto_rawDescOnce sync.Once
|
|
||||||
file_transport_internet_xtls_config_proto_rawDescData = file_transport_internet_xtls_config_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_transport_internet_xtls_config_proto_rawDescGZIP() []byte {
|
|
||||||
file_transport_internet_xtls_config_proto_rawDescOnce.Do(func() {
|
|
||||||
file_transport_internet_xtls_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_xtls_config_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_transport_internet_xtls_config_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_transport_internet_xtls_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
|
||||||
var file_transport_internet_xtls_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
|
||||||
var file_transport_internet_xtls_config_proto_goTypes = []interface{}{
|
|
||||||
(Certificate_Usage)(0), // 0: xray.transport.internet.xtls.Certificate.Usage
|
|
||||||
(*Certificate)(nil), // 1: xray.transport.internet.xtls.Certificate
|
|
||||||
(*Config)(nil), // 2: xray.transport.internet.xtls.Config
|
|
||||||
}
|
|
||||||
var file_transport_internet_xtls_config_proto_depIdxs = []int32{
|
|
||||||
0, // 0: xray.transport.internet.xtls.Certificate.usage:type_name -> xray.transport.internet.xtls.Certificate.Usage
|
|
||||||
1, // 1: xray.transport.internet.xtls.Config.certificate:type_name -> xray.transport.internet.xtls.Certificate
|
|
||||||
2, // [2:2] is the sub-list for method output_type
|
|
||||||
2, // [2:2] is the sub-list for method input_type
|
|
||||||
2, // [2:2] is the sub-list for extension type_name
|
|
||||||
2, // [2:2] is the sub-list for extension extendee
|
|
||||||
0, // [0:2] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_transport_internet_xtls_config_proto_init() }
|
|
||||||
func file_transport_internet_xtls_config_proto_init() {
|
|
||||||
if File_transport_internet_xtls_config_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_transport_internet_xtls_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Certificate); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_transport_internet_xtls_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*Config); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
type x struct{}
|
|
||||||
out := protoimpl.TypeBuilder{
|
|
||||||
File: protoimpl.DescBuilder{
|
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
||||||
RawDescriptor: file_transport_internet_xtls_config_proto_rawDesc,
|
|
||||||
NumEnums: 1,
|
|
||||||
NumMessages: 2,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 0,
|
|
||||||
},
|
|
||||||
GoTypes: file_transport_internet_xtls_config_proto_goTypes,
|
|
||||||
DependencyIndexes: file_transport_internet_xtls_config_proto_depIdxs,
|
|
||||||
EnumInfos: file_transport_internet_xtls_config_proto_enumTypes,
|
|
||||||
MessageInfos: file_transport_internet_xtls_config_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_transport_internet_xtls_config_proto = out.File
|
|
||||||
file_transport_internet_xtls_config_proto_rawDesc = nil
|
|
||||||
file_transport_internet_xtls_config_proto_goTypes = nil
|
|
||||||
file_transport_internet_xtls_config_proto_depIdxs = nil
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package xray.transport.internet.xtls;
|
|
||||||
option csharp_namespace = "Xray.Transport.Internet.Xtls";
|
|
||||||
option go_package = "github.com/xtls/xray-core/transport/internet/xtls";
|
|
||||||
option java_package = "com.xray.transport.internet.xtls";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
|
|
||||||
message Certificate {
|
|
||||||
// TLS certificate in x509 format.
|
|
||||||
bytes certificate = 1;
|
|
||||||
|
|
||||||
// TLS key in x509 format.
|
|
||||||
bytes key = 2;
|
|
||||||
|
|
||||||
enum Usage {
|
|
||||||
ENCIPHERMENT = 0;
|
|
||||||
AUTHORITY_VERIFY = 1;
|
|
||||||
AUTHORITY_ISSUE = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
Usage usage = 3;
|
|
||||||
|
|
||||||
uint64 ocsp_stapling = 4;
|
|
||||||
|
|
||||||
// TLS certificate path
|
|
||||||
string certificate_path = 5;
|
|
||||||
|
|
||||||
// TLS Key path
|
|
||||||
string key_path = 6;
|
|
||||||
|
|
||||||
// If true, one-Time Loading
|
|
||||||
bool One_time_loading = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Config {
|
|
||||||
// Whether or not to allow self-signed certificates.
|
|
||||||
bool allow_insecure = 1;
|
|
||||||
|
|
||||||
// List of certificates to be served on server.
|
|
||||||
repeated Certificate certificate = 2;
|
|
||||||
|
|
||||||
// Override server name.
|
|
||||||
string server_name = 3;
|
|
||||||
|
|
||||||
// Lists of string as ALPN values.
|
|
||||||
repeated string next_protocol = 4;
|
|
||||||
|
|
||||||
// Whether or not to enable session (ticket) resumption.
|
|
||||||
bool enable_session_resumption = 5;
|
|
||||||
|
|
||||||
// If true, root certificates on the system will not be loaded for
|
|
||||||
// verification.
|
|
||||||
bool disable_system_root = 6;
|
|
||||||
|
|
||||||
// The minimum TLS version.
|
|
||||||
string min_version = 7;
|
|
||||||
|
|
||||||
// The maximum TLS version.
|
|
||||||
string max_version = 8;
|
|
||||||
|
|
||||||
// Specify cipher suites, except for TLS 1.3.
|
|
||||||
string cipher_suites = 9;
|
|
||||||
|
|
||||||
// Whether the server selects its most preferred ciphersuite.
|
|
||||||
bool prefer_server_cipher_suites = 10;
|
|
||||||
|
|
||||||
bool reject_unknown_sni = 12;
|
|
||||||
|
|
||||||
/* @Document A pinned certificate chain sha256 hash.
|
|
||||||
@Document If the server's hash does not match this value, the connection will be aborted.
|
|
||||||
@Document This value replace allow_insecure.
|
|
||||||
@Critical
|
|
||||||
*/
|
|
||||||
repeated bytes pinned_peer_certificate_chain_sha256 = 13;
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
//go:build !windows
|
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package xtls
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/x509"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type rootCertsCache struct {
|
|
||||||
sync.Mutex
|
|
||||||
pool *x509.CertPool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *rootCertsCache) load() (*x509.CertPool, error) {
|
|
||||||
c.Lock()
|
|
||||||
defer c.Unlock()
|
|
||||||
|
|
||||||
if c.pool != nil {
|
|
||||||
return c.pool, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
pool, err := x509.SystemCertPool()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
c.pool = pool
|
|
||||||
return pool, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var rootCerts rootCertsCache
|
|
||||||
|
|
||||||
func (c *Config) getCertPool() (*x509.CertPool, error) {
|
|
||||||
if c.DisableSystemRoot {
|
|
||||||
return c.loadSelfCertPool()
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.Certificate) == 0 {
|
|
||||||
return rootCerts.load()
|
|
||||||
}
|
|
||||||
|
|
||||||
pool, err := x509.SystemCertPool()
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("system root").AtWarning().Base(err)
|
|
||||||
}
|
|
||||||
for _, cert := range c.Certificate {
|
|
||||||
if !pool.AppendCertsFromPEM(cert.Certificate) {
|
|
||||||
return nil, newError("append cert to root").AtWarning().Base(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pool, err
|
|
||||||
}
|
|
|
@ -1,97 +0,0 @@
|
||||||
package xtls_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/x509"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
xtls "github.com/xtls/go"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/protocol/tls/cert"
|
|
||||||
. "github.com/xtls/xray-core/transport/internet/xtls"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCertificateIssuing(t *testing.T) {
|
|
||||||
certificate := ParseCertificate(cert.MustGenerate(nil, cert.Authority(true), cert.KeyUsage(x509.KeyUsageCertSign)))
|
|
||||||
certificate.Usage = Certificate_AUTHORITY_ISSUE
|
|
||||||
|
|
||||||
c := &Config{
|
|
||||||
Certificate: []*Certificate{
|
|
||||||
certificate,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
xtlsConfig := c.GetXTLSConfig()
|
|
||||||
xrayCert, err := xtlsConfig.GetCertificate(&xtls.ClientHelloInfo{
|
|
||||||
ServerName: "www.example.com",
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
x509Cert, err := x509.ParseCertificate(xrayCert.Certificate[0])
|
|
||||||
common.Must(err)
|
|
||||||
if !x509Cert.NotAfter.After(time.Now()) {
|
|
||||||
t.Error("NotAfter: ", x509Cert.NotAfter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExpiredCertificate(t *testing.T) {
|
|
||||||
caCert := cert.MustGenerate(nil, cert.Authority(true), cert.KeyUsage(x509.KeyUsageCertSign))
|
|
||||||
expiredCert := cert.MustGenerate(caCert, cert.NotAfter(time.Now().Add(time.Minute*-2)), cert.CommonName("www.example.com"), cert.DNSNames("www.example.com"))
|
|
||||||
|
|
||||||
certificate := ParseCertificate(caCert)
|
|
||||||
certificate.Usage = Certificate_AUTHORITY_ISSUE
|
|
||||||
|
|
||||||
certificate2 := ParseCertificate(expiredCert)
|
|
||||||
|
|
||||||
c := &Config{
|
|
||||||
Certificate: []*Certificate{
|
|
||||||
certificate,
|
|
||||||
certificate2,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
xtlsConfig := c.GetXTLSConfig()
|
|
||||||
xrayCert, err := xtlsConfig.GetCertificate(&xtls.ClientHelloInfo{
|
|
||||||
ServerName: "www.example.com",
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
x509Cert, err := x509.ParseCertificate(xrayCert.Certificate[0])
|
|
||||||
common.Must(err)
|
|
||||||
if !x509Cert.NotAfter.After(time.Now()) {
|
|
||||||
t.Error("NotAfter: ", x509Cert.NotAfter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestInsecureCertificates(t *testing.T) {
|
|
||||||
c := &Config{}
|
|
||||||
|
|
||||||
xtlsConfig := c.GetXTLSConfig()
|
|
||||||
if len(xtlsConfig.CipherSuites) > 0 {
|
|
||||||
t.Fatal("Unexpected tls cipher suites list: ", xtlsConfig.CipherSuites)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkCertificateIssuing(b *testing.B) {
|
|
||||||
certificate := ParseCertificate(cert.MustGenerate(nil, cert.Authority(true), cert.KeyUsage(x509.KeyUsageCertSign)))
|
|
||||||
certificate.Usage = Certificate_AUTHORITY_ISSUE
|
|
||||||
|
|
||||||
c := &Config{
|
|
||||||
Certificate: []*Certificate{
|
|
||||||
certificate,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
xtlsConfig := c.GetXTLSConfig()
|
|
||||||
lenCerts := len(xtlsConfig.Certificates)
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_, _ = xtlsConfig.GetCertificate(&xtls.ClientHelloInfo{
|
|
||||||
ServerName: "www.example.com",
|
|
||||||
})
|
|
||||||
delete(xtlsConfig.NameToCertificate, "www.example.com")
|
|
||||||
xtlsConfig.Certificates = xtlsConfig.Certificates[:lenCerts]
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
//go:build windows
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package xtls
|
|
||||||
|
|
||||||
import "crypto/x509"
|
|
||||||
|
|
||||||
func (c *Config) getCertPool() (*x509.CertPool, error) {
|
|
||||||
if c.DisableSystemRoot {
|
|
||||||
return c.loadSelfCertPool()
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package xtls
|
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
|
||||||
|
|
||||||
type errPathObjHolder struct{}
|
|
||||||
|
|
||||||
func newError(values ...interface{}) *errors.Error {
|
|
||||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
package xtls
|
|
||||||
|
|
||||||
import _ "unsafe"
|
|
||||||
|
|
||||||
//go:linkname errNoCertificates github.com/xtls/go.errNoCertificates
|
|
||||||
var errNoCertificates error
|
|
|
@ -1,35 +0,0 @@
|
||||||
package xtls
|
|
||||||
|
|
||||||
import (
|
|
||||||
xtls "github.com/xtls/go"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
|
||||||
|
|
||||||
type Conn struct {
|
|
||||||
*xtls.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Conn) HandshakeAddress() net.Address {
|
|
||||||
if err := c.Handshake(); err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
state := c.ConnectionState()
|
|
||||||
if state.ServerName == "" {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return net.ParseAddress(state.ServerName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Client initiates a XTLS client handshake on the given connection.
|
|
||||||
func Client(c net.Conn, config *xtls.Config) net.Conn {
|
|
||||||
xtlsConn := xtls.Client(c, config)
|
|
||||||
return &Conn{Conn: xtlsConn}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server initiates a XTLS server handshake on the given connection.
|
|
||||||
func Server(c net.Conn, config *xtls.Config) net.Conn {
|
|
||||||
xtlsConn := xtls.Server(c, config)
|
|
||||||
return &Conn{Conn: xtlsConn}
|
|
||||||
}
|
|
Loading…
Reference in New Issue