mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-23 01:56:48 +08:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3ed502abbb |
73
.github/workflows/release-win7.yml
vendored
73
.github/workflows/release-win7.yml
vendored
@@ -1,5 +1,11 @@
|
||||
name: Build and Release for Windows 7
|
||||
|
||||
# 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:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
@@ -9,7 +15,51 @@ on:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
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:
|
||||
needs: prepare
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
@@ -31,9 +81,6 @@ jobs:
|
||||
GOARCH: ${{ matrix.goarch }}
|
||||
CGO_ENABLED: 0
|
||||
steps:
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Show workflow information
|
||||
run: |
|
||||
_NAME=${{ matrix.assetname }}
|
||||
@@ -43,17 +90,18 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
go-version: stable
|
||||
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
|
||||
rm -r $GOSDK/*
|
||||
unzip ./go-for-win7-linux-amd64.zip -d $GOSDK
|
||||
rm ./go-for-win7-linux-amd64.zip
|
||||
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get project dependencies
|
||||
run: go mod download
|
||||
@@ -61,15 +109,10 @@ jobs:
|
||||
- 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
|
||||
make
|
||||
find . -maxdepth 1 -type f -regex './\(wxray\|xray\).exe' -exec mv {} ./build_assets/ \;
|
||||
|
||||
- name: Restore Geodat Cache
|
||||
- name: Restore Cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
|
70
.github/workflows/release.yml
vendored
70
.github/workflows/release.yml
vendored
@@ -1,5 +1,11 @@
|
||||
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:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
@@ -9,7 +15,51 @@ on:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
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:
|
||||
needs: prepare
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
@@ -123,24 +173,10 @@ jobs:
|
||||
- name: Build Xray
|
||||
run: |
|
||||
mkdir -p build_assets
|
||||
COMMID=$(git describe --always --dirty)
|
||||
if [[ ${GOOS} == 'windows' ]]; then
|
||||
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
|
||||
make
|
||||
find . -maxdepth 1 -type f -regex './\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \;
|
||||
|
||||
- name: Restore Geodat Cache
|
||||
- name: Restore Cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
|
65
.github/workflows/scheduled-assets-update.yml
vendored
65
.github/workflows/scheduled-assets-update.yml
vendored
@@ -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 }}
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- name: Restore Geodat Cache
|
||||
- name: Restore Cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: resources
|
||||
|
37
Makefile
Normal file
37
Makefile
Normal 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
|
18
README.md
18
README.md
@@ -24,9 +24,7 @@
|
||||
|
||||
[Project X Channel](https://t.me/projectXtls)
|
||||
|
||||
[Project VLESS](https://t.me/projectVless) (Русский)
|
||||
|
||||
[Project XHTTP](https://t.me/projectXhttp) (Persian)
|
||||
[Project VLESS](https://t.me/projectVless) (non-Chinese)
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -74,8 +72,6 @@
|
||||
- [PassWall](https://github.com/xiaorouji/openwrt-passwall), [PassWall 2](https://github.com/xiaorouji/openwrt-passwall2)
|
||||
- [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))
|
||||
- Asuswrt-Merlin
|
||||
- [XRAYUI](https://github.com/DanielLavrushin/asuswrt-merlin-xrayui)
|
||||
- Windows
|
||||
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||
- [Furious](https://github.com/LorenEteval/Furious)
|
||||
@@ -85,7 +81,6 @@
|
||||
- [X-flutter](https://github.com/XTLS/X-flutter)
|
||||
- [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
|
||||
- iOS & macOS arm64
|
||||
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
|
||||
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
||||
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
||||
- macOS arm64 & x64
|
||||
@@ -103,7 +98,6 @@
|
||||
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
||||
- Xray Tools
|
||||
- [xray-knife](https://github.com/lilendian0x00/xray-knife)
|
||||
- [xray-checker](https://github.com/kutovoys/xray-checker)
|
||||
- Xray Wrapper
|
||||
- [XTLS/libXray](https://github.com/XTLS/libXray)
|
||||
- [xtlsapi](https://github.com/hiddify/xtlsapi)
|
||||
@@ -127,27 +121,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).
|
||||
- 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)
|
||||
|
||||
```powershell
|
||||
$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
|
||||
|
||||
```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
|
||||
|
||||
Make sure that you are using the same Go version, and remember to set the git commit id (7 bytes):
|
||||
|
||||
```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
|
||||
|
@@ -43,15 +43,11 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
||||
}
|
||||
switch {
|
||||
case strings.EqualFold(u.String(), "localhost"):
|
||||
return NewLocalNameServer(queryStrategy), nil
|
||||
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
|
||||
return NewDoHNameServer(u, queryStrategy, dispatcher, false), nil
|
||||
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
|
||||
return NewDoHNameServer(u, queryStrategy, dispatcher, true), 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
|
||||
return NewLocalNameServer(), nil
|
||||
case strings.EqualFold(u.Scheme, "https"): // DOH Remote mode
|
||||
return NewDoHNameServer(u, dispatcher, queryStrategy)
|
||||
case strings.EqualFold(u.Scheme, "https+local"): // DOH Local mode
|
||||
return NewDoHLocalNameServer(u, queryStrategy), nil
|
||||
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
||||
return NewQUICNameServer(u, queryStrategy)
|
||||
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
|
||||
|
@@ -3,18 +3,14 @@ package dns
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
utls "github.com/refraction-networking/utls"
|
||||
"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/log"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@@ -27,13 +23,13 @@ import (
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
// DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format,
|
||||
// which is compatible with traditional dns over udp(RFC1035),
|
||||
// thus most of the DOH implementation is copied from udpns.go
|
||||
type DoHNameServer struct {
|
||||
dispatcher routing.Dispatcher
|
||||
sync.RWMutex
|
||||
ips map[string]*record
|
||||
pub *pubsub.Service
|
||||
@@ -44,18 +40,93 @@ type DoHNameServer struct {
|
||||
queryStrategy QueryStrategy
|
||||
}
|
||||
|
||||
// NewDoHNameServer creates DOH/DOHL client object for remote/local resolving.
|
||||
func NewDoHNameServer(url *url.URL, queryStrategy QueryStrategy, dispatcher routing.Dispatcher, h2c bool) *DoHNameServer {
|
||||
url.Scheme = "https"
|
||||
mode := "DOH"
|
||||
if dispatcher == nil {
|
||||
mode = "DOHL"
|
||||
// NewDoHNameServer creates DOH server object for remote resolving.
|
||||
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (*DoHNameServer, error) {
|
||||
errors.LogInfo(context.Background(), "DNS: created Remote DOH client for ", url.String())
|
||||
s := baseDOHNameServer(url, "DOH", queryStrategy)
|
||||
|
||||
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{
|
||||
ips: make(map[string]*record),
|
||||
pub: pubsub.NewService(),
|
||||
name: mode + "//" + url.Host,
|
||||
name: prefix + "//" + url.Host,
|
||||
dohURL: url.String(),
|
||||
queryStrategy: queryStrategy,
|
||||
}
|
||||
@@ -63,65 +134,6 @@ func NewDoHNameServer(url *url.URL, queryStrategy QueryStrategy, dispatcher rout
|
||||
Interval: time.Minute,
|
||||
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
|
||||
}
|
||||
|
||||
@@ -281,8 +293,6 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
|
||||
req.Header.Add("Accept", "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
|
||||
|
||||
resp, err := hc.Do(req.WithContext(ctx))
|
||||
|
@@ -17,7 +17,7 @@ func TestDOHNameServer(t *testing.T) {
|
||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||
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)
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
@@ -34,7 +34,7 @@ func TestDOHNameServerWithCache(t *testing.T) {
|
||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||
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)
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
@@ -62,7 +62,7 @@ func TestDOHNameServerWithIPv4Override(t *testing.T) {
|
||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||
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)
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
@@ -85,7 +85,7 @@ func TestDOHNameServerWithIPv6Override(t *testing.T) {
|
||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||
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)
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
|
@@ -14,19 +14,13 @@ import (
|
||||
|
||||
// LocalNameServer is an wrapper over local DNS feature.
|
||||
type LocalNameServer struct {
|
||||
client *localdns.Client
|
||||
queryStrategy QueryStrategy
|
||||
client *localdns.Client
|
||||
}
|
||||
|
||||
const errEmptyResponse = "No address associated with hostname"
|
||||
|
||||
// QueryIP implements Server.
|
||||
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()
|
||||
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.
|
||||
func NewLocalNameServer(queryStrategy QueryStrategy) *LocalNameServer {
|
||||
func NewLocalNameServer() *LocalNameServer {
|
||||
errors.LogInfo(context.Background(), "DNS: created localhost client")
|
||||
return &LocalNameServer{
|
||||
queryStrategy: queryStrategy,
|
||||
client: localdns.New(),
|
||||
client: localdns.New(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
|
||||
func NewLocalDNSClient() *Client {
|
||||
return &Client{server: NewLocalNameServer(QueryStrategy_USE_IP)}
|
||||
return &Client{server: NewLocalNameServer()}
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func TestLocalNameServer(t *testing.T) {
|
||||
s := NewLocalNameServer(QueryStrategy_USE_IP)
|
||||
s := NewLocalNameServer()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/quic-go/quic-go"
|
||||
"github.com/xtls/quic-go"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
|
@@ -27,8 +27,7 @@ type Config struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// Tag of the outbound handler that handles metrics http connections.
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
Listen string `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
@@ -68,28 +67,20 @@ func (x *Config) GetTag() string {
|
||||
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_rawDesc = []byte{
|
||||
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,
|
||||
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,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74,
|
||||
0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e,
|
||||
0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x50, 0x01, 0x5a, 0x25, 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, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
|
||||
0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4d, 0x65, 0x74,
|
||||
0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x42, 0x52, 0x0a, 0x14, 0x63, 0x6f, 0x6d, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
|
||||
0x50, 0x01, 0x5a, 0x25, 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, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0xaa, 0x02, 0x10, 0x58, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -10,5 +10,4 @@ option java_multiple_files = true;
|
||||
message Config {
|
||||
// Tag of the outbound handler that handles metrics http connections.
|
||||
string tag = 1;
|
||||
string listen = 2;
|
||||
}
|
||||
|
@@ -24,15 +24,12 @@ type MetricsHandler struct {
|
||||
statsManager feature_stats.Manager
|
||||
observatory extension.Observatory
|
||||
tag string
|
||||
listen string
|
||||
tcpListener net.Listener
|
||||
}
|
||||
|
||||
// NewMetricsHandler creates a new MetricsHandler based on the given config.
|
||||
func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHandler, error) {
|
||||
c := &MetricsHandler{
|
||||
tag: config.Tag,
|
||||
listen: config.Listen,
|
||||
tag: config.Tag,
|
||||
}
|
||||
common.Must(core.RequireFeatures(ctx, func(om outbound.Manager, sm feature_stats.Manager) {
|
||||
c.statsManager = sm
|
||||
@@ -90,23 +87,6 @@ func (p *MetricsHandler) Type() interface{} {
|
||||
}
|
||||
|
||||
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{
|
||||
buffer: make(chan net.Conn, 4),
|
||||
done: done.New(),
|
||||
|
@@ -66,10 +66,10 @@ func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *H
|
||||
settings.Timeout = time.Duration(5) * time.Second
|
||||
}
|
||||
return &HealthPing{
|
||||
ctx: ctx,
|
||||
ctx: ctx,
|
||||
dispatcher: dispatcher,
|
||||
Settings: settings,
|
||||
Results: nil,
|
||||
Settings: settings,
|
||||
Results: nil,
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -32,7 +32,7 @@ type Observer struct {
|
||||
|
||||
finished *done.Instance
|
||||
|
||||
ohm outbound.Manager
|
||||
ohm outbound.Manager
|
||||
dispatcher routing.Dispatcher
|
||||
}
|
||||
|
||||
@@ -226,9 +226,9 @@ func New(ctx context.Context, config *Config) (*Observer, error) {
|
||||
return nil, errors.New("Cannot get depended features").Base(err)
|
||||
}
|
||||
return &Observer{
|
||||
config: config,
|
||||
ctx: ctx,
|
||||
ohm: outboundManager,
|
||||
config: config,
|
||||
ctx: ctx,
|
||||
ohm: outboundManager,
|
||||
dispatcher: dispatcher,
|
||||
}, nil
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ type DynamicInboundHandler struct {
|
||||
receiverConfig *proxyman.ReceiverConfig
|
||||
streamSettings *internet.MemoryStreamConfig
|
||||
portMutex sync.Mutex
|
||||
portsInUse map[net.Port]struct{}
|
||||
portsInUse map[net.Port]bool
|
||||
workerMutex sync.RWMutex
|
||||
worker []worker
|
||||
lastRefresh time.Time
|
||||
@@ -39,7 +39,7 @@ func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *p
|
||||
tag: tag,
|
||||
proxyConfig: proxyConfig,
|
||||
receiverConfig: receiverConfig,
|
||||
portsInUse: make(map[net.Port]struct{}),
|
||||
portsInUse: make(map[net.Port]bool),
|
||||
mux: mux.NewServer(ctx),
|
||||
v: v,
|
||||
ctx: ctx,
|
||||
@@ -84,7 +84,7 @@ func (h *DynamicInboundHandler) allocatePort() net.Port {
|
||||
port := net.Port(allPorts[r])
|
||||
_, used := h.portsInUse[port]
|
||||
if !used {
|
||||
h.portsInUse[port] = struct{}{}
|
||||
h.portsInUse[port] = true
|
||||
return port
|
||||
}
|
||||
}
|
||||
|
@@ -324,7 +324,6 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||
if w.sniffingConfig != nil {
|
||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
||||
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
|
||||
}
|
||||
@@ -465,7 +464,8 @@ func (w *dsWorker) callback(conn stat.Connection) {
|
||||
}
|
||||
}
|
||||
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),
|
||||
Tag: w.tag,
|
||||
Conn: conn,
|
||||
|
@@ -273,16 +273,7 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds)-1]
|
||||
if h.senderSettings.ViaCidr == "" {
|
||||
if h.senderSettings.Via.AsAddress().Family().IsDomain() && h.senderSettings.Via.AsAddress().Domain() == "origin" {
|
||||
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()
|
||||
}
|
||||
ob.Gateway = h.senderSettings.Via.AsAddress()
|
||||
} else { //Get a random address.
|
||||
ob.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr)
|
||||
}
|
||||
|
@@ -60,24 +60,6 @@ func (s *statsServer) GetStatsOnline(ctx context.Context, request *GetStatsReque
|
||||
}, 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) {
|
||||
matcher, err := strmatcher.Substr.New(request.Pattern)
|
||||
if err != nil {
|
||||
|
@@ -424,59 +424,6 @@ func (x *SysStatsResponse) GetUptime() uint32 {
|
||||
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 {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -485,7 +432,7 @@ type Config struct {
|
||||
|
||||
func (x *Config) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -497,7 +444,7 @@ func (x *Config) String() string {
|
||||
func (*Config) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -510,7 +457,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||
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
|
||||
@@ -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,
|
||||
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,
|
||||
0x69, 0x6d, 0x65, 0x22, 0xbb, 0x01, 0x0a, 0x1c, 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, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
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,
|
||||
0x69, 0x6d, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xa1, 0x03,
|
||||
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, 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,
|
||||
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,
|
||||
0x77, 0x0a, 0x14, 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,
|
||||
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, 0x34, 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, 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,
|
||||
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, 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 (
|
||||
@@ -627,38 +554,33 @@ func file_app_stats_command_command_proto_rawDescGZIP() []byte {
|
||||
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{
|
||||
(*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest
|
||||
(*Stat)(nil), // 1: xray.app.stats.command.Stat
|
||||
(*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse
|
||||
(*QueryStatsRequest)(nil), // 3: xray.app.stats.command.QueryStatsRequest
|
||||
(*QueryStatsResponse)(nil), // 4: xray.app.stats.command.QueryStatsResponse
|
||||
(*SysStatsRequest)(nil), // 5: xray.app.stats.command.SysStatsRequest
|
||||
(*SysStatsResponse)(nil), // 6: xray.app.stats.command.SysStatsResponse
|
||||
(*GetStatsOnlineIpListResponse)(nil), // 7: xray.app.stats.command.GetStatsOnlineIpListResponse
|
||||
(*Config)(nil), // 8: xray.app.stats.command.Config
|
||||
nil, // 9: xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
|
||||
(*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest
|
||||
(*Stat)(nil), // 1: xray.app.stats.command.Stat
|
||||
(*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse
|
||||
(*QueryStatsRequest)(nil), // 3: xray.app.stats.command.QueryStatsRequest
|
||||
(*QueryStatsResponse)(nil), // 4: xray.app.stats.command.QueryStatsResponse
|
||||
(*SysStatsRequest)(nil), // 5: xray.app.stats.command.SysStatsRequest
|
||||
(*SysStatsResponse)(nil), // 6: xray.app.stats.command.SysStatsResponse
|
||||
(*Config)(nil), // 7: xray.app.stats.command.Config
|
||||
}
|
||||
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, // 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, // 3: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest
|
||||
0, // 4: xray.app.stats.command.StatsService.GetStatsOnline:input_type -> xray.app.stats.command.GetStatsRequest
|
||||
3, // 5: xray.app.stats.command.StatsService.QueryStats:input_type -> xray.app.stats.command.QueryStatsRequest
|
||||
5, // 6: xray.app.stats.command.StatsService.GetSysStats:input_type -> xray.app.stats.command.SysStatsRequest
|
||||
0, // 7: xray.app.stats.command.StatsService.GetStatsOnlineIpList:input_type -> xray.app.stats.command.GetStatsRequest
|
||||
2, // 8: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse
|
||||
2, // 9: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse
|
||||
4, // 10: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse
|
||||
6, // 11: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse
|
||||
7, // 12: xray.app.stats.command.StatsService.GetStatsOnlineIpList:output_type -> xray.app.stats.command.GetStatsOnlineIpListResponse
|
||||
8, // [8:13] is the sub-list for method output_type
|
||||
3, // [3:8] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
0, // 2: 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
|
||||
3, // 4: 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
|
||||
2, // 6: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse
|
||||
2, // 7: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse
|
||||
4, // 8: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse
|
||||
6, // 9: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse
|
||||
6, // [6:10] is the sub-list for method output_type
|
||||
2, // [2:6] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_app_stats_command_command_proto_init() }
|
||||
@@ -672,7 +594,7 @@ func file_app_stats_command_command_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_app_stats_command_command_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 10,
|
||||
NumMessages: 8,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
@@ -46,17 +46,11 @@ message SysStatsResponse {
|
||||
uint32 Uptime = 10;
|
||||
}
|
||||
|
||||
message GetStatsOnlineIpListResponse {
|
||||
string name = 1;
|
||||
map<string, int64> ips = 2;
|
||||
}
|
||||
|
||||
service StatsService {
|
||||
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
|
||||
rpc GetStatsOnline(GetStatsRequest) returns (GetStatsResponse) {}
|
||||
rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {}
|
||||
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
|
||||
rpc GetStatsOnlineIpList(GetStatsRequest) returns (GetStatsOnlineIpListResponse) {}
|
||||
}
|
||||
|
||||
message Config {}
|
||||
|
@@ -19,11 +19,10 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
StatsService_GetStats_FullMethodName = "/xray.app.stats.command.StatsService/GetStats"
|
||||
StatsService_GetStatsOnline_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnline"
|
||||
StatsService_QueryStats_FullMethodName = "/xray.app.stats.command.StatsService/QueryStats"
|
||||
StatsService_GetSysStats_FullMethodName = "/xray.app.stats.command.StatsService/GetSysStats"
|
||||
StatsService_GetStatsOnlineIpList_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnlineIpList"
|
||||
StatsService_GetStats_FullMethodName = "/xray.app.stats.command.StatsService/GetStats"
|
||||
StatsService_GetStatsOnline_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnline"
|
||||
StatsService_QueryStats_FullMethodName = "/xray.app.stats.command.StatsService/QueryStats"
|
||||
StatsService_GetSysStats_FullMethodName = "/xray.app.stats.command.StatsService/GetSysStats"
|
||||
)
|
||||
|
||||
// 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)
|
||||
QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, 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 {
|
||||
@@ -85,16 +83,6 @@ func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsReques
|
||||
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.
|
||||
// All implementations must embed UnimplementedStatsServiceServer
|
||||
// for forward compatibility.
|
||||
@@ -103,7 +91,6 @@ type StatsServiceServer interface {
|
||||
GetStatsOnline(context.Context, *GetStatsRequest) (*GetStatsResponse, error)
|
||||
QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error)
|
||||
GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error)
|
||||
GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error)
|
||||
mustEmbedUnimplementedStatsServiceServer()
|
||||
}
|
||||
|
||||
@@ -126,9 +113,6 @@ func (UnimplementedStatsServiceServer) QueryStats(context.Context, *QueryStatsRe
|
||||
func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error) {
|
||||
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) testEmbeddedByValue() {}
|
||||
|
||||
@@ -222,24 +206,6 @@ func _StatsService_GetSysStats_Handler(srv interface{}, ctx context.Context, dec
|
||||
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.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -263,10 +229,6 @@ var StatsService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "GetSysStats",
|
||||
Handler: _StatsService_GetSysStats_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetStatsOnlineIpList",
|
||||
Handler: _StatsService_GetStatsOnlineIpList_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "app/stats/command/command.proto",
|
||||
|
@@ -35,56 +35,37 @@ func (c *OnlineMap) List() []string {
|
||||
|
||||
// AddIP implements stats.OnlineMap.
|
||||
func (c *OnlineMap) AddIP(ip string) {
|
||||
list := c.ipList
|
||||
|
||||
if ip == "127.0.0.1" {
|
||||
return
|
||||
}
|
||||
if _, ok := list[ip]; !ok {
|
||||
c.access.Lock()
|
||||
list[ip] = time.Now()
|
||||
c.access.Unlock()
|
||||
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
|
||||
if _, ok := c.ipList[ip]; !ok {
|
||||
c.ipList[ip] = time.Now()
|
||||
}
|
||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
||||
list = c.RemoveExpiredIPs(list)
|
||||
now := time.Now()
|
||||
for k, t := range c.ipList {
|
||||
diff := now.Sub(t)
|
||||
if diff.Seconds() > 20 {
|
||||
delete(c.ipList, k) // safe to do delete in range
|
||||
}
|
||||
}
|
||||
c.lastCleanup = time.Now()
|
||||
}
|
||||
|
||||
c.value = len(list)
|
||||
c.ipList = list
|
||||
c.value = len(c.ipList)
|
||||
}
|
||||
|
||||
func (c *OnlineMap) GetKeys() []string {
|
||||
c.access.RLock()
|
||||
defer c.access.RUnlock()
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
|
||||
keys := []string{}
|
||||
for k := range c.ipList {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.Time {
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
for k, t := range list {
|
||||
diff := now.Sub(t)
|
||||
if diff.Seconds() > 20 {
|
||||
delete(list, k)
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
@@ -1,15 +1,2 @@
|
||||
// Package crypto provides common crypto libraries for Xray.
|
||||
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()
|
||||
}
|
||||
|
@@ -146,7 +146,7 @@ func (w *fileLogWriter) Close() error {
|
||||
func CreateStdoutLogWriter() WriterCreator {
|
||||
return func() Writer {
|
||||
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 {
|
||||
return func() Writer {
|
||||
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{
|
||||
file: file,
|
||||
logger: log.New(file, "", log.Ldate|log.Ltime|log.Lmicroseconds),
|
||||
logger: log.New(file, "", log.Ldate|log.Ltime),
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
@@ -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 {
|
||||
// deep-clone outbounds because it is going to be mutated concurrently
|
||||
// (Target and OriginalTarget)
|
||||
ctx = session.ContextCloneOutboundsAndContent(ctx)
|
||||
ctx = session.ContextCloneOutbounds(ctx)
|
||||
errors.LogInfo(ctx, "received request for ", meta.Target)
|
||||
{
|
||||
msg := &log.AccessMessage{
|
||||
|
@@ -89,10 +89,12 @@ func UnixDestination(address Address) Destination {
|
||||
// NetAddr returns the network address in this Destination in string form.
|
||||
func (d Destination) NetAddr() string {
|
||||
addr := ""
|
||||
if d.Network == Network_TCP || d.Network == Network_UDP {
|
||||
addr = d.Address.String() + ":" + d.Port.String()
|
||||
} else if d.Network == Network_UNIX {
|
||||
addr = d.Address.String()
|
||||
if d.Address != nil {
|
||||
if d.Network == Network_TCP || d.Network == Network_UDP {
|
||||
addr = d.Address.String() + ":" + d.Port.String()
|
||||
} else if d.Network == Network_UNIX {
|
||||
addr = d.Address.String()
|
||||
}
|
||||
}
|
||||
return addr
|
||||
}
|
||||
|
@@ -1,14 +1,2 @@
|
||||
// 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"
|
||||
|
||||
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
|
||||
|
@@ -76,9 +76,8 @@ type (
|
||||
)
|
||||
|
||||
var (
|
||||
ResolveTCPAddr = net.ResolveTCPAddr
|
||||
ResolveUDPAddr = net.ResolveUDPAddr
|
||||
ResolveUnixAddr = net.ResolveUnixAddr
|
||||
ResolveUDPAddr = net.ResolveUDPAddr
|
||||
)
|
||||
|
||||
type Resolver = net.Resolver
|
||||
|
@@ -63,7 +63,7 @@ func SniffHTTP(b []byte, c context.Context) (*SniffHeader, error) {
|
||||
ShouldSniffAttr := true
|
||||
// If content.Attributes have information, that means it comes from HTTP inbound PlainHTTP mode.
|
||||
// It will set attributes, so skip it.
|
||||
if content == nil || len(content.Attributes) != 0 {
|
||||
if content == nil || content.AttributeLen() != 0 {
|
||||
ShouldSniffAttr = false
|
||||
}
|
||||
if err := beginWithHTTPMethod(b); err != nil {
|
||||
|
@@ -8,7 +8,7 @@ import (
|
||||
"encoding/binary"
|
||||
"io"
|
||||
|
||||
"github.com/quic-go/quic-go/quicvarint"
|
||||
"github.com/xtls/quic-go/quicvarint"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/bytespool"
|
||||
|
3
common/protocol/tls/cert/.gitignore
vendored
3
common/protocol/tls/cert/.gitignore
vendored
@@ -1,2 +1 @@
|
||||
*.crt
|
||||
*.key
|
||||
*.pem
|
@@ -78,9 +78,9 @@ func printJSON(certificate *Certificate) {
|
||||
func printFile(certificate *Certificate, name string) error {
|
||||
certPEM, keyPEM := certificate.ToPEM()
|
||||
return task.Run(context.Background(), func() error {
|
||||
return writeFile(certPEM, name+".crt")
|
||||
return writeFile(certPEM, name+"_cert.pem")
|
||||
}, func() error {
|
||||
return writeFile(keyPEM, name+".key")
|
||||
return writeFile(keyPEM, name+"_key.pem")
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
cnet "github.com/xtls/xray-core/common/net"
|
||||
@@ -31,9 +32,6 @@ func JSONMarshalWithoutEscape(t interface{}) ([]byte, error) {
|
||||
}
|
||||
|
||||
func marshalTypedMessage(v *cserial.TypedMessage, ignoreNullValue bool, insertTypeInfo bool) interface{} {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
tmsg, err := v.GetInstance()
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -58,9 +56,7 @@ func marshalSlice(v reflect.Value, ignoreNullValue bool, insertTypeInfo bool) in
|
||||
}
|
||||
|
||||
func isNullValue(f reflect.StructField, rv reflect.Value) bool {
|
||||
if rv.Kind() == reflect.Struct {
|
||||
return false
|
||||
} else if rv.Kind() == reflect.String && rv.Len() == 0 {
|
||||
if rv.Kind() == reflect.String && rv.Len() == 0 {
|
||||
return true
|
||||
} else if !isValueKind(rv.Kind()) && rv.IsNil() {
|
||||
return true
|
||||
@@ -186,12 +182,6 @@ func marshalKnownType(v interface{}, ignoreNullValue bool, insertTypeInfo bool)
|
||||
case *conf.PortList:
|
||||
cpl := v.(*conf.PortList)
|
||||
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:
|
||||
if addr := v.(cnet.Address); addr != nil {
|
||||
return addr.String(), true
|
||||
@@ -202,29 +192,28 @@ func marshalKnownType(v interface{}, ignoreNullValue bool, insertTypeInfo bool)
|
||||
}
|
||||
}
|
||||
|
||||
var valueKinds = []reflect.Kind{
|
||||
reflect.Bool,
|
||||
reflect.Int,
|
||||
reflect.Int8,
|
||||
reflect.Int16,
|
||||
reflect.Int32,
|
||||
reflect.Int64,
|
||||
reflect.Uint,
|
||||
reflect.Uint8,
|
||||
reflect.Uint16,
|
||||
reflect.Uint32,
|
||||
reflect.Uint64,
|
||||
reflect.Uintptr,
|
||||
reflect.Float32,
|
||||
reflect.Float64,
|
||||
reflect.Complex64,
|
||||
reflect.Complex128,
|
||||
reflect.String,
|
||||
}
|
||||
|
||||
func isValueKind(kind reflect.Kind) bool {
|
||||
switch kind {
|
||||
case reflect.Bool,
|
||||
reflect.Int,
|
||||
reflect.Int8,
|
||||
reflect.Int16,
|
||||
reflect.Int32,
|
||||
reflect.Int64,
|
||||
reflect.Uint,
|
||||
reflect.Uint8,
|
||||
reflect.Uint16,
|
||||
reflect.Uint32,
|
||||
reflect.Uint64,
|
||||
reflect.Uintptr,
|
||||
reflect.Float32,
|
||||
reflect.Float64,
|
||||
reflect.Complex64,
|
||||
reflect.Complex128,
|
||||
reflect.String:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return slices.Contains(valueKinds, kind)
|
||||
}
|
||||
|
||||
func marshalInterface(v interface{}, ignoreNullValue bool, insertTypeInfo bool) interface{} {
|
||||
|
@@ -116,129 +116,98 @@ func TestMarshalConfigJson(t *testing.T) {
|
||||
"system",
|
||||
"inboundDownlink",
|
||||
"outboundUplink",
|
||||
"XHTTP_IN",
|
||||
"\"host\": \"bing.com\"",
|
||||
"scMaxEachPostBytes",
|
||||
"\"from\": 100",
|
||||
"\"to\": 1000",
|
||||
"\"from\": 1000000",
|
||||
"\"to\": 1000000",
|
||||
}
|
||||
for _, kw := range keywords {
|
||||
if !strings.Contains(tc, kw) {
|
||||
t.Log("config.json:", tc)
|
||||
t.Error("keyword not found:", kw)
|
||||
break
|
||||
t.Error("marshaled config error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getConfig() string {
|
||||
return `{
|
||||
"log": {
|
||||
"loglevel": "debug"
|
||||
},
|
||||
"stats": {},
|
||||
"policy": {
|
||||
"levels": {
|
||||
"0": {
|
||||
"statsUserUplink": true,
|
||||
"statsUserDownlink": true
|
||||
}
|
||||
},
|
||||
"system": {
|
||||
"statsInboundUplink": true,
|
||||
"statsInboundDownlink": true,
|
||||
"statsOutboundUplink": true,
|
||||
"statsOutboundDownlink": true
|
||||
}
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "agentin",
|
||||
"protocol": "http",
|
||||
"port": 18080,
|
||||
"listen": "127.0.0.1",
|
||||
"settings": {}
|
||||
},
|
||||
{
|
||||
"listen": "127.0.0.1",
|
||||
"port": 10085,
|
||||
"protocol": "dokodemo-door",
|
||||
"settings": {
|
||||
"address": "127.0.0.1"
|
||||
},
|
||||
"tag": "api-in"
|
||||
}
|
||||
],
|
||||
"api": {
|
||||
"tag": "api",
|
||||
"services": [
|
||||
"HandlerService",
|
||||
"StatsService"
|
||||
]
|
||||
},
|
||||
"routing": {
|
||||
"rules": [
|
||||
{
|
||||
"inboundTag": [
|
||||
"api-in"
|
||||
],
|
||||
"outboundTag": "api",
|
||||
"type": "field"
|
||||
}
|
||||
],
|
||||
"domainStrategy": "AsIs"
|
||||
},
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "1.2.3.4",
|
||||
"port": 1234,
|
||||
"users": [
|
||||
{
|
||||
"id": "4784f9b8-a879-4fec-9718-ebddefa47750",
|
||||
"encryption": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"tag": "XHTTP_IN",
|
||||
"streamSettings": {
|
||||
"network": "xhttp",
|
||||
"xhttpSettings": {
|
||||
"host": "bing.com",
|
||||
"path": "/xhttp_client_upload",
|
||||
"mode": "auto",
|
||||
"extra": {
|
||||
"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
|
||||
}
|
||||
}
|
||||
]
|
||||
}`
|
||||
"log": {
|
||||
"loglevel": "debug"
|
||||
},
|
||||
"stats": {},
|
||||
"policy": {
|
||||
"levels": {
|
||||
"0": {
|
||||
"statsUserUplink": true,
|
||||
"statsUserDownlink": true
|
||||
}
|
||||
},
|
||||
"system": {
|
||||
"statsInboundUplink": true,
|
||||
"statsInboundDownlink": true,
|
||||
"statsOutboundUplink": true,
|
||||
"statsOutboundDownlink": true
|
||||
}
|
||||
},
|
||||
"inbounds": [
|
||||
{
|
||||
"tag": "agentin",
|
||||
"protocol": "http",
|
||||
"port": 8080,
|
||||
"listen": "127.0.0.1",
|
||||
"settings": {}
|
||||
},
|
||||
{
|
||||
"listen": "127.0.0.1",
|
||||
"port": 10085,
|
||||
"protocol": "dokodemo-door",
|
||||
"settings": {
|
||||
"address": "127.0.0.1"
|
||||
},
|
||||
"tag": "api-in"
|
||||
}
|
||||
],
|
||||
"api": {
|
||||
"tag": "api",
|
||||
"services": [
|
||||
"HandlerService",
|
||||
"StatsService"
|
||||
]
|
||||
},
|
||||
"routing": {
|
||||
"rules": [
|
||||
{
|
||||
"inboundTag": [
|
||||
"api-in"
|
||||
],
|
||||
"outboundTag": "api",
|
||||
"type": "field"
|
||||
}
|
||||
],
|
||||
"domainStrategy": "AsIs"
|
||||
},
|
||||
"outbounds": [
|
||||
{
|
||||
"protocol": "vless",
|
||||
"settings": {
|
||||
"vnext": [
|
||||
{
|
||||
"address": "1.2.3.4",
|
||||
"port": 1234,
|
||||
"users": [
|
||||
{
|
||||
"id": "4784f9b8-a879-4fec-9718-ebddefa47750",
|
||||
"encryption": "none"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"tag": "agentout",
|
||||
"streamSettings": {
|
||||
"network": "ws",
|
||||
"security": "none",
|
||||
"wsSettings": {
|
||||
"path": "/?ed=2048",
|
||||
"host": "bing.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}`
|
||||
}
|
||||
|
@@ -23,8 +23,6 @@ const (
|
||||
timeoutOnlyKey ctx.SessionKey = 8
|
||||
allowedNetworkKey ctx.SessionKey = 9
|
||||
handlerSessionKey ctx.SessionKey = 10
|
||||
mitmAlpn11Key ctx.SessionKey = 11
|
||||
mitmServerNameKey ctx.SessionKey = 12
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func ContextCloneOutboundsAndContent(ctx context.Context) context.Context {
|
||||
func ContextCloneOutbounds(ctx context.Context) context.Context {
|
||||
outbounds := OutboundsFromContext(ctx)
|
||||
newOutbounds := make([]*Outbound, len(outbounds))
|
||||
for i, ob := range outbounds {
|
||||
@@ -55,15 +53,7 @@ func ContextCloneOutboundsAndContent(ctx context.Context) context.Context {
|
||||
newOutbounds[i] = &v
|
||||
}
|
||||
|
||||
content := ContentFromContext(ctx)
|
||||
newContent := Content{}
|
||||
if content != nil {
|
||||
newContent = *content
|
||||
if content.Attributes != nil {
|
||||
panic("content.Attributes != nil")
|
||||
}
|
||||
}
|
||||
return ContextWithContent(ContextWithOutbounds(ctx, newOutbounds), &newContent)
|
||||
return ContextWithOutbounds(ctx, newOutbounds)
|
||||
}
|
||||
|
||||
func OutboundsFromContext(ctx context.Context) []*Outbound {
|
||||
@@ -172,25 +162,3 @@ func AllowedNetworkFromContext(ctx context.Context) net.Network {
|
||||
}
|
||||
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 ""
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ package session // import "github.com/xtls/xray-core/common/session"
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"sync"
|
||||
|
||||
c "github.com/xtls/xray-core/common/ctx"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
@@ -74,8 +75,8 @@ type Outbound struct {
|
||||
|
||||
// SniffingRequest controls the behavior of content sniffing.
|
||||
type SniffingRequest struct {
|
||||
ExcludeForDomain []string // read-only once set
|
||||
OverrideDestinationForProtocol []string // read-only once set
|
||||
ExcludeForDomain []string
|
||||
OverrideDestinationForProtocol []string
|
||||
Enabled bool
|
||||
MetadataOnly bool
|
||||
RouteOnly bool
|
||||
@@ -91,6 +92,10 @@ type Content struct {
|
||||
Attributes map[string]string
|
||||
|
||||
SkipDNSResolve bool
|
||||
|
||||
mu sync.Mutex
|
||||
|
||||
isLocked bool
|
||||
}
|
||||
|
||||
// Sockopt is the settings for socket connection.
|
||||
@@ -99,8 +104,22 @@ type Sockopt struct {
|
||||
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.
|
||||
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 {
|
||||
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.
|
||||
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 {
|
||||
return ""
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
@@ -18,8 +18,8 @@ import (
|
||||
|
||||
var (
|
||||
Version_x byte = 25
|
||||
Version_y byte = 3
|
||||
Version_z byte = 6
|
||||
Version_y byte = 1
|
||||
Version_z byte = 1
|
||||
)
|
||||
|
||||
var (
|
||||
|
@@ -359,7 +359,7 @@ func (s *Instance) AddFeature(feature features.Feature) error {
|
||||
}
|
||||
s.pendingOptionalResolutions = pendingOptional
|
||||
s.resolveLock.Unlock()
|
||||
|
||||
|
||||
var err error
|
||||
for _, r := range availableResolution {
|
||||
err = r.callbackResolution(s.features) // only return the last error for now
|
||||
|
@@ -25,7 +25,7 @@ type Handler interface {
|
||||
// xray:api:stable
|
||||
type Manager interface {
|
||||
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)
|
||||
// AddHandler adds the given handler into this Manager.
|
||||
AddHandler(ctx context.Context, handler Handler) error
|
||||
|
@@ -11,7 +11,7 @@ type Context interface {
|
||||
// GetInboundTag returns the tag of the inbound the connection was from.
|
||||
GetInboundTag() string
|
||||
|
||||
// GetSourceIPs returns the source IPs bound to the connection.
|
||||
// GetSourcesIPs returns the source IPs bound to the connection.
|
||||
GetSourceIPs() []net.IP
|
||||
|
||||
// GetSourcePort returns the source port of the connection.
|
||||
|
@@ -2,7 +2,6 @@ package stats
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
@@ -31,8 +30,6 @@ type OnlineMap interface {
|
||||
AddIP(string)
|
||||
// List is the current OnlineMap ip list.
|
||||
List() []string
|
||||
// IpTimeMap return client ips and their last access time.
|
||||
IpTimeMap() map[string]time.Time
|
||||
}
|
||||
|
||||
// Channel is the interface for stats channel.
|
||||
|
38
go.mod
38
go.mod
@@ -1,18 +1,17 @@
|
||||
module github.com/xtls/xray-core
|
||||
|
||||
go 1.24
|
||||
go 1.23
|
||||
|
||||
require (
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0
|
||||
github.com/cloudflare/circl v1.6.0
|
||||
github.com/cloudflare/circl v1.5.0
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
||||
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/miekg/dns v1.1.63
|
||||
github.com/miekg/dns v1.1.62
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pires/go-proxyproto v0.8.0
|
||||
github.com/quic-go/quic-go v0.50.0
|
||||
github.com/refraction-networking/utls v1.6.7
|
||||
github.com/sagernet/sing v0.5.1
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||
@@ -20,18 +19,19 @@ require (
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
github.com/xtls/quic-go v0.48.2
|
||||
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.36.0
|
||||
golang.org/x/net v0.37.0
|
||||
golang.org/x/sync v0.12.0
|
||||
golang.org/x/sys v0.31.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/net v0.33.0
|
||||
golang.org/x/sync v0.10.0
|
||||
golang.org/x/sys v0.28.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
google.golang.org/grpc v1.71.0
|
||||
google.golang.org/protobuf v1.36.5
|
||||
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0
|
||||
google.golang.org/grpc v1.69.2
|
||||
google.golang.org/protobuf v1.36.1
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489
|
||||
h12.io/socks v1.0.3
|
||||
lukechampine.com/blake3 v1.4.0
|
||||
lukechampine.com/blake3 v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -48,14 +48,14 @@ require (
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // 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/mod v0.21.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // 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-20241015192408-796eee8c2d53 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
94
go.sum
94
go.sum
@@ -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/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
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.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/cloudflare/circl v1.5.0 h1:hxIWksrX6XN5a1L2TI/h53AGPhNHoUBo+TD1ms9+pys=
|
||||
github.com/cloudflare/circl v1.5.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -24,8 +24,8 @@ 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/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
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/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
@@ -38,8 +38,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/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
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.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
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/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
@@ -54,8 +54,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
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.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo=
|
||||
github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
|
||||
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/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||
@@ -76,43 +74,43 @@ github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQ
|
||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/xtls/quic-go v0.48.2 h1:59Gs+E9qtc9s0uniXYDA649gNEZlMWcNpFLyp9jfkuE=
|
||||
github.com/xtls/quic-go v0.48.2/go.mod h1:rcyY5J0JT+1d5pa5Y+FbCsXM7Zu79jE87ZSFOBfiH7Q=
|
||||
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/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
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=
|
||||
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
||||
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
|
||||
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
|
||||
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
|
||||
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
|
||||
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
|
||||
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
|
||||
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
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=
|
||||
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.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
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/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
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-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.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
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.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -121,21 +119,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.5.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.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
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.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.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -143,12 +141,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/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||
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-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
|
||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53 h1:X58yt85/IXCx0Y3ZwN6sEIKZzQtDEYaBWrDvErdXrRE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241015192408-796eee8c2d53/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||
google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
|
||||
google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -158,9 +156,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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
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-20240320123526-dc6abceb7ff0/go.mod h1:NQHVAzMwvZ+Qe3ElSiHmq9RUm1MdNHpUZ52fiEqvn+0=
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE=
|
||||
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/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
|
||||
lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w=
|
||||
lukechampine.com/blake3 v1.4.0/go.mod h1:MQJNQCTnR+kwOP/JEZSxj3MaQjp80FOFSNMMHXcSeX0=
|
||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||
|
@@ -203,24 +203,6 @@ func (list *PortList) Build() *net.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
|
||||
func (list *PortList) UnmarshalJSON(data []byte) error {
|
||||
var listStr string
|
||||
|
@@ -12,13 +12,13 @@ import (
|
||||
)
|
||||
|
||||
type NameServerConfig struct {
|
||||
Address *Address `json:"address"`
|
||||
ClientIP *Address `json:"clientIp"`
|
||||
Port uint16 `json:"port"`
|
||||
SkipFallback bool `json:"skipFallback"`
|
||||
Domains []string `json:"domains"`
|
||||
ExpectIPs StringList `json:"expectIps"`
|
||||
QueryStrategy string `json:"queryStrategy"`
|
||||
Address *Address
|
||||
ClientIP *Address
|
||||
Port uint16
|
||||
SkipFallback bool
|
||||
Domains []string
|
||||
ExpectIPs StringList
|
||||
QueryStrategy string
|
||||
}
|
||||
|
||||
func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
||||
|
@@ -2,7 +2,6 @@ package conf
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
@@ -153,9 +152,8 @@ func (c *FreedomConfig) Build() (proto.Message, error) {
|
||||
func ParseNoise(noise *Noise) (*freedom.Noise, error) {
|
||||
var err error
|
||||
NConfig := new(freedom.Noise)
|
||||
noise.Packet = strings.TrimSpace(noise.Packet)
|
||||
|
||||
switch noise.Type {
|
||||
switch strings.ToLower(noise.Type) {
|
||||
case "rand":
|
||||
min, max, err := ParseRangeString(noise.Packet)
|
||||
if err != nil {
|
||||
@@ -168,25 +166,18 @@ func ParseNoise(noise *Noise) (*freedom.Noise, error) {
|
||||
}
|
||||
|
||||
case "str":
|
||||
// user input string
|
||||
NConfig.Packet = []byte(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)
|
||||
}
|
||||
//user input string
|
||||
NConfig.StrNoise = []byte(strings.TrimSpace(noise.Packet))
|
||||
|
||||
case "base64":
|
||||
// user input base64
|
||||
NConfig.Packet, err = base64.RawURLEncoding.DecodeString(strings.NewReplacer("+", "-", "/", "_", "=", "").Replace(noise.Packet))
|
||||
//user input base64
|
||||
NConfig.StrNoise, err = base64.StdEncoding.DecodeString(strings.TrimSpace(noise.Packet))
|
||||
if err != nil {
|
||||
return nil, errors.New("Invalid base64 string").Base(err)
|
||||
return nil, errors.New("Invalid base64 string")
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@@ -6,21 +6,15 @@ import (
|
||||
)
|
||||
|
||||
type MetricsConfig struct {
|
||||
Tag string `json:"tag"`
|
||||
Listen string `json:"listen"`
|
||||
Tag string `json:"tag"`
|
||||
}
|
||||
|
||||
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 == "" {
|
||||
c.Tag = "Metrics"
|
||||
return nil, errors.New("metrics tag can't be empty.")
|
||||
}
|
||||
|
||||
return &metrics.Config{
|
||||
Tag: c.Tag,
|
||||
Listen: c.Listen,
|
||||
Tag: c.Tag,
|
||||
}, nil
|
||||
}
|
||||
|
@@ -231,7 +231,6 @@ type SplitHTTPConfig struct {
|
||||
ScMaxEachPostBytes Int32Range `json:"scMaxEachPostBytes"`
|
||||
ScMinPostsIntervalMs Int32Range `json:"scMinPostsIntervalMs"`
|
||||
ScMaxBufferedPosts int64 `json:"scMaxBufferedPosts"`
|
||||
ScStreamUpServerSecs Int32Range `json:"scStreamUpServerSecs"`
|
||||
Xmux XmuxConfig `json:"xmux"`
|
||||
DownloadSettings *StreamConfig `json:"downloadSettings"`
|
||||
Extra json.RawMessage `json:"extra"`
|
||||
@@ -281,10 +280,6 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
@@ -308,7 +303,6 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
||||
ScMaxEachPostBytes: newRangeConfig(c.ScMaxEachPostBytes),
|
||||
ScMinPostsIntervalMs: newRangeConfig(c.ScMinPostsIntervalMs),
|
||||
ScMaxBufferedPosts: c.ScMaxBufferedPosts,
|
||||
ScStreamUpServerSecs: newRangeConfig(c.ScStreamUpServerSecs),
|
||||
Xmux: &splithttp.XmuxConfig{
|
||||
MaxConcurrency: newRangeConfig(c.Xmux.MaxConcurrency),
|
||||
MaxConnections: newRangeConfig(c.Xmux.MaxConnections),
|
||||
@@ -410,8 +404,6 @@ type TLSConfig struct {
|
||||
PinnedPeerCertificatePublicKeySha256 *[]string `json:"pinnedPeerCertificatePublicKeySha256"`
|
||||
CurvePreferences *StringList `json:"curvePreferences"`
|
||||
MasterKeyLog string `json:"masterKeyLog"`
|
||||
ServerNameToVerify string `json:"serverNameToVerify"`
|
||||
VerifyPeerCertInNames []string `json:"verifyPeerCertInNames"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -433,13 +425,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
||||
if c.ALPN != nil && len(*c.ALPN) > 0 {
|
||||
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 {
|
||||
config.CurvePreferences = []string(*c.CurvePreferences)
|
||||
}
|
||||
@@ -450,7 +435,7 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
||||
config.CipherSuites = c.CipherSuites
|
||||
config.Fingerprint = strings.ToLower(c.Fingerprint)
|
||||
if config.Fingerprint != "unsafe" && 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
|
||||
|
||||
@@ -478,11 +463,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
||||
|
||||
config.MasterKeyLog = c.MasterKeyLog
|
||||
|
||||
if c.ServerNameToVerify != "" {
|
||||
return nil, errors.PrintRemovedFeatureError(`"serverNameToVerify"`, `"verifyPeerCertInNames"`)
|
||||
}
|
||||
config.VerifyPeerCertInNames = c.VerifyPeerCertInNames
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
@@ -502,7 +482,6 @@ type REALITYConfig struct {
|
||||
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
ServerName string `json:"serverName"`
|
||||
Password string `json:"password"`
|
||||
PublicKey string `json:"publicKey"`
|
||||
ShortId string `json:"shortId"`
|
||||
SpiderX string `json:"spiderX"`
|
||||
@@ -611,14 +590,11 @@ func (c *REALITYConfig) Build() (proto.Message, error) {
|
||||
if len(c.ServerNames) != 0 {
|
||||
return nil, errors.New(`non-empty "serverNames", please use "serverName" instead`)
|
||||
}
|
||||
if c.Password != "" {
|
||||
c.PublicKey = c.Password
|
||||
}
|
||||
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 {
|
||||
return nil, errors.New(`invalid "password": `, c.PublicKey)
|
||||
return nil, errors.New(`invalid "publicKey": `, c.PublicKey)
|
||||
}
|
||||
if len(c.ShortIds) != 0 {
|
||||
return nil, errors.New(`non-empty "shortIds", please use "shortId" instead`)
|
||||
@@ -715,7 +691,6 @@ type SocketConfig struct {
|
||||
Interface string `json:"interface"`
|
||||
TcpMptcp bool `json:"tcpMptcp"`
|
||||
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
|
||||
AddressPortStrategy string `json:"addressPortStrategy"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -785,26 +760,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||
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{
|
||||
Mark: c.Mark,
|
||||
Tfo: tfo,
|
||||
@@ -823,7 +778,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
||||
Interface: c.Interface,
|
||||
TcpMptcp: c.TcpMptcp,
|
||||
CustomSockopt: customSockopts,
|
||||
AddressPortStrategy: addressPortStrategy,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@@ -292,9 +292,7 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
||||
senderSettings.ViaCidr = strings.Split(*c.SendThrough, "/")[1]
|
||||
} else {
|
||||
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()
|
||||
|
@@ -89,11 +89,12 @@ func whichProtoc(suffix, targetedVersion string) (string, error) {
|
||||
|
||||
path, err := exec.LookPath(protoc)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf(`
|
||||
errStr := fmt.Sprintf(`
|
||||
Command "%s" not found.
|
||||
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
|
||||
`, protoc, protoc, protoc, targetedVersion)
|
||||
return "", fmt.Errorf(errStr)
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
|
@@ -27,6 +27,5 @@ var CmdAPI = &base.Command{
|
||||
cmdRemoveRules,
|
||||
cmdSourceIpBlock,
|
||||
cmdOnlineStats,
|
||||
cmdOnlineStatsIpList,
|
||||
},
|
||||
}
|
||||
|
@@ -13,20 +13,25 @@ import (
|
||||
var cmdBalancerInfo = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api bi [--server=127.0.0.1:8080] [balancer]...",
|
||||
Short: "Retrieve balancer information",
|
||||
Short: "balancer information",
|
||||
Long: `
|
||||
Retrieve information of specified balancers, including health, strategy and selecting.
|
||||
If no balancer tag specified, information for all balancers is returned.
|
||||
Get information of specified balancers, including health, strategy
|
||||
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:
|
||||
|
||||
-json
|
||||
Use json output.
|
||||
|
||||
-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
|
||||
Timeout seconds to call API. Default 3
|
||||
|
||||
Example:
|
||||
|
||||
|
@@ -7,27 +7,31 @@ import (
|
||||
|
||||
var cmdBalancerOverride = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api bo [--server=127.0.0.1:8080] <-b balancer> outboundTag <-r>",
|
||||
Short: "Override balancer",
|
||||
UsageLine: "{{.Exec}} api bo [--server=127.0.0.1:8080] <-b balancer> outboundTag",
|
||||
Short: "balancer override",
|
||||
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
|
||||
|
||||
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
|
||||
-r, -remove
|
||||
Remove the overridden
|
||||
|
||||
-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:
|
||||
|
||||
|
@@ -8,28 +8,20 @@ import (
|
||||
var cmdInboundUser = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api inbounduser [--server=127.0.0.1:8080] -tag=tag [-email=email]",
|
||||
Short: "Retrieve inbound user(s)",
|
||||
Short: "Get Inbound User",
|
||||
Long: `
|
||||
Get User info from an inbound.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
-tag
|
||||
Inbound tag
|
||||
|
||||
-email
|
||||
The user's email address. If not provided, all users will be retrieved.
|
||||
|
||||
-email
|
||||
User email. If email is not given, will get all users
|
||||
Example:
|
||||
|
||||
{{.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"
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -tag="tag name" -email="xray@love.com"
|
||||
`,
|
||||
Run: executeInboundUser,
|
||||
}
|
||||
|
@@ -8,24 +8,18 @@ import (
|
||||
var cmdInboundUserCount = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api inboundusercount [--server=127.0.0.1:8080] -tag=tag",
|
||||
Short: "Retrieve inbound user count",
|
||||
Short: "Get Inbound User Count",
|
||||
Long: `
|
||||
Retrieve the user count for a specified inbound tag.
|
||||
|
||||
Get User count from an inbound.
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
-tag
|
||||
Inbound tag
|
||||
|
||||
Inbound tag
|
||||
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,
|
||||
}
|
||||
|
@@ -15,18 +15,13 @@ var cmdAddInbounds = &base.Command{
|
||||
Short: "Add inbounds",
|
||||
Long: `
|
||||
Add inbounds to Xray.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
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,
|
||||
}
|
||||
|
@@ -14,18 +14,13 @@ var cmdRemoveInbounds = &base.Command{
|
||||
Short: "Remove inbounds",
|
||||
Long: `
|
||||
Remove inbounds from Xray.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
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,
|
||||
}
|
||||
|
@@ -11,18 +11,11 @@ var cmdRestartLogger = &base.Command{
|
||||
Short: "Restart the logger",
|
||||
Long: `
|
||||
Restart the logger of Xray.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
`,
|
||||
Run: executeRestartLogger,
|
||||
}
|
||||
|
@@ -15,18 +15,13 @@ var cmdAddOutbounds = &base.Command{
|
||||
Short: "Add outbounds",
|
||||
Long: `
|
||||
Add outbounds to Xray.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
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,
|
||||
}
|
||||
|
@@ -14,18 +14,13 @@ var cmdRemoveOutbounds = &base.Command{
|
||||
Short: "Remove outbounds",
|
||||
Long: `
|
||||
Remove outbounds from Xray.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
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,
|
||||
}
|
||||
|
@@ -16,21 +16,16 @@ var cmdAddRules = &base.Command{
|
||||
Short: "Add routing rules",
|
||||
Long: `
|
||||
Add routing rules to Xray.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
|
||||
-append
|
||||
Append to the existing configuration instead of replacing it. Default false
|
||||
append or replace config. Default false
|
||||
|
||||
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,
|
||||
}
|
||||
|
@@ -9,22 +9,17 @@ import (
|
||||
|
||||
var cmdRemoveRules = &base.Command{
|
||||
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",
|
||||
Long: `
|
||||
Remove routing rules by ruleTag from Xray.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 ruleTag1 ruleTag2
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 ruleTag1 ruleTag2
|
||||
`,
|
||||
Run: executeRemoveRules,
|
||||
}
|
||||
|
@@ -14,34 +14,25 @@ import (
|
||||
var cmdSourceIpBlock = &base.Command{
|
||||
CustomFlags: true,
|
||||
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: `
|
||||
Block connections by source IP address.
|
||||
|
||||
Drop connections by source ip.
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
-outbound
|
||||
Specifies the outbound tag.
|
||||
|
||||
route traffic to specific outbound.
|
||||
-inbound
|
||||
Specifies the inbound tag.
|
||||
|
||||
target traffig from specific inbound.
|
||||
-ruletag
|
||||
The ruleTag. Default sourceIpBlock
|
||||
|
||||
set ruleTag. Default sourceIpBlock
|
||||
-reset
|
||||
remove ruletag and apply new source IPs. Default false
|
||||
|
||||
Example:
|
||||
|
||||
{{.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
|
||||
Example:
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
|
||||
`,
|
||||
Run: executeSourceIpBlock,
|
||||
}
|
||||
|
@@ -8,26 +8,19 @@ import (
|
||||
var cmdGetStats = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api stats [--server=127.0.0.1:8080] [-name '']",
|
||||
Short: "Retrieve statistics",
|
||||
Short: "Get statistics",
|
||||
Long: `
|
||||
Retrieve the statistics from Xray.
|
||||
|
||||
Get statistics from Xray.
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
-name
|
||||
Name of the counter.
|
||||
|
||||
Name of the stat counter.
|
||||
-reset
|
||||
Reset the counter after fetching their values. Default false
|
||||
|
||||
Reset the counter to fetching its value.
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -name "inbound>>>statin>>>traffic>>>downlink"
|
||||
`,
|
||||
Run: executeGetStats,
|
||||
|
@@ -7,25 +7,21 @@ import (
|
||||
|
||||
var cmdOnlineStats = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api statsonline [--server=127.0.0.1:8080] [-email '']",
|
||||
Short: "Retrieve the online session count for a user",
|
||||
UsageLine: "{{.Exec}} api statsonline [--server=127.0.0.1:8080] [-name '']",
|
||||
Short: "Get online user",
|
||||
Long: `
|
||||
Retrieve the current number of active sessions for a user from Xray.
|
||||
|
||||
Get statistics from Xray.
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
-email
|
||||
The user's email address.
|
||||
|
||||
email of the user.
|
||||
-reset
|
||||
Reset the counter to fetching its value.
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "xray@love.com"
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -email "user1@test.com"
|
||||
`,
|
||||
Run: executeOnlineStats,
|
||||
}
|
||||
|
@@ -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)
|
||||
}
|
@@ -11,23 +11,16 @@ var cmdQueryStats = &base.Command{
|
||||
Short: "Query statistics",
|
||||
Long: `
|
||||
Query statistics from Xray.
|
||||
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
-pattern
|
||||
Filter pattern for the statistics query.
|
||||
|
||||
Pattern of the query.
|
||||
-reset
|
||||
Reset the counter after fetching their values. Default false
|
||||
|
||||
Reset the counter to fetching its value.
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 -pattern "counter_"
|
||||
`,
|
||||
Run: executeQueryStats,
|
||||
|
@@ -8,21 +8,14 @@ import (
|
||||
var cmdSysStats = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api statssys [--server=127.0.0.1:8080]",
|
||||
Short: "Retrieve system statistics",
|
||||
Short: "Get system statistics",
|
||||
Long: `
|
||||
Retrieve system statistics from Xray.
|
||||
|
||||
Get system statistics from Xray.
|
||||
Arguments:
|
||||
|
||||
-s, -server <server:port>
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
|
||||
-t, -timeout <seconds>
|
||||
Timeout in seconds for calling API. Default 3
|
||||
|
||||
Example:
|
||||
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
`,
|
||||
Run: executeSysStats,
|
||||
}
|
||||
|
@@ -50,17 +50,17 @@ func executeTypedMessageToJson(cmd *base.Command, args []string) {
|
||||
|
||||
reader, err := confloader.LoadConfig(cmd.Flag.Arg(0))
|
||||
if err != nil {
|
||||
base.Fatalf("failed to load config: %s", err)
|
||||
base.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
base.Fatalf("failed to read config: %s", err)
|
||||
base.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
tm := cserial.TypedMessage{}
|
||||
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 {
|
||||
|
@@ -53,12 +53,12 @@ func executeConvertConfigsToProtobuf(cmd *base.Command, args []string) {
|
||||
}
|
||||
|
||||
if len(unnamedArgs) < 1 {
|
||||
base.Fatalf("invalid config list length: %d", len(unnamedArgs))
|
||||
base.Fatalf("empty config list")
|
||||
}
|
||||
|
||||
pbConfig, err := core.LoadConfig("auto", unnamedArgs)
|
||||
if err != nil {
|
||||
base.Fatalf("failed to load config: %s", err)
|
||||
base.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
if optDump {
|
||||
|
@@ -42,8 +42,7 @@ func Curve25519Genkey(StdEncoding bool, input_base64 string) {
|
||||
// Modify random bytes using algorithm described at:
|
||||
// https://cr.yp.to/ecdh.html.
|
||||
privateKey[0] &= 248
|
||||
privateKey[31] &= 127
|
||||
privateKey[31] |= 64
|
||||
privateKey[31] &= 127 | 64
|
||||
|
||||
if publicKey, err = curve25519.X25519(privateKey, curve25519.Basepoint); err != nil {
|
||||
output = err.Error()
|
||||
|
@@ -120,9 +120,9 @@ func writeFile(content []byte, name string) error {
|
||||
func printFile(certificate *cert.Certificate, name string) error {
|
||||
certPEM, keyPEM := certificate.ToPEM()
|
||||
return task.Run(context.Background(), func() error {
|
||||
return writeFile(certPEM, name+".crt")
|
||||
return writeFile(certPEM, name+"_cert.pem")
|
||||
}, func() error {
|
||||
return writeFile(keyPEM, name+".key")
|
||||
return writeFile(keyPEM, name+"_key.pem")
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -45,7 +45,6 @@ The -dump flag tells Xray to print the merged config.
|
||||
|
||||
func init() {
|
||||
cmdRun.Run = executeRun // break init loop
|
||||
log.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds)
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/xtls/xray-core/features/policy"
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -64,6 +63,10 @@ func (d *DokodemoDoor) policy() policy.Session {
|
||||
return p
|
||||
}
|
||||
|
||||
type hasHandshakeAddressContext interface {
|
||||
HandshakeAddressContext(ctx context.Context) net.Address
|
||||
}
|
||||
|
||||
// Process implements proxy.Inbound.
|
||||
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())
|
||||
@@ -83,14 +86,11 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
|
||||
destinationOverridden = true
|
||||
}
|
||||
}
|
||||
if tlsConn, ok := conn.(tls.Interface); ok && !destinationOverridden {
|
||||
if serverName := tlsConn.HandshakeContextServerName(ctx); serverName != "" {
|
||||
dest.Address = net.DomainAddress(serverName)
|
||||
if handshake, ok := conn.(hasHandshakeAddressContext); ok && !destinationOverridden {
|
||||
addr := handshake.HandshakeAddressContext(ctx)
|
||||
if addr != nil {
|
||||
dest.Address = addr
|
||||
destinationOverridden = true
|
||||
ctx = session.ContextWithMitmServerName(ctx, serverName)
|
||||
}
|
||||
if tlsConn.NegotiatedProtocol() != "h2" {
|
||||
ctx = session.ContextWithMitmAlpn11(ctx, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -233,7 +233,7 @@ type Noise struct {
|
||||
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"`
|
||||
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() {
|
||||
@@ -294,9 +294,9 @@ func (x *Noise) GetDelayMax() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Noise) GetPacket() []byte {
|
||||
func (x *Noise) GetStrNoise() []byte {
|
||||
if x != nil {
|
||||
return x.Packet
|
||||
return x.StrNoise
|
||||
}
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
@@ -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,
|
||||
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,
|
||||
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70,
|
||||
0x61, 0x63, 0x6b, 0x65, 0x74, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||
0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||
0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61,
|
||||
0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61,
|
||||
0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
||||
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13, 0x64, 0x65, 0x73,
|
||||
0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a,
|
||||
0x09, 0x73, 0x74, 0x72, 0x5f, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x52, 0x08, 0x73, 0x74, 0x72, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f,
|
||||
0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29,
|
||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65,
|
||||
0x64, 0x6f, 0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73,
|
||||
0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
||||
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
|
||||
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73,
|
||||
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,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12,
|
||||
0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66,
|
||||
0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x52,
|
||||
0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||
0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72,
|
||||
0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06, 0x6e, 0x6f, 0x69,
|
||||
0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
|
||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10,
|
||||
0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a,
|
||||
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53,
|
||||
0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
||||
0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36,
|
||||
0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10,
|
||||
0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07,
|
||||
0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12,
|
||||
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12,
|
||||
0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42,
|
||||
0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x66, 0x72, 0x65,
|
||||
0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
0x52, 0x13, 0x64, 0x65, 0x73, 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, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c,
|
||||
0x65, 0x76, 0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67,
|
||||
0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25,
|
||||
0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
||||
0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18,
|
||||
0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65,
|
||||
0x52, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d,
|
||||
0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41,
|
||||
0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12,
|
||||
0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08,
|
||||
0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53,
|
||||
0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43,
|
||||
0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49,
|
||||
0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x36, 0x34, 0x10, 0x0a, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01,
|
||||
0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c,
|
||||
0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -25,7 +25,7 @@ message Noise {
|
||||
uint64 length_max = 2;
|
||||
uint64 delay_min = 3;
|
||||
uint64 delay_max = 4;
|
||||
bytes packet = 5;
|
||||
bytes str_noise = 5;
|
||||
}
|
||||
|
||||
message Config {
|
||||
|
@@ -4,12 +4,12 @@ import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/pires/go-proxyproto"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"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/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@@ -266,9 +266,6 @@ func isTLSConn(conn stat.Connection) bool {
|
||||
if _, ok := conn.(*tls.Conn); ok {
|
||||
return true
|
||||
}
|
||||
if _, ok := conn.(*tls.UConn); ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -410,11 +407,11 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
var err error
|
||||
for _, n := range w.noises {
|
||||
//User input string or base64 encoded string
|
||||
if n.Packet != nil {
|
||||
noise = n.Packet
|
||||
if n.StrNoise != nil {
|
||||
noise = n.StrNoise
|
||||
} else {
|
||||
//Random noise
|
||||
noise, err = GenerateRandomBytes(crypto.RandBetween(int64(n.LengthMin),
|
||||
noise, err = GenerateRandomBytes(randBetween(int64(n.LengthMin),
|
||||
int64(n.LengthMax)))
|
||||
}
|
||||
if err != nil {
|
||||
@@ -423,7 +420,7 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
|
||||
|
||||
if n.DelayMin != 0 || n.DelayMax != 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)
|
||||
var hello []byte
|
||||
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) {
|
||||
to = len(data)
|
||||
}
|
||||
@@ -466,7 +463,7 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
|
||||
hello = append(hello, buf[:5+l]...)
|
||||
} else {
|
||||
_, 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 {
|
||||
return 0, err
|
||||
}
|
||||
@@ -493,13 +490,13 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
|
||||
return f.writer.Write(b)
|
||||
}
|
||||
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) {
|
||||
to = len(b)
|
||||
}
|
||||
n, err := f.writer.Write(b[from:to])
|
||||
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 {
|
||||
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) {
|
||||
b := make([]byte, n)
|
||||
_, err := rand.Read(b)
|
||||
|
@@ -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))
|
||||
}
|
||||
responseFunc := func() error {
|
||||
ob.CanSpliceCopy = 1
|
||||
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
|
||||
return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
|
||||
}
|
||||
|
@@ -207,7 +207,6 @@ func (s *Server) handleConnect(ctx context.Context, _ *http.Request, reader *buf
|
||||
}
|
||||
|
||||
responseDone := func() error {
|
||||
inbound.CanSpliceCopy = 1
|
||||
defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
|
||||
|
||||
v2writer := buf.NewWriter(conn)
|
||||
|
198
proxy/proxy.go
198
proxy/proxy.go
@@ -107,65 +107,37 @@ type TrafficState struct {
|
||||
IsTLS bool
|
||||
Cipher uint16
|
||||
RemainingServerHello int32
|
||||
Inbound InboundState
|
||||
Outbound OutboundState
|
||||
}
|
||||
|
||||
type InboundState struct {
|
||||
// reader link state
|
||||
WithinPaddingBuffers bool
|
||||
UplinkReaderDirectCopy bool
|
||||
RemainingCommand int32
|
||||
RemainingContent int32
|
||||
RemainingPadding int32
|
||||
CurrentCommand int
|
||||
// write link state
|
||||
IsPadding bool
|
||||
DownlinkWriterDirectCopy bool
|
||||
}
|
||||
|
||||
type OutboundState struct {
|
||||
// reader link state
|
||||
WithinPaddingBuffers bool
|
||||
DownlinkReaderDirectCopy bool
|
||||
ReaderSwitchToDirectCopy bool
|
||||
RemainingCommand int32
|
||||
RemainingContent int32
|
||||
RemainingPadding int32
|
||||
CurrentCommand int
|
||||
|
||||
// write link state
|
||||
IsPadding bool
|
||||
UplinkWriterDirectCopy bool
|
||||
IsPadding bool
|
||||
WriterSwitchToDirectCopy bool
|
||||
}
|
||||
|
||||
func NewTrafficState(userUUID []byte) *TrafficState {
|
||||
return &TrafficState{
|
||||
UserUUID: userUUID,
|
||||
NumberOfPacketToFilter: 8,
|
||||
EnableXtls: false,
|
||||
IsTLS12orAbove: false,
|
||||
IsTLS: false,
|
||||
Cipher: 0,
|
||||
RemainingServerHello: -1,
|
||||
Inbound: InboundState{
|
||||
WithinPaddingBuffers: true,
|
||||
UplinkReaderDirectCopy: false,
|
||||
RemainingCommand: -1,
|
||||
RemainingContent: -1,
|
||||
RemainingPadding: -1,
|
||||
CurrentCommand: 0,
|
||||
IsPadding: true,
|
||||
DownlinkWriterDirectCopy: false,
|
||||
},
|
||||
Outbound: OutboundState{
|
||||
WithinPaddingBuffers: true,
|
||||
DownlinkReaderDirectCopy: false,
|
||||
RemainingCommand: -1,
|
||||
RemainingContent: -1,
|
||||
RemainingPadding: -1,
|
||||
CurrentCommand: 0,
|
||||
IsPadding: true,
|
||||
UplinkWriterDirectCopy: false,
|
||||
},
|
||||
UserUUID: userUUID,
|
||||
NumberOfPacketToFilter: 8,
|
||||
EnableXtls: false,
|
||||
IsTLS12orAbove: false,
|
||||
IsTLS: false,
|
||||
Cipher: 0,
|
||||
RemainingServerHello: -1,
|
||||
WithinPaddingBuffers: true,
|
||||
ReaderSwitchToDirectCopy: false,
|
||||
RemainingCommand: -1,
|
||||
RemainingContent: -1,
|
||||
RemainingPadding: -1,
|
||||
CurrentCommand: 0,
|
||||
IsPadding: true,
|
||||
WriterSwitchToDirectCopy: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,58 +147,37 @@ type VisionReader struct {
|
||||
buf.Reader
|
||||
trafficState *TrafficState
|
||||
ctx context.Context
|
||||
isUplink bool
|
||||
}
|
||||
|
||||
func NewVisionReader(reader buf.Reader, state *TrafficState, isUplink bool, context context.Context) *VisionReader {
|
||||
func NewVisionReader(reader buf.Reader, state *TrafficState, context context.Context) *VisionReader {
|
||||
return &VisionReader{
|
||||
Reader: reader,
|
||||
trafficState: state,
|
||||
ctx: context,
|
||||
isUplink: isUplink,
|
||||
}
|
||||
}
|
||||
|
||||
func (w *VisionReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
buffer, err := w.Reader.ReadMultiBuffer()
|
||||
if !buffer.IsEmpty() {
|
||||
var withinPaddingBuffers *bool
|
||||
var remainingContent *int32
|
||||
var remainingPadding *int32
|
||||
var currentCommand *int
|
||||
var switchToDirectCopy *bool
|
||||
if w.isUplink {
|
||||
withinPaddingBuffers = &w.trafficState.Inbound.WithinPaddingBuffers
|
||||
remainingContent = &w.trafficState.Inbound.RemainingContent
|
||||
remainingPadding = &w.trafficState.Inbound.RemainingPadding
|
||||
currentCommand = &w.trafficState.Inbound.CurrentCommand
|
||||
switchToDirectCopy = &w.trafficState.Inbound.UplinkReaderDirectCopy
|
||||
} else {
|
||||
withinPaddingBuffers = &w.trafficState.Outbound.WithinPaddingBuffers
|
||||
remainingContent = &w.trafficState.Outbound.RemainingContent
|
||||
remainingPadding = &w.trafficState.Outbound.RemainingPadding
|
||||
currentCommand = &w.trafficState.Outbound.CurrentCommand
|
||||
switchToDirectCopy = &w.trafficState.Outbound.DownlinkReaderDirectCopy
|
||||
}
|
||||
|
||||
if *withinPaddingBuffers || w.trafficState.NumberOfPacketToFilter > 0 {
|
||||
if w.trafficState.WithinPaddingBuffers || w.trafficState.NumberOfPacketToFilter > 0 {
|
||||
mb2 := make(buf.MultiBuffer, 0, len(buffer))
|
||||
for _, b := range buffer {
|
||||
newbuffer := XtlsUnpadding(b, w.trafficState, w.isUplink, w.ctx)
|
||||
newbuffer := XtlsUnpadding(b, w.trafficState, w.ctx)
|
||||
if newbuffer.Len() > 0 {
|
||||
mb2 = append(mb2, newbuffer)
|
||||
}
|
||||
}
|
||||
buffer = mb2
|
||||
if *remainingContent > 0 || *remainingPadding > 0 || *currentCommand == 0 {
|
||||
*withinPaddingBuffers = true
|
||||
} else if *currentCommand == 1 {
|
||||
*withinPaddingBuffers = false
|
||||
} else if *currentCommand == 2 {
|
||||
*withinPaddingBuffers = false
|
||||
*switchToDirectCopy = true
|
||||
if w.trafficState.RemainingContent > 0 || w.trafficState.RemainingPadding > 0 || w.trafficState.CurrentCommand == 0 {
|
||||
w.trafficState.WithinPaddingBuffers = true
|
||||
} else if w.trafficState.CurrentCommand == 1 {
|
||||
w.trafficState.WithinPaddingBuffers = false
|
||||
} else if w.trafficState.CurrentCommand == 2 {
|
||||
w.trafficState.WithinPaddingBuffers = false
|
||||
w.trafficState.ReaderSwitchToDirectCopy = true
|
||||
} else {
|
||||
errors.LogInfo(w.ctx, "XtlsRead unknown command ", *currentCommand, buffer.Len())
|
||||
errors.LogInfo(w.ctx, "XtlsRead unknown command ", w.trafficState.CurrentCommand, buffer.Len())
|
||||
}
|
||||
}
|
||||
if w.trafficState.NumberOfPacketToFilter > 0 {
|
||||
@@ -243,10 +194,9 @@ type VisionWriter struct {
|
||||
trafficState *TrafficState
|
||||
ctx context.Context
|
||||
writeOnceUserUUID []byte
|
||||
isUplink bool
|
||||
}
|
||||
|
||||
func NewVisionWriter(writer buf.Writer, state *TrafficState, isUplink bool, context context.Context) *VisionWriter {
|
||||
func NewVisionWriter(writer buf.Writer, state *TrafficState, context context.Context) *VisionWriter {
|
||||
w := make([]byte, len(state.UserUUID))
|
||||
copy(w, state.UserUUID)
|
||||
return &VisionWriter{
|
||||
@@ -254,7 +204,6 @@ func NewVisionWriter(writer buf.Writer, state *TrafficState, isUplink bool, cont
|
||||
trafficState: state,
|
||||
ctx: context,
|
||||
writeOnceUserUUID: w,
|
||||
isUplink: isUplink,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,16 +211,7 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
if w.trafficState.NumberOfPacketToFilter > 0 {
|
||||
XtlsFilterTls(mb, w.trafficState, w.ctx)
|
||||
}
|
||||
var isPadding *bool
|
||||
var switchToDirectCopy *bool
|
||||
if w.isUplink {
|
||||
isPadding = &w.trafficState.Outbound.IsPadding
|
||||
switchToDirectCopy = &w.trafficState.Outbound.UplinkWriterDirectCopy
|
||||
} else {
|
||||
isPadding = &w.trafficState.Inbound.IsPadding
|
||||
switchToDirectCopy = &w.trafficState.Inbound.DownlinkWriterDirectCopy
|
||||
}
|
||||
if *isPadding {
|
||||
if w.trafficState.IsPadding {
|
||||
if len(mb) == 1 && mb[0] == nil {
|
||||
mb[0] = XtlsPadding(nil, CommandPaddingContinue, &w.writeOnceUserUUID, true, w.ctx) // we do a long padding to hide vless header
|
||||
return w.Writer.WriteMultiBuffer(mb)
|
||||
@@ -281,7 +221,7 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
for i, b := range mb {
|
||||
if w.trafficState.IsTLS && b.Len() >= 6 && bytes.Equal(TlsApplicationDataStart, b.BytesTo(3)) {
|
||||
if w.trafficState.EnableXtls {
|
||||
*switchToDirectCopy = true
|
||||
w.trafficState.WriterSwitchToDirectCopy = true
|
||||
}
|
||||
var command byte = CommandPaddingContinue
|
||||
if i == len(mb)-1 {
|
||||
@@ -291,16 +231,16 @@ func (w *VisionWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
}
|
||||
}
|
||||
mb[i] = XtlsPadding(b, command, &w.writeOnceUserUUID, true, w.ctx)
|
||||
*isPadding = false // padding going to end
|
||||
w.trafficState.IsPadding = false // padding going to end
|
||||
longPadding = false
|
||||
continue
|
||||
} else if !w.trafficState.IsTLS12orAbove && w.trafficState.NumberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early
|
||||
*isPadding = false
|
||||
w.trafficState.IsPadding = false
|
||||
mb[i] = XtlsPadding(b, CommandPaddingEnd, &w.writeOnceUserUUID, longPadding, w.ctx)
|
||||
break
|
||||
}
|
||||
var command byte = CommandPaddingContinue
|
||||
if i == len(mb)-1 && !*isPadding {
|
||||
if i == len(mb)-1 && !w.trafficState.IsPadding {
|
||||
command = CommandPaddingEnd
|
||||
if w.trafficState.EnableXtls {
|
||||
command = CommandPaddingDirect
|
||||
@@ -387,53 +327,38 @@ func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, longPadding bool
|
||||
}
|
||||
|
||||
// XtlsUnpadding remove padding and parse command
|
||||
func XtlsUnpadding(b *buf.Buffer, s *TrafficState, isUplink bool, ctx context.Context) *buf.Buffer {
|
||||
var remainingCommand *int32
|
||||
var remainingContent *int32
|
||||
var remainingPadding *int32
|
||||
var currentCommand *int
|
||||
if isUplink {
|
||||
remainingCommand = &s.Inbound.RemainingCommand
|
||||
remainingContent = &s.Inbound.RemainingContent
|
||||
remainingPadding = &s.Inbound.RemainingPadding
|
||||
currentCommand = &s.Inbound.CurrentCommand
|
||||
} else {
|
||||
remainingCommand = &s.Outbound.RemainingCommand
|
||||
remainingContent = &s.Outbound.RemainingContent
|
||||
remainingPadding = &s.Outbound.RemainingPadding
|
||||
currentCommand = &s.Outbound.CurrentCommand
|
||||
}
|
||||
if *remainingCommand == -1 && *remainingContent == -1 && *remainingPadding == -1 { // initial state
|
||||
func XtlsUnpadding(b *buf.Buffer, s *TrafficState, ctx context.Context) *buf.Buffer {
|
||||
if s.RemainingCommand == -1 && s.RemainingContent == -1 && s.RemainingPadding == -1 { // initial state
|
||||
if b.Len() >= 21 && bytes.Equal(s.UserUUID, b.BytesTo(16)) {
|
||||
b.Advance(16)
|
||||
*remainingCommand = 5
|
||||
s.RemainingCommand = 5
|
||||
} else {
|
||||
return b
|
||||
}
|
||||
}
|
||||
newbuffer := buf.New()
|
||||
for b.Len() > 0 {
|
||||
if *remainingCommand > 0 {
|
||||
if s.RemainingCommand > 0 {
|
||||
data, err := b.ReadByte()
|
||||
if err != nil {
|
||||
return newbuffer
|
||||
}
|
||||
switch *remainingCommand {
|
||||
switch s.RemainingCommand {
|
||||
case 5:
|
||||
*currentCommand = int(data)
|
||||
s.CurrentCommand = int(data)
|
||||
case 4:
|
||||
*remainingContent = int32(data) << 8
|
||||
s.RemainingContent = int32(data) << 8
|
||||
case 3:
|
||||
*remainingContent = *remainingContent | int32(data)
|
||||
s.RemainingContent = s.RemainingContent | int32(data)
|
||||
case 2:
|
||||
*remainingPadding = int32(data) << 8
|
||||
s.RemainingPadding = int32(data) << 8
|
||||
case 1:
|
||||
*remainingPadding = *remainingPadding | int32(data)
|
||||
errors.LogInfo(ctx, "Xtls Unpadding new block, content ", *remainingContent, " padding ", *remainingPadding, " command ", *currentCommand)
|
||||
s.RemainingPadding = s.RemainingPadding | int32(data)
|
||||
errors.LogInfo(ctx, "Xtls Unpadding new block, content ", s.RemainingContent, " padding ", s.RemainingPadding, " command ", s.CurrentCommand)
|
||||
}
|
||||
*remainingCommand--
|
||||
} else if *remainingContent > 0 {
|
||||
len := *remainingContent
|
||||
s.RemainingCommand--
|
||||
} else if s.RemainingContent > 0 {
|
||||
len := s.RemainingContent
|
||||
if b.Len() < len {
|
||||
len = b.Len()
|
||||
}
|
||||
@@ -442,22 +367,22 @@ func XtlsUnpadding(b *buf.Buffer, s *TrafficState, isUplink bool, ctx context.Co
|
||||
return newbuffer
|
||||
}
|
||||
newbuffer.Write(data)
|
||||
*remainingContent -= len
|
||||
s.RemainingContent -= len
|
||||
} else { // remainingPadding > 0
|
||||
len := *remainingPadding
|
||||
len := s.RemainingPadding
|
||||
if b.Len() < len {
|
||||
len = b.Len()
|
||||
}
|
||||
b.Advance(len)
|
||||
*remainingPadding -= len
|
||||
s.RemainingPadding -= len
|
||||
}
|
||||
if *remainingCommand <= 0 && *remainingContent <= 0 && *remainingPadding <= 0 { // this block done
|
||||
if *currentCommand == 0 {
|
||||
*remainingCommand = 5
|
||||
if s.RemainingCommand <= 0 && s.RemainingContent <= 0 && s.RemainingPadding <= 0 { // this block done
|
||||
if s.CurrentCommand == 0 {
|
||||
s.RemainingCommand = 5
|
||||
} else {
|
||||
*remainingCommand = -1 // set to initial state
|
||||
*remainingContent = -1
|
||||
*remainingPadding = -1
|
||||
s.RemainingCommand = -1 // set to initial state
|
||||
s.RemainingContent = -1
|
||||
s.RemainingPadding = -1
|
||||
if b.Len() > 0 { // shouldn't happen
|
||||
newbuffer.Write(b.Bytes())
|
||||
}
|
||||
@@ -524,7 +449,7 @@ func XtlsFilterTls(buffer buf.MultiBuffer, trafficState *TrafficState, ctx conte
|
||||
}
|
||||
}
|
||||
|
||||
// UnwrapRawConn support unwrap stats, tls, utls, reality, proxyproto, uds-wrapper conn and get raw tcp/uds conn from it
|
||||
// UnwrapRawConn support unwrap stats, tls, utls, reality and proxyproto conn and get raw tcp conn from it
|
||||
func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
|
||||
var readCounter, writerCounter stats.Counter
|
||||
if conn != nil {
|
||||
@@ -547,9 +472,6 @@ func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
|
||||
conn = pc.Raw()
|
||||
// 8192 > 4096, there is no need to process pc's bufReader
|
||||
}
|
||||
if uc, ok := conn.(*internet.UnixConnWrapper); ok {
|
||||
conn = uc.UnixConn
|
||||
}
|
||||
}
|
||||
return conn, readCounter, writerCounter
|
||||
}
|
||||
|
@@ -146,7 +146,6 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
return buf.Copy(link.Reader, buf.NewWriter(conn), buf.UpdateActivity(timer))
|
||||
}
|
||||
responseFunc = func() error {
|
||||
ob.CanSpliceCopy = 1
|
||||
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
|
||||
return buf.Copy(buf.NewReader(conn), link.Writer, buf.UpdateActivity(timer))
|
||||
}
|
||||
@@ -162,7 +161,6 @@ func (c *Client) Process(ctx context.Context, link *transport.Link, dialer inter
|
||||
return buf.Copy(link.Reader, writer, buf.UpdateActivity(timer))
|
||||
}
|
||||
responseFunc = func() error {
|
||||
ob.CanSpliceCopy = 1
|
||||
defer timer.SetTimeout(p.Timeouts.UplinkOnly)
|
||||
reader := &UDPReader{Reader: udpConn}
|
||||
return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
|
||||
|
@@ -2,7 +2,6 @@ package socks
|
||||
|
||||
import (
|
||||
"context"
|
||||
goerrors "errors"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
@@ -79,13 +78,7 @@ func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Con
|
||||
switch network {
|
||||
case net.Network_TCP:
|
||||
firstbyte := make([]byte, 1)
|
||||
if n, err := conn.Read(firstbyte); n == 0 {
|
||||
if goerrors.Is(err, io.EOF) {
|
||||
errors.LogInfo(ctx, "Connection closed immediately, likely health check connection")
|
||||
return nil
|
||||
}
|
||||
return errors.New("failed to read from connection").Base(err)
|
||||
}
|
||||
conn.Read(firstbyte)
|
||||
if firstbyte[0] != 5 && firstbyte[0] != 4 { // Check if it is Socks5/4/4a
|
||||
errors.LogDebug(ctx, "Not Socks request, try to parse as HTTP request")
|
||||
return s.httpServer.ProcessWithFirstbyte(ctx, network, conn, dispatcher, firstbyte...)
|
||||
@@ -199,7 +192,6 @@ func (s *Server) transport(ctx context.Context, reader io.Reader, writer io.Writ
|
||||
}
|
||||
|
||||
responseDone := func() error {
|
||||
inbound.CanSpliceCopy = 1
|
||||
defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
|
||||
|
||||
v2writer := buf.NewWriter(writer)
|
||||
@@ -257,7 +249,6 @@ func (s *Server) handleUDPPayload(ctx context.Context, conn stat.Connection, dis
|
||||
if inbound != nil && inbound.Source.IsValid() {
|
||||
errors.LogInfo(ctx, "client UDP connection from ", inbound.Source)
|
||||
}
|
||||
inbound.CanSpliceCopy = 1
|
||||
|
||||
var dest *net.Destination
|
||||
|
||||
|
@@ -61,13 +61,13 @@ func DecodeHeaderAddons(buffer *buf.Buffer, reader io.Reader) (*Addons, error) {
|
||||
}
|
||||
|
||||
// EncodeBodyAddons returns a Writer that auto-encrypt content written by caller.
|
||||
func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, isUplink bool, context context.Context) buf.Writer {
|
||||
func EncodeBodyAddons(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons, state *proxy.TrafficState, context context.Context) buf.Writer {
|
||||
if request.Command == protocol.RequestCommandUDP {
|
||||
return NewMultiLengthPacketWriter(writer.(buf.Writer))
|
||||
}
|
||||
w := buf.NewWriter(writer)
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
w = proxy.NewVisionWriter(w, state, isUplink, context)
|
||||
w = proxy.NewVisionWriter(w, state, context)
|
||||
}
|
||||
return w
|
||||
}
|
||||
|
@@ -172,19 +172,19 @@ func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*A
|
||||
}
|
||||
|
||||
// XtlsRead filter and read xtls protocol
|
||||
func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, isUplink bool, ctx context.Context) error {
|
||||
func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer, conn net.Conn, input *bytes.Reader, rawInput *bytes.Buffer, trafficState *proxy.TrafficState, ob *session.Outbound, ctx context.Context) error {
|
||||
err := func() error {
|
||||
for {
|
||||
if isUplink && trafficState.Inbound.UplinkReaderDirectCopy || !isUplink && trafficState.Outbound.DownlinkReaderDirectCopy {
|
||||
if trafficState.ReaderSwitchToDirectCopy {
|
||||
var writerConn net.Conn
|
||||
var inTimer *signal.ActivityTimer
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil {
|
||||
writerConn = inbound.Conn
|
||||
inTimer = inbound.Timer
|
||||
if isUplink && inbound.CanSpliceCopy == 2 {
|
||||
if inbound.CanSpliceCopy == 2 {
|
||||
inbound.CanSpliceCopy = 1
|
||||
}
|
||||
if !isUplink && ob != nil && ob.CanSpliceCopy == 2 { // ob need to be passed in due to context can change
|
||||
if ob != nil && ob.CanSpliceCopy == 2 { // ob need to be passed in due to context can change
|
||||
ob.CanSpliceCopy = 1
|
||||
}
|
||||
}
|
||||
@@ -193,7 +193,7 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer,
|
||||
buffer, err := reader.ReadMultiBuffer()
|
||||
if !buffer.IsEmpty() {
|
||||
timer.Update()
|
||||
if isUplink && trafficState.Inbound.UplinkReaderDirectCopy || !isUplink && trafficState.Outbound.DownlinkReaderDirectCopy {
|
||||
if trafficState.ReaderSwitchToDirectCopy {
|
||||
// XTLS Vision processes struct TLS Conn's input and rawInput
|
||||
if inputBuffer, err := buf.ReadFrom(input); err == nil {
|
||||
if !inputBuffer.IsEmpty() {
|
||||
@@ -222,28 +222,24 @@ func XtlsRead(reader buf.Reader, writer buf.Writer, timer *signal.ActivityTimer,
|
||||
}
|
||||
|
||||
// XtlsWrite filter and write xtls protocol
|
||||
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, trafficState *proxy.TrafficState, ob *session.Outbound, isUplink bool, ctx context.Context) error {
|
||||
func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, trafficState *proxy.TrafficState, ob *session.Outbound, ctx context.Context) error {
|
||||
err := func() error {
|
||||
var ct stats.Counter
|
||||
for {
|
||||
buffer, err := reader.ReadMultiBuffer()
|
||||
if isUplink && trafficState.Outbound.UplinkWriterDirectCopy || !isUplink && trafficState.Inbound.DownlinkWriterDirectCopy {
|
||||
if trafficState.WriterSwitchToDirectCopy {
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||
if !isUplink && inbound.CanSpliceCopy == 2 {
|
||||
if inbound.CanSpliceCopy == 2 {
|
||||
inbound.CanSpliceCopy = 1
|
||||
}
|
||||
if isUplink && ob != nil && ob.CanSpliceCopy == 2 {
|
||||
if ob != nil && ob.CanSpliceCopy == 2 {
|
||||
ob.CanSpliceCopy = 1
|
||||
}
|
||||
}
|
||||
rawConn, _, writerCounter := proxy.UnwrapRawConn(conn)
|
||||
writer = buf.NewWriter(rawConn)
|
||||
ct = writerCounter
|
||||
if isUplink {
|
||||
trafficState.Outbound.UplinkWriterDirectCopy = false
|
||||
} else {
|
||||
trafficState.Inbound.DownlinkWriterDirectCopy = false
|
||||
}
|
||||
trafficState.WriterSwitchToDirectCopy = false
|
||||
}
|
||||
if !buffer.IsEmpty() {
|
||||
if ct != nil {
|
||||
|
@@ -538,8 +538,8 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
|
||||
clientReader = proxy.NewVisionReader(clientReader, trafficState, true, ctx1)
|
||||
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, true, ctx1)
|
||||
clientReader = proxy.NewVisionReader(clientReader, trafficState, ctx1)
|
||||
err = encoding.XtlsRead(clientReader, serverWriter, timer, connection, input, rawInput, trafficState, nil, ctx1)
|
||||
} else {
|
||||
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
|
||||
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
||||
@@ -561,7 +561,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
}
|
||||
|
||||
// default: clientWriter := bufferWriter
|
||||
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, false, ctx)
|
||||
clientWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, ctx)
|
||||
multiBuffer, err1 := serverReader.ReadMultiBuffer()
|
||||
if err1 != nil {
|
||||
return err1 // ...
|
||||
@@ -576,7 +576,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
||||
|
||||
var err error
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
err = encoding.XtlsWrite(serverReader, clientWriter, timer, connection, trafficState, nil, false, ctx)
|
||||
err = encoding.XtlsWrite(serverReader, clientWriter, timer, connection, trafficState, nil, ctx)
|
||||
} else {
|
||||
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBuffer
|
||||
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
||||
|
@@ -194,7 +194,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
}
|
||||
|
||||
// default: serverWriter := bufferWriter
|
||||
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, true, ctx)
|
||||
serverWriter := encoding.EncodeBodyAddons(bufferWriter, request, requestAddons, trafficState, ctx)
|
||||
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||
serverWriter = xudp.NewPacketWriter(serverWriter, target, xudp.GetGlobalID(ctx))
|
||||
}
|
||||
@@ -234,7 +234,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
}
|
||||
}
|
||||
ctx1 := session.ContextWithInbound(ctx, nil) // TODO enable splice
|
||||
err = encoding.XtlsWrite(clientReader, serverWriter, timer, conn, trafficState, ob, true, ctx1)
|
||||
err = encoding.XtlsWrite(clientReader, serverWriter, timer, conn, trafficState, ob, ctx1)
|
||||
} else {
|
||||
// from clientReader.ReadMultiBuffer to serverWriter.WriteMultiBuffer
|
||||
err = buf.Copy(clientReader, serverWriter, buf.UpdateActivity(timer))
|
||||
@@ -261,7 +261,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
// default: serverReader := buf.NewReader(conn)
|
||||
serverReader := encoding.DecodeBodyAddons(conn, request, responseAddons)
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
serverReader = proxy.NewVisionReader(serverReader, trafficState, false, ctx)
|
||||
serverReader = proxy.NewVisionReader(serverReader, trafficState, ctx)
|
||||
}
|
||||
if request.Command == protocol.RequestCommandMux && request.Port == 666 {
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
@@ -272,7 +272,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
}
|
||||
|
||||
if requestAddons.Flow == vless.XRV {
|
||||
err = encoding.XtlsRead(serverReader, clientWriter, timer, conn, input, rawInput, trafficState, ob, false, ctx)
|
||||
err = encoding.XtlsRead(serverReader, clientWriter, timer, conn, input, rawInput, trafficState, ob, ctx)
|
||||
} else {
|
||||
// from serverReader.ReadMultiBuffer to clientWriter.WriteMultiBuffer
|
||||
err = buf.Copy(serverReader, clientWriter, buf.UpdateActivity(timer))
|
||||
|
@@ -157,7 +157,7 @@ func (tun *netTun) Write(buf [][]byte, offset int) (int, error) {
|
||||
// WriteNotify implements channel.Notification
|
||||
func (tun *netTun) WriteNotify() {
|
||||
pkt := tun.ep.Read()
|
||||
if pkt == nil {
|
||||
if pkt.IsNil() {
|
||||
return
|
||||
}
|
||||
|
||||
|
@@ -194,7 +194,7 @@ func createGVisorTun(localAddresses []netip.Addr, mtu int, handler promiscuousMo
|
||||
Timeout: 15 * time.Second,
|
||||
})
|
||||
|
||||
handler(xnet.UDPDestination(xnet.IPAddress(id.LocalAddress.AsSlice()), xnet.Port(id.LocalPort)), gonet.NewUDPConn(&wq, ep))
|
||||
handler(xnet.UDPDestination(xnet.IPAddress(id.LocalAddress.AsSlice()), xnet.Port(id.LocalPort)), gonet.NewUDPConn(stack, &wq, ep))
|
||||
}(r)
|
||||
})
|
||||
stack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
"context"
|
||||
_ "embed"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@@ -18,12 +17,6 @@ import (
|
||||
//go:embed dialer.html
|
||||
var webpage []byte
|
||||
|
||||
type task struct {
|
||||
Method string `json:"method"`
|
||||
URL string `json:"url"`
|
||||
Extra any `json:"extra,omitempty"`
|
||||
}
|
||||
|
||||
var conns chan *websocket.Conn
|
||||
|
||||
var upgrader = &websocket.Upgrader{
|
||||
@@ -62,69 +55,23 @@ func HasBrowserDialer() bool {
|
||||
return conns != nil
|
||||
}
|
||||
|
||||
type webSocketExtra struct {
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
}
|
||||
|
||||
func DialWS(uri string, ed []byte) (*websocket.Conn, error) {
|
||||
task := task{
|
||||
Method: "WS",
|
||||
URL: uri,
|
||||
}
|
||||
|
||||
data := []byte("WS " + uri)
|
||||
if ed != nil {
|
||||
task.Extra = webSocketExtra{
|
||||
Protocol: base64.RawURLEncoding.EncodeToString(ed),
|
||||
}
|
||||
data = append(data, " "+base64.RawURLEncoding.EncodeToString(ed)...)
|
||||
}
|
||||
|
||||
return dialTask(task)
|
||||
return dialRaw(data)
|
||||
}
|
||||
|
||||
type httpExtra struct {
|
||||
Referrer string `json:"referrer,omitempty"`
|
||||
Headers map[string]string `json:"headers,omitempty"`
|
||||
func DialGet(uri string) (*websocket.Conn, error) {
|
||||
data := []byte("GET " + uri)
|
||||
return dialRaw(data)
|
||||
}
|
||||
|
||||
func httpExtraFromHeaders(headers http.Header) *httpExtra {
|
||||
if len(headers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
extra := httpExtra{}
|
||||
if referrer := headers.Get("Referer"); referrer != "" {
|
||||
extra.Referrer = referrer
|
||||
headers.Del("Referer")
|
||||
}
|
||||
|
||||
if len(headers) > 0 {
|
||||
extra.Headers = make(map[string]string)
|
||||
for header := range headers {
|
||||
extra.Headers[header] = headers.Get(header)
|
||||
}
|
||||
}
|
||||
|
||||
return &extra
|
||||
}
|
||||
|
||||
func DialGet(uri string, headers http.Header) (*websocket.Conn, error) {
|
||||
task := task{
|
||||
Method: "GET",
|
||||
URL: uri,
|
||||
Extra: httpExtraFromHeaders(headers),
|
||||
}
|
||||
|
||||
return dialTask(task)
|
||||
}
|
||||
|
||||
func DialPost(uri string, headers http.Header, payload []byte) error {
|
||||
task := task{
|
||||
Method: "POST",
|
||||
URL: uri,
|
||||
Extra: httpExtraFromHeaders(headers),
|
||||
}
|
||||
|
||||
conn, err := dialTask(task)
|
||||
func DialPost(uri string, payload []byte) error {
|
||||
data := []byte("POST " + uri)
|
||||
conn, err := dialRaw(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -143,12 +90,7 @@ func DialPost(uri string, headers http.Header, payload []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func dialTask(task task) (*websocket.Conn, error) {
|
||||
data, err := json.Marshal(task)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func dialRaw(data []byte) (*websocket.Conn, error) {
|
||||
var conn *websocket.Conn
|
||||
for {
|
||||
conn = <-conns
|
||||
@@ -158,7 +100,7 @@ func dialTask(task task) (*websocket.Conn, error) {
|
||||
break
|
||||
}
|
||||
}
|
||||
err = CheckOK(conn)
|
||||
err := CheckOK(conn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@@ -14,28 +14,10 @@
|
||||
let upstreamGetCount = 0;
|
||||
let upstreamWsCount = 0;
|
||||
let upstreamPostCount = 0;
|
||||
|
||||
function prepareRequestInit(extra) {
|
||||
const requestInit = {};
|
||||
if (extra.referrer) {
|
||||
// note: we have to strip the protocol and host part.
|
||||
// Browsers disallow that, and will reset the value to current page if attempted.
|
||||
const referrer = URL.parse(extra.referrer);
|
||||
requestInit.referrer = referrer.pathname + referrer.search + referrer.hash;
|
||||
requestInit.referrerPolicy = "unsafe-url";
|
||||
}
|
||||
|
||||
if (extra.headers) {
|
||||
requestInit.headers = extra.headers;
|
||||
}
|
||||
|
||||
return requestInit;
|
||||
}
|
||||
|
||||
let check = function () {
|
||||
if (clientIdleCount > 0) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
clientIdleCount += 1;
|
||||
console.log("Prepare", url);
|
||||
let ws = new WebSocket(url);
|
||||
@@ -47,12 +29,12 @@
|
||||
// double-checking that this continues to work
|
||||
ws.onmessage = function (event) {
|
||||
clientIdleCount -= 1;
|
||||
let task = JSON.parse(event.data);
|
||||
switch (task.method) {
|
||||
let [method, url, protocol] = event.data.split(" ");
|
||||
switch (method) {
|
||||
case "WS": {
|
||||
upstreamWsCount += 1;
|
||||
console.log("Dial WS", task.url, task.extra.protocol);
|
||||
const wss = new WebSocket(task.url, task.extra.protocol);
|
||||
console.log("Dial WS", url, protocol);
|
||||
const wss = new WebSocket(url, protocol);
|
||||
wss.binaryType = "arraybuffer";
|
||||
let opened = false;
|
||||
ws.onmessage = function (event) {
|
||||
@@ -78,12 +60,10 @@
|
||||
wss.close()
|
||||
};
|
||||
break;
|
||||
}
|
||||
};
|
||||
case "GET": {
|
||||
(async () => {
|
||||
const requestInit = prepareRequestInit(task.extra);
|
||||
|
||||
console.log("Dial GET", task.url);
|
||||
console.log("Dial GET", url);
|
||||
ws.send("ok");
|
||||
const controller = new AbortController();
|
||||
|
||||
@@ -103,62 +83,58 @@
|
||||
ws.onclose = (event) => {
|
||||
try {
|
||||
reader && reader.cancel();
|
||||
} catch(e) {}
|
||||
} catch(e) {};
|
||||
|
||||
try {
|
||||
controller.abort();
|
||||
} catch(e) {}
|
||||
} catch(e) {};
|
||||
};
|
||||
|
||||
try {
|
||||
upstreamGetCount += 1;
|
||||
|
||||
requestInit.signal = controller.signal;
|
||||
const response = await fetch(task.url, requestInit);
|
||||
const response = await fetch(url, {signal: controller.signal});
|
||||
|
||||
const body = await response.body;
|
||||
reader = body.getReader();
|
||||
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (value) ws.send(value); // don't send back "undefined" string when received nothing
|
||||
ws.send(value);
|
||||
if (done) break;
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
upstreamGetCount -= 1;
|
||||
console.log("Dial GET DONE, remaining: ", upstreamGetCount);
|
||||
ws.close();
|
||||
}
|
||||
};
|
||||
})();
|
||||
break;
|
||||
}
|
||||
};
|
||||
case "POST": {
|
||||
upstreamPostCount += 1;
|
||||
|
||||
const requestInit = prepareRequestInit(task.extra);
|
||||
requestInit.method = "POST";
|
||||
|
||||
console.log("Dial POST", task.url);
|
||||
console.log("Dial POST", url);
|
||||
ws.send("ok");
|
||||
ws.onmessage = async (event) => {
|
||||
try {
|
||||
requestInit.body = event.data;
|
||||
const response = await fetch(task.url, requestInit);
|
||||
const response = await fetch(
|
||||
url,
|
||||
{method: "POST", body: event.data}
|
||||
);
|
||||
if (response.ok) {
|
||||
ws.send("ok");
|
||||
} else {
|
||||
console.error("bad status code");
|
||||
ws.send("fail");
|
||||
}
|
||||
};
|
||||
} finally {
|
||||
upstreamPostCount -= 1;
|
||||
console.log("Dial POST DONE, remaining: ", upstreamPostCount);
|
||||
ws.close();
|
||||
}
|
||||
};
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
check();
|
||||
};
|
||||
|
@@ -95,67 +95,6 @@ func (DomainStrategy) EnumDescriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type AddressPortStrategy int32
|
||||
|
||||
const (
|
||||
AddressPortStrategy_None AddressPortStrategy = 0
|
||||
AddressPortStrategy_SrvPortOnly AddressPortStrategy = 1
|
||||
AddressPortStrategy_SrvAddressOnly AddressPortStrategy = 2
|
||||
AddressPortStrategy_SrvPortAndAddress AddressPortStrategy = 3
|
||||
AddressPortStrategy_TxtPortOnly AddressPortStrategy = 4
|
||||
AddressPortStrategy_TxtAddressOnly AddressPortStrategy = 5
|
||||
AddressPortStrategy_TxtPortAndAddress AddressPortStrategy = 6
|
||||
)
|
||||
|
||||
// Enum value maps for AddressPortStrategy.
|
||||
var (
|
||||
AddressPortStrategy_name = map[int32]string{
|
||||
0: "None",
|
||||
1: "SrvPortOnly",
|
||||
2: "SrvAddressOnly",
|
||||
3: "SrvPortAndAddress",
|
||||
4: "TxtPortOnly",
|
||||
5: "TxtAddressOnly",
|
||||
6: "TxtPortAndAddress",
|
||||
}
|
||||
AddressPortStrategy_value = map[string]int32{
|
||||
"None": 0,
|
||||
"SrvPortOnly": 1,
|
||||
"SrvAddressOnly": 2,
|
||||
"SrvPortAndAddress": 3,
|
||||
"TxtPortOnly": 4,
|
||||
"TxtAddressOnly": 5,
|
||||
"TxtPortAndAddress": 6,
|
||||
}
|
||||
)
|
||||
|
||||
func (x AddressPortStrategy) Enum() *AddressPortStrategy {
|
||||
p := new(AddressPortStrategy)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x AddressPortStrategy) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (AddressPortStrategy) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_transport_internet_config_proto_enumTypes[1].Descriptor()
|
||||
}
|
||||
|
||||
func (AddressPortStrategy) Type() protoreflect.EnumType {
|
||||
return &file_transport_internet_config_proto_enumTypes[1]
|
||||
}
|
||||
|
||||
func (x AddressPortStrategy) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AddressPortStrategy.Descriptor instead.
|
||||
func (AddressPortStrategy) EnumDescriptor() ([]byte, []int) {
|
||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
type SocketConfig_TProxyMode int32
|
||||
|
||||
const (
|
||||
@@ -192,11 +131,11 @@ func (x SocketConfig_TProxyMode) String() string {
|
||||
}
|
||||
|
||||
func (SocketConfig_TProxyMode) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_transport_internet_config_proto_enumTypes[2].Descriptor()
|
||||
return file_transport_internet_config_proto_enumTypes[1].Descriptor()
|
||||
}
|
||||
|
||||
func (SocketConfig_TProxyMode) Type() protoreflect.EnumType {
|
||||
return &file_transport_internet_config_proto_enumTypes[2]
|
||||
return &file_transport_internet_config_proto_enumTypes[1]
|
||||
}
|
||||
|
||||
func (x SocketConfig_TProxyMode) Number() protoreflect.EnumNumber {
|
||||
@@ -495,24 +434,23 @@ type SocketConfig struct {
|
||||
Tproxy SocketConfig_TProxyMode `protobuf:"varint,3,opt,name=tproxy,proto3,enum=xray.transport.internet.SocketConfig_TProxyMode" json:"tproxy,omitempty"`
|
||||
// ReceiveOriginalDestAddress is for enabling IP_RECVORIGDSTADDR socket
|
||||
// option. This option is for UDP only.
|
||||
ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"`
|
||||
BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"`
|
||||
BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"`
|
||||
AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"`
|
||||
DomainStrategy DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
|
||||
DialerProxy string `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"`
|
||||
TcpKeepAliveInterval int32 `protobuf:"varint,10,opt,name=tcp_keep_alive_interval,json=tcpKeepAliveInterval,proto3" json:"tcp_keep_alive_interval,omitempty"`
|
||||
TcpKeepAliveIdle int32 `protobuf:"varint,11,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"`
|
||||
TcpCongestion string `protobuf:"bytes,12,opt,name=tcp_congestion,json=tcpCongestion,proto3" json:"tcp_congestion,omitempty"`
|
||||
Interface string `protobuf:"bytes,13,opt,name=interface,proto3" json:"interface,omitempty"`
|
||||
V6Only bool `protobuf:"varint,14,opt,name=v6only,proto3" json:"v6only,omitempty"`
|
||||
TcpWindowClamp int32 `protobuf:"varint,15,opt,name=tcp_window_clamp,json=tcpWindowClamp,proto3" json:"tcp_window_clamp,omitempty"`
|
||||
TcpUserTimeout int32 `protobuf:"varint,16,opt,name=tcp_user_timeout,json=tcpUserTimeout,proto3" json:"tcp_user_timeout,omitempty"`
|
||||
TcpMaxSeg int32 `protobuf:"varint,17,opt,name=tcp_max_seg,json=tcpMaxSeg,proto3" json:"tcp_max_seg,omitempty"`
|
||||
Penetrate bool `protobuf:"varint,18,opt,name=penetrate,proto3" json:"penetrate,omitempty"`
|
||||
TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"`
|
||||
CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"`
|
||||
AddressPortStrategy AddressPortStrategy `protobuf:"varint,21,opt,name=address_port_strategy,json=addressPortStrategy,proto3,enum=xray.transport.internet.AddressPortStrategy" json:"address_port_strategy,omitempty"`
|
||||
ReceiveOriginalDestAddress bool `protobuf:"varint,4,opt,name=receive_original_dest_address,json=receiveOriginalDestAddress,proto3" json:"receive_original_dest_address,omitempty"`
|
||||
BindAddress []byte `protobuf:"bytes,5,opt,name=bind_address,json=bindAddress,proto3" json:"bind_address,omitempty"`
|
||||
BindPort uint32 `protobuf:"varint,6,opt,name=bind_port,json=bindPort,proto3" json:"bind_port,omitempty"`
|
||||
AcceptProxyProtocol bool `protobuf:"varint,7,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"`
|
||||
DomainStrategy DomainStrategy `protobuf:"varint,8,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
|
||||
DialerProxy string `protobuf:"bytes,9,opt,name=dialer_proxy,json=dialerProxy,proto3" json:"dialer_proxy,omitempty"`
|
||||
TcpKeepAliveInterval int32 `protobuf:"varint,10,opt,name=tcp_keep_alive_interval,json=tcpKeepAliveInterval,proto3" json:"tcp_keep_alive_interval,omitempty"`
|
||||
TcpKeepAliveIdle int32 `protobuf:"varint,11,opt,name=tcp_keep_alive_idle,json=tcpKeepAliveIdle,proto3" json:"tcp_keep_alive_idle,omitempty"`
|
||||
TcpCongestion string `protobuf:"bytes,12,opt,name=tcp_congestion,json=tcpCongestion,proto3" json:"tcp_congestion,omitempty"`
|
||||
Interface string `protobuf:"bytes,13,opt,name=interface,proto3" json:"interface,omitempty"`
|
||||
V6Only bool `protobuf:"varint,14,opt,name=v6only,proto3" json:"v6only,omitempty"`
|
||||
TcpWindowClamp int32 `protobuf:"varint,15,opt,name=tcp_window_clamp,json=tcpWindowClamp,proto3" json:"tcp_window_clamp,omitempty"`
|
||||
TcpUserTimeout int32 `protobuf:"varint,16,opt,name=tcp_user_timeout,json=tcpUserTimeout,proto3" json:"tcp_user_timeout,omitempty"`
|
||||
TcpMaxSeg int32 `protobuf:"varint,17,opt,name=tcp_max_seg,json=tcpMaxSeg,proto3" json:"tcp_max_seg,omitempty"`
|
||||
Penetrate bool `protobuf:"varint,18,opt,name=penetrate,proto3" json:"penetrate,omitempty"`
|
||||
TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"`
|
||||
CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"`
|
||||
}
|
||||
|
||||
func (x *SocketConfig) Reset() {
|
||||
@@ -685,13 +623,6 @@ func (x *SocketConfig) GetCustomSockopt() []*CustomSockopt {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SocketConfig) GetAddressPortStrategy() AddressPortStrategy {
|
||||
if x != nil {
|
||||
return x.AddressPortStrategy
|
||||
}
|
||||
return AddressPortStrategy_None
|
||||
}
|
||||
|
||||
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_transport_internet_config_proto_rawDesc = []byte{
|
||||
@@ -747,7 +678,7 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
||||
0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
|
||||
0x65, 0x22, 0xfd, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x65, 0x22, 0x9b, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
|
||||
0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f,
|
||||
@@ -801,44 +732,28 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
||||
0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
|
||||
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
||||
0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x52,
|
||||
0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x12, 0x60,
|
||||
0x0a, 0x15, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
|
||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50,
|
||||
0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x13, 0x61, 0x64, 0x64,
|
||||
0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||
0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07,
|
||||
0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78,
|
||||
0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10,
|
||||
0x02, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61,
|
||||
0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12,
|
||||
0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55,
|
||||
0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f,
|
||||
0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34,
|
||||
0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10,
|
||||
0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12,
|
||||
0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d,
|
||||
0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a,
|
||||
0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a,
|
||||
0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x2a, 0x97, 0x01,
|
||||
0x0a, 0x13, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72,
|
||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12,
|
||||
0x0f, 0x0a, 0x0b, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x01,
|
||||
0x12, 0x12, 0x0a, 0x0e, 0x53, 0x72, 0x76, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e,
|
||||
0x6c, 0x79, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x41,
|
||||
0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54,
|
||||
0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e,
|
||||
0x54, 0x78, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x05,
|
||||
0x12, 0x15, 0x0a, 0x11, 0x54, 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x6e, 0x64, 0x41, 0x64,
|
||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x06, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e,
|
||||
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x22, 0x2f,
|
||||
0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03,
|
||||
0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10,
|
||||
0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a,
|
||||
0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
|
||||
0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a,
|
||||
0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45,
|
||||
0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50,
|
||||
0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10,
|
||||
0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12,
|
||||
0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a,
|
||||
0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09,
|
||||
0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46,
|
||||
0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46,
|
||||
0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x42, 0x67, 0x0a, 0x1b, 0x63,
|
||||
0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -853,35 +768,33 @@ func file_transport_internet_config_proto_rawDescGZIP() []byte {
|
||||
return file_transport_internet_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
|
||||
var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||
var file_transport_internet_config_proto_goTypes = []any{
|
||||
(DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy
|
||||
(AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy
|
||||
(SocketConfig_TProxyMode)(0), // 2: xray.transport.internet.SocketConfig.TProxyMode
|
||||
(*TransportConfig)(nil), // 3: xray.transport.internet.TransportConfig
|
||||
(*StreamConfig)(nil), // 4: xray.transport.internet.StreamConfig
|
||||
(*ProxyConfig)(nil), // 5: xray.transport.internet.ProxyConfig
|
||||
(*CustomSockopt)(nil), // 6: xray.transport.internet.CustomSockopt
|
||||
(*SocketConfig)(nil), // 7: xray.transport.internet.SocketConfig
|
||||
(*serial.TypedMessage)(nil), // 8: xray.common.serial.TypedMessage
|
||||
(*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain
|
||||
(SocketConfig_TProxyMode)(0), // 1: xray.transport.internet.SocketConfig.TProxyMode
|
||||
(*TransportConfig)(nil), // 2: xray.transport.internet.TransportConfig
|
||||
(*StreamConfig)(nil), // 3: xray.transport.internet.StreamConfig
|
||||
(*ProxyConfig)(nil), // 4: xray.transport.internet.ProxyConfig
|
||||
(*CustomSockopt)(nil), // 5: xray.transport.internet.CustomSockopt
|
||||
(*SocketConfig)(nil), // 6: xray.transport.internet.SocketConfig
|
||||
(*serial.TypedMessage)(nil), // 7: xray.common.serial.TypedMessage
|
||||
(*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain
|
||||
}
|
||||
var file_transport_internet_config_proto_depIdxs = []int32{
|
||||
8, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
||||
9, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
|
||||
3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig
|
||||
8, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
|
||||
7, // 4: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
|
||||
2, // 5: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
|
||||
7, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
||||
8, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
|
||||
2, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig
|
||||
7, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
|
||||
6, // 4: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
|
||||
1, // 5: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
|
||||
0, // 6: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||
6, // 7: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
|
||||
1, // 8: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy
|
||||
9, // [9:9] is the sub-list for method output_type
|
||||
9, // [9:9] is the sub-list for method input_type
|
||||
9, // [9:9] is the sub-list for extension type_name
|
||||
9, // [9:9] is the sub-list for extension extendee
|
||||
0, // [0:9] is the sub-list for field type_name
|
||||
5, // 7: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
|
||||
8, // [8:8] is the sub-list for method output_type
|
||||
8, // [8:8] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_transport_internet_config_proto_init() }
|
||||
@@ -894,7 +807,7 @@ func file_transport_internet_config_proto_init() {
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_transport_internet_config_proto_rawDesc,
|
||||
NumEnums: 3,
|
||||
NumEnums: 2,
|
||||
NumMessages: 5,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
|
@@ -23,16 +23,6 @@ enum DomainStrategy {
|
||||
FORCE_IP64 = 10;
|
||||
}
|
||||
|
||||
enum AddressPortStrategy {
|
||||
None = 0;
|
||||
SrvPortOnly = 1;
|
||||
SrvAddressOnly = 2;
|
||||
SrvPortAndAddress = 3;
|
||||
TxtPortOnly = 4;
|
||||
TxtAddressOnly = 5;
|
||||
TxtPortAndAddress = 6;
|
||||
}
|
||||
|
||||
message TransportConfig {
|
||||
// Transport protocol name.
|
||||
string protocol_name = 3;
|
||||
@@ -126,6 +116,4 @@ message SocketConfig {
|
||||
bool tcp_mptcp = 19;
|
||||
|
||||
repeated CustomSockopt customSockopt = 20;
|
||||
|
||||
AddressPortStrategy address_port_strategy = 21;
|
||||
}
|
||||
|
@@ -2,9 +2,6 @@ package internet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
gonet "net"
|
||||
"strings"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/dice"
|
||||
@@ -143,93 +140,6 @@ func redirect(ctx context.Context, dst net.Destination, obt string) net.Conn {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkAddressPortStrategy(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (*net.Destination, error) {
|
||||
if sockopt.AddressPortStrategy == AddressPortStrategy_None {
|
||||
return nil, nil
|
||||
}
|
||||
newDest := dest
|
||||
var OverridePort, OverrideAddress bool
|
||||
var OverrideBy string
|
||||
switch sockopt.AddressPortStrategy {
|
||||
case AddressPortStrategy_SrvPortOnly:
|
||||
OverridePort = true
|
||||
OverrideAddress = false
|
||||
OverrideBy = "srv"
|
||||
case AddressPortStrategy_SrvAddressOnly:
|
||||
OverridePort = false
|
||||
OverrideAddress = true
|
||||
OverrideBy = "srv"
|
||||
case AddressPortStrategy_SrvPortAndAddress:
|
||||
OverridePort = true
|
||||
OverrideAddress = true
|
||||
OverrideBy = "srv"
|
||||
case AddressPortStrategy_TxtPortOnly:
|
||||
OverridePort = true
|
||||
OverrideAddress = false
|
||||
OverrideBy = "txt"
|
||||
case AddressPortStrategy_TxtAddressOnly:
|
||||
OverridePort = false
|
||||
OverrideAddress = true
|
||||
OverrideBy = "txt"
|
||||
case AddressPortStrategy_TxtPortAndAddress:
|
||||
OverridePort = true
|
||||
OverrideAddress = true
|
||||
OverrideBy = "txt"
|
||||
default:
|
||||
return nil, errors.New("unknown AddressPortStrategy")
|
||||
}
|
||||
|
||||
if !dest.Address.Family().IsDomain() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if OverrideBy == "srv" {
|
||||
errors.LogDebug(ctx, "query SRV record for "+dest.Address.String())
|
||||
parts := strings.SplitN(dest.Address.String(), ".", 3)
|
||||
if len(parts) != 3 {
|
||||
return nil, errors.New("invalid address format", dest.Address.String())
|
||||
}
|
||||
_, srvRecords, err := gonet.DefaultResolver.LookupSRV(context.Background(), parts[0][1:], parts[1][1:], parts[2])
|
||||
if err != nil {
|
||||
return nil, errors.New("failed to lookup SRV record").Base(err)
|
||||
}
|
||||
errors.LogDebug(ctx, "SRV record: "+fmt.Sprintf("addr=%s, port=%d, priority=%d, weight=%d", srvRecords[0].Target, srvRecords[0].Port, srvRecords[0].Priority, srvRecords[0].Weight))
|
||||
if OverridePort {
|
||||
newDest.Port = net.Port(srvRecords[0].Port)
|
||||
}
|
||||
if OverrideAddress {
|
||||
newDest.Address = net.ParseAddress(srvRecords[0].Target)
|
||||
}
|
||||
return &newDest, nil
|
||||
}
|
||||
if OverrideBy == "txt" {
|
||||
errors.LogDebug(ctx, "query TXT record for "+dest.Address.String())
|
||||
txtRecords, err := gonet.DefaultResolver.LookupTXT(ctx, dest.Address.String())
|
||||
if err != nil {
|
||||
errors.LogError(ctx, "failed to lookup SRV record: "+err.Error())
|
||||
return nil, errors.New("failed to lookup SRV record").Base(err)
|
||||
}
|
||||
for _, txtRecord := range txtRecords {
|
||||
errors.LogDebug(ctx, "TXT record: "+txtRecord)
|
||||
addr_s, port_s, _ := net.SplitHostPort(string(txtRecord))
|
||||
addr := net.ParseAddress(addr_s)
|
||||
port, err := net.PortFromString(port_s)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if OverridePort {
|
||||
newDest.Port = port
|
||||
}
|
||||
if OverrideAddress {
|
||||
newDest.Address = addr
|
||||
}
|
||||
return &newDest, nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// DialSystem calls system dialer to create a network connection.
|
||||
func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
|
||||
var src net.Address
|
||||
@@ -242,11 +152,6 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
|
||||
return effectiveSystemDialer.Dial(ctx, src, dest, sockopt)
|
||||
}
|
||||
|
||||
if newDest, err := checkAddressPortStrategy(ctx, dest, sockopt); err == nil && newDest != nil {
|
||||
errors.LogInfo(ctx, "replace destination with "+newDest.String())
|
||||
dest = *newDest
|
||||
}
|
||||
|
||||
if canLookupIP(ctx, dest, sockopt) {
|
||||
ips, err := lookupIP(dest.Address.String(), sockopt.DomainStrategy, src)
|
||||
if err == nil && len(ips) > 0 {
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"crypto/ecdh"
|
||||
"crypto/ed25519"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
gotls "crypto/tls"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"regexp"
|
||||
@@ -25,7 +27,6 @@ import (
|
||||
|
||||
utls "github.com/refraction-networking/utls"
|
||||
"github.com/xtls/reality"
|
||||
"github.com/xtls/xray-core/common/crypto"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/core"
|
||||
@@ -179,12 +180,12 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
|
||||
prefix := []byte("https://" + uConn.ServerName)
|
||||
maps.Lock()
|
||||
if maps.maps == nil {
|
||||
maps.maps = make(map[string]map[string]struct{})
|
||||
maps.maps = make(map[string]map[string]bool)
|
||||
}
|
||||
paths := maps.maps[uConn.ServerName]
|
||||
if paths == nil {
|
||||
paths = make(map[string]struct{})
|
||||
paths[config.SpiderX] = struct{}{}
|
||||
paths = make(map[string]bool)
|
||||
paths[config.SpiderX] = true
|
||||
maps.maps[uConn.ServerName] = paths
|
||||
}
|
||||
firstURL := string(prefix) + getPathLocked(paths)
|
||||
@@ -212,13 +213,13 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
|
||||
}
|
||||
times := 1
|
||||
if !first {
|
||||
times = int(crypto.RandBetween(config.SpiderY[4], config.SpiderY[5]))
|
||||
times = int(randBetween(config.SpiderY[4], config.SpiderY[5]))
|
||||
}
|
||||
for j := 0; j < times; j++ {
|
||||
if !first && j == 0 {
|
||||
req.Header.Set("Referer", firstURL)
|
||||
}
|
||||
req.AddCookie(&http.Cookie{Name: "padding", Value: strings.Repeat("0", int(crypto.RandBetween(config.SpiderY[0], config.SpiderY[1])))})
|
||||
req.AddCookie(&http.Cookie{Name: "padding", Value: strings.Repeat("0", int(randBetween(config.SpiderY[0], config.SpiderY[1])))})
|
||||
if resp, err = client.Do(req); err != nil {
|
||||
break
|
||||
}
|
||||
@@ -231,7 +232,7 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
|
||||
for _, m := range href.FindAllSubmatch(body, -1) {
|
||||
m[1] = bytes.TrimPrefix(m[1], prefix)
|
||||
if !bytes.Contains(m[1], dot) {
|
||||
paths[string(m[1])] = struct{}{}
|
||||
paths[string(m[1])] = true
|
||||
}
|
||||
}
|
||||
req.URL.Path = getPathLocked(paths)
|
||||
@@ -242,18 +243,18 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
|
||||
}
|
||||
maps.Unlock()
|
||||
if !first {
|
||||
time.Sleep(time.Duration(crypto.RandBetween(config.SpiderY[6], config.SpiderY[7])) * time.Millisecond) // interval
|
||||
time.Sleep(time.Duration(randBetween(config.SpiderY[6], config.SpiderY[7])) * time.Millisecond) // interval
|
||||
}
|
||||
}
|
||||
}
|
||||
get(true)
|
||||
concurrency := int(crypto.RandBetween(config.SpiderY[2], config.SpiderY[3]))
|
||||
concurrency := int(randBetween(config.SpiderY[2], config.SpiderY[3]))
|
||||
for i := 0; i < concurrency; i++ {
|
||||
go get(false)
|
||||
}
|
||||
// Do not close the connection
|
||||
}()
|
||||
time.Sleep(time.Duration(crypto.RandBetween(config.SpiderY[8], config.SpiderY[9])) * time.Millisecond) // return
|
||||
time.Sleep(time.Duration(randBetween(config.SpiderY[8], config.SpiderY[9])) * time.Millisecond) // return
|
||||
return nil, errors.New("REALITY: processed invalid connection").AtWarning()
|
||||
}
|
||||
return uConn, nil
|
||||
@@ -266,11 +267,11 @@ var (
|
||||
|
||||
var maps struct {
|
||||
sync.Mutex
|
||||
maps map[string]map[string]struct{}
|
||||
maps map[string]map[string]bool
|
||||
}
|
||||
|
||||
func getPathLocked(paths map[string]struct{}) string {
|
||||
stopAt := int(crypto.RandBetween(0, int64(len(paths)-1)))
|
||||
func getPathLocked(paths map[string]bool) string {
|
||||
stopAt := int(randBetween(0, int64(len(paths)-1)))
|
||||
i := 0
|
||||
for s := range paths {
|
||||
if i == stopAt {
|
||||
@@ -280,3 +281,11 @@ func getPathLocked(paths map[string]struct{}) string {
|
||||
}
|
||||
return "/"
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
@@ -5,15 +5,13 @@ import (
|
||||
"io"
|
||||
gonet "net"
|
||||
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/transport/internet/browser_dialer"
|
||||
"github.com/xtls/xray-core/transport/internet/websocket"
|
||||
)
|
||||
|
||||
// BrowserDialerClient implements splithttp.DialerClient in terms of browser dialer
|
||||
type BrowserDialerClient struct {
|
||||
transportConfig *Config
|
||||
}
|
||||
// implements splithttp.DialerClient in terms of browser dialer
|
||||
// has no fields because everything is global state :O)
|
||||
type BrowserDialerClient struct{}
|
||||
|
||||
func (c *BrowserDialerClient) IsClosed() bool {
|
||||
panic("not implemented yet")
|
||||
@@ -21,10 +19,10 @@ func (c *BrowserDialerClient) IsClosed() bool {
|
||||
|
||||
func (c *BrowserDialerClient) OpenStream(ctx context.Context, url string, body io.Reader, uploadOnly bool) (io.ReadCloser, gonet.Addr, gonet.Addr, error) {
|
||||
if body != nil {
|
||||
return nil, nil, nil, errors.New("bidirectional streaming for browser dialer not implemented yet")
|
||||
panic("not implemented yet")
|
||||
}
|
||||
|
||||
conn, err := browser_dialer.DialGet(url, c.transportConfig.GetRequestHeader(url))
|
||||
conn, err := browser_dialer.DialGet(url)
|
||||
dummyAddr := &gonet.IPAddr{}
|
||||
if err != nil {
|
||||
return nil, dummyAddr, dummyAddr, err
|
||||
@@ -39,7 +37,7 @@ func (c *BrowserDialerClient) PostPacket(ctx context.Context, url string, body i
|
||||
return err
|
||||
}
|
||||
|
||||
err = browser_dialer.DialPost(url, c.transportConfig.GetRequestHeader(url), bytes)
|
||||
err = browser_dialer.DialPost(url, bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@@ -55,12 +55,12 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, body i
|
||||
},
|
||||
})
|
||||
|
||||
method := "GET" // stream-down
|
||||
method := "GET"
|
||||
if body != nil {
|
||||
method = "POST" // stream-up/one
|
||||
method = "POST"
|
||||
}
|
||||
req, _ := http.NewRequestWithContext(context.WithoutCancel(ctx), method, url, body)
|
||||
req.Header = c.transportConfig.GetRequestHeader(url)
|
||||
req, _ := http.NewRequestWithContext(ctx, method, url, body)
|
||||
req.Header = c.transportConfig.GetRequestHeader()
|
||||
if method == "POST" && !c.transportConfig.NoGRPCHeader {
|
||||
req.Header.Set("Content-Type", "application/grpc")
|
||||
}
|
||||
@@ -69,20 +69,17 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, body i
|
||||
go func() {
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
if !uploadOnly { // stream-down is enough
|
||||
c.closed = true
|
||||
errors.LogInfoInner(ctx, err, "failed to "+method+" "+url)
|
||||
}
|
||||
errors.LogInfoInner(ctx, err, "failed to "+method+" "+url)
|
||||
gotConn.Close()
|
||||
wrc.Close()
|
||||
return
|
||||
}
|
||||
if resp.StatusCode != 200 && !uploadOnly {
|
||||
// c.closed = true
|
||||
errors.LogInfo(ctx, "unexpected status ", resp.StatusCode)
|
||||
}
|
||||
if resp.StatusCode != 200 || uploadOnly { // stream-up
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
resp.Body.Close() // if it is called immediately, the upload will be interrupted also
|
||||
if resp.StatusCode != 200 || uploadOnly {
|
||||
resp.Body.Close()
|
||||
wrc.Close()
|
||||
return
|
||||
}
|
||||
@@ -94,24 +91,23 @@ func (c *DefaultDialerClient) OpenStream(ctx context.Context, url string, body i
|
||||
}
|
||||
|
||||
func (c *DefaultDialerClient) PostPacket(ctx context.Context, url string, body io.Reader, contentLength int64) error {
|
||||
req, err := http.NewRequestWithContext(context.WithoutCancel(ctx), "POST", url, body)
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", url, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req.ContentLength = contentLength
|
||||
req.Header = c.transportConfig.GetRequestHeader(url)
|
||||
req.Header = c.transportConfig.GetRequestHeader()
|
||||
|
||||
if c.httpVersion != "1.1" {
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
c.closed = true
|
||||
return err
|
||||
}
|
||||
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
// c.closed = true
|
||||
return errors.New("bad status code:", resp.Status)
|
||||
}
|
||||
} else {
|
||||
@@ -143,12 +139,11 @@ func (c *DefaultDialerClient) PostPacket(ctx context.Context, url string, body i
|
||||
if h1UploadConn.UnreadedResponsesCount > 0 {
|
||||
resp, err := http.ReadResponse(h1UploadConn.RespBufReader, req)
|
||||
if err != nil {
|
||||
c.closed = true
|
||||
return fmt.Errorf("error while reading response: %s", err.Error())
|
||||
}
|
||||
io.Copy(io.Discard, resp.Body)
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != 200 {
|
||||
// c.closed = true
|
||||
// resp.Body.Close() // I'm not sure
|
||||
return fmt.Errorf("got non-200 error response code: %d", resp.StatusCode)
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
package splithttp
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/crypto"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
)
|
||||
|
||||
@@ -33,31 +33,24 @@ func (c *Config) GetNormalizedQuery() string {
|
||||
query = pathAndQuery[1]
|
||||
}
|
||||
|
||||
/*
|
||||
if query != "" {
|
||||
query += "&"
|
||||
}
|
||||
query += "x_version=" + core.Version()
|
||||
*/
|
||||
if query != "" {
|
||||
query += "&"
|
||||
}
|
||||
|
||||
paddingLen := c.GetNormalizedXPaddingBytes().rand()
|
||||
if paddingLen > 0 {
|
||||
query += "x_padding=" + strings.Repeat("0", int(paddingLen))
|
||||
}
|
||||
|
||||
return query
|
||||
}
|
||||
|
||||
func (c *Config) GetRequestHeader(rawURL string) http.Header {
|
||||
func (c *Config) GetRequestHeader() http.Header {
|
||||
header := http.Header{}
|
||||
for k, v := range c.Headers {
|
||||
header.Add(k, v)
|
||||
}
|
||||
|
||||
u, _ := url.Parse(rawURL)
|
||||
// https://www.rfc-editor.org/rfc/rfc7541.html#appendix-B
|
||||
// h2's HPACK Header Compression feature employs a huffman encoding using a static table.
|
||||
// 'X' is assigned an 8 bit code, so HPACK compression won't change actual padding length on the wire.
|
||||
// https://www.rfc-editor.org/rfc/rfc9204.html#section-4.1.2-2
|
||||
// h3's similar QPACK feature uses the same huffman table.
|
||||
u.RawQuery = "x_padding=" + strings.Repeat("X", int(c.GetNormalizedXPaddingBytes().rand()))
|
||||
header.Set("Referer", u.String())
|
||||
|
||||
return header
|
||||
}
|
||||
|
||||
@@ -65,8 +58,10 @@ func (c *Config) WriteResponseHeader(writer http.ResponseWriter) {
|
||||
// CORS headers for the browser dialer
|
||||
writer.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
writer.Header().Set("Access-Control-Allow-Methods", "GET, POST")
|
||||
// writer.Header().Set("X-Version", core.Version())
|
||||
writer.Header().Set("X-Padding", strings.Repeat("X", int(c.GetNormalizedXPaddingBytes().rand())))
|
||||
paddingLen := c.GetNormalizedXPaddingBytes().rand()
|
||||
if paddingLen > 0 {
|
||||
writer.Header().Set("X-Padding", strings.Repeat("0", int(paddingLen)))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) GetNormalizedXPaddingBytes() RangeConfig {
|
||||
@@ -110,17 +105,6 @@ func (c *Config) GetNormalizedScMaxBufferedPosts() int {
|
||||
return int(c.ScMaxBufferedPosts)
|
||||
}
|
||||
|
||||
func (c *Config) GetNormalizedScStreamUpServerSecs() RangeConfig {
|
||||
if c.ScStreamUpServerSecs == nil || c.ScStreamUpServerSecs.To == 0 {
|
||||
return RangeConfig{
|
||||
From: 20,
|
||||
To: 80,
|
||||
}
|
||||
}
|
||||
|
||||
return *c.ScMinPostsIntervalMs
|
||||
}
|
||||
|
||||
func (m *XmuxConfig) GetNormalizedMaxConcurrency() RangeConfig {
|
||||
if m.MaxConcurrency == nil {
|
||||
return RangeConfig{
|
||||
@@ -183,5 +167,9 @@ func init() {
|
||||
}
|
||||
|
||||
func (c RangeConfig) rand() int32 {
|
||||
return int32(crypto.RandBetween(int64(c.From), int64(c.To)))
|
||||
if c.From == c.To {
|
||||
return c.From
|
||||
}
|
||||
bigInt, _ := rand.Int(rand.Reader, big.NewInt(int64(c.To-c.From)))
|
||||
return c.From + int32(bigInt.Int64())
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user