Compare commits

..

1 Commits

Author SHA1 Message Date
风扇滑翔翼
a7e12176fb Add grpc multi conn 2024-12-19 10:45:35 +00:00
146 changed files with 2325 additions and 3370 deletions

View File

@@ -1,117 +0,0 @@
name: Build and Release for Windows 7
on:
workflow_dispatch:
release:
types: [published]
push:
pull_request:
types: [opened, synchronize, reopened]
jobs:
build:
permissions:
contents: write
strategy:
matrix:
include:
# BEGIN Windows 7
- goos: windows
goarch: amd64
assetname: win7-64
- goos: windows
goarch: 386
assetname: win7-32
# END Windows 7
fail-fast: false
runs-on: ubuntu-latest
env:
GOOS: ${{ matrix.goos}}
GOARCH: ${{ matrix.goarch }}
CGO_ENABLED: 0
steps:
- name: Checkout codebase
uses: actions/checkout@v4
- name: Show workflow information
run: |
_NAME=${{ matrix.assetname }}
echo "GOOS: ${{ matrix.goos }}, GOARCH: ${{ matrix.goarch }}, RELEASE_NAME: $_NAME"
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
check-latest: true
- name: Setup patched builder
run: |
GOSDK=$(go env GOROOT)
rm -r $GOSDK/*
cd $GOSDK
curl -O -L https://github.com/XTLS/go-win7/releases/latest/download/go-for-win7-linux-amd64.zip
unzip ./go-for-win7-linux-amd64.zip -d $GOSDK
rm ./go-for-win7-linux-amd64.zip
- name: Get project dependencies
run: go mod download
- name: Build Xray
run: |
mkdir -p build_assets
COMMID=$(git describe --always --dirty)
echo 'Building Xray for Windows 7...'
go build -o build_assets/xray.exe -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Copy README.md & LICENSE
run: |
mv -f resources/* build_assets
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
- name: Create ZIP archive
if: github.event_name == 'release'
shell: bash
run: |
pushd build_assets || exit 1
touch -mt $(date +%Y01010000) *
zip -9vr ../Xray-${{ env.ASSET_NAME }}.zip .
popd || exit 1
FILE=./Xray-${{ env.ASSET_NAME }}.zip
DGST=$FILE.dgst
for METHOD in {"md5","sha1","sha256","sha512"}
do
openssl dgst -$METHOD $FILE | sed 's/([^)]*)//g' >>$DGST
done
- name: Change the name
run: |
mv build_assets Xray-${{ env.ASSET_NAME }}
- name: Upload files to Artifacts
uses: actions/upload-artifact@v4
with:
name: Xray-${{ env.ASSET_NAME }}
path: |
./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-${{ env.ASSET_NAME }}.zip*
tag: ${{ github.ref }}
file_glob: true

View File

@@ -1,15 +1,76 @@
name: Build and Release name: Build and Release
# NOTE: This Github Actions file depends on the Makefile.
# Building the correct package requires the correct binaries generated by the Makefile. To
# ensure the correct output, the Makefile must accept the appropriate input and compile the
# correct file with the correct name. If you need to modify this file, please ensure it won't
# disrupt the Makefile.
on: on:
workflow_dispatch: workflow_dispatch:
release: release:
types: [published] types: [published]
push: push:
branches:
- main
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/release.yml"
pull_request: pull_request:
types: [opened, synchronize, reopened] types: [opened, synchronize, reopened]
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/release.yml"
jobs: jobs:
prepare:
runs-on: ubuntu-latest
steps:
- name: Restore Cache
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Update Geodat
id: update
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
retry_wait_seconds: 60
max_attempts: 60
command: |
[ -d 'resources' ] || mkdir resources
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite')
for i in "${LIST[@]}"
do
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3}'))
FILE_NAME="${INFO[2]}.dat"
echo -e "Verifying HASH key..."
HASH="$(curl -sL "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
continue
else
echo -e "Downloading https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat..."
curl -L "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat" -o ./resources/${FILE_NAME}
echo -e "Verifying HASH key..."
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
echo "unhit=true" >> $GITHUB_OUTPUT
fi
done
- name: Save Cache
uses: actions/cache/save@v4
if: ${{ steps.update.outputs.unhit }}
with:
path: resources
key: xray-geodat-${{ github.sha }}-${{ github.run_number }}
build: build:
needs: prepare
permissions: permissions:
contents: write contents: write
strategy: strategy:
@@ -17,7 +78,9 @@ jobs:
# Include amd64 on all platforms. # Include amd64 on all platforms.
goos: [windows, freebsd, openbsd, linux, darwin] goos: [windows, freebsd, openbsd, linux, darwin]
goarch: [amd64, 386] goarch: [amd64, 386]
gotoolchain: [""]
patch-assetname: [""] patch-assetname: [""]
exclude: exclude:
# Exclude i386 on darwin # Exclude i386 on darwin
- goarch: 386 - goarch: 386
@@ -92,6 +155,16 @@ jobs:
goarch: arm goarch: arm
goarm: 7 goarm: 7
# END OPENBSD ARM # END OPENBSD ARM
# BEGIN Windows 7
- goos: windows
goarch: amd64
gotoolchain: 1.21.4
patch-assetname: win7-64
- goos: windows
goarch: 386
gotoolchain: 1.21.4
patch-assetname: win7-32
# END Windows 7
fail-fast: false fail-fast: false
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -114,7 +187,7 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version-file: go.mod go-version: ${{ matrix.gotoolchain || '1.23' }}
check-latest: true check-latest: true
- name: Get project dependencies - name: Get project dependencies
@@ -123,24 +196,10 @@ jobs:
- name: Build Xray - name: Build Xray
run: | run: |
mkdir -p build_assets mkdir -p build_assets
COMMID=$(git describe --always --dirty) make
if [[ ${GOOS} == 'windows' ]]; then find . -maxdepth 1 -type f -regex './\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \;
echo 'Building Xray for Windows...'
go build -o build_assets/xray.exe -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
else
echo 'Building Xray...'
go build -o build_assets/xray -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
if [[ ${GOARCH} == 'mips' || ${GOARCH} == 'mipsle' ]]; then
echo 'Building soft-float Xray for MIPS/MIPSLE 32-bit...'
GOMIPS=softfloat go build -o build_assets/xray_softfloat -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
fi
fi
- name: Restore Geodat Cache - name: Restore Cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
with: with:
path: resources path: resources

View File

@@ -1,65 +0,0 @@
name: Scheduled assets update
# NOTE: This Github Actions is required by other actions, for preparing other packaging assets in a
# routine manner, for example: GeoIP/GeoSite.
# Currently updating:
# - Geodat (GeoIP/Geosite)
on:
workflow_dispatch:
schedule:
# Update GeoData on every day (22:30 UTC)
- cron: '30 22 * * *'
push:
# Prevent triggering update request storm
paths:
- ".github/workflows/scheduled-assets-update.yml"
pull_request:
# Prevent triggering update request storm
paths:
- ".github/workflows/scheduled-assets-update.yml"
jobs:
geodat:
if: github.event.schedule == '30 22 * * *' || github.event_name == 'push'|| github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- name: Restore Geodat Cache
uses: actions/cache/restore@v4
with:
path: resources
key: xray-geodat-
- name: Update Geodat
id: update
uses: nick-fields/retry@v3
with:
timeout_minutes: 60
retry_wait_seconds: 60
max_attempts: 60
command: |
[ -d 'resources' ] || mkdir resources
LIST=('Loyalsoldier v2ray-rules-dat geoip geoip' 'Loyalsoldier v2ray-rules-dat geosite geosite')
for i in "${LIST[@]}"
do
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3,$4}'))
FILE_NAME="${INFO[3]}.dat"
echo -e "Verifying HASH key..."
HASH="$(curl -sL "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
continue
else
echo -e "Downloading https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat..."
curl -L "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat" -o ./resources/${FILE_NAME}
echo -e "Verifying HASH key..."
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
echo "unhit=true" >> $GITHUB_OUTPUT
fi
done
- name: Save Geodat Cache
uses: actions/cache/save@v4
if: ${{ steps.update.outputs.unhit }}
with:
path: resources
key: xray-geodat-${{ github.sha }}-${{ github.run_number }}

View File

@@ -2,8 +2,20 @@ name: Test
on: on:
push: push:
branches:
- main
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/*.yml"
pull_request: pull_request:
types: [opened, synchronize, reopened] types: [opened, synchronize, reopened]
paths:
- "**/*.go"
- "go.mod"
- "go.sum"
- ".github/workflows/*.yml"
jobs: jobs:
test: test:
@@ -20,9 +32,9 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version-file: go.mod go-version: '1.23'
check-latest: true check-latest: true
- name: Restore Geodat Cache - name: Restore Cache
uses: actions/cache/restore@v4 uses: actions/cache/restore@v4
with: with:
path: resources path: resources

37
Makefile Normal file
View File

@@ -0,0 +1,37 @@
NAME = xray
VERSION=$(shell git describe --always --dirty)
# NOTE: This MAKEFILE can be used to build Xray-core locally and in Automatic workflows. It is \
provided for convenience in automatic building and functions as a part of it.
# NOTE: If you need to modify this file, please be aware that:\
- This file is not the main Makefile; it only accepts environment variables and builds the \
binary.\
- Automatic building expects the correct binaries to be built by this Makefile. If you \
intend to propose a change to this Makefile, carefully review the file below and ensure \
that the change will not accidentally break the automatic building:\
.github/workflows/release.yml \
Otherwise it is recommended to contact the project maintainers.
LDFLAGS = -X github.com/xtls/xray-core/core.build=$(VERSION) -s -w -buildid=
PARAMS = -trimpath -ldflags "$(LDFLAGS)" -v
MAIN = ./main
PREFIX ?= $(shell go env GOPATH)
ifeq ($(GOOS),windows)
OUTPUT = $(NAME).exe
ADDITION = go build -o w$(NAME).exe -trimpath -ldflags "-H windowsgui $(LDFLAGS)" -v $(MAIN)
else
OUTPUT = $(NAME)
endif
ifeq ($(shell echo "$(GOARCH)" | grep -Eq "(mips|mipsle)" && echo true),true) #
ADDITION = GOMIPS=softfloat go build -o $(NAME)_softfloat -trimpath -ldflags "$(LDFLAGS)" -v $(MAIN)
endif
.PHONY: clean build
build:
go build -o $(OUTPUT) $(PARAMS) $(MAIN)
$(ADDITION)
clean:
go clean -v -i $(PWD)
rm -f xray xray.exe wxray.exe xray_softfloat

View File

@@ -6,9 +6,7 @@
## Donation & NFTs ## Donation & NFTs
- **ETH/USDT/USDC: `0xDc3Fe44F0f25D13CACb1C4896CD0D321df3146Ee`** [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633)
- **Project X NFT: [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633)**
- **REALITY NFT: [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113)**
## License ## License
@@ -24,9 +22,7 @@
[Project X Channel](https://t.me/projectXtls) [Project X Channel](https://t.me/projectXtls)
[Project VLESS](https://t.me/projectVless) (Русский) [Project VLESS](https://t.me/projectVless) (non-Chinese)
[Project XHTTP](https://t.me/projectXhttp) (Persian)
## Installation ## Installation
@@ -74,8 +70,6 @@
- [PassWall](https://github.com/xiaorouji/openwrt-passwall), [PassWall 2](https://github.com/xiaorouji/openwrt-passwall2) - [PassWall](https://github.com/xiaorouji/openwrt-passwall), [PassWall 2](https://github.com/xiaorouji/openwrt-passwall2)
- [ShadowSocksR Plus+](https://github.com/fw876/helloworld) - [ShadowSocksR Plus+](https://github.com/fw876/helloworld)
- [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray)) - [luci-app-xray](https://github.com/yichya/luci-app-xray) ([openwrt-xray](https://github.com/yichya/openwrt-xray))
- Asuswrt-Merlin
- [XRAYUI](https://github.com/DanielLavrushin/asuswrt-merlin-xrayui)
- Windows - Windows
- [v2rayN](https://github.com/2dust/v2rayN) - [v2rayN](https://github.com/2dust/v2rayN)
- [Furious](https://github.com/LorenEteval/Furious) - [Furious](https://github.com/LorenEteval/Furious)
@@ -85,7 +79,6 @@
- [X-flutter](https://github.com/XTLS/X-flutter) - [X-flutter](https://github.com/XTLS/X-flutter)
- [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray) - [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
- iOS & macOS arm64 - iOS & macOS arm64
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
- [FoXray](https://apps.apple.com/app/foxray/id6448898396) - [FoXray](https://apps.apple.com/app/foxray/id6448898396)
- [Streisand](https://apps.apple.com/app/streisand/id6450534064) - [Streisand](https://apps.apple.com/app/streisand/id6450534064)
- macOS arm64 & x64 - macOS arm64 & x64
@@ -103,7 +96,6 @@
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118) - [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
- Xray Tools - Xray Tools
- [xray-knife](https://github.com/lilendian0x00/xray-knife) - [xray-knife](https://github.com/lilendian0x00/xray-knife)
- [xray-checker](https://github.com/kutovoys/xray-checker)
- Xray Wrapper - Xray Wrapper
- [XTLS/libXray](https://github.com/XTLS/libXray) - [XTLS/libXray](https://github.com/XTLS/libXray)
- [xtlsapi](https://github.com/hiddify/xtlsapi) - [xtlsapi](https://github.com/hiddify/xtlsapi)
@@ -127,27 +119,25 @@
- [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases). - [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases).
- For third-party projects used in [Xray-core](https://github.com/XTLS/Xray-core), check your local or [the latest go.mod](https://github.com/XTLS/Xray-core/blob/main/go.mod). - For third-party projects used in [Xray-core](https://github.com/XTLS/Xray-core), check your local or [the latest go.mod](https://github.com/XTLS/Xray-core/blob/main/go.mod).
## One-line Compilation ## Compilation
### Windows (PowerShell) ### Windows (PowerShell)
```powershell ```powershell
$env:CGO_ENABLED=0 $env:CGO_ENABLED=0
go build -o xray.exe -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -v ./main go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main
``` ```
### Linux / macOS ### Linux / macOS
```bash ```bash
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-s -w -buildid=" -v ./main CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
``` ```
### Reproducible Releases ### Reproducible Releases
Make sure that you are using the same Go version, and remember to set the git commit id (7 bytes):
```bash ```bash
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=REPLACE -s -w -buildid=" -v ./main make
``` ```
## Stargazers over time ## Stargazers over time

View File

@@ -106,7 +106,7 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
d := new(DefaultDispatcher) d := new(DefaultDispatcher)
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error { if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) { core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
d.fdns = fdns d.fdns = fdns
}) })
return d.Init(config.(*Config), om, router, pm, sm, dc) return d.Init(config.(*Config), om, router, pm, sm, dc)

View File

@@ -35,7 +35,7 @@ type Client struct {
var errExpectedIPNonMatch = errors.New("expectIPs not match") var errExpectedIPNonMatch = errors.New("expectIPs not match")
// NewServer creates a name server object according to the network destination url. // NewServer creates a name server object according to the network destination url.
func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (Server, error) { func NewServer(dest net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (Server, error) {
if address := dest.Address; address.Family().IsDomain() { if address := dest.Address; address.Family().IsDomain() {
u, err := url.Parse(address.Domain()) u, err := url.Parse(address.Domain())
if err != nil { if err != nil {
@@ -43,15 +43,11 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
} }
switch { switch {
case strings.EqualFold(u.String(), "localhost"): case strings.EqualFold(u.String(), "localhost"):
return NewLocalNameServer(queryStrategy), nil return NewLocalNameServer(), nil
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode
return NewDoHNameServer(u, queryStrategy, dispatcher, false), nil return NewDoHNameServer(u, dispatcher, queryStrategy)
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode
return NewDoHNameServer(u, queryStrategy, dispatcher, true), nil return NewDoHLocalNameServer(u, queryStrategy), nil
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
return NewDoHNameServer(u, queryStrategy, nil, false), nil
case strings.EqualFold(u.Scheme, "h2c+local"): // DNS-over-HTTPS h2c Local mode
return NewDoHNameServer(u, queryStrategy, nil, true), nil
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
return NewQUICNameServer(u, queryStrategy) return NewQUICNameServer(u, queryStrategy)
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
@@ -59,11 +55,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
return NewTCPLocalNameServer(u, queryStrategy) return NewTCPLocalNameServer(u, queryStrategy)
case strings.EqualFold(u.String(), "fakedns"): case strings.EqualFold(u.String(), "fakedns"):
var fd dns.FakeDNSEngine return NewFakeDNSServer(), nil
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
fd = fdns
})
return NewFakeDNSServer(fd), nil
} }
} }
if dest.Network == net.Network_Unknown { if dest.Network == net.Network_Unknown {
@@ -88,7 +80,7 @@ func NewClient(
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error { err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
// Create a new server for each client for now // Create a new server for each client for now
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, ns.GetQueryStrategy()) server, err := NewServer(ns.Address.AsDestination(), dispatcher, ns.GetQueryStrategy())
if err != nil { if err != nil {
return errors.New("failed to create nameserver").Base(err).AtWarning() return errors.New("failed to create nameserver").Base(err).AtWarning()
} }

View File

@@ -3,18 +3,15 @@ package dns
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/tls"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
"strings"
"sync" "sync"
"sync/atomic"
"time" "time"
utls "github.com/refraction-networking/utls"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/log" "github.com/xtls/xray-core/common/log"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -27,35 +24,111 @@ import (
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet"
"golang.org/x/net/dns/dnsmessage" "golang.org/x/net/dns/dnsmessage"
"golang.org/x/net/http2"
) )
// DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format, // DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format,
// which is compatible with traditional dns over udp(RFC1035), // which is compatible with traditional dns over udp(RFC1035),
// thus most of the DOH implementation is copied from udpns.go // thus most of the DOH implementation is copied from udpns.go
type DoHNameServer struct { type DoHNameServer struct {
dispatcher routing.Dispatcher
sync.RWMutex sync.RWMutex
ips map[string]*record ips map[string]*record
pub *pubsub.Service pub *pubsub.Service
cleanup *task.Periodic cleanup *task.Periodic
reqID uint32
httpClient *http.Client httpClient *http.Client
dohURL string dohURL string
name string name string
queryStrategy QueryStrategy queryStrategy QueryStrategy
} }
// NewDoHNameServer creates DOH/DOHL client object for remote/local resolving. // NewDoHNameServer creates DOH server object for remote resolving.
func NewDoHNameServer(url *url.URL, queryStrategy QueryStrategy, dispatcher routing.Dispatcher, h2c bool) *DoHNameServer { func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (*DoHNameServer, error) {
url.Scheme = "https" errors.LogInfo(context.Background(), "DNS: created Remote DOH client for ", url.String())
mode := "DOH" s := baseDOHNameServer(url, "DOH", queryStrategy)
if dispatcher == nil {
mode = "DOHL" s.dispatcher = dispatcher
tr := &http.Transport{
MaxIdleConns: 30,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 30 * time.Second,
ForceAttemptHTTP2: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
link, err := s.dispatcher.Dispatch(toDnsContext(ctx, s.dohURL), dest)
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if err != nil {
return nil, err
}
cc := common.ChainedClosable{}
if cw, ok := link.Writer.(common.Closable); ok {
cc = append(cc, cw)
}
if cr, ok := link.Reader.(common.Closable); ok {
cc = append(cc, cr)
}
return cnc.NewConnection(
cnc.ConnectionInputMulti(link.Writer),
cnc.ConnectionOutputMulti(link.Reader),
cnc.ConnectionOnClose(cc),
), nil
},
} }
errors.LogInfo(context.Background(), "DNS: created ", mode, " client for ", url.String(), ", with h2c ", h2c) s.httpClient = &http.Client{
Timeout: time.Second * 180,
Transport: tr,
}
return s, nil
}
// NewDoHLocalNameServer creates DOH client object for local resolving
func NewDoHLocalNameServer(url *url.URL, queryStrategy QueryStrategy) *DoHNameServer {
url.Scheme = "https"
s := baseDOHNameServer(url, "DOHL", queryStrategy)
tr := &http.Transport{
IdleConnTimeout: 90 * time.Second,
ForceAttemptHTTP2: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
conn, err := internet.DialSystem(ctx, dest, nil)
log.Record(&log.AccessMessage{
From: "DNS",
To: s.dohURL,
Status: log.AccessAccepted,
Detour: "local",
})
if err != nil {
return nil, err
}
return conn, nil
},
}
s.httpClient = &http.Client{
Timeout: time.Second * 180,
Transport: tr,
}
errors.LogInfo(context.Background(), "DNS: created Local DOH client for ", url.String())
return s
}
func baseDOHNameServer(url *url.URL, prefix string, queryStrategy QueryStrategy) *DoHNameServer {
s := &DoHNameServer{ s := &DoHNameServer{
ips: make(map[string]*record), ips: make(map[string]*record),
pub: pubsub.NewService(), pub: pubsub.NewService(),
name: mode + "//" + url.Host, name: prefix + "//" + url.Host,
dohURL: url.String(), dohURL: url.String(),
queryStrategy: queryStrategy, queryStrategy: queryStrategy,
} }
@@ -63,65 +136,6 @@ func NewDoHNameServer(url *url.URL, queryStrategy QueryStrategy, dispatcher rout
Interval: time.Minute, Interval: time.Minute,
Execute: s.Cleanup, Execute: s.Cleanup,
} }
s.httpClient = &http.Client{
Transport: &http2.Transport{
IdleConnTimeout: net.ConnIdleTimeout,
ReadIdleTimeout: net.ChromeH2KeepAlivePeriod,
DialTLSContext: func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) {
dest, err := net.ParseDestination(network + ":" + addr)
if err != nil {
return nil, err
}
var conn net.Conn
if dispatcher != nil {
dnsCtx := toDnsContext(ctx, s.dohURL)
if h2c {
dnsCtx = session.ContextWithMitmAlpn11(dnsCtx, false) // for insurance
dnsCtx = session.ContextWithMitmServerName(dnsCtx, url.Hostname())
}
link, err := dispatcher.Dispatch(dnsCtx, dest)
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if err != nil {
return nil, err
}
cc := common.ChainedClosable{}
if cw, ok := link.Writer.(common.Closable); ok {
cc = append(cc, cw)
}
if cr, ok := link.Reader.(common.Closable); ok {
cc = append(cc, cr)
}
conn = cnc.NewConnection(
cnc.ConnectionInputMulti(link.Writer),
cnc.ConnectionOutputMulti(link.Reader),
cnc.ConnectionOnClose(cc),
)
} else {
log.Record(&log.AccessMessage{
From: "DNS",
To: s.dohURL,
Status: log.AccessAccepted,
Detour: "local",
})
conn, err = internet.DialSystem(ctx, dest, nil)
if err != nil {
return nil, err
}
}
if !h2c {
conn = utls.UClient(conn, &utls.Config{ServerName: url.Hostname()}, utls.HelloChrome_Auto)
if err := conn.(*utls.UConn).HandshakeContext(ctx); err != nil {
return nil, err
}
}
return conn, nil
},
},
}
return s return s
} }
@@ -208,7 +222,7 @@ func (s *DoHNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
} }
func (s *DoHNameServer) newReqID() uint16 { func (s *DoHNameServer) newReqID() uint16 {
return 0 return uint16(atomic.AddUint32(&s.reqID, 1))
} }
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
@@ -281,8 +295,6 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
req.Header.Add("Accept", "application/dns-message") req.Header.Add("Accept", "application/dns-message")
req.Header.Add("Content-Type", "application/dns-message") req.Header.Add("Content-Type", "application/dns-message")
req.Header.Set("X-Padding", strings.Repeat("X", int(crypto.RandBetween(100, 1000))))
hc := s.httpClient hc := s.httpClient
resp, err := hc.Do(req.WithContext(ctx)) resp, err := hc.Do(req.WithContext(ctx))

View File

@@ -17,7 +17,7 @@ func TestDOHNameServer(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query") url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err) common.Must(err)
s := NewDoHNameServer(url, QueryStrategy_USE_IP, nil, false) s := NewDoHLocalNameServer(url, QueryStrategy_USE_IP)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
@@ -34,7 +34,7 @@ func TestDOHNameServerWithCache(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query") url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err) common.Must(err)
s := NewDoHNameServer(url, QueryStrategy_USE_IP, nil, false) s := NewDoHLocalNameServer(url, QueryStrategy_USE_IP)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
@@ -62,7 +62,7 @@ func TestDOHNameServerWithIPv4Override(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query") url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err) common.Must(err)
s := NewDoHNameServer(url, QueryStrategy_USE_IP4, nil, false) s := NewDoHLocalNameServer(url, QueryStrategy_USE_IP4)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,
@@ -85,7 +85,7 @@ func TestDOHNameServerWithIPv6Override(t *testing.T) {
url, err := url.Parse("https+local://1.1.1.1/dns-query") url, err := url.Parse("https+local://1.1.1.1/dns-query")
common.Must(err) common.Must(err)
s := NewDoHNameServer(url, QueryStrategy_USE_IP6, nil, false) s := NewDoHLocalNameServer(url, QueryStrategy_USE_IP6)
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5) ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
IPv4Enable: true, IPv4Enable: true,

View File

@@ -5,6 +5,7 @@ import (
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/dns" "github.com/xtls/xray-core/features/dns"
) )
@@ -12,8 +13,8 @@ type FakeDNSServer struct {
fakeDNSEngine dns.FakeDNSEngine fakeDNSEngine dns.FakeDNSEngine
} }
func NewFakeDNSServer(fd dns.FakeDNSEngine) *FakeDNSServer { func NewFakeDNSServer() *FakeDNSServer {
return &FakeDNSServer{fakeDNSEngine: fd} return &FakeDNSServer{}
} }
func (FakeDNSServer) Name() string { func (FakeDNSServer) Name() string {
@@ -22,9 +23,12 @@ func (FakeDNSServer) Name() string {
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, opt dns.IPOption, _ bool) ([]net.IP, error) { func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, opt dns.IPOption, _ bool) ([]net.IP, error) {
if f.fakeDNSEngine == nil { if f.fakeDNSEngine == nil {
return nil, errors.New("Unable to locate a fake DNS Engine").AtError() if err := core.RequireFeatures(ctx, func(fd dns.FakeDNSEngine) {
f.fakeDNSEngine = fd
}); err != nil {
return nil, errors.New("Unable to locate a fake DNS Engine").Base(err).AtError()
}
} }
var ips []net.Address var ips []net.Address
if fkr0, ok := f.fakeDNSEngine.(dns.FakeDNSEngineRev0); ok { if fkr0, ok := f.fakeDNSEngine.(dns.FakeDNSEngineRev0); ok {
ips = fkr0.GetFakeIPForDomain3(domain, opt.IPv4Enable, opt.IPv6Enable) ips = fkr0.GetFakeIPForDomain3(domain, opt.IPv4Enable, opt.IPv6Enable)

View File

@@ -14,19 +14,13 @@ import (
// LocalNameServer is an wrapper over local DNS feature. // LocalNameServer is an wrapper over local DNS feature.
type LocalNameServer struct { type LocalNameServer struct {
client *localdns.Client client *localdns.Client
queryStrategy QueryStrategy
} }
const errEmptyResponse = "No address associated with hostname" const errEmptyResponse = "No address associated with hostname"
// QueryIP implements Server. // QueryIP implements Server.
func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) { func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) {
option = ResolveIpOptionOverride(s.queryStrategy, option)
if !option.IPv4Enable && !option.IPv6Enable {
return nil, dns.ErrEmptyResponse
}
start := time.Now() start := time.Now()
ips, err = s.client.LookupIP(domain, option) ips, err = s.client.LookupIP(domain, option)
@@ -48,15 +42,14 @@ func (s *LocalNameServer) Name() string {
} }
// NewLocalNameServer creates localdns server object for directly lookup in system DNS. // NewLocalNameServer creates localdns server object for directly lookup in system DNS.
func NewLocalNameServer(queryStrategy QueryStrategy) *LocalNameServer { func NewLocalNameServer() *LocalNameServer {
errors.LogInfo(context.Background(), "DNS: created localhost client") errors.LogInfo(context.Background(), "DNS: created localhost client")
return &LocalNameServer{ return &LocalNameServer{
queryStrategy: queryStrategy, client: localdns.New(),
client: localdns.New(),
} }
} }
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS. // NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
func NewLocalDNSClient() *Client { func NewLocalDNSClient() *Client {
return &Client{server: NewLocalNameServer(QueryStrategy_USE_IP)} return &Client{server: NewLocalNameServer()}
} }

View File

@@ -12,7 +12,7 @@ import (
) )
func TestLocalNameServer(t *testing.T) { func TestLocalNameServer(t *testing.T) {
s := NewLocalNameServer(QueryStrategy_USE_IP) s := NewLocalNameServer()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{ ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{
IPv4Enable: true, IPv4Enable: true,

View File

@@ -6,6 +6,7 @@ import (
"encoding/binary" "encoding/binary"
"net/url" "net/url"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/quic-go/quic-go" "github.com/quic-go/quic-go"
@@ -36,6 +37,7 @@ type QUICNameServer struct {
ips map[string]*record ips map[string]*record
pub *pubsub.Service pub *pubsub.Service
cleanup *task.Periodic cleanup *task.Periodic
reqID uint32
name string name string
destination *net.Destination destination *net.Destination
connection quic.Connection connection quic.Connection
@@ -154,7 +156,7 @@ func (s *QUICNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
} }
func (s *QUICNameServer) newReqID() uint16 { func (s *QUICNameServer) newReqID() uint16 {
return 0 return uint16(atomic.AddUint32(&s.reqID, 1))
} }
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) { func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {

View File

@@ -27,8 +27,7 @@ type Config struct {
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
// Tag of the outbound handler that handles metrics http connections. // Tag of the outbound handler that handles metrics http connections.
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"` Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
Listen string `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
} }
func (x *Config) Reset() { func (x *Config) Reset() {
@@ -68,28 +67,20 @@ func (x *Config) GetTag() string {
return "" return ""
} }
func (x *Config) GetListen() string {
if x != nil {
return x.Listen
}
return ""
}
var File_app_metrics_config_proto protoreflect.FileDescriptor var File_app_metrics_config_proto protoreflect.FileDescriptor
var file_app_metrics_config_proto_rawDesc = []byte{ var file_app_metrics_config_proto_rawDesc = []byte{
0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x63, 0x6f, 0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x63, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79,
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x32, 0x0a, 0x06, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x1a, 0x0a, 0x06,
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e,
0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79,
0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72,
0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x6f, 0x74, 0x6f, 0x33,
0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@@ -10,5 +10,4 @@ option java_multiple_files = true;
message Config { message Config {
// Tag of the outbound handler that handles metrics http connections. // Tag of the outbound handler that handles metrics http connections.
string tag = 1; string tag = 1;
string listen = 2;
} }

View File

@@ -24,15 +24,12 @@ type MetricsHandler struct {
statsManager feature_stats.Manager statsManager feature_stats.Manager
observatory extension.Observatory observatory extension.Observatory
tag string tag string
listen string
tcpListener net.Listener
} }
// NewMetricsHandler creates a new MetricsHandler based on the given config. // NewMetricsHandler creates a new MetricsHandler based on the given config.
func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHandler, error) { func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHandler, error) {
c := &MetricsHandler{ c := &MetricsHandler{
tag: config.Tag, tag: config.Tag,
listen: config.Listen,
} }
common.Must(core.RequireFeatures(ctx, func(om outbound.Manager, sm feature_stats.Manager) { common.Must(core.RequireFeatures(ctx, func(om outbound.Manager, sm feature_stats.Manager) {
c.statsManager = sm c.statsManager = sm
@@ -90,23 +87,6 @@ func (p *MetricsHandler) Type() interface{} {
} }
func (p *MetricsHandler) Start() error { func (p *MetricsHandler) Start() error {
// direct listen a port if listen is set
if p.listen != "" {
TCPlistener, err := net.Listen("tcp", p.listen)
if err != nil {
return err
}
p.tcpListener = TCPlistener
errors.LogInfo(context.Background(), "Metrics server listening on ", p.listen)
go func() {
if err := http.Serve(TCPlistener, http.DefaultServeMux); err != nil {
errors.LogErrorInner(context.Background(), err, "failed to start metrics server")
}
}()
}
listener := &OutboundListener{ listener := &OutboundListener{
buffer: make(chan net.Conn, 4), buffer: make(chan net.Conn, 4),
done: done.New(), done: done.New(),

View File

@@ -12,7 +12,6 @@ import (
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -89,15 +88,13 @@ func (o *Observer) Close() error {
func New(ctx context.Context, config *Config) (*Observer, error) { func New(ctx context.Context, config *Config) (*Observer, error) {
var outboundManager outbound.Manager var outboundManager outbound.Manager
var dispatcher routing.Dispatcher err := core.RequireFeatures(ctx, func(om outbound.Manager) {
err := core.RequireFeatures(ctx, func(om outbound.Manager, rd routing.Dispatcher) {
outboundManager = om outboundManager = om
dispatcher = rd
}) })
if err != nil { if err != nil {
return nil, errors.New("Cannot get depended features").Base(err) return nil, errors.New("Cannot get depended features").Base(err)
} }
hp := NewHealthPing(ctx, dispatcher, config.PingConfig) hp := NewHealthPing(ctx, config.PingConfig)
return &Observer{ return &Observer{
config: config, config: config,
ctx: ctx, ctx: ctx,

View File

@@ -9,7 +9,6 @@ import (
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/features/routing"
) )
// HealthPingSettings holds settings for health Checker // HealthPingSettings holds settings for health Checker
@@ -24,7 +23,6 @@ type HealthPingSettings struct {
// HealthPing is the health checker for balancers // HealthPing is the health checker for balancers
type HealthPing struct { type HealthPing struct {
ctx context.Context ctx context.Context
dispatcher routing.Dispatcher
access sync.Mutex access sync.Mutex
ticker *time.Ticker ticker *time.Ticker
tickerClose chan struct{} tickerClose chan struct{}
@@ -34,7 +32,7 @@ type HealthPing struct {
} }
// NewHealthPing creates a new HealthPing with settings // NewHealthPing creates a new HealthPing with settings
func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *HealthPingConfig) *HealthPing { func NewHealthPing(ctx context.Context, config *HealthPingConfig) *HealthPing {
settings := &HealthPingSettings{} settings := &HealthPingSettings{}
if config != nil { if config != nil {
settings = &HealthPingSettings{ settings = &HealthPingSettings{
@@ -66,10 +64,9 @@ func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *H
settings.Timeout = time.Duration(5) * time.Second settings.Timeout = time.Duration(5) * time.Second
} }
return &HealthPing{ return &HealthPing{
ctx: ctx, ctx: ctx,
dispatcher: dispatcher, Settings: settings,
Settings: settings, Results: nil,
Results: nil,
} }
} }
@@ -152,7 +149,6 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
handler := tag handler := tag
client := newPingClient( client := newPingClient(
h.ctx, h.ctx,
h.dispatcher,
h.Settings.Destination, h.Settings.Destination,
h.Settings.Timeout, h.Settings.Timeout,
handler, handler,

View File

@@ -6,7 +6,6 @@ import (
"time" "time"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/tagged" "github.com/xtls/xray-core/transport/internet/tagged"
) )
@@ -15,10 +14,10 @@ type pingClient struct {
httpClient *http.Client httpClient *http.Client
} }
func newPingClient(ctx context.Context, dispatcher routing.Dispatcher, destination string, timeout time.Duration, handler string) *pingClient { func newPingClient(ctx context.Context, destination string, timeout time.Duration, handler string) *pingClient {
return &pingClient{ return &pingClient{
destination: destination, destination: destination,
httpClient: newHTTPClient(ctx, dispatcher, handler, timeout), httpClient: newHTTPClient(ctx, handler, timeout),
} }
} }
@@ -29,7 +28,7 @@ func newDirectPingClient(destination string, timeout time.Duration) *pingClient
} }
} }
func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, handler string, timeout time.Duration) *http.Client { func newHTTPClient(ctxv context.Context, handler string, timeout time.Duration) *http.Client {
tr := &http.Transport{ tr := &http.Transport{
DisableKeepAlives: true, DisableKeepAlives: true,
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
@@ -37,7 +36,7 @@ func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, handler
if err != nil { if err != nil {
return nil, err return nil, err
} }
return tagged.Dialer(ctxv, dispatcher, dest, handler) return tagged.Dialer(ctxv, dest, handler)
}, },
} }
return &http.Client{ return &http.Client{

View File

@@ -38,7 +38,7 @@ func init() {
sv := &service{v: s} sv := &service{v: s}
err := s.RequireFeatures(func(Observatory extension.Observatory) { err := s.RequireFeatures(func(Observatory extension.Observatory) {
sv.observatory = Observatory sv.observatory = Observatory
}, false) })
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -18,7 +18,6 @@ import (
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
"github.com/xtls/xray-core/features/extension" "github.com/xtls/xray-core/features/extension"
"github.com/xtls/xray-core/features/outbound" "github.com/xtls/xray-core/features/outbound"
"github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/tagged" "github.com/xtls/xray-core/transport/internet/tagged"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@@ -32,8 +31,7 @@ type Observer struct {
finished *done.Instance finished *done.Instance
ohm outbound.Manager ohm outbound.Manager
dispatcher routing.Dispatcher
} }
func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) { func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) {
@@ -133,7 +131,7 @@ func (o *Observer) probe(outbound string) ProbeResult {
return errors.New("cannot understand address").Base(err) return errors.New("cannot understand address").Base(err)
} }
trackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest) trackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest)
conn, err := tagged.Dialer(trackedCtx, o.dispatcher, dest, outbound) conn, err := tagged.Dialer(trackedCtx, dest, outbound)
if err != nil { if err != nil {
return errors.New("cannot dial remote address ", dest).Base(err) return errors.New("cannot dial remote address ", dest).Base(err)
} }
@@ -217,19 +215,16 @@ func (o *Observer) findStatusLocationLockHolderOnly(outbound string) int {
func New(ctx context.Context, config *Config) (*Observer, error) { func New(ctx context.Context, config *Config) (*Observer, error) {
var outboundManager outbound.Manager var outboundManager outbound.Manager
var dispatcher routing.Dispatcher err := core.RequireFeatures(ctx, func(om outbound.Manager) {
err := core.RequireFeatures(ctx, func(om outbound.Manager, rd routing.Dispatcher) {
outboundManager = om outboundManager = om
dispatcher = rd
}) })
if err != nil { if err != nil {
return nil, errors.New("Cannot get depended features").Base(err) return nil, errors.New("Cannot get depended features").Base(err)
} }
return &Observer{ return &Observer{
config: config, config: config,
ctx: ctx, ctx: ctx,
ohm: outboundManager, ohm: outboundManager,
dispatcher: dispatcher,
}, nil }, nil
} }

View File

@@ -177,7 +177,7 @@ func (s *service) Register(server *grpc.Server) {
common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) { common.Must(s.v.RequireFeatures(func(im inbound.Manager, om outbound.Manager) {
hs.ihm = im hs.ihm = im
hs.ohm = om hs.ohm = om
}, false)) }))
RegisterHandlerServiceServer(server, hs) RegisterHandlerServiceServer(server, hs)
// For compatibility purposes // For compatibility purposes

View File

@@ -23,7 +23,7 @@ type DynamicInboundHandler struct {
receiverConfig *proxyman.ReceiverConfig receiverConfig *proxyman.ReceiverConfig
streamSettings *internet.MemoryStreamConfig streamSettings *internet.MemoryStreamConfig
portMutex sync.Mutex portMutex sync.Mutex
portsInUse map[net.Port]struct{} portsInUse map[net.Port]bool
workerMutex sync.RWMutex workerMutex sync.RWMutex
worker []worker worker []worker
lastRefresh time.Time lastRefresh time.Time
@@ -39,7 +39,7 @@ func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *p
tag: tag, tag: tag,
proxyConfig: proxyConfig, proxyConfig: proxyConfig,
receiverConfig: receiverConfig, receiverConfig: receiverConfig,
portsInUse: make(map[net.Port]struct{}), portsInUse: make(map[net.Port]bool),
mux: mux.NewServer(ctx), mux: mux.NewServer(ctx),
v: v, v: v,
ctx: ctx, ctx: ctx,
@@ -84,7 +84,7 @@ func (h *DynamicInboundHandler) allocatePort() net.Port {
port := net.Port(allPorts[r]) port := net.Port(allPorts[r])
_, used := h.portsInUse[port] _, used := h.portsInUse[port]
if !used { if !used {
h.portsInUse[port] = struct{}{} h.portsInUse[port] = true
return port return port
} }
} }

View File

@@ -7,7 +7,6 @@ import (
"github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/proxyman"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/serial" "github.com/xtls/xray-core/common/serial"
"github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/common/session"
"github.com/xtls/xray-core/core" "github.com/xtls/xray-core/core"
@@ -159,9 +158,6 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
Mark: streamSettings.SocketSettings.Mark, Mark: streamSettings.SocketSettings.Mark,
}) })
} }
if streamSettings != nil && streamSettings.ProtocolName == "splithttp" {
ctx = session.ContextWithAllowedNetwork(ctx, net.Network_UDP)
}
allocStrategy := receiverSettings.AllocationStrategy allocStrategy := receiverSettings.AllocationStrategy
if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always { if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always {

View File

@@ -324,7 +324,6 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
if w.sniffingConfig != nil { if w.sniffingConfig != nil {
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
} }
@@ -465,7 +464,8 @@ func (w *dsWorker) callback(conn stat.Connection) {
} }
} }
ctx = session.ContextWithInbound(ctx, &session.Inbound{ ctx = session.ContextWithInbound(ctx, &session.Inbound{
Source: net.DestinationFromAddr(conn.RemoteAddr()), // Unix have no source addr, so we use gateway as source for log.
Source: net.UnixDestination(w.address),
Gateway: net.UnixDestination(w.address), Gateway: net.UnixDestination(w.address),
Tag: w.tag, Tag: w.tag,
Conn: conn, Conn: conn,

View File

@@ -273,16 +273,7 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
outbounds := session.OutboundsFromContext(ctx) outbounds := session.OutboundsFromContext(ctx)
ob := outbounds[len(outbounds)-1] ob := outbounds[len(outbounds)-1]
if h.senderSettings.ViaCidr == "" { if h.senderSettings.ViaCidr == "" {
if h.senderSettings.Via.AsAddress().Family().IsDomain() && h.senderSettings.Via.AsAddress().Domain() == "origin" { ob.Gateway = h.senderSettings.Via.AsAddress()
if inbound := session.InboundFromContext(ctx); inbound != nil {
origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String())
if err == nil {
ob.Gateway = net.ParseAddress(origin)
}
}
} else {
ob.Gateway = h.senderSettings.Via.AsAddress()
}
} else { //Get a random address. } else { //Get a random address.
ob.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr) ob.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr)
} }

View File

@@ -31,12 +31,6 @@ type RoundRobinStrategy struct {
func (s *RoundRobinStrategy) InjectContext(ctx context.Context) { func (s *RoundRobinStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx s.ctx = ctx
if len(s.FallbackTag) > 0 {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
} }
func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string { func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string {
@@ -44,6 +38,12 @@ func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string {
} }
func (s *RoundRobinStrategy) PickOutbound(tags []string) string { func (s *RoundRobinStrategy) PickOutbound(tags []string) string {
if len(s.FallbackTag) > 0 && s.observatory == nil {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
if s.observatory != nil { if s.observatory != nil {
observeReport, err := s.observatory.GetObservation(s.ctx) observeReport, err := s.observatory.GetObservation(s.ctx)
if err == nil { if err == nil {

View File

@@ -135,7 +135,7 @@ func (s *service) Register(server *grpc.Server) {
vCoreDesc := RoutingService_ServiceDesc vCoreDesc := RoutingService_ServiceDesc
vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService" vCoreDesc.ServiceName = "v2ray.core.app.router.command.RoutingService"
server.RegisterService(&vCoreDesc, rs) server.RegisterService(&vCoreDesc, rs)
}, false)) }))
} }
func init() { func init() {

View File

@@ -58,12 +58,8 @@ type node struct {
RTTDeviationCost time.Duration RTTDeviationCost time.Duration
} }
func (s *LeastLoadStrategy) InjectContext(ctx context.Context) { func (l *LeastLoadStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx l.ctx = ctx
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observer = observatory
return nil
}))
} }
func (s *LeastLoadStrategy) PickOutbound(candidates []string) string { func (s *LeastLoadStrategy) PickOutbound(candidates []string) string {
@@ -140,8 +136,10 @@ func (s *LeastLoadStrategy) selectLeastLoad(nodes []*node) []*node {
func (s *LeastLoadStrategy) getNodes(candidates []string, maxRTT time.Duration) []*node { func (s *LeastLoadStrategy) getNodes(candidates []string, maxRTT time.Duration) []*node {
if s.observer == nil { if s.observer == nil {
errors.LogError(s.ctx, "observer is nil") common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
return make([]*node, 0) s.observer = observatory
return nil
}))
} }
observeResult, err := s.observer.GetObservation(s.ctx) observeResult, err := s.observer.GetObservation(s.ctx)
if err != nil { if err != nil {

View File

@@ -21,20 +21,19 @@ func (l *LeastPingStrategy) GetPrincipleTarget(strings []string) []string {
func (l *LeastPingStrategy) InjectContext(ctx context.Context) { func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
l.ctx = ctx l.ctx = ctx
common.Must(core.RequireFeatures(l.ctx, func(observatory extension.Observatory) error {
l.observatory = observatory
return nil
}))
} }
func (l *LeastPingStrategy) PickOutbound(strings []string) string { func (l *LeastPingStrategy) PickOutbound(strings []string) string {
if l.observatory == nil { if l.observatory == nil {
errors.LogError(l.ctx, "observer is nil") common.Must(core.RequireFeatures(l.ctx, func(observatory extension.Observatory) error {
return "" l.observatory = observatory
return nil
}))
} }
observeReport, err := l.observatory.GetObservation(l.ctx) observeReport, err := l.observatory.GetObservation(l.ctx)
if err != nil { if err != nil {
errors.LogInfoInner(l.ctx, err, "cannot get observer report") errors.LogInfoInner(l.ctx, err, "cannot get observe report")
return "" return ""
} }
outboundsList := outboundList(strings) outboundsList := outboundList(strings)

View File

@@ -20,12 +20,6 @@ type RandomStrategy struct {
func (s *RandomStrategy) InjectContext(ctx context.Context) { func (s *RandomStrategy) InjectContext(ctx context.Context) {
s.ctx = ctx s.ctx = ctx
if len(s.FallbackTag) > 0 {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
} }
func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string { func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string {
@@ -33,6 +27,12 @@ func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string {
} }
func (s *RandomStrategy) PickOutbound(candidates []string) string { func (s *RandomStrategy) PickOutbound(candidates []string) string {
if len(s.FallbackTag) > 0 && s.observatory == nil {
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
s.observatory = observatory
return nil
}))
}
if s.observatory != nil { if s.observatory != nil {
observeReport, err := s.observatory.GetObservation(s.ctx) observeReport, err := s.observatory.GetObservation(s.ctx)
if err == nil { if err == nil {

View File

@@ -60,24 +60,6 @@ func (s *statsServer) GetStatsOnline(ctx context.Context, request *GetStatsReque
}, nil }, nil
} }
func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
c := s.stats.GetOnlineMap(request.Name)
if c == nil {
return nil, errors.New(request.Name, " not found.")
}
ips := make(map[string]int64)
for ip, t := range c.IpTimeMap() {
ips[ip] = t.Unix()
}
return &GetStatsOnlineIpListResponse{
Name: request.Name,
Ips: ips,
}, nil
}
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) { func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
matcher, err := strmatcher.Substr.New(request.Pattern) matcher, err := strmatcher.Substr.New(request.Pattern)
if err != nil { if err != nil {

View File

@@ -424,59 +424,6 @@ func (x *SysStatsResponse) GetUptime() uint32 {
return 0 return 0
} }
type GetStatsOnlineIpListResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Ips map[string]int64 `protobuf:"bytes,2,rep,name=ips,proto3" json:"ips,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
}
func (x *GetStatsOnlineIpListResponse) Reset() {
*x = GetStatsOnlineIpListResponse{}
mi := &file_app_stats_command_command_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetStatsOnlineIpListResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetStatsOnlineIpListResponse) ProtoMessage() {}
func (x *GetStatsOnlineIpListResponse) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[7]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetStatsOnlineIpListResponse.ProtoReflect.Descriptor instead.
func (*GetStatsOnlineIpListResponse) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{7}
}
func (x *GetStatsOnlineIpListResponse) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *GetStatsOnlineIpListResponse) GetIps() map[string]int64 {
if x != nil {
return x.Ips
}
return nil
}
type Config struct { type Config struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
@@ -485,7 +432,7 @@ type Config struct {
func (x *Config) Reset() { func (x *Config) Reset() {
*x = Config{} *x = Config{}
mi := &file_app_stats_command_command_proto_msgTypes[8] mi := &file_app_stats_command_command_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@@ -497,7 +444,7 @@ func (x *Config) String() string {
func (*Config) ProtoMessage() {} func (*Config) ProtoMessage() {}
func (x *Config) ProtoReflect() protoreflect.Message { func (x *Config) ProtoReflect() protoreflect.Message {
mi := &file_app_stats_command_command_proto_msgTypes[8] mi := &file_app_stats_command_command_proto_msgTypes[7]
if x != nil { if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@@ -510,7 +457,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
// Deprecated: Use Config.ProtoReflect.Descriptor instead. // Deprecated: Use Config.ProtoReflect.Descriptor instead.
func (*Config) Descriptor() ([]byte, []int) { func (*Config) Descriptor() ([]byte, []int) {
return file_app_stats_command_command_proto_rawDescGZIP(), []int{8} return file_app_stats_command_command_proto_rawDescGZIP(), []int{7}
} }
var File_app_stats_command_command_proto protoreflect.FileDescriptor var File_app_stats_command_command_proto protoreflect.FileDescriptor
@@ -559,60 +506,40 @@ var file_app_stats_command_command_proto_rawDesc = []byte{
0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x50, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x50,
0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x55, 0x61, 0x75, 0x73, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x4e, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x55,
0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x70, 0x74, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x55, 0x70, 0x74,
0x69, 0x6d, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x69, 0x6d, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xa1, 0x03,
0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61,
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4f, 0x0a, 0x03, 0x69, 0x70, 0x73, 0x18,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47,
0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x70, 0x4c,
0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x49, 0x70, 0x73, 0x45,
0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x69, 0x70, 0x73, 0x1a, 0x36, 0x0a, 0x08, 0x49, 0x70, 0x73,
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, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
0x01, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0x9a, 0x04, 0x0a, 0x0c,
0x53, 0x74, 0x61, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x08,
0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61,
0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74,
0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a,
0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12,
0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61,
0x74, 0x73, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74,
0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72,
0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, 0x0a, 0x0b, 0x47,
0x65, 0x74, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61,
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73,
0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74,
0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
0x77, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e,
0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x65, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61,
0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74,
0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61,
0x1a, 0x34, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70,
0x74, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x0a, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x74, 0x61, 0x74, 0x73, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x65, 0x72, 0x79, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73,
0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x16, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x62, 0x0a,
0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x27, 0x2e, 0x78,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53,
0x79, 0x73, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
0x00, 0x42, 0x64, 0x0a, 0x1a, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50,
0x01, 0x5a, 0x2b, 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, 0x61, 0x70, 0x70,
0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02,
0x16, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x2e,
0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@@ -627,38 +554,33 @@ func file_app_stats_command_command_proto_rawDescGZIP() []byte {
return file_app_stats_command_command_proto_rawDescData return file_app_stats_command_command_proto_rawDescData
} }
var file_app_stats_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_app_stats_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_app_stats_command_command_proto_goTypes = []any{ var file_app_stats_command_command_proto_goTypes = []any{
(*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest (*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest
(*Stat)(nil), // 1: xray.app.stats.command.Stat (*Stat)(nil), // 1: xray.app.stats.command.Stat
(*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse (*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse
(*QueryStatsRequest)(nil), // 3: xray.app.stats.command.QueryStatsRequest (*QueryStatsRequest)(nil), // 3: xray.app.stats.command.QueryStatsRequest
(*QueryStatsResponse)(nil), // 4: xray.app.stats.command.QueryStatsResponse (*QueryStatsResponse)(nil), // 4: xray.app.stats.command.QueryStatsResponse
(*SysStatsRequest)(nil), // 5: xray.app.stats.command.SysStatsRequest (*SysStatsRequest)(nil), // 5: xray.app.stats.command.SysStatsRequest
(*SysStatsResponse)(nil), // 6: xray.app.stats.command.SysStatsResponse (*SysStatsResponse)(nil), // 6: xray.app.stats.command.SysStatsResponse
(*GetStatsOnlineIpListResponse)(nil), // 7: xray.app.stats.command.GetStatsOnlineIpListResponse (*Config)(nil), // 7: xray.app.stats.command.Config
(*Config)(nil), // 8: xray.app.stats.command.Config
nil, // 9: xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
} }
var file_app_stats_command_command_proto_depIdxs = []int32{ var file_app_stats_command_command_proto_depIdxs = []int32{
1, // 0: xray.app.stats.command.GetStatsResponse.stat:type_name -> xray.app.stats.command.Stat 1, // 0: xray.app.stats.command.GetStatsResponse.stat:type_name -> xray.app.stats.command.Stat
1, // 1: xray.app.stats.command.QueryStatsResponse.stat:type_name -> xray.app.stats.command.Stat 1, // 1: xray.app.stats.command.QueryStatsResponse.stat:type_name -> xray.app.stats.command.Stat
9, // 2: xray.app.stats.command.GetStatsOnlineIpListResponse.ips:type_name -> xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry 0, // 2: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest
0, // 3: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest 0, // 3: xray.app.stats.command.StatsService.GetStatsOnline:input_type -> xray.app.stats.command.GetStatsRequest
0, // 4: xray.app.stats.command.StatsService.GetStatsOnline:input_type -> xray.app.stats.command.GetStatsRequest 3, // 4: xray.app.stats.command.StatsService.QueryStats:input_type -> xray.app.stats.command.QueryStatsRequest
3, // 5: xray.app.stats.command.StatsService.QueryStats:input_type -> xray.app.stats.command.QueryStatsRequest 5, // 5: xray.app.stats.command.StatsService.GetSysStats:input_type -> xray.app.stats.command.SysStatsRequest
5, // 6: xray.app.stats.command.StatsService.GetSysStats:input_type -> xray.app.stats.command.SysStatsRequest 2, // 6: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse
0, // 7: xray.app.stats.command.StatsService.GetStatsOnlineIpList:input_type -> xray.app.stats.command.GetStatsRequest 2, // 7: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse
2, // 8: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse 4, // 8: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse
2, // 9: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse 6, // 9: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse
4, // 10: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse 6, // [6:10] is the sub-list for method output_type
6, // 11: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse 2, // [2:6] is the sub-list for method input_type
7, // 12: xray.app.stats.command.StatsService.GetStatsOnlineIpList:output_type -> xray.app.stats.command.GetStatsOnlineIpListResponse 2, // [2:2] is the sub-list for extension type_name
8, // [8:13] is the sub-list for method output_type 2, // [2:2] is the sub-list for extension extendee
3, // [3:8] is the sub-list for method input_type 0, // [0:2] is the sub-list for field type_name
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_app_stats_command_command_proto_init() } func init() { file_app_stats_command_command_proto_init() }
@@ -672,7 +594,7 @@ func file_app_stats_command_command_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_app_stats_command_command_proto_rawDesc, RawDescriptor: file_app_stats_command_command_proto_rawDesc,
NumEnums: 0, NumEnums: 0,
NumMessages: 10, NumMessages: 8,
NumExtensions: 0, NumExtensions: 0,
NumServices: 1, NumServices: 1,
}, },

View File

@@ -46,17 +46,11 @@ message SysStatsResponse {
uint32 Uptime = 10; uint32 Uptime = 10;
} }
message GetStatsOnlineIpListResponse {
string name = 1;
map<string, int64> ips = 2;
}
service StatsService { service StatsService {
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {} rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
rpc GetStatsOnline(GetStatsRequest) returns (GetStatsResponse) {} rpc GetStatsOnline(GetStatsRequest) returns (GetStatsResponse) {}
rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {} rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {}
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {} rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
rpc GetStatsOnlineIpList(GetStatsRequest) returns (GetStatsOnlineIpListResponse) {}
} }
message Config {} message Config {}

View File

@@ -19,11 +19,10 @@ import (
const _ = grpc.SupportPackageIsVersion9 const _ = grpc.SupportPackageIsVersion9
const ( const (
StatsService_GetStats_FullMethodName = "/xray.app.stats.command.StatsService/GetStats" StatsService_GetStats_FullMethodName = "/xray.app.stats.command.StatsService/GetStats"
StatsService_GetStatsOnline_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnline" StatsService_GetStatsOnline_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnline"
StatsService_QueryStats_FullMethodName = "/xray.app.stats.command.StatsService/QueryStats" StatsService_QueryStats_FullMethodName = "/xray.app.stats.command.StatsService/QueryStats"
StatsService_GetSysStats_FullMethodName = "/xray.app.stats.command.StatsService/GetSysStats" StatsService_GetSysStats_FullMethodName = "/xray.app.stats.command.StatsService/GetSysStats"
StatsService_GetStatsOnlineIpList_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnlineIpList"
) )
// StatsServiceClient is the client API for StatsService service. // StatsServiceClient is the client API for StatsService service.
@@ -34,7 +33,6 @@ type StatsServiceClient interface {
GetStatsOnline(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error) GetStatsOnline(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error)
QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, error) QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, error)
GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error) GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error)
GetStatsOnlineIpList(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsOnlineIpListResponse, error)
} }
type statsServiceClient struct { type statsServiceClient struct {
@@ -85,16 +83,6 @@ func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsReques
return out, nil return out, nil
} }
func (c *statsServiceClient) GetStatsOnlineIpList(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsOnlineIpListResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(GetStatsOnlineIpListResponse)
err := c.cc.Invoke(ctx, StatsService_GetStatsOnlineIpList_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// StatsServiceServer is the server API for StatsService service. // StatsServiceServer is the server API for StatsService service.
// All implementations must embed UnimplementedStatsServiceServer // All implementations must embed UnimplementedStatsServiceServer
// for forward compatibility. // for forward compatibility.
@@ -103,7 +91,6 @@ type StatsServiceServer interface {
GetStatsOnline(context.Context, *GetStatsRequest) (*GetStatsResponse, error) GetStatsOnline(context.Context, *GetStatsRequest) (*GetStatsResponse, error)
QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error) QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error)
GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error) GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error)
GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error)
mustEmbedUnimplementedStatsServiceServer() mustEmbedUnimplementedStatsServiceServer()
} }
@@ -126,9 +113,6 @@ func (UnimplementedStatsServiceServer) QueryStats(context.Context, *QueryStatsRe
func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error) { func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetSysStats not implemented") return nil, status.Errorf(codes.Unimplemented, "method GetSysStats not implemented")
} }
func (UnimplementedStatsServiceServer) GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetStatsOnlineIpList not implemented")
}
func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServiceServer() {} func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServiceServer() {}
func (UnimplementedStatsServiceServer) testEmbeddedByValue() {} func (UnimplementedStatsServiceServer) testEmbeddedByValue() {}
@@ -222,24 +206,6 @@ func _StatsService_GetSysStats_Handler(srv interface{}, ctx context.Context, dec
return interceptor(ctx, in, info, handler) return interceptor(ctx, in, info, handler)
} }
func _StatsService_GetStatsOnlineIpList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetStatsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(StatsServiceServer).GetStatsOnlineIpList(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: StatsService_GetStatsOnlineIpList_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(StatsServiceServer).GetStatsOnlineIpList(ctx, req.(*GetStatsRequest))
}
return interceptor(ctx, in, info, handler)
}
// StatsService_ServiceDesc is the grpc.ServiceDesc for StatsService service. // StatsService_ServiceDesc is the grpc.ServiceDesc for StatsService service.
// It's only intended for direct use with grpc.RegisterService, // It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy) // and not to be introspected or modified (even as a copy)
@@ -263,10 +229,6 @@ var StatsService_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetSysStats", MethodName: "GetSysStats",
Handler: _StatsService_GetSysStats_Handler, Handler: _StatsService_GetSysStats_Handler,
}, },
{
MethodName: "GetStatsOnlineIpList",
Handler: _StatsService_GetStatsOnlineIpList_Handler,
},
}, },
Streams: []grpc.StreamDesc{}, Streams: []grpc.StreamDesc{},
Metadata: "app/stats/command/command.proto", Metadata: "app/stats/command/command.proto",

View File

@@ -78,13 +78,3 @@ func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.
} }
return list return list
} }
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
list := c.ipList
if time.Since(c.lastCleanup) > c.cleanupPeriod {
list = c.RemoveExpiredIPs(list)
c.lastCleanup = time.Now()
}
return c.ipList
}

View File

@@ -38,7 +38,7 @@ func Error2(v interface{}, err error) error {
func envFile() (string, error) { func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" { if file := os.Getenv("GOENV"); file != "" {
if file == "off" { if file == "off" {
return "", errors.New("GOENV=off") return "", fmt.Errorf("GOENV=off")
} }
return file, nil return file, nil
} }
@@ -47,7 +47,7 @@ func envFile() (string, error) {
return "", err return "", err
} }
if dir == "" { if dir == "" {
return "", errors.New("missing user-config dir") return "", fmt.Errorf("missing user-config dir")
} }
return filepath.Join(dir, "go", "env"), nil return filepath.Join(dir, "go", "env"), nil
} }
@@ -60,7 +60,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err return "", err
} }
if file == "" { if file == "" {
return "", errors.New("missing runtime env file") return "", fmt.Errorf("missing runtime env file")
} }
var data []byte var data []byte
var runtimeEnv string var runtimeEnv string

View File

@@ -1,15 +1,2 @@
// Package crypto provides common crypto libraries for Xray. // Package crypto provides common crypto libraries for Xray.
package crypto // import "github.com/xtls/xray-core/common/crypto" package crypto // import "github.com/xtls/xray-core/common/crypto"
import (
"crypto/rand"
"math/big"
)
func RandBetween(from int64, to int64) int64 {
if from == to {
return from
}
bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from))
return from + bigInt.Int64()
}

View File

@@ -146,7 +146,7 @@ func (w *fileLogWriter) Close() error {
func CreateStdoutLogWriter() WriterCreator { func CreateStdoutLogWriter() WriterCreator {
return func() Writer { return func() Writer {
return &consoleLogWriter{ return &consoleLogWriter{
logger: log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lmicroseconds), logger: log.New(os.Stdout, "", log.Ldate|log.Ltime),
} }
} }
} }
@@ -155,7 +155,7 @@ func CreateStdoutLogWriter() WriterCreator {
func CreateStderrLogWriter() WriterCreator { func CreateStderrLogWriter() WriterCreator {
return func() Writer { return func() Writer {
return &consoleLogWriter{ return &consoleLogWriter{
logger: log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lmicroseconds), logger: log.New(os.Stderr, "", log.Ldate|log.Ltime),
} }
} }
} }
@@ -174,7 +174,7 @@ func CreateFileLogWriter(path string) (WriterCreator, error) {
} }
return &fileLogWriter{ return &fileLogWriter{
file: file, file: file,
logger: log.New(file, "", log.Ldate|log.Ltime|log.Lmicroseconds), logger: log.New(file, "", log.Ldate|log.Ltime),
} }
}, nil }, nil
} }

View File

@@ -120,7 +120,7 @@ func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.Bu
func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error { func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error {
// deep-clone outbounds because it is going to be mutated concurrently // deep-clone outbounds because it is going to be mutated concurrently
// (Target and OriginalTarget) // (Target and OriginalTarget)
ctx = session.ContextCloneOutboundsAndContent(ctx) ctx = session.ContextCloneOutbounds(ctx)
errors.LogInfo(ctx, "received request for ", meta.Target) errors.LogInfo(ctx, "received request for ", meta.Target)
{ {
msg := &log.AccessMessage{ msg := &log.AccessMessage{

View File

@@ -89,10 +89,12 @@ func UnixDestination(address Address) Destination {
// NetAddr returns the network address in this Destination in string form. // NetAddr returns the network address in this Destination in string form.
func (d Destination) NetAddr() string { func (d Destination) NetAddr() string {
addr := "" addr := ""
if d.Network == Network_TCP || d.Network == Network_UDP { if d.Address != nil {
addr = d.Address.String() + ":" + d.Port.String() if d.Network == Network_TCP || d.Network == Network_UDP {
} else if d.Network == Network_UNIX { addr = d.Address.String() + ":" + d.Port.String()
addr = d.Address.String() } else if d.Network == Network_UNIX {
addr = d.Address.String()
}
} }
return addr return addr
} }

View File

@@ -1,14 +1,2 @@
// Package net is a drop-in replacement to Golang's net package, with some more functionalities. // Package net is a drop-in replacement to Golang's net package, with some more functionalities.
package net // import "github.com/xtls/xray-core/common/net" package net // import "github.com/xtls/xray-core/common/net"
import "time"
// defines the maximum time an idle TCP session can survive in the tunnel, so
// it should be consistent across HTTP versions and with other transports.
const ConnIdleTimeout = 300 * time.Second
// consistent with quic-go
const QuicgoH3KeepAlivePeriod = 10 * time.Second
// consistent with chrome
const ChromeH2KeepAlivePeriod = 45 * time.Second

View File

@@ -76,9 +76,8 @@ type (
) )
var ( var (
ResolveTCPAddr = net.ResolveTCPAddr
ResolveUDPAddr = net.ResolveUDPAddr
ResolveUnixAddr = net.ResolveUnixAddr ResolveUnixAddr = net.ResolveUnixAddr
ResolveUDPAddr = net.ResolveUDPAddr
) )
type Resolver = net.Resolver type Resolver = net.Resolver

View File

@@ -63,7 +63,7 @@ func SniffHTTP(b []byte, c context.Context) (*SniffHeader, error) {
ShouldSniffAttr := true ShouldSniffAttr := true
// If content.Attributes have information, that means it comes from HTTP inbound PlainHTTP mode. // If content.Attributes have information, that means it comes from HTTP inbound PlainHTTP mode.
// It will set attributes, so skip it. // It will set attributes, so skip it.
if content == nil || len(content.Attributes) != 0 { if content == nil || content.AttributeLen() != 0 {
ShouldSniffAttr = false ShouldSniffAttr = false
} }
if err := beginWithHTTPMethod(b); err != nil { if err := beginWithHTTPMethod(b); err != nil {

View File

@@ -1,2 +1 @@
*.crt *.pem
*.key

View File

@@ -78,9 +78,9 @@ func printJSON(certificate *Certificate) {
func printFile(certificate *Certificate, name string) error { func printFile(certificate *Certificate, name string) error {
certPEM, keyPEM := certificate.ToPEM() certPEM, keyPEM := certificate.ToPEM()
return task.Run(context.Background(), func() error { return task.Run(context.Background(), func() error {
return writeFile(certPEM, name+".crt") return writeFile(certPEM, name+"_cert.pem")
}, func() error { }, func() error {
return writeFile(keyPEM, name+".key") return writeFile(keyPEM, name+"_key.pem")
}) })
} }

View File

@@ -58,9 +58,7 @@ func marshalSlice(v reflect.Value, ignoreNullValue bool, insertTypeInfo bool) in
} }
func isNullValue(f reflect.StructField, rv reflect.Value) bool { func isNullValue(f reflect.StructField, rv reflect.Value) bool {
if rv.Kind() == reflect.Struct { if rv.Kind() == reflect.String && rv.Len() == 0 {
return false
} else if rv.Kind() == reflect.String && rv.Len() == 0 {
return true return true
} else if !isValueKind(rv.Kind()) && rv.IsNil() { } else if !isValueKind(rv.Kind()) && rv.IsNil() {
return true return true
@@ -186,12 +184,6 @@ func marshalKnownType(v interface{}, ignoreNullValue bool, insertTypeInfo bool)
case *conf.PortList: case *conf.PortList:
cpl := v.(*conf.PortList) cpl := v.(*conf.PortList)
return serializePortList(cpl.Build()) return serializePortList(cpl.Build())
case conf.Int32Range:
i32rng := v.(conf.Int32Range)
if i32rng.Left == i32rng.Right {
return i32rng.Left, true
}
return i32rng.String(), true
case cnet.Address: case cnet.Address:
if addr := v.(cnet.Address); addr != nil { if addr := v.(cnet.Address); addr != nil {
return addr.String(), true return addr.String(), true

View File

@@ -116,129 +116,100 @@ func TestMarshalConfigJson(t *testing.T) {
"system", "system",
"inboundDownlink", "inboundDownlink",
"outboundUplink", "outboundUplink",
"XHTTP_IN",
"\"host\": \"bing.com\"",
"scMaxEachPostBytes",
"\"from\": 100",
"\"to\": 1000",
"\"from\": 1000000",
"\"to\": 1000000",
} }
for _, kw := range keywords { for _, kw := range keywords {
if !strings.Contains(tc, kw) { if !strings.Contains(tc, kw) {
t.Log("config.json:", tc) t.Error("marshaled config error")
t.Error("keyword not found:", kw)
break
} }
} }
} }
func getConfig() string { func getConfig() string {
return `{ return `{
"log": { "log": {
"loglevel": "debug" "loglevel": "debug"
}, },
"stats": {}, "stats": {},
"policy": { "policy": {
"levels": { "levels": {
"0": { "0": {
"statsUserUplink": true, "statsUserUplink": true,
"statsUserDownlink": true "statsUserDownlink": true
} }
}, },
"system": { "system": {
"statsInboundUplink": true, "statsInboundUplink": true,
"statsInboundDownlink": true, "statsInboundDownlink": true,
"statsOutboundUplink": true, "statsOutboundUplink": true,
"statsOutboundDownlink": true "statsOutboundDownlink": true
} }
}, },
"inbounds": [ "inbounds": [
{ {
"tag": "agentin", "tag": "agentin",
"protocol": "http", "protocol": "http",
"port": 18080, "port": 8080,
"listen": "127.0.0.1", "listen": "127.0.0.1",
"settings": {} "settings": {}
}, },
{ {
"listen": "127.0.0.1", "listen": "127.0.0.1",
"port": 10085, "port": 10085,
"protocol": "dokodemo-door", "protocol": "dokodemo-door",
"settings": { "settings": {
"address": "127.0.0.1" "address": "127.0.0.1"
}, },
"tag": "api-in" "tag": "api-in"
} }
], ],
"api": { "api": {
"tag": "api", "tag": "api",
"services": [ "services": [
"HandlerService", "HandlerService",
"StatsService" "StatsService"
] ]
}, },
"routing": { "routing": {
"rules": [ "rules": [
{ {
"inboundTag": [ "inboundTag": [
"api-in" "api-in"
], ],
"outboundTag": "api", "outboundTag": "api",
"type": "field" "type": "field"
} }
], ],
"domainStrategy": "AsIs" "domainStrategy": "AsIs"
}, },
"outbounds": [ "outbounds": [
{ {
"protocol": "vless", "protocol": "vless",
"settings": { "settings": {
"vnext": [ "vnext": [
{ {
"address": "1.2.3.4", "address": "1.2.3.4",
"port": 1234, "port": 1234,
"users": [ "users": [
{ {
"id": "4784f9b8-a879-4fec-9718-ebddefa47750", "id": "4784f9b8-a879-4fec-9718-ebddefa47750",
"encryption": "none" "encryption": "none"
} }
] ]
} }
] ]
}, },
"tag": "XHTTP_IN", "tag": "agentout",
"streamSettings": { "streamSettings": {
"network": "xhttp", "network": "ws",
"xhttpSettings": { "security": "none",
"host": "bing.com", "wsSettings": {
"path": "/xhttp_client_upload", "path": "/?ed=2048",
"mode": "auto", "headers": {
"extra": { "Host": "bing.com"
"noSSEHeader": false, }
"scMaxEachPostBytes": 1000000, }
"scMaxBufferedPosts": 30, }
"xPaddingBytes": "100-1000" }
} ]
}, }`
"sockopt": {
"tcpFastOpen": true,
"acceptProxyProtocol": false,
"tcpcongestion": "bbr",
"tcpMptcp": true
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
],
"metadataOnly": false,
"routeOnly": true
}
}
]
}`
} }

View File

@@ -23,8 +23,6 @@ const (
timeoutOnlyKey ctx.SessionKey = 8 timeoutOnlyKey ctx.SessionKey = 8
allowedNetworkKey ctx.SessionKey = 9 allowedNetworkKey ctx.SessionKey = 9
handlerSessionKey ctx.SessionKey = 10 handlerSessionKey ctx.SessionKey = 10
mitmAlpn11Key ctx.SessionKey = 11
mitmServerNameKey ctx.SessionKey = 12
) )
func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context { func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
@@ -42,7 +40,7 @@ func ContextWithOutbounds(ctx context.Context, outbounds []*Outbound) context.Co
return context.WithValue(ctx, outboundSessionKey, outbounds) return context.WithValue(ctx, outboundSessionKey, outbounds)
} }
func ContextCloneOutboundsAndContent(ctx context.Context) context.Context { func ContextCloneOutbounds(ctx context.Context) context.Context {
outbounds := OutboundsFromContext(ctx) outbounds := OutboundsFromContext(ctx)
newOutbounds := make([]*Outbound, len(outbounds)) newOutbounds := make([]*Outbound, len(outbounds))
for i, ob := range outbounds { for i, ob := range outbounds {
@@ -55,15 +53,7 @@ func ContextCloneOutboundsAndContent(ctx context.Context) context.Context {
newOutbounds[i] = &v newOutbounds[i] = &v
} }
content := ContentFromContext(ctx) return ContextWithOutbounds(ctx, newOutbounds)
newContent := Content{}
if content != nil {
newContent = *content
if content.Attributes != nil {
panic("content.Attributes != nil")
}
}
return ContextWithContent(ContextWithOutbounds(ctx, newOutbounds), &newContent)
} }
func OutboundsFromContext(ctx context.Context) []*Outbound { func OutboundsFromContext(ctx context.Context) []*Outbound {
@@ -172,25 +162,3 @@ func AllowedNetworkFromContext(ctx context.Context) net.Network {
} }
return net.Network_Unknown return net.Network_Unknown
} }
func ContextWithMitmAlpn11(ctx context.Context, alpn11 bool) context.Context {
return context.WithValue(ctx, mitmAlpn11Key, alpn11)
}
func MitmAlpn11FromContext(ctx context.Context) bool {
if val, ok := ctx.Value(mitmAlpn11Key).(bool); ok {
return val
}
return false
}
func ContextWithMitmServerName(ctx context.Context, serverName string) context.Context {
return context.WithValue(ctx, mitmServerNameKey, serverName)
}
func MitmServerNameFromContext(ctx context.Context) string {
if val, ok := ctx.Value(mitmServerNameKey).(string); ok {
return val
}
return ""
}

View File

@@ -4,6 +4,7 @@ package session // import "github.com/xtls/xray-core/common/session"
import ( import (
"context" "context"
"math/rand" "math/rand"
"sync"
c "github.com/xtls/xray-core/common/ctx" c "github.com/xtls/xray-core/common/ctx"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -74,8 +75,8 @@ type Outbound struct {
// SniffingRequest controls the behavior of content sniffing. // SniffingRequest controls the behavior of content sniffing.
type SniffingRequest struct { type SniffingRequest struct {
ExcludeForDomain []string // read-only once set ExcludeForDomain []string
OverrideDestinationForProtocol []string // read-only once set OverrideDestinationForProtocol []string
Enabled bool Enabled bool
MetadataOnly bool MetadataOnly bool
RouteOnly bool RouteOnly bool
@@ -91,6 +92,10 @@ type Content struct {
Attributes map[string]string Attributes map[string]string
SkipDNSResolve bool SkipDNSResolve bool
mu sync.Mutex
isLocked bool
} }
// Sockopt is the settings for socket connection. // Sockopt is the settings for socket connection.
@@ -99,8 +104,22 @@ type Sockopt struct {
Mark int32 Mark int32
} }
// Some how when using mux, there will be a same ctx between different requests
// This will cause problem as it's designed for single request, like concurrent map writes
// Add a Mutex as a temp solution
// SetAttribute attaches additional string attributes to content. // SetAttribute attaches additional string attributes to content.
func (c *Content) SetAttribute(name string, value string) { func (c *Content) SetAttribute(name string, value string) {
if c.isLocked {
errors.LogError(context.Background(), "Multiple goroutines are tring to access one routing content, tring to write ", name, ":", value)
}
c.mu.Lock()
c.isLocked = true
defer func() {
c.isLocked = false
c.mu.Unlock()
}()
if c.Attributes == nil { if c.Attributes == nil {
c.Attributes = make(map[string]string) c.Attributes = make(map[string]string)
} }
@@ -109,8 +128,24 @@ func (c *Content) SetAttribute(name string, value string) {
// Attribute retrieves additional string attributes from content. // Attribute retrieves additional string attributes from content.
func (c *Content) Attribute(name string) string { func (c *Content) Attribute(name string) string {
c.mu.Lock()
c.isLocked = true
defer func() {
c.isLocked = false
c.mu.Unlock()
}()
if c.Attributes == nil { if c.Attributes == nil {
return "" return ""
} }
return c.Attributes[name] return c.Attributes[name]
} }
func (c *Content) AttributeLen() int {
c.mu.Lock()
c.isLocked = true
defer func() {
c.isLocked = false
c.mu.Unlock()
}()
return len(c.Attributes)
}

View File

@@ -2,7 +2,6 @@ package core
import ( import (
"io" "io"
"slices"
"strings" "strings"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -65,11 +64,14 @@ func GetMergedConfig(args cmdarg.Arg) (string, error) {
supported := []string{"json", "yaml", "toml"} supported := []string{"json", "yaml", "toml"}
for _, file := range args { for _, file := range args {
format := getFormat(file) format := getFormat(file)
if slices.Contains(supported, format) { for _, s := range supported {
files = append(files, &ConfigSource{ if s == format {
Name: file, files = append(files, &ConfigSource{
Format: format, Name: file,
}) Format: format,
})
break
}
} }
} }
return ConfigMergedFormFiles(files) return ConfigMergedFormFiles(files)

View File

@@ -17,9 +17,9 @@ import (
) )
var ( var (
Version_x byte = 25 Version_x byte = 24
Version_y byte = 3 Version_y byte = 11
Version_z byte = 6 Version_z byte = 30
) )
var ( var (

View File

@@ -44,13 +44,22 @@ func getFeature(allFeatures []features.Feature, t reflect.Type) features.Feature
return nil return nil
} }
func (r *resolution) callbackResolution(allFeatures []features.Feature) error { func (r *resolution) resolve(allFeatures []features.Feature) (bool, error) {
var fs []features.Feature
for _, d := range r.deps {
f := getFeature(allFeatures, d)
if f == nil {
return false, nil
}
fs = append(fs, f)
}
callback := reflect.ValueOf(r.callback) callback := reflect.ValueOf(r.callback)
var input []reflect.Value var input []reflect.Value
callbackType := callback.Type() callbackType := callback.Type()
for i := 0; i < callbackType.NumIn(); i++ { for i := 0; i < callbackType.NumIn(); i++ {
pt := callbackType.In(i) pt := callbackType.In(i)
for _, f := range allFeatures { for _, f := range fs {
if reflect.TypeOf(f).AssignableTo(pt) { if reflect.TypeOf(f).AssignableTo(pt) {
input = append(input, reflect.ValueOf(f)) input = append(input, reflect.ValueOf(f))
break break
@@ -75,17 +84,15 @@ func (r *resolution) callbackResolution(allFeatures []features.Feature) error {
} }
} }
return err return true, err
} }
// Instance combines all Xray features. // Instance combines all Xray features.
type Instance struct { type Instance struct {
statusLock sync.Mutex access sync.Mutex
features []features.Feature features []features.Feature
pendingResolutions []resolution featureResolutions []resolution
pendingOptionalResolutions []resolution running bool
running bool
resolveLock sync.Mutex
ctx context.Context ctx context.Context
} }
@@ -146,14 +153,7 @@ func addOutboundHandlers(server *Instance, configs []*OutboundHandlerConfig) err
// See Instance.RequireFeatures for more information. // See Instance.RequireFeatures for more information.
func RequireFeatures(ctx context.Context, callback interface{}) error { func RequireFeatures(ctx context.Context, callback interface{}) error {
v := MustFromContext(ctx) v := MustFromContext(ctx)
return v.RequireFeatures(callback, false) return v.RequireFeatures(callback)
}
// OptionalFeatures is a helper function to aquire features from Instance in context.
// See Instance.RequireFeatures for more information.
func OptionalFeatures(ctx context.Context, callback interface{}) error {
v := MustFromContext(ctx)
return v.RequireFeatures(callback, true)
} }
// New returns a new Xray instance based on given configuration. // New returns a new Xray instance based on given configuration.
@@ -227,12 +227,9 @@ func initInstanceWithConfig(config *Config, server *Instance) (bool, error) {
}(), }(),
) )
server.resolveLock.Lock() if server.featureResolutions != nil {
if server.pendingResolutions != nil {
server.resolveLock.Unlock()
return true, errors.New("not all dependencies are resolved.") return true, errors.New("not all dependencies are resolved.")
} }
server.resolveLock.Unlock()
if err := addInboundHandlers(server, config.Inbound); err != nil { if err := addInboundHandlers(server, config.Inbound); err != nil {
return true, err return true, err
@@ -251,8 +248,8 @@ func (s *Instance) Type() interface{} {
// Close shutdown the Xray instance. // Close shutdown the Xray instance.
func (s *Instance) Close() error { func (s *Instance) Close() error {
s.statusLock.Lock() s.access.Lock()
defer s.statusLock.Unlock() defer s.access.Unlock()
s.running = false s.running = false
@@ -271,7 +268,7 @@ func (s *Instance) Close() error {
// RequireFeatures registers a callback, which will be called when all dependent features are registered. // RequireFeatures registers a callback, which will be called when all dependent features are registered.
// The callback must be a func(). All its parameters must be features.Feature. // The callback must be a func(). All its parameters must be features.Feature.
func (s *Instance) RequireFeatures(callback interface{}, optional bool) error { func (s *Instance) RequireFeatures(callback interface{}) error {
callbackType := reflect.TypeOf(callback) callbackType := reflect.TypeOf(callback)
if callbackType.Kind() != reflect.Func { if callbackType.Kind() != reflect.Func {
panic("not a function") panic("not a function")
@@ -286,32 +283,17 @@ func (s *Instance) RequireFeatures(callback interface{}, optional bool) error {
deps: featureTypes, deps: featureTypes,
callback: callback, callback: callback,
} }
if finished, err := r.resolve(s.features); finished {
s.resolveLock.Lock() return err
foundAll := true
for _, d := range r.deps {
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
}
if foundAll {
s.resolveLock.Unlock()
return r.callbackResolution(s.features)
} else {
if optional {
s.pendingOptionalResolutions = append(s.pendingOptionalResolutions, r)
} else {
s.pendingResolutions = append(s.pendingResolutions, r)
}
s.resolveLock.Unlock()
return nil
} }
s.featureResolutions = append(s.featureResolutions, r)
return nil
} }
// AddFeature registers a feature into current Instance. // AddFeature registers a feature into current Instance.
func (s *Instance) AddFeature(feature features.Feature) error { func (s *Instance) AddFeature(feature features.Feature) error {
s.features = append(s.features, feature)
if s.running { if s.running {
if err := feature.Start(); err != nil { if err := feature.Start(); err != nil {
errors.LogInfoInner(s.ctx, err, "failed to start feature") errors.LogInfoInner(s.ctx, err, "failed to start feature")
@@ -319,52 +301,27 @@ func (s *Instance) AddFeature(feature features.Feature) error {
return nil return nil
} }
s.resolveLock.Lock() if s.featureResolutions == nil {
s.features = append(s.features, feature) return nil
}
var availableResolution []resolution var pendingResolutions []resolution
var pending []resolution for _, r := range s.featureResolutions {
for _, r := range s.pendingResolutions { finished, err := r.resolve(s.features)
foundAll := true if finished && err != nil {
for _, d := range r.deps { return err
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
} }
if foundAll { if !finished {
availableResolution = append(availableResolution, r) pendingResolutions = append(pendingResolutions, r)
} else {
pending = append(pending, r)
} }
} }
s.pendingResolutions = pending if len(pendingResolutions) == 0 {
s.featureResolutions = nil
var pendingOptional []resolution } else if len(pendingResolutions) < len(s.featureResolutions) {
for _, r := range s.pendingOptionalResolutions { s.featureResolutions = pendingResolutions
foundAll := true
for _, d := range r.deps {
f := getFeature(s.features, d)
if f == nil {
foundAll = false
break
}
}
if foundAll {
availableResolution = append(availableResolution, r)
} else {
pendingOptional = append(pendingOptional, r)
}
} }
s.pendingOptionalResolutions = pendingOptional
s.resolveLock.Unlock()
var err error return nil
for _, r := range availableResolution {
err = r.callbackResolution(s.features) // only return the last error for now
}
return err
} }
// GetFeature returns a feature of the given type, or nil if such feature is not registered. // GetFeature returns a feature of the given type, or nil if such feature is not registered.
@@ -377,8 +334,8 @@ func (s *Instance) GetFeature(featureType interface{}) features.Feature {
// //
// xray:api:stable // xray:api:stable
func (s *Instance) Start() error { func (s *Instance) Start() error {
s.statusLock.Lock() s.access.Lock()
defer s.statusLock.Unlock() defer s.access.Unlock()
s.running = true s.running = true
for _, f := range s.features { for _, f := range s.features {

View File

@@ -30,7 +30,7 @@ func TestXrayDependency(t *testing.T) {
t.Error("expected dns client fulfilled, but actually nil") t.Error("expected dns client fulfilled, but actually nil")
} }
wait <- true wait <- true
}, false) })
instance.AddFeature(localdns.New()) instance.AddFeature(localdns.New())
<-wait <-wait
} }

View File

@@ -25,7 +25,7 @@ type Handler interface {
// xray:api:stable // xray:api:stable
type Manager interface { type Manager interface {
features.Feature features.Feature
// GetHandler returns an InboundHandler for the given tag. // GetHandlers returns an InboundHandler for the given tag.
GetHandler(ctx context.Context, tag string) (Handler, error) GetHandler(ctx context.Context, tag string) (Handler, error)
// AddHandler adds the given handler into this Manager. // AddHandler adds the given handler into this Manager.
AddHandler(ctx context.Context, handler Handler) error AddHandler(ctx context.Context, handler Handler) error

View File

@@ -11,7 +11,7 @@ type Context interface {
// GetInboundTag returns the tag of the inbound the connection was from. // GetInboundTag returns the tag of the inbound the connection was from.
GetInboundTag() string GetInboundTag() string
// GetSourceIPs returns the source IPs bound to the connection. // GetSourcesIPs returns the source IPs bound to the connection.
GetSourceIPs() []net.IP GetSourceIPs() []net.IP
// GetSourcePort returns the source port of the connection. // GetSourcePort returns the source port of the connection.

View File

@@ -2,7 +2,6 @@ package stats
import ( import (
"context" "context"
"time"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
@@ -31,8 +30,6 @@ type OnlineMap interface {
AddIP(string) AddIP(string)
// List is the current OnlineMap ip list. // List is the current OnlineMap ip list.
List() []string List() []string
// IpTimeMap return client ips and their last access time.
IpTimeMap() map[string]time.Time
} }
// Channel is the interface for stats channel. // Channel is the interface for stats channel.

40
go.mod
View File

@@ -1,18 +1,18 @@
module github.com/xtls/xray-core module github.com/xtls/xray-core
go 1.24 go 1.21.4
require ( require (
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0
github.com/cloudflare/circl v1.6.0 github.com/cloudflare/circl v1.4.0
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
github.com/golang/mock v1.7.0-rc.1 github.com/golang/mock v1.7.0-rc.1
github.com/google/go-cmp v0.7.0 github.com/google/go-cmp v0.6.0
github.com/gorilla/websocket v1.5.3 github.com/gorilla/websocket v1.5.3
github.com/miekg/dns v1.1.63 github.com/miekg/dns v1.1.62
github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml v1.9.5
github.com/pires/go-proxyproto v0.8.0 github.com/pires/go-proxyproto v0.8.0
github.com/quic-go/quic-go v0.50.0 github.com/quic-go/quic-go v0.46.0
github.com/refraction-networking/utls v1.6.7 github.com/refraction-networking/utls v1.6.7
github.com/sagernet/sing v0.5.1 github.com/sagernet/sing v0.5.1
github.com/sagernet/sing-shadowsocks v0.2.7 github.com/sagernet/sing-shadowsocks v0.2.7
@@ -22,16 +22,16 @@ require (
github.com/vishvananda/netlink v1.3.0 github.com/vishvananda/netlink v1.3.0
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
golang.org/x/crypto v0.36.0 golang.org/x/crypto v0.29.0
golang.org/x/net v0.37.0 golang.org/x/net v0.31.0
golang.org/x/sync v0.12.0 golang.org/x/sync v0.9.0
golang.org/x/sys v0.31.0 golang.org/x/sys v0.27.0
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
google.golang.org/grpc v1.71.0 google.golang.org/grpc v1.67.1
google.golang.org/protobuf v1.36.5 google.golang.org/protobuf v1.35.2
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489
h12.io/socks v1.0.3 h12.io/socks v1.0.3
lukechampine.com/blake3 v1.4.0 lukechampine.com/blake3 v1.3.0
) )
require ( require (
@@ -45,17 +45,17 @@ require (
github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/onsi/ginkgo/v2 v2.19.0 // indirect github.com/onsi/ginkgo/v2 v2.19.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect github.com/quic-go/qpack v0.4.0 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/vishvananda/netns v0.0.4 // indirect github.com/vishvananda/netns v0.0.4 // indirect
go.uber.org/mock v0.5.0 // indirect go.uber.org/mock v0.4.0 // indirect
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
golang.org/x/mod v0.21.0 // indirect golang.org/x/mod v0.18.0 // indirect
golang.org/x/text v0.23.0 // indirect golang.org/x/text v0.20.0 // indirect
golang.org/x/time v0.7.0 // indirect golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.26.0 // indirect golang.org/x/tools v0.22.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

98
go.sum
View File

@@ -2,8 +2,8 @@ github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJS
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM= github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= github.com/cloudflare/circl v1.4.0 h1:BV7h5MgrktNzytKmWjpOtdYrf0lkkbF8YMlBGPhJQrY=
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudflare/circl v1.4.0/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -12,24 +12,18 @@ github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFP
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
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 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U= github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs= github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g= github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g=
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI= github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
@@ -38,8 +32,8 @@ github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0N
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
@@ -52,10 +46,10 @@ github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKp
github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY= github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo= github.com/quic-go/quic-go v0.46.0 h1:uuwLClEEyk1DNvchH8uCByQVjo3yKL9opKulExNDs7Y=
github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E= github.com/quic-go/quic-go v0.46.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
@@ -79,40 +73,28 @@ github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZla
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg= github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg=
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE= github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -121,21 +103,21 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.6/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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -143,12 +125,12 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4= golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA= golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -158,9 +140,9 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 h1:P+U/06iIKPQ3DLcg+zBfSCia1luZ2msPZrJ8jYDFPs0= gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE=
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0/go.mod h1:NQHVAzMwvZ+Qe3ElSiHmq9RUm1MdNHpUZ52fiEqvn+0= gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk=
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo= h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck= h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w= lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
lukechampine.com/blake3 v1.4.0/go.mod h1:MQJNQCTnR+kwOP/JEZSxj3MaQjp80FOFSNMMHXcSeX0= lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=

View File

@@ -2,7 +2,6 @@ package conf
import ( import (
"encoding/json" "encoding/json"
"fmt"
"strconv" "strconv"
"strings" "strings"
@@ -203,24 +202,6 @@ func (list *PortList) Build() *net.PortList {
return portList return portList
} }
func (v PortList) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
func (v PortList) String() string {
ports := []string{}
for _, port := range v.Range {
if port.From == port.To {
p := strconv.Itoa(int(port.From))
ports = append(ports, p)
} else {
p := fmt.Sprintf("%d-%d", port.From, port.To)
ports = append(ports, p)
}
}
return strings.Join(ports, ",")
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON // UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (list *PortList) UnmarshalJSON(data []byte) error { func (list *PortList) UnmarshalJSON(data []byte) error {
var listStr string var listStr string
@@ -277,18 +258,6 @@ type Int32Range struct {
To int32 To int32
} }
func (v Int32Range) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
func (v Int32Range) String() string {
if v.Left == v.Right {
return strconv.Itoa(int(v.Left))
} else {
return fmt.Sprintf("%d-%d", v.Left, v.Right)
}
}
func (v *Int32Range) UnmarshalJSON(data []byte) error { func (v *Int32Range) UnmarshalJSON(data []byte) error {
defer v.ensureOrder() defer v.ensureOrder()
var str string var str string

View File

@@ -12,13 +12,13 @@ import (
) )
type NameServerConfig struct { type NameServerConfig struct {
Address *Address `json:"address"` Address *Address
ClientIP *Address `json:"clientIp"` ClientIP *Address
Port uint16 `json:"port"` Port uint16
SkipFallback bool `json:"skipFallback"` SkipFallback bool
Domains []string `json:"domains"` Domains []string
ExpectIPs StringList `json:"expectIps"` ExpectIPs StringList
QueryStrategy string `json:"queryStrategy"` QueryStrategy string
} }
func (c *NameServerConfig) UnmarshalJSON(data []byte) error { func (c *NameServerConfig) UnmarshalJSON(data []byte) error {

View File

@@ -2,7 +2,6 @@ package conf
import ( import (
"encoding/base64" "encoding/base64"
"encoding/hex"
"net" "net"
"strings" "strings"
@@ -153,9 +152,8 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
func ParseNoise(noise *Noise) (*freedom.Noise, error) { func ParseNoise(noise *Noise) (*freedom.Noise, error) {
var err error var err error
NConfig := new(freedom.Noise) NConfig := new(freedom.Noise)
noise.Packet = strings.TrimSpace(noise.Packet)
switch noise.Type { switch strings.ToLower(noise.Type) {
case "rand": case "rand":
min, max, err := ParseRangeString(noise.Packet) min, max, err := ParseRangeString(noise.Packet)
if err != nil { if err != nil {
@@ -163,35 +161,42 @@ func ParseNoise(noise *Noise) (*freedom.Noise, error) {
} }
NConfig.LengthMin = uint64(min) NConfig.LengthMin = uint64(min)
NConfig.LengthMax = uint64(max) NConfig.LengthMax = uint64(max)
if NConfig.LengthMin > NConfig.LengthMax {
NConfig.LengthMin, NConfig.LengthMax = NConfig.LengthMax, NConfig.LengthMin
}
if NConfig.LengthMin == 0 { if NConfig.LengthMin == 0 {
return nil, errors.New("rand lengthMin or lengthMax cannot be 0") return nil, errors.New("rand lengthMin or lengthMax cannot be 0")
} }
case "str": case "str":
// user input string //user input string
NConfig.Packet = []byte(noise.Packet) NConfig.StrNoise = []byte(strings.TrimSpace(noise.Packet))
case "hex":
// user input hex
NConfig.Packet, err = hex.DecodeString(noise.Packet)
if err != nil {
return nil, errors.New("Invalid hex string").Base(err)
}
case "base64": case "base64":
// user input base64 //user input base64
NConfig.Packet, err = base64.RawURLEncoding.DecodeString(strings.NewReplacer("+", "-", "/", "_", "=", "").Replace(noise.Packet)) NConfig.StrNoise, err = base64.StdEncoding.DecodeString(strings.TrimSpace(noise.Packet))
if err != nil { if err != nil {
return nil, errors.New("Invalid base64 string").Base(err) return nil, errors.New("Invalid base64 string")
} }
default: default:
return nil, errors.New("Invalid packet, only rand/str/hex/base64 are supported") return nil, errors.New("Invalid packet,only rand,str,base64 are supported")
} }
if noise.Delay != nil { if noise.Delay != nil {
NConfig.DelayMin = uint64(noise.Delay.From) if noise.Delay.From != 0 && noise.Delay.To != 0 {
NConfig.DelayMax = uint64(noise.Delay.To) NConfig.DelayMin = uint64(noise.Delay.From)
NConfig.DelayMax = uint64(noise.Delay.To)
if NConfig.DelayMin > NConfig.LengthMax {
NConfig.DelayMin, NConfig.DelayMax = NConfig.LengthMax, NConfig.DelayMin
}
} else {
return nil, errors.New("DelayMin or DelayMax cannot be zero")
}
} else {
NConfig.DelayMin = 0
NConfig.DelayMax = 0
} }
return NConfig, nil return NConfig, nil
} }

View File

@@ -14,6 +14,7 @@ type GRPCConfig struct {
PermitWithoutStream bool `json:"permit_without_stream"` PermitWithoutStream bool `json:"permit_without_stream"`
InitialWindowsSize int32 `json:"initial_windows_size"` InitialWindowsSize int32 `json:"initial_windows_size"`
UserAgent string `json:"user_agent"` UserAgent string `json:"user_agent"`
MultiConnections int32 `json:"multi_connections"`
} }
func (g *GRPCConfig) Build() (proto.Message, error) { func (g *GRPCConfig) Build() (proto.Message, error) {
@@ -37,5 +38,6 @@ func (g *GRPCConfig) Build() (proto.Message, error) {
PermitWithoutStream: g.PermitWithoutStream, PermitWithoutStream: g.PermitWithoutStream,
InitialWindowsSize: g.InitialWindowsSize, InitialWindowsSize: g.InitialWindowsSize,
UserAgent: g.UserAgent, UserAgent: g.UserAgent,
MultiConnections: g.MultiConnections,
}, nil }, nil
} }

View File

@@ -6,21 +6,15 @@ import (
) )
type MetricsConfig struct { type MetricsConfig struct {
Tag string `json:"tag"` Tag string `json:"tag"`
Listen string `json:"listen"`
} }
func (c *MetricsConfig) Build() (*metrics.Config, error) { func (c *MetricsConfig) Build() (*metrics.Config, error) {
if c.Listen == "" && c.Tag == "" {
return nil, errors.New("Metrics must have a tag or listen address.")
}
// If the tag is empty but have "listen" set a default "Metrics" for compatibility.
if c.Tag == "" { if c.Tag == "" {
c.Tag = "Metrics" return nil, errors.New("metrics tag can't be empty.")
} }
return &metrics.Config{ return &metrics.Config{
Tag: c.Tag, Tag: c.Tag,
Listen: c.Listen,
}, nil }, nil
} }

View File

@@ -163,15 +163,13 @@ func (c *WebSocketConfig) Build() (proto.Message, error) {
path = u.String() path = u.String()
} }
} }
// Priority (client): host > serverName > address // If http host is not set in the Host field, but in headers field, we add it to Host Field here.
for k, v := range c.Headers { // If we don't do that, http host will be overwritten as address.
if strings.ToLower(k) == "host" { // Host priority: Host field > headers field > address.
errors.PrintDeprecatedFeatureWarning(`"host" in "headers"`, `independent "host"`) if c.Host == "" && c.Headers["host"] != "" {
if c.Host == "" { c.Host = c.Headers["host"]
c.Host = v } else if c.Host == "" && c.Headers["Host"] != "" {
} c.Host = c.Headers["Host"]
delete(c.Headers, k)
}
} }
config := &websocket.Config{ config := &websocket.Config{
Path: path, Path: path,
@@ -204,11 +202,15 @@ func (c *HttpUpgradeConfig) Build() (proto.Message, error) {
path = u.String() path = u.String()
} }
} }
// Priority (client): host > serverName > address // If http host is not set in the Host field, but in headers field, we add it to Host Field here.
for k := range c.Headers { // If we don't do that, http host will be overwritten as address.
if strings.ToLower(k) == "host" { // Host priority: Host field > headers field > address.
return nil, errors.New(`"headers" can't contain "host"`) if c.Host == "" && c.Headers["host"] != "" {
} c.Host = c.Headers["host"]
delete(c.Headers, "host")
} else if c.Host == "" && c.Headers["Host"] != "" {
c.Host = c.Headers["Host"]
delete(c.Headers, "Host")
} }
config := &httpupgrade.Config{ config := &httpupgrade.Config{
Path: path, Path: path,
@@ -223,31 +225,36 @@ func (c *HttpUpgradeConfig) Build() (proto.Message, error) {
type SplitHTTPConfig struct { type SplitHTTPConfig struct {
Host string `json:"host"` Host string `json:"host"`
Path string `json:"path"` Path string `json:"path"`
Mode string `json:"mode"`
Headers map[string]string `json:"headers"` Headers map[string]string `json:"headers"`
XPaddingBytes Int32Range `json:"xPaddingBytes"` ScMaxConcurrentPosts *Int32Range `json:"scMaxConcurrentPosts"`
NoGRPCHeader bool `json:"noGRPCHeader"` ScMaxEachPostBytes *Int32Range `json:"scMaxEachPostBytes"`
ScMinPostsIntervalMs *Int32Range `json:"scMinPostsIntervalMs"`
NoSSEHeader bool `json:"noSSEHeader"` NoSSEHeader bool `json:"noSSEHeader"`
ScMaxEachPostBytes Int32Range `json:"scMaxEachPostBytes"` XPaddingBytes *Int32Range `json:"xPaddingBytes"`
ScMinPostsIntervalMs Int32Range `json:"scMinPostsIntervalMs"` Xmux Xmux `json:"xmux"`
ScMaxBufferedPosts int64 `json:"scMaxBufferedPosts"`
ScStreamUpServerSecs Int32Range `json:"scStreamUpServerSecs"`
Xmux XmuxConfig `json:"xmux"`
DownloadSettings *StreamConfig `json:"downloadSettings"` DownloadSettings *StreamConfig `json:"downloadSettings"`
Mode string `json:"mode"`
Extra json.RawMessage `json:"extra"` Extra json.RawMessage `json:"extra"`
NoGRPCHeader bool `json:"noGRPCHeader"`
KeepAlivePeriod int64 `json:"keepAlivePeriod"`
} }
type XmuxConfig struct { type Xmux struct {
MaxConcurrency Int32Range `json:"maxConcurrency"` MaxConcurrency *Int32Range `json:"maxConcurrency"`
MaxConnections Int32Range `json:"maxConnections"` MaxConnections *Int32Range `json:"maxConnections"`
CMaxReuseTimes Int32Range `json:"cMaxReuseTimes"` CMaxReuseTimes *Int32Range `json:"cMaxReuseTimes"`
HMaxRequestTimes Int32Range `json:"hMaxRequestTimes"` CMaxLifetimeMs *Int32Range `json:"cMaxLifetimeMs"`
HMaxReusableSecs Int32Range `json:"hMaxReusableSecs"`
HKeepAlivePeriod int64 `json:"hKeepAlivePeriod"`
} }
func newRangeConfig(input Int32Range) *splithttp.RangeConfig { func splithttpNewRandRangeConfig(input *Int32Range) *splithttp.RandRangeConfig {
return &splithttp.RangeConfig{ if input == nil {
return &splithttp.RandRangeConfig{
From: 0,
To: 0,
}
}
return &splithttp.RandRangeConfig{
From: input.From, From: input.From,
To: input.To, To: input.To,
} }
@@ -263,9 +270,41 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
extra.Host = c.Host extra.Host = c.Host
extra.Path = c.Path extra.Path = c.Path
extra.Mode = c.Mode extra.Mode = c.Mode
extra.Extra = c.Extra
c = &extra c = &extra
} }
// If http host is not set in the Host field, but in headers field, we add it to Host Field here.
// If we don't do that, http host will be overwritten as address.
// Host priority: Host field > headers field > address.
if c.Host == "" && c.Headers["host"] != "" {
c.Host = c.Headers["host"]
} else if c.Host == "" && c.Headers["Host"] != "" {
c.Host = c.Headers["Host"]
}
if c.Xmux.MaxConnections != nil && c.Xmux.MaxConnections.To > 0 && c.Xmux.MaxConcurrency != nil && c.Xmux.MaxConcurrency.To > 0 {
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
}
// Multiplexing config
muxProtobuf := splithttp.Multiplexing{
MaxConcurrency: splithttpNewRandRangeConfig(c.Xmux.MaxConcurrency),
MaxConnections: splithttpNewRandRangeConfig(c.Xmux.MaxConnections),
CMaxReuseTimes: splithttpNewRandRangeConfig(c.Xmux.CMaxReuseTimes),
CMaxLifetimeMs: splithttpNewRandRangeConfig(c.Xmux.CMaxLifetimeMs),
}
if muxProtobuf.MaxConcurrency.To == 0 &&
muxProtobuf.MaxConnections.To == 0 &&
muxProtobuf.CMaxReuseTimes.To == 0 &&
muxProtobuf.CMaxLifetimeMs.To == 0 {
muxProtobuf.MaxConcurrency.From = 16
muxProtobuf.MaxConcurrency.To = 32
muxProtobuf.CMaxReuseTimes.From = 64
muxProtobuf.CMaxReuseTimes.To = 128
}
switch c.Mode { switch c.Mode {
case "": case "":
c.Mode = "auto" c.Mode = "auto"
@@ -274,61 +313,32 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
return nil, errors.New("unsupported mode: " + c.Mode) return nil, errors.New("unsupported mode: " + c.Mode)
} }
// Priority (client): host > serverName > address
for k := range c.Headers {
if strings.ToLower(k) == "host" {
return nil, errors.New(`"headers" can't contain "host"`)
}
}
if c.XPaddingBytes != (Int32Range{}) && (c.XPaddingBytes.From <= 0 || c.XPaddingBytes.To <= 0) {
return nil, errors.New("xPaddingBytes cannot be disabled")
}
if c.Xmux.MaxConnections.To > 0 && c.Xmux.MaxConcurrency.To > 0 {
return nil, errors.New("maxConnections cannot be specified together with maxConcurrency")
}
if c.Xmux == (XmuxConfig{}) {
c.Xmux.MaxConcurrency.From = 16
c.Xmux.MaxConcurrency.To = 32
c.Xmux.HMaxRequestTimes.From = 600
c.Xmux.HMaxRequestTimes.To = 900
c.Xmux.HMaxReusableSecs.From = 1800
c.Xmux.HMaxReusableSecs.To = 3000
}
config := &splithttp.Config{ config := &splithttp.Config{
Host: c.Host,
Path: c.Path, Path: c.Path,
Mode: c.Mode, Host: c.Host,
Headers: c.Headers, Header: c.Headers,
XPaddingBytes: newRangeConfig(c.XPaddingBytes), ScMaxConcurrentPosts: splithttpNewRandRangeConfig(c.ScMaxConcurrentPosts),
NoGRPCHeader: c.NoGRPCHeader, ScMaxEachPostBytes: splithttpNewRandRangeConfig(c.ScMaxEachPostBytes),
ScMinPostsIntervalMs: splithttpNewRandRangeConfig(c.ScMinPostsIntervalMs),
NoSSEHeader: c.NoSSEHeader, NoSSEHeader: c.NoSSEHeader,
ScMaxEachPostBytes: newRangeConfig(c.ScMaxEachPostBytes), XPaddingBytes: splithttpNewRandRangeConfig(c.XPaddingBytes),
ScMinPostsIntervalMs: newRangeConfig(c.ScMinPostsIntervalMs), Xmux: &muxProtobuf,
ScMaxBufferedPosts: c.ScMaxBufferedPosts, Mode: c.Mode,
ScStreamUpServerSecs: newRangeConfig(c.ScStreamUpServerSecs), NoGRPCHeader: c.NoGRPCHeader,
Xmux: &splithttp.XmuxConfig{ KeepAlivePeriod: c.KeepAlivePeriod,
MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency),
MaxConnections: newRangeConfig(c.Xmux.MaxConnections),
CMaxReuseTimes: newRangeConfig(c.Xmux.CMaxReuseTimes),
HMaxRequestTimes: newRangeConfig(c.Xmux.HMaxRequestTimes),
HMaxReusableSecs: newRangeConfig(c.Xmux.HMaxReusableSecs),
HKeepAlivePeriod: c.Xmux.HKeepAlivePeriod,
},
} }
var err error
if c.DownloadSettings != nil { if c.DownloadSettings != nil {
if c.Mode == "stream-one" { if c.Mode == "stream-one" {
return nil, errors.New(`Can not use "downloadSettings" in "stream-one" mode.`) return nil, errors.New(`Can not use "downloadSettings" in "stream-one" mode.`)
} }
var err error if c.Extra != nil {
c.DownloadSettings.SocketSettings = nil
}
if config.DownloadSettings, err = c.DownloadSettings.Build(); err != nil { if config.DownloadSettings, err = c.DownloadSettings.Build(); err != nil {
return nil, errors.New(`Failed to build "downloadSettings".`).Base(err) return nil, errors.New(`Failed to build "downloadSettings".`).Base(err)
} }
} }
return config, nil return config, nil
} }
@@ -410,8 +420,6 @@ type TLSConfig struct {
PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"` PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"`
CurvePreferences *StringList `json:"curvePreferences"` CurvePreferences *StringList `json:"curvePreferences"`
MasterKeyLog string `json:"masterKeyLog"` MasterKeyLog string `json:"masterKeyLog"`
ServerNameToVerify string `json:"serverNameToVerify"`
VerifyPeerCertInNames []string `json:"verifyPeerCertInNames"`
} }
// Build implements Buildable. // Build implements Buildable.
@@ -433,13 +441,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
if c.ALPN != nil && len(*c.ALPN) > 0 { if c.ALPN != nil && len(*c.ALPN) > 0 {
config.NextProtocol = []string(*c.ALPN) config.NextProtocol = []string(*c.ALPN)
} }
if len(config.NextProtocol) > 1 {
for _, p := range config.NextProtocol {
if tcp.IsFromMitm(p) {
return nil, errors.New(`only one element is allowed in "alpn" when using "fromMitm" in it`)
}
}
}
if c.CurvePreferences != nil && len(*c.CurvePreferences) > 0 { if c.CurvePreferences != nil && len(*c.CurvePreferences) > 0 {
config.CurvePreferences = []string(*c.CurvePreferences) config.CurvePreferences = []string(*c.CurvePreferences)
} }
@@ -449,8 +450,8 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.MaxVersion = c.MaxVersion config.MaxVersion = c.MaxVersion
config.CipherSuites = c.CipherSuites config.CipherSuites = c.CipherSuites
config.Fingerprint = strings.ToLower(c.Fingerprint) config.Fingerprint = strings.ToLower(c.Fingerprint)
if config.Fingerprint != "unsafe" && tls.GetFingerprint(config.Fingerprint) == nil { if config.Fingerprint != "" && tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint) return nil, errors.New(`unknown fingerprint: `, config.Fingerprint)
} }
config.RejectUnknownSni = c.RejectUnknownSNI config.RejectUnknownSni = c.RejectUnknownSNI
@@ -478,11 +479,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
config.MasterKeyLog = c.MasterKeyLog config.MasterKeyLog = c.MasterKeyLog
if c.ServerNameToVerify != "" {
return nil, errors.PrintRemovedFeatureError(`"serverNameToVerify"`, `"verifyPeerCertInNames"`)
}
config.VerifyPeerCertInNames = c.VerifyPeerCertInNames
return config, nil return config, nil
} }
@@ -502,7 +498,6 @@ type REALITYConfig struct {
Fingerprint string `json:"fingerprint"` Fingerprint string `json:"fingerprint"`
ServerName string `json:"serverName"` ServerName string `json:"serverName"`
Password string `json:"password"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
ShortId string `json:"shortId"` ShortId string `json:"shortId"`
SpiderX string `json:"spiderX"` SpiderX string `json:"spiderX"`
@@ -601,24 +596,23 @@ func (c *REALITYConfig) Build() (proto.Message, error) {
config.ServerNames = c.ServerNames config.ServerNames = c.ServerNames
config.MaxTimeDiff = c.MaxTimeDiff config.MaxTimeDiff = c.MaxTimeDiff
} else { } else {
config.Fingerprint = strings.ToLower(c.Fingerprint) if c.Fingerprint == "" {
if config.Fingerprint == "unsafe" || config.Fingerprint == "hellogolang" { return nil, errors.New(`empty "fingerprint"`)
return nil, errors.New(`invalid "fingerprint": `, config.Fingerprint)
} }
if tls.GetFingerprint(config.Fingerprint) == nil { if config.Fingerprint = strings.ToLower(c.Fingerprint); tls.GetFingerprint(config.Fingerprint) == nil {
return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint) return nil, errors.New(`unknown "fingerprint": `, config.Fingerprint)
} }
if config.Fingerprint == "hellogolang" {
return nil, errors.New(`invalid "fingerprint": `, config.Fingerprint)
}
if len(c.ServerNames) != 0 { if len(c.ServerNames) != 0 {
return nil, errors.New(`non-empty "serverNames", please use "serverName" instead`) return nil, errors.New(`non-empty "serverNames", please use "serverName" instead`)
} }
if c.Password != "" {
c.PublicKey = c.Password
}
if c.PublicKey == "" { if c.PublicKey == "" {
return nil, errors.New(`empty "password"`) return nil, errors.New(`empty "publicKey"`)
} }
if config.PublicKey, err = base64.RawURLEncoding.DecodeString(c.PublicKey); err != nil || len(config.PublicKey) != 32 { if config.PublicKey, err = base64.RawURLEncoding.DecodeString(c.PublicKey); err != nil || len(config.PublicKey) != 32 {
return nil, errors.New(`invalid "password": `, c.PublicKey) return nil, errors.New(`invalid "publicKey": `, c.PublicKey)
} }
if len(c.ShortIds) != 0 { if len(c.ShortIds) != 0 {
return nil, errors.New(`non-empty "shortIds", please use "shortId" instead`) return nil, errors.New(`non-empty "shortIds", please use "shortId" instead`)
@@ -709,13 +703,12 @@ type SocketConfig struct {
TCPCongestion string `json:"tcpCongestion"` TCPCongestion string `json:"tcpCongestion"`
TCPWindowClamp int32 `json:"tcpWindowClamp"` TCPWindowClamp int32 `json:"tcpWindowClamp"`
TCPMaxSeg int32 `json:"tcpMaxSeg"` TCPMaxSeg int32 `json:"tcpMaxSeg"`
Penetrate bool `json:"penetrate"` TcpNoDelay bool `json:"tcpNoDelay"`
TCPUserTimeout int32 `json:"tcpUserTimeout"` TCPUserTimeout int32 `json:"tcpUserTimeout"`
V6only bool `json:"v6only"` V6only bool `json:"v6only"`
Interface string `json:"interface"` Interface string `json:"interface"`
TcpMptcp bool `json:"tcpMptcp"` TcpMptcp bool `json:"tcpMptcp"`
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"` CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
AddressPortStrategy string `json:"addressPortStrategy"`
} }
// Build implements Buildable. // Build implements Buildable.
@@ -785,26 +778,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
customSockopts = append(customSockopts, customSockopt) customSockopts = append(customSockopts, customSockopt)
} }
addressPortStrategy := internet.AddressPortStrategy_None
switch strings.ToLower(c.AddressPortStrategy) {
case "none", "":
addressPortStrategy = internet.AddressPortStrategy_None
case "srvportonly":
addressPortStrategy = internet.AddressPortStrategy_SrvPortOnly
case "srvaddressonly":
addressPortStrategy = internet.AddressPortStrategy_SrvAddressOnly
case "srvportandaddress":
addressPortStrategy = internet.AddressPortStrategy_SrvPortAndAddress
case "txtportonly":
addressPortStrategy = internet.AddressPortStrategy_TxtPortOnly
case "txtaddressonly":
addressPortStrategy = internet.AddressPortStrategy_TxtAddressOnly
case "txtportandaddress":
addressPortStrategy = internet.AddressPortStrategy_TxtPortAndAddress
default:
return nil, errors.New("unsupported address and port strategy: ", c.AddressPortStrategy)
}
return &internet.SocketConfig{ return &internet.SocketConfig{
Mark: c.Mark, Mark: c.Mark,
Tfo: tfo, Tfo: tfo,
@@ -817,13 +790,12 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
TcpCongestion: c.TCPCongestion, TcpCongestion: c.TCPCongestion,
TcpWindowClamp: c.TCPWindowClamp, TcpWindowClamp: c.TCPWindowClamp,
TcpMaxSeg: c.TCPMaxSeg, TcpMaxSeg: c.TCPMaxSeg,
Penetrate: c.Penetrate, TcpNoDelay: c.TcpNoDelay,
TcpUserTimeout: c.TCPUserTimeout, TcpUserTimeout: c.TCPUserTimeout,
V6Only: c.V6only, V6Only: c.V6only,
Interface: c.Interface, Interface: c.Interface,
TcpMptcp: c.TcpMptcp, TcpMptcp: c.TcpMptcp,
CustomSockopt: customSockopts, CustomSockopt: customSockopts,
AddressPortStrategy: addressPortStrategy,
}, nil }, nil
} }

View File

@@ -24,7 +24,6 @@ var (
"dokodemo-door": func() interface{} { return new(DokodemoConfig) }, "dokodemo-door": func() interface{} { return new(DokodemoConfig) },
"http": func() interface{} { return new(HTTPServerConfig) }, "http": func() interface{} { return new(HTTPServerConfig) },
"shadowsocks": func() interface{} { return new(ShadowsocksServerConfig) }, "shadowsocks": func() interface{} { return new(ShadowsocksServerConfig) },
"mixed": func() interface{} { return new(SocksServerConfig) },
"socks": func() interface{} { return new(SocksServerConfig) }, "socks": func() interface{} { return new(SocksServerConfig) },
"vless": func() interface{} { return new(VLessInboundConfig) }, "vless": func() interface{} { return new(VLessInboundConfig) },
"vmess": func() interface{} { return new(VMessInboundConfig) }, "vmess": func() interface{} { return new(VMessInboundConfig) },
@@ -292,9 +291,7 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
senderSettings.ViaCidr = strings.Split(*c.SendThrough, "/")[1] senderSettings.ViaCidr = strings.Split(*c.SendThrough, "/")[1]
} else { } else {
if address.Family().IsDomain() { if address.Family().IsDomain() {
if address.Address.Domain() != "origin" { return nil, errors.New("unable to send through: " + address.String())
return nil, errors.New("unable to send through: " + address.String())
}
} }
} }
senderSettings.Via = address.Build() senderSettings.Via = address.Build()

View File

@@ -48,7 +48,9 @@ func TestXrayConfig(t *testing.T) {
"streamSettings": { "streamSettings": {
"network": "ws", "network": "ws",
"wsSettings": { "wsSettings": {
"host": "example.domain", "headers": {
"host": "example.domain"
},
"path": "" "path": ""
}, },
"tlsSettings": { "tlsSettings": {
@@ -137,6 +139,9 @@ func TestXrayConfig(t *testing.T) {
ProtocolName: "websocket", ProtocolName: "websocket",
Settings: serial.ToTypedMessage(&websocket.Config{ Settings: serial.ToTypedMessage(&websocket.Config{
Host: "example.domain", Host: "example.domain",
Header: map[string]string{
"host": "example.domain",
},
}), }),
}, },
}, },

View File

@@ -1,7 +1,6 @@
package main package main
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"go/build" "go/build"
@@ -19,7 +18,7 @@ var directory = flag.String("pwd", "", "Working directory of Xray vformat.")
func envFile() (string, error) { func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" { if file := os.Getenv("GOENV"); file != "" {
if file == "off" { if file == "off" {
return "", errors.New("GOENV=off") return "", fmt.Errorf("GOENV=off")
} }
return file, nil return file, nil
} }
@@ -28,7 +27,7 @@ func envFile() (string, error) {
return "", err return "", err
} }
if dir == "" { if dir == "" {
return "", errors.New("missing user-config dir") return "", fmt.Errorf("missing user-config dir")
} }
return filepath.Join(dir, "go", "env"), nil return filepath.Join(dir, "go", "env"), nil
} }
@@ -41,7 +40,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err return "", err
} }
if file == "" { if file == "" {
return "", errors.New("missing runtime env file") return "", fmt.Errorf("missing runtime env file")
} }
var data []byte var data []byte
var runtimeEnv string var runtimeEnv string

View File

@@ -1,7 +1,6 @@
package main package main
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"go/build" "go/build"
@@ -23,7 +22,7 @@ var directory = flag.String("pwd", "", "Working directory of Xray vprotogen.")
func envFile() (string, error) { func envFile() (string, error) {
if file := os.Getenv("GOENV"); file != "" { if file := os.Getenv("GOENV"); file != "" {
if file == "off" { if file == "off" {
return "", errors.New("GOENV=off") return "", fmt.Errorf("GOENV=off")
} }
return file, nil return file, nil
} }
@@ -32,7 +31,7 @@ func envFile() (string, error) {
return "", err return "", err
} }
if dir == "" { if dir == "" {
return "", errors.New("missing user-config dir") return "", fmt.Errorf("missing user-config dir")
} }
return filepath.Join(dir, "go", "env"), nil return filepath.Join(dir, "go", "env"), nil
} }
@@ -45,7 +44,7 @@ func GetRuntimeEnv(key string) (string, error) {
return "", err return "", err
} }
if file == "" { if file == "" {
return "", errors.New("missing runtime env file") return "", fmt.Errorf("missing runtime env file")
} }
var data []byte var data []byte
var runtimeEnv string var runtimeEnv string
@@ -89,11 +88,12 @@ func whichProtoc(suffix, targetedVersion string) (string, error) {
path, err := exec.LookPath(protoc) path, err := exec.LookPath(protoc)
if err != nil { if err != nil {
return "", fmt.Errorf(` errStr := fmt.Sprintf(`
Command "%s" not found. Command "%s" not found.
Make sure that %s is in your system path or current path. Make sure that %s is in your system path or current path.
Download %s v%s or later from https://github.com/protocolbuffers/protobuf/releases Download %s v%s or later from https://github.com/protocolbuffers/protobuf/releases
`, protoc, protoc, protoc, targetedVersion) `, protoc, protoc, protoc, targetedVersion)
return "", fmt.Errorf(errStr)
} }
return path, nil return path, nil
} }
@@ -101,12 +101,12 @@ Download %s v%s or later from https://github.com/protocolbuffers/protobuf/releas
func getProjectProtocVersion(url string) (string, error) { func getProjectProtocVersion(url string) (string, error) {
resp, err := http.Get(url) resp, err := http.Get(url)
if err != nil { if err != nil {
return "", errors.New("can not get the version of protobuf used in xray project") return "", fmt.Errorf("can not get the version of protobuf used in xray project")
} }
defer resp.Body.Close() defer resp.Body.Close()
body, err := io.ReadAll(resp.Body) body, err := io.ReadAll(resp.Body)
if err != nil { if err != nil {
return "", errors.New("can not read from body") return "", fmt.Errorf("can not read from body")
} }
versionRegexp := regexp.MustCompile(`\/\/\s*protoc\s*v\d+\.(\d+\.\d+)`) versionRegexp := regexp.MustCompile(`\/\/\s*protoc\s*v\d+\.(\d+\.\d+)`)
matched := versionRegexp.FindStringSubmatch(string(body)) matched := versionRegexp.FindStringSubmatch(string(body))

View File

@@ -27,6 +27,5 @@ var CmdAPI = &base.Command{
cmdRemoveRules, cmdRemoveRules,
cmdSourceIpBlock, cmdSourceIpBlock,
cmdOnlineStats, cmdOnlineStats,
cmdOnlineStatsIpList,
}, },
} }

View File

@@ -13,20 +13,25 @@ import (
var cmdBalancerInfo = &base.Command{ var cmdBalancerInfo = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api bi [--server=127.0.0.1:8080] [balancer]...", UsageLine: "{{.Exec}} api bi [--server=127.0.0.1:8080] [balancer]...",
Short: "Retrieve balancer information", Short: "balancer information",
Long: ` Long: `
Retrieve information of specified balancers, including health, strategy and selecting. Get information of specified balancers, including health, strategy
If no balancer tag specified, information for all balancers is returned. and selecting. If no balancer tag specified, get information of
all balancers.
> Ensure that "RoutingService" is enabled under "config.api.services" in the server configuration. > Make sure you have "RoutingService" set in "config.api.services"
of server config.
Arguments: Arguments:
-json
Use json output.
-s, -server <server:port> -s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout <seconds> -t, -timeout <seconds>
Timeout in seconds for calling API. Default 3 Timeout seconds to call API. Default 3
Example: Example:

View File

@@ -7,27 +7,31 @@ import (
var cmdBalancerOverride = &base.Command{ var cmdBalancerOverride = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api bo [--server=127.0.0.1:8080] <-b balancer> outboundTag <-r>", UsageLine: "{{.Exec}} api bo [--server=127.0.0.1:8080] <-b balancer> outboundTag",
Short: "Override balancer", Short: "balancer override",
Long: ` Long: `
Override the selection target of a balancer. Override a balancer's selection.
> Ensure that the "RoutingService" is properly configured under "config.api.services" in the server configuration. > Make sure you have "RoutingService" set in "config.api.services"
of server config.
Once the balancer's selection is overridden: Once a balancer's selecting is overridden:
- The balancer's selection result will always be outboundTag - The balancer's selection result will always be outboundTag
Arguments: Arguments:
-s, -server <server:port> -r, -remove
The API server address. Default 127.0.0.1:8080 Remove the overridden
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-r, -remove -r, -remove
Remove the existing override. Remove the override
-s, -server
The API server address. Default 127.0.0.1:8080
-t, -timeout
Timeout seconds to call API. Default 3
Example: Example:

View File

@@ -8,28 +8,20 @@ import (
var cmdInboundUser = &base.Command{ var cmdInboundUser = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api inbounduser [--server=127.0.0.1:8080] -tag=tag [-email=email]", UsageLine: "{{.Exec}} api inbounduser [--server=127.0.0.1:8080] -tag=tag [-email=email]",
Short: "Retrieve inbound user(s)", Short: "Get Inbound User",
Long: ` Long: `
Get User info from an inbound. Get User info from an inbound.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
-tag -tag
Inbound tag Inbound tag
-email
-email User email. If email is not given, will get all users
The user's email address. If not provided, all users will be retrieved.
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name" -email="xray@love.com"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name" -email="xray@love.com"
`, `,
Run: executeInboundUser, Run: executeInboundUser,
} }

View File

@@ -8,24 +8,18 @@ import (
var cmdInboundUserCount = &base.Command{ var cmdInboundUserCount = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api inboundusercount [--server=127.0.0.1:8080] -tag=tag", UsageLine: "{{.Exec}} api inboundusercount [--server=127.0.0.1:8080] -tag=tag",
Short: "Retrieve inbound user count", Short: "Get Inbound User Count",
Long: ` Long: `
Retrieve the user count for a specified inbound tag. Get User count from an inbound.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
-tag -tag
Inbound tag Inbound tag
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name"
`, `,
Run: executeInboundUserCount, Run: executeInboundUserCount,
} }

View File

@@ -15,18 +15,13 @@ var cmdAddInbounds = &base.Command{
Short: "Add inbounds", Short: "Add inbounds",
Long: ` Long: `
Add inbounds to Xray. Add inbounds to Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
`, `,
Run: executeAddInbounds, Run: executeAddInbounds,
} }

View File

@@ -14,18 +14,13 @@ var cmdRemoveInbounds = &base.Command{
Short: "Remove inbounds", Short: "Remove inbounds",
Long: ` Long: `
Remove inbounds from Xray. Remove inbounds from Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
`, `,
Run: executeRemoveInbounds, Run: executeRemoveInbounds,
} }

View File

@@ -11,18 +11,11 @@ var cmdRestartLogger = &base.Command{
Short: "Restart the logger", Short: "Restart the logger",
Long: ` Long: `
Restart the logger of Xray. Restart the logger of Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
`, `,
Run: executeRestartLogger, Run: executeRestartLogger,
} }

View File

@@ -15,18 +15,13 @@ var cmdAddOutbounds = &base.Command{
Short: "Add outbounds", Short: "Add outbounds",
Long: ` Long: `
Add outbounds to Xray. Add outbounds to Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
`, `,
Run: executeAddOutbounds, Run: executeAddOutbounds,
} }

View File

@@ -14,18 +14,13 @@ var cmdRemoveOutbounds = &base.Command{
Short: "Remove outbounds", Short: "Remove outbounds",
Long: ` Long: `
Remove outbounds from Xray. Remove outbounds from Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json "tag name"
`, `,
Run: executeRemoveOutbounds, Run: executeRemoveOutbounds,
} }

View File

@@ -16,21 +16,16 @@ var cmdAddRules = &base.Command{
Short: "Add routing rules", Short: "Add routing rules",
Long: ` Long: `
Add routing rules to Xray. Add routing rules to Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds>
Timeout seconds to call API. Default 3 Timeout seconds to call API. Default 3
-append -append
Append to the existing configuration instead of replacing it. Default false append or replace config. Default false
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
`, `,
Run: executeAddRules, Run: executeAddRules,
} }

View File

@@ -9,22 +9,17 @@ import (
var cmdRemoveRules = &base.Command{ var cmdRemoveRules = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api rmrules [--server=127.0.0.1:8080] [ruleTag]...", UsageLine: "{{.Exec}} api rmrules [--server=127.0.0.1:8080] ruleTag1 ruleTag2...",
Short: "Remove routing rules by ruleTag", Short: "Remove routing rules by ruleTag",
Long: ` Long: `
Remove routing rules by ruleTag from Xray. Remove routing rules by ruleTag from Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 ruleTag1 ruleTag2
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 ruleTag1 ruleTag2
`, `,
Run: executeRemoveRules, Run: executeRemoveRules,
} }

View File

@@ -3,7 +3,6 @@ package api
import ( import (
"bytes" "bytes"
"context" "context"
"errors"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@@ -102,7 +101,7 @@ func fetchHTTPContent(target string) ([]byte, error) {
content, err := buf.ReadAllToBytes(resp.Body) content, err := buf.ReadAllToBytes(resp.Body)
if err != nil { if err != nil {
return nil, errors.New("failed to read HTTP response") return nil, fmt.Errorf("failed to read HTTP response")
} }
return content, nil return content, nil

View File

@@ -14,34 +14,25 @@ import (
var cmdSourceIpBlock = &base.Command{ var cmdSourceIpBlock = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api sib [--server=127.0.0.1:8080] -outbound=blocked -inbound=socks 1.2.3.4", UsageLine: "{{.Exec}} api sib [--server=127.0.0.1:8080] -outbound=blocked -inbound=socks 1.2.3.4",
Short: "Block connections by source IP", Short: "Drop connections by source ip",
Long: ` Long: `
Block connections by source IP address. Drop connections by source ip.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
-outbound -outbound
Specifies the outbound tag. route traffic to specific outbound.
-inbound -inbound
Specifies the inbound tag. target traffig from specific inbound.
-ruletag -ruletag
The ruleTag. Default sourceIpBlock set ruleTag. Default sourceIpBlock
-reset -reset
remove ruletag and apply new source IPs. Default false remove ruletag and apply new source IPs. Default false
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -outbound=blocked -inbound=socks 1.2.3.4
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -outbound=blocked -inbound=socks 1.2.3.4 -reset
`, `,
Run: executeSourceIpBlock, Run: executeSourceIpBlock,
} }

View File

@@ -8,26 +8,19 @@ import (
var cmdGetStats = &base.Command{ var cmdGetStats = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api stats [--server=127.0.0.1:8080] [-name '']", UsageLine: "{{.Exec}} api stats [--server=127.0.0.1:8080] [-name '']",
Short: "Retrieve statistics", Short: "Get statistics",
Long: ` Long: `
Retrieve the statistics from Xray. Get statistics from Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
-name -name
Name of the counter. Name of the stat counter.
-reset -reset
Reset the counter after fetching their values. Default false Reset the counter to fetching its value.
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -name "inbound>>>statin>>>traffic>>>downlink" {{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -name "inbound>>>statin>>>traffic>>>downlink"
`, `,
Run: executeGetStats, Run: executeGetStats,

View File

@@ -7,25 +7,21 @@ import (
var cmdOnlineStats = &base.Command{ var cmdOnlineStats = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api statsonline [--server=127.0.0.1:8080] [-email '']", UsageLine: "{{.Exec}} api statsonline [--server=127.0.0.1:8080] [-name '']",
Short: "Retrieve the online session count for a user", Short: "Get online user",
Long: ` Long: `
Retrieve the current number of active sessions for a user from Xray. Get statistics from Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
-email -email
The user's email address. email of the user.
-reset
Reset the counter to fetching its value.
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "user1@test.com"
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "xray@love.com"
`, `,
Run: executeOnlineStats, Run: executeOnlineStats,
} }

View File

@@ -1,51 +0,0 @@
package api
import (
statsService "github.com/xtls/xray-core/app/stats/command"
"github.com/xtls/xray-core/main/commands/base"
)
var cmdOnlineStatsIpList = &base.Command{
CustomFlags: true,
UsageLine: "{{.Exec}} api statsonlineiplist [--server=127.0.0.1:8080] [-email '']",
Short: "Retrieve a user's online IP addresses and access times",
Long: `
Retrieve the online IP addresses and corresponding access timestamps for a user from Xray.
Arguments:
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080
-t, -timeout <seconds>
Timeout in seconds for calling API. Default 3
-email
The user's email address.
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "xray@love.com"
`,
Run: executeOnlineStatsIpList,
}
func executeOnlineStatsIpList(cmd *base.Command, args []string) {
setSharedFlags(cmd)
email := cmd.Flag.String("email", "", "")
cmd.Flag.Parse(args)
statName := "user>>>" + *email + ">>>online"
conn, ctx, close := dialAPIServer()
defer close()
client := statsService.NewStatsServiceClient(conn)
r := &statsService.GetStatsRequest{
Name: statName,
Reset_: false,
}
resp, err := client.GetStatsOnlineIpList(ctx, r)
if err != nil {
base.Fatalf("failed to get stats: %s", err)
}
showJSONResponse(resp)
}

View File

@@ -11,23 +11,16 @@ var cmdQueryStats = &base.Command{
Short: "Query statistics", Short: "Query statistics",
Long: ` Long: `
Query statistics from Xray. Query statistics from Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
-pattern -pattern
Filter pattern for the statistics query. Pattern of the query.
-reset -reset
Reset the counter after fetching their values. Default false Reset the counter to fetching its value.
Example: Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -pattern "counter_" {{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -pattern "counter_"
`, `,
Run: executeQueryStats, Run: executeQueryStats,

View File

@@ -8,21 +8,14 @@ import (
var cmdSysStats = &base.Command{ var cmdSysStats = &base.Command{
CustomFlags: true, CustomFlags: true,
UsageLine: "{{.Exec}} api statssys [--server=127.0.0.1:8080]", UsageLine: "{{.Exec}} api statssys [--server=127.0.0.1:8080]",
Short: "Retrieve system statistics", Short: "Get system statistics",
Long: ` Long: `
Retrieve system statistics from Xray. Get system statistics from Xray.
Arguments: Arguments:
-s, -server
-s, -server <server:port>
The API server address. Default 127.0.0.1:8080 The API server address. Default 127.0.0.1:8080
-t, -timeout
-t, -timeout <seconds> Timeout seconds to call API. Default 3
Timeout in seconds for calling API. Default 3
Example:
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
`, `,
Run: executeSysStats, Run: executeSysStats,
} }

View File

@@ -50,17 +50,17 @@ func executeTypedMessageToJson(cmd *base.Command, args []string) {
reader, err := confloader.LoadConfig(cmd.Flag.Arg(0)) reader, err := confloader.LoadConfig(cmd.Flag.Arg(0))
if err != nil { if err != nil {
base.Fatalf("failed to load config: %s", err) base.Fatalf(err.Error())
} }
b, err := io.ReadAll(reader) b, err := io.ReadAll(reader)
if err != nil { if err != nil {
base.Fatalf("failed to read config: %s", err) base.Fatalf(err.Error())
} }
tm := cserial.TypedMessage{} tm := cserial.TypedMessage{}
if err = json.Unmarshal(b, &tm); err != nil { if err = json.Unmarshal(b, &tm); err != nil {
base.Fatalf("failed to unmarshal config: %s", err) base.Fatalf(err.Error())
} }
if j, ok := creflect.MarshalToJson(&tm, injectTypeInfo); ok { if j, ok := creflect.MarshalToJson(&tm, injectTypeInfo); ok {

View File

@@ -53,12 +53,12 @@ func executeConvertConfigsToProtobuf(cmd *base.Command, args []string) {
} }
if len(unnamedArgs) < 1 { if len(unnamedArgs) < 1 {
base.Fatalf("invalid config list length: %d", len(unnamedArgs)) base.Fatalf("empty config list")
} }
pbConfig, err := core.LoadConfig("auto", unnamedArgs) pbConfig, err := core.LoadConfig("auto", unnamedArgs)
if err != nil { if err != nil {
base.Fatalf("failed to load config: %s", err) base.Fatalf(err.Error())
} }
if optDump { if optDump {

View File

@@ -42,8 +42,7 @@ func Curve25519Genkey(StdEncoding bool, input_base64 string) {
// Modify random bytes using algorithm described at: // Modify random bytes using algorithm described at:
// https://cr.yp.to/ecdh.html. // https://cr.yp.to/ecdh.html.
privateKey[0] &= 248 privateKey[0] &= 248
privateKey[31] &= 127 privateKey[31] &= 127 | 64
privateKey[31] |= 64
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil { if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
output = err.Error() output = err.Error()

View File

@@ -120,9 +120,9 @@ func writeFile(content []byte, name string) error {
func printFile(certificate *cert.Certificate, name string) error { func printFile(certificate *cert.Certificate, name string) error {
certPEM, keyPEM := certificate.ToPEM() certPEM, keyPEM := certificate.ToPEM()
return task.Run(context.Background(), func() error { return task.Run(context.Background(), func() error {
return writeFile(certPEM, name+".crt") return writeFile(certPEM, name+"_cert.pem")
}, func() error { }, func() error {
return writeFile(keyPEM, name+".key") return writeFile(keyPEM, name+"_key.pem")
}) })
} }

View File

@@ -45,7 +45,6 @@ The -dump flag tells Xray to print the merged config.
func init() { func init() {
cmdRun.Run = executeRun // break init loop cmdRun.Run = executeRun // break init loop
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
} }
var ( var (

View File

@@ -27,7 +27,7 @@ func init() {
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) { common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
h := new(Handler) h := new(Handler)
if err := core.RequireFeatures(ctx, func(dnsClient dns.Client, policyManager policy.Manager) error { if err := core.RequireFeatures(ctx, func(dnsClient dns.Client, policyManager policy.Manager) error {
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) { core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
h.fdns = fdns h.fdns = fdns
}) })
return h.Init(config.(*Config), dnsClient, policyManager) return h.Init(config.(*Config), dnsClient, policyManager)

View File

@@ -2,7 +2,6 @@ package dokodemo
import ( import (
"context" "context"
"runtime"
"sync/atomic" "sync/atomic"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
@@ -18,7 +17,6 @@ import (
"github.com/xtls/xray-core/features/policy" "github.com/xtls/xray-core/features/policy"
"github.com/xtls/xray-core/features/routing" "github.com/xtls/xray-core/features/routing"
"github.com/xtls/xray-core/transport/internet/stat" "github.com/xtls/xray-core/transport/internet/stat"
"github.com/xtls/xray-core/transport/internet/tls"
) )
func init() { func init() {
@@ -64,6 +62,10 @@ func (d *DokodemoDoor) policy() policy.Session {
return p return p
} }
type hasHandshakeAddressContext interface {
HandshakeAddressContext(ctx context.Context) net.Address
}
// Process implements proxy.Inbound. // Process implements proxy.Inbound.
func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error { func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
errors.LogDebug(ctx, "processing connection from: ", conn.RemoteAddr()) errors.LogDebug(ctx, "processing connection from: ", conn.RemoteAddr())
@@ -83,14 +85,11 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
destinationOverridden = true destinationOverridden = true
} }
} }
if tlsConn, ok := conn.(tls.Interface); ok && !destinationOverridden { if handshake, ok := conn.(hasHandshakeAddressContext); ok && !destinationOverridden {
if serverName := tlsConn.HandshakeContextServerName(ctx); serverName != "" { addr := handshake.HandshakeAddressContext(ctx)
dest.Address = net.DomainAddress(serverName) if addr != nil {
dest.Address = addr
destinationOverridden = true destinationOverridden = true
ctx = session.ContextWithMitmServerName(ctx, serverName)
}
if tlsConn.NegotiatedProtocol() != "h2" {
ctx = session.ContextWithMitmAlpn11(ctx, true)
} }
} }
} }
@@ -148,6 +147,10 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
return nil return nil
} }
tproxyRequest := func() error {
return nil
}
var writer buf.Writer var writer buf.Writer
if network == net.Network_TCP { if network == net.Network_TCP {
writer = buf.NewWriter(conn) writer = buf.NewWriter(conn)
@@ -177,12 +180,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
return err return err
} }
writer = NewPacketWriter(pConn, &dest, mark, back) writer = NewPacketWriter(pConn, &dest, mark, back)
defer func() { defer writer.(*PacketWriter).Close()
runtime.Gosched()
common.Interrupt(link.Reader) // maybe duplicated
runtime.Gosched()
writer.(*PacketWriter).Close() // close fake UDP conns
}()
/* /*
sockopt := &internet.SocketConfig{ sockopt := &internet.SocketConfig{
Tproxy: internet.SocketConfig_TProxy, Tproxy: internet.SocketConfig_TProxy,
@@ -221,24 +219,17 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
responseDone := func() error { responseDone := func() error {
defer timer.SetTimeout(plcy.Timeouts.UplinkOnly) defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
if network == net.Network_UDP && destinationOverridden {
buf.Copy(link.Reader, writer) // respect upload's timeout
return nil
}
if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil { if err := buf.Copy(link.Reader, writer, buf.UpdateActivity(timer)); err != nil {
return errors.New("failed to transport response").Base(err) return errors.New("failed to transport response").Base(err)
} }
return nil return nil
} }
if err := task.Run(ctx, if err := task.Run(ctx, task.OnSuccess(func() error {
task.OnSuccess(func() error { return task.Run(ctx, requestDone) }, task.Close(link.Writer)), return task.Run(ctx, requestDone, tproxyRequest)
responseDone); err != nil { }, task.Close(link.Writer)), responseDone); err != nil {
runtime.Gosched()
common.Interrupt(link.Writer)
runtime.Gosched()
common.Interrupt(link.Reader) common.Interrupt(link.Reader)
common.Interrupt(link.Writer)
return errors.New("connection ends").Base(err) return errors.New("connection ends").Base(err)
} }

View File

@@ -233,7 +233,7 @@ type Noise struct {
LengthMax uint64 `protobuf:"varint,2,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"` LengthMax uint64 `protobuf:"varint,2,opt,name=length_max,json=lengthMax,proto3" json:"length_max,omitempty"`
DelayMin uint64 `protobuf:"varint,3,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,omitempty"` DelayMin uint64 `protobuf:"varint,3,opt,name=delay_min,json=delayMin,proto3" json:"delay_min,omitempty"`
DelayMax uint64 `protobuf:"varint,4,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"` DelayMax uint64 `protobuf:"varint,4,opt,name=delay_max,json=delayMax,proto3" json:"delay_max,omitempty"`
Packet []byte `protobuf:"bytes,5,opt,name=packet,proto3" json:"packet,omitempty"` StrNoise []byte `protobuf:"bytes,5,opt,name=str_noise,json=strNoise,proto3" json:"str_noise,omitempty"`
} }
func (x *Noise) Reset() { func (x *Noise) Reset() {
@@ -294,9 +294,9 @@ func (x *Noise) GetDelayMax() uint64 {
return 0 return 0
} }
func (x *Noise) GetPacket() []byte { func (x *Noise) GetStrNoise() []byte {
if x != nil { if x != nil {
return x.Packet return x.StrNoise
} }
return nil return nil
} }
@@ -412,7 +412,7 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74,
0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65,
0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x22, 0x97, 0x01, 0x0a, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x22, 0x9c, 0x01, 0x0a, 0x05,
0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f,
0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74,
0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d,
@@ -420,49 +420,49 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e,
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e,
0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20,
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a,
0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x09, 0x73, 0x74, 0x72, 0x5f, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c,
0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x73, 0x74, 0x72, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43,
0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29,
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x43, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65,
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x64, 0x6f, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69,
0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73,
0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73,
0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13, 0x64, 0x65, 0x73,
0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65,
0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65,
0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x76, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c,
0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74,
0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72,
0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67,
0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25,
0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f,
0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18,
0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06, 0x6e, 0x6f, 0x69, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65,
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x52, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d,
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41,
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12,
0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08,
0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53,
0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43,
0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49,
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x36, 0x34, 0x10, 0x0a, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01,
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x66, 0x72, 0x65, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c,
0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78,
0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x79, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79,
0x33, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (

View File

@@ -25,7 +25,7 @@ message Noise {
uint64 length_max = 2; uint64 length_max = 2;
uint64 delay_min = 3; uint64 delay_min = 3;
uint64 delay_max = 4; uint64 delay_max = 4;
bytes packet = 5; bytes str_noise = 5;
} }
message Config { message Config {

View File

@@ -4,12 +4,12 @@ import (
"context" "context"
"crypto/rand" "crypto/rand"
"io" "io"
"math/big"
"time" "time"
"github.com/pires/go-proxyproto" "github.com/pires/go-proxyproto"
"github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/buf" "github.com/xtls/xray-core/common/buf"
"github.com/xtls/xray-core/common/crypto"
"github.com/xtls/xray-core/common/dice" "github.com/xtls/xray-core/common/dice"
"github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/errors"
"github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/net"
@@ -266,9 +266,6 @@ func isTLSConn(conn stat.Connection) bool {
if _, ok := conn.(*tls.Conn); ok { if _, ok := conn.(*tls.Conn); ok {
return true return true
} }
if _, ok := conn.(*tls.UConn); ok {
return true
}
} }
return false return false
} }
@@ -410,11 +407,11 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
var err error var err error
for _, n := range w.noises { for _, n := range w.noises {
//User input string or base64 encoded string //User input string or base64 encoded string
if n.Packet != nil { if n.StrNoise != nil {
noise = n.Packet noise = n.StrNoise
} else { } else {
//Random noise //Random noise
noise, err = GenerateRandomBytes(crypto.RandBetween(int64(n.LengthMin), noise, err = GenerateRandomBytes(randBetween(int64(n.LengthMin),
int64(n.LengthMax))) int64(n.LengthMax)))
} }
if err != nil { if err != nil {
@@ -422,8 +419,8 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
} }
w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)}) w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
if n.DelayMin != 0 || n.DelayMax != 0 { if n.DelayMin != 0 {
time.Sleep(time.Duration(crypto.RandBetween(int64(n.DelayMin), int64(n.DelayMax))) * time.Millisecond) time.Sleep(time.Duration(randBetween(int64(n.DelayMin), int64(n.DelayMax))) * time.Millisecond)
} }
} }
@@ -452,7 +449,7 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
buf := make([]byte, 1024) buf := make([]byte, 1024)
var hello []byte var hello []byte
for from := 0; ; { for from := 0; ; {
to := from + int(crypto.RandBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax))) to := from + int(randBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax)))
if to > len(data) { if to > len(data) {
to = len(data) to = len(data)
} }
@@ -466,7 +463,7 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
hello = append(hello, buf[:5+l]...) hello = append(hello, buf[:5+l]...)
} else { } else {
_, err := f.writer.Write(buf[:5+l]) _, err := f.writer.Write(buf[:5+l])
time.Sleep(time.Duration(crypto.RandBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond) time.Sleep(time.Duration(randBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@@ -493,13 +490,13 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
return f.writer.Write(b) return f.writer.Write(b)
} }
for from := 0; ; { for from := 0; ; {
to := from + int(crypto.RandBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax))) to := from + int(randBetween(int64(f.fragment.LengthMin), int64(f.fragment.LengthMax)))
if to > len(b) { if to > len(b) {
to = len(b) to = len(b)
} }
n, err := f.writer.Write(b[from:to]) n, err := f.writer.Write(b[from:to])
from += n from += n
time.Sleep(time.Duration(crypto.RandBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond) time.Sleep(time.Duration(randBetween(int64(f.fragment.IntervalMin), int64(f.fragment.IntervalMax))) * time.Millisecond)
if err != nil { if err != nil {
return from, err return from, err
} }
@@ -509,6 +506,14 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
} }
} }
// stolen from github.com/xtls/xray-core/transport/internet/reality
func randBetween(left int64, right int64) int64 {
if left == right {
return left
}
bigInt, _ := rand.Int(rand.Reader, big.NewInt(right-left))
return left + bigInt.Int64()
}
func GenerateRandomBytes(n int64) ([]byte, error) { func GenerateRandomBytes(n int64) ([]byte, error) {
b := make([]byte, n) b := make([]byte, n)
_, err := rand.Read(b) _, err := rand.Read(b)

View File

@@ -151,7 +151,6 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer)) return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
} }
responseFunc := func() error { responseFunc := func() error {
ob.CanSpliceCopy = 1
defer timer.SetTimeout(p.Timeouts.UplinkOnly) defer timer.SetTimeout(p.Timeouts.UplinkOnly)
return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer)) return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
} }

Some files were not shown because too many files have changed in this diff Show More