mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-24 02:26:48 +08:00
Compare commits
4 Commits
v1.8.0
...
dev-shadow
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3b8f09153e | ||
![]() |
0188c2d67d | ||
![]() |
6fb673aee4 | ||
![]() |
d6c2a9aab7 |
73
.github/workflows/release.yml
vendored
73
.github/workflows/release.yml
vendored
@@ -20,51 +20,7 @@ on:
|
|||||||
- "go.sum"
|
- "go.sum"
|
||||||
- ".github/workflows/*.yml"
|
- ".github/workflows/*.yml"
|
||||||
jobs:
|
jobs:
|
||||||
prepare:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Restore Cache
|
|
||||||
uses: actions/cache/restore@v3
|
|
||||||
with:
|
|
||||||
path: resources
|
|
||||||
key: xray-geodat-
|
|
||||||
|
|
||||||
- name: Update Geodat
|
|
||||||
id: update
|
|
||||||
uses: nick-fields/retry@v2
|
|
||||||
with:
|
|
||||||
timeout_minutes: 60
|
|
||||||
retry_wait_seconds: 60
|
|
||||||
max_attempts: 60
|
|
||||||
command: |
|
|
||||||
[ -d 'resources' ] || mkdir resources
|
|
||||||
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite')
|
|
||||||
for i in "${LIST[@]}"
|
|
||||||
do
|
|
||||||
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3}'))
|
|
||||||
FILE_NAME="${INFO[2]}.dat"
|
|
||||||
echo -e "Verifying HASH key..."
|
|
||||||
HASH="$(curl -sL "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
|
|
||||||
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
|
|
||||||
continue
|
|
||||||
else
|
|
||||||
echo -e "Downloading https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat..."
|
|
||||||
curl -L "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat" -o ./resources/${FILE_NAME}
|
|
||||||
echo -e "Verifying HASH key..."
|
|
||||||
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
|
|
||||||
echo "unhit=true" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Save Cache
|
|
||||||
uses: actions/cache/save@v3
|
|
||||||
if: ${{ steps.update.outputs.unhit }}
|
|
||||||
with:
|
|
||||||
path: resources
|
|
||||||
key: xray-geodat-${{ github.sha }}-${{ github.run_number }}
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: prepare
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
strategy:
|
strategy:
|
||||||
@@ -204,17 +160,26 @@ jobs:
|
|||||||
cd ./build_assets || exit 1
|
cd ./build_assets || exit 1
|
||||||
mv xray xray.exe
|
mv xray xray.exe
|
||||||
|
|
||||||
- name: Restore Cache
|
- name: Prepare to release
|
||||||
uses: actions/cache/restore@v3
|
uses: nick-fields/retry@v2
|
||||||
with:
|
with:
|
||||||
path: resources
|
timeout_minutes: 60
|
||||||
key: xray-geodat-
|
retry_wait_seconds: 60
|
||||||
|
max_attempts: 60
|
||||||
- name: Copy README.md & LICENSE
|
command: |
|
||||||
run: |
|
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
|
||||||
mv -f resources/* build_assets
|
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
|
||||||
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
|
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite')
|
||||||
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
|
for i in "${LIST[@]}"
|
||||||
|
do
|
||||||
|
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3}'))
|
||||||
|
FILE_NAME="${INFO[2]}.dat"
|
||||||
|
echo -e "Downloading https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat..."
|
||||||
|
curl -L "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat" -o ./build_assets/${FILE_NAME}
|
||||||
|
echo -e "Verifying HASH key..."
|
||||||
|
HASH="$(curl -sL "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
|
||||||
|
[ "$(sha256sum "./build_assets/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
|
||||||
|
done
|
||||||
|
|
||||||
- name: Create ZIP archive
|
- name: Create ZIP archive
|
||||||
shell: bash
|
shell: bash
|
||||||
|
19
.github/workflows/test.yml
vendored
19
.github/workflows/test.yml
vendored
@@ -34,11 +34,18 @@ jobs:
|
|||||||
check-latest: true
|
check-latest: true
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
- name: Restore Cache
|
|
||||||
uses: actions/cache/restore@v3
|
- name: Prepare geo*dat
|
||||||
with:
|
if: ${{ matrix.os != 'windows-latest' }}
|
||||||
path: resources
|
run: |
|
||||||
key: xray-geodat-
|
mkdir resources
|
||||||
enableCrossOsArchive: true
|
wget -O ./resources/geoip.dat https://github.com/v2fly/geoip/releases/latest/download/geoip.dat
|
||||||
|
wget -O ./resources/geosite.dat https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat
|
||||||
|
- name: Prepare geo*dat for Windows
|
||||||
|
if: ${{ matrix.os == 'windows-latest' }}
|
||||||
|
run: |
|
||||||
|
mkdir resources
|
||||||
|
Invoke-WebRequest -Uri "https://github.com/v2fly/geoip/releases/latest/download/geoip.dat" -OutFile "./resources/geoip.dat"
|
||||||
|
Invoke-WebRequest -Uri "https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat" -OutFile "./resources/geosite.dat"
|
||||||
- name: Test
|
- name: Test
|
||||||
run: go test -timeout 1h -v ./...
|
run: go test -timeout 1h -v ./...
|
||||||
|
46
common/singbridge/destination.go
Normal file
46
common/singbridge/destination.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package singbridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ToNetwork(network string) net.Network {
|
||||||
|
switch N.NetworkName(network) {
|
||||||
|
case N.NetworkTCP:
|
||||||
|
return net.Network_TCP
|
||||||
|
case N.NetworkUDP:
|
||||||
|
return net.Network_UDP
|
||||||
|
default:
|
||||||
|
return net.Network_Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToDestination(socksaddr M.Socksaddr, network net.Network) net.Destination {
|
||||||
|
if socksaddr.IsFqdn() {
|
||||||
|
return net.Destination{
|
||||||
|
Network: network,
|
||||||
|
Address: net.DomainAddress(socksaddr.Fqdn),
|
||||||
|
Port: net.Port(socksaddr.Port),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return net.Destination{
|
||||||
|
Network: network,
|
||||||
|
Address: net.IPAddress(socksaddr.Addr.AsSlice()),
|
||||||
|
Port: net.Port(socksaddr.Port),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToSocksaddr(destination net.Destination) M.Socksaddr {
|
||||||
|
var addr M.Socksaddr
|
||||||
|
switch destination.Address.Family() {
|
||||||
|
case net.AddressFamilyDomain:
|
||||||
|
addr.Fqdn = destination.Address.Domain()
|
||||||
|
default:
|
||||||
|
addr.Addr = M.AddrFromIP(destination.Address.IP())
|
||||||
|
}
|
||||||
|
addr.Port = uint16(destination.Port)
|
||||||
|
return addr
|
||||||
|
}
|
29
common/singbridge/dialer.go
Normal file
29
common/singbridge/dialer.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package singbridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ N.Dialer = (*XrayDialer)(nil)
|
||||||
|
|
||||||
|
type XrayDialer struct {
|
||||||
|
internet.Dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDialer(dialer internet.Dialer) *XrayDialer {
|
||||||
|
return &XrayDialer{dialer}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *XrayDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
return d.Dialer.Dial(ctx, ToDestination(destination, ToNetwork(network)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *XrayDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
43
common/singbridge/dialer_tls.go
Normal file
43
common/singbridge/dialer_tls.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
package singbridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
gotls "crypto/tls"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
|
)
|
||||||
|
|
||||||
|
type XrayTLSDialer struct {
|
||||||
|
dialer internet.Dialer
|
||||||
|
clientFunc tls.CustomClientFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTLSDialer(dialer internet.Dialer, clientFunc tls.CustomClientFunc) *XrayTLSDialer {
|
||||||
|
return &XrayTLSDialer{dialer, clientFunc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *XrayTLSDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
var internetTLSConfig *tls.Config
|
||||||
|
var tlsConfig *gotls.Config
|
||||||
|
conn, err := d.dialer.Dial(tls.ContextWithCustomClient(ctx, func(conn net.Conn, xrayConfig *tls.Config, config *gotls.Config) net.Conn {
|
||||||
|
internetTLSConfig = xrayConfig
|
||||||
|
tlsConfig = config
|
||||||
|
return conn
|
||||||
|
}), ToDestination(destination, ToNetwork(network)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if tlsConfig == nil {
|
||||||
|
return nil, E.New("missing TLS config")
|
||||||
|
}
|
||||||
|
return d.clientFunc(conn, internetTLSConfig, tlsConfig), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *XrayTLSDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
10
common/singbridge/error.go
Normal file
10
common/singbridge/error.go
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
package singbridge
|
||||||
|
|
||||||
|
import E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
|
||||||
|
func ReturnError(err error) error {
|
||||||
|
if E.IsClosed(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
70
common/singbridge/logger.go
Normal file
70
common/singbridge/logger.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package singbridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/logger"
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ logger.ContextLogger = (*XrayLogger)(nil)
|
||||||
|
|
||||||
|
type XrayLogger struct {
|
||||||
|
newError func(values ...any) *errors.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogger(newErrorFunc func(values ...any) *errors.Error) *XrayLogger {
|
||||||
|
return &XrayLogger{
|
||||||
|
newErrorFunc,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) Trace(args ...any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) Debug(args ...any) {
|
||||||
|
l.newError(args...).AtDebug().WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) Info(args ...any) {
|
||||||
|
l.newError(args...).AtInfo().WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) Warn(args ...any) {
|
||||||
|
l.newError(args...).AtWarning().WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) Error(args ...any) {
|
||||||
|
l.newError(args...).AtError().WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) Fatal(args ...any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) Panic(args ...any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) TraceContext(ctx context.Context, args ...any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) DebugContext(ctx context.Context, args ...any) {
|
||||||
|
l.newError(args...).AtDebug().WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) InfoContext(ctx context.Context, args ...any) {
|
||||||
|
l.newError(args...).AtInfo().WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) WarnContext(ctx context.Context, args ...any) {
|
||||||
|
l.newError(args...).AtWarning().WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) ErrorContext(ctx context.Context, args ...any) {
|
||||||
|
l.newError(args...).AtError().WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) FatalContext(ctx context.Context, args ...any) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *XrayLogger) PanicContext(ctx context.Context, args ...any) {
|
||||||
|
}
|
61
common/singbridge/pipe.go
Normal file
61
common/singbridge/pipe.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package singbridge
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/bufio"
|
||||||
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/transport"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CopyConn(ctx context.Context, inboundConn net.Conn, link *transport.Link, serverConn net.Conn) error {
|
||||||
|
conn := &PipeConnWrapper{
|
||||||
|
W: link.Writer,
|
||||||
|
Conn: inboundConn,
|
||||||
|
}
|
||||||
|
if ir, ok := link.Reader.(io.Reader); ok {
|
||||||
|
conn.R = ir
|
||||||
|
} else {
|
||||||
|
conn.R = &buf.BufferedReader{Reader: link.Reader}
|
||||||
|
}
|
||||||
|
return ReturnError(bufio.CopyConn(ctx, conn, serverConn))
|
||||||
|
}
|
||||||
|
|
||||||
|
type PipeConnWrapper struct {
|
||||||
|
R io.Reader
|
||||||
|
W buf.Writer
|
||||||
|
net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PipeConnWrapper) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PipeConnWrapper) Read(b []byte) (n int, err error) {
|
||||||
|
return w.R.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PipeConnWrapper) Write(p []byte) (n int, err error) {
|
||||||
|
n = len(p)
|
||||||
|
var mb buf.MultiBuffer
|
||||||
|
pLen := len(p)
|
||||||
|
for pLen > 0 {
|
||||||
|
buffer := buf.New()
|
||||||
|
if pLen > buf.Size {
|
||||||
|
_, err = buffer.Write(p[:buf.Size])
|
||||||
|
p = p[buf.Size:]
|
||||||
|
} else {
|
||||||
|
buffer.Write(p)
|
||||||
|
}
|
||||||
|
pLen -= int(buffer.Len())
|
||||||
|
mb = append(mb, buffer)
|
||||||
|
}
|
||||||
|
err = w.W.WriteMultiBuffer(mb)
|
||||||
|
if err != nil {
|
||||||
|
n = 0
|
||||||
|
buf.ReleaseMulti(mb)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
@@ -20,8 +20,8 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
Version_x byte = 1
|
Version_x byte = 1
|
||||||
Version_y byte = 8
|
Version_y byte = 7
|
||||||
Version_z byte = 0
|
Version_z byte = 5
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
52
go.mod
52
go.mod
@@ -5,28 +5,31 @@ go 1.20
|
|||||||
require (
|
require (
|
||||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/golang/protobuf v1.5.3
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/google/go-cmp v0.5.9
|
github.com/google/go-cmp v0.5.9
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/miekg/dns v1.1.51
|
github.com/miekg/dns v1.1.50
|
||||||
github.com/pelletier/go-toml v1.9.5
|
github.com/pelletier/go-toml v1.9.5
|
||||||
github.com/pires/go-proxyproto v0.6.2
|
github.com/pires/go-proxyproto v0.6.2
|
||||||
github.com/quic-go/quic-go v0.33.0
|
github.com/quic-go/quic-go v0.32.0
|
||||||
github.com/refraction-networking/utls v1.2.3-0.20230308205431-4f1df6c200db
|
github.com/refraction-networking/utls v1.2.2
|
||||||
github.com/sagernet/sing v0.1.7
|
github.com/sagernet/sing v0.1.6
|
||||||
github.com/sagernet/sing-shadowsocks v0.1.1
|
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7
|
||||||
|
github.com/sagernet/sing-shadowtls v0.0.0-20230221123345-78e50cd7b587
|
||||||
|
github.com/sagernet/utls v0.0.0-20230220130002-c08891932056
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c
|
||||||
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.1
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||||
github.com/xtls/reality v0.0.0-20230309125256-0d0713b108c8
|
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3
|
||||||
go.starlark.net v0.0.0-20230302034142-4b1e35fe2254
|
github.com/xtls/reality v0.0.0-20230217102704-085bdf2104d3
|
||||||
golang.org/x/crypto v0.7.0
|
go.starlark.net v0.0.0-20230128213706-3f75dec8e403
|
||||||
golang.org/x/net v0.8.0
|
golang.org/x/crypto v0.6.0
|
||||||
|
golang.org/x/net v0.7.0
|
||||||
golang.org/x/sync v0.1.0
|
golang.org/x/sync v0.1.0
|
||||||
golang.org/x/sys v0.6.0
|
golang.org/x/sys v0.5.0
|
||||||
google.golang.org/grpc v1.53.0
|
google.golang.org/grpc v1.53.0
|
||||||
google.golang.org/protobuf v1.29.0
|
google.golang.org/protobuf v1.28.1
|
||||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
||||||
h12.io/socks v1.0.3
|
h12.io/socks v1.0.3
|
||||||
)
|
)
|
||||||
@@ -38,21 +41,22 @@ require (
|
|||||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||||
github.com/google/btree v1.1.2 // indirect
|
github.com/google/btree v1.1.2 // indirect
|
||||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 // indirect
|
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
|
||||||
github.com/klauspost/compress v1.16.0 // indirect
|
github.com/klauspost/compress v1.15.15 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.9.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.8.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-19 v0.2.1 // indirect
|
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.1.1 // indirect
|
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
|
||||||
|
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833 // indirect
|
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect
|
||||||
golang.org/x/mod v0.9.0 // indirect
|
golang.org/x/mod v0.8.0 // indirect
|
||||||
golang.org/x/text v0.8.0 // indirect
|
golang.org/x/text v0.7.0 // indirect
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.7.0 // indirect
|
golang.org/x/tools v0.6.0 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
lukechampine.com/blake3 v1.1.7 // indirect
|
lukechampine.com/blake3 v1.1.7 // indirect
|
||||||
|
128
go.sum
128
go.sum
@@ -58,8 +58,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
|||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
@@ -76,8 +76,8 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u
|
|||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10 h1:CqYfpuYIjnlNxM3msdyPRKabhXZWbKjf3Q8BWROFBso=
|
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U=
|
||||||
github.com/google/pprof v0.0.0-20230228050547-1710fef4ab10/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
|
github.com/google/pprof v0.0.0-20230207041349-798e818bf904/go.mod h1:uglQLonpP8qtYCYyzA+8c/9qtqgA3qsXGYqCPKARAFg=
|
||||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
@@ -91,11 +91,11 @@ github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0
|
|||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
|
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
||||||
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
@@ -106,15 +106,15 @@ github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm
|
|||||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
github.com/miekg/dns v1.1.51 h1:0+Xg7vObnhrz/4ZCZcZh7zPXlmU0aveS2HDBd0m0qSo=
|
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||||
github.com/miekg/dns v1.1.51/go.mod h1:2Z9d3CP1LQWihRZUf29mQ19yDThaI4DAYzte2CaQW5c=
|
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||||
github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8=
|
github.com/onsi/ginkgo/v2 v2.8.1 h1:xFTEVwOFa1D/Ty24Ws1npBWkDYEV9BqZrsDxVrVkrrU=
|
||||||
github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk=
|
github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc=
|
||||||
github.com/onsi/gomega v1.27.1 h1:rfztXRbg6nv/5f+Raen9RcGoSecHIFgBBLQK3Wdj754=
|
github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
|
||||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
@@ -130,21 +130,27 @@ github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:
|
|||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A=
|
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||||
github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||||
github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk=
|
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
|
||||||
github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||||
github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0=
|
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
|
||||||
github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA=
|
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||||
github.com/refraction-networking/utls v1.2.3-0.20230308205431-4f1df6c200db h1:ULRv/GPW5KYDafE0FACN2no+HTCyQLUtfyOIeyp3GNc=
|
github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
|
||||||
github.com/refraction-networking/utls v1.2.3-0.20230308205431-4f1df6c200db/go.mod h1:kHXvVB66a4BzVRYC4Em7e1HAfp7uwOCCw0+2CZ3sMY8=
|
github.com/quic-go/quic-go v0.32.0/go.mod h1:/fCsKANhQIeD5l76c2JFU+07gVE3KaA0FP+0zMWwfwo=
|
||||||
|
github.com/refraction-networking/utls v1.2.2 h1:uBE6V173CwG8MQrSBpNZHAix1fxOvuLKYyjFAu3uqo0=
|
||||||
|
github.com/refraction-networking/utls v1.2.2/go.mod h1:L1goe44KvhnTfctUffM2isnJpSjPlYShrhXDeZaoYKw=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||||
github.com/sagernet/sing v0.1.7 h1:g4vjr3q8SUlBZSx97Emz5OBfSMBxxW5Q8C2PfdoSo08=
|
github.com/sagernet/sing v0.1.6 h1:Qy63OUfKpcqKjfd5rPmUlj0RGjHZSK/PJn0duyCCsRg=
|
||||||
github.com/sagernet/sing v0.1.7/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.6/go.mod h1:JLSXsPTGRJFo/3X7EcAOCUgJH2/gAoxSJgBsnCZRp/w=
|
||||||
github.com/sagernet/sing-shadowsocks v0.1.1 h1:uFK2rlVeD/b1xhDwSMbUI2goWc6fOKxp+ZeKHZq6C9Q=
|
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7 h1:Plup6oEiyLzY3HDqQ+QsUBzgBGdVmcsgf3t8h940z9U=
|
||||||
github.com/sagernet/sing-shadowsocks v0.1.1/go.mod h1:f3mHTy5shnVM9l8UocMlJgC/1G/zdj5FuEuVXhDinGU=
|
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7/go.mod h1:O5LtOs8Ivw686FqLpO0Zu+A0ROVE15VeqEK3yDRRAms=
|
||||||
|
github.com/sagernet/sing-shadowtls v0.0.0-20230221123345-78e50cd7b587 h1:OjIXlHT2bblZfp+ciupM4xY9+Ccpj9FsuHRtKRBv+Pg=
|
||||||
|
github.com/sagernet/sing-shadowtls v0.0.0-20230221123345-78e50cd7b587/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
||||||
|
github.com/sagernet/utls v0.0.0-20230220130002-c08891932056 h1:gDXi/0uYe8dA48UyUI1LM2la5QYN0IvsDvR2H2+kFnA=
|
||||||
|
github.com/sagernet/utls v0.0.0-20230220130002-c08891932056/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
||||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
||||||
@@ -182,20 +188,21 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
||||||
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/reality v0.0.0-20230309125256-0d0713b108c8 h1:LLtLxEe3S0Ko+ckqt4t29RLskpNdOZfgjZCC2/Byr50=
|
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3 h1:a3Y4WVjCxwoyO4E2xdNvq577tW8lkSBgyrA8E9+2NtM=
|
||||||
github.com/xtls/reality v0.0.0-20230309125256-0d0713b108c8/go.mod h1:rkuAY1S9F8eI8gDiPDYvACE8e2uwkyg8qoOTuwWov7Y=
|
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY=
|
||||||
|
github.com/xtls/reality v0.0.0-20230217102704-085bdf2104d3 h1:Rp9BfXZ+Li5j5L40zAdFZLcr0nXrYBPgaNpQ9lQnpWg=
|
||||||
|
github.com/xtls/reality v0.0.0-20230217102704-085bdf2104d3/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=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||||
go.starlark.net v0.0.0-20230302034142-4b1e35fe2254 h1:Ss6D3hLXTM0KobyBYEAygXzFfGcjnmfEJOBgSbemCtg=
|
go.starlark.net v0.0.0-20230128213706-3f75dec8e403 h1:jPeC7Exc+m8OBJUlWbBLh0O5UZPM7yU5W4adnhhbG4U=
|
||||||
go.starlark.net v0.0.0-20230302034142-4b1e35fe2254/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
|
go.starlark.net v0.0.0-20230128213706-3f75dec8e403/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||||
@@ -204,21 +211,18 @@ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnf
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||||
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833 h1:SChBja7BCQewoTAU7IgvucQKMIXrEpFxNMs0spT3/5s=
|
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w=
|
||||||
golang.org/x/exp v0.0.0-20230307190834-24139beb5833/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
||||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
|
||||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -230,12 +234,10 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@@ -247,7 +249,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -258,26 +259,22 @@ golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
|
||||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
@@ -291,10 +288,9 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3
|
|||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
|
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -313,8 +309,8 @@ google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk
|
|||||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA=
|
google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc h1:ijGwO+0vL2hJt5gaygqP2j6PfflOBrRot0IczKbmtio=
|
||||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
|
google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
@@ -333,8 +329,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
|||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0=
|
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||||
google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
|
102
infra/conf/shadowtls.go
Normal file
102
infra/conf/shadowtls.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package conf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/sagernet/sing/common"
|
||||||
|
"github.com/xtls/xray-core/proxy/shadowtls"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShadowTLSServerConfig struct {
|
||||||
|
Version uint16 `json:"version"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Users []ShadowTLSUser `json:"users,omitempty"`
|
||||||
|
Handshake *ShadowTLSHandshakeConfig `json:"handshake"`
|
||||||
|
HandshakeForServerName map[string]*ShadowTLSHandshakeConfig `json:"handshakeForServerName,omitempty"`
|
||||||
|
StrictMode bool `json:"strictMode,omitempty"`
|
||||||
|
Detour string `json:"detour"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShadowTLSUser struct {
|
||||||
|
Email string `json:"email,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShadowTLSHandshakeConfig struct {
|
||||||
|
Address *Address `json:"address"`
|
||||||
|
Port uint16 `json:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ShadowTLSServerConfig) Build() (proto.Message, error) {
|
||||||
|
if c.Version == 0 {
|
||||||
|
return nil, newError("shadow-tls version is not set.")
|
||||||
|
}
|
||||||
|
if c.Version == 3 && len(c.Users) == 0 {
|
||||||
|
return nil, newError("shadow-tls users is not set.")
|
||||||
|
}
|
||||||
|
if c.Handshake == nil {
|
||||||
|
return nil, newError("shadow-tls handshake config is not set.")
|
||||||
|
}
|
||||||
|
var handshakeForServerName map[string]*shadowtls.HandshakeConfig
|
||||||
|
if c.HandshakeForServerName != nil {
|
||||||
|
for serverName, serverConfig := range c.HandshakeForServerName {
|
||||||
|
if serverConfig.Address == nil {
|
||||||
|
return nil, newError("shadow-tls handshake server address is not set.")
|
||||||
|
}
|
||||||
|
if serverConfig.Port == 0 {
|
||||||
|
return nil, newError("shadow-tls handshake server port is not set.")
|
||||||
|
}
|
||||||
|
handshakeForServerName[serverName] = &shadowtls.HandshakeConfig{
|
||||||
|
Address: serverConfig.Address.Build(),
|
||||||
|
Port: uint32(serverConfig.Port),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if c.Handshake.Address == nil {
|
||||||
|
return nil, newError("shadow-tls handshake server address is not set.")
|
||||||
|
}
|
||||||
|
if c.Handshake.Port == 0 {
|
||||||
|
return nil, newError("shadow-tls handshake server port is not set.")
|
||||||
|
}
|
||||||
|
return &shadowtls.ServerConfig{
|
||||||
|
Version: uint32(c.Version),
|
||||||
|
Password: c.Password,
|
||||||
|
Users: common.Map(c.Users, func(it ShadowTLSUser) *shadowtls.User {
|
||||||
|
return &shadowtls.User{
|
||||||
|
Email: it.Email,
|
||||||
|
Password: it.Password,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
Handshake: &shadowtls.HandshakeConfig{
|
||||||
|
Address: c.Handshake.Address.Build(),
|
||||||
|
Port: uint32(c.Handshake.Port),
|
||||||
|
},
|
||||||
|
HandshakeForServerName: handshakeForServerName,
|
||||||
|
StrictMode: c.StrictMode,
|
||||||
|
Detour: c.Detour,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShadowTLSClientConfig struct {
|
||||||
|
Address *Address `json:"address"`
|
||||||
|
Port uint16 `json:"port"`
|
||||||
|
Version uint16 `json:"version"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ShadowTLSClientConfig) Build() (proto.Message, error) {
|
||||||
|
if c.Version == 0 {
|
||||||
|
return nil, newError("shadow-tls version is not set.")
|
||||||
|
}
|
||||||
|
if c.Address == nil {
|
||||||
|
return nil, newError("shadow-tls server address is not set.")
|
||||||
|
}
|
||||||
|
if c.Port == 0 {
|
||||||
|
return nil, newError("shadow-tls server port is not set.")
|
||||||
|
}
|
||||||
|
return &shadowtls.ClientConfig{
|
||||||
|
Address: c.Address.Build(),
|
||||||
|
Port: uint32(c.Port),
|
||||||
|
Version: uint32(c.Version),
|
||||||
|
Password: c.Password,
|
||||||
|
}, nil
|
||||||
|
}
|
@@ -4,7 +4,6 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/dns"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/http"
|
"github.com/xtls/xray-core/transport/internet/headers/http"
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/noop"
|
"github.com/xtls/xray-core/transport/internet/headers/noop"
|
||||||
"github.com/xtls/xray-core/transport/internet/headers/srtp"
|
"github.com/xtls/xray-core/transport/internet/headers/srtp"
|
||||||
@@ -50,19 +49,6 @@ func (WireguardAuthenticator) Build() (proto.Message, error) {
|
|||||||
return new(wireguard.WireguardConfig), nil
|
return new(wireguard.WireguardConfig), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type DNSAuthenticator struct {
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *DNSAuthenticator) Build() (proto.Message, error) {
|
|
||||||
config := new(dns.Config)
|
|
||||||
config.Domain = "www.baidu.com"
|
|
||||||
if len(v.Domain) > 0 {
|
|
||||||
config.Domain = v.Domain
|
|
||||||
}
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type DTLSAuthenticator struct{}
|
type DTLSAuthenticator struct{}
|
||||||
|
|
||||||
func (DTLSAuthenticator) Build() (proto.Message, error) {
|
func (DTLSAuthenticator) Build() (proto.Message, error) {
|
||||||
|
@@ -26,6 +26,7 @@ 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 (
|
||||||
@@ -36,7 +37,6 @@ var (
|
|||||||
"wechat-video": func() interface{} { return new(WechatVideoAuthenticator) },
|
"wechat-video": func() interface{} { return new(WechatVideoAuthenticator) },
|
||||||
"dtls": func() interface{} { return new(DTLSAuthenticator) },
|
"dtls": func() interface{} { return new(DTLSAuthenticator) },
|
||||||
"wireguard": func() interface{} { return new(WireguardAuthenticator) },
|
"wireguard": func() interface{} { return new(WireguardAuthenticator) },
|
||||||
"dns": func() interface{} { return new(DNSAuthenticator) },
|
|
||||||
}, "type", "")
|
}, "type", "")
|
||||||
|
|
||||||
tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
tcpHeaderLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||||
@@ -343,20 +343,19 @@ func (c *TLSCertConfig) Build() (*tls.Certificate, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TLSConfig struct {
|
type TLSConfig struct {
|
||||||
Insecure bool `json:"allowInsecure"`
|
Insecure bool `json:"allowInsecure"`
|
||||||
Certs []*TLSCertConfig `json:"certificates"`
|
Certs []*TLSCertConfig `json:"certificates"`
|
||||||
ServerName string `json:"serverName"`
|
ServerName string `json:"serverName"`
|
||||||
ALPN *StringList `json:"alpn"`
|
ALPN *StringList `json:"alpn"`
|
||||||
EnableSessionResumption bool `json:"enableSessionResumption"`
|
EnableSessionResumption bool `json:"enableSessionResumption"`
|
||||||
DisableSystemRoot bool `json:"disableSystemRoot"`
|
DisableSystemRoot bool `json:"disableSystemRoot"`
|
||||||
MinVersion string `json:"minVersion"`
|
MinVersion string `json:"minVersion"`
|
||||||
MaxVersion string `json:"maxVersion"`
|
MaxVersion string `json:"maxVersion"`
|
||||||
CipherSuites string `json:"cipherSuites"`
|
CipherSuites string `json:"cipherSuites"`
|
||||||
PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
|
PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
|
||||||
Fingerprint string `json:"fingerprint"`
|
Fingerprint string `json:"fingerprint"`
|
||||||
RejectUnknownSNI bool `json:"rejectUnknownSni"`
|
RejectUnknownSNI bool `json:"rejectUnknownSni"`
|
||||||
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
|
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
|
||||||
PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
@@ -401,17 +400,117 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.PinnedPeerCertificatePublicKeySha256 != nil {
|
return config, nil
|
||||||
config.PinnedPeerCertificatePublicKeySha256 = [][]byte{}
|
}
|
||||||
for _, v := range *c.PinnedPeerCertificatePublicKeySha256 {
|
|
||||||
|
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)
|
hashValue, err := base64.StdEncoding.DecodeString(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
config.PinnedPeerCertificatePublicKeySha256 = append(config.PinnedPeerCertificatePublicKeySha256, hashValue)
|
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
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -532,18 +631,12 @@ func (c *REALITYConfig) Build() (proto.Message, error) {
|
|||||||
if config.Fingerprint == "hellogolang" {
|
if config.Fingerprint == "hellogolang" {
|
||||||
return nil, newError(`invalid "fingerprint": `, config.Fingerprint)
|
return nil, newError(`invalid "fingerprint": `, config.Fingerprint)
|
||||||
}
|
}
|
||||||
if len(c.ServerNames) != 0 {
|
|
||||||
return nil, newError(`non-empty "serverNames", please use "serverName" instead`)
|
|
||||||
}
|
|
||||||
if c.PublicKey == "" {
|
if c.PublicKey == "" {
|
||||||
return nil, newError(`empty "publicKey"`)
|
return nil, newError(`empty "publicKey"`)
|
||||||
}
|
}
|
||||||
if config.PublicKey, err = base64.RawURLEncoding.DecodeString(c.PublicKey); err != nil || len(config.PublicKey) != 32 {
|
if config.PublicKey, err = base64.RawURLEncoding.DecodeString(c.PublicKey); err != nil || len(config.PublicKey) != 32 {
|
||||||
return nil, newError(`invalid "publicKey": `, c.PublicKey)
|
return nil, newError(`invalid "publicKey": `, c.PublicKey)
|
||||||
}
|
}
|
||||||
if len(c.ShortIds) != 0 {
|
|
||||||
return nil, newError(`non-empty "shortIds", please use "shortId" instead`)
|
|
||||||
}
|
|
||||||
config.ShortId = make([]byte, 8)
|
config.ShortId = make([]byte, 8)
|
||||||
if _, err = hex.Decode(config.ShortId, []byte(c.ShortId)); err != nil {
|
if _, err = hex.Decode(config.ShortId, []byte(c.ShortId)); err != nil {
|
||||||
return nil, newError(`invalid "shortId": `, c.ShortId)
|
return nil, newError(`invalid "shortId": `, c.ShortId)
|
||||||
@@ -616,8 +709,6 @@ type SocketConfig struct {
|
|||||||
TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"`
|
TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"`
|
||||||
TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"`
|
TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"`
|
||||||
TCPCongestion string `json:"tcpCongestion"`
|
TCPCongestion string `json:"tcpCongestion"`
|
||||||
TCPWindowClamp int32 `json:"tcpWindowClamp"`
|
|
||||||
V6only bool `json:"v6only"`
|
|
||||||
Interface string `json:"interface"`
|
Interface string `json:"interface"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -668,8 +759,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
TcpKeepAliveInterval: c.TCPKeepAliveInterval,
|
TcpKeepAliveInterval: c.TCPKeepAliveInterval,
|
||||||
TcpKeepAliveIdle: c.TCPKeepAliveIdle,
|
TcpKeepAliveIdle: c.TCPKeepAliveIdle,
|
||||||
TcpCongestion: c.TCPCongestion,
|
TcpCongestion: c.TCPCongestion,
|
||||||
TcpWindowClamp: c.TCPWindowClamp,
|
|
||||||
V6Only: c.V6only,
|
|
||||||
Interface: c.Interface,
|
Interface: c.Interface,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@@ -678,6 +767,7 @@ 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"`
|
||||||
@@ -702,11 +792,12 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||||||
}
|
}
|
||||||
config.ProtocolName = protocol
|
config.ProtocolName = protocol
|
||||||
}
|
}
|
||||||
switch strings.ToLower(c.Security) {
|
if strings.EqualFold(c.Security, "tls") {
|
||||||
case "", "none":
|
|
||||||
case "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()
|
||||||
@@ -716,9 +807,29 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||||||
tm := serial.ToTypedMessage(ts)
|
tm := serial.ToTypedMessage(ts)
|
||||||
config.SecuritySettings = append(config.SecuritySettings, tm)
|
config.SecuritySettings = append(config.SecuritySettings, tm)
|
||||||
config.SecurityType = tm.Type
|
config.SecurityType = tm.Type
|
||||||
case "reality":
|
}
|
||||||
if config.ProtocolName != "tcp" && config.ProtocolName != "http" && config.ProtocolName != "grpc" && config.ProtocolName != "domainsocket" {
|
if strings.EqualFold(c.Security, "xtls") {
|
||||||
return nil, newError("REALITY only supports TCP, H2, gRPC and DomainSocket for now.")
|
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 config.ProtocolName != "tcp" && config.ProtocolName != "http" && config.ProtocolName != "domainsocket" {
|
||||||
|
return nil, newError("REALITY only supports TCP, H2 and DomainSocket for now.")
|
||||||
}
|
}
|
||||||
if c.REALITYSettings == nil {
|
if c.REALITYSettings == nil {
|
||||||
return nil, newError(`REALITY: Empty "realitySettings".`)
|
return nil, newError(`REALITY: Empty "realitySettings".`)
|
||||||
@@ -730,10 +841,6 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
|||||||
tm := serial.ToTypedMessage(ts)
|
tm := serial.ToTypedMessage(ts)
|
||||||
config.SecuritySettings = append(config.SecuritySettings, tm)
|
config.SecuritySettings = append(config.SecuritySettings, tm)
|
||||||
config.SecurityType = tm.Type
|
config.SecurityType = tm.Type
|
||||||
case "xtls":
|
|
||||||
return nil, newError(`Please use VLESS flow "xtls-rprx-vision" with TLS or REALITY.`)
|
|
||||||
default:
|
|
||||||
return nil, newError(`Unknown security "` + c.Security + `".`)
|
|
||||||
}
|
}
|
||||||
if c.TCPSettings != nil {
|
if c.TCPSettings != nil {
|
||||||
ts, err := c.TCPSettings.Build()
|
ts, err := c.TCPSettings.Build()
|
||||||
|
@@ -53,7 +53,11 @@ func (c *TrojanClientConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch account.Flow {
|
switch account.Flow {
|
||||||
case "":
|
case "", "xtls-rprx-origin", "xtls-rprx-origin-udp443", "xtls-rprx-direct", "xtls-rprx-direct-udp443":
|
||||||
|
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`)
|
||||||
}
|
}
|
||||||
@@ -115,7 +119,9 @@ func (c *TrojanServerConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch account.Flow {
|
switch account.Flow {
|
||||||
case "":
|
case "", "xtls-rprx-origin", "xtls-rprx-direct":
|
||||||
|
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`)
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
@@ -52,8 +53,18 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
|||||||
}
|
}
|
||||||
account.Id = u.String()
|
account.Id = u.String()
|
||||||
|
|
||||||
switch account.Flow {
|
accountFlow := account.Flow
|
||||||
case "", vless.XRV:
|
flows := strings.Split(account.Flow, ",")
|
||||||
|
for _, f := range flows {
|
||||||
|
t := strings.TrimSpace(f)
|
||||||
|
if t != "none" {
|
||||||
|
accountFlow = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch accountFlow {
|
||||||
|
case "", vless.XRO, vless.XRD, 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`)
|
||||||
}
|
}
|
||||||
@@ -180,7 +191,11 @@ func (c *VLessOutboundConfig) Build() (proto.Message, error) {
|
|||||||
account.Id = u.String()
|
account.Id = u.String()
|
||||||
|
|
||||||
switch account.Flow {
|
switch account.Flow {
|
||||||
case "", vless.XRV, vless.XRV + "-udp443":
|
case "", vless.XRO, vless.XRO + "-udp443", vless.XRD, vless.XRD + "-udp443", 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-vision-udp443",
|
"flow": "xtls-rprx-direct-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-vision-udp443",
|
Flow: "xtls-rprx-direct-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-vision",
|
"flow": "xtls-rprx-direct",
|
||||||
"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-vision",
|
Flow: "xtls-rprx-direct",
|
||||||
}),
|
}),
|
||||||
Level: 0,
|
Level: 0,
|
||||||
Email: "love@example.com",
|
Email: "love@example.com",
|
||||||
|
@@ -52,7 +52,6 @@ type WireGuardConfig struct {
|
|||||||
Peers []*WireGuardPeerConfig `json:"peers"`
|
Peers []*WireGuardPeerConfig `json:"peers"`
|
||||||
MTU int `json:"mtu"`
|
MTU int `json:"mtu"`
|
||||||
NumWorkers int `json:"workers"`
|
NumWorkers int `json:"workers"`
|
||||||
Reserved []byte `json:"reserved"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *WireGuardConfig) Build() (proto.Message, error) {
|
func (c *WireGuardConfig) Build() (proto.Message, error) {
|
||||||
@@ -91,11 +90,6 @@ func (c *WireGuardConfig) Build() (proto.Message, error) {
|
|||||||
// we don't need to process fallback manually
|
// we don't need to process fallback manually
|
||||||
config.NumWorkers = int32(c.NumWorkers)
|
config.NumWorkers = int32(c.NumWorkers)
|
||||||
|
|
||||||
if len(c.Reserved) != 0 && len(c.Reserved) != 3 {
|
|
||||||
return nil, newError(`"reserved" should be empty or 3 bytes`)
|
|
||||||
}
|
|
||||||
config.Reserved = c.Reserved
|
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,6 +13,7 @@ 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 (
|
||||||
@@ -25,6 +26,7 @@ var (
|
|||||||
"vmess": func() interface{} { return new(VMessInboundConfig) },
|
"vmess": func() interface{} { return new(VMessInboundConfig) },
|
||||||
"trojan": func() interface{} { return new(TrojanServerConfig) },
|
"trojan": func() interface{} { return new(TrojanServerConfig) },
|
||||||
"mtproto": func() interface{} { return new(MTProtoServerConfig) },
|
"mtproto": func() interface{} { return new(MTProtoServerConfig) },
|
||||||
|
"shadow-tls": func() interface{} { return new(ShadowTLSServerConfig) },
|
||||||
}, "protocol", "settings")
|
}, "protocol", "settings")
|
||||||
|
|
||||||
outboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
outboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||||
@@ -40,6 +42,7 @@ var (
|
|||||||
"mtproto": func() interface{} { return new(MTProtoClientConfig) },
|
"mtproto": func() interface{} { return new(MTProtoClientConfig) },
|
||||||
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
||||||
"wireguard": func() interface{} { return new(WireGuardConfig) },
|
"wireguard": func() interface{} { return new(WireGuardConfig) },
|
||||||
|
"shadow-tls": func() interface{} { return new(ShadowTLSClientConfig) },
|
||||||
}, "protocol", "settings")
|
}, "protocol", "settings")
|
||||||
|
|
||||||
ctllog = log.New(os.Stderr, "xctl> ", 0)
|
ctllog = log.New(os.Stderr, "xctl> ", 0)
|
||||||
@@ -235,6 +238,9 @@ 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 {
|
||||||
@@ -315,6 +321,9 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +348,15 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.MuxSettings != nil {
|
if c.MuxSettings != nil {
|
||||||
senderSettings.MultiplexSettings = c.MuxSettings.Build()
|
ms := 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("{}")
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/main/commands/base"
|
"github.com/xtls/xray-core/main/commands/base"
|
||||||
"golang.org/x/crypto/curve25519"
|
"golang.org/x/crypto/curve25519"
|
||||||
@@ -43,26 +44,17 @@ func executeX25519(cmd *base.Command, args []string) {
|
|||||||
goto out
|
goto out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if privateKey == nil {
|
if privateKey == nil {
|
||||||
privateKey = make([]byte, curve25519.ScalarSize)
|
privateKey = make([]byte, curve25519.ScalarSize)
|
||||||
if _, err = rand.Read(privateKey); err != nil {
|
if _, err = io.ReadFull(rand.Reader, privateKey); err != nil {
|
||||||
output = err.Error()
|
output = err.Error()
|
||||||
goto out
|
goto out
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify random bytes using algorithm described at:
|
|
||||||
// https://cr.yp.to/ecdh.html.
|
|
||||||
privateKey[0] &= 248
|
|
||||||
privateKey[31] &= 127
|
|
||||||
privateKey[31] |= 64
|
|
||||||
|
|
||||||
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
|
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
|
||||||
output = err.Error()
|
output = err.Error()
|
||||||
goto out
|
goto out
|
||||||
}
|
}
|
||||||
|
|
||||||
output = fmt.Sprintf("Private key: %v\nPublic key: %v",
|
output = fmt.Sprintf("Private key: %v\nPublic key: %v",
|
||||||
base64.RawURLEncoding.EncodeToString(privateKey),
|
base64.RawURLEncoding.EncodeToString(privateKey),
|
||||||
base64.RawURLEncoding.EncodeToString(publicKey))
|
base64.RawURLEncoding.EncodeToString(publicKey))
|
||||||
|
@@ -42,6 +42,7 @@ import (
|
|||||||
_ "github.com/xtls/xray-core/proxy/loopback"
|
_ "github.com/xtls/xray-core/proxy/loopback"
|
||||||
_ "github.com/xtls/xray-core/proxy/mtproto"
|
_ "github.com/xtls/xray-core/proxy/mtproto"
|
||||||
_ "github.com/xtls/xray-core/proxy/shadowsocks"
|
_ "github.com/xtls/xray-core/proxy/shadowsocks"
|
||||||
|
_ "github.com/xtls/xray-core/proxy/shadowtls"
|
||||||
_ "github.com/xtls/xray-core/proxy/socks"
|
_ "github.com/xtls/xray-core/proxy/socks"
|
||||||
_ "github.com/xtls/xray-core/proxy/trojan"
|
_ "github.com/xtls/xray-core/proxy/trojan"
|
||||||
_ "github.com/xtls/xray-core/proxy/vless/inbound"
|
_ "github.com/xtls/xray-core/proxy/vless/inbound"
|
||||||
@@ -61,6 +62,7 @@ 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"
|
||||||
|
@@ -17,6 +17,7 @@ import (
|
|||||||
"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/session"
|
||||||
|
"github.com/xtls/xray-core/common/singbridge"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
)
|
)
|
||||||
@@ -73,7 +74,7 @@ func (i *Inbound) Process(ctx context.Context, network net.Network, connection s
|
|||||||
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
||||||
|
|
||||||
if network == net.Network_TCP {
|
if network == net.Network_TCP {
|
||||||
return returnError(i.service.NewConnection(ctx, connection, metadata))
|
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
|
||||||
} else {
|
} else {
|
||||||
reader := buf.NewReader(connection)
|
reader := buf.NewReader(connection)
|
||||||
pc := &natPacketConn{connection}
|
pc := &natPacketConn{connection}
|
||||||
@@ -81,7 +82,7 @@ func (i *Inbound) Process(ctx context.Context, network net.Network, connection s
|
|||||||
mb, err := reader.ReadMultiBuffer()
|
mb, err := reader.ReadMultiBuffer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
buf.ReleaseMulti(mb)
|
buf.ReleaseMulti(mb)
|
||||||
return returnError(err)
|
return singbridge.ReturnError(err)
|
||||||
}
|
}
|
||||||
for _, buffer := range mb {
|
for _, buffer := range mb {
|
||||||
packet := B.As(buffer.Bytes()).ToOwned()
|
packet := B.As(buffer.Bytes()).ToOwned()
|
||||||
@@ -111,16 +112,11 @@ func (i *Inbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.M
|
|||||||
})
|
})
|
||||||
newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
||||||
dispatcher := session.DispatcherFromContext(ctx)
|
dispatcher := session.DispatcherFromContext(ctx)
|
||||||
link, err := dispatcher.Dispatch(ctx, toDestination(metadata.Destination, net.Network_TCP))
|
link, err := dispatcher.Dispatch(ctx, singbridge.ToDestination(metadata.Destination, net.Network_TCP))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
outConn := &pipeConnWrapper{
|
return singbridge.CopyConn(ctx, nil, link, conn)
|
||||||
&buf.BufferedReader{Reader: link.Reader},
|
|
||||||
link.Writer,
|
|
||||||
conn,
|
|
||||||
}
|
|
||||||
return bufio.CopyConn(ctx, conn, outConn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||||
@@ -137,7 +133,7 @@ func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, me
|
|||||||
})
|
})
|
||||||
newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
||||||
dispatcher := session.DispatcherFromContext(ctx)
|
dispatcher := session.DispatcherFromContext(ctx)
|
||||||
destination := toDestination(metadata.Destination, net.Network_UDP)
|
destination := singbridge.ToDestination(metadata.Destination, net.Network_UDP)
|
||||||
link, err := dispatcher.Dispatch(ctx, destination)
|
link, err := dispatcher.Dispatch(ctx, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -21,6 +21,7 @@ import (
|
|||||||
"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/session"
|
||||||
|
"github.com/xtls/xray-core/common/singbridge"
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
"github.com/xtls/xray-core/common/uuid"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
@@ -162,7 +163,7 @@ func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, con
|
|||||||
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
||||||
|
|
||||||
if network == net.Network_TCP {
|
if network == net.Network_TCP {
|
||||||
return returnError(i.service.NewConnection(ctx, connection, metadata))
|
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
|
||||||
} else {
|
} else {
|
||||||
reader := buf.NewReader(connection)
|
reader := buf.NewReader(connection)
|
||||||
pc := &natPacketConn{connection}
|
pc := &natPacketConn{connection}
|
||||||
@@ -170,7 +171,7 @@ func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, con
|
|||||||
mb, err := reader.ReadMultiBuffer()
|
mb, err := reader.ReadMultiBuffer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
buf.ReleaseMulti(mb)
|
buf.ReleaseMulti(mb)
|
||||||
return returnError(err)
|
return singbridge.ReturnError(err)
|
||||||
}
|
}
|
||||||
for _, buffer := range mb {
|
for _, buffer := range mb {
|
||||||
packet := B.As(buffer.Bytes()).ToOwned()
|
packet := B.As(buffer.Bytes()).ToOwned()
|
||||||
@@ -202,16 +203,11 @@ func (i *MultiUserInbound) NewConnection(ctx context.Context, conn net.Conn, met
|
|||||||
})
|
})
|
||||||
newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
||||||
dispatcher := session.DispatcherFromContext(ctx)
|
dispatcher := session.DispatcherFromContext(ctx)
|
||||||
link, err := dispatcher.Dispatch(ctx, toDestination(metadata.Destination, net.Network_TCP))
|
link, err := dispatcher.Dispatch(ctx, singbridge.ToDestination(metadata.Destination, net.Network_TCP))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
outConn := &pipeConnWrapper{
|
return singbridge.CopyConn(ctx, conn, link, conn)
|
||||||
&buf.BufferedReader{Reader: link.Reader},
|
|
||||||
link.Writer,
|
|
||||||
conn,
|
|
||||||
}
|
|
||||||
return bufio.CopyConn(ctx, conn, outConn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||||
@@ -230,7 +226,7 @@ func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.Packe
|
|||||||
})
|
})
|
||||||
newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
||||||
dispatcher := session.DispatcherFromContext(ctx)
|
dispatcher := session.DispatcherFromContext(ctx)
|
||||||
destination := toDestination(metadata.Destination, net.Network_UDP)
|
destination := singbridge.ToDestination(metadata.Destination, net.Network_UDP)
|
||||||
link, err := dispatcher.Dispatch(ctx, destination)
|
link, err := dispatcher.Dispatch(ctx, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -19,6 +19,7 @@ import (
|
|||||||
"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/session"
|
||||||
|
"github.com/xtls/xray-core/common/singbridge"
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
"github.com/xtls/xray-core/common/uuid"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
@@ -66,7 +67,7 @@ func NewRelayServer(ctx context.Context, config *RelayServerConfig) (*RelayInbou
|
|||||||
C.MapIndexed(config.Destinations, func(index int, it *RelayDestination) int { return index }),
|
C.MapIndexed(config.Destinations, func(index int, it *RelayDestination) int { return index }),
|
||||||
C.Map(config.Destinations, func(it *RelayDestination) string { return it.Key }),
|
C.Map(config.Destinations, func(it *RelayDestination) string { return it.Key }),
|
||||||
C.Map(config.Destinations, func(it *RelayDestination) M.Socksaddr {
|
C.Map(config.Destinations, func(it *RelayDestination) M.Socksaddr {
|
||||||
return toSocksaddr(net.Destination{
|
return singbridge.ToSocksaddr(net.Destination{
|
||||||
Address: it.Address.AsAddress(),
|
Address: it.Address.AsAddress(),
|
||||||
Port: net.Port(it.Port),
|
Port: net.Port(it.Port),
|
||||||
})
|
})
|
||||||
@@ -94,7 +95,7 @@ func (i *RelayInbound) Process(ctx context.Context, network net.Network, connect
|
|||||||
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
||||||
|
|
||||||
if network == net.Network_TCP {
|
if network == net.Network_TCP {
|
||||||
return returnError(i.service.NewConnection(ctx, connection, metadata))
|
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
|
||||||
} else {
|
} else {
|
||||||
reader := buf.NewReader(connection)
|
reader := buf.NewReader(connection)
|
||||||
pc := &natPacketConn{connection}
|
pc := &natPacketConn{connection}
|
||||||
@@ -102,7 +103,7 @@ func (i *RelayInbound) Process(ctx context.Context, network net.Network, connect
|
|||||||
mb, err := reader.ReadMultiBuffer()
|
mb, err := reader.ReadMultiBuffer()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
buf.ReleaseMulti(mb)
|
buf.ReleaseMulti(mb)
|
||||||
return returnError(err)
|
return singbridge.ReturnError(err)
|
||||||
}
|
}
|
||||||
for _, buffer := range mb {
|
for _, buffer := range mb {
|
||||||
packet := B.As(buffer.Bytes()).ToOwned()
|
packet := B.As(buffer.Bytes()).ToOwned()
|
||||||
@@ -134,16 +135,11 @@ func (i *RelayInbound) NewConnection(ctx context.Context, conn net.Conn, metadat
|
|||||||
})
|
})
|
||||||
newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
newError("tunnelling request to tcp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
||||||
dispatcher := session.DispatcherFromContext(ctx)
|
dispatcher := session.DispatcherFromContext(ctx)
|
||||||
link, err := dispatcher.Dispatch(ctx, toDestination(metadata.Destination, net.Network_TCP))
|
link, err := dispatcher.Dispatch(ctx, singbridge.ToDestination(metadata.Destination, net.Network_TCP))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
outConn := &pipeConnWrapper{
|
return singbridge.CopyConn(ctx, nil, link, conn)
|
||||||
&buf.BufferedReader{Reader: link.Reader},
|
|
||||||
link.Writer,
|
|
||||||
conn,
|
|
||||||
}
|
|
||||||
return bufio.CopyConn(ctx, conn, outConn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *RelayInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
func (i *RelayInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||||
@@ -162,7 +158,7 @@ func (i *RelayInbound) NewPacketConnection(ctx context.Context, conn N.PacketCon
|
|||||||
})
|
})
|
||||||
newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(ctx))
|
||||||
dispatcher := session.DispatcherFromContext(ctx)
|
dispatcher := session.DispatcherFromContext(ctx)
|
||||||
destination := toDestination(metadata.Destination, net.Network_UDP)
|
destination := singbridge.ToDestination(metadata.Destination, net.Network_UDP)
|
||||||
link, err := dispatcher.Dispatch(ctx, destination)
|
link, err := dispatcher.Dispatch(ctx, destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -2,7 +2,6 @@ package shadowsocks_2022
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -18,6 +17,7 @@ import (
|
|||||||
"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/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/singbridge"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@@ -88,7 +88,7 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
|
|||||||
}
|
}
|
||||||
|
|
||||||
if network == net.Network_TCP {
|
if network == net.Network_TCP {
|
||||||
serverConn := o.method.DialEarlyConn(connection, toSocksaddr(destination))
|
serverConn := o.method.DialEarlyConn(connection, singbridge.ToSocksaddr(destination))
|
||||||
var handshake bool
|
var handshake bool
|
||||||
if timeoutReader, isTimeoutReader := link.Reader.(buf.TimeoutReader); isTimeoutReader {
|
if timeoutReader, isTimeoutReader := link.Reader.(buf.TimeoutReader); isTimeoutReader {
|
||||||
mb, err := timeoutReader.ReadMultiBufferTimeout(time.Millisecond * 100)
|
mb, err := timeoutReader.ReadMultiBufferTimeout(time.Millisecond * 100)
|
||||||
@@ -123,17 +123,7 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
|
|||||||
return newError("client handshake").Base(err)
|
return newError("client handshake").Base(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
conn := &pipeConnWrapper{
|
return singbridge.CopyConn(ctx, inboundConn, link, serverConn)
|
||||||
W: link.Writer,
|
|
||||||
Conn: inboundConn,
|
|
||||||
}
|
|
||||||
if ir, ok := link.Reader.(io.Reader); ok {
|
|
||||||
conn.R = ir
|
|
||||||
} else {
|
|
||||||
conn.R = &buf.BufferedReader{Reader: link.Reader}
|
|
||||||
}
|
|
||||||
|
|
||||||
return returnError(bufio.CopyConn(ctx, conn, serverConn))
|
|
||||||
} else {
|
} else {
|
||||||
var packetConn N.PacketConn
|
var packetConn N.PacketConn
|
||||||
if pc, isPacketConn := inboundConn.(N.PacketConn); isPacketConn {
|
if pc, isPacketConn := inboundConn.(N.PacketConn); isPacketConn {
|
||||||
@@ -151,10 +141,10 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
|
|||||||
|
|
||||||
if o.uot {
|
if o.uot {
|
||||||
serverConn := o.method.DialEarlyConn(connection, M.Socksaddr{Fqdn: uot.UOTMagicAddress})
|
serverConn := o.method.DialEarlyConn(connection, M.Socksaddr{Fqdn: uot.UOTMagicAddress})
|
||||||
return returnError(bufio.CopyPacketConn(ctx, packetConn, uot.NewClientConn(serverConn)))
|
return singbridge.ReturnError(bufio.CopyPacketConn(ctx, packetConn, uot.NewClientConn(serverConn)))
|
||||||
} else {
|
} else {
|
||||||
serverConn := o.method.DialPacketConn(connection)
|
serverConn := o.method.DialPacketConn(connection)
|
||||||
return returnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))
|
return singbridge.ReturnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,82 +1,15 @@
|
|||||||
package shadowsocks_2022
|
package shadowsocks_2022
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
|
|
||||||
B "github.com/sagernet/sing/common/buf"
|
B "github.com/sagernet/sing/common/buf"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
"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/singbridge"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||||
|
|
||||||
func toDestination(socksaddr M.Socksaddr, network net.Network) net.Destination {
|
|
||||||
if socksaddr.IsFqdn() {
|
|
||||||
return net.Destination{
|
|
||||||
Network: network,
|
|
||||||
Address: net.DomainAddress(socksaddr.Fqdn),
|
|
||||||
Port: net.Port(socksaddr.Port),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return net.Destination{
|
|
||||||
Network: network,
|
|
||||||
Address: net.IPAddress(socksaddr.Addr.AsSlice()),
|
|
||||||
Port: net.Port(socksaddr.Port),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func toSocksaddr(destination net.Destination) M.Socksaddr {
|
|
||||||
var addr M.Socksaddr
|
|
||||||
switch destination.Address.Family() {
|
|
||||||
case net.AddressFamilyDomain:
|
|
||||||
addr.Fqdn = destination.Address.Domain()
|
|
||||||
default:
|
|
||||||
addr.Addr = M.AddrFromIP(destination.Address.IP())
|
|
||||||
}
|
|
||||||
addr.Port = uint16(destination.Port)
|
|
||||||
return addr
|
|
||||||
}
|
|
||||||
|
|
||||||
type pipeConnWrapper struct {
|
|
||||||
R io.Reader
|
|
||||||
W buf.Writer
|
|
||||||
net.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *pipeConnWrapper) Close() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *pipeConnWrapper) Read(b []byte) (n int, err error) {
|
|
||||||
return w.R.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *pipeConnWrapper) Write(p []byte) (n int, err error) {
|
|
||||||
n = len(p)
|
|
||||||
var mb buf.MultiBuffer
|
|
||||||
pLen := len(p)
|
|
||||||
for pLen > 0 {
|
|
||||||
buffer := buf.New()
|
|
||||||
if pLen > buf.Size {
|
|
||||||
_, err = buffer.Write(p[:buf.Size])
|
|
||||||
p = p[buf.Size:]
|
|
||||||
} else {
|
|
||||||
buffer.Write(p)
|
|
||||||
}
|
|
||||||
pLen -= int(buffer.Len())
|
|
||||||
mb = append(mb, buffer)
|
|
||||||
}
|
|
||||||
err = w.W.WriteMultiBuffer(mb)
|
|
||||||
if err != nil {
|
|
||||||
n = 0
|
|
||||||
buf.ReleaseMulti(mb)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
type packetConnWrapper struct {
|
type packetConnWrapper struct {
|
||||||
buf.Reader
|
buf.Reader
|
||||||
buf.Writer
|
buf.Writer
|
||||||
@@ -100,7 +33,7 @@ func (w *packetConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
|
|||||||
destination = w.Dest
|
destination = w.Dest
|
||||||
}
|
}
|
||||||
bb.Release()
|
bb.Release()
|
||||||
return toSocksaddr(destination), nil
|
return singbridge.ToSocksaddr(destination), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mb, err := w.ReadMultiBuffer()
|
mb, err := w.ReadMultiBuffer()
|
||||||
@@ -120,14 +53,14 @@ func (w *packetConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
|
|||||||
destination = w.Dest
|
destination = w.Dest
|
||||||
}
|
}
|
||||||
bb.Release()
|
bb.Release()
|
||||||
return toSocksaddr(destination), nil
|
return singbridge.ToSocksaddr(destination), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *packetConnWrapper) WritePacket(buffer *B.Buffer, destination M.Socksaddr) error {
|
func (w *packetConnWrapper) WritePacket(buffer *B.Buffer, destination M.Socksaddr) error {
|
||||||
vBuf := buf.New()
|
vBuf := buf.New()
|
||||||
vBuf.Write(buffer.Bytes())
|
vBuf.Write(buffer.Bytes())
|
||||||
endpoint := toDestination(destination, net.Network_UDP)
|
endpoint := singbridge.ToDestination(destination, net.Network_UDP)
|
||||||
vBuf.UDP = &endpoint
|
vBuf.UDP = &endpoint
|
||||||
return w.Writer.WriteMultiBuffer(buf.MultiBuffer{vBuf})
|
return w.Writer.WriteMultiBuffer(buf.MultiBuffer{vBuf})
|
||||||
}
|
}
|
||||||
@@ -136,10 +69,3 @@ func (w *packetConnWrapper) Close() error {
|
|||||||
buf.ReleaseMulti(w.cached)
|
buf.ReleaseMulti(w.cached)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func returnError(err error) error {
|
|
||||||
if E.IsClosed(err) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
483
proxy/shadowtls/config.pb.go
Normal file
483
proxy/shadowtls/config.pb.go
Normal file
@@ -0,0 +1,483 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.28.1
|
||||||
|
// protoc v3.21.12
|
||||||
|
// source: proxy/shadowtls/config.proto
|
||||||
|
|
||||||
|
package shadowtls
|
||||||
|
|
||||||
|
import (
|
||||||
|
net "github.com/xtls/xray-core/common/net"
|
||||||
|
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 ServerConfig struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
|
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||||
|
Users []*User `protobuf:"bytes,3,rep,name=users,proto3" json:"users,omitempty"`
|
||||||
|
Handshake *HandshakeConfig `protobuf:"bytes,4,opt,name=handshake,proto3" json:"handshake,omitempty"`
|
||||||
|
HandshakeForServerName map[string]*HandshakeConfig `protobuf:"bytes,5,rep,name=handshake_for_server_name,json=handshakeForServerName,proto3" json:"handshake_for_server_name,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
|
StrictMode bool `protobuf:"varint,6,opt,name=strict_mode,json=strictMode,proto3" json:"strict_mode,omitempty"`
|
||||||
|
Detour string `protobuf:"bytes,7,opt,name=detour,proto3" json:"detour,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) Reset() {
|
||||||
|
*x = ServerConfig{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proxy_shadowtls_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ServerConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ServerConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proxy_shadowtls_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 ServerConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ServerConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proxy_shadowtls_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) GetVersion() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Version
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) GetPassword() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Password
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) GetUsers() []*User {
|
||||||
|
if x != nil {
|
||||||
|
return x.Users
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) GetHandshake() *HandshakeConfig {
|
||||||
|
if x != nil {
|
||||||
|
return x.Handshake
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) GetHandshakeForServerName() map[string]*HandshakeConfig {
|
||||||
|
if x != nil {
|
||||||
|
return x.HandshakeForServerName
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) GetStrictMode() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.StrictMode
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ServerConfig) GetDetour() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Detour
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type HandshakeConfig struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Address *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||||
|
Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HandshakeConfig) Reset() {
|
||||||
|
*x = HandshakeConfig{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proxy_shadowtls_config_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HandshakeConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*HandshakeConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *HandshakeConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proxy_shadowtls_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 HandshakeConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*HandshakeConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proxy_shadowtls_config_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HandshakeConfig) GetAddress() *net.IPOrDomain {
|
||||||
|
if x != nil {
|
||||||
|
return x.Address
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *HandshakeConfig) GetPort() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Port
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
|
||||||
|
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||||
|
Level int32 `protobuf:"varint,3,opt,name=level,proto3" json:"level,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *User) Reset() {
|
||||||
|
*x = User{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proxy_shadowtls_config_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *User) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*User) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *User) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proxy_shadowtls_config_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use User.ProtoReflect.Descriptor instead.
|
||||||
|
func (*User) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proxy_shadowtls_config_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *User) GetEmail() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Email
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *User) GetPassword() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Password
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *User) GetLevel() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Level
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type ClientConfig struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Address *net.IPOrDomain `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||||
|
Port uint32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
|
||||||
|
Version uint32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
|
Password string `protobuf:"bytes,4,opt,name=password,proto3" json:"password,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientConfig) Reset() {
|
||||||
|
*x = ClientConfig{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_proxy_shadowtls_config_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientConfig) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ClientConfig) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ClientConfig) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_proxy_shadowtls_config_proto_msgTypes[3]
|
||||||
|
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 ClientConfig.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ClientConfig) Descriptor() ([]byte, []int) {
|
||||||
|
return file_proxy_shadowtls_config_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientConfig) GetAddress() *net.IPOrDomain {
|
||||||
|
if x != nil {
|
||||||
|
return x.Address
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientConfig) GetPort() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Port
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientConfig) GetVersion() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Version
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ClientConfig) GetPassword() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Password
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_proxy_shadowtls_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_proxy_shadowtls_config_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x74, 0x6c,
|
||||||
|
0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14,
|
||||||
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f,
|
||||||
|
0x77, 0x74, 0x6c, 0x73, 0x1a, 0x18, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
||||||
|
0x2f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe1,
|
||||||
|
0x03, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||||
|
0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
|
||||||
|
0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73,
|
||||||
|
0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73,
|
||||||
|
0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x03,
|
||||||
|
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
|
0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x74, 0x6c, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72,
|
||||||
|
0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x12, 0x43, 0x0a, 0x09, 0x68, 0x61, 0x6e, 0x64, 0x73,
|
||||||
|
0x68, 0x61, 0x6b, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x74, 0x6c,
|
||||||
|
0x73, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
|
0x67, 0x52, 0x09, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x12, 0x79, 0x0a, 0x19,
|
||||||
|
0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x73, 0x65,
|
||||||
|
0x72, 0x76, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||||
|
0x3e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61,
|
||||||
|
0x64, 0x6f, 0x77, 0x74, 0x6c, 0x73, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e,
|
||||||
|
0x66, 0x69, 0x67, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x46, 0x6f, 0x72,
|
||||||
|
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52,
|
||||||
|
0x16, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x46, 0x6f, 0x72, 0x53, 0x65, 0x72,
|
||||||
|
0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x63,
|
||||||
|
0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x73, 0x74,
|
||||||
|
0x72, 0x69, 0x63, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x65, 0x74, 0x6f,
|
||||||
|
0x75, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x65, 0x74, 0x6f, 0x75, 0x72,
|
||||||
|
0x1a, 0x70, 0x0a, 0x1b, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x46, 0x6f, 0x72,
|
||||||
|
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
|
||||||
|
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
|
||||||
|
0x79, 0x12, 0x3b, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||||
|
0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68,
|
||||||
|
0x61, 0x64, 0x6f, 0x77, 0x74, 0x6c, 0x73, 0x2e, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b,
|
||||||
|
0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
|
||||||
|
0x38, 0x01, 0x22, 0x5c, 0x0a, 0x0f, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x43,
|
||||||
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
||||||
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
||||||
|
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d,
|
||||||
|
0x61, 0x69, 0x6e, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04,
|
||||||
|
0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74,
|
||||||
|
0x22, 0x4e, 0x0a, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69,
|
||||||
|
0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1a,
|
||||||
|
0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65,
|
||||||
|
0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c,
|
||||||
|
0x22, 0x8f, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
|
0x67, 0x12, 0x35, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||||
|
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
|
||||||
|
0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74,
|
||||||
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x18, 0x0a, 0x07,
|
||||||
|
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76,
|
||||||
|
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||||
|
0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||||
|
0x72, 0x64, 0x42, 0x5e, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
|
||||||
|
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x74, 0x6c, 0x73, 0x50, 0x01,
|
||||||
|
0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c,
|
||||||
|
0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78,
|
||||||
|
0x79, 0x2f, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x14, 0x58, 0x72,
|
||||||
|
0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x53, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x54,
|
||||||
|
0x4c, 0x53, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_proxy_shadowtls_config_proto_rawDescOnce sync.Once
|
||||||
|
file_proxy_shadowtls_config_proto_rawDescData = file_proxy_shadowtls_config_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_proxy_shadowtls_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_proxy_shadowtls_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_proxy_shadowtls_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_proxy_shadowtls_config_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_proxy_shadowtls_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_proxy_shadowtls_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
|
var file_proxy_shadowtls_config_proto_goTypes = []interface{}{
|
||||||
|
(*ServerConfig)(nil), // 0: xray.proxy.shadowtls.ServerConfig
|
||||||
|
(*HandshakeConfig)(nil), // 1: xray.proxy.shadowtls.HandshakeConfig
|
||||||
|
(*User)(nil), // 2: xray.proxy.shadowtls.User
|
||||||
|
(*ClientConfig)(nil), // 3: xray.proxy.shadowtls.ClientConfig
|
||||||
|
nil, // 4: xray.proxy.shadowtls.ServerConfig.HandshakeForServerNameEntry
|
||||||
|
(*net.IPOrDomain)(nil), // 5: xray.common.net.IPOrDomain
|
||||||
|
}
|
||||||
|
var file_proxy_shadowtls_config_proto_depIdxs = []int32{
|
||||||
|
2, // 0: xray.proxy.shadowtls.ServerConfig.users:type_name -> xray.proxy.shadowtls.User
|
||||||
|
1, // 1: xray.proxy.shadowtls.ServerConfig.handshake:type_name -> xray.proxy.shadowtls.HandshakeConfig
|
||||||
|
4, // 2: xray.proxy.shadowtls.ServerConfig.handshake_for_server_name:type_name -> xray.proxy.shadowtls.ServerConfig.HandshakeForServerNameEntry
|
||||||
|
5, // 3: xray.proxy.shadowtls.HandshakeConfig.address:type_name -> xray.common.net.IPOrDomain
|
||||||
|
5, // 4: xray.proxy.shadowtls.ClientConfig.address:type_name -> xray.common.net.IPOrDomain
|
||||||
|
1, // 5: xray.proxy.shadowtls.ServerConfig.HandshakeForServerNameEntry.value:type_name -> xray.proxy.shadowtls.HandshakeConfig
|
||||||
|
6, // [6:6] is the sub-list for method output_type
|
||||||
|
6, // [6:6] is the sub-list for method input_type
|
||||||
|
6, // [6:6] is the sub-list for extension type_name
|
||||||
|
6, // [6:6] is the sub-list for extension extendee
|
||||||
|
0, // [0:6] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_proxy_shadowtls_config_proto_init() }
|
||||||
|
func file_proxy_shadowtls_config_proto_init() {
|
||||||
|
if File_proxy_shadowtls_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_proxy_shadowtls_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ServerConfig); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proxy_shadowtls_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*HandshakeConfig); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proxy_shadowtls_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*User); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_proxy_shadowtls_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ClientConfig); 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_proxy_shadowtls_config_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 5,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_proxy_shadowtls_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_proxy_shadowtls_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_proxy_shadowtls_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_proxy_shadowtls_config_proto = out.File
|
||||||
|
file_proxy_shadowtls_config_proto_rawDesc = nil
|
||||||
|
file_proxy_shadowtls_config_proto_goTypes = nil
|
||||||
|
file_proxy_shadowtls_config_proto_depIdxs = nil
|
||||||
|
}
|
37
proxy/shadowtls/config.proto
Normal file
37
proxy/shadowtls/config.proto
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.proxy.shadowtls;
|
||||||
|
option csharp_namespace = "Xray.Proxy.ShadowTLS";
|
||||||
|
option go_package = "github.com/xtls/xray-core/proxy/shadowtls";
|
||||||
|
option java_package = "com.xray.proxy.shadowtls";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
import "common/net/address.proto";
|
||||||
|
|
||||||
|
message ServerConfig {
|
||||||
|
uint32 version = 1;
|
||||||
|
string password = 2;
|
||||||
|
repeated User users = 3;
|
||||||
|
HandshakeConfig handshake = 4;
|
||||||
|
map<string, HandshakeConfig> handshake_for_server_name = 5;
|
||||||
|
bool strict_mode = 6;
|
||||||
|
string detour = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HandshakeConfig {
|
||||||
|
xray.common.net.IPOrDomain address = 1;
|
||||||
|
uint32 port = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message User {
|
||||||
|
string email = 1;
|
||||||
|
string password = 2;
|
||||||
|
int32 level = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ClientConfig {
|
||||||
|
xray.common.net.IPOrDomain address = 1;
|
||||||
|
uint32 port = 2;
|
||||||
|
uint32 version = 3;
|
||||||
|
string password = 4;
|
||||||
|
}
|
9
proxy/shadowtls/errors.generated.go
Normal file
9
proxy/shadowtls/errors.generated.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package shadowtls
|
||||||
|
|
||||||
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
|
type errPathObjHolder struct{}
|
||||||
|
|
||||||
|
func newError(values ...interface{}) *errors.Error {
|
||||||
|
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||||
|
}
|
136
proxy/shadowtls/inbound.go
Normal file
136
proxy/shadowtls/inbound.go
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
package shadowtls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-shadowtls"
|
||||||
|
sing_common "github.com/sagernet/sing/common"
|
||||||
|
"github.com/sagernet/sing/common/auth"
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/log"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/singbridge"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/inbound"
|
||||||
|
"github.com/xtls/xray-core/features/routing"
|
||||||
|
"github.com/xtls/xray-core/proxy"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
|
return NewServer(ctx, config.(*ServerConfig))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Inbound struct {
|
||||||
|
service *shadowtls.Service
|
||||||
|
inboundManager inbound.Manager
|
||||||
|
detour string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(ctx context.Context, config *ServerConfig) (*Inbound, error) {
|
||||||
|
v := core.MustFromContext(ctx)
|
||||||
|
inbound := &Inbound{
|
||||||
|
inboundManager: v.GetFeature(inbound.ManagerType()).(inbound.Manager),
|
||||||
|
detour: config.Detour,
|
||||||
|
}
|
||||||
|
var handshakeForServerName map[string]shadowtls.HandshakeConfig
|
||||||
|
if config.Version > 1 {
|
||||||
|
handshakeForServerName = make(map[string]shadowtls.HandshakeConfig)
|
||||||
|
for serverName, serverConfig := range config.HandshakeForServerName {
|
||||||
|
handshakeForServerName[serverName] = shadowtls.HandshakeConfig{
|
||||||
|
Server: singbridge.ToSocksaddr(net.Destination{
|
||||||
|
Address: serverConfig.Address.AsAddress(),
|
||||||
|
Port: net.Port(serverConfig.Port),
|
||||||
|
}),
|
||||||
|
Dialer: N.SystemDialer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
service, err := shadowtls.NewService(shadowtls.ServiceConfig{
|
||||||
|
Version: int(config.Version),
|
||||||
|
Password: config.Password,
|
||||||
|
Users: sing_common.Map(config.Users, func(it *User) shadowtls.User {
|
||||||
|
return shadowtls.User{
|
||||||
|
Name: it.Email,
|
||||||
|
Password: it.Password,
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
Handshake: shadowtls.HandshakeConfig{
|
||||||
|
Server: singbridge.ToSocksaddr(net.Destination{
|
||||||
|
Address: config.Handshake.Address.AsAddress(),
|
||||||
|
Port: net.Port(config.Handshake.Port),
|
||||||
|
}),
|
||||||
|
Dialer: N.SystemDialer,
|
||||||
|
},
|
||||||
|
HandshakeForServerName: handshakeForServerName,
|
||||||
|
StrictMode: config.StrictMode,
|
||||||
|
Handler: inbound,
|
||||||
|
Logger: singbridge.NewLogger(newError),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "create service")
|
||||||
|
}
|
||||||
|
inbound.service = service
|
||||||
|
return inbound, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Inbound) Network() []net.Network {
|
||||||
|
return []net.Network{net.Network_TCP}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Inbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
|
||||||
|
inbound := session.InboundFromContext(ctx)
|
||||||
|
var metadata M.Metadata
|
||||||
|
if inbound.Source.IsValid() {
|
||||||
|
metadata.Source = M.ParseSocksaddr(inbound.Source.NetAddr())
|
||||||
|
}
|
||||||
|
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
||||||
|
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Inbound) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
|
||||||
|
inboundHandler, err := i.inboundManager.GetHandler(ctx, i.detour)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "detour not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
inboundWrapper, loaded := inboundHandler.(proxy.GetInbound)
|
||||||
|
if !loaded {
|
||||||
|
return newError("can't get inbound proxy from handler.")
|
||||||
|
}
|
||||||
|
|
||||||
|
inboundDetour := inboundWrapper.GetInbound()
|
||||||
|
|
||||||
|
email, _ := auth.UserFromContext[string](ctx)
|
||||||
|
inbound := session.InboundFromContext(ctx)
|
||||||
|
inbound.User = &protocol.MemoryUser{
|
||||||
|
Email: email,
|
||||||
|
}
|
||||||
|
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
||||||
|
From: metadata.Source,
|
||||||
|
To: metadata.Destination,
|
||||||
|
Status: log.AccessAccepted,
|
||||||
|
Email: email,
|
||||||
|
})
|
||||||
|
newError("tunnelling request to detour").WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
return inboundDetour.Process(ctx, net.Network_TCP, conn, session.DispatcherFromContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Inbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||||
|
return os.ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Inbound) NewError(ctx context.Context, err error) {
|
||||||
|
if E.IsClosed(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
newError(err).AtWarning().WriteToLog()
|
||||||
|
}
|
110
proxy/shadowtls/outbound.go
Normal file
110
proxy/shadowtls/outbound.go
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
package shadowtls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
"github.com/sagernet/sing-shadowtls"
|
||||||
|
sing_common "github.com/sagernet/sing/common"
|
||||||
|
utls "github.com/sagernet/utls"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/singbridge"
|
||||||
|
"github.com/xtls/xray-core/transport"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
internet_tls "github.com/xtls/xray-core/transport/internet/tls"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
|
return NewClient(ctx, config.(*ClientConfig))
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
type Outbound struct {
|
||||||
|
ctx context.Context
|
||||||
|
clientConfig shadowtls.ClientConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
|
||||||
|
return &Outbound{
|
||||||
|
ctx: ctx,
|
||||||
|
clientConfig: shadowtls.ClientConfig{
|
||||||
|
Version: int(config.Version),
|
||||||
|
Password: config.Password,
|
||||||
|
Server: singbridge.ToSocksaddr(net.Destination{
|
||||||
|
Address: config.Address.AsAddress(),
|
||||||
|
Port: net.Port(config.Port),
|
||||||
|
}),
|
||||||
|
Logger: singbridge.NewLogger(newError),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||||
|
var inboundConn net.Conn
|
||||||
|
inbound := session.InboundFromContext(ctx)
|
||||||
|
if inbound != nil {
|
||||||
|
inboundConn = inbound.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
outbound := session.OutboundFromContext(ctx)
|
||||||
|
if outbound == nil || !outbound.Target.IsValid() {
|
||||||
|
return newError("target not specified")
|
||||||
|
}
|
||||||
|
destination := outbound.Target
|
||||||
|
|
||||||
|
if destination.Network != net.Network_TCP {
|
||||||
|
return newError("only TCP is supported")
|
||||||
|
}
|
||||||
|
|
||||||
|
newError("tunneling request to ", destination, " via ", o.clientConfig.Server).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
|
||||||
|
var client *shadowtls.Client
|
||||||
|
clientConfig := o.clientConfig
|
||||||
|
clientConfig.Dialer = singbridge.NewTLSDialer(dialer, func(conn net.Conn, xrayConfig *internet_tls.Config, config *tls.Config) net.Conn {
|
||||||
|
if fingerprint := GetFingerprint(xrayConfig.Fingerprint); fingerprint != nil {
|
||||||
|
client.SetHandshakeFunc(uTLSHandshakeFunc(config, fingerprint))
|
||||||
|
} else {
|
||||||
|
client.SetHandshakeFunc(shadowtls.DefaultTLSHandshakeFunc(clientConfig.Password, config))
|
||||||
|
}
|
||||||
|
return conn
|
||||||
|
})
|
||||||
|
var err error
|
||||||
|
client, err = shadowtls.NewClient(clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
return newError("failed to create client").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := client.DialContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return newError("failed to connect to server").Base(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return singbridge.CopyConn(ctx, inboundConn, link, conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func uTLSHandshakeFunc(config *tls.Config, clientHelloID *utls.ClientHelloID) shadowtls.TLSHandshakeFunc {
|
||||||
|
return func(ctx context.Context, conn net.Conn, sessionIDGenerator shadowtls.TLSSessionIDGeneratorFunc) error {
|
||||||
|
tlsConfig := &utls.Config{
|
||||||
|
Rand: config.Rand,
|
||||||
|
Time: config.Time,
|
||||||
|
VerifyPeerCertificate: config.VerifyPeerCertificate,
|
||||||
|
RootCAs: config.RootCAs,
|
||||||
|
NextProtos: config.NextProtos,
|
||||||
|
ServerName: config.ServerName,
|
||||||
|
InsecureSkipVerify: config.InsecureSkipVerify,
|
||||||
|
CipherSuites: config.CipherSuites,
|
||||||
|
MinVersion: config.MinVersion,
|
||||||
|
MaxVersion: config.MaxVersion,
|
||||||
|
CurvePreferences: sing_common.Map(config.CurvePreferences, func(it tls.CurveID) utls.CurveID {
|
||||||
|
return utls.CurveID(it)
|
||||||
|
}),
|
||||||
|
SessionTicketsDisabled: config.SessionTicketsDisabled,
|
||||||
|
Renegotiation: utls.RenegotiationSupport(config.Renegotiation),
|
||||||
|
SessionIDGenerator: sessionIDGenerator,
|
||||||
|
}
|
||||||
|
tlsConn := utls.UClient(conn, tlsConfig, *clientHelloID)
|
||||||
|
return tlsConn.HandshakeContext(ctx)
|
||||||
|
}
|
||||||
|
}
|
3
proxy/shadowtls/shadowtls.go
Normal file
3
proxy/shadowtls/shadowtls.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package shadowtls
|
||||||
|
|
||||||
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
105
proxy/shadowtls/utls.go
Normal file
105
proxy/shadowtls/utls.go
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
package shadowtls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
|
utls "github.com/sagernet/utls"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
bigInt, _ := rand.Int(rand.Reader, big.NewInt(int64(len(ModernFingerprints))))
|
||||||
|
stopAt := int(bigInt.Int64())
|
||||||
|
i := 0
|
||||||
|
for _, v := range ModernFingerprints {
|
||||||
|
if i == stopAt {
|
||||||
|
PresetFingerprints["random"] = v
|
||||||
|
break
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
weights := utls.DefaultWeights
|
||||||
|
weights.TLSVersMax_Set_VersionTLS13 = 1
|
||||||
|
weights.FirstKeyShare_Set_CurveP256 = 0
|
||||||
|
randomized := utls.HelloRandomized
|
||||||
|
randomized.Seed, _ = utls.NewPRNGSeed()
|
||||||
|
randomized.Weights = &weights
|
||||||
|
PresetFingerprints["randomized"] = &randomized
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetFingerprint(name string) (fingerprint *utls.ClientHelloID) {
|
||||||
|
if name == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fingerprint = PresetFingerprints[name]; fingerprint != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fingerprint = ModernFingerprints[name]; fingerprint != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if fingerprint = OtherFingerprints[name]; fingerprint != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var PresetFingerprints = map[string]*utls.ClientHelloID{
|
||||||
|
// Recommended preset options in GUI clients
|
||||||
|
"chrome": &utls.HelloChrome_Auto,
|
||||||
|
"firefox": &utls.HelloFirefox_Auto,
|
||||||
|
"safari": &utls.HelloSafari_Auto,
|
||||||
|
"ios": &utls.HelloIOS_Auto,
|
||||||
|
"android": &utls.HelloAndroid_11_OkHttp,
|
||||||
|
"edge": &utls.HelloEdge_Auto,
|
||||||
|
"360": &utls.Hello360_Auto,
|
||||||
|
"qq": &utls.HelloQQ_Auto,
|
||||||
|
"random": nil,
|
||||||
|
"randomized": nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
var ModernFingerprints = map[string]*utls.ClientHelloID{
|
||||||
|
// One of these will be chosen as `random` at startup
|
||||||
|
"hellofirefox_99": &utls.HelloFirefox_99,
|
||||||
|
"hellofirefox_102": &utls.HelloFirefox_102,
|
||||||
|
"hellofirefox_105": &utls.HelloFirefox_105,
|
||||||
|
"hellochrome_83": &utls.HelloChrome_83,
|
||||||
|
"hellochrome_87": &utls.HelloChrome_87,
|
||||||
|
"hellochrome_96": &utls.HelloChrome_96,
|
||||||
|
"hellochrome_100": &utls.HelloChrome_100,
|
||||||
|
"hellochrome_102": &utls.HelloChrome_102,
|
||||||
|
"hellochrome_106_shuffle": &utls.HelloChrome_106_Shuffle,
|
||||||
|
"helloios_13": &utls.HelloIOS_13,
|
||||||
|
"helloios_14": &utls.HelloIOS_14,
|
||||||
|
"helloedge_85": &utls.HelloEdge_85,
|
||||||
|
"helloedge_106": &utls.HelloEdge_106,
|
||||||
|
"hellosafari_16_0": &utls.HelloSafari_16_0,
|
||||||
|
"hello360_11_0": &utls.Hello360_11_0,
|
||||||
|
"helloqq_11_1": &utls.HelloQQ_11_1,
|
||||||
|
}
|
||||||
|
|
||||||
|
var OtherFingerprints = map[string]*utls.ClientHelloID{
|
||||||
|
// Golang, randomized, auto, and fingerprints that are too old
|
||||||
|
"hellogolang": &utls.HelloGolang,
|
||||||
|
"hellorandomized": &utls.HelloRandomized,
|
||||||
|
"hellorandomizedalpn": &utls.HelloRandomizedALPN,
|
||||||
|
"hellorandomizednoalpn": &utls.HelloRandomizedNoALPN,
|
||||||
|
"hellofirefox_auto": &utls.HelloFirefox_Auto,
|
||||||
|
"hellofirefox_55": &utls.HelloFirefox_55,
|
||||||
|
"hellofirefox_56": &utls.HelloFirefox_56,
|
||||||
|
"hellofirefox_63": &utls.HelloFirefox_63,
|
||||||
|
"hellofirefox_65": &utls.HelloFirefox_65,
|
||||||
|
"hellochrome_auto": &utls.HelloChrome_Auto,
|
||||||
|
"hellochrome_58": &utls.HelloChrome_58,
|
||||||
|
"hellochrome_62": &utls.HelloChrome_62,
|
||||||
|
"hellochrome_70": &utls.HelloChrome_70,
|
||||||
|
"hellochrome_72": &utls.HelloChrome_72,
|
||||||
|
"helloios_auto": &utls.HelloIOS_Auto,
|
||||||
|
"helloios_11_1": &utls.HelloIOS_11_1,
|
||||||
|
"helloios_12_1": &utls.HelloIOS_12_1,
|
||||||
|
"helloandroid_11_okhttp": &utls.HelloAndroid_11_OkHttp,
|
||||||
|
"helloedge_auto": &utls.HelloEdge_Auto,
|
||||||
|
"hellosafari_auto": &utls.HelloSafari_Auto,
|
||||||
|
"hello360_auto": &utls.Hello360_Auto,
|
||||||
|
"hello360_7_5": &utls.Hello360_7_5,
|
||||||
|
"helloqq_auto": &utls.HelloQQ_Auto,
|
||||||
|
}
|
@@ -2,12 +2,14 @@ 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"
|
||||||
@@ -15,9 +17,11 @@ 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
|
||||||
@@ -93,6 +97,49 @@ 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)
|
||||||
@@ -146,6 +193,13 @@ 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))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,4 +215,11 @@ 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,12 +1,22 @@
|
|||||||
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 (
|
||||||
@@ -17,13 +27,25 @@ 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
|
||||||
@@ -68,6 +90,10 @@ 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 {
|
||||||
@@ -175,6 +201,10 @@ 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)
|
||||||
@@ -258,3 +288,66 @@ 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,6 +5,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
@@ -12,6 +13,7 @@ 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"
|
||||||
@@ -21,16 +23,25 @@ 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.
|
||||||
@@ -224,6 +235,39 @@ 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,
|
||||||
@@ -233,7 +277,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, statConn)
|
return s.handleConnection(ctx, sessionPolicy, destination, clientReader, buf.NewWriter(conn), dispatcher, iConn, rawConn, 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 {
|
||||||
@@ -299,7 +343,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, statConn *stat.CounterConnection,
|
clientWriter buf.Writer, dispatcher routing.Dispatcher, iConn stat.Connection, rawConn syscall.RawConn, 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)
|
||||||
@@ -312,7 +356,18 @@ 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
|
||||||
@@ -351,6 +406,12 @@ 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-vision".
|
// Flow of the account. May be "xtls-rprx-direct".
|
||||||
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-vision".
|
// Flow settings. May be "xtls-rprx-direct".
|
||||||
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-vision".
|
// Flow settings. May be "xtls-rprx-direct".
|
||||||
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.XRV:
|
case vless.XRO, vless.XRD, 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,6 +6,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -23,6 +24,7 @@ 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 (
|
||||||
@@ -34,23 +36,6 @@ var (
|
|||||||
tlsClientHandShakeStart = []byte{0x16, 0x03}
|
tlsClientHandShakeStart = []byte{0x16, 0x03}
|
||||||
tlsServerHandShakeStart = []byte{0x16, 0x03, 0x03}
|
tlsServerHandShakeStart = []byte{0x16, 0x03, 0x03}
|
||||||
tlsApplicationDataStart = []byte{0x17, 0x03, 0x03}
|
tlsApplicationDataStart = []byte{0x17, 0x03, 0x03}
|
||||||
|
|
||||||
Tls13CipherSuiteDic = map[uint16]string{
|
|
||||||
0x1301: "TLS_AES_128_GCM_SHA256",
|
|
||||||
0x1302: "TLS_AES_256_GCM_SHA384",
|
|
||||||
0x1303: "TLS_CHACHA20_POLY1305_SHA256",
|
|
||||||
0x1304: "TLS_AES_128_CCM_SHA256",
|
|
||||||
0x1305: "TLS_AES_128_CCM_8_SHA256",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
tlsHandshakeTypeClientHello byte = 0x01
|
|
||||||
tlsHandshakeTypeServerHello byte = 0x02
|
|
||||||
|
|
||||||
CommandPaddingContinue byte = 0x00
|
|
||||||
CommandPaddingEnd byte = 0x01
|
|
||||||
CommandPaddingDirect byte = 0x02
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var addrParser = protocol.NewAddressParser(
|
var addrParser = protocol.NewAddressParser(
|
||||||
@@ -204,6 +189,65 @@ 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,
|
||||||
@@ -212,7 +256,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
|||||||
) error {
|
) error {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
var ct stats.Counter
|
var ct stats.Counter
|
||||||
withinPaddingBuffers := true
|
filterUUID := true
|
||||||
shouldSwitchToDirectCopy := false
|
shouldSwitchToDirectCopy := false
|
||||||
var remainingContent int32 = -1
|
var remainingContent int32 = -1
|
||||||
var remainingPadding int32 = -1
|
var remainingPadding int32 = -1
|
||||||
@@ -250,15 +294,13 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
|||||||
}
|
}
|
||||||
buffer, err := reader.ReadMultiBuffer()
|
buffer, err := reader.ReadMultiBuffer()
|
||||||
if !buffer.IsEmpty() {
|
if !buffer.IsEmpty() {
|
||||||
if withinPaddingBuffers || *numberOfPacketToFilter > 0 {
|
if filterUUID && (*isTLS || *numberOfPacketToFilter > 0) {
|
||||||
buffer = XtlsUnpadding(ctx, buffer, userUUID, &remainingContent, &remainingPadding, ¤tCommand)
|
buffer = XtlsUnpadding(ctx, buffer, userUUID, &remainingContent, &remainingPadding, ¤tCommand)
|
||||||
if remainingContent == 0 && remainingPadding == 0 {
|
if remainingContent == 0 && remainingPadding == 0 {
|
||||||
if currentCommand == 1 {
|
if currentCommand == 1 {
|
||||||
withinPaddingBuffers = false
|
filterUUID = false
|
||||||
remainingContent = -1
|
|
||||||
remainingPadding = -1 // set to initial state to parse the next padding
|
|
||||||
} else if currentCommand == 2 {
|
} else if currentCommand == 2 {
|
||||||
withinPaddingBuffers = false
|
filterUUID = false
|
||||||
shouldSwitchToDirectCopy = true
|
shouldSwitchToDirectCopy = true
|
||||||
// XTLS Vision processes struct TLS Conn's input and rawInput
|
// XTLS Vision processes struct TLS Conn's input and rawInput
|
||||||
if inputBuffer, err := buf.ReadFrom(input); err == nil {
|
if inputBuffer, err := buf.ReadFrom(input); err == nil {
|
||||||
@@ -271,15 +313,9 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
|||||||
buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
|
buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if currentCommand == 0 {
|
} else if currentCommand != 0 {
|
||||||
withinPaddingBuffers = true
|
|
||||||
} else {
|
|
||||||
newError("XtlsRead unknown command ", currentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
newError("XtlsRead unknown command ", currentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
} else if remainingContent > 0 || remainingPadding > 0 {
|
|
||||||
withinPaddingBuffers = true
|
|
||||||
} else {
|
|
||||||
withinPaddingBuffers = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if *numberOfPacketToFilter > 0 {
|
if *numberOfPacketToFilter > 0 {
|
||||||
@@ -306,12 +342,12 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
|||||||
|
|
||||||
// XtlsWrite filter and write xtls protocol
|
// XtlsWrite filter and write xtls protocol
|
||||||
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter,
|
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter,
|
||||||
ctx context.Context, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool,
|
ctx context.Context, userUUID *[]byte, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool,
|
||||||
cipher *uint16, remainingServerHello *int32,
|
cipher *uint16, remainingServerHello *int32,
|
||||||
) error {
|
) error {
|
||||||
err := func() error {
|
err := func() error {
|
||||||
var ct stats.Counter
|
var ct stats.Counter
|
||||||
isPadding := true
|
filterTlsApplicationData := true
|
||||||
shouldSwitchToDirectCopy := false
|
shouldSwitchToDirectCopy := false
|
||||||
for {
|
for {
|
||||||
buffer, err := reader.ReadMultiBuffer()
|
buffer, err := reader.ReadMultiBuffer()
|
||||||
@@ -319,26 +355,27 @@ func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdate
|
|||||||
if *numberOfPacketToFilter > 0 {
|
if *numberOfPacketToFilter > 0 {
|
||||||
XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx)
|
XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx)
|
||||||
}
|
}
|
||||||
if isPadding {
|
if filterTlsApplicationData && *isTLS {
|
||||||
buffer = ReshapeMultiBuffer(ctx, buffer)
|
buffer = ReshapeMultiBuffer(ctx, buffer)
|
||||||
var xtlsSpecIndex int
|
var xtlsSpecIndex int
|
||||||
for i, b := range buffer {
|
for i, b := range buffer {
|
||||||
if *isTLS && b.Len() >= 6 && bytes.Equal(tlsApplicationDataStart, b.BytesTo(3)) {
|
if b.Len() >= 6 && bytes.Equal(tlsApplicationDataStart, b.BytesTo(3)) {
|
||||||
var command byte = CommandPaddingEnd
|
var command byte = 0x01
|
||||||
if *enableXtls {
|
if *enableXtls {
|
||||||
shouldSwitchToDirectCopy = true
|
shouldSwitchToDirectCopy = true
|
||||||
xtlsSpecIndex = i
|
xtlsSpecIndex = i
|
||||||
command = CommandPaddingDirect
|
command = 0x02
|
||||||
}
|
}
|
||||||
isPadding = false
|
filterTlsApplicationData = false
|
||||||
buffer[i] = XtlsPadding(b, command, nil, *isTLS, ctx)
|
buffer[i] = XtlsPadding(b, command, userUUID, ctx)
|
||||||
break
|
break
|
||||||
} else if !*isTLS12orAbove && *numberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early
|
} else if !*isTLS12orAbove && *numberOfPacketToFilter <= 0 {
|
||||||
isPadding = false
|
// maybe tls 1.1 or 1.0
|
||||||
buffer[i] = XtlsPadding(b, CommandPaddingEnd, nil, *isTLS, ctx)
|
filterTlsApplicationData = false
|
||||||
|
buffer[i] = XtlsPadding(b, 0x01, userUUID, ctx)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
buffer[i] = XtlsPadding(b, CommandPaddingContinue, nil, *isTLS, ctx)
|
buffer[i] = XtlsPadding(b, 0x00, userUUID, ctx)
|
||||||
}
|
}
|
||||||
if shouldSwitchToDirectCopy {
|
if shouldSwitchToDirectCopy {
|
||||||
encryptBuffer, directBuffer := buf.SplitMulti(buffer, xtlsSpecIndex+1)
|
encryptBuffer, directBuffer := buf.SplitMulti(buffer, xtlsSpecIndex+1)
|
||||||
@@ -385,7 +422,7 @@ func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXt
|
|||||||
*numberOfPacketToFilter--
|
*numberOfPacketToFilter--
|
||||||
if b.Len() >= 6 {
|
if b.Len() >= 6 {
|
||||||
startsBytes := b.BytesTo(6)
|
startsBytes := b.BytesTo(6)
|
||||||
if bytes.Equal(tlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == tlsHandshakeTypeServerHello {
|
if bytes.Equal(tlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == 0x02 {
|
||||||
*remainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5
|
*remainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5
|
||||||
*isTLS12orAbove = true
|
*isTLS12orAbove = true
|
||||||
*isTLS = true
|
*isTLS = true
|
||||||
@@ -396,7 +433,7 @@ func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXt
|
|||||||
} else {
|
} else {
|
||||||
newError("XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx))
|
newError("XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
} else if bytes.Equal(tlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == tlsHandshakeTypeClientHello {
|
} else if bytes.Equal(tlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == 0x01 {
|
||||||
*isTLS = true
|
*isTLS = true
|
||||||
newError("XtlsFilterTls found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
newError("XtlsFilterTls found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
@@ -432,75 +469,68 @@ func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXt
|
|||||||
|
|
||||||
// ReshapeMultiBuffer prepare multi buffer for padding stucture (max 21 bytes)
|
// ReshapeMultiBuffer prepare multi buffer for padding stucture (max 21 bytes)
|
||||||
func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer {
|
func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer {
|
||||||
needReshape := 0
|
needReshape := false
|
||||||
for _, b := range buffer {
|
for _, b := range buffer {
|
||||||
if b.Len() >= buf.Size-21 {
|
if b.Len() >= buf.Size-21 {
|
||||||
needReshape += 1
|
needReshape = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if needReshape == 0 {
|
if !needReshape {
|
||||||
return buffer
|
return buffer
|
||||||
}
|
}
|
||||||
mb2 := make(buf.MultiBuffer, 0, len(buffer)+needReshape)
|
mb2 := make(buf.MultiBuffer, 0, len(buffer))
|
||||||
toPrint := ""
|
print := ""
|
||||||
for i, buffer1 := range buffer {
|
for _, b := range buffer {
|
||||||
if buffer1.Len() >= buf.Size-21 {
|
if b.Len() >= buf.Size-21 {
|
||||||
index := int32(bytes.LastIndex(buffer1.Bytes(), tlsApplicationDataStart))
|
index := int32(bytes.LastIndex(b.Bytes(), tlsApplicationDataStart))
|
||||||
if index <= 0 || index > buf.Size-21 {
|
if index <= 0 {
|
||||||
index = buf.Size / 2
|
index = buf.Size / 2
|
||||||
}
|
}
|
||||||
|
buffer1 := buf.New()
|
||||||
buffer2 := buf.New()
|
buffer2 := buf.New()
|
||||||
buffer2.Write(buffer1.BytesFrom(index))
|
buffer1.Write(b.BytesTo(index))
|
||||||
buffer1.Resize(0, index)
|
buffer2.Write(b.BytesFrom(index))
|
||||||
mb2 = append(mb2, buffer1, buffer2)
|
mb2 = append(mb2, buffer1, buffer2)
|
||||||
toPrint += " " + strconv.Itoa(int(buffer1.Len())) + " " + strconv.Itoa(int(buffer2.Len()))
|
print += " " + strconv.Itoa(int(buffer1.Len())) + " " + strconv.Itoa(int(buffer2.Len()))
|
||||||
} else {
|
} else {
|
||||||
mb2 = append(mb2, buffer1)
|
newbuffer := buf.New()
|
||||||
toPrint += " " + strconv.Itoa(int(buffer1.Len()))
|
newbuffer.Write(b.Bytes())
|
||||||
|
mb2 = append(mb2, newbuffer)
|
||||||
|
print += " " + strconv.Itoa(int(b.Len()))
|
||||||
}
|
}
|
||||||
buffer[i] = nil
|
|
||||||
}
|
}
|
||||||
buffer = buffer[:0]
|
buf.ReleaseMulti(buffer)
|
||||||
newError("ReshapeMultiBuffer ", toPrint).WriteToLog(session.ExportIDToError(ctx))
|
newError("ReshapeMultiBuffer ", print).WriteToLog(session.ExportIDToError(ctx))
|
||||||
return mb2
|
return mb2
|
||||||
}
|
}
|
||||||
|
|
||||||
// XtlsPadding add padding to eliminate length siganature during tls handshake
|
// XtlsPadding add padding to eliminate length siganature during tls handshake
|
||||||
func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, longPadding bool, ctx context.Context) *buf.Buffer {
|
func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, ctx context.Context) *buf.Buffer {
|
||||||
var contentLen int32 = 0
|
var contantLen int32 = 0
|
||||||
var paddingLen int32 = 0
|
var paddingLen int32 = 0
|
||||||
if b != nil {
|
if b != nil {
|
||||||
contentLen = b.Len()
|
contantLen = b.Len()
|
||||||
}
|
}
|
||||||
if contentLen < 900 && longPadding {
|
if contantLen < 900 {
|
||||||
l, err := rand.Int(rand.Reader, big.NewInt(500))
|
l, err := rand.Int(rand.Reader, big.NewInt(500))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
paddingLen = int32(l.Int64()) + 900 - contentLen
|
paddingLen = int32(l.Int64()) + 900 - contantLen
|
||||||
} else {
|
|
||||||
l, err := rand.Int(rand.Reader, big.NewInt(256))
|
|
||||||
if err != nil {
|
|
||||||
newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
}
|
|
||||||
paddingLen = int32(l.Int64())
|
|
||||||
}
|
|
||||||
if paddingLen > buf.Size - 21 - contentLen {
|
|
||||||
paddingLen = buf.Size - 21 - contentLen
|
|
||||||
}
|
}
|
||||||
newbuffer := buf.New()
|
newbuffer := buf.New()
|
||||||
if userUUID != nil {
|
if userUUID != nil {
|
||||||
newbuffer.Write(*userUUID)
|
newbuffer.Write(*userUUID)
|
||||||
*userUUID = nil
|
*userUUID = nil
|
||||||
}
|
}
|
||||||
newbuffer.Write([]byte{command, byte(contentLen >> 8), byte(contentLen), byte(paddingLen >> 8), byte(paddingLen)})
|
newbuffer.Write([]byte{command, byte(contantLen >> 8), byte(contantLen), byte(paddingLen >> 8), byte(paddingLen)})
|
||||||
if b != nil {
|
if (b != nil) {
|
||||||
newbuffer.Write(b.Bytes())
|
newbuffer.Write(b.Bytes())
|
||||||
b.Release()
|
b.Release()
|
||||||
b = nil
|
b = nil
|
||||||
}
|
}
|
||||||
newbuffer.Extend(paddingLen)
|
newbuffer.Extend(paddingLen)
|
||||||
newError("XtlsPadding ", contentLen, " ", paddingLen, " ", command).WriteToLog(session.ExportIDToError(ctx))
|
newError("XtlsPadding ", contantLen, " ", paddingLen, " ", command).WriteToLog(session.ExportIDToError(ctx))
|
||||||
return newbuffer
|
return newbuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,7 +545,6 @@ func XtlsUnpadding(ctx context.Context, buffer buf.MultiBuffer, userUUID []byte,
|
|||||||
posByte = 16
|
posByte = 16
|
||||||
*remainingContent = 0
|
*remainingContent = 0
|
||||||
*remainingPadding = 0
|
*remainingPadding = 0
|
||||||
*currentCommand = 0
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -574,3 +603,11 @@ func XtlsUnpadding(ctx context.Context, buffer buf.MultiBuffer, userUUID []byte,
|
|||||||
buf.ReleaseMulti(buffer)
|
buf.ReleaseMulti(buffer)
|
||||||
return mb2
|
return mb2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var Tls13CipherSuiteDic = map[uint16]string{
|
||||||
|
0x1301: "TLS_AES_128_GCM_SHA256",
|
||||||
|
0x1302: "TLS_AES_256_GCM_SHA384",
|
||||||
|
0x1303: "TLS_CHACHA20_POLY1305_SHA256",
|
||||||
|
0x1304: "TLS_AES_128_CCM_SHA256",
|
||||||
|
0x1305: "TLS_AES_128_CCM_8_SHA256",
|
||||||
|
}
|
||||||
|
@@ -20,6 +20,7 @@ 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"
|
||||||
@@ -36,8 +37,11 @@ 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
|
||||||
@@ -49,6 +53,13 @@ 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.
|
||||||
@@ -230,6 +241,12 @@ 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
|
||||||
@@ -450,52 +467,79 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
var rawConn syscall.RawConn
|
var rawConn syscall.RawConn
|
||||||
var input *bytes.Reader
|
var input *bytes.Reader
|
||||||
var rawInput *bytes.Buffer
|
var rawInput *bytes.Buffer
|
||||||
|
allowNoneFlow := false
|
||||||
|
accountFlow := account.Flow
|
||||||
|
flows := strings.Split(account.Flow, ",")
|
||||||
|
for _, f := range flows {
|
||||||
|
t := strings.TrimSpace(f)
|
||||||
|
if t == "none" {
|
||||||
|
allowNoneFlow = true
|
||||||
|
} else {
|
||||||
|
accountFlow = t
|
||||||
|
}
|
||||||
|
}
|
||||||
switch requestAddons.Flow {
|
switch requestAddons.Flow {
|
||||||
case vless.XRV:
|
case vless.XRO, vless.XRD, vless.XRV:
|
||||||
if account.Flow == requestAddons.Flow {
|
if accountFlow == requestAddons.Flow {
|
||||||
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()
|
||||||
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:
|
||||||
var t reflect.Type
|
if requestAddons.Flow == vless.XRV {
|
||||||
var p uintptr
|
var t reflect.Type
|
||||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
var p uintptr
|
||||||
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
|
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||||
return newError(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning()
|
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
|
||||||
|
return newError(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning()
|
||||||
|
}
|
||||||
|
netConn = tlsConn.NetConn()
|
||||||
|
if pc, ok := netConn.(*proxyproto.Conn); ok {
|
||||||
|
netConn = pc.Raw()
|
||||||
|
// 8192 > 4096, there is no need to process pc's bufReader
|
||||||
|
}
|
||||||
|
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 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("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning()
|
return newError(`failed to use ` + requestAddons.Flow + `, maybe "security" is not "xtls"`).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()
|
||||||
}
|
}
|
||||||
case "":
|
case "", "none":
|
||||||
if account.Flow == vless.XRV && (request.Command == protocol.RequestCommandTCP || isMuxAndNotXUDP(request, first)) {
|
if accountFlow == vless.XRV && !allowNoneFlow && (request.Command == protocol.RequestCommandTCP || isMuxAndNotXUDP(request, first)) {
|
||||||
return newError(account.ID.String() + " is not able to use \"\". Note that the pure TLS proxy has certain TLS in TLS characters.").AtWarning()
|
return newError(account.ID.String() + " is not able to use " + vless.XRV +
|
||||||
|
". Note the pure tls proxy has certain tls in tls characters. Append \",none\" in flow to suppress").AtWarning()
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return newError("unknown request flow " + requestAddons.Flow).AtWarning()
|
return newError("unknown request flow " + requestAddons.Flow).AtWarning()
|
||||||
@@ -545,8 +589,12 @@ 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)
|
||||||
err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
|
if requestAddons.Flow == vless.XRV {
|
||||||
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
|
||||||
|
&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))
|
||||||
@@ -576,9 +624,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
}
|
}
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello, ctx)
|
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello, ctx)
|
||||||
multiBuffer = encoding.ReshapeMultiBuffer(ctx, multiBuffer)
|
if isTLS {
|
||||||
for i, b := range multiBuffer {
|
multiBuffer = encoding.ReshapeMultiBuffer(ctx, multiBuffer)
|
||||||
multiBuffer[i] = encoding.XtlsPadding(b, encoding.CommandPaddingContinue, &userUUID, isTLS, ctx)
|
for i, b := range multiBuffer {
|
||||||
|
multiBuffer[i] = encoding.XtlsPadding(b, 0x00, &userUUID, ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := clientWriter.WriteMultiBuffer(multiBuffer); err != nil {
|
if err := clientWriter.WriteMultiBuffer(multiBuffer); err != nil {
|
||||||
@@ -595,7 +645,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
if statConn != nil {
|
if statConn != nil {
|
||||||
counter = statConn.WriteCounter
|
counter = statConn.WriteCounter
|
||||||
}
|
}
|
||||||
err = encoding.XtlsWrite(serverReader, clientWriter, timer, netConn, counter, ctx, &numberOfPacketToFilter,
|
err = encoding.XtlsWrite(serverReader, clientWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter,
|
||||||
&enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
&enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||||
} else {
|
} else {
|
||||||
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
|
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
|
||||||
|
@@ -15,6 +15,7 @@ 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"
|
||||||
@@ -31,12 +32,22 @@ 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.
|
||||||
@@ -129,11 +140,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.XRV + "-udp443":
|
case vless.XRO + "-udp443", vless.XRD + "-udp443", vless.XRS + "-udp443", vless.XRV + "-udp443":
|
||||||
allowUDP443 = true
|
allowUDP443 = true
|
||||||
requestAddons.Flow = requestAddons.Flow[:16]
|
requestAddons.Flow = requestAddons.Flow[:16]
|
||||||
fallthrough
|
fallthrough
|
||||||
case vless.XRV:
|
case vless.XRO, vless.XRD, vless.XRS, 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()
|
||||||
@@ -143,30 +154,53 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
}
|
}
|
||||||
requestAddons.Flow = ""
|
requestAddons.Flow = ""
|
||||||
case protocol.RequestCommandTCP:
|
case protocol.RequestCommandTCP:
|
||||||
var t reflect.Type
|
if requestAddons.Flow == vless.XRV {
|
||||||
var p uintptr
|
var t reflect.Type
|
||||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
var p uintptr
|
||||||
netConn = tlsConn.NetConn()
|
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||||
t = reflect.TypeOf(tlsConn.Conn).Elem()
|
netConn = tlsConn.NetConn()
|
||||||
p = uintptr(unsafe.Pointer(tlsConn.Conn))
|
t = reflect.TypeOf(tlsConn.Conn).Elem()
|
||||||
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
|
p = uintptr(unsafe.Pointer(tlsConn.Conn))
|
||||||
netConn = utlsConn.NetConn()
|
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
|
||||||
t = reflect.TypeOf(utlsConn.Conn).Elem()
|
netConn = utlsConn.NetConn()
|
||||||
p = uintptr(unsafe.Pointer(utlsConn.Conn))
|
t = reflect.TypeOf(utlsConn.Conn).Elem()
|
||||||
} else if realityConn, ok := iConn.(*reality.UConn); ok {
|
p = uintptr(unsafe.Pointer(utlsConn.Conn))
|
||||||
netConn = realityConn.NetConn()
|
} else if realityConn, ok := iConn.(*reality.UConn); ok {
|
||||||
t = reflect.TypeOf(realityConn.Conn).Elem()
|
netConn = realityConn.NetConn()
|
||||||
p = uintptr(unsafe.Pointer(realityConn.Conn))
|
t = reflect.TypeOf(realityConn.Conn).Elem()
|
||||||
|
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("XTLS only supports TCP, mKCP and DomainSocket for now.").AtWarning()
|
return newError(`failed to use ` + requestAddons.Flow + `, maybe "security" is not "xtls"`).AtWarning()
|
||||||
}
|
}
|
||||||
if sc, ok := netConn.(syscall.Conn); ok {
|
}
|
||||||
rawConn, _ = sc.SyscallConn()
|
default:
|
||||||
}
|
if _, ok := iConn.(*xtls.Conn); ok {
|
||||||
i, _ := t.FieldByName("input")
|
panic(`To avoid misunderstanding, you must fill in VLESS "flow" when using XTLS.`)
|
||||||
r, _ := t.FieldByName("rawInput")
|
|
||||||
input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset))
|
|
||||||
rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,9 +243,10 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
if err1 == nil {
|
if err1 == nil {
|
||||||
if requestAddons.Flow == vless.XRV {
|
if requestAddons.Flow == vless.XRV {
|
||||||
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello, ctx)
|
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello, ctx)
|
||||||
multiBuffer = encoding.ReshapeMultiBuffer(ctx, multiBuffer)
|
if isTLS {
|
||||||
for i, b := range multiBuffer {
|
for i, b := range multiBuffer {
|
||||||
multiBuffer[i] = encoding.XtlsPadding(b, encoding.CommandPaddingContinue, &userUUID, isTLS, ctx)
|
multiBuffer[i] = encoding.XtlsPadding(b, 0x00, &userUUID, ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := serverWriter.WriteMultiBuffer(multiBuffer); err != nil {
|
if err := serverWriter.WriteMultiBuffer(multiBuffer); err != nil {
|
||||||
@@ -221,7 +256,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
return err1
|
return err1
|
||||||
} else if requestAddons.Flow == vless.XRV {
|
} else if requestAddons.Flow == vless.XRV {
|
||||||
mb := make(buf.MultiBuffer, 1)
|
mb := make(buf.MultiBuffer, 1)
|
||||||
mb[0] = encoding.XtlsPadding(nil, encoding.CommandPaddingContinue, &userUUID, true, ctx) // we do a long padding to hide vless header
|
mb[0] = encoding.XtlsPadding(nil, 0x01, &userUUID, ctx) // it must not be tls so padding finish with it (command 1)
|
||||||
newError("Insert padding with empty content to camouflage VLESS header ", mb.Len()).WriteToLog(session.ExportIDToError(ctx))
|
newError("Insert padding with empty content to camouflage VLESS header ", mb.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||||
if err := serverWriter.WriteMultiBuffer(mb); err != nil {
|
if err := serverWriter.WriteMultiBuffer(mb); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -250,7 +285,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
if statConn != nil {
|
if statConn != nil {
|
||||||
counter = statConn.WriteCounter
|
counter = statConn.WriteCounter
|
||||||
}
|
}
|
||||||
err = encoding.XtlsWrite(clientReader, serverWriter, timer, netConn, counter, ctx, &numberOfPacketToFilter,
|
err = encoding.XtlsWrite(clientReader, serverWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter,
|
||||||
&enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
&enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||||
} else {
|
} else {
|
||||||
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
|
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
|
||||||
@@ -286,8 +321,15 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
if statConn != nil {
|
if statConn != nil {
|
||||||
counter = statConn.ReadCounter
|
counter = statConn.ReadCounter
|
||||||
}
|
}
|
||||||
err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
|
if requestAddons.Flow == vless.XRV {
|
||||||
&numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, input, rawInput, counter, ctx, account.ID.Bytes(),
|
||||||
|
&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,5 +8,8 @@ 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"
|
||||||
)
|
)
|
||||||
|
@@ -31,7 +31,6 @@ type netBindClient struct {
|
|||||||
dialer internet.Dialer
|
dialer internet.Dialer
|
||||||
dns dns.Client
|
dns dns.Client
|
||||||
dnsOption dns.IPOption
|
dnsOption dns.IPOption
|
||||||
reserved []byte
|
|
||||||
|
|
||||||
readQueue chan *netReadInfo
|
readQueue chan *netReadInfo
|
||||||
}
|
}
|
||||||
@@ -129,13 +128,6 @@ func (bind *netBindClient) connectTo(endpoint *netEndpoint) error {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
i, err := c.Read(v.buff)
|
i, err := c.Read(v.buff)
|
||||||
|
|
||||||
if i > 3 {
|
|
||||||
v.buff[1] = 0
|
|
||||||
v.buff[2] = 0
|
|
||||||
v.buff[3] = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
v.bytes = i
|
v.bytes = i
|
||||||
v.endpoint = endpoint
|
v.endpoint = endpoint
|
||||||
v.err = err
|
v.err = err
|
||||||
@@ -165,10 +157,6 @@ func (bind *netBindClient) Send(buff []byte, endpoint conn.Endpoint) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buff) > 3 && len(bind.reserved) == 3 {
|
|
||||||
copy(buff[1:], bind.reserved)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = nend.conn.Write(buff)
|
_, err = nend.conn.Write(buff)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
|
@@ -109,7 +109,6 @@ type DeviceConfig struct {
|
|||||||
Peers []*PeerConfig `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"`
|
Peers []*PeerConfig `protobuf:"bytes,3,rep,name=peers,proto3" json:"peers,omitempty"`
|
||||||
Mtu int32 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"`
|
Mtu int32 `protobuf:"varint,4,opt,name=mtu,proto3" json:"mtu,omitempty"`
|
||||||
NumWorkers int32 `protobuf:"varint,5,opt,name=num_workers,json=numWorkers,proto3" json:"num_workers,omitempty"`
|
NumWorkers int32 `protobuf:"varint,5,opt,name=num_workers,json=numWorkers,proto3" json:"num_workers,omitempty"`
|
||||||
Reserved []byte `protobuf:"bytes,6,opt,name=reserved,proto3" json:"reserved,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeviceConfig) Reset() {
|
func (x *DeviceConfig) Reset() {
|
||||||
@@ -179,13 +178,6 @@ func (x *DeviceConfig) GetNumWorkers() int32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *DeviceConfig) GetReserved() []byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.Reserved
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_proxy_wireguard_config_proto protoreflect.FileDescriptor
|
var File_proxy_wireguard_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_proxy_wireguard_config_proto_rawDesc = []byte{
|
var file_proxy_wireguard_config_proto_rawDesc = []byte{
|
||||||
@@ -203,7 +195,7 @@ var file_proxy_wireguard_config_proto_rawDesc = []byte{
|
|||||||
0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x41, 0x6c,
|
0x76, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x6b, 0x65, 0x65, 0x70, 0x41, 0x6c,
|
||||||
0x69, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x69,
|
0x69, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x69,
|
||||||
0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65,
|
0x70, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65,
|
||||||
0x64, 0x49, 0x70, 0x73, 0x22, 0xd0, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43,
|
0x64, 0x49, 0x70, 0x73, 0x22, 0xb4, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x43,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f,
|
||||||
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65,
|
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x63, 0x72, 0x65,
|
||||||
0x74, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
0x74, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
@@ -214,15 +206,14 @@ var file_proxy_wireguard_config_proto_rawDesc = []byte{
|
|||||||
0x67, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18,
|
0x67, 0x52, 0x05, 0x70, 0x65, 0x65, 0x72, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x74, 0x75, 0x18,
|
||||||
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x75,
|
0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x75,
|
||||||
0x6d, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
|
0x6d, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||||
0x0a, 0x6e, 0x75, 0x6d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x72,
|
0x0a, 0x6e, 0x75, 0x6d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x42, 0x5e, 0x0a, 0x18, 0x63,
|
||||||
0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x72,
|
0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x77, 0x69,
|
||||||
0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x42, 0x5e, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64, 0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75,
|
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
||||||
0x61, 0x72, 0x64, 0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x77, 0x69, 0x72, 0x65, 0x67,
|
||||||
0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65,
|
0x75, 0x61, 0x72, 0x64, 0xaa, 0x02, 0x14, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78,
|
||||||
0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x77, 0x69, 0x72, 0x65, 0x67, 0x75, 0x61, 0x72, 0x64,
|
0x79, 0x2e, 0x57, 0x69, 0x72, 0x65, 0x47, 0x75, 0x61, 0x72, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||||
0xaa, 0x02, 0x14, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x57, 0x69,
|
0x74, 0x6f, 0x33,
|
||||||
0x72, 0x65, 0x47, 0x75, 0x61, 0x72, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -20,5 +20,4 @@ message DeviceConfig {
|
|||||||
repeated PeerConfig peers = 3;
|
repeated PeerConfig peers = 3;
|
||||||
int32 mtu = 4;
|
int32 mtu = 4;
|
||||||
int32 num_workers = 5;
|
int32 num_workers = 5;
|
||||||
bytes reserved = 6;
|
|
||||||
}
|
}
|
@@ -82,10 +82,9 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
})
|
})
|
||||||
// bind := conn.NewStdNetBind() // TODO: conn.Bind wrapper for dialer
|
// bind := conn.NewStdNetBind() // TODO: conn.Bind wrapper for dialer
|
||||||
bind := &netBindClient{
|
bind := &netBindClient{
|
||||||
dialer: dialer,
|
dialer: dialer,
|
||||||
workers: int(h.conf.NumWorkers),
|
workers: int(h.conf.NumWorkers),
|
||||||
dns: h.dns,
|
dns: h.dns,
|
||||||
reserved: h.conf.Reserved,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
net, err := h.makeVirtualTun(bind)
|
net, err := h.makeVirtualTun(bind)
|
||||||
|
156
testing/scenarios/shadowtls_test.go
Normal file
156
testing/scenarios/shadowtls_test.go
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
package scenarios
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||||
|
"github.com/xtls/xray-core/app/log"
|
||||||
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
clog "github.com/xtls/xray-core/common/log"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/serial"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/proxy/dokodemo"
|
||||||
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
|
"github.com/xtls/xray-core/proxy/shadowsocks_2022"
|
||||||
|
"github.com/xtls/xray-core/proxy/shadowtls"
|
||||||
|
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestShadowTLSTcp(t *testing.T) {
|
||||||
|
password := make([]byte, 32)
|
||||||
|
rand.Read(password)
|
||||||
|
testShadowTLSTcp(t, shadowaead_2022.List[0], base64.StdEncoding.EncodeToString(password))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testShadowTLSTcp(t *testing.T, method string, password string) {
|
||||||
|
tcpServer := tcp.Server{
|
||||||
|
MsgProcessor: xor,
|
||||||
|
}
|
||||||
|
dest, err := tcpServer.Start()
|
||||||
|
common.Must(err)
|
||||||
|
defer tcpServer.Close()
|
||||||
|
|
||||||
|
serverPort := tcp.PickPort()
|
||||||
|
serverPort = 18462
|
||||||
|
serverConfig := &core.Config{
|
||||||
|
App: []*serial.TypedMessage{
|
||||||
|
serial.ToTypedMessage(&log.Config{
|
||||||
|
ErrorLogLevel: clog.Severity_Debug,
|
||||||
|
ErrorLogType: log.LogType_Console,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Inbound: []*core.InboundHandlerConfig{
|
||||||
|
{
|
||||||
|
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||||
|
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort)}},
|
||||||
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
|
}),
|
||||||
|
ProxySettings: serial.ToTypedMessage(&shadowtls.ServerConfig{
|
||||||
|
Version: 3,
|
||||||
|
Users: []*shadowtls.User{{Password: password}},
|
||||||
|
Handshake: &shadowtls.HandshakeConfig{
|
||||||
|
Address: net.NewIPOrDomain(net.DomainAddress("google.com")),
|
||||||
|
Port: 443,
|
||||||
|
},
|
||||||
|
Detour: "detour",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Tag: "detour",
|
||||||
|
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||||
|
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(serverPort + 1)}},
|
||||||
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
|
}),
|
||||||
|
ProxySettings: serial.ToTypedMessage(&shadowsocks_2022.ServerConfig{
|
||||||
|
Method: method,
|
||||||
|
Key: password,
|
||||||
|
Network: []net.Network{net.Network_TCP},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
|
{
|
||||||
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
clientPort := tcp.PickPort()
|
||||||
|
clientPort = 12434
|
||||||
|
clientConfig := &core.Config{
|
||||||
|
App: []*serial.TypedMessage{
|
||||||
|
serial.ToTypedMessage(&log.Config{
|
||||||
|
ErrorLogLevel: clog.Severity_Debug,
|
||||||
|
ErrorLogType: log.LogType_Console,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
Inbound: []*core.InboundHandlerConfig{
|
||||||
|
{
|
||||||
|
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||||
|
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
|
||||||
|
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
|
}),
|
||||||
|
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||||
|
Address: net.NewIPOrDomain(dest.Address),
|
||||||
|
Port: uint32(dest.Port),
|
||||||
|
Networks: []net.Network{net.Network_TCP},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
|
{
|
||||||
|
ProxySettings: serial.ToTypedMessage(&shadowsocks_2022.ClientConfig{
|
||||||
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
|
Port: uint32(serverPort),
|
||||||
|
Method: method,
|
||||||
|
Key: password,
|
||||||
|
}),
|
||||||
|
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||||
|
ProxySettings: &internet.ProxyConfig{
|
||||||
|
Tag: "detour",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Tag: "detour",
|
||||||
|
ProxySettings: serial.ToTypedMessage(&shadowtls.ClientConfig{
|
||||||
|
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||||
|
Port: uint32(serverPort),
|
||||||
|
Version: 3,
|
||||||
|
Password: password,
|
||||||
|
}),
|
||||||
|
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||||
|
StreamSettings: &internet.StreamConfig{
|
||||||
|
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||||
|
SecuritySettings: []*serial.TypedMessage{
|
||||||
|
serial.ToTypedMessage(&tls.Config{
|
||||||
|
ServerName: "google.com",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||||
|
common.Must(err)
|
||||||
|
defer CloseAllServers(servers)
|
||||||
|
|
||||||
|
var errGroup errgroup.Group
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
errGroup.Go(testTCPConn(clientPort, 10240*1024, time.Second*20))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := errGroup.Wait(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.28.1
|
// protoc-gen-go v1.28.1
|
||||||
// protoc v4.22.0
|
// protoc v3.21.12
|
||||||
// source: transport/internet/config.proto
|
// source: transport/internet/config.proto
|
||||||
|
|
||||||
package internet
|
package internet
|
||||||
@@ -426,8 +426,6 @@ type SocketConfig struct {
|
|||||||
TcpKeepAliveIdle int32 `protobuf:"varint,11,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"`
|
TcpKeepAliveIdle int32 `protobuf:"varint,11,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"`
|
||||||
TcpCongestion string `protobuf:"bytes,12,opt,name=tcp_congestion,json=tcpCongestion,proto3" json:"tcp_congestion,omitempty"`
|
TcpCongestion string `protobuf:"bytes,12,opt,name=tcp_congestion,json=tcpCongestion,proto3" json:"tcp_congestion,omitempty"`
|
||||||
Interface string `protobuf:"bytes,13,opt,name=interface,proto3" json:"interface,omitempty"`
|
Interface string `protobuf:"bytes,13,opt,name=interface,proto3" json:"interface,omitempty"`
|
||||||
V6Only bool `protobuf:"varint,14,opt,name=v6only,proto3" json:"v6only,omitempty"`
|
|
||||||
TcpWindowClamp int32 `protobuf:"varint,15,opt,name=tcp_window_clamp,json=tcpWindowClamp,proto3" json:"tcp_window_clamp,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SocketConfig) Reset() {
|
func (x *SocketConfig) Reset() {
|
||||||
@@ -553,20 +551,6 @@ func (x *SocketConfig) GetInterface() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SocketConfig) GetV6Only() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.V6Only
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *SocketConfig) GetTcpWindowClamp() int32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.TcpWindowClamp
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_transport_internet_config_proto_rawDesc = []byte{
|
var file_transport_internet_config_proto_rawDesc = []byte{
|
||||||
@@ -619,7 +603,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
|||||||
0x12, 0x30, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79,
|
0x12, 0x30, 0x0a, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79,
|
||||||
0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74,
|
0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74,
|
||||||
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f,
|
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f,
|
||||||
0x78, 0x79, 0x22, 0xc8, 0x05, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e,
|
0x78, 0x79, 0x22, 0x86, 0x05, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e,
|
||||||
0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x05, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02,
|
0x05, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02,
|
||||||
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72,
|
0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72,
|
||||||
@@ -656,31 +640,27 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
|||||||
0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74,
|
0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74,
|
||||||
0x63, 0x70, 0x43, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09,
|
0x63, 0x70, 0x43, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09,
|
||||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x36,
|
0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50,
|
||||||
0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, 0x36, 0x6f, 0x6e,
|
0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10,
|
||||||
0x6c, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x63, 0x70, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77,
|
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a,
|
||||||
0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x63,
|
0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5a, 0x0a, 0x11, 0x54,
|
||||||
0x70, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x43, 0x6c, 0x61, 0x6d, 0x70, 0x22, 0x2f, 0x0a, 0x0a,
|
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||||
0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66,
|
0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50,
|
||||||
0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12,
|
0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09,
|
||||||
0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x5a, 0x0a,
|
0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x48,
|
||||||
0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
0x54, 0x54, 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
||||||
0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55,
|
0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x05, 0x2a, 0x41, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x44, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x4b, 0x43, 0x50, 0x10, 0x02, 0x12, 0x0d,
|
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f,
|
||||||
0x0a, 0x09, 0x57, 0x65, 0x62, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x03, 0x12, 0x08, 0x0a,
|
0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01,
|
||||||
0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x04, 0x12, 0x10, 0x0a, 0x0c, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a,
|
||||||
0x6e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x10, 0x05, 0x2a, 0x41, 0x0a, 0x0e, 0x44, 0x6f, 0x6d,
|
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f,
|
||||||
0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41,
|
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
||||||
0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
|
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74,
|
||||||
0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12,
|
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
||||||
0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x42, 0x67, 0x0a, 0x1b,
|
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
||||||
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79,
|
||||||
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67,
|
0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72,
|
||||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78,
|
0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
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, 0xaa, 0x02, 0x17, 0x58, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74,
|
|
||||||
0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -100,8 +100,4 @@ message SocketConfig {
|
|||||||
string tcp_congestion = 12;
|
string tcp_congestion = 12;
|
||||||
|
|
||||||
string interface = 13;
|
string interface = 13;
|
||||||
|
|
||||||
bool v6only = 14;
|
|
||||||
|
|
||||||
int32 tcp_window_clamp = 15;
|
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,7 @@ 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) {
|
||||||
@@ -28,6 +29,8 @@ 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,6 +9,7 @@ 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"
|
||||||
@@ -16,6 +17,7 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@ 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
|
||||||
@@ -61,6 +64,9 @@ 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()
|
||||||
}
|
}
|
||||||
@@ -94,6 +100,8 @@ 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()
|
||||||
|
@@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/grpc/encoding"
|
"github.com/xtls/xray-core/transport/internet/grpc/encoding"
|
||||||
"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"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
@@ -78,7 +77,6 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
globalDialerMap = make(map[dialerConf]*grpc.ClientConn)
|
globalDialerMap = make(map[dialerConf]*grpc.ClientConn)
|
||||||
}
|
}
|
||||||
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
tlsConfig := tls.ConfigFromStreamSettings(streamSettings)
|
||||||
realityConfig := reality.ConfigFromStreamSettings(streamSettings)
|
|
||||||
sockopt := streamSettings.SocketSettings
|
sockopt := streamSettings.SocketSettings
|
||||||
grpcSettings := streamSettings.ProtocolSettings.(*Config)
|
grpcSettings := streamSettings.ProtocolSettings.(*Config)
|
||||||
|
|
||||||
@@ -118,11 +116,7 @@ func getGrpcClient(ctx context.Context, dest net.Destination, streamSettings *in
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
address := net.ParseAddress(rawHost)
|
address := net.ParseAddress(rawHost)
|
||||||
c, err := internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt)
|
return internet.DialSystem(gctx, net.TCPDestination(address, port), sockopt)
|
||||||
if err == nil && realityConfig != nil {
|
|
||||||
return reality.UClient(c, realityConfig, ctx, dest)
|
|
||||||
}
|
|
||||||
return c, err
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,13 +4,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
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"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/grpc/encoding"
|
"github.com/xtls/xray-core/transport/internet/grpc/encoding"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
@@ -127,9 +125,6 @@ func Listen(ctx context.Context, address net.Address, port net.Port, settings *i
|
|||||||
|
|
||||||
encoding.RegisterGRPCServiceServerX(s, listener, grpcSettings.getNormalizedName())
|
encoding.RegisterGRPCServiceServerX(s, listener, grpcSettings.getNormalizedName())
|
||||||
|
|
||||||
if config := reality.ConfigFromStreamSettings(settings); config != nil {
|
|
||||||
streamListener = goreality.NewListener(streamListener, config.GetREALITYConfig())
|
|
||||||
}
|
|
||||||
if err = s.Serve(streamListener); err != nil {
|
if err = s.Serve(streamListener); err != nil {
|
||||||
newError("Listener for gRPC ended").Base(err).WriteToLog()
|
newError("Listener for gRPC ended").Base(err).WriteToLog()
|
||||||
}
|
}
|
||||||
|
@@ -1,153 +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/headers/dns/config.proto
|
|
||||||
|
|
||||||
package dns
|
|
||||||
|
|
||||||
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 Config struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Domain string `protobuf:"bytes,1,opt,name=domain,proto3" json:"domain,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
|
||||||
*x = Config{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_transport_internet_headers_dns_config_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*Config) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_transport_internet_headers_dns_config_proto_msgTypes[0]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
|
||||||
func (*Config) Descriptor() ([]byte, []int) {
|
|
||||||
return file_transport_internet_headers_dns_config_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config) GetDomain() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Domain
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_transport_internet_headers_dns_config_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_transport_internet_headers_dns_config_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x2b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
|
||||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x64, 0x6e, 0x73,
|
|
||||||
0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
|
||||||
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x64,
|
|
||||||
0x6e, 0x73, 0x22, 0x20, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x16, 0x0a, 0x06,
|
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f,
|
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x42, 0x8b, 0x01, 0x0a, 0x27, 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, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x64, 0x6e, 0x73,
|
|
||||||
0x50, 0x01, 0x5a, 0x38, 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, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x23, 0x58,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e,
|
|
||||||
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x44,
|
|
||||||
0x4e, 0x53, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_transport_internet_headers_dns_config_proto_rawDescOnce sync.Once
|
|
||||||
file_transport_internet_headers_dns_config_proto_rawDescData = file_transport_internet_headers_dns_config_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_transport_internet_headers_dns_config_proto_rawDescGZIP() []byte {
|
|
||||||
file_transport_internet_headers_dns_config_proto_rawDescOnce.Do(func() {
|
|
||||||
file_transport_internet_headers_dns_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_headers_dns_config_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_transport_internet_headers_dns_config_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_transport_internet_headers_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
|
||||||
var file_transport_internet_headers_dns_config_proto_goTypes = []interface{}{
|
|
||||||
(*Config)(nil), // 0: xray.transport.internet.headers.dns.Config
|
|
||||||
}
|
|
||||||
var file_transport_internet_headers_dns_config_proto_depIdxs = []int32{
|
|
||||||
0, // [0:0] is the sub-list for method output_type
|
|
||||||
0, // [0:0] is the sub-list for method input_type
|
|
||||||
0, // [0:0] is the sub-list for extension type_name
|
|
||||||
0, // [0:0] is the sub-list for extension extendee
|
|
||||||
0, // [0:0] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_transport_internet_headers_dns_config_proto_init() }
|
|
||||||
func file_transport_internet_headers_dns_config_proto_init() {
|
|
||||||
if File_transport_internet_headers_dns_config_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_transport_internet_headers_dns_config_proto_msgTypes[0].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_headers_dns_config_proto_rawDesc,
|
|
||||||
NumEnums: 0,
|
|
||||||
NumMessages: 1,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 0,
|
|
||||||
},
|
|
||||||
GoTypes: file_transport_internet_headers_dns_config_proto_goTypes,
|
|
||||||
DependencyIndexes: file_transport_internet_headers_dns_config_proto_depIdxs,
|
|
||||||
MessageInfos: file_transport_internet_headers_dns_config_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_transport_internet_headers_dns_config_proto = out.File
|
|
||||||
file_transport_internet_headers_dns_config_proto_rawDesc = nil
|
|
||||||
file_transport_internet_headers_dns_config_proto_goTypes = nil
|
|
||||||
file_transport_internet_headers_dns_config_proto_depIdxs = nil
|
|
||||||
}
|
|
@@ -1,12 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package xray.transport.internet.headers.dns;
|
|
||||||
option csharp_namespace = "Xray.Transport.Internet.Headers.DNS";
|
|
||||||
option go_package = "github.com/xtls/xray-core/transport/internet/headers/dns";
|
|
||||||
option java_package = "com.xray.transport.internet.headers.dns";
|
|
||||||
option java_multiple_files = true;
|
|
||||||
|
|
||||||
message Config {
|
|
||||||
string domain = 1;
|
|
||||||
}
|
|
||||||
|
|
@@ -1,57 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/binary"
|
|
||||||
|
|
||||||
"github.com/miekg/dns"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DNS struct {
|
|
||||||
header []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d DNS) Size() int32 {
|
|
||||||
return int32(len(d.header))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Serialize implements PacketHeader.
|
|
||||||
func (d DNS) Serialize(b []byte) {
|
|
||||||
copy(b, d.header)
|
|
||||||
binary.BigEndian.PutUint16(b[0:], dice.RollUint16()) // random transaction ID
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDNS returns a new DNS instance based on given config.
|
|
||||||
func NewDNS(ctx context.Context, config interface{}) (interface{}, error) {
|
|
||||||
var header []byte
|
|
||||||
|
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0000) // Transaction ID
|
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0100) // Flags: Standard query
|
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0001) // Questions
|
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0000) // Answer RRs
|
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0000) // Authority RRs
|
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0000) // Additional RRs
|
|
||||||
|
|
||||||
buf := make([]byte, 0x100)
|
|
||||||
|
|
||||||
off1, err := dns.PackDomainName(dns.Fqdn(config.(*Config).Domain), buf, 0, nil, false)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
header = append(header, buf[:off1]...)
|
|
||||||
|
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0001) // Type: A
|
|
||||||
header = binary.BigEndian.AppendUint16(header, 0x0001) // Class: IN
|
|
||||||
|
|
||||||
return DNS{
|
|
||||||
header: header,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), NewDNS))
|
|
||||||
}
|
|
@@ -3,7 +3,6 @@ package http
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
gotls "crypto/tls"
|
gotls "crypto/tls"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -167,68 +166,23 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
// Disable any compression method from server.
|
// Disable any compression method from server.
|
||||||
request.Header.Set("Accept-Encoding", "identity")
|
request.Header.Set("Accept-Encoding", "identity")
|
||||||
|
|
||||||
wrc := &WaitReadCloser{Wait: make(chan struct{})}
|
response, err := client.Do(request)
|
||||||
go func() {
|
if err != nil {
|
||||||
response, err := client.Do(request)
|
return nil, newError("failed to dial to ", dest).Base(err).AtWarning()
|
||||||
if err != nil {
|
}
|
||||||
newError("failed to dial to ", dest).Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
if response.StatusCode != 200 {
|
||||||
wrc.Close()
|
return nil, newError("unexpected status", response.StatusCode).AtWarning()
|
||||||
return
|
}
|
||||||
}
|
|
||||||
if response.StatusCode != 200 {
|
|
||||||
newError("unexpected status", response.StatusCode).AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
wrc.Close()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
wrc.Set(response.Body)
|
|
||||||
}()
|
|
||||||
|
|
||||||
bwriter := buf.NewBufferedWriter(pwriter)
|
bwriter := buf.NewBufferedWriter(pwriter)
|
||||||
common.Must(bwriter.SetBuffered(false))
|
common.Must(bwriter.SetBuffered(false))
|
||||||
return cnc.NewConnection(
|
return cnc.NewConnection(
|
||||||
cnc.ConnectionOutput(wrc),
|
cnc.ConnectionOutput(response.Body),
|
||||||
cnc.ConnectionInput(bwriter),
|
cnc.ConnectionInput(bwriter),
|
||||||
cnc.ConnectionOnClose(common.ChainedClosable{breader, bwriter, wrc}),
|
cnc.ConnectionOnClose(common.ChainedClosable{breader, bwriter, response.Body}),
|
||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(internet.RegisterTransportDialer(protocolName, Dial))
|
common.Must(internet.RegisterTransportDialer(protocolName, Dial))
|
||||||
}
|
}
|
||||||
|
|
||||||
type WaitReadCloser struct {
|
|
||||||
Wait chan struct{}
|
|
||||||
io.ReadCloser
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WaitReadCloser) Set(rc io.ReadCloser) {
|
|
||||||
w.ReadCloser = rc
|
|
||||||
defer func() {
|
|
||||||
if recover() != nil {
|
|
||||||
rc.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
close(w.Wait)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WaitReadCloser) Read(b []byte) (int, error) {
|
|
||||||
if w.ReadCloser == nil {
|
|
||||||
if <-w.Wait; w.ReadCloser == nil {
|
|
||||||
return 0, io.ErrClosedPipe
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.ReadCloser.Read(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *WaitReadCloser) Close() error {
|
|
||||||
if w.ReadCloser != nil {
|
|
||||||
return w.ReadCloser.Close()
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if recover() != nil && w.ReadCloser != nil {
|
|
||||||
w.ReadCloser.Close()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
close(w.Wait)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
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"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
@@ -16,7 +15,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"github.com/xtls/xray-core/transport/internet/reality"
|
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
"golang.org/x/net/http2/h2c"
|
"golang.org/x/net/http2/h2c"
|
||||||
@@ -51,13 +49,6 @@ func (fw flushWriter) Write(p []byte) (n int, err error) {
|
|||||||
return 0, io.ErrClosedPipe
|
return 0, io.ErrClosedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if recover() != nil {
|
|
||||||
fw.d.Close()
|
|
||||||
err = io.ErrClosedPipe
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
n, err = fw.w.Write(p)
|
n, err = fw.w.Write(p)
|
||||||
if f, ok := fw.w.(http.Flusher); ok && err == nil {
|
if f, ok := fw.w.(http.Flusher); ok && err == nil {
|
||||||
f.Flush()
|
f.Flush()
|
||||||
@@ -196,17 +187,14 @@ func Listen(ctx context.Context, address net.Address, port net.Port, streamSetti
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config == nil {
|
if config == nil {
|
||||||
if config := reality.ConfigFromStreamSettings(streamSettings); config != nil {
|
|
||||||
streamListener = goreality.NewListener(streamListener, config.GetREALITYConfig())
|
|
||||||
}
|
|
||||||
err = server.Serve(streamListener)
|
err = server.Serve(streamListener)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("stopping serving H2C or REALITY H2").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("stopping serving H2C").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
err = server.ServeTLS(streamListener, "", "")
|
err = server.ServeTLS(streamListener, "", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("stopping serving TLS H2").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("stopping serving TLS").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
@@ -12,6 +12,7 @@ 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())
|
||||||
@@ -86,6 +87,8 @@ 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,6 +6,7 @@ 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"
|
||||||
@@ -13,6 +14,7 @@ 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 {
|
||||||
@@ -27,6 +29,7 @@ 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
|
||||||
@@ -59,6 +62,9 @@ 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 {
|
||||||
@@ -131,6 +137,8 @@ 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)
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package reality
|
package reality
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/reality"
|
"github.com/xtls/reality"
|
||||||
@@ -9,10 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *Config) GetREALITYConfig() *reality.Config {
|
func (c *Config) GetREALITYConfig() *reality.Config {
|
||||||
var dialer net.Dialer
|
|
||||||
config := &reality.Config{
|
config := &reality.Config{
|
||||||
DialContext: dialer.DialContext,
|
|
||||||
|
|
||||||
Show: c.Show,
|
Show: c.Show,
|
||||||
Type: c.Type,
|
Type: c.Type,
|
||||||
Dest: c.Dest,
|
Dest: c.Dest,
|
||||||
|
@@ -52,7 +52,7 @@ func (c *Conn) HandshakeAddress() net.Address {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Server(c net.Conn, config *reality.Config) (net.Conn, error) {
|
func Server(c net.Conn, config *reality.Config) (net.Conn, error) {
|
||||||
realityConn, err := reality.Server(context.Background(), c, config)
|
realityConn, err := reality.Server(c, config)
|
||||||
return &Conn{Conn: realityConn}, err
|
return &Conn{Conn: realityConn}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,7 +46,7 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||||||
return newError("failed to set SO_MARK").Base(err)
|
return newError("failed to set SO_MARK").Base(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Interface != "" {
|
if config.Interface != "" {
|
||||||
if err := syscall.BindToDevice(int(fd), config.Interface); err != nil {
|
if err := syscall.BindToDevice(int(fd), config.Interface); err != nil {
|
||||||
return newError("failed to set Interface").Base(err)
|
return newError("failed to set Interface").Base(err)
|
||||||
@@ -89,12 +89,6 @@ func applyOutboundSocketOptions(network string, address string, fd uintptr, conf
|
|||||||
return newError("failed to set TCP_CONGESTION", err)
|
return newError("failed to set TCP_CONGESTION", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.TcpWindowClamp > 0 {
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_WINDOW_CLAMP, int(config.TcpWindowClamp)); err != nil {
|
|
||||||
return newError("failed to set TCP_WINDOW_CLAMP", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Tproxy.IsEnabled() {
|
if config.Tproxy.IsEnabled() {
|
||||||
@@ -145,12 +139,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
|||||||
return newError("failed to set TCP_CONGESTION", err)
|
return newError("failed to set TCP_CONGESTION", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.TcpWindowClamp > 0 {
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_WINDOW_CLAMP, int(config.TcpWindowClamp)); err != nil {
|
|
||||||
return newError("failed to set TCP_WINDOW_CLAMP", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Tproxy.IsEnabled() {
|
if config.Tproxy.IsEnabled() {
|
||||||
@@ -167,12 +155,6 @@ func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.V6Only {
|
|
||||||
if err := syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, syscall.IPV6_V6ONLY, 1); err != nil {
|
|
||||||
return newError("failed to set IPV6_V6ONLY", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@ 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.
|
||||||
@@ -22,14 +23,22 @@ 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 {
|
||||||
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
|
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
|
||||||
if fingerprint := tls.GetFingerprint(config.Fingerprint); fingerprint != nil {
|
customClient, loaded := tls.CustomClientFromContext(ctx)
|
||||||
conn = tls.UClient(conn, tlsConfig, fingerprint)
|
if loaded {
|
||||||
if err := conn.(*tls.UConn).Handshake(); err != nil {
|
conn = customClient(conn, config, tlsConfig)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
conn = tls.Client(conn, tlsConfig)
|
if fingerprint := tls.GetFingerprint(config.Fingerprint); fingerprint != nil {
|
||||||
|
conn = tls.UClient(conn, tlsConfig, fingerprint)
|
||||||
|
if err := conn.(*tls.UConn).Handshake(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
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,6 +6,7 @@ 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"
|
||||||
@@ -14,12 +15,14 @@ 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
|
||||||
@@ -75,6 +78,9 @@ 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()
|
||||||
}
|
}
|
||||||
@@ -112,6 +118,8 @@ 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()
|
||||||
|
@@ -266,20 +266,6 @@ func (c *Config) verifyPeerCert(rawCerts [][]byte, verifiedChains [][]*x509.Cert
|
|||||||
}
|
}
|
||||||
return newError("peer cert is unrecognized: ", base64.StdEncoding.EncodeToString(hashValue))
|
return newError("peer cert is unrecognized: ", base64.StdEncoding.EncodeToString(hashValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.PinnedPeerCertificatePublicKeySha256 != nil {
|
|
||||||
for _, v := range verifiedChains {
|
|
||||||
for _, cert := range v {
|
|
||||||
publicHash := GenerateCertPublicKeyHash(cert)
|
|
||||||
for _, c := range c.PinnedPeerCertificatePublicKeySha256 {
|
|
||||||
if hmac.Equal(publicHash, c) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newError("peer public key is unrecognized.")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -203,11 +203,6 @@ type Config struct {
|
|||||||
// @Document This value replace allow_insecure.
|
// @Document This value replace allow_insecure.
|
||||||
// @Critical
|
// @Critical
|
||||||
PinnedPeerCertificateChainSha256 [][]byte `protobuf:"bytes,13,rep,name=pinned_peer_certificate_chain_sha256,json=pinnedPeerCertificateChainSha256,proto3" json:"pinned_peer_certificate_chain_sha256,omitempty"`
|
PinnedPeerCertificateChainSha256 [][]byte `protobuf:"bytes,13,rep,name=pinned_peer_certificate_chain_sha256,json=pinnedPeerCertificateChainSha256,proto3" json:"pinned_peer_certificate_chain_sha256,omitempty"`
|
||||||
// @Document A pinned certificate public key sha256 hash.
|
|
||||||
// @Document If the server's public key hash does not match this value, the connection will be aborted.
|
|
||||||
// @Document This value replace allow_insecure.
|
|
||||||
// @Critical
|
|
||||||
PinnedPeerCertificatePublicKeySha256 [][]byte `protobuf:"bytes,14,rep,name=pinned_peer_certificate_public_key_sha256,json=pinnedPeerCertificatePublicKeySha256,proto3" json:"pinned_peer_certificate_public_key_sha256,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -333,13 +328,6 @@ func (x *Config) GetPinnedPeerCertificateChainSha256() [][]byte {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetPinnedPeerCertificatePublicKeySha256() [][]byte {
|
|
||||||
if x != nil {
|
|
||||||
return x.PinnedPeerCertificatePublicKeySha256
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_transport_internet_tls_config_proto protoreflect.FileDescriptor
|
var File_transport_internet_tls_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
||||||
@@ -369,7 +357,7 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
|||||||
0x43, 0x49, 0x50, 0x48, 0x45, 0x52, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x00, 0x12, 0x14, 0x0a, 0x10,
|
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,
|
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,
|
0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x54, 0x59, 0x5f,
|
||||||
0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xcc, 0x05, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
0x49, 0x53, 0x53, 0x55, 0x45, 0x10, 0x02, 0x22, 0xf3, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
||||||
0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x6e, 0x73, 0x65,
|
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,
|
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, 0x4a, 0x0a, 0x0b, 0x63, 0x65, 0x72,
|
0x77, 0x49, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x72, 0x65, 0x12, 0x4a, 0x0a, 0x0b, 0x63, 0x65, 0x72,
|
||||||
@@ -408,21 +396,15 @@ var file_transport_internet_tls_config_proto_rawDesc = []byte{
|
|||||||
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x73,
|
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,
|
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,
|
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, 0x12, 0x57, 0x0a,
|
0x74, 0x65, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x42, 0x73, 0x0a,
|
||||||
0x29, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72,
|
0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
||||||
0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
|
0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73,
|
||||||
0x6b, 0x65, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0c,
|
0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
||||||
0x52, 0x24, 0x70, 0x69, 0x6e, 0x6e, 0x65, 0x64, 0x50, 0x65, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74,
|
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72,
|
||||||
0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79,
|
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||||
0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x42, 0x73, 0x0a, 0x1f, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
0x2f, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e,
|
||||||
0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74,
|
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54,
|
||||||
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x74, 0x6c, 0x73, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74,
|
0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
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, 0x74, 0x6c, 0x73, 0xaa, 0x02, 0x1b,
|
|
||||||
0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49,
|
|
||||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x54, 0x6c, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@@ -76,11 +76,4 @@ message Config {
|
|||||||
@Critical
|
@Critical
|
||||||
*/
|
*/
|
||||||
repeated bytes pinned_peer_certificate_chain_sha256 = 13;
|
repeated bytes pinned_peer_certificate_chain_sha256 = 13;
|
||||||
|
|
||||||
/* @Document A pinned certificate public key sha256 hash.
|
|
||||||
@Document If the server's public key hash does not match this value, the connection will be aborted.
|
|
||||||
@Document This value replace allow_insecure.
|
|
||||||
@Critical
|
|
||||||
*/
|
|
||||||
repeated bytes pinned_peer_certificate_public_key_sha256 = 14;
|
|
||||||
}
|
}
|
||||||
|
21
transport/internet/tls/custom.go
Normal file
21
transport/internet/tls/custom.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package tls
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"crypto/tls"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type customClientKey struct{}
|
||||||
|
|
||||||
|
type CustomClientFunc func(conn net.Conn, xrayConfig *Config, config *tls.Config) net.Conn
|
||||||
|
|
||||||
|
func CustomClientFromContext(ctx context.Context) (CustomClientFunc, bool) {
|
||||||
|
client, loaded := ctx.Value(customClientKey{}).(CustomClientFunc)
|
||||||
|
return client, loaded
|
||||||
|
}
|
||||||
|
|
||||||
|
func ContextWithCustomClient(ctx context.Context, customClient CustomClientFunc) context.Context {
|
||||||
|
return context.WithValue(ctx, customClientKey{}, customClient)
|
||||||
|
}
|
@@ -2,7 +2,6 @@ package tls
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
)
|
)
|
||||||
@@ -35,8 +34,3 @@ func GenerateCertChainHash(rawCerts [][]byte) []byte {
|
|||||||
}
|
}
|
||||||
return hashValue
|
return hashValue
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateCertPublicKeyHash(cert *x509.Certificate) []byte {
|
|
||||||
out := sha256.Sum256(cert.RawSubjectPublicKeyInfo)
|
|
||||||
return out[:]
|
|
||||||
}
|
|
||||||
|
@@ -1,9 +1,6 @@
|
|||||||
package tls
|
package tls
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/pem"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -111,89 +108,3 @@ tzY45d4mjPs0fKCFKSsVM6YT0tX4NwIKsOaeQg30WLtRyDwYm6ma/a/UUUS0FloZ
|
|||||||
assert.Equal(t, "FW3SVMCL6um2wVltOdgJ3DpI82aredw83YoCblkMkVM=", hash)
|
assert.Equal(t, "FW3SVMCL6um2wVltOdgJ3DpI82aredw83YoCblkMkVM=", hash)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCalculateCertPublicKeyHash(t *testing.T) {
|
|
||||||
const Single = `-----BEGIN CERTIFICATE-----
|
|
||||||
MIINWTCCC0GgAwIBAgITLQAxbA/A+lw/1sLDAAAAADFsDzANBgkqhkiG9w0BAQsF
|
|
||||||
ADBPMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9u
|
|
||||||
MSAwHgYDVQQDExdNaWNyb3NvZnQgUlNBIFRMUyBDQSAwMjAeFw0yMjExMjUwMDU2
|
|
||||||
NTZaFw0yMzA1MjUwMDU2NTZaMBcxFTATBgNVBAMTDHd3dy5iaW5nLmNvbTCCASIw
|
|
||||||
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOH89lKmtkDnClFiQwfZofZO4h8C
|
|
||||||
Ye/+ChI67pEw5Q6/MxJzHiMKe8f1WaNuc+wkdHdct+BmQ+AftozIJt+eSN6IF7eY
|
|
||||||
dsutBvR87GNLFe40MBvfyvTQVM9Ulv04JxOpKTYnsf2wmktEI3y7FCgfm9RT71n+
|
|
||||||
Zef8Z8fa4By7aGfbbCQ0DsHl5P9o3ug/eLQODzK9NuQlwcVBHD2Zvgo+K7WOsjgE
|
|
||||||
k8JnOr+2zc0WWT4OrWSDJE/3l+jvhxmZkrwgmks4m9zUZvAnYAz/xxVCJRqbI3Ou
|
|
||||||
S5fkJJ3f6IxPbS2i8OWz6tma1aIkgQaFNJQuYOJa1esfQcEzs6kb/Xx5DXUCAwEA
|
|
||||||
AaOCCWQwgglgMIIBfQYKKwYBBAHWeQIEAgSCAW0EggFpAWcAdgCt9776fP8QyIud
|
|
||||||
PZwePhhqtGcpXc+xDCTKhYY069yCigAAAYSsUtxtAAAEAwBHMEUCIQCP/Jpp337p
|
|
||||||
cKITqS/kNlA4bNY6TK1Ad0VlsdkzQU+oZgIgFZb2AcsyT1UKCmM3ziGsLdvS9MAT
|
|
||||||
D1g/kztyDXhkA70AdgBVgdTCFpA2AUrqC5tXPFPwwOQ4eHAlCBcvo6odBxPTDAAA
|
|
||||||
AYSsUtsZAAAEAwBHMEUCIQDvlqXrdA440PW6b+JLj4F0ZVQNKHcv1lub0FhQqHgR
|
|
||||||
wAIgAtC7eXvXXhVBuO+Bd3fkDI0aGQM+pcvIesBoygzStjQAdQB6MoxU2LcttiDq
|
|
||||||
OOBSHumEFnAyE4VNO9IrwTpXo1LrUgAAAYSsUtmfAAAEAwBGMEQCIDgjSYt6e/h8
|
|
||||||
dv2KGEL3AJZUBH2gp1AA5saH8o3OyMJhAiBOCzo3oWlVFeF/8c0fxIIs9Fj4w8BY
|
|
||||||
INo0jNP/k7apgTAnBgkrBgEEAYI3FQoEGjAYMAoGCCsGAQUFBwMBMAoGCCsGAQUF
|
|
||||||
BwMCMD4GCSsGAQQBgjcVBwQxMC8GJysGAQQBgjcVCIfahnWD7tkBgsmFG4G1nmGF
|
|
||||||
9OtggV2Fho5Bh8KYUAIBZAIBJzCBhwYIKwYBBQUHAQEEezB5MFMGCCsGAQUFBzAC
|
|
||||||
hkdodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL21zY29ycC9NaWNyb3NvZnQl
|
|
||||||
MjBSU0ElMjBUTFMlMjBDQSUyMDAyLmNydDAiBggrBgEFBQcwAYYWaHR0cDovL29j
|
|
||||||
c3AubXNvY3NwLmNvbTAdBgNVHQ4EFgQUpuSPPchFlPGu8FTbzPhJTFxQ7RowDgYD
|
|
||||||
VR0PAQH/BAQDAgSwMIIFbQYDVR0RBIIFZDCCBWCCDHd3dy5iaW5nLmNvbYIQZGlj
|
|
||||||
dC5iaW5nLmNvbS5jboITKi5wbGF0Zm9ybS5iaW5nLmNvbYIKKi5iaW5nLmNvbYII
|
|
||||||
YmluZy5jb22CFmllb25saW5lLm1pY3Jvc29mdC5jb22CEyoud2luZG93c3NlYXJj
|
|
||||||
aC5jb22CGWNuLmllb25saW5lLm1pY3Jvc29mdC5jb22CESoub3JpZ2luLmJpbmcu
|
|
||||||
Y29tgg0qLm1tLmJpbmcubmV0gg4qLmFwaS5iaW5nLmNvbYIYZWNuLmRldi52aXJ0
|
|
||||||
dWFsZWFydGgubmV0gg0qLmNuLmJpbmcubmV0gg0qLmNuLmJpbmcuY29tghBzc2wt
|
|
||||||
YXBpLmJpbmcuY29tghBzc2wtYXBpLmJpbmcubmV0gg4qLmFwaS5iaW5nLm5ldIIO
|
|
||||||
Ki5iaW5nYXBpcy5jb22CD2JpbmdzYW5kYm94LmNvbYIWZmVlZGJhY2subWljcm9z
|
|
||||||
b2Z0LmNvbYIbaW5zZXJ0bWVkaWEuYmluZy5vZmZpY2UubmV0gg5yLmJhdC5iaW5n
|
|
||||||
LmNvbYIQKi5yLmJhdC5iaW5nLmNvbYISKi5kaWN0LmJpbmcuY29tLmNugg8qLmRp
|
|
||||||
Y3QuYmluZy5jb22CDiouc3NsLmJpbmcuY29tghAqLmFwcGV4LmJpbmcuY29tghYq
|
|
||||||
LnBsYXRmb3JtLmNuLmJpbmcuY29tgg13cC5tLmJpbmcuY29tggwqLm0uYmluZy5j
|
|
||||||
b22CD2dsb2JhbC5iaW5nLmNvbYIRd2luZG93c3NlYXJjaC5jb22CDnNlYXJjaC5t
|
|
||||||
c24uY29tghEqLmJpbmdzYW5kYm94LmNvbYIZKi5hcGkudGlsZXMuZGl0dS5saXZl
|
|
||||||
LmNvbYIPKi5kaXR1LmxpdmUuY29tghgqLnQwLnRpbGVzLmRpdHUubGl2ZS5jb22C
|
|
||||||
GCoudDEudGlsZXMuZGl0dS5saXZlLmNvbYIYKi50Mi50aWxlcy5kaXR1LmxpdmUu
|
|
||||||
Y29tghgqLnQzLnRpbGVzLmRpdHUubGl2ZS5jb22CFSoudGlsZXMuZGl0dS5saXZl
|
|
||||||
LmNvbYILM2QubGl2ZS5jb22CE2FwaS5zZWFyY2gubGl2ZS5jb22CFGJldGEuc2Vh
|
|
||||||
cmNoLmxpdmUuY29tghVjbndlYi5zZWFyY2gubGl2ZS5jb22CDGRldi5saXZlLmNv
|
|
||||||
bYINZGl0dS5saXZlLmNvbYIRZmFyZWNhc3QubGl2ZS5jb22CDmltYWdlLmxpdmUu
|
|
||||||
Y29tgg9pbWFnZXMubGl2ZS5jb22CEWxvY2FsLmxpdmUuY29tLmF1ghRsb2NhbHNl
|
|
||||||
YXJjaC5saXZlLmNvbYIUbHM0ZC5zZWFyY2gubGl2ZS5jb22CDW1haWwubGl2ZS5j
|
|
||||||
b22CEW1hcGluZGlhLmxpdmUuY29tgg5sb2NhbC5saXZlLmNvbYINbWFwcy5saXZl
|
|
||||||
LmNvbYIQbWFwcy5saXZlLmNvbS5hdYIPbWluZGlhLmxpdmUuY29tgg1uZXdzLmxp
|
|
||||||
dmUuY29tghxvcmlnaW4uY253ZWIuc2VhcmNoLmxpdmUuY29tghZwcmV2aWV3Lmxv
|
|
||||||
Y2FsLmxpdmUuY29tgg9zZWFyY2gubGl2ZS5jb22CEnRlc3QubWFwcy5saXZlLmNv
|
|
||||||
bYIOdmlkZW8ubGl2ZS5jb22CD3ZpZGVvcy5saXZlLmNvbYIVdmlydHVhbGVhcnRo
|
|
||||||
LmxpdmUuY29tggx3YXAubGl2ZS5jb22CEndlYm1hc3Rlci5saXZlLmNvbYITd2Vi
|
|
||||||
bWFzdGVycy5saXZlLmNvbYIVd3d3LmxvY2FsLmxpdmUuY29tLmF1ghR3d3cubWFw
|
|
||||||
cy5saXZlLmNvbS5hdTCBsAYDVR0fBIGoMIGlMIGioIGfoIGchk1odHRwOi8vbXNj
|
|
||||||
cmwubWljcm9zb2Z0LmNvbS9wa2kvbXNjb3JwL2NybC9NaWNyb3NvZnQlMjBSU0El
|
|
||||||
MjBUTFMlMjBDQSUyMDAyLmNybIZLaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3Br
|
|
||||||
aS9tc2NvcnAvY3JsL01pY3Jvc29mdCUyMFJTQSUyMFRMUyUyMENBJTIwMDIuY3Js
|
|
||||||
MFcGA1UdIARQME4wQgYJKwYBBAGCNyoBMDUwMwYIKwYBBQUHAgEWJ2h0dHA6Ly93
|
|
||||||
d3cubWljcm9zb2Z0LmNvbS9wa2kvbXNjb3JwL2NwczAIBgZngQwBAgEwHwYDVR0j
|
|
||||||
BBgwFoAU/y9/4Qb0OPMt7SWNmML+DvZs/PowHQYDVR0lBBYwFAYIKwYBBQUHAwEG
|
|
||||||
CCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4ICAQB4OIB/EHxpF64iFZME7XkJjZYn
|
|
||||||
ZiYIfOfHs6EGDNn7fxvpZS9HVy1jOWv/RvzEbMuSV3b/fItaJN/zATBg5/6hb5Jq
|
|
||||||
HGIcnKmb+tYrKlYhSOngHSu/8/OYP1dFFIqcVe0769kwXaKUzLh6UVRaS+mB7GFc
|
|
||||||
sXmPMbv5NM7mCUEdMkOaoSmubfw/WzmmRGrcSmtCxtIwMcp8Jf13Esunq//4+9w3
|
|
||||||
M/JXa8ubmXyrY63zt/Oz/NkVJvja89ueovscy6s5sw2r+Su4bRsJjmxwCbakp56K
|
|
||||||
rbh7z417LzW88MMuATvOyk/O8Rbw2KYVSEiQgO54kHI0YkHkJ/6IoeAT1pmCfHUE
|
|
||||||
Rd+Ec8T+/lE2BPLVqp8SjogDYiybb0IR5Gn2vYyUdzsS2h/C5qGNd2t5ehxfjQoL
|
|
||||||
G6Y3GJZQRxkSX6TLPYU0U63wWb4yeSxabpBlARaZMaAoqDa3cX53WCnrAXDz8vuH
|
|
||||||
yAtX2/Jq7IpybFK5kFzbxfI02Ik0aCWJUnXPL8L6esTskwvkzX8rSI/bjPrzcJL5
|
|
||||||
B9pONLy6wc8/Arfu2eNlMbs8s/g8c5zkEc3fBZ9tJ1dqlnMAVgB2+fwI3aK4F34N
|
|
||||||
uyfZW7Xu65KkPhbMnO0GVGM7X4Lkyjm4ysQ9PIRV3MwMfXH+RBSXlIayLTcYG4gl
|
|
||||||
XF1a/qnao6nMjyTIyQ==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
`
|
|
||||||
t.Run("singlepublickey", func(t *testing.T) {
|
|
||||||
block, _ := pem.Decode([]byte(Single))
|
|
||||||
cert, err := x509.ParseCertificate(block.Bytes)
|
|
||||||
assert.Equal(t, err, nil)
|
|
||||||
hash := GenerateCertPublicKeyHash(cert)
|
|
||||||
hashstr := base64.StdEncoding.EncodeToString(hash)
|
|
||||||
assert.Equal(t, "xI/4mNm8xF9uDT4vA9G1+aKAaybwNlkRECnN8vGAHTM=", hashstr)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
377
transport/internet/xtls/config.go
Normal file
377
transport/internet/xtls/config.go
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
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
|
||||||
|
}
|
478
transport/internet/xtls/config.pb.go
Normal file
478
transport/internet/xtls/config.pb.go
Normal file
@@ -0,0 +1,478 @@
|
|||||||
|
// 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
|
||||||
|
}
|
76
transport/internet/xtls/config.proto
Normal file
76
transport/internet/xtls/config.proto
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
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;
|
||||||
|
}
|
53
transport/internet/xtls/config_other.go
Normal file
53
transport/internet/xtls/config_other.go
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
//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
|
||||||
|
}
|
97
transport/internet/xtls/config_test.go
Normal file
97
transport/internet/xtls/config_test.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
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]
|
||||||
|
}
|
||||||
|
}
|
14
transport/internet/xtls/config_windows.go
Normal file
14
transport/internet/xtls/config_windows.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//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
|
||||||
|
}
|
9
transport/internet/xtls/errors.generated.go
Normal file
9
transport/internet/xtls/errors.generated.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
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{})
|
||||||
|
}
|
6
transport/internet/xtls/unsafe.go
Normal file
6
transport/internet/xtls/unsafe.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package xtls
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname errNoCertificates github.com/xtls/go.errNoCertificates
|
||||||
|
var errNoCertificates error
|
35
transport/internet/xtls/xtls.go
Normal file
35
transport/internet/xtls/xtls.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
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}
|
||||||
|
}
|
Reference in New Issue
Block a user