mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 09:36:49 +08:00
Compare commits
86 Commits
v1.6.3
...
dev-shadow
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3b8f09153e | ||
![]() |
0188c2d67d | ||
![]() |
6fb673aee4 | ||
![]() |
d6c2a9aab7 | ||
![]() |
4d5c3195d2 | ||
![]() |
c7358a32f5 | ||
![]() |
e1cd1fd33e | ||
![]() |
82003f28b2 | ||
![]() |
4d2e2b24d3 | ||
![]() |
15999e5c2a | ||
![]() |
48ff0d92c9 | ||
![]() |
229e2513b5 | ||
![]() |
9046eda5ce | ||
![]() |
f32921df30 | ||
![]() |
c3faa8b7ac | ||
![]() |
00c9576118 | ||
![]() |
fa7300e910 | ||
![]() |
b57d3fa869 | ||
![]() |
53833c2323 | ||
![]() |
f176ec54ee | ||
![]() |
bf35e9dcd6 | ||
![]() |
dc72cf2c78 | ||
![]() |
74416570d4 | ||
![]() |
b70912799b | ||
![]() |
15bb23e4ec | ||
![]() |
915690b9ef | ||
![]() |
f571aa72df | ||
![]() |
fb212905bd | ||
![]() |
3fb67f065a | ||
![]() |
77d2f9edd7 | ||
![]() |
7added2693 | ||
![]() |
f536359367 | ||
![]() |
0d5c62e44d | ||
![]() |
620eb63c1b | ||
![]() |
32ce7cd730 | ||
![]() |
717518cb5f | ||
![]() |
7b8ff01114 | ||
![]() |
ed960cc885 | ||
![]() |
1bf3a632ca | ||
![]() |
ff5ce767df | ||
![]() |
8c0d3c0257 | ||
![]() |
9bc1564b0a | ||
![]() |
6a85682716 | ||
![]() |
6f61021f7a | ||
![]() |
c0ceebe709 | ||
![]() |
eaf401eda9 | ||
![]() |
11ec77bc76 | ||
![]() |
3b2ff95a9b | ||
![]() |
3db7d44fc2 | ||
![]() |
c4fbdf1b78 | ||
![]() |
c9b6fc0104 | ||
![]() |
d7ac6946d2 | ||
![]() |
48a75fc340 | ||
![]() |
a55cf1d0bf | ||
![]() |
f35ded79ad | ||
![]() |
f3104b8684 | ||
![]() |
bc4de6a026 | ||
![]() |
3e4e050313 | ||
![]() |
b8e8229242 | ||
![]() |
a8fa5bf516 | ||
![]() |
4a3f3ef775 | ||
![]() |
5858726233 | ||
![]() |
b13c3f053a | ||
![]() |
2e30093ffd | ||
![]() |
1d7c40d728 | ||
![]() |
143229b148 | ||
![]() |
79eda46c62 | ||
![]() |
d87758d46f | ||
![]() |
e5e9e58d66 | ||
![]() |
0565589b8b | ||
![]() |
3cf1b7e601 | ||
![]() |
e18b52a5df | ||
![]() |
691b2b1c73 | ||
![]() |
494a10971b | ||
![]() |
34b3f0204a | ||
![]() |
18fd768166 | ||
![]() |
07d4cfd81a | ||
![]() |
d3efd2d24f | ||
![]() |
aa846b8420 | ||
![]() |
8006430c15 | ||
![]() |
04278a8940 | ||
![]() |
48f7cc2132 | ||
![]() |
8e75e9d763 | ||
![]() |
c7f7e07821 | ||
![]() |
ff2cdcdaaa | ||
![]() |
095e6a714b |
50
.github/workflows/release.yml
vendored
50
.github/workflows/release.yml
vendored
@@ -115,17 +115,15 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Show workflow information
|
||||
id: get_filename
|
||||
run: |
|
||||
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
|
||||
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
|
||||
echo "::set-output name=ASSET_NAME::$_NAME"
|
||||
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.20'
|
||||
check-latest: true
|
||||
|
||||
- name: Get project dependencies
|
||||
@@ -163,30 +161,34 @@ jobs:
|
||||
mv xray xray.exe
|
||||
|
||||
- name: Prepare to release
|
||||
run: |
|
||||
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
|
||||
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
|
||||
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}'))
|
||||
LASTEST_TAG="$(curl -sL "https://api.github.com/repos/v2fly/${INFO[0]}/releases" | jq -r ".[0].tag_name" || echo "latest")"
|
||||
FILE_NAME="${INFO[2]}.dat"
|
||||
echo -e "Downloading ${FILE_NAME}..."
|
||||
curl -L "https://github.com/v2fly/${INFO[0]}/releases/download/${LASTEST_TAG}/${INFO[1]}.dat" -o ./build_assets/${FILE_NAME}
|
||||
echo -e "Verifying HASH key..."
|
||||
HASH="$(curl -sL "https://github.com/v2fly/${INFO[0]}/releases/download/${LASTEST_TAG}/${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
|
||||
uses: nick-fields/retry@v2
|
||||
with:
|
||||
timeout_minutes: 60
|
||||
retry_wait_seconds: 60
|
||||
max_attempts: 60
|
||||
command: |
|
||||
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
|
||||
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
|
||||
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 "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
|
||||
shell: bash
|
||||
run: |
|
||||
pushd build_assets || exit 1
|
||||
touch -mt $(date +%Y01010000) *
|
||||
zip -9vr ../Xray-$ASSET_NAME.zip .
|
||||
zip -9vr ../Xray-${{ env.ASSET_NAME }}.zip .
|
||||
popd || exit 1
|
||||
FILE=./Xray-$ASSET_NAME.zip
|
||||
FILE=./Xray-${{ env.ASSET_NAME }}.zip
|
||||
DGST=$FILE.dgst
|
||||
for METHOD in {"md5","sha1","sha256","sha512"}
|
||||
do
|
||||
@@ -195,20 +197,20 @@ jobs:
|
||||
|
||||
- name: Change the name
|
||||
run: |
|
||||
mv build_assets Xray-$ASSET_NAME
|
||||
mv build_assets Xray-${{ env.ASSET_NAME }}
|
||||
|
||||
- name: Upload files to Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Xray-${{ steps.get_filename.outputs.ASSET_NAME }}
|
||||
name: Xray-${{ env.ASSET_NAME }}
|
||||
path: |
|
||||
./Xray-${{ steps.get_filename.outputs.ASSET_NAME }}/*
|
||||
./Xray-${{ env.ASSET_NAME }}/*
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./Xray-${{ steps.get_filename.outputs.ASSET_NAME }}.zip*
|
||||
file: ./Xray-${{ env.ASSET_NAME }}.zip*
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -30,7 +30,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: 1.19
|
||||
go-version: '1.20'
|
||||
check-latest: true
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v3
|
||||
|
@@ -63,7 +63,7 @@ This repo relies on the following third-party projects:
|
||||
- In production:
|
||||
- [ghodss/yaml](https://github.com/ghodss/yaml)
|
||||
- [gorilla/websocket](https://github.com/gorilla/websocket)
|
||||
- [lucas-clemente/quic-go](https://github.com/lucas-clemente/quic-go)
|
||||
- [quic-go/quic-go](https://github.com/quic-go/quic-go)
|
||||
- [pelletier/go-toml](https://github.com/pelletier/go-toml)
|
||||
- [pires/go-proxyproto](https://github.com/pires/go-proxyproto)
|
||||
- [refraction-networking/utls](https://github.com/refraction-networking/utls)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/commander/config.proto
|
||||
|
||||
package commander
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/dispatcher/config.proto
|
||||
|
||||
package dispatcher
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/dns/config.proto
|
||||
|
||||
package dns
|
||||
|
@@ -7,8 +7,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/log"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/log"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/core"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/dns/fakedns/fakedns.proto
|
||||
|
||||
package fakedns
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/quic-go/quic-go"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/log"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/log/command/config.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.18.0
|
||||
// - protoc v3.21.12
|
||||
// source: app/log/command/config.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/log/config.proto
|
||||
|
||||
package log
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/metrics/config.proto
|
||||
|
||||
package metrics
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/observatory/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.18.0
|
||||
// - protoc v3.21.12
|
||||
// source: app/observatory/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/observatory/config.proto
|
||||
|
||||
package observatory
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/policy/config.proto
|
||||
|
||||
package policy
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/proxyman/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.18.0
|
||||
// - protoc v3.21.12
|
||||
// source: app/proxyman/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/proxyman/config.proto
|
||||
|
||||
package proxyman
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/reverse/config.proto
|
||||
|
||||
package reverse
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/router/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.18.0
|
||||
// - protoc v3.21.12
|
||||
// source: app/router/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/router/config.proto
|
||||
|
||||
package router
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/stats/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.2.0
|
||||
// - protoc v3.18.0
|
||||
// - protoc v3.21.12
|
||||
// source: app/stats/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: app/stats/config.proto
|
||||
|
||||
package stats
|
||||
|
@@ -160,6 +160,19 @@ func (b *Buffer) BytesTo(to int32) []byte {
|
||||
return b.v[b.start : b.start+to]
|
||||
}
|
||||
|
||||
// Check makes sure that 0 <= b.start <= b.end.
|
||||
func (b *Buffer) Check() {
|
||||
if b.start < 0 {
|
||||
b.start = 0
|
||||
}
|
||||
if b.end < 0 {
|
||||
b.end = 0
|
||||
}
|
||||
if b.start > b.end {
|
||||
b.start = b.end
|
||||
}
|
||||
}
|
||||
|
||||
// Resize cuts the buffer at the given position.
|
||||
func (b *Buffer) Resize(from, to int32) {
|
||||
if from < 0 {
|
||||
@@ -173,6 +186,7 @@ func (b *Buffer) Resize(from, to int32) {
|
||||
}
|
||||
b.end = b.start + to
|
||||
b.start += from
|
||||
b.Check()
|
||||
}
|
||||
|
||||
// Advance cuts the buffer at the given position.
|
||||
@@ -181,6 +195,7 @@ func (b *Buffer) Advance(from int32) {
|
||||
from += b.Len()
|
||||
}
|
||||
b.start += from
|
||||
b.Check()
|
||||
}
|
||||
|
||||
// Len returns the length of the buffer content.
|
||||
|
@@ -2,8 +2,8 @@ package crypto
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"math/rand"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
@@ -265,7 +265,8 @@ func (w *AuthenticationWriter) seal(b []byte) (*buf.Buffer, error) {
|
||||
return nil, err
|
||||
}
|
||||
if paddingSize > 0 {
|
||||
// With size of the chunk and padding length encrypted, the content of padding doesn't matter much.
|
||||
// These paddings will send in clear text.
|
||||
// To avoid leakage of PRNG internal state, a cryptographically secure PRNG should be used.
|
||||
paddingBytes := eb.Extend(paddingSize)
|
||||
common.Must2(rand.Read(paddingBytes))
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/log/log.proto
|
||||
|
||||
package log
|
||||
|
@@ -355,6 +355,7 @@ func (m *ClientWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.Buffered
|
||||
common.Interrupt(s.input)
|
||||
common.Interrupt(s.output)
|
||||
}
|
||||
common.Interrupt(s.input)
|
||||
s.Close()
|
||||
}
|
||||
if meta.Option.Has(OptionData) {
|
||||
|
@@ -202,6 +202,7 @@ func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.Buffered
|
||||
common.Interrupt(s.input)
|
||||
common.Interrupt(s.output)
|
||||
}
|
||||
common.Interrupt(s.input)
|
||||
s.Close()
|
||||
}
|
||||
if meta.Option.Has(OptionData) {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/net/address.proto
|
||||
|
||||
package net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/net/destination.proto
|
||||
|
||||
package net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/net/network.proto
|
||||
|
||||
package net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/net/port.proto
|
||||
|
||||
package net
|
||||
|
@@ -3,6 +3,8 @@ package protocol
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"golang.org/x/sys/cpu"
|
||||
|
||||
"github.com/xtls/xray-core/common/bitmask"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/uuid"
|
||||
@@ -79,9 +81,21 @@ type CommandSwitchAccount struct {
|
||||
ValidMin byte
|
||||
}
|
||||
|
||||
var (
|
||||
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
|
||||
hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
|
||||
// Keep in sync with crypto/aes/cipher_s390x.go.
|
||||
hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR &&
|
||||
(cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
|
||||
|
||||
hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 ||
|
||||
runtime.GOARCH == "arm64" && hasGCMAsmARM64 ||
|
||||
runtime.GOARCH == "s390x" && hasGCMAsmS390X
|
||||
)
|
||||
|
||||
func (sc *SecurityConfig) GetSecurityType() SecurityType {
|
||||
if sc == nil || sc.Type == SecurityType_AUTO {
|
||||
if runtime.GOARCH == "amd64" || runtime.GOARCH == "s390x" || runtime.GOARCH == "arm64" {
|
||||
if hasAESGCMHardwareSupport {
|
||||
return SecurityType_AES128_GCM
|
||||
}
|
||||
return SecurityType_CHACHA20_POLY1305
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/protocol/headers.proto
|
||||
|
||||
package protocol
|
||||
|
@@ -1,16 +1,18 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/cipher"
|
||||
|
||||
"github.com/marten-seemann/qtls-go1-18"
|
||||
_ "crypto/tls"
|
||||
_ "unsafe"
|
||||
)
|
||||
|
||||
type (
|
||||
// A CipherSuiteTLS13 is a cipher suite for TLS 1.3
|
||||
CipherSuiteTLS13 = qtls.CipherSuiteTLS13
|
||||
)
|
||||
|
||||
func AEADAESGCMTLS13(key, fixedNonce []byte) cipher.AEAD {
|
||||
return qtls.AEADAESGCMTLS13(key, fixedNonce)
|
||||
type CipherSuiteTLS13 struct {
|
||||
ID uint16
|
||||
KeyLen int
|
||||
AEAD func(key, fixedNonce []byte) cipher.AEAD
|
||||
Hash crypto.Hash
|
||||
}
|
||||
|
||||
//go:linkname AEADAESGCMTLS13 crypto/tls.aeadAESGCMTLS13
|
||||
func AEADAESGCMTLS13(key, nonceMask []byte) cipher.AEAD
|
||||
|
@@ -7,7 +7,7 @@ import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/quicvarint"
|
||||
"github.com/quic-go/quic-go/quicvarint"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/protocol/server_spec.proto
|
||||
|
||||
package protocol
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/protocol/user.proto
|
||||
|
||||
package protocol
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: common/serial/typed_message.proto
|
||||
|
||||
package serial
|
||||
|
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
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: core/config.proto
|
||||
|
||||
package core
|
||||
|
@@ -26,7 +26,8 @@ func MustFromContext(ctx context.Context) *Instance {
|
||||
return x
|
||||
}
|
||||
|
||||
/* toContext returns ctx from the given context, or creates an Instance if the context doesn't find that.
|
||||
/*
|
||||
toContext returns ctx from the given context, or creates an Instance if the context doesn't find that.
|
||||
|
||||
It is unsupported to use this function to create a context that is suitable to invoke Xray's internal component
|
||||
in third party code, you shouldn't use //go:linkname to alias of this function into your own package and
|
||||
@@ -34,7 +35,6 @@ use this function in your third party code.
|
||||
|
||||
For third party code, usage enabled by creating a context to interact with Xray's internal component is unsupported,
|
||||
and may break at any time.
|
||||
|
||||
*/
|
||||
func toContext(ctx context.Context, v *Instance) context.Context {
|
||||
if FromContext(ctx) != v {
|
||||
@@ -43,7 +43,8 @@ func toContext(ctx context.Context, v *Instance) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
/*ToBackgroundDetachedContext create a detached context from another context
|
||||
/*
|
||||
ToBackgroundDetachedContext create a detached context from another context
|
||||
Internal API
|
||||
*/
|
||||
func ToBackgroundDetachedContext(ctx context.Context) context.Context {
|
||||
|
10
core/core.go
10
core/core.go
@@ -12,13 +12,19 @@ package core
|
||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "1.6.3"
|
||||
Version_x byte = 1
|
||||
Version_y byte = 7
|
||||
Version_z byte = 5
|
||||
)
|
||||
|
||||
var (
|
||||
build = "Custom"
|
||||
codename = "Xray, Penetrates Everything."
|
||||
intro = "A unified platform for anti-censorship."
|
||||
@@ -27,7 +33,7 @@ var (
|
||||
// Version returns Xray's version as a string, in the form of "x.y.z" where x, y and z are numbers.
|
||||
// ".z" part may be omitted in regular releases.
|
||||
func Version() string {
|
||||
return version
|
||||
return fmt.Sprintf("%v.%v.%v", Version_x, Version_y, Version_z)
|
||||
}
|
||||
|
||||
// VersionStatement returns a list of strings representing the full version info.
|
||||
|
57
go.mod
57
go.mod
@@ -1,53 +1,62 @@
|
||||
module github.com/xtls/xray-core
|
||||
|
||||
go 1.19
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/protobuf v1.5.2
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/lucas-clemente/quic-go v0.30.0
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.3
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pires/go-proxyproto v0.6.2
|
||||
github.com/refraction-networking/utls v1.1.5
|
||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1
|
||||
github.com/quic-go/quic-go v0.32.0
|
||||
github.com/refraction-networking/utls v1.2.2
|
||||
github.com/sagernet/sing v0.1.6
|
||||
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/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
|
||||
github.com/stretchr/testify v1.8.1
|
||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837
|
||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/net v0.1.0
|
||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3
|
||||
github.com/xtls/reality v0.0.0-20230217102704-085bdf2104d3
|
||||
go.starlark.net v0.0.0-20230128213706-3f75dec8e403
|
||||
golang.org/x/crypto v0.6.0
|
||||
golang.org/x/net v0.7.0
|
||||
golang.org/x/sync v0.1.0
|
||||
golang.org/x/sys v0.1.0
|
||||
google.golang.org/grpc v1.50.1
|
||||
golang.org/x/sys v0.5.0
|
||||
google.golang.org/grpc v1.53.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
||||
h12.io/socks v1.0.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/google/pprof v0.0.0-20221103000818-d260c55eee4c // indirect
|
||||
github.com/klauspost/compress v1.15.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.1.2 // indirect
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.4.0 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 // indirect
|
||||
github.com/klauspost/compress v1.15.15 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.3 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.8.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 // 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
|
||||
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/text v0.4.0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect
|
||||
golang.org/x/mod v0.8.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.1.7 // indirect
|
||||
|
123
go.sum
123
go.sum
@@ -8,8 +8,8 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
@@ -34,8 +34,8 @@ github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJn
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
|
||||
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
@@ -61,6 +61,8 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
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 v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@@ -74,10 +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/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-20221010195024-131d412537ea h1:R3VfsTXMMK4JCWZDdxScmnTzu9n9YRsDvguLis0U/b8=
|
||||
github.com/google/pprof v0.0.0-20221010195024-131d412537ea/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/pprof v0.0.0-20221103000818-d260c55eee4c h1:lvddKcYTQ545ADhBujtIJmqQrZBDsGo7XIMbAQe/sNY=
|
||||
github.com/google/pprof v0.0.0-20221103000818-d260c55eee4c/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/pprof v0.0.0-20230207041349-798e818bf904 h1:4/hN5RUoecvl+RmJRE2YxKWtnnQls6rQjjW5oV7qg2U=
|
||||
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 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
@@ -91,26 +91,19 @@ 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/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/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
|
||||
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
||||
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.1.2 h1:XhdX4fqAJUA0yj+kUwMavO0hHrSPAecYdYf1ZmxHvak=
|
||||
github.com/klauspost/cpuid/v2 v2.1.2/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
|
||||
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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lucas-clemente/quic-go v0.30.0 h1:nwLW0h8ahVQ5EPTIM7uhl/stHqQDea15oRlYKZmw2O0=
|
||||
github.com/lucas-clemente/quic-go v0.30.0/go.mod h1:ssOrRsOmdxa768Wr78vnh2B8JozgLsMzG/g+0qEC7uk=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
|
||||
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/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
@@ -119,9 +112,9 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
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/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/onsi/ginkgo/v2 v2.4.0 h1:+Ig9nvqgS5OBSACXNk15PLdp0U9XPYROt9CFzVdFGIs=
|
||||
github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo=
|
||||
github.com/onsi/gomega v1.22.1 h1:pY8O4lBfsHKZHM/6nrxkhVPUznOlIu3quZcKP/M20KI=
|
||||
github.com/onsi/ginkgo/v2 v2.8.1 h1:xFTEVwOFa1D/Ty24Ws1npBWkDYEV9BqZrsDxVrVkrrU=
|
||||
github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc=
|
||||
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/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
@@ -137,15 +130,29 @@ 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/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/refraction-networking/utls v1.1.5 h1:JtrojoNhbUQkBqEg05sP3gDgDj6hIEAAVKbI9lx4n6w=
|
||||
github.com/refraction-networking/utls v1.1.5/go.mod h1:jRQxtYi7nkq1p28HF2lwOH5zQm9aC8rpK0O9lIIzGh8=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||
github.com/quic-go/quic-go v0.32.0 h1:lY02md31s1JgPiiyfqJijpu/UX/Iun304FI3yUqX7tA=
|
||||
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/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc h1:x7H64IiqyrpxPWl/KrWkknzEK4GmpqgfZeVKFVw6E/M=
|
||||
github.com/sagernet/sing v0.0.0-20220801112236-1bb95f9661fc/go.mod h1:GbtQfZSpmtD3cXeD1qX2LCMwY8dH+bnnInDTqd92IsM=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1 h1:RYvOc69eSNMN0dwVugrDts41Nn7Ar/C/n/fvytvFcp4=
|
||||
github.com/sagernet/sing-shadowsocks v0.0.0-20220801112336-a91eacdd01e1/go.mod h1:NqZjiXszgVCMQ4gVDa2V+drhS8NMfGqUqDF86EacEFc=
|
||||
github.com/sagernet/sing v0.1.6 h1:Qy63OUfKpcqKjfd5rPmUlj0RGjHZSK/PJn0duyCCsRg=
|
||||
github.com/sagernet/sing v0.1.6/go.mod h1:JLSXsPTGRJFo/3X7EcAOCUgJH2/gAoxSJgBsnCZRp/w=
|
||||
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7 h1:Plup6oEiyLzY3HDqQ+QsUBzgBGdVmcsgf3t8h940z9U=
|
||||
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/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/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
@@ -188,33 +195,34 @@ github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF
|
||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 h1:AHhUwwFJGl27E46OpdJHplZkK09m7aETNBNzhT6t15M=
|
||||
github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY=
|
||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3 h1:a3Y4WVjCxwoyO4E2xdNvq577tW8lkSBgyrA8E9+2NtM=
|
||||
github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY=
|
||||
github.com/xtls/reality v0.0.0-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=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2 h1:5/KzhcSqd4UgY51l17r7C5g/JiE6DRw1Vq7VJfQHuMc=
|
||||
go.starlark.net v0.0.0-20221028183056-acb66ad56dd2/go.mod h1:kIVgS18CjmEC3PqMd5kaJSGEifyV/CeB9x506ZJ1Vbk=
|
||||
go.starlark.net v0.0.0-20230128213706-3f75dec8e403 h1:jPeC7Exc+m8OBJUlWbBLh0O5UZPM7yU5W4adnhhbG4U=
|
||||
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/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f h1:Al51T6tzvuh3oiwX11vex3QgJ2XTedFPGmbEVh8cdoc=
|
||||
golang.org/x/exp v0.0.0-20221028150844-83b7d23a625f/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/exp v0.0.0-20221106115401-f9659909a136 h1:Fq7F/w7MAa1KJ5bt2aJ62ihqp9HDcRuyILskkpIAurw=
|
||||
golang.org/x/exp v0.0.0-20221106115401-f9659909a136/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w=
|
||||
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-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-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.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
||||
golang.org/x/mod v0.8.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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -228,10 +236,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0=
|
||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
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-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -259,21 +265,20 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
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-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.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-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/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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||
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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
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.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -284,8 +289,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
|
||||
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.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -304,16 +309,16 @@ 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-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-20221027153422-115e99e71e1c h1:QgY/XxIAIeccR+Ca/rDdKubLIU9rcJ3xfy1DC/Wd2Oo=
|
||||
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c/go.mod h1:CGI5F/G+E5bKwmfYo09AXuVN4dD894kIKUFmVbP2/Fo=
|
||||
google.golang.org/genproto v0.0.0-20230209215440-0dfe4f8abfcc h1:ijGwO+0vL2hJt5gaygqP2j6PfflOBrRot0IczKbmtio=
|
||||
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.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.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
|
||||
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
|
||||
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
|
||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -338,6 +343,8 @@ gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4=
|
||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
||||
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
|
||||
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
@@ -53,6 +53,7 @@ type HTTPRemoteConfig struct {
|
||||
|
||||
type HTTPClientConfig struct {
|
||||
Servers []*HTTPRemoteConfig `json:"servers"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
}
|
||||
|
||||
func (v *HTTPClientConfig) Build() (proto.Message, error) {
|
||||
@@ -77,5 +78,12 @@ func (v *HTTPClientConfig) Build() (proto.Message, error) {
|
||||
}
|
||||
config.Server[idx] = server
|
||||
}
|
||||
config.Header = make([]*http.Header, 0, 32)
|
||||
for key, value := range v.Headers {
|
||||
config.Header = append(config.Header, &http.Header{
|
||||
Key: key,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
@@ -107,7 +107,7 @@ func buildShadowsocks2022(v *ShadowsocksServerConfig) (proto.Message, error) {
|
||||
config.Email = v.Email
|
||||
return config, nil
|
||||
}
|
||||
|
||||
|
||||
if v.Cipher == "" {
|
||||
return nil, newError("shadowsocks 2022 (multi-user): missing server method")
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func buildShadowsocks2022(v *ShadowsocksServerConfig) (proto.Message, error) {
|
||||
config.Method = v.Cipher
|
||||
config.Key = v.Password
|
||||
config.Network = v.NetworkList.Build()
|
||||
|
||||
|
||||
for _, user := range v.Users {
|
||||
if user.Cipher != "" {
|
||||
return nil, newError("shadowsocks 2022 (multi-user): users must have empty method")
|
||||
@@ -145,10 +145,10 @@ func buildShadowsocks2022(v *ShadowsocksServerConfig) (proto.Message, error) {
|
||||
return nil, newError("shadowsocks 2022 (relay): all users must have relay address")
|
||||
}
|
||||
config.Destinations = append(config.Destinations, &shadowsocks_2022.RelayDestination{
|
||||
Key: user.Password,
|
||||
Email: user.Email,
|
||||
Key: user.Password,
|
||||
Email: user.Email,
|
||||
Address: user.Address.Build(),
|
||||
Port: uint32(user.Port),
|
||||
Port: uint32(user.Port),
|
||||
})
|
||||
}
|
||||
return config, nil
|
||||
|
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
|
||||
}
|
@@ -2,13 +2,17 @@ package conf
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math"
|
||||
"net/url"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
@@ -18,6 +22,7 @@ import (
|
||||
"github.com/xtls/xray-core/transport/internet/http"
|
||||
"github.com/xtls/xray-core/transport/internet/kcp"
|
||||
"github.com/xtls/xray-core/transport/internet/quic"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
"github.com/xtls/xray-core/transport/internet/tcp"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"github.com/xtls/xray-core/transport/internet/websocket"
|
||||
@@ -379,6 +384,9 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
||||
config.CipherSuites = c.CipherSuites
|
||||
config.PreferServerCipherSuites = c.PreferServerCipherSuites
|
||||
config.Fingerprint = strings.ToLower(c.Fingerprint)
|
||||
if config.Fingerprint != "" && tls.GetFingerprint(config.Fingerprint) == nil {
|
||||
return nil, newError(`unknown fingerprint: `, config.Fingerprint)
|
||||
}
|
||||
config.RejectUnknownSni = c.RejectUnknownSNI
|
||||
|
||||
if c.PinnedPeerCertificateChainSha256 != nil {
|
||||
@@ -455,6 +463,7 @@ type XTLSConfig struct {
|
||||
MaxVersion string `json:"maxVersion"`
|
||||
CipherSuites string `json:"cipherSuites"`
|
||||
PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
RejectUnknownSNI bool `json:"rejectUnknownSni"`
|
||||
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
|
||||
}
|
||||
@@ -484,6 +493,9 @@ func (c *XTLSConfig) Build() (proto.Message, error) {
|
||||
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 {
|
||||
@@ -497,6 +509,169 @@ func (c *XTLSConfig) Build() (proto.Message, error) {
|
||||
}
|
||||
}
|
||||
|
||||
newError(`You are using an old version of XTLS, which is deprecated now and will be removed soon. Please use flow "xtls-rprx-vision" with "tls & tlsSettings" instead.`).AtWarning().WriteToLog()
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type REALITYConfig struct {
|
||||
Show bool `json:"show"`
|
||||
Dest json.RawMessage `json:"dest"`
|
||||
Type string `json:"type"`
|
||||
Xver uint64 `json:"xver"`
|
||||
ServerNames []string `json:"serverNames"`
|
||||
PrivateKey string `json:"privateKey"`
|
||||
MinClientVer string `json:"minClientVer"`
|
||||
MaxClientVer string `json:"maxClientVer"`
|
||||
MaxTimeDiff uint64 `json:"maxTimeDiff"`
|
||||
ShortIds []string `json:"shortIds"`
|
||||
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
ServerName string `json:"serverName"`
|
||||
PublicKey string `json:"publicKey"`
|
||||
ShortId string `json:"shortId"`
|
||||
SpiderX string `json:"spiderX"`
|
||||
}
|
||||
|
||||
func (c *REALITYConfig) Build() (proto.Message, error) {
|
||||
config := new(reality.Config)
|
||||
config.Show = c.Show
|
||||
var err error
|
||||
if c.Dest != nil {
|
||||
var i uint16
|
||||
var s string
|
||||
if err = json.Unmarshal(c.Dest, &i); err == nil {
|
||||
s = strconv.Itoa(int(i))
|
||||
} else {
|
||||
_ = json.Unmarshal(c.Dest, &s)
|
||||
}
|
||||
if c.Type == "" && s != "" {
|
||||
switch s[0] {
|
||||
case '@', '/':
|
||||
c.Type = "unix"
|
||||
if s[0] == '@' && len(s) > 1 && s[1] == '@' && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
|
||||
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path)) // may need padding to work with haproxy
|
||||
copy(fullAddr, s[1:])
|
||||
s = string(fullAddr)
|
||||
}
|
||||
default:
|
||||
if _, err = strconv.Atoi(s); err == nil {
|
||||
s = "127.0.0.1:" + s
|
||||
}
|
||||
if _, _, err = net.SplitHostPort(s); err == nil {
|
||||
c.Type = "tcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.Type == "" {
|
||||
return nil, newError(`please fill in a valid value for "dest"`)
|
||||
}
|
||||
if c.Xver > 2 {
|
||||
return nil, newError(`invalid PROXY protocol version, "xver" only accepts 0, 1, 2`)
|
||||
}
|
||||
if len(c.ServerNames) == 0 {
|
||||
return nil, newError(`empty "serverNames"`)
|
||||
}
|
||||
if c.PrivateKey == "" {
|
||||
return nil, newError(`empty "privateKey"`)
|
||||
}
|
||||
if config.PrivateKey, err = base64.RawURLEncoding.DecodeString(c.PrivateKey); err != nil || len(config.PrivateKey) != 32 {
|
||||
return nil, newError(`invalid "privateKey": `, c.PrivateKey)
|
||||
}
|
||||
if c.MinClientVer != "" {
|
||||
config.MinClientVer = make([]byte, 3)
|
||||
var u uint64
|
||||
for i, s := range strings.Split(c.MinClientVer, ".") {
|
||||
if i == 3 {
|
||||
return nil, newError(`invalid "minClientVer": `, c.MinClientVer)
|
||||
}
|
||||
if u, err = strconv.ParseUint(s, 10, 8); err != nil {
|
||||
return nil, newError(`"minClientVer[`, i, `]" should be lesser than 256`)
|
||||
} else {
|
||||
config.MinClientVer[i] = byte(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.MaxClientVer != "" {
|
||||
config.MaxClientVer = make([]byte, 3)
|
||||
var u uint64
|
||||
for i, s := range strings.Split(c.MaxClientVer, ".") {
|
||||
if i == 3 {
|
||||
return nil, newError(`invalid "maxClientVer": `, c.MaxClientVer)
|
||||
}
|
||||
if u, err = strconv.ParseUint(s, 10, 8); err != nil {
|
||||
return nil, newError(`"maxClientVer[`, i, `]" should be lesser than 256`)
|
||||
} else {
|
||||
config.MaxClientVer[i] = byte(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(c.ShortIds) == 0 {
|
||||
return nil, newError(`empty "shortIds"`)
|
||||
}
|
||||
config.ShortIds = make([][]byte, len(c.ShortIds))
|
||||
for i, s := range c.ShortIds {
|
||||
config.ShortIds[i] = make([]byte, 8)
|
||||
if _, err = hex.Decode(config.ShortIds[i], []byte(s)); err != nil {
|
||||
return nil, newError(`invalid "shortIds[`, i, `]": `, s)
|
||||
}
|
||||
}
|
||||
config.Dest = s
|
||||
config.Type = c.Type
|
||||
config.Xver = c.Xver
|
||||
config.ServerNames = c.ServerNames
|
||||
config.MaxTimeDiff = c.MaxTimeDiff
|
||||
} else {
|
||||
if c.Fingerprint == "" {
|
||||
return nil, newError(`empty "fingerprint"`)
|
||||
}
|
||||
if config.Fingerprint = strings.ToLower(c.Fingerprint); tls.GetFingerprint(config.Fingerprint) == nil {
|
||||
return nil, newError(`unknown "fingerprint": `, config.Fingerprint)
|
||||
}
|
||||
if config.Fingerprint == "hellogolang" {
|
||||
return nil, newError(`invalid "fingerprint": `, config.Fingerprint)
|
||||
}
|
||||
if c.PublicKey == "" {
|
||||
return nil, newError(`empty "publicKey"`)
|
||||
}
|
||||
if config.PublicKey, err = base64.RawURLEncoding.DecodeString(c.PublicKey); err != nil || len(config.PublicKey) != 32 {
|
||||
return nil, newError(`invalid "publicKey": `, c.PublicKey)
|
||||
}
|
||||
config.ShortId = make([]byte, 8)
|
||||
if _, err = hex.Decode(config.ShortId, []byte(c.ShortId)); err != nil {
|
||||
return nil, newError(`invalid "shortId": `, c.ShortId)
|
||||
}
|
||||
if c.SpiderX == "" {
|
||||
c.SpiderX = "/"
|
||||
}
|
||||
if c.SpiderX[0] != '/' {
|
||||
return nil, newError(`invalid "spiderX": `, c.SpiderX)
|
||||
}
|
||||
config.SpiderY = make([]int64, 10)
|
||||
u, _ := url.Parse(c.SpiderX)
|
||||
q := u.Query()
|
||||
parse := func(param string, index int) {
|
||||
if q.Get(param) != "" {
|
||||
s := strings.Split(q.Get(param), "-")
|
||||
if len(s) == 1 {
|
||||
config.SpiderY[index], _ = strconv.ParseInt(s[0], 10, 64)
|
||||
config.SpiderY[index+1], _ = strconv.ParseInt(s[0], 10, 64)
|
||||
} else {
|
||||
config.SpiderY[index], _ = strconv.ParseInt(s[0], 10, 64)
|
||||
config.SpiderY[index+1], _ = strconv.ParseInt(s[1], 10, 64)
|
||||
}
|
||||
}
|
||||
q.Del(param)
|
||||
}
|
||||
parse("p", 0) // padding
|
||||
parse("c", 2) // concurrency
|
||||
parse("t", 4) // times
|
||||
parse("i", 6) // interval
|
||||
parse("r", 8) // return
|
||||
u.RawQuery = q.Encode()
|
||||
config.SpiderX = u.String()
|
||||
config.ServerName = c.ServerName
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -533,7 +708,8 @@ type SocketConfig struct {
|
||||
DialerProxy string `json:"dialerProxy"`
|
||||
TCPKeepAliveInterval int32 `json:"tcpKeepAliveInterval"`
|
||||
TCPKeepAliveIdle int32 `json:"tcpKeepAliveIdle"`
|
||||
TCPCongestion string `json:"tcpCongestion"`
|
||||
TCPCongestion string `json:"tcpCongestion"`
|
||||
Interface string `json:"interface"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -582,24 +758,26 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||
DialerProxy: c.DialerProxy,
|
||||
TcpKeepAliveInterval: c.TCPKeepAliveInterval,
|
||||
TcpKeepAliveIdle: c.TCPKeepAliveIdle,
|
||||
TcpCongestion: c.TCPCongestion,
|
||||
TcpCongestion: c.TCPCongestion,
|
||||
Interface: c.Interface,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type StreamConfig struct {
|
||||
Network *TransportProtocol `json:"network"`
|
||||
Security string `json:"security"`
|
||||
TLSSettings *TLSConfig `json:"tlsSettings"`
|
||||
XTLSSettings *XTLSConfig `json:"xtlsSettings"`
|
||||
TCPSettings *TCPConfig `json:"tcpSettings"`
|
||||
KCPSettings *KCPConfig `json:"kcpSettings"`
|
||||
WSSettings *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPSettings *HTTPConfig `json:"httpSettings"`
|
||||
DSSettings *DomainSocketConfig `json:"dsSettings"`
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
SocketSettings *SocketConfig `json:"sockopt"`
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
Network *TransportProtocol `json:"network"`
|
||||
Security string `json:"security"`
|
||||
TLSSettings *TLSConfig `json:"tlsSettings"`
|
||||
XTLSSettings *XTLSConfig `json:"xtlsSettings"`
|
||||
REALITYSettings *REALITYConfig `json:"realitySettings"`
|
||||
TCPSettings *TCPConfig `json:"tcpSettings"`
|
||||
KCPSettings *KCPConfig `json:"kcpSettings"`
|
||||
WSSettings *WebSocketConfig `json:"wsSettings"`
|
||||
HTTPSettings *HTTPConfig `json:"httpSettings"`
|
||||
DSSettings *DomainSocketConfig `json:"dsSettings"`
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
SocketSettings *SocketConfig `json:"sockopt"`
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -649,6 +827,21 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
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 {
|
||||
return nil, newError(`REALITY: Empty "realitySettings".`)
|
||||
}
|
||||
ts, err := c.REALITYSettings.Build()
|
||||
if err != nil {
|
||||
return nil, newError("Failed to build REALITY config.").Base(err)
|
||||
}
|
||||
tm := serial.ToTypedMessage(ts)
|
||||
config.SecuritySettings = append(config.SecuritySettings, tm)
|
||||
config.SecurityType = tm.Type
|
||||
}
|
||||
if c.TCPSettings != nil {
|
||||
ts, err := c.TCPSettings.Build()
|
||||
if err != nil {
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
@@ -52,7 +53,15 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
||||
}
|
||||
account.Id = u.String()
|
||||
|
||||
switch account.Flow {
|
||||
accountFlow := account.Flow
|
||||
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`)
|
||||
|
111
infra/conf/wireguard.go
Normal file
111
infra/conf/wireguard.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/xtls/xray-core/proxy/wireguard"
|
||||
)
|
||||
|
||||
type WireGuardPeerConfig struct {
|
||||
PublicKey string `json:"publicKey"`
|
||||
PreSharedKey string `json:"preSharedKey"`
|
||||
Endpoint string `json:"endpoint"`
|
||||
KeepAlive int `json:"keepAlive"`
|
||||
AllowedIPs []string `json:"allowedIPs,omitempty"`
|
||||
}
|
||||
|
||||
func (c *WireGuardPeerConfig) Build() (proto.Message, error) {
|
||||
var err error
|
||||
config := new(wireguard.PeerConfig)
|
||||
|
||||
config.PublicKey, err = parseWireGuardKey(c.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.PreSharedKey != "" {
|
||||
config.PreSharedKey, err = parseWireGuardKey(c.PreSharedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
config.PreSharedKey = "0000000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
||||
|
||||
config.Endpoint = c.Endpoint
|
||||
// default 0
|
||||
config.KeepAlive = int32(c.KeepAlive)
|
||||
if c.AllowedIPs == nil {
|
||||
config.AllowedIps = []string{"0.0.0.0/0", "::0/0"}
|
||||
} else {
|
||||
config.AllowedIps = c.AllowedIPs
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type WireGuardConfig struct {
|
||||
SecretKey string `json:"secretKey"`
|
||||
Address []string `json:"address"`
|
||||
Peers []*WireGuardPeerConfig `json:"peers"`
|
||||
MTU int `json:"mtu"`
|
||||
NumWorkers int `json:"workers"`
|
||||
}
|
||||
|
||||
func (c *WireGuardConfig) Build() (proto.Message, error) {
|
||||
config := new(wireguard.DeviceConfig)
|
||||
|
||||
var err error
|
||||
config.SecretKey, err = parseWireGuardKey(c.SecretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if c.Address == nil {
|
||||
// bogon ips
|
||||
config.Endpoint = []string{"10.0.0.1", "fd59:7153:2388:b5fd:0000:0000:0000:0001"}
|
||||
} else {
|
||||
config.Endpoint = c.Address
|
||||
}
|
||||
|
||||
if c.Peers != nil {
|
||||
config.Peers = make([]*wireguard.PeerConfig, len(c.Peers))
|
||||
for i, p := range c.Peers {
|
||||
msg, err := p.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
config.Peers[i] = msg.(*wireguard.PeerConfig)
|
||||
}
|
||||
}
|
||||
|
||||
if c.MTU == 0 {
|
||||
config.Mtu = 1420
|
||||
} else {
|
||||
config.Mtu = int32(c.MTU)
|
||||
}
|
||||
// these a fallback code exists in github.com/nanoda0523/wireguard-go code,
|
||||
// we don't need to process fallback manually
|
||||
config.NumWorkers = int32(c.NumWorkers)
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func parseWireGuardKey(str string) (string, error) {
|
||||
if len(str) != 64 {
|
||||
// may in base64 form
|
||||
dat, err := base64.StdEncoding.DecodeString(str)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(dat) != 32 {
|
||||
return "", newError("key should be 32 bytes: " + str)
|
||||
}
|
||||
return hex.EncodeToString(dat), err
|
||||
} else {
|
||||
// already hex form
|
||||
return str, nil
|
||||
}
|
||||
}
|
49
infra/conf/wireguard_test.go
Normal file
49
infra/conf/wireguard_test.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package conf_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/xtls/xray-core/infra/conf"
|
||||
"github.com/xtls/xray-core/proxy/wireguard"
|
||||
)
|
||||
|
||||
func TestWireGuardOutbound(t *testing.T) {
|
||||
creator := func() Buildable {
|
||||
return new(WireGuardConfig)
|
||||
}
|
||||
|
||||
runMultiTestCase(t, []TestCase{
|
||||
{
|
||||
Input: `{
|
||||
"secretKey": "uJv5tZMDltsiYEn+kUwb0Ll/CXWhMkaSCWWhfPEZM3A=",
|
||||
"address": ["10.1.1.1", "fd59:7153:2388:b5fd:0000:0000:1234:0001"],
|
||||
"peers": [
|
||||
{
|
||||
"publicKey": "6e65ce0be17517110c17d77288ad87e7fd5252dcc7d09b95a39d61db03df832a",
|
||||
"endpoint": "127.0.0.1:1234"
|
||||
}
|
||||
],
|
||||
"mtu": 1300,
|
||||
"workers": 2
|
||||
}`,
|
||||
Parser: loadJSON(creator),
|
||||
Output: &wireguard.DeviceConfig{
|
||||
// key converted into hex form
|
||||
SecretKey: "b89bf9b5930396db226049fe914c1bd0b97f0975a13246920965a17cf1193370",
|
||||
Endpoint: []string{"10.1.1.1", "fd59:7153:2388:b5fd:0000:0000:1234:0001"},
|
||||
Peers: []*wireguard.PeerConfig{
|
||||
{
|
||||
// also can read from hex form directly
|
||||
PublicKey: "6e65ce0be17517110c17d77288ad87e7fd5252dcc7d09b95a39d61db03df832a",
|
||||
PreSharedKey: "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
Endpoint: "127.0.0.1:1234",
|
||||
KeepAlive: 0,
|
||||
AllowedIps: []string{"0.0.0.0/0", "::0/0"},
|
||||
},
|
||||
},
|
||||
Mtu: 1300,
|
||||
NumWorkers: 2,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
@@ -26,6 +26,7 @@ var (
|
||||
"vmess": func() interface{} { return new(VMessInboundConfig) },
|
||||
"trojan": func() interface{} { return new(TrojanServerConfig) },
|
||||
"mtproto": func() interface{} { return new(MTProtoServerConfig) },
|
||||
"shadow-tls": func() interface{} { return new(ShadowTLSServerConfig) },
|
||||
}, "protocol", "settings")
|
||||
|
||||
outboundConfigLoader = NewJSONConfigLoader(ConfigCreatorCache{
|
||||
@@ -40,6 +41,8 @@ var (
|
||||
"trojan": func() interface{} { return new(TrojanClientConfig) },
|
||||
"mtproto": func() interface{} { return new(MTProtoClientConfig) },
|
||||
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
||||
"wireguard": func() interface{} { return new(WireGuardConfig) },
|
||||
"shadow-tls": func() interface{} { return new(ShadowTLSClientConfig) },
|
||||
}, "protocol", "settings")
|
||||
|
||||
ctllog = log.New(os.Stderr, "xctl> ", 0)
|
||||
|
@@ -15,5 +15,6 @@ func init() {
|
||||
// cmdConvert,
|
||||
tls.CmdTLS,
|
||||
cmdUUID,
|
||||
cmdX25519,
|
||||
)
|
||||
}
|
||||
|
63
main/commands/all/x25519.go
Normal file
63
main/commands/all/x25519.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package all
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/xtls/xray-core/main/commands/base"
|
||||
"golang.org/x/crypto/curve25519"
|
||||
)
|
||||
|
||||
var cmdX25519 = &base.Command{
|
||||
UsageLine: `{{.Exec}} x25519 [-i "private key (base64.RawURLEncoding)"]`,
|
||||
Short: `Generate key pair for x25519 key exchange`,
|
||||
Long: `
|
||||
Generate key pair for x25519 key exchange.
|
||||
|
||||
Random: {{.Exec}} x25519
|
||||
|
||||
From private key: {{.Exec}} x25519 -i "private key (base64.RawURLEncoding)"
|
||||
`,
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdX25519.Run = executeX25519 // break init loop
|
||||
}
|
||||
|
||||
var input_base64 = cmdX25519.Flag.String("i", "", "")
|
||||
|
||||
func executeX25519(cmd *base.Command, args []string) {
|
||||
var output string
|
||||
var err error
|
||||
var privateKey []byte
|
||||
var publicKey []byte
|
||||
if len(*input_base64) > 0 {
|
||||
privateKey, err = base64.RawURLEncoding.DecodeString(*input_base64)
|
||||
if err != nil {
|
||||
output = err.Error()
|
||||
goto out
|
||||
}
|
||||
if len(privateKey) != curve25519.ScalarSize {
|
||||
output = "Invalid length of private key."
|
||||
goto out
|
||||
}
|
||||
}
|
||||
if privateKey == nil {
|
||||
privateKey = make([]byte, curve25519.ScalarSize)
|
||||
if _, err = io.ReadFull(rand.Reader, privateKey); err != nil {
|
||||
output = err.Error()
|
||||
goto out
|
||||
}
|
||||
}
|
||||
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
|
||||
output = err.Error()
|
||||
goto out
|
||||
}
|
||||
output = fmt.Sprintf("Private key: %v\nPublic key: %v",
|
||||
base64.RawURLEncoding.EncodeToString(privateKey),
|
||||
base64.RawURLEncoding.EncodeToString(publicKey))
|
||||
out:
|
||||
fmt.Println(output)
|
||||
}
|
@@ -42,12 +42,14 @@ import (
|
||||
_ "github.com/xtls/xray-core/proxy/loopback"
|
||||
_ "github.com/xtls/xray-core/proxy/mtproto"
|
||||
_ "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/trojan"
|
||||
_ "github.com/xtls/xray-core/proxy/vless/inbound"
|
||||
_ "github.com/xtls/xray-core/proxy/vless/outbound"
|
||||
_ "github.com/xtls/xray-core/proxy/vmess/inbound"
|
||||
_ "github.com/xtls/xray-core/proxy/vmess/outbound"
|
||||
_ "github.com/xtls/xray-core/proxy/wireguard"
|
||||
|
||||
// Transports
|
||||
_ "github.com/xtls/xray-core/transport/internet/domainsocket"
|
||||
@@ -55,6 +57,7 @@ import (
|
||||
_ "github.com/xtls/xray-core/transport/internet/http"
|
||||
_ "github.com/xtls/xray-core/transport/internet/kcp"
|
||||
_ "github.com/xtls/xray-core/transport/internet/quic"
|
||||
_ "github.com/xtls/xray-core/transport/internet/reality"
|
||||
_ "github.com/xtls/xray-core/transport/internet/tcp"
|
||||
_ "github.com/xtls/xray-core/transport/internet/tls"
|
||||
_ "github.com/xtls/xray-core/transport/internet/udp"
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/blackhole/config.proto
|
||||
|
||||
package blackhole
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/dns/config.proto
|
||||
|
||||
package dns
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/dokodemo/config.proto
|
||||
|
||||
package dokodemo
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/freedom/config.proto
|
||||
|
||||
package freedom
|
||||
|
@@ -2,12 +2,14 @@ package http
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"text/template"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
@@ -30,6 +32,7 @@ import (
|
||||
type Client struct {
|
||||
serverPicker protocol.ServerPicker
|
||||
policyManager policy.Manager
|
||||
header []*Header
|
||||
}
|
||||
|
||||
type h2Conn struct {
|
||||
@@ -60,6 +63,7 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
return &Client{
|
||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
header: config.Header,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -88,12 +92,17 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
buf.ReleaseMulti(mbuf)
|
||||
defer bytespool.Free(firstPayload)
|
||||
|
||||
header, err := fillRequestHeader(ctx, c.header)
|
||||
if err != nil {
|
||||
return newError("failed to fill out header").Base(err)
|
||||
}
|
||||
|
||||
if err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||
server := c.serverPicker.PickServer()
|
||||
dest := server.Destination()
|
||||
user = server.PickUser()
|
||||
|
||||
netConn, err := setUpHTTPTunnel(ctx, dest, targetAddr, user, dialer, firstPayload)
|
||||
netConn, err := setUpHTTPTunnel(ctx, dest, targetAddr, user, dialer, header, firstPayload)
|
||||
if netConn != nil {
|
||||
if _, ok := netConn.(*http2Conn); !ok {
|
||||
if _, err := netConn.Write(firstPayload); err != nil {
|
||||
@@ -139,8 +148,42 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
return nil
|
||||
}
|
||||
|
||||
// fillRequestHeader will fill out the template of the headers
|
||||
func fillRequestHeader(ctx context.Context, header []*Header) ([]*Header, error) {
|
||||
if len(header) == 0 {
|
||||
return header, nil
|
||||
}
|
||||
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
|
||||
data := struct {
|
||||
Source net.Destination
|
||||
Target net.Destination
|
||||
}{
|
||||
Source: inbound.Source,
|
||||
Target: outbound.Target,
|
||||
}
|
||||
|
||||
filled := make([]*Header, len(header))
|
||||
for i, h := range header {
|
||||
tmpl, err := template.New(h.Key).Parse(h.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
|
||||
if err = tmpl.Execute(&buf, data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
filled[i] = &Header{Key: h.Key, Value: buf.String()}
|
||||
}
|
||||
|
||||
return filled, nil
|
||||
}
|
||||
|
||||
// setUpHTTPTunnel will create a socket tunnel via HTTP CONNECT method
|
||||
func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, user *protocol.MemoryUser, dialer internet.Dialer, firstPayload []byte) (net.Conn, error) {
|
||||
func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, user *protocol.MemoryUser, dialer internet.Dialer, header []*Header, firstPayload []byte) (net.Conn, error) {
|
||||
req := &http.Request{
|
||||
Method: http.MethodConnect,
|
||||
URL: &url.URL{Host: target},
|
||||
@@ -154,6 +197,10 @@ func setUpHTTPTunnel(ctx context.Context, dest net.Destination, target string, u
|
||||
req.Header.Set("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth)))
|
||||
}
|
||||
|
||||
for _, h := range header {
|
||||
req.Header.Set(h.Key, h.Value)
|
||||
}
|
||||
|
||||
connectHTTP1 := func(rawConn net.Conn) (net.Conn, error) {
|
||||
req.Header.Set("Proxy-Connection", "Keep-Alive")
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/http/config.proto
|
||||
|
||||
package http
|
||||
@@ -150,6 +150,61 @@ func (x *ServerConfig) GetUserLevel() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
type Header struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Header) Reset() {
|
||||
*x = Header{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_http_config_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Header) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Header) ProtoMessage() {}
|
||||
|
||||
func (x *Header) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_http_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 Header.ProtoReflect.Descriptor instead.
|
||||
func (*Header) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_http_config_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *Header) GetKey() string {
|
||||
if x != nil {
|
||||
return x.Key
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Header) GetValue() string {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ClientConfig is the protobuf config for HTTP proxy client.
|
||||
type ClientConfig struct {
|
||||
state protoimpl.MessageState
|
||||
@@ -158,12 +213,13 @@ type ClientConfig struct {
|
||||
|
||||
// Sever is a list of HTTP server addresses.
|
||||
Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"`
|
||||
Header []*Header `protobuf:"bytes,2,rep,name=header,proto3" json:"header,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ClientConfig) Reset() {
|
||||
*x = ClientConfig{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_http_config_proto_msgTypes[2]
|
||||
mi := &file_proxy_http_config_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -176,7 +232,7 @@ func (x *ClientConfig) String() string {
|
||||
func (*ClientConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ClientConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_http_config_proto_msgTypes[2]
|
||||
mi := &file_proxy_http_config_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -189,7 +245,7 @@ func (x *ClientConfig) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use ClientConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ClientConfig) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_http_config_proto_rawDescGZIP(), []int{2}
|
||||
return file_proxy_http_config_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint {
|
||||
@@ -199,6 +255,13 @@ func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ClientConfig) GetHeader() []*Header {
|
||||
if x != nil {
|
||||
return x.Header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_proxy_http_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proxy_http_config_proto_rawDesc = []byte{
|
||||
@@ -227,17 +290,23 @@ var file_proxy_http_config_proto_rawDesc = []byte{
|
||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||
0x01, 0x22, 0x4c, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||
0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45,
|
||||
0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x42,
|
||||
0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x50, 0x01, 0x5a, 0x24, 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, 0x68, 0x74, 0x74, 0x70, 0xaa, 0x02,
|
||||
0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x48, 0x74, 0x74, 0x70,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x01, 0x22, 0x30, 0x0a, 0x06, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x22, 0x7d, 0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65,
|
||||
0x72, 0x12, 0x2f, 0x0a, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||
0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x68,
|
||||
0x74, 0x74, 0x70, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64,
|
||||
0x65, 0x72, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x50, 0x01, 0x5a, 0x24, 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, 0x68, 0x74, 0x74,
|
||||
0x70, 0xaa, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x48,
|
||||
0x74, 0x74, 0x70, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -252,22 +321,24 @@ func file_proxy_http_config_proto_rawDescGZIP() []byte {
|
||||
return file_proxy_http_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proxy_http_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_proxy_http_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||
var file_proxy_http_config_proto_goTypes = []interface{}{
|
||||
(*Account)(nil), // 0: xray.proxy.http.Account
|
||||
(*ServerConfig)(nil), // 1: xray.proxy.http.ServerConfig
|
||||
(*ClientConfig)(nil), // 2: xray.proxy.http.ClientConfig
|
||||
nil, // 3: xray.proxy.http.ServerConfig.AccountsEntry
|
||||
(*protocol.ServerEndpoint)(nil), // 4: xray.common.protocol.ServerEndpoint
|
||||
(*Header)(nil), // 2: xray.proxy.http.Header
|
||||
(*ClientConfig)(nil), // 3: xray.proxy.http.ClientConfig
|
||||
nil, // 4: xray.proxy.http.ServerConfig.AccountsEntry
|
||||
(*protocol.ServerEndpoint)(nil), // 5: xray.common.protocol.ServerEndpoint
|
||||
}
|
||||
var file_proxy_http_config_proto_depIdxs = []int32{
|
||||
3, // 0: xray.proxy.http.ServerConfig.accounts:type_name -> xray.proxy.http.ServerConfig.AccountsEntry
|
||||
4, // 1: xray.proxy.http.ClientConfig.server:type_name -> xray.common.protocol.ServerEndpoint
|
||||
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
|
||||
4, // 0: xray.proxy.http.ServerConfig.accounts:type_name -> xray.proxy.http.ServerConfig.AccountsEntry
|
||||
5, // 1: xray.proxy.http.ClientConfig.server:type_name -> xray.common.protocol.ServerEndpoint
|
||||
2, // 2: xray.proxy.http.ClientConfig.header:type_name -> xray.proxy.http.Header
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proxy_http_config_proto_init() }
|
||||
@@ -301,6 +372,18 @@ func file_proxy_http_config_proto_init() {
|
||||
}
|
||||
}
|
||||
file_proxy_http_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Header); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proxy_http_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ClientConfig); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
@@ -319,7 +402,7 @@ func file_proxy_http_config_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proxy_http_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumMessages: 5,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
@@ -21,8 +21,14 @@ message ServerConfig {
|
||||
uint32 user_level = 4;
|
||||
}
|
||||
|
||||
message Header {
|
||||
string key = 1;
|
||||
string value = 2;
|
||||
}
|
||||
|
||||
// ClientConfig is the protobuf config for HTTP proxy client.
|
||||
message ClientConfig {
|
||||
// Sever is a list of HTTP server addresses.
|
||||
repeated xray.common.protocol.ServerEndpoint server = 1;
|
||||
repeated Header header = 2;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/loopback/config.proto
|
||||
|
||||
package loopback
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/mtproto/config.proto
|
||||
|
||||
package mtproto
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/shadowsocks/config.proto
|
||||
|
||||
package shadowsocks
|
||||
|
29
proxy/shadowsocks_2022/config.go
Normal file
29
proxy/shadowsocks_2022/config.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package shadowsocks_2022
|
||||
|
||||
import (
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
)
|
||||
|
||||
// MemoryAccount is an account type converted from Account.
|
||||
type MemoryAccount struct {
|
||||
Key string
|
||||
Email string
|
||||
Level int32
|
||||
}
|
||||
|
||||
// AsAccount implements protocol.AsAccount.
|
||||
func (u *User) AsAccount() (protocol.Account, error) {
|
||||
return &MemoryAccount{
|
||||
Key: u.GetKey(),
|
||||
Email: u.GetEmail(),
|
||||
Level: u.GetLevel(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Equals implements protocol.Account.Equals().
|
||||
func (a *MemoryAccount) Equals(another protocol.Account) bool {
|
||||
if account, ok := another.(*MemoryAccount); ok {
|
||||
return a.Key == account.Key
|
||||
}
|
||||
return false
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/shadowsocks_2022/config.proto
|
||||
|
||||
package shadowsocks_2022
|
||||
|
@@ -17,6 +17,7 @@ import (
|
||||
"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/features/routing"
|
||||
"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)
|
||||
|
||||
if network == net.Network_TCP {
|
||||
return returnError(i.service.NewConnection(ctx, connection, metadata))
|
||||
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
|
||||
} else {
|
||||
reader := buf.NewReader(connection)
|
||||
pc := &natPacketConn{connection}
|
||||
@@ -81,7 +82,7 @@ func (i *Inbound) Process(ctx context.Context, network net.Network, connection s
|
||||
mb, err := reader.ReadMultiBuffer()
|
||||
if err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return returnError(err)
|
||||
return singbridge.ReturnError(err)
|
||||
}
|
||||
for _, buffer := range mb {
|
||||
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))
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
outConn := &pipeConnWrapper{
|
||||
&buf.BufferedReader{Reader: link.Reader},
|
||||
link.Writer,
|
||||
conn,
|
||||
}
|
||||
return bufio.CopyConn(ctx, conn, outConn)
|
||||
return singbridge.CopyConn(ctx, nil, link, conn)
|
||||
}
|
||||
|
||||
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))
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-shadowsocks/shadowaead_2022"
|
||||
C "github.com/sagernet/sing/common"
|
||||
@@ -19,6 +21,7 @@ import (
|
||||
"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/common/uuid"
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
@@ -31,6 +34,7 @@ func init() {
|
||||
}
|
||||
|
||||
type MultiUserInbound struct {
|
||||
sync.Mutex
|
||||
networks []net.Network
|
||||
users []*User
|
||||
service *shadowaead_2022.MultiService[int]
|
||||
@@ -78,6 +82,72 @@ func NewMultiServer(ctx context.Context, config *MultiUserServerConfig) (*MultiU
|
||||
return inbound, nil
|
||||
}
|
||||
|
||||
// AddUser implements proxy.UserManager.AddUser().
|
||||
func (i *MultiUserInbound) AddUser(ctx context.Context, u *protocol.MemoryUser) error {
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
account := u.Account.(*MemoryAccount)
|
||||
if account.Email != "" {
|
||||
for idx := range i.users {
|
||||
if i.users[idx].Email == account.Email {
|
||||
return newError("User ", account.Email, " already exists.")
|
||||
}
|
||||
}
|
||||
}
|
||||
i.users = append(i.users, &User{
|
||||
Key: account.Key,
|
||||
Email: account.Email,
|
||||
Level: account.Level,
|
||||
})
|
||||
|
||||
// sync to multi service
|
||||
// Considering implements shadowsocks2022 in xray-core may have better performance.
|
||||
i.service.UpdateUsersWithPasswords(
|
||||
C.MapIndexed(i.users, func(index int, it *User) int { return index }),
|
||||
C.Map(i.users, func(it *User) string { return it.Key }),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveUser implements proxy.UserManager.RemoveUser().
|
||||
func (i *MultiUserInbound) RemoveUser(ctx context.Context, email string) error {
|
||||
if email == "" {
|
||||
return newError("Email must not be empty.")
|
||||
}
|
||||
|
||||
i.Lock()
|
||||
defer i.Unlock()
|
||||
|
||||
idx := -1
|
||||
for ii, u := range i.users {
|
||||
if strings.EqualFold(u.Email, email) {
|
||||
idx = ii
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if idx == -1 {
|
||||
return newError("User ", email, " not found.")
|
||||
}
|
||||
|
||||
ulen := len(i.users)
|
||||
|
||||
i.users[idx] = i.users[ulen-1]
|
||||
i.users[ulen-1] = nil
|
||||
i.users = i.users[:ulen-1]
|
||||
|
||||
// sync to multi service
|
||||
// Considering implements shadowsocks2022 in xray-core may have better performance.
|
||||
i.service.UpdateUsersWithPasswords(
|
||||
C.MapIndexed(i.users, func(index int, it *User) int { return index }),
|
||||
C.Map(i.users, func(it *User) string { return it.Key }),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *MultiUserInbound) Network() []net.Network {
|
||||
return i.networks
|
||||
}
|
||||
@@ -93,7 +163,7 @@ func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, con
|
||||
ctx = session.ContextWithDispatcher(ctx, dispatcher)
|
||||
|
||||
if network == net.Network_TCP {
|
||||
return returnError(i.service.NewConnection(ctx, connection, metadata))
|
||||
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
|
||||
} else {
|
||||
reader := buf.NewReader(connection)
|
||||
pc := &natPacketConn{connection}
|
||||
@@ -101,7 +171,7 @@ func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, con
|
||||
mb, err := reader.ReadMultiBuffer()
|
||||
if err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return returnError(err)
|
||||
return singbridge.ReturnError(err)
|
||||
}
|
||||
for _, buffer := range mb {
|
||||
packet := B.As(buffer.Bytes()).ToOwned()
|
||||
@@ -133,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))
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
outConn := &pipeConnWrapper{
|
||||
&buf.BufferedReader{Reader: link.Reader},
|
||||
link.Writer,
|
||||
conn,
|
||||
}
|
||||
return bufio.CopyConn(ctx, conn, outConn)
|
||||
return singbridge.CopyConn(ctx, conn, link, conn)
|
||||
}
|
||||
|
||||
func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
|
||||
@@ -161,7 +226,7 @@ func (i *MultiUserInbound) NewPacketConnection(ctx context.Context, conn N.Packe
|
||||
})
|
||||
newError("tunnelling request to udp:", metadata.Destination).WriteToLog(session.ExportIDToError(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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@@ -19,6 +19,7 @@ import (
|
||||
"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/common/uuid"
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"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.Map(config.Destinations, func(it *RelayDestination) string { return it.Key }),
|
||||
C.Map(config.Destinations, func(it *RelayDestination) M.Socksaddr {
|
||||
return toSocksaddr(net.Destination{
|
||||
return singbridge.ToSocksaddr(net.Destination{
|
||||
Address: it.Address.AsAddress(),
|
||||
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)
|
||||
|
||||
if network == net.Network_TCP {
|
||||
return returnError(i.service.NewConnection(ctx, connection, metadata))
|
||||
return singbridge.ReturnError(i.service.NewConnection(ctx, connection, metadata))
|
||||
} else {
|
||||
reader := buf.NewReader(connection)
|
||||
pc := &natPacketConn{connection}
|
||||
@@ -102,7 +103,7 @@ func (i *RelayInbound) Process(ctx context.Context, network net.Network, connect
|
||||
mb, err := reader.ReadMultiBuffer()
|
||||
if err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return returnError(err)
|
||||
return singbridge.ReturnError(err)
|
||||
}
|
||||
for _, buffer := range mb {
|
||||
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))
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
outConn := &pipeConnWrapper{
|
||||
&buf.BufferedReader{Reader: link.Reader},
|
||||
link.Writer,
|
||||
conn,
|
||||
}
|
||||
return bufio.CopyConn(ctx, conn, outConn)
|
||||
return singbridge.CopyConn(ctx, nil, link, conn)
|
||||
}
|
||||
|
||||
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))
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@@ -2,7 +2,6 @@ package shadowsocks_2022
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"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"
|
||||
)
|
||||
@@ -88,7 +88,7 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
|
||||
}
|
||||
|
||||
if network == net.Network_TCP {
|
||||
serverConn := o.method.DialEarlyConn(connection, toSocksaddr(destination))
|
||||
serverConn := o.method.DialEarlyConn(connection, singbridge.ToSocksaddr(destination))
|
||||
var handshake bool
|
||||
if timeoutReader, isTimeoutReader := link.Reader.(buf.TimeoutReader); isTimeoutReader {
|
||||
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)
|
||||
}
|
||||
}
|
||||
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))
|
||||
return singbridge.CopyConn(ctx, inboundConn, link, serverConn)
|
||||
} else {
|
||||
var packetConn N.PacketConn
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
B "github.com/sagernet/sing/common/buf"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"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
|
||||
|
||||
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 {
|
||||
buf.Reader
|
||||
buf.Writer
|
||||
@@ -100,7 +33,7 @@ func (w *packetConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
|
||||
destination = w.Dest
|
||||
}
|
||||
bb.Release()
|
||||
return toSocksaddr(destination), nil
|
||||
return singbridge.ToSocksaddr(destination), nil
|
||||
}
|
||||
}
|
||||
mb, err := w.ReadMultiBuffer()
|
||||
@@ -120,14 +53,14 @@ func (w *packetConnWrapper) ReadPacket(buffer *B.Buffer) (M.Socksaddr, error) {
|
||||
destination = w.Dest
|
||||
}
|
||||
bb.Release()
|
||||
return toSocksaddr(destination), nil
|
||||
return singbridge.ToSocksaddr(destination), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (w *packetConnWrapper) WritePacket(buffer *B.Buffer, destination M.Socksaddr) error {
|
||||
vBuf := buf.New()
|
||||
vBuf.Write(buffer.Bytes())
|
||||
endpoint := toDestination(destination, net.Network_UDP)
|
||||
endpoint := singbridge.ToDestination(destination, net.Network_UDP)
|
||||
vBuf.UDP = &endpoint
|
||||
return w.Writer.WriteMultiBuffer(buf.MultiBuffer{vBuf})
|
||||
}
|
||||
@@ -136,10 +69,3 @@ func (w *packetConnWrapper) Close() error {
|
||||
buf.ReleaseMulti(w.cached)
|
||||
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,
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/socks/config.proto
|
||||
|
||||
package socks
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/trojan/config.proto
|
||||
|
||||
package trojan
|
||||
|
@@ -24,6 +24,7 @@ import (
|
||||
"github.com/xtls/xray-core/features/policy"
|
||||
"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/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"github.com/xtls/xray-core/transport/internet/udp"
|
||||
@@ -155,9 +156,8 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
|
||||
return newError("unable to set read deadline").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
first := buf.New()
|
||||
defer first.Release()
|
||||
|
||||
first := buf.FromBytes(make([]byte, buf.Size))
|
||||
first.Clear()
|
||||
firstLen, err := first.ReadFrom(conn)
|
||||
if err != nil {
|
||||
return newError("failed to read first request").Base(err)
|
||||
@@ -412,6 +412,12 @@ func (s *Server) fallback(ctx context.Context, sid errors.ExportOption, err erro
|
||||
alpn = cs.NegotiatedProtocol
|
||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
||||
} else if realityConn, ok := iConn.(*reality.Conn); ok {
|
||||
cs := realityConn.ConnectionState()
|
||||
name = cs.ServerName
|
||||
alpn = cs.NegotiatedProtocol
|
||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
||||
}
|
||||
name = strings.ToLower(name)
|
||||
alpn = strings.ToLower(alpn)
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/vless/account.proto
|
||||
|
||||
package vless
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/vless/encoding/addons.proto
|
||||
|
||||
package encoding
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"io"
|
||||
"math/big"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -30,10 +31,12 @@ const (
|
||||
Version = byte(0)
|
||||
)
|
||||
|
||||
var tls13SupportedVersions = []byte{0x00, 0x2b, 0x00, 0x02, 0x03, 0x04}
|
||||
var tlsClientHandShakeStart = []byte{0x16, 0x03}
|
||||
var tlsServerHandShakeStart = []byte{0x16, 0x03, 0x03}
|
||||
var tlsApplicationDataStart = []byte{0x17, 0x03, 0x03}
|
||||
var (
|
||||
tls13SupportedVersions = []byte{0x00, 0x2b, 0x00, 0x02, 0x03, 0x04}
|
||||
tlsClientHandShakeStart = []byte{0x16, 0x03}
|
||||
tlsServerHandShakeStart = []byte{0x16, 0x03, 0x03}
|
||||
tlsApplicationDataStart = []byte{0x17, 0x03, 0x03}
|
||||
)
|
||||
|
||||
var addrParser = protocol.NewAddressParser(
|
||||
protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4),
|
||||
@@ -246,7 +249,11 @@ func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, c
|
||||
}
|
||||
|
||||
// XtlsRead filter and read xtls protocol
|
||||
func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn, counter stats.Counter, ctx context.Context, userUUID []byte, numberOfPacketToFilter *int, isTLS13 *bool, isTLS12 *bool, isTLS *bool) error {
|
||||
func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn,
|
||||
input *bytes.Reader, rawInput *bytes.Buffer,
|
||||
counter stats.Counter, ctx context.Context, userUUID []byte, numberOfPacketToFilter *int, enableXtls *bool,
|
||||
isTLS12orAbove *bool, isTLS *bool, cipher *uint16, remainingServerHello *int32,
|
||||
) error {
|
||||
err := func() error {
|
||||
var ct stats.Counter
|
||||
filterUUID := true
|
||||
@@ -257,8 +264,8 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
||||
for {
|
||||
if shouldSwitchToDirectCopy {
|
||||
shouldSwitchToDirectCopy = false
|
||||
if runtime.GOOS == "linux" || runtime.GOOS == "android" {
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil {
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
|
||||
if _, ok := inbound.User.Account.(*vless.MemoryAccount); inbound.User.Account == nil || ok {
|
||||
iConn := inbound.Conn
|
||||
statConn, ok := iConn.(*stat.CounterConnection)
|
||||
if ok {
|
||||
@@ -278,11 +285,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
||||
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, rawConn, nil)
|
||||
@@ -299,13 +302,24 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
||||
} else if currentCommand == 2 {
|
||||
filterUUID = false
|
||||
shouldSwitchToDirectCopy = true
|
||||
// XTLS Vision processes struct TLS Conn's input and rawInput
|
||||
if inputBuffer, err := buf.ReadFrom(input); err == nil {
|
||||
if !inputBuffer.IsEmpty() {
|
||||
buffer, _ = buf.MergeMulti(buffer, inputBuffer)
|
||||
}
|
||||
}
|
||||
if rawInputBuffer, err := buf.ReadFrom(rawInput); err == nil {
|
||||
if !rawInputBuffer.IsEmpty() {
|
||||
buffer, _ = buf.MergeMulti(buffer, rawInputBuffer)
|
||||
}
|
||||
}
|
||||
} else if currentCommand != 0 {
|
||||
newError("XtlsRead unknown command ", currentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
}
|
||||
}
|
||||
if *numberOfPacketToFilter > 0 {
|
||||
XtlsFilterTls13(buffer, numberOfPacketToFilter, isTLS13, isTLS12, isTLS, ctx)
|
||||
XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx)
|
||||
}
|
||||
if ct != nil {
|
||||
ct.Add(int64(buffer.Len()))
|
||||
@@ -327,7 +341,10 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater
|
||||
}
|
||||
|
||||
// XtlsWrite filter and write xtls protocol
|
||||
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter, ctx context.Context, userUUID *[]byte, numberOfPacketToFilter *int, isTLS13 *bool, isTLS12 *bool, isTLS *bool) error {
|
||||
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter,
|
||||
ctx context.Context, userUUID *[]byte, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool,
|
||||
cipher *uint16, remainingServerHello *int32,
|
||||
) error {
|
||||
err := func() error {
|
||||
var ct stats.Counter
|
||||
filterTlsApplicationData := true
|
||||
@@ -336,14 +353,15 @@ func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdate
|
||||
buffer, err := reader.ReadMultiBuffer()
|
||||
if !buffer.IsEmpty() {
|
||||
if *numberOfPacketToFilter > 0 {
|
||||
XtlsFilterTls13(buffer, numberOfPacketToFilter, isTLS13, isTLS12, isTLS, ctx)
|
||||
XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx)
|
||||
}
|
||||
if filterTlsApplicationData && *isTLS {
|
||||
buffer = ReshapeMultiBuffer(ctx, buffer)
|
||||
var xtlsSpecIndex int
|
||||
for i, b := range buffer {
|
||||
if b.Len() >= 6 && bytes.Equal(tlsApplicationDataStart, b.BytesTo(3)) {
|
||||
var command byte = 0x01
|
||||
if *isTLS13 {
|
||||
if *enableXtls {
|
||||
shouldSwitchToDirectCopy = true
|
||||
xtlsSpecIndex = i
|
||||
command = 0x02
|
||||
@@ -351,8 +369,8 @@ func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdate
|
||||
filterTlsApplicationData = false
|
||||
buffer[i] = XtlsPadding(b, command, userUUID, ctx)
|
||||
break
|
||||
} else if !*isTLS12 && !*isTLS13 && *numberOfPacketToFilter <= 0 {
|
||||
//maybe tls 1.1 or 1.0
|
||||
} else if !*isTLS12orAbove && *numberOfPacketToFilter <= 0 {
|
||||
// maybe tls 1.1 or 1.0
|
||||
filterTlsApplicationData = false
|
||||
buffer[i] = XtlsPadding(b, 0x01, userUUID, ctx)
|
||||
break
|
||||
@@ -396,59 +414,123 @@ func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdate
|
||||
return nil
|
||||
}
|
||||
|
||||
// XtlsFilterTls13 filter and recognize tls 1.3
|
||||
func XtlsFilterTls13(buffer buf.MultiBuffer, numberOfPacketToFilter *int, isTLS13 *bool, isTLS12 *bool, isTLS *bool, ctx context.Context) {
|
||||
// XtlsFilterTls filter and recognize tls 1.3 and other info
|
||||
func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool,
|
||||
cipher *uint16, remainingServerHello *int32, ctx context.Context,
|
||||
) {
|
||||
for _, b := range buffer {
|
||||
*numberOfPacketToFilter--
|
||||
if b.Len() >= 6 {
|
||||
startsBytes := b.BytesTo(6)
|
||||
if bytes.Equal(tlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == 0x02 {
|
||||
total := (int(startsBytes[3])<<8 | int(startsBytes[4])) + 5
|
||||
if b.Len() >= int32(total) {
|
||||
if bytes.Contains(b.BytesTo(int32(total)), tls13SupportedVersions) {
|
||||
*isTLS13 = true
|
||||
*isTLS = true
|
||||
newError("XtlsFilterTls13 found tls 1.3! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||
} else {
|
||||
*isTLS12 = true
|
||||
*isTLS = true
|
||||
newError("XtlsFilterTls13 found tls 1.2! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
*numberOfPacketToFilter = 0
|
||||
return
|
||||
*remainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5
|
||||
*isTLS12orAbove = true
|
||||
*isTLS = true
|
||||
if b.Len() >= 79 && *remainingServerHello >= 79 {
|
||||
sessionIdLen := int32(b.Byte(43))
|
||||
cipherSuite := b.BytesRange(43+sessionIdLen+1, 43+sessionIdLen+3)
|
||||
*cipher = uint16(cipherSuite[0])<<8 | uint16(cipherSuite[1])
|
||||
} else {
|
||||
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] == 0x01 {
|
||||
*isTLS = true
|
||||
newError("XtlsFilterTls13 found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||
newError("XtlsFilterTls found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
}
|
||||
if *remainingServerHello > 0 {
|
||||
end := *remainingServerHello
|
||||
if end > b.Len() {
|
||||
end = b.Len()
|
||||
}
|
||||
*remainingServerHello -= b.Len()
|
||||
if bytes.Contains(b.BytesTo(end), tls13SupportedVersions) {
|
||||
v, ok := Tls13CipherSuiteDic[*cipher]
|
||||
if !ok {
|
||||
v = "Old cipher: " + strconv.FormatUint(uint64(*cipher), 16)
|
||||
} else if v != "TLS_AES_128_CCM_8_SHA256" {
|
||||
*enableXtls = true
|
||||
}
|
||||
newError("XtlsFilterTls found tls 1.3! ", b.Len(), " ", v).WriteToLog(session.ExportIDToError(ctx))
|
||||
*numberOfPacketToFilter = 0
|
||||
return
|
||||
} else if *remainingServerHello <= 0 {
|
||||
newError("XtlsFilterTls found tls 1.2! ", b.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||
*numberOfPacketToFilter = 0
|
||||
return
|
||||
}
|
||||
newError("XtlsFilterTls inconclusive server hello ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
if *numberOfPacketToFilter <= 0 {
|
||||
newError("XtlsFilterTls13 stop filtering", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||
newError("XtlsFilterTls stop filtering", buffer.Len()).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ReshapeMultiBuffer prepare multi buffer for padding stucture (max 21 bytes)
|
||||
func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer {
|
||||
needReshape := false
|
||||
for _, b := range buffer {
|
||||
if b.Len() >= buf.Size-21 {
|
||||
needReshape = true
|
||||
}
|
||||
}
|
||||
if !needReshape {
|
||||
return buffer
|
||||
}
|
||||
mb2 := make(buf.MultiBuffer, 0, len(buffer))
|
||||
print := ""
|
||||
for _, b := range buffer {
|
||||
if b.Len() >= buf.Size-21 {
|
||||
index := int32(bytes.LastIndex(b.Bytes(), tlsApplicationDataStart))
|
||||
if index <= 0 {
|
||||
index = buf.Size / 2
|
||||
}
|
||||
buffer1 := buf.New()
|
||||
buffer2 := buf.New()
|
||||
buffer1.Write(b.BytesTo(index))
|
||||
buffer2.Write(b.BytesFrom(index))
|
||||
mb2 = append(mb2, buffer1, buffer2)
|
||||
print += " " + strconv.Itoa(int(buffer1.Len())) + " " + strconv.Itoa(int(buffer2.Len()))
|
||||
} else {
|
||||
newbuffer := buf.New()
|
||||
newbuffer.Write(b.Bytes())
|
||||
mb2 = append(mb2, newbuffer)
|
||||
print += " " + strconv.Itoa(int(b.Len()))
|
||||
}
|
||||
}
|
||||
buf.ReleaseMulti(buffer)
|
||||
newError("ReshapeMultiBuffer ", print).WriteToLog(session.ExportIDToError(ctx))
|
||||
return mb2
|
||||
}
|
||||
|
||||
// XtlsPadding add padding to eliminate length siganature during tls handshake
|
||||
func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, ctx context.Context) *buf.Buffer {
|
||||
var length int32 = 0
|
||||
if b.Len() < 900 {
|
||||
var contantLen int32 = 0
|
||||
var paddingLen int32 = 0
|
||||
if b != nil {
|
||||
contantLen = b.Len()
|
||||
}
|
||||
if contantLen < 900 {
|
||||
l, err := rand.Int(rand.Reader, big.NewInt(500))
|
||||
if err != nil {
|
||||
newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
length = int32(l.Int64()) + 900 - b.Len()
|
||||
paddingLen = int32(l.Int64()) + 900 - contantLen
|
||||
}
|
||||
newbuffer := buf.New()
|
||||
if userUUID != nil {
|
||||
newbuffer.Write(*userUUID)
|
||||
*userUUID = nil
|
||||
}
|
||||
newbuffer.Write([]byte{command, byte(b.Len() >> 8), byte(b.Len()), byte(length >> 8), byte(length)})
|
||||
newbuffer.Write(b.Bytes())
|
||||
newbuffer.Extend(length)
|
||||
newError("XtlsPadding ", b.Len(), " ", length, " ", command).WriteToLog(session.ExportIDToError(ctx))
|
||||
b.Release()
|
||||
b = nil
|
||||
newbuffer.Write([]byte{command, byte(contantLen >> 8), byte(contantLen), byte(paddingLen >> 8), byte(paddingLen)})
|
||||
if (b != nil) {
|
||||
newbuffer.Write(b.Bytes())
|
||||
b.Release()
|
||||
b = nil
|
||||
}
|
||||
newbuffer.Extend(paddingLen)
|
||||
newError("XtlsPadding ", contantLen, " ", paddingLen, " ", command).WriteToLog(session.ExportIDToError(ctx))
|
||||
return newbuffer
|
||||
}
|
||||
|
||||
@@ -480,7 +562,7 @@ func XtlsUnpadding(ctx context.Context, buffer buf.MultiBuffer, userUUID []byte,
|
||||
b := buffer[i]
|
||||
for posByte < b.Len() {
|
||||
if *remainingContent <= 0 && *remainingPadding <= 0 {
|
||||
if *currentCommand == 1 {
|
||||
if *currentCommand == 1 { // possible buffer after padding, no need to worry about xtls (command 2)
|
||||
len := b.Len() - posByte
|
||||
newbuffer := buf.New()
|
||||
newbuffer.Write(b.BytesRange(posByte, posByte+len))
|
||||
@@ -521,3 +603,11 @@ func XtlsUnpadding(ctx context.Context, buffer buf.MultiBuffer, userUUID []byte,
|
||||
buf.ReleaseMulti(buffer)
|
||||
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",
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/vless/inbound/config.proto
|
||||
|
||||
package inbound
|
||||
|
@@ -3,13 +3,18 @@ package inbound
|
||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
gotls "crypto/tls"
|
||||
"io"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/pires/go-proxyproto"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
@@ -21,7 +26,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/common/signal"
|
||||
"github.com/xtls/xray-core/common/task"
|
||||
core "github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/dns"
|
||||
feature_inbound "github.com/xtls/xray-core/features/inbound"
|
||||
"github.com/xtls/xray-core/features/policy"
|
||||
@@ -29,6 +34,7 @@ import (
|
||||
"github.com/xtls/xray-core/features/stats"
|
||||
"github.com/xtls/xray-core/proxy/vless"
|
||||
"github.com/xtls/xray-core/proxy/vless/encoding"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
||||
@@ -149,6 +155,19 @@ func New(ctx context.Context, config *Config, dc dns.Client) (*Handler, error) {
|
||||
return handler, nil
|
||||
}
|
||||
|
||||
func isMuxAndNotXUDP(request *protocol.RequestHeader, first *buf.Buffer) bool {
|
||||
if request.Command != protocol.RequestCommandMux {
|
||||
return false
|
||||
}
|
||||
if first.Len() < 7 {
|
||||
return true
|
||||
}
|
||||
firstBytes := first.Bytes()
|
||||
return !(firstBytes[2] == 0 && // ID high
|
||||
firstBytes[3] == 0 && // ID low
|
||||
firstBytes[6] == 2) // Network type: UDP
|
||||
}
|
||||
|
||||
// Close implements common.Closable.Close().
|
||||
func (h *Handler) Close() error {
|
||||
return errors.Combine(common.Close(h.validator))
|
||||
@@ -184,9 +203,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
return newError("unable to set read deadline").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
first := buf.New()
|
||||
defer first.Release()
|
||||
|
||||
first := buf.FromBytes(make([]byte, buf.Size))
|
||||
first.Clear()
|
||||
firstLen, _ := first.ReadFrom(connection)
|
||||
newError("firstLen = ", firstLen).AtInfo().WriteToLog(sid)
|
||||
|
||||
@@ -229,6 +247,12 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
alpn = cs.NegotiatedProtocol
|
||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
||||
} else if realityConn, ok := iConn.(*reality.Conn); ok {
|
||||
cs := realityConn.ConnectionState()
|
||||
name = cs.ServerName
|
||||
alpn = cs.NegotiatedProtocol
|
||||
newError("realName = " + name).AtInfo().WriteToLog(sid)
|
||||
newError("realAlpn = " + alpn).AtInfo().WriteToLog(sid)
|
||||
}
|
||||
name = strings.ToLower(name)
|
||||
alpn = strings.ToLower(alpn)
|
||||
@@ -441,10 +465,22 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
|
||||
var netConn net.Conn
|
||||
var rawConn syscall.RawConn
|
||||
|
||||
var input *bytes.Reader
|
||||
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 {
|
||||
case vless.XRO, vless.XRD, vless.XRV:
|
||||
if account.Flow == requestAddons.Flow {
|
||||
if accountFlow == requestAddons.Flow {
|
||||
switch request.Command {
|
||||
case protocol.RequestCommandMux:
|
||||
return newError(requestAddons.Flow + " doesn't support Mux").AtWarning()
|
||||
@@ -452,18 +488,37 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
return newError(requestAddons.Flow + " doesn't support UDP").AtWarning()
|
||||
case protocol.RequestCommandTCP:
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
var t reflect.Type
|
||||
var p uintptr
|
||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||
netConn = tlsConn.NetConn()
|
||||
if sc, ok := netConn.(syscall.Conn); ok {
|
||||
rawConn, _ = sc.SyscallConn()
|
||||
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"`).AtWarning()
|
||||
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
|
||||
@@ -481,7 +536,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
} else {
|
||||
return newError(account.ID.String() + " is not able to use " + requestAddons.Flow).AtWarning()
|
||||
}
|
||||
case "":
|
||||
case "", "none":
|
||||
if accountFlow == vless.XRV && !allowNoneFlow && (request.Command == protocol.RequestCommandTCP || isMuxAndNotXUDP(request, first)) {
|
||||
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:
|
||||
return newError("unknown request flow " + requestAddons.Flow).AtWarning()
|
||||
}
|
||||
@@ -508,9 +567,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
|
||||
serverReader := link.Reader // .(*pipe.Reader)
|
||||
serverWriter := link.Writer // .(*pipe.Writer)
|
||||
isTLS13 := false
|
||||
isTLS12 := false
|
||||
enableXtls := false
|
||||
isTLS12orAbove := false
|
||||
isTLS := false
|
||||
var cipher uint16 = 0
|
||||
var remainingServerHello int32 = -1
|
||||
numberOfPacketToFilter := 8
|
||||
|
||||
postRequest := func() error {
|
||||
@@ -526,10 +587,11 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
if statConn != nil {
|
||||
counter = statConn.ReadCounter
|
||||
}
|
||||
//TODO enable splice
|
||||
// TODO enable splice
|
||||
ctx = session.ContextWithInbound(ctx, nil)
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
err = encoding.XtlsRead(clientReader, serverWriter, timer, netConn, rawConn, counter, ctx, account.ID.Bytes(), &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS)
|
||||
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)
|
||||
}
|
||||
@@ -561,10 +623,10 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
return err1 // ...
|
||||
}
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
encoding.XtlsFilterTls13(multiBuffer, &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS, ctx)
|
||||
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello, ctx)
|
||||
if isTLS {
|
||||
multiBuffer = encoding.ReshapeMultiBuffer(ctx, multiBuffer)
|
||||
for i, b := range multiBuffer {
|
||||
|
||||
multiBuffer[i] = encoding.XtlsPadding(b, 0x00, &userUUID, ctx)
|
||||
}
|
||||
}
|
||||
@@ -583,7 +645,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
if statConn != nil {
|
||||
counter = statConn.WriteCounter
|
||||
}
|
||||
err = encoding.XtlsWrite(serverReader, clientWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS)
|
||||
err = encoding.XtlsWrite(serverReader, clientWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter,
|
||||
&enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||
} else {
|
||||
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBufer
|
||||
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/vless/outbound/config.proto
|
||||
|
||||
package outbound
|
||||
|
@@ -3,9 +3,15 @@ package outbound
|
||||
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
gotls "crypto/tls"
|
||||
"reflect"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
utls "github.com/refraction-networking/utls"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@@ -16,13 +22,14 @@ import (
|
||||
"github.com/xtls/xray-core/common/signal"
|
||||
"github.com/xtls/xray-core/common/task"
|
||||
"github.com/xtls/xray-core/common/xudp"
|
||||
core "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/stats"
|
||||
"github.com/xtls/xray-core/proxy/vless"
|
||||
"github.com/xtls/xray-core/proxy/vless/encoding"
|
||||
"github.com/xtls/xray-core/transport"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"github.com/xtls/xray-core/transport/internet/xtls"
|
||||
@@ -129,6 +136,8 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
|
||||
var netConn net.Conn
|
||||
var rawConn syscall.RawConn
|
||||
var input *bytes.Reader
|
||||
var rawInput *bytes.Buffer
|
||||
allowUDP443 := false
|
||||
switch requestAddons.Flow {
|
||||
case vless.XRO + "-udp443", vless.XRD + "-udp443", vless.XRS + "-udp443", vless.XRV + "-udp443":
|
||||
@@ -146,21 +155,32 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
requestAddons.Flow = ""
|
||||
case protocol.RequestCommandTCP:
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
var t reflect.Type
|
||||
var p uintptr
|
||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||
netConn = tlsConn.NetConn()
|
||||
if sc, ok := netConn.(syscall.Conn); ok {
|
||||
rawConn, _ = sc.SyscallConn()
|
||||
}
|
||||
t = reflect.TypeOf(tlsConn.Conn).Elem()
|
||||
p = uintptr(unsafe.Pointer(tlsConn.Conn))
|
||||
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
|
||||
netConn = utlsConn.Conn.NetConn()
|
||||
if sc, ok := netConn.(syscall.Conn); ok {
|
||||
rawConn, _ = sc.SyscallConn()
|
||||
}
|
||||
netConn = utlsConn.NetConn()
|
||||
t = reflect.TypeOf(utlsConn.Conn).Elem()
|
||||
p = uintptr(unsafe.Pointer(utlsConn.Conn))
|
||||
} else if realityConn, ok := iConn.(*reality.UConn); ok {
|
||||
netConn = realityConn.NetConn()
|
||||
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"`).AtWarning()
|
||||
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
|
||||
@@ -190,9 +210,11 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
|
||||
clientReader := link.Reader // .(*pipe.Reader)
|
||||
clientWriter := link.Writer // .(*pipe.Writer)
|
||||
isTLS13 := false
|
||||
isTLS12 := false
|
||||
enableXtls := false
|
||||
isTLS12orAbove := false
|
||||
isTLS := false
|
||||
var cipher uint16 = 0
|
||||
var remainingServerHello int32 = -1
|
||||
numberOfPacketToFilter := 8
|
||||
|
||||
if request.Command == protocol.RequestCommandUDP && h.cone && request.Port != 53 && request.Port != 443 {
|
||||
@@ -215,20 +237,33 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
serverWriter = xudp.NewPacketWriter(serverWriter, target)
|
||||
}
|
||||
userUUID := account.ID.Bytes()
|
||||
multiBuffer, err1 := clientReader.ReadMultiBuffer()
|
||||
if err1 != nil {
|
||||
return err1 // ...
|
||||
}
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
encoding.XtlsFilterTls13(multiBuffer, &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS, ctx)
|
||||
if isTLS {
|
||||
for i, b := range multiBuffer {
|
||||
multiBuffer[i] = encoding.XtlsPadding(b, 0x00, &userUUID, ctx)
|
||||
timeoutReader, ok := clientReader.(buf.TimeoutReader)
|
||||
if ok {
|
||||
multiBuffer, err1 := timeoutReader.ReadMultiBufferTimeout(time.Millisecond * 500)
|
||||
if err1 == nil {
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
encoding.XtlsFilterTls(multiBuffer, &numberOfPacketToFilter, &enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello, ctx)
|
||||
if isTLS {
|
||||
for i, b := range multiBuffer {
|
||||
multiBuffer[i] = encoding.XtlsPadding(b, 0x00, &userUUID, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := serverWriter.WriteMultiBuffer(multiBuffer); err != nil {
|
||||
return err // ...
|
||||
}
|
||||
} else if err1 != buf.ErrReadTimeout {
|
||||
return err1
|
||||
} else if requestAddons.Flow == vless.XRV {
|
||||
mb := make(buf.MultiBuffer, 1)
|
||||
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))
|
||||
if err := serverWriter.WriteMultiBuffer(mb); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := serverWriter.WriteMultiBuffer(multiBuffer); err != nil {
|
||||
return err // ...
|
||||
} else {
|
||||
newError("Reader is not timeout reader, will send out vless header separately from first payload").AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
// Flush; bufferWriter.WriteMultiBufer now is bufferWriter.writer.WriteMultiBuffer
|
||||
if err := bufferWriter.SetBuffered(false); err != nil {
|
||||
@@ -237,11 +272,21 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
|
||||
var err error
|
||||
if rawConn != nil && requestAddons.Flow == vless.XRV {
|
||||
if tlsConn, ok := iConn.(*tls.Conn); ok {
|
||||
if tlsConn.ConnectionState().Version != gotls.VersionTLS13 {
|
||||
return newError(`failed to use `+requestAddons.Flow+`, found outer tls version `, tlsConn.ConnectionState().Version).AtWarning()
|
||||
}
|
||||
} else if utlsConn, ok := iConn.(*tls.UConn); ok {
|
||||
if utlsConn.ConnectionState().Version != utls.VersionTLS13 {
|
||||
return newError(`failed to use `+requestAddons.Flow+`, found outer tls version `, utlsConn.ConnectionState().Version).AtWarning()
|
||||
}
|
||||
}
|
||||
var counter stats.Counter
|
||||
if statConn != nil {
|
||||
counter = statConn.WriteCounter
|
||||
}
|
||||
err = encoding.XtlsWrite(clientReader, serverWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS)
|
||||
err = encoding.XtlsWrite(clientReader, serverWriter, timer, netConn, counter, ctx, &userUUID, &numberOfPacketToFilter,
|
||||
&enableXtls, &isTLS12orAbove, &isTLS, &cipher, &remainingServerHello)
|
||||
} else {
|
||||
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBufer
|
||||
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
||||
@@ -277,8 +322,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
counter = statConn.ReadCounter
|
||||
}
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
err = encoding.XtlsRead(serverReader, clientWriter, timer, netConn, rawConn, counter, ctx, account.ID.Bytes(), &numberOfPacketToFilter, &isTLS13, &isTLS12, &isTLS)
|
||||
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 {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.28.1
|
||||
// protoc v3.18.0
|
||||
// protoc v3.21.12
|
||||
// source: proxy/vmess/account.proto
|
||||
|
||||
package vmess
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user