mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-24 02:26:48 +08:00
Compare commits
378 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6f9df63c70 | ||
![]() |
253a422467 | ||
![]() |
72bbc5ae0e | ||
![]() |
ee21763928 | ||
![]() |
667279af57 | ||
![]() |
62e881b01a | ||
![]() |
9122d0f056 | ||
![]() |
def5807c64 | ||
![]() |
084f4f2e4c | ||
![]() |
65b467e448 | ||
![]() |
37e1e401a8 | ||
![]() |
e8616c6087 | ||
![]() |
ca6af4c19d | ||
![]() |
8852d02099 | ||
![]() |
9112cfd39c | ||
![]() |
bf4b1fab3c | ||
![]() |
d11d72be6c | ||
![]() |
c9f517108c | ||
![]() |
038f849dd3 | ||
![]() |
a4e80f01e4 | ||
![]() |
86b4b81f1d | ||
![]() |
6b8e36f6ee | ||
![]() |
5f5ae37571 | ||
![]() |
c80646a045 | ||
![]() |
51b2922427 | ||
![]() |
19d3a4faba | ||
![]() |
f58fededc5 | ||
![]() |
bb26f8576b | ||
![]() |
e7324700ed | ||
![]() |
cb7e081000 | ||
![]() |
70b8b2aaca | ||
![]() |
ecedc51173 | ||
![]() |
d9af02812f | ||
![]() |
6cc5d1de44 | ||
![]() |
1f2ffb5222 | ||
![]() |
a514d48bae | ||
![]() |
37c8957495 | ||
![]() |
f3231fb94e | ||
![]() |
bfd5da2f00 | ||
![]() |
ae518cce52 | ||
![]() |
dd81ad5342 | ||
![]() |
18e5b0963f | ||
![]() |
90d915ea05 | ||
![]() |
d9994538bc | ||
![]() |
69aa3f48cc | ||
![]() |
ca32496a38 | ||
![]() |
d3060c28f8 | ||
![]() |
ac8109eef8 | ||
![]() |
197bc78ea1 | ||
![]() |
039e5f2078 | ||
![]() |
242f3b0e0b | ||
![]() |
b4c1a56026 | ||
![]() |
9f8e9e8e64 | ||
![]() |
06c9e50c52 | ||
![]() |
4f601530fa | ||
![]() |
b33b0bc89d | ||
![]() |
01b7e5e9be | ||
![]() |
24a2be43ef | ||
![]() |
29d7865d78 | ||
![]() |
05d24d6827 | ||
![]() |
76b27a37cb | ||
![]() |
15cf31f30a | ||
![]() |
54ad0e96a0 | ||
![]() |
be23d5d3b7 | ||
![]() |
67affe3753 | ||
![]() |
2c0a89f7dc | ||
![]() |
a4d1509c23 | ||
![]() |
f4ab8d7e8b | ||
![]() |
beb603af06 | ||
![]() |
a0d06f3a97 | ||
![]() |
526c6789ed | ||
![]() |
6872be5cc3 | ||
![]() |
c6b78318cb | ||
![]() |
f89998fc77 | ||
![]() |
0573760346 | ||
![]() |
172f353bd7 | ||
![]() |
55efac7236 | ||
![]() |
f57ec13880 | ||
![]() |
f1e35ad9d4 | ||
![]() |
d6801ab031 | ||
![]() |
c3322294be | ||
![]() |
836e84b851 | ||
![]() |
4a0b45d1ff | ||
![]() |
c04c333afc | ||
![]() |
9e5bc07bf2 | ||
![]() |
4c8ee0af50 | ||
![]() |
25ea69fc3a | ||
![]() |
a4790133d2 | ||
![]() |
ccba465590 | ||
![]() |
6526e74d49 | ||
![]() |
7b54255cc1 | ||
![]() |
43bc929030 | ||
![]() |
fbc7c1cf84 | ||
![]() |
cc4be239cf | ||
![]() |
2d898480be | ||
![]() |
55dc26f228 | ||
![]() |
9401d65ef1 | ||
![]() |
c38179a67f | ||
![]() |
a5b297f968 | ||
![]() |
d208fd31c9 | ||
![]() |
2e201c57cc | ||
![]() |
336b2daeb9 | ||
![]() |
c8b4580869 | ||
![]() |
03b8c094de | ||
![]() |
267d93f7bd | ||
![]() |
7f16f4ccd9 | ||
![]() |
9e07d8304d | ||
![]() |
9d3de59d3f | ||
![]() |
4d5c3195d2 | ||
![]() |
c7358a32f5 | ||
![]() |
e1cd1fd33e | ||
![]() |
82003f28b2 | ||
![]() |
4d2e2b24d3 | ||
![]() |
15999e5c2a | ||
![]() |
48ff0d92c9 | ||
![]() |
229e2513b5 | ||
![]() |
9046eda5ce | ||
![]() |
f32921df30 | ||
![]() |
c3faa8b7ac | ||
![]() |
00c9576118 | ||
![]() |
fa7300e910 | ||
![]() |
b57d3fa869 | ||
![]() |
53833c2323 | ||
![]() |
f176ec54ee | ||
![]() |
bf35e9dcd6 | ||
![]() |
dc72cf2c78 | ||
![]() |
74416570d4 | ||
![]() |
b70912799b | ||
![]() |
15bb23e4ec | ||
![]() |
915690b9ef | ||
![]() |
f571aa72df | ||
![]() |
fb212905bd | ||
![]() |
3fb67f065a | ||
![]() |
77d2f9edd7 | ||
![]() |
7added2693 | ||
![]() |
f536359367 | ||
![]() |
0d5c62e44d | ||
![]() |
620eb63c1b | ||
![]() |
32ce7cd730 | ||
![]() |
717518cb5f | ||
![]() |
7b8ff01114 | ||
![]() |
ed960cc885 | ||
![]() |
1bf3a632ca | ||
![]() |
ff5ce767df | ||
![]() |
8c0d3c0257 | ||
![]() |
9bc1564b0a | ||
![]() |
6a85682716 | ||
![]() |
6f61021f7a | ||
![]() |
c0ceebe709 | ||
![]() |
eaf401eda9 | ||
![]() |
11ec77bc76 | ||
![]() |
3b2ff95a9b | ||
![]() |
3db7d44fc2 | ||
![]() |
c4fbdf1b78 | ||
![]() |
c9b6fc0104 | ||
![]() |
d7ac6946d2 | ||
![]() |
48a75fc340 | ||
![]() |
a55cf1d0bf | ||
![]() |
f35ded79ad | ||
![]() |
f3104b8684 | ||
![]() |
bc4de6a026 | ||
![]() |
3e4e050313 | ||
![]() |
b8e8229242 | ||
![]() |
a8fa5bf516 | ||
![]() |
4a3f3ef775 | ||
![]() |
5858726233 | ||
![]() |
b13c3f053a | ||
![]() |
2e30093ffd | ||
![]() |
1d7c40d728 | ||
![]() |
143229b148 | ||
![]() |
79eda46c62 | ||
![]() |
d87758d46f | ||
![]() |
e5e9e58d66 | ||
![]() |
0565589b8b | ||
![]() |
3cf1b7e601 | ||
![]() |
e18b52a5df | ||
![]() |
691b2b1c73 | ||
![]() |
494a10971b | ||
![]() |
34b3f0204a | ||
![]() |
18fd768166 | ||
![]() |
07d4cfd81a | ||
![]() |
d3efd2d24f | ||
![]() |
aa846b8420 | ||
![]() |
8006430c15 | ||
![]() |
04278a8940 | ||
![]() |
48f7cc2132 | ||
![]() |
8e75e9d763 | ||
![]() |
c7f7e07821 | ||
![]() |
ff2cdcdaaa | ||
![]() |
095e6a714b | ||
![]() |
15d66974cc | ||
![]() |
8ef609ff46 | ||
![]() |
fffd908db2 | ||
![]() |
9b293013e6 | ||
![]() |
5e695327b1 | ||
![]() |
341d317d0c | ||
![]() |
87c1c426d5 | ||
![]() |
2637970976 | ||
![]() |
da0b13cca0 | ||
![]() |
1f93cbbc5d | ||
![]() |
149e2247e8 | ||
![]() |
51859425d7 | ||
![]() |
93c7ebe382 | ||
![]() |
ed9b99cfc8 | ||
![]() |
825fb9f8bd | ||
![]() |
8117b66949 | ||
![]() |
8cf23f1947 | ||
![]() |
43477109f5 | ||
![]() |
632cb34116 | ||
![]() |
79fdc5f6f7 | ||
![]() |
6bb735d103 | ||
![]() |
c21595a937 | ||
![]() |
92795677f9 | ||
![]() |
debd2e3ba8 | ||
![]() |
84537e98c4 | ||
![]() |
ed9ffa82c9 | ||
![]() |
b55b6bb5e0 | ||
![]() |
35d5a7fe93 | ||
![]() |
71a9a6dd55 | ||
![]() |
2096821c07 | ||
![]() |
4140bcd11a | ||
![]() |
59602db02d | ||
![]() |
76638d793c | ||
![]() |
b67314796f | ||
![]() |
340234166b | ||
![]() |
50b5ea5a54 | ||
![]() |
5e323958b6 | ||
![]() |
2b46178ff9 | ||
![]() |
c835622b37 | ||
![]() |
05483cc729 | ||
![]() |
b4e11e1856 | ||
![]() |
f956b142d8 | ||
![]() |
7d52ded2a3 | ||
![]() |
e459daaaf6 | ||
![]() |
00230a74d5 | ||
![]() |
9480bc0379 | ||
![]() |
0eed604ba3 | ||
![]() |
52930a16b2 | ||
![]() |
0f2a6f2088 | ||
![]() |
9f365b7b45 | ||
![]() |
a809596829 | ||
![]() |
7d946562eb | ||
![]() |
d4f18b1342 | ||
![]() |
ba4ce4c24f | ||
![]() |
a1c3aed9d3 | ||
![]() |
ec8904066a | ||
![]() |
def30a0882 | ||
![]() |
bd0cf955c7 | ||
![]() |
e91f033c01 | ||
![]() |
f1b70b4155 | ||
![]() |
cc67e83a8f | ||
![]() |
ea9246ec7f | ||
![]() |
0c9bd21b59 | ||
![]() |
34aab75484 | ||
![]() |
c3505632fd | ||
![]() |
6f93ef7736 | ||
![]() |
c4a307e84d | ||
![]() |
f1d753f069 | ||
![]() |
91ce752405 | ||
![]() |
f0b58d9ee0 | ||
![]() |
d56f38d38e | ||
![]() |
7b72e19e16 | ||
![]() |
4e5752f93e | ||
![]() |
36906d018d | ||
![]() |
79f3057687 | ||
![]() |
c375b144f8 | ||
![]() |
1edce576ca | ||
![]() |
cf7e675c45 | ||
![]() |
b6391cbbe1 | ||
![]() |
398375d76f | ||
![]() |
3b77e26fa7 | ||
![]() |
22706041d1 | ||
![]() |
087f0d1240 | ||
![]() |
3f64f3206c | ||
![]() |
f046feb9ca | ||
![]() |
778992eeb9 | ||
![]() |
5f3949a838 | ||
![]() |
95af983154 | ||
![]() |
63895caf60 | ||
![]() |
dcba88e511 | ||
![]() |
244db57398 | ||
![]() |
3bfd6853f4 | ||
![]() |
00c4b6f44f | ||
![]() |
2f86c7c795 | ||
![]() |
5e18ae68b7 | ||
![]() |
8caf690680 | ||
![]() |
b413066012 | ||
![]() |
c9df755426 | ||
![]() |
11518fe089 | ||
![]() |
4fb4dacae7 | ||
![]() |
99f45a2d7f | ||
![]() |
24a0ae0ea9 | ||
![]() |
e8400e65f0 | ||
![]() |
393d211d1e | ||
![]() |
c6550aecfc | ||
![]() |
430235a1cf | ||
![]() |
755268b7d4 | ||
![]() |
70306c4ec8 | ||
![]() |
35eb165f63 | ||
![]() |
91ffb7617d | ||
![]() |
09ca5c7341 | ||
![]() |
97b7460786 | ||
![]() |
fd508e92ca | ||
![]() |
441e770b96 | ||
![]() |
3d3801fc25 | ||
![]() |
7f00df4f02 | ||
![]() |
94c249a8c8 | ||
![]() |
c1a54ae58e | ||
![]() |
03ade23022 | ||
![]() |
8bff676fb0 | ||
![]() |
d78d1f119c | ||
![]() |
cd93e10d58 | ||
![]() |
7dcf08c5ef | ||
![]() |
22e46b846c | ||
![]() |
496b2c02c5 | ||
![]() |
cf1ee095a2 | ||
![]() |
b3ab94ef5b | ||
![]() |
b6f77e4944 | ||
![]() |
d4f38ac339 | ||
![]() |
ebf2873146 | ||
![]() |
41ce6ccf9f | ||
![]() |
42284a757c | ||
![]() |
d51db9469e | ||
![]() |
aa554871ef | ||
![]() |
578d903a9e | ||
![]() |
30a40aa6f1 | ||
![]() |
dfcfecf7d8 | ||
![]() |
68d37adf88 | ||
![]() |
e96e5994d0 | ||
![]() |
b4cdb6075b | ||
![]() |
dde033ca1f | ||
![]() |
9ad26fa049 | ||
![]() |
800b3bd3fe | ||
![]() |
1447615f3a | ||
![]() |
980b35b3fe | ||
![]() |
9ea1bf7c1d | ||
![]() |
63da3a5481 | ||
![]() |
3057a7c999 | ||
![]() |
c8e2a99e68 | ||
![]() |
756bac7fa4 | ||
![]() |
b0a08d3ed3 | ||
![]() |
0d292e0dcd | ||
![]() |
dd9da23a59 | ||
![]() |
4e88a369c4 | ||
![]() |
e93da4bd02 | ||
![]() |
d5a7901601 | ||
![]() |
6fb5c887b2 | ||
![]() |
4fc284a8e9 | ||
![]() |
7c240e8630 | ||
![]() |
d6ae4e9ba2 | ||
![]() |
c3298c38a0 | ||
![]() |
eb6ced79e7 | ||
![]() |
63d0cb1bd6 | ||
![]() |
dd6769954c | ||
![]() |
28b17b529d | ||
![]() |
abb8ba8b0e | ||
![]() |
7038bded7b | ||
![]() |
ff35118af5 | ||
![]() |
707efd6d12 | ||
![]() |
5c366db847 | ||
![]() |
77d0419aca | ||
![]() |
238bd5d050 | ||
![]() |
3fe61ed4a2 | ||
![]() |
13bc0432bc | ||
![]() |
9b204ed99b | ||
![]() |
acb81ebe3d | ||
![]() |
6a60332700 | ||
![]() |
45dc97e2b6 | ||
![]() |
0f0a424e8c | ||
![]() |
c4fc277758 | ||
![]() |
3bf3d96472 | ||
![]() |
3c7189a3e7 | ||
![]() |
27224868ab | ||
![]() |
50e576081e | ||
![]() |
625cf7361a | ||
![]() |
a3023e43ef | ||
![]() |
6c9e57d624 | ||
![]() |
76a3f24169 |
4
.github/dependabot.yml
vendored
4
.github/dependabot.yml
vendored
@@ -9,3 +9,7 @@ updates:
|
|||||||
directory: "/" # Location of package manifests
|
directory: "/" # Location of package manifests
|
||||||
schedule:
|
schedule:
|
||||||
interval: "daily"
|
interval: "daily"
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
|
22
.github/docker/Dockerfile
vendored
Normal file
22
.github/docker/Dockerfile
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY . .
|
||||||
|
ARG TARGETOS TARGETARCH
|
||||||
|
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
|
||||||
|
|
||||||
|
FROM --platform=${TARGETPLATFORM} alpine:latest
|
||||||
|
WORKDIR /root
|
||||||
|
COPY .github/docker/files/config.json /etc/xray/config.json
|
||||||
|
COPY --from=build /src/xray /usr/bin/xray
|
||||||
|
RUN set -ex \
|
||||||
|
&& apk add --no-cache tzdata ca-certificates \
|
||||||
|
&& mkdir -p /var/log/xray /usr/share/xray \
|
||||||
|
&& chmod +x /usr/bin/xray \
|
||||||
|
&& wget -O /usr/share/xray/geosite.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat \
|
||||||
|
&& wget -O /usr/share/xray/geoip.dat https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat
|
||||||
|
|
||||||
|
VOLUME /etc/xray
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
ENTRYPOINT [ "/usr/bin/xray" ]
|
||||||
|
CMD [ "-config", "/etc/xray/config.json" ]
|
18
.github/docker/files/config.json
vendored
Normal file
18
.github/docker/files/config.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"inbounds": [{
|
||||||
|
"port": 9000,
|
||||||
|
"protocol": "vmess",
|
||||||
|
"settings": {
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"id": "1eb6e917-774b-4a84-aff6-b058577c60a5",
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"outbounds": [{
|
||||||
|
"protocol": "freedom",
|
||||||
|
"settings": {}
|
||||||
|
}]
|
||||||
|
}
|
45
.github/workflows/docker.yml
vendored
Normal file
45
.github/workflows/docker.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
name: Build docker image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Docker metadata
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
||||||
|
flavor: latest=true
|
||||||
|
tags: |
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
|
type=semver,pattern={{version}}
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.repository_owner }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- # Add support for more platforms with QEMU (optional)
|
||||||
|
# https://github.com/docker/setup-qemu-action
|
||||||
|
name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
file: .github/docker/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
95
.github/workflows/release.yml
vendored
95
.github/workflows/release.yml
vendored
@@ -20,7 +20,53 @@ on:
|
|||||||
- "go.sum"
|
- "go.sum"
|
||||||
- ".github/workflows/*.yml"
|
- ".github/workflows/*.yml"
|
||||||
jobs:
|
jobs:
|
||||||
|
prepare:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Restore Cache
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
path: resources
|
||||||
|
key: xray-geodat-
|
||||||
|
|
||||||
|
- name: Update Geodat
|
||||||
|
id: update
|
||||||
|
uses: nick-fields/retry@v2
|
||||||
|
with:
|
||||||
|
timeout_minutes: 60
|
||||||
|
retry_wait_seconds: 60
|
||||||
|
max_attempts: 60
|
||||||
|
command: |
|
||||||
|
[ -d 'resources' ] || mkdir resources
|
||||||
|
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite')
|
||||||
|
for i in "${LIST[@]}"
|
||||||
|
do
|
||||||
|
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3}'))
|
||||||
|
FILE_NAME="${INFO[2]}.dat"
|
||||||
|
echo -e "Verifying HASH key..."
|
||||||
|
HASH="$(curl -sL "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
|
||||||
|
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
echo -e "Downloading https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat..."
|
||||||
|
curl -L "https://raw.githubusercontent.com/v2fly/${INFO[0]}/release/${INFO[1]}.dat" -o ./resources/${FILE_NAME}
|
||||||
|
echo -e "Verifying HASH key..."
|
||||||
|
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
|
||||||
|
echo "unhit=true" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Save Cache
|
||||||
|
uses: actions/cache/save@v3
|
||||||
|
if: ${{ steps.update.outputs.unhit }}
|
||||||
|
with:
|
||||||
|
path: resources
|
||||||
|
key: xray-geodat-${{ github.sha }}-${{ github.run_number }}
|
||||||
|
|
||||||
build:
|
build:
|
||||||
|
needs: prepare
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# Include amd64 on all platforms.
|
# Include amd64 on all platforms.
|
||||||
@@ -110,20 +156,19 @@ jobs:
|
|||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Show workflow information
|
- name: Show workflow information
|
||||||
id: get_filename
|
|
||||||
run: |
|
run: |
|
||||||
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
|
export _NAME=$(jq ".[\"$GOOS-$GOARCH$GOARM$GOMIPS\"].friendlyName" -r < .github/build/friendly-filenames.json)
|
||||||
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
|
echo "GOOS: $GOOS, GOARCH: $GOARCH, GOARM: $GOARM, GOMIPS: $GOMIPS, RELEASE_NAME: $_NAME"
|
||||||
echo "::set-output name=ASSET_NAME::$_NAME"
|
|
||||||
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ^1.17.2
|
go-version: '1.20'
|
||||||
|
check-latest: true
|
||||||
|
|
||||||
- name: Get project dependencies
|
- name: Get project dependencies
|
||||||
run: go mod download
|
run: go mod download
|
||||||
@@ -143,6 +188,11 @@ jobs:
|
|||||||
mkdir -p build_assets
|
mkdir -p build_assets
|
||||||
go build -v -o build_assets/xray -trimpath -ldflags "-s -w -buildid=" ./main
|
go build -v -o build_assets/xray -trimpath -ldflags "-s -w -buildid=" ./main
|
||||||
|
|
||||||
|
- name: Build background Xray on Windows
|
||||||
|
if: matrix.goos == 'windows'
|
||||||
|
run: |
|
||||||
|
go build -v -o build_assets/wxray.exe -trimpath -ldflags "-s -w -H windowsgui -buildid=" ./main
|
||||||
|
|
||||||
- name: Build Mips softfloat Xray
|
- name: Build Mips softfloat Xray
|
||||||
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
|
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
|
||||||
run: |
|
run: |
|
||||||
@@ -154,31 +204,26 @@ jobs:
|
|||||||
cd ./build_assets || exit 1
|
cd ./build_assets || exit 1
|
||||||
mv xray xray.exe
|
mv xray xray.exe
|
||||||
|
|
||||||
- name: Prepare to release
|
- name: Restore Cache
|
||||||
|
uses: actions/cache/restore@v3
|
||||||
|
with:
|
||||||
|
path: resources
|
||||||
|
key: xray-geodat-
|
||||||
|
|
||||||
|
- name: Copy README.md & LICENSE
|
||||||
run: |
|
run: |
|
||||||
|
mv -f resources/* build_assets
|
||||||
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
|
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
|
||||||
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
|
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
|
||||||
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite')
|
|
||||||
for i in "${LIST[@]}"
|
|
||||||
do
|
|
||||||
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3}'))
|
|
||||||
LASTEST_TAG="$(curl -sL "https://api.github.com/repos/v2fly/${INFO[0]}/releases" | jq -r ".[0].tag_name" || echo "latest")"
|
|
||||||
FILE_NAME="${INFO[2]}.dat"
|
|
||||||
echo -e "Downloading ${FILE_NAME}..."
|
|
||||||
curl -L "https://github.com/v2fly/${INFO[0]}/releases/download/${LASTEST_TAG}/${INFO[1]}.dat" -o ./build_assets/${FILE_NAME}
|
|
||||||
echo -e "Verifying HASH key..."
|
|
||||||
HASH="$(curl -sL "https://github.com/v2fly/${INFO[0]}/releases/download/${LASTEST_TAG}/${INFO[1]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
|
|
||||||
[ "$(sha256sum "./build_assets/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Create ZIP archive
|
- name: Create ZIP archive
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
pushd build_assets || exit 1
|
pushd build_assets || exit 1
|
||||||
touch -mt $(date +%Y01010000) *
|
touch -mt $(date +%Y01010000) *
|
||||||
zip -9vr ../Xray-$ASSET_NAME.zip .
|
zip -9vr ../Xray-${{ env.ASSET_NAME }}.zip .
|
||||||
popd || exit 1
|
popd || exit 1
|
||||||
FILE=./Xray-$ASSET_NAME.zip
|
FILE=./Xray-${{ env.ASSET_NAME }}.zip
|
||||||
DGST=$FILE.dgst
|
DGST=$FILE.dgst
|
||||||
for METHOD in {"md5","sha1","sha256","sha512"}
|
for METHOD in {"md5","sha1","sha256","sha512"}
|
||||||
do
|
do
|
||||||
@@ -187,20 +232,20 @@ jobs:
|
|||||||
|
|
||||||
- name: Change the name
|
- name: Change the name
|
||||||
run: |
|
run: |
|
||||||
mv build_assets Xray-$ASSET_NAME
|
mv build_assets Xray-${{ env.ASSET_NAME }}
|
||||||
|
|
||||||
- name: Upload files to Artifacts
|
- name: Upload files to Artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: Xray-${{ steps.get_filename.outputs.ASSET_NAME }}
|
name: Xray-${{ env.ASSET_NAME }}
|
||||||
path: |
|
path: |
|
||||||
./Xray-${{ steps.get_filename.outputs.ASSET_NAME }}/*
|
./Xray-${{ env.ASSET_NAME }}/*
|
||||||
|
|
||||||
- name: Upload binaries to release
|
- name: Upload binaries to release
|
||||||
uses: svenstaro/upload-release-action@v2
|
uses: svenstaro/upload-release-action@v2
|
||||||
if: github.event_name == 'release'
|
if: github.event_name == 'release'
|
||||||
with:
|
with:
|
||||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
file: ./Xray-${{ steps.get_filename.outputs.ASSET_NAME }}.zip*
|
file: ./Xray-${{ env.ASSET_NAME }}.zip*
|
||||||
tag: ${{ github.ref }}
|
tag: ${{ github.ref }}
|
||||||
file_glob: true
|
file_glob: true
|
||||||
|
28
.github/workflows/test.yml
vendored
28
.github/workflows/test.yml
vendored
@@ -19,6 +19,8 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -26,23 +28,17 @@ jobs:
|
|||||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ^1.17.2
|
go-version: '1.20'
|
||||||
|
check-latest: true
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
- name: Restore Cache
|
||||||
- name: Prepare geo*dat
|
uses: actions/cache/restore@v3
|
||||||
if: ${{ matrix.os != 'windows-latest' }}
|
with:
|
||||||
run: |
|
path: resources
|
||||||
mkdir resources
|
key: xray-geodat-
|
||||||
wget -O ./resources/geoip.dat https://github.com/v2fly/geoip/releases/latest/download/geoip.dat
|
enableCrossOsArchive: true
|
||||||
wget -O ./resources/geosite.dat https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat
|
|
||||||
- name: Prepare geo*dat for Windows
|
|
||||||
if: ${{ matrix.os == 'windows-latest' }}
|
|
||||||
run: |
|
|
||||||
mkdir resources
|
|
||||||
Invoke-WebRequest -Uri "https://github.com/v2fly/geoip/releases/latest/download/geoip.dat" -OutFile "./resources/geoip.dat"
|
|
||||||
Invoke-WebRequest -Uri "https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat" -OutFile "./resources/geosite.dat"
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: go test -timeout 1h -v ./...
|
run: go test -timeout 1h -v ./...
|
||||||
|
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Binaries for programs and plugins
|
||||||
|
*.exe
|
||||||
|
*.exe~
|
||||||
|
*.dll
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
|
||||||
|
# Test binary, built with `go test -c`
|
||||||
|
*.test
|
||||||
|
|
||||||
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
|
*.out
|
||||||
|
|
||||||
|
# Dependency directories (remove the comment below to include it)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
*.DS_Store
|
||||||
|
.idea
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
xray
|
||||||
|
mockgen
|
||||||
|
vprotogen
|
||||||
|
!infra/vprotogen/
|
||||||
|
errorgen
|
||||||
|
!common/errors/errorgen/
|
||||||
|
*.dat
|
||||||
|
.vscode
|
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
|
and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the
|
||||||
|
overall community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or
|
||||||
|
advances of any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email
|
||||||
|
address, without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
https://t.me/projectXtls.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series
|
||||||
|
of actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or
|
||||||
|
permanent ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within
|
||||||
|
the community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.0, available at
|
||||||
|
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||||
|
enforcement ladder](https://github.com/mozilla/diversity).
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
https://www.contributor-covenant.org/faq. Translations are available at
|
||||||
|
https://www.contributor-covenant.org/translations.
|
184
README.md
184
README.md
@@ -1,85 +1,16 @@
|
|||||||
# Project X
|
# Project X
|
||||||
|
|
||||||
[Project X](https://github.com/XTLS) originates from XTLS protocol, provides a set of network tools such as [Xray-core](https://github.com/XTLS/Xray-core) and [Xray-flutter](https://github.com/XTLS/Xray-flutter).
|
[Project X](https://github.com/XTLS) originates from XTLS protocol, providing a set of network tools such as [Xray-core](https://github.com/XTLS/Xray-core) and [REALITY](https://github.com/XTLS/REALITY).
|
||||||
|
|
||||||
|
[README](https://github.com/XTLS/Xray-core#readme) is open, so feel free to submit your project [here](https://github.com/XTLS/Xray-core/pulls).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[Mozilla Public License Version 2.0](https://github.com/XTLS/Xray-core/blob/main/LICENSE)
|
[Mozilla Public License Version 2.0](https://github.com/XTLS/Xray-core/blob/main/LICENSE)
|
||||||
|
|
||||||
## Installation
|
## Documentation
|
||||||
|
|
||||||
- Linux Script
|
[Project X Official Website](https://xtls.github.io)
|
||||||
- [Xray-install](https://github.com/XTLS/Xray-install)
|
|
||||||
- [Xray-script](https://github.com/kirin10000/Xray-script)
|
|
||||||
- Docker
|
|
||||||
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
|
|
||||||
- Xray-docker
|
|
||||||
- One Click
|
|
||||||
- [ProxySU](https://github.com/proxysu/ProxySU)
|
|
||||||
- [v2ray-agent](https://github.com/mack-a/v2ray-agent)
|
|
||||||
- [Xray-yes](https://github.com/jiuqi9997/Xray-yes)
|
|
||||||
- [Xray_onekey](https://github.com/wulabing/Xray_onekey)
|
|
||||||
- Magisk
|
|
||||||
- [Xray4Magisk](https://github.com/CerteKim/Xray4Magisk)
|
|
||||||
- [Xray_For_Magisk](https://github.com/E7KMbb/Xray_For_Magisk)
|
|
||||||
- Homebrew
|
|
||||||
- `brew install xray`
|
|
||||||
- [(Tap) Repository 0](https://github.com/N4FA/homebrew-xray)
|
|
||||||
- [(Tap) Repository 1](https://github.com/xiruizhao/homebrew-xray)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
[Xray-examples](https://github.com/XTLS/Xray-examples) / [VLESS-TCP-XTLS-WHATEVER](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-WHATEVER)
|
|
||||||
|
|
||||||
## GUI Clients
|
|
||||||
|
|
||||||
- OpenWrt
|
|
||||||
- [PassWall](https://github.com/xiaorouji/openwrt-passwall)
|
|
||||||
- [Hello World](https://github.com/jerrykuku/luci-app-vssr)
|
|
||||||
- [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))
|
|
||||||
- Windows
|
|
||||||
- [v2rayN](https://github.com/2dust/v2rayN)
|
|
||||||
- [Qv2ray](https://github.com/Qv2ray/Qv2ray) (This project had been archived and currently inactive)
|
|
||||||
- [Netch (NetFilter & TUN/TAP)](https://github.com/NetchX/Netch)
|
|
||||||
- Android
|
|
||||||
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
|
||||||
- [AnXray](https://github.com/XTLS/AnXray)
|
|
||||||
- [Kitsunebi](https://github.com/rurirei/Kitsunebi/tree/release_xtls)
|
|
||||||
- iOS & macOS (with M1 chip)
|
|
||||||
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
|
||||||
- macOS (Intel chip & M1 chip)
|
|
||||||
- [Qv2ray](https://github.com/Qv2ray/Qv2ray) (This project had been archived and currently inactive)
|
|
||||||
|
|
||||||
## Credits
|
|
||||||
|
|
||||||
This repo relies on the following third-party projects:
|
|
||||||
|
|
||||||
- Special thanks:
|
|
||||||
- [v2fly/v2ray-core](https://github.com/v2fly/v2ray-core)
|
|
||||||
- In production:
|
|
||||||
- [gorilla/websocket](https://github.com/gorilla/websocket)
|
|
||||||
- [lucas-clemente/quic-go](https://github.com/lucas-clemente/quic-go)
|
|
||||||
- [pires/go-proxyproto](https://github.com/pires/go-proxyproto)
|
|
||||||
- [seiflotfy/cuckoofilter](https://github.com/seiflotfy/cuckoofilter)
|
|
||||||
- [google/starlark-go](https://github.com/google/starlark-go)
|
|
||||||
- For testing only:
|
|
||||||
- [miekg/dns](https://github.com/miekg/dns)
|
|
||||||
- [h12w/socks](https://github.com/h12w/socks)
|
|
||||||
|
|
||||||
## Compilation
|
|
||||||
|
|
||||||
### Windows
|
|
||||||
|
|
||||||
```
|
|
||||||
go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main
|
|
||||||
```
|
|
||||||
|
|
||||||
### Linux / macOS
|
|
||||||
|
|
||||||
```
|
|
||||||
go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
|
|
||||||
```
|
|
||||||
|
|
||||||
## Telegram
|
## Telegram
|
||||||
|
|
||||||
@@ -87,6 +18,111 @@ go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
|
|||||||
|
|
||||||
[Project X Channel](https://t.me/projectXtls)
|
[Project X Channel](https://t.me/projectXtls)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
- Linux Script
|
||||||
|
- [XTLS/Xray-install](https://github.com/XTLS/Xray-install)
|
||||||
|
- Docker
|
||||||
|
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
|
||||||
|
- Web Panel
|
||||||
|
- [X-UI](https://github.com/FranzKafkaYu/x-ui), [X-UI-English](https://github.com/NidukaAkalanka/x-ui-english), [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [X-UI](https://github.com/diditra/x-ui)
|
||||||
|
- [Xray-UI](https://github.com/qist/xray-ui), [X-UI](https://github.com/sing-web/x-ui)
|
||||||
|
- [Hiddify](https://github.com/hiddify/hiddify-config)
|
||||||
|
- [Marzban](https://github.com/Gozargah/Marzban)
|
||||||
|
- [Libertea](https://github.com/VZiChoushaDui/Libertea)
|
||||||
|
- One Click
|
||||||
|
- [Xray-REALITY](https://github.com/zxcvos/Xray-script), [xray-reality](https://github.com/sajjaddg/xray-reality), [reality-ezpz](https://github.com/aleskxyz/reality-ezpz)
|
||||||
|
- [Xray-script](https://github.com/kirin10000/Xray-script), [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool)
|
||||||
|
- [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
|
||||||
|
- Magisk
|
||||||
|
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
|
||||||
|
- [Xray_For_Magisk](https://github.com/E7KMbb/Xray_For_Magisk)
|
||||||
|
- Homebrew
|
||||||
|
- `brew install xray`
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
- Example
|
||||||
|
- [VLESS-XTLS-uTLS-REALITY](https://github.com/XTLS/REALITY#readme)
|
||||||
|
- [VLESS-TCP-XTLS-Vision](https://github.com/XTLS/Xray-examples/tree/main/VLESS-TCP-XTLS-Vision)
|
||||||
|
- [All-in-One-fallbacks-Nginx](https://github.com/XTLS/Xray-examples/tree/main/All-in-One-fallbacks-Nginx)
|
||||||
|
- Xray-examples
|
||||||
|
- [XTLS/Xray-examples](https://github.com/XTLS/Xray-examples)
|
||||||
|
- [chika0801/Xray-examples](https://github.com/chika0801/Xray-examples)
|
||||||
|
- [lxhao61/integrated-examples](https://github.com/lxhao61/integrated-examples)
|
||||||
|
- Tutorial
|
||||||
|
- [XTLS Vision](https://github.com/chika0801/Xray-install)
|
||||||
|
- [REALITY (English)](https://cscot.pages.dev/2023/03/02/Xray-REALITY-tutorial/)
|
||||||
|
- [XTLS-Iran-Reality (English)](https://github.com/SasukeFreestyle/XTLS-Iran-Reality)
|
||||||
|
|
||||||
|
## GUI Clients
|
||||||
|
|
||||||
|
- OpenWrt
|
||||||
|
- [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))
|
||||||
|
- Windows
|
||||||
|
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
|
- [HiddifyN](https://github.com/hiddify/HiddifyN)
|
||||||
|
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
|
||||||
|
- Android
|
||||||
|
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
||||||
|
- [HiddifyNG](https://github.com/hiddify/HiddifyNG)
|
||||||
|
- [X-flutter](https://github.com/XTLS/X-flutter)
|
||||||
|
- iOS & macOS arm64
|
||||||
|
- [Mango](https://github.com/arror/Mango)
|
||||||
|
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
||||||
|
- macOS arm64 & x64
|
||||||
|
- [V2RayXS](https://github.com/tzmax/V2RayXS)
|
||||||
|
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
||||||
|
- Linux
|
||||||
|
- [v2rayA](https://github.com/v2rayA/v2rayA)
|
||||||
|
|
||||||
|
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
|
||||||
|
|
||||||
|
- iOS & macOS arm64
|
||||||
|
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
||||||
|
- Xray Wrapper
|
||||||
|
- [XTLS/libXray](https://github.com/XTLS/libXray)
|
||||||
|
- [xtlsapi](https://github.com/hiddify/xtlsapi)
|
||||||
|
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
|
||||||
|
- [XrayKit](https://github.com/arror/XrayKit)
|
||||||
|
- [XrayR](https://github.com/XrayR-project/XrayR)
|
||||||
|
- [XrayR-release](https://github.com/XrayR-project/XrayR-release)
|
||||||
|
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
|
||||||
|
- [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta)
|
||||||
|
- [Clash Verge](https://github.com/zzzgydi/clash-verge)
|
||||||
|
- [clashN](https://github.com/2dust/clashN)
|
||||||
|
- [Clash Meta for Android](https://github.com/MetaCubeX/ClashMetaForAndroid)
|
||||||
|
- [meta_for_ios](https://t.me/meta_for_ios)
|
||||||
|
- [sing-box](https://github.com/SagerNet/sing-box)
|
||||||
|
- [installReality](https://github.com/BoxXt/installReality)
|
||||||
|
- [sbox-reality](https://github.com/Misaka-blog/sbox-reality)
|
||||||
|
- [sing-box-for-ios](https://github.com/SagerNet/sing-box-for-ios)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
[Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
- [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).
|
||||||
|
|
||||||
|
## Compilation
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -o xray.exe -trimpath -ldflags "-s -w -buildid=" ./main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux / macOS
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
|
||||||
|
```
|
||||||
|
|
||||||
## Stargazers over time
|
## Stargazers over time
|
||||||
|
|
||||||
[](https://starchart.cc/XTLS/Xray-core)
|
[](https://starchart.cc/XTLS/Xray-core)
|
||||||
|
@@ -7,12 +7,11 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Commander is a Xray feature that provides gRPC methods to external clients.
|
// Commander is a Xray feature that provides gRPC methods to external clients.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/commander/config.proto
|
// source: app/commander/config.proto
|
||||||
|
|
||||||
package commander
|
package commander
|
||||||
|
@@ -37,7 +37,7 @@ func (l *OutboundListener) Accept() (net.Conn, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implement net.Listener.
|
// Close implements net.Listener.
|
||||||
func (l *OutboundListener) Close() error {
|
func (l *OutboundListener) Close() error {
|
||||||
common.Must(l.done.Close())
|
common.Must(l.done.Close())
|
||||||
L:
|
L:
|
||||||
|
@@ -3,10 +3,9 @@ package commander
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/reflection"
|
"google.golang.org/grpc/reflection"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Service is a Commander service.
|
// Service is a Commander service.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/dispatcher/config.proto
|
// source: app/dispatcher/config.proto
|
||||||
|
|
||||||
package dispatcher
|
package dispatcher
|
||||||
|
@@ -4,6 +4,7 @@ package dispatcher
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -92,13 +93,18 @@ type DefaultDispatcher struct {
|
|||||||
router routing.Router
|
router routing.Router
|
||||||
policy policy.Manager
|
policy policy.Manager
|
||||||
stats stats.Manager
|
stats stats.Manager
|
||||||
|
dns dns.Client
|
||||||
|
fdns dns.FakeDNSEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
d := new(DefaultDispatcher)
|
d := new(DefaultDispatcher)
|
||||||
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager) error {
|
if err := core.RequireFeatures(ctx, func(om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dc dns.Client) error {
|
||||||
return d.Init(config.(*Config), om, router, pm, sm)
|
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||||
|
d.fdns = fdns
|
||||||
|
})
|
||||||
|
return d.Init(config.(*Config), om, router, pm, sm, dc)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -107,11 +113,12 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes DefaultDispatcher.
|
// Init initializes DefaultDispatcher.
|
||||||
func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager) error {
|
func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dns dns.Client) error {
|
||||||
d.ohm = om
|
d.ohm = om
|
||||||
d.router = router
|
d.router = router
|
||||||
d.policy = pm
|
d.policy = pm
|
||||||
d.stats = sm
|
d.stats = sm
|
||||||
|
d.dns = dns
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,10 +135,77 @@ func (*DefaultDispatcher) Start() error {
|
|||||||
// Close implements common.Closable.
|
// Close implements common.Closable.
|
||||||
func (*DefaultDispatcher) Close() error { return nil }
|
func (*DefaultDispatcher) Close() error { return nil }
|
||||||
|
|
||||||
func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *transport.Link) {
|
func (d *DefaultDispatcher) getLink(ctx context.Context, network net.Network, sniffing session.SniffingRequest) (*transport.Link, *transport.Link) {
|
||||||
opt := pipe.OptionsFromContext(ctx)
|
downOpt := pipe.OptionsFromContext(ctx)
|
||||||
uplinkReader, uplinkWriter := pipe.New(opt...)
|
upOpt := downOpt
|
||||||
downlinkReader, downlinkWriter := pipe.New(opt...)
|
|
||||||
|
if network == net.Network_UDP {
|
||||||
|
var ip2domain *sync.Map // net.IP.String() => domain, this map is used by server side when client turn on fakedns
|
||||||
|
// Client will send domain address in the buffer.UDP.Address, server record all possible target IP addrs.
|
||||||
|
// When target replies, server will restore the domain and send back to client.
|
||||||
|
// Note: this map is not global but per connection context
|
||||||
|
upOpt = append(upOpt, pipe.OnTransmission(func(mb buf.MultiBuffer) buf.MultiBuffer {
|
||||||
|
for i, buffer := range mb {
|
||||||
|
if buffer.UDP == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addr := buffer.UDP.Address
|
||||||
|
if addr.Family().IsIP() {
|
||||||
|
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && fkr0.IsIPInIPPool(addr) && sniffing.Enabled {
|
||||||
|
domain := fkr0.GetDomainFromFakeDNS(addr)
|
||||||
|
if len(domain) > 0 {
|
||||||
|
buffer.UDP.Address = net.DomainAddress(domain)
|
||||||
|
newError("[fakedns client] override with domain: ", domain, " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
} else {
|
||||||
|
newError("[fakedns client] failed to find domain! :", addr.String(), " for xUDP buffer at ", i).AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ip2domain == nil {
|
||||||
|
ip2domain = new(sync.Map)
|
||||||
|
newError("[fakedns client] create a new map").WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
domain := addr.Domain()
|
||||||
|
ips, err := d.dns.LookupIP(domain, dns.IPOption{true, true, false})
|
||||||
|
if err == nil {
|
||||||
|
for _, ip := range ips {
|
||||||
|
ip2domain.Store(ip.String(), domain)
|
||||||
|
}
|
||||||
|
newError("[fakedns client] candidate ip: "+fmt.Sprintf("%v", ips), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
} else {
|
||||||
|
newError("[fakedns client] failed to look up IP for ", domain, " for xUDP buffer at ", i).Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mb
|
||||||
|
}))
|
||||||
|
downOpt = append(downOpt, pipe.OnTransmission(func(mb buf.MultiBuffer) buf.MultiBuffer {
|
||||||
|
for i, buffer := range mb {
|
||||||
|
if buffer.UDP == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addr := buffer.UDP.Address
|
||||||
|
if addr.Family().IsIP() {
|
||||||
|
if ip2domain == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if domain, found := ip2domain.Load(addr.IP().String()); found {
|
||||||
|
buffer.UDP.Address = net.DomainAddress(domain.(string))
|
||||||
|
newError("[fakedns client] restore domain: ", domain.(string), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok {
|
||||||
|
fakeIp := fkr0.GetFakeIPForDomain(addr.Domain())
|
||||||
|
buffer.UDP.Address = fakeIp[0]
|
||||||
|
newError("[fakedns client] restore FakeIP: ", buffer.UDP, fmt.Sprintf("%v", fakeIp), " for xUDP buffer at ", i).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return mb
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
uplinkReader, uplinkWriter := pipe.New(upOpt...)
|
||||||
|
downlinkReader, downlinkWriter := pipe.New(downOpt...)
|
||||||
|
|
||||||
inboundLink := &transport.Link{
|
inboundLink := &transport.Link{
|
||||||
Reader: downlinkReader,
|
Reader: downlinkReader,
|
||||||
@@ -174,17 +248,16 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
|
|||||||
return inboundLink, outboundLink
|
return inboundLink, outboundLink
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
|
func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
|
||||||
domain := result.Domain()
|
domain := result.Domain()
|
||||||
|
if domain == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
for _, d := range request.ExcludeForDomain {
|
for _, d := range request.ExcludeForDomain {
|
||||||
if strings.ToLower(domain) == d {
|
if strings.ToLower(domain) == d {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var fakeDNSEngine dns.FakeDNSEngine
|
|
||||||
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
|
||||||
fakeDNSEngine = fdns
|
|
||||||
})
|
|
||||||
protocolString := result.Protocol()
|
protocolString := result.Protocol()
|
||||||
if resComp, ok := result.(SnifferResultComposite); ok {
|
if resComp, ok := result.(SnifferResultComposite); ok {
|
||||||
protocolString = resComp.ProtocolForDomainResult()
|
protocolString = resComp.ProtocolForDomainResult()
|
||||||
@@ -193,10 +266,10 @@ func shouldOverride(ctx context.Context, result SniffResult, request session.Sni
|
|||||||
if strings.HasPrefix(protocolString, p) {
|
if strings.HasPrefix(protocolString, p) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" &&
|
if fkr0, ok := d.fdns.(dns.FakeDNSEngineRev0); ok && protocolString != "bittorrent" && p == "fakedns" &&
|
||||||
destination.Address.Family().IsIP() && fkr0.IsIPInIPPool(destination.Address) {
|
destination.Address.Family().IsIP() && fkr0.IsIPInIPPool(destination.Address) {
|
||||||
newError("Using sniffer ", protocolString, " since the fake DNS missed").WriteToLog(session.ExportIDToError(ctx))
|
newError("Using sniffer ", protocolString, " since the fake DNS missed").WriteToLog(session.ExportIDToError(ctx))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if resultSubset, ok := result.(SnifferIsProtoSubsetOf); ok {
|
if resultSubset, ok := result.(SnifferIsProtoSubsetOf); ok {
|
||||||
if resultSubset.IsProtoSubsetOf(p) {
|
if resultSubset.IsProtoSubsetOf(p) {
|
||||||
@@ -217,45 +290,35 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
|||||||
Target: destination,
|
Target: destination,
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithOutbound(ctx, ob)
|
ctx = session.ContextWithOutbound(ctx, ob)
|
||||||
|
|
||||||
inbound, outbound := d.getLink(ctx)
|
|
||||||
content := session.ContentFromContext(ctx)
|
content := session.ContentFromContext(ctx)
|
||||||
if content == nil {
|
if content == nil {
|
||||||
content = new(session.Content)
|
content = new(session.Content)
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
}
|
}
|
||||||
|
|
||||||
sniffingRequest := content.SniffingRequest
|
sniffingRequest := content.SniffingRequest
|
||||||
switch {
|
inbound, outbound := d.getLink(ctx, destination.Network, sniffingRequest)
|
||||||
case !sniffingRequest.Enabled:
|
if !sniffingRequest.Enabled {
|
||||||
go d.routedDispatch(ctx, outbound, destination)
|
go d.routedDispatch(ctx, outbound, destination)
|
||||||
case destination.Network != net.Network_TCP:
|
} else {
|
||||||
// Only metadata sniff will be used for non tcp connection
|
|
||||||
result, err := sniffer(ctx, nil, true)
|
|
||||||
if err == nil {
|
|
||||||
content.Protocol = result.Protocol()
|
|
||||||
if shouldOverride(ctx, result, sniffingRequest, destination) {
|
|
||||||
domain := result.Domain()
|
|
||||||
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
destination.Address = net.ParseAddress(domain)
|
|
||||||
ob.Target = destination
|
|
||||||
}
|
|
||||||
}
|
|
||||||
go d.routedDispatch(ctx, outbound, destination)
|
|
||||||
default:
|
|
||||||
go func() {
|
go func() {
|
||||||
cReader := &cachedReader{
|
cReader := &cachedReader{
|
||||||
reader: outbound.Reader.(*pipe.Reader),
|
reader: outbound.Reader.(*pipe.Reader),
|
||||||
}
|
}
|
||||||
outbound.Reader = cReader
|
outbound.Reader = cReader
|
||||||
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly)
|
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
content.Protocol = result.Protocol()
|
content.Protocol = result.Protocol()
|
||||||
}
|
}
|
||||||
if err == nil && shouldOverride(ctx, result, sniffingRequest, destination) {
|
if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
|
||||||
domain := result.Domain()
|
domain := result.Domain()
|
||||||
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
|
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
|
||||||
destination.Address = net.ParseAddress(domain)
|
destination.Address = net.ParseAddress(domain)
|
||||||
ob.Target = destination
|
if sniffingRequest.RouteOnly && result.Protocol() != "fakedns" {
|
||||||
|
ob.RouteTarget = destination
|
||||||
|
} else {
|
||||||
|
ob.Target = destination
|
||||||
|
}
|
||||||
}
|
}
|
||||||
d.routedDispatch(ctx, outbound, destination)
|
d.routedDispatch(ctx, outbound, destination)
|
||||||
}()
|
}()
|
||||||
@@ -263,7 +326,49 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
|||||||
return inbound, nil
|
return inbound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool) (SniffResult, error) {
|
// DispatchLink implements routing.Dispatcher.
|
||||||
|
func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.Destination, outbound *transport.Link) error {
|
||||||
|
if !destination.IsValid() {
|
||||||
|
return newError("Dispatcher: Invalid destination.")
|
||||||
|
}
|
||||||
|
ob := &session.Outbound{
|
||||||
|
Target: destination,
|
||||||
|
}
|
||||||
|
ctx = session.ContextWithOutbound(ctx, ob)
|
||||||
|
content := session.ContentFromContext(ctx)
|
||||||
|
if content == nil {
|
||||||
|
content = new(session.Content)
|
||||||
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
}
|
||||||
|
sniffingRequest := content.SniffingRequest
|
||||||
|
if !sniffingRequest.Enabled {
|
||||||
|
d.routedDispatch(ctx, outbound, destination)
|
||||||
|
} else {
|
||||||
|
cReader := &cachedReader{
|
||||||
|
reader: outbound.Reader.(*pipe.Reader),
|
||||||
|
}
|
||||||
|
outbound.Reader = cReader
|
||||||
|
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network)
|
||||||
|
if err == nil {
|
||||||
|
content.Protocol = result.Protocol()
|
||||||
|
}
|
||||||
|
if err == nil && d.shouldOverride(ctx, result, sniffingRequest, destination) {
|
||||||
|
domain := result.Domain()
|
||||||
|
newError("sniffed domain: ", domain).WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
destination.Address = net.ParseAddress(domain)
|
||||||
|
if sniffingRequest.RouteOnly && result.Protocol() != "fakedns" {
|
||||||
|
ob.RouteTarget = destination
|
||||||
|
} else {
|
||||||
|
ob.Target = destination
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d.routedDispatch(ctx, outbound, destination)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, network net.Network) (SniffResult, error) {
|
||||||
payload := buf.New()
|
payload := buf.New()
|
||||||
defer payload.Release()
|
defer payload.Release()
|
||||||
|
|
||||||
@@ -289,7 +394,7 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool) (Sni
|
|||||||
|
|
||||||
cReader.Cache(payload)
|
cReader.Cache(payload)
|
||||||
if !payload.IsEmpty() {
|
if !payload.IsEmpty() {
|
||||||
result, err := sniffer.Sniff(ctx, payload.Bytes())
|
result, err := sniffer.Sniff(ctx, payload.Bytes(), network)
|
||||||
if err != common.ErrNoClue {
|
if err != common.ErrNoClue {
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
@@ -310,16 +415,46 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool) (Sni
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
|
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
|
||||||
|
ob := session.OutboundFromContext(ctx)
|
||||||
|
if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() {
|
||||||
|
proxied := hosts.LookupHosts(ob.Target.String())
|
||||||
|
if proxied != nil {
|
||||||
|
ro := ob.RouteTarget == destination
|
||||||
|
destination.Address = *proxied
|
||||||
|
if ro {
|
||||||
|
ob.RouteTarget = destination
|
||||||
|
} else {
|
||||||
|
ob.Target = destination
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var handler outbound.Handler
|
var handler outbound.Handler
|
||||||
|
|
||||||
if d.router != nil {
|
routingLink := routing_session.AsRoutingContext(ctx)
|
||||||
if route, err := d.router.PickRoute(routing_session.AsRoutingContext(ctx)); err == nil {
|
inTag := routingLink.GetInboundTag()
|
||||||
tag := route.GetOutboundTag()
|
isPickRoute := 0
|
||||||
if h := d.ohm.GetHandler(tag); h != nil {
|
if forcedOutboundTag := session.GetForcedOutboundTagFromContext(ctx); forcedOutboundTag != "" {
|
||||||
newError("taking detour [", tag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
|
ctx = session.SetForcedOutboundTagToContext(ctx, "")
|
||||||
|
if h := d.ohm.GetHandler(forcedOutboundTag); h != nil {
|
||||||
|
isPickRoute = 1
|
||||||
|
newError("taking platform initialized detour [", forcedOutboundTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
handler = h
|
||||||
|
} else {
|
||||||
|
newError("non existing tag for platform initialized detour: ", forcedOutboundTag).AtError().WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
common.Close(link.Writer)
|
||||||
|
common.Interrupt(link.Reader)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else if d.router != nil {
|
||||||
|
if route, err := d.router.PickRoute(routingLink); err == nil {
|
||||||
|
outTag := route.GetOutboundTag()
|
||||||
|
if h := d.ohm.GetHandler(outTag); h != nil {
|
||||||
|
isPickRoute = 2
|
||||||
|
newError("taking detour [", outTag, "] for [", destination, "]").WriteToLog(session.ExportIDToError(ctx))
|
||||||
handler = h
|
handler = h
|
||||||
} else {
|
} else {
|
||||||
newError("non existing outTag: ", tag).AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
newError("non existing outTag: ", outTag).AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
newError("default route for ", destination).WriteToLog(session.ExportIDToError(ctx))
|
newError("default route for ", destination).WriteToLog(session.ExportIDToError(ctx))
|
||||||
@@ -339,7 +474,15 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
|
|||||||
|
|
||||||
if accessMessage := log.AccessMessageFromContext(ctx); accessMessage != nil {
|
if accessMessage := log.AccessMessageFromContext(ctx); accessMessage != nil {
|
||||||
if tag := handler.Tag(); tag != "" {
|
if tag := handler.Tag(); tag != "" {
|
||||||
accessMessage.Detour = tag
|
if inTag == "" {
|
||||||
|
accessMessage.Detour = tag
|
||||||
|
} else if isPickRoute == 1 {
|
||||||
|
accessMessage.Detour = inTag + " ==> " + tag
|
||||||
|
} else if isPickRoute == 2 {
|
||||||
|
accessMessage.Detour = inTag + " -> " + tag
|
||||||
|
} else {
|
||||||
|
accessMessage.Detour = inTag + " >> " + tag
|
||||||
|
}
|
||||||
}
|
}
|
||||||
log.Record(accessMessage)
|
log.Record(accessMessage)
|
||||||
}
|
}
|
||||||
|
@@ -11,15 +11,16 @@ import (
|
|||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// newFakeDNSSniffer Create a Fake DNS metadata sniffer
|
// newFakeDNSSniffer Creates a Fake DNS metadata sniffer
|
||||||
func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) {
|
func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) {
|
||||||
var fakeDNSEngine dns.FakeDNSEngine
|
var fakeDNSEngine dns.FakeDNSEngine
|
||||||
err := core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
{
|
||||||
fakeDNSEngine = fdns
|
fakeDNSEngineFeat := core.MustFromContext(ctx).GetFeature((*dns.FakeDNSEngine)(nil))
|
||||||
})
|
if fakeDNSEngineFeat != nil {
|
||||||
if err != nil {
|
fakeDNSEngine = fakeDNSEngineFeat.(dns.FakeDNSEngine)
|
||||||
return protocolSnifferWithMetadata{}, err
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if fakeDNSEngine == nil {
|
if fakeDNSEngine == nil {
|
||||||
errNotInit := newError("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
|
errNotInit := newError("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
|
||||||
return protocolSnifferWithMetadata{}, errNotInit
|
return protocolSnifferWithMetadata{}, errNotInit
|
||||||
@@ -84,7 +85,8 @@ func (f DNSThenOthersSniffResult) Domain() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWithMetadata, others []protocolSnifferWithMetadata) (
|
func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWithMetadata, others []protocolSnifferWithMetadata) (
|
||||||
protocolSnifferWithMetadata, error) { // nolint: unparam
|
protocolSnifferWithMetadata, error,
|
||||||
|
) { // nolint: unparam
|
||||||
// ctx may be used in the future
|
// ctx may be used in the future
|
||||||
_ = ctx
|
_ = ctx
|
||||||
return protocolSnifferWithMetadata{
|
return protocolSnifferWithMetadata{
|
||||||
|
@@ -4,8 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol/bittorrent"
|
"github.com/xtls/xray-core/common/protocol/bittorrent"
|
||||||
"github.com/xtls/xray-core/common/protocol/http"
|
"github.com/xtls/xray-core/common/protocol/http"
|
||||||
|
"github.com/xtls/xray-core/common/protocol/quic"
|
||||||
"github.com/xtls/xray-core/common/protocol/tls"
|
"github.com/xtls/xray-core/common/protocol/tls"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,6 +24,7 @@ type protocolSnifferWithMetadata struct {
|
|||||||
// for both TCP and UDP connections
|
// for both TCP and UDP connections
|
||||||
// It will not be shown as a traffic type for routing unless there is no other successful sniffing.
|
// It will not be shown as a traffic type for routing unless there is no other successful sniffing.
|
||||||
metadataSniffer bool
|
metadataSniffer bool
|
||||||
|
network net.Network
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sniffer struct {
|
type Sniffer struct {
|
||||||
@@ -31,9 +34,11 @@ type Sniffer struct {
|
|||||||
func NewSniffer(ctx context.Context) *Sniffer {
|
func NewSniffer(ctx context.Context) *Sniffer {
|
||||||
ret := &Sniffer{
|
ret := &Sniffer{
|
||||||
sniffer: []protocolSnifferWithMetadata{
|
sniffer: []protocolSnifferWithMetadata{
|
||||||
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b) }, false},
|
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b) }, false, net.Network_TCP},
|
||||||
{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false},
|
{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
|
||||||
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false},
|
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
|
||||||
|
{func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
|
||||||
|
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffUTP(b) }, false, net.Network_UDP},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if sniffer, err := newFakeDNSSniffer(ctx); err == nil {
|
if sniffer, err := newFakeDNSSniffer(ctx); err == nil {
|
||||||
@@ -49,11 +54,11 @@ func NewSniffer(ctx context.Context) *Sniffer {
|
|||||||
|
|
||||||
var errUnknownContent = newError("unknown content")
|
var errUnknownContent = newError("unknown content")
|
||||||
|
|
||||||
func (s *Sniffer) Sniff(c context.Context, payload []byte) (SniffResult, error) {
|
func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
|
||||||
var pendingSniffer []protocolSnifferWithMetadata
|
var pendingSniffer []protocolSnifferWithMetadata
|
||||||
for _, si := range s.sniffer {
|
for _, si := range s.sniffer {
|
||||||
s := si.protocolSniffer
|
s := si.protocolSniffer
|
||||||
if si.metadataSniffer {
|
if si.metadataSniffer || si.network != network {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
result, err := s(c, payload)
|
result, err := s(c, payload)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/dns/config.proto
|
// source: app/dns/config.proto
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
@@ -219,14 +219,14 @@ type Config struct {
|
|||||||
// the moment. A special value 'localhost' as a domain address can be set to
|
// the moment. A special value 'localhost' as a domain address can be set to
|
||||||
// use DNS on local system.
|
// use DNS on local system.
|
||||||
//
|
//
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/dns/config.proto.
|
||||||
NameServers []*net.Endpoint `protobuf:"bytes,1,rep,name=NameServers,proto3" json:"NameServers,omitempty"`
|
NameServers []*net.Endpoint `protobuf:"bytes,1,rep,name=NameServers,proto3" json:"NameServers,omitempty"`
|
||||||
// NameServer list used by this DNS client.
|
// NameServer list used by this DNS client.
|
||||||
NameServer []*NameServer `protobuf:"bytes,5,rep,name=name_server,json=nameServer,proto3" json:"name_server,omitempty"`
|
NameServer []*NameServer `protobuf:"bytes,5,rep,name=name_server,json=nameServer,proto3" json:"name_server,omitempty"`
|
||||||
// Static hosts. Domain to IP.
|
// Static hosts. Domain to IP.
|
||||||
// Deprecated. Use static_hosts.
|
// Deprecated. Use static_hosts.
|
||||||
//
|
//
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/dns/config.proto.
|
||||||
Hosts map[string]*net.IPOrDomain `protobuf:"bytes,2,rep,name=Hosts,proto3" json:"Hosts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
Hosts map[string]*net.IPOrDomain `protobuf:"bytes,2,rep,name=Hosts,proto3" json:"Hosts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
// Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes
|
// Client IP for EDNS client subnet. Must be 4 bytes (IPv4) or 16 bytes
|
||||||
// (IPv6).
|
// (IPv6).
|
||||||
@@ -273,7 +273,7 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{1}
|
return file_app_dns_config_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/dns/config.proto.
|
||||||
func (x *Config) GetNameServers() []*net.Endpoint {
|
func (x *Config) GetNameServers() []*net.Endpoint {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.NameServers
|
return x.NameServers
|
||||||
@@ -288,7 +288,7 @@ func (x *Config) GetNameServer() []*NameServer {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/dns/config.proto.
|
||||||
func (x *Config) GetHosts() map[string]*net.IPOrDomain {
|
func (x *Config) GetHosts() map[string]*net.IPOrDomain {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Hosts
|
return x.Hosts
|
||||||
|
@@ -215,7 +215,7 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
|
|||||||
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
|
newError("failed to lookup ip for domain ", domain, " at server ", client.Name()).Base(err).WriteToLog()
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch {
|
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch && err != dns.ErrEmptyResponse {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,6 +223,22 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
|
|||||||
return nil, newError("returning nil for domain ", domain).Base(errors.Combine(errs...))
|
return nil, newError("returning nil for domain ", domain).Base(errors.Combine(errs...))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LookupHosts implements dns.HostsLookup.
|
||||||
|
func (s *DNS) LookupHosts(domain string) *net.Address {
|
||||||
|
domain = strings.TrimSuffix(domain, ".")
|
||||||
|
if domain == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Normalize the FQDN form query
|
||||||
|
addrs := s.hosts.Lookup(domain, *s.ipOption)
|
||||||
|
if len(addrs) > 0 {
|
||||||
|
newError("domain replaced: ", domain, " -> ", addrs[0].String()).AtInfo().WriteToLog()
|
||||||
|
return &addrs[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetIPOption implements ClientWithIPOption.
|
// GetIPOption implements ClientWithIPOption.
|
||||||
func (s *DNS) GetIPOption() *dns.IPOption {
|
func (s *DNS) GetIPOption() *dns.IPOption {
|
||||||
return s.ipOption
|
return s.ipOption
|
||||||
|
@@ -13,6 +13,7 @@ import (
|
|||||||
_ "github.com/xtls/xray-core/app/proxyman/outbound"
|
_ "github.com/xtls/xray-core/app/proxyman/outbound"
|
||||||
"github.com/xtls/xray-core/app/router"
|
"github.com/xtls/xray-core/app/router"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
@@ -260,7 +261,7 @@ func TestUDPServer(t *testing.T) {
|
|||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
})
|
})
|
||||||
if err != feature_dns.ErrEmptyResponse {
|
if !errors.AllEqual(feature_dns.ErrEmptyResponse, errors.Cause(err)) {
|
||||||
t.Fatal("error: ", err)
|
t.Fatal("error: ", err)
|
||||||
}
|
}
|
||||||
if len(ips) != 0 {
|
if len(ips) != 0 {
|
||||||
|
@@ -1,19 +1,22 @@
|
|||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fqdn normalize domain make sure it ends with '.'
|
// Fqdn normalizes domain make sure it ends with '.'
|
||||||
func Fqdn(domain string) string {
|
func Fqdn(domain string) string {
|
||||||
if len(domain) > 0 && strings.HasSuffix(domain, ".") {
|
if len(domain) > 0 && strings.HasSuffix(domain, ".") {
|
||||||
return domain
|
return domain
|
||||||
@@ -163,7 +166,7 @@ func buildReqMsgs(domain string, option dns_feature.IPOption, reqIDGen func() ui
|
|||||||
return reqs
|
return reqs
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseResponse parse DNS answers from the returned payload
|
// parseResponse parses DNS answers from the returned payload
|
||||||
func parseResponse(payload []byte) (*IPRecord, error) {
|
func parseResponse(payload []byte) (*IPRecord, error) {
|
||||||
var parser dnsmessage.Parser
|
var parser dnsmessage.Parser
|
||||||
h, err := parser.Start(payload)
|
h, err := parser.Start(payload)
|
||||||
@@ -226,3 +229,19 @@ L:
|
|||||||
|
|
||||||
return ipRecord, nil
|
return ipRecord, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// toDnsContext create a new background context with parent inbound, session and dns log
|
||||||
|
func toDnsContext(ctx context.Context, addr string) context.Context {
|
||||||
|
dnsCtx := core.ToBackgroundDetachedContext(ctx)
|
||||||
|
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
|
dnsCtx = session.ContextWithInbound(dnsCtx, inbound)
|
||||||
|
}
|
||||||
|
dnsCtx = session.ContextWithContent(dnsCtx, session.ContentFromContext(ctx))
|
||||||
|
dnsCtx = log.ContextWithAccessMessage(dnsCtx, &log.AccessMessage{
|
||||||
|
From: "DNS",
|
||||||
|
To: addr,
|
||||||
|
Status: log.AccessAccepted,
|
||||||
|
Reason: "",
|
||||||
|
})
|
||||||
|
return dnsCtx
|
||||||
|
}
|
||||||
|
@@ -7,11 +7,10 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_parseResponse(t *testing.T) {
|
func Test_parseResponse(t *testing.T) {
|
||||||
|
@@ -5,6 +5,7 @@ import (
|
|||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
gonet "net"
|
gonet "net"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
@@ -16,6 +17,7 @@ import (
|
|||||||
type Holder struct {
|
type Holder struct {
|
||||||
domainToIP cache.Lru
|
domainToIP cache.Lru
|
||||||
ipRange *gonet.IPNet
|
ipRange *gonet.IPNet
|
||||||
|
mu *sync.Mutex
|
||||||
|
|
||||||
config *FakeDnsPool
|
config *FakeDnsPool
|
||||||
}
|
}
|
||||||
@@ -49,6 +51,7 @@ func (fkdns *Holder) Start() error {
|
|||||||
func (fkdns *Holder) Close() error {
|
func (fkdns *Holder) Close() error {
|
||||||
fkdns.domainToIP = nil
|
fkdns.domainToIP = nil
|
||||||
fkdns.ipRange = nil
|
fkdns.ipRange = nil
|
||||||
|
fkdns.mu = nil
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +70,7 @@ func NewFakeDNSHolder() (*Holder, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) {
|
func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) {
|
||||||
return &Holder{nil, nil, conf}, nil
|
return &Holder{nil, nil, nil, conf}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fkdns *Holder) initializeFromConfig() error {
|
func (fkdns *Holder) initializeFromConfig() error {
|
||||||
@@ -89,11 +92,14 @@ func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
|
|||||||
}
|
}
|
||||||
fkdns.domainToIP = cache.NewLru(lruSize)
|
fkdns.domainToIP = cache.NewLru(lruSize)
|
||||||
fkdns.ipRange = ipRange
|
fkdns.ipRange = ipRange
|
||||||
|
fkdns.mu = new(sync.Mutex)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetFakeIPForDomain check and generate a fake IP for a domain name
|
// GetFakeIPForDomain checks and generates a fake IP for a domain name
|
||||||
func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
|
func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
|
||||||
|
fkdns.mu.Lock()
|
||||||
|
defer fkdns.mu.Unlock()
|
||||||
if v, ok := fkdns.domainToIP.Get(domain); ok {
|
if v, ok := fkdns.domainToIP.Get(domain); ok {
|
||||||
return []net.Address{v.(net.Address)}
|
return []net.Address{v.(net.Address)}
|
||||||
}
|
}
|
||||||
@@ -123,7 +129,7 @@ func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
|
|||||||
return []net.Address{ip}
|
return []net.Address{ip}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDomainFromFakeDNS check if an IP is a fake IP and have corresponding domain name
|
// GetDomainFromFakeDNS checks if an IP is a fake IP and have corresponding domain name
|
||||||
func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string {
|
func (fkdns *Holder) GetDomainFromFakeDNS(ip net.Address) string {
|
||||||
if !ip.Family().IsIP() || !fkdns.ipRange.Contains(ip.IP()) {
|
if !ip.Family().IsIP() || !fkdns.ipRange.Contains(ip.IP()) {
|
||||||
return ""
|
return ""
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/dns/fakedns/fakedns.proto
|
// source: app/dns/fakedns/fakedns.proto
|
||||||
|
|
||||||
package fakedns
|
package fakedns
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
package fakedns
|
package fakedns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
gonet "net"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
gonet "net"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
"github.com/xtls/xray-core/common/uuid"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
|
"golang.org/x/sync/errgroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ipPrefix = "198.1"
|
var ipPrefix = "198.1"
|
||||||
@@ -67,6 +67,31 @@ func TestFakeDnsHolderCreateMappingManySingleDomain(t *testing.T) {
|
|||||||
assert.Equal(t, addr[0].IP().String(), addr2[0].IP().String())
|
assert.Equal(t, addr[0].IP().String(), addr2[0].IP().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetFakeIPForDomainConcurrently(t *testing.T) {
|
||||||
|
fkdns, err := NewFakeDNSHolder()
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
|
total := 200
|
||||||
|
addr := make([][]net.Address, total)
|
||||||
|
var errg errgroup.Group
|
||||||
|
for i := 0; i < total; i++ {
|
||||||
|
errg.Go(testGetFakeIP(i, addr, fkdns))
|
||||||
|
}
|
||||||
|
errg.Wait()
|
||||||
|
for i := 0; i < total; i++ {
|
||||||
|
for j := i + 1; j < total; j++ {
|
||||||
|
assert.NotEqual(t, addr[i][0].IP().String(), addr[j][0].IP().String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testGetFakeIP(index int, addr [][]net.Address, fkdns *Holder) func() error {
|
||||||
|
return func() error {
|
||||||
|
addr[index] = fkdns.GetFakeIPForDomain("fakednstest" + strconv.Itoa(index) + ".example.com")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestFakeDnsHolderCreateMappingAndRollOver(t *testing.T) {
|
func TestFakeDnsHolderCreateMappingAndRollOver(t *testing.T) {
|
||||||
fkdns, err := NewFakeDNSHolderConfigOnly(&FakeDnsPool{
|
fkdns, err := NewFakeDNSHolderConfigOnly(&FakeDnsPool{
|
||||||
IpPool: dns.FakeIPv4Pool,
|
IpPool: dns.FakeIPv4Pool,
|
||||||
@@ -148,31 +173,31 @@ func TestFakeDNSMulti(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("allocateTwoAddressForTwoPool", func(t *testing.T) {
|
t.Run("allocateTwoAddressForTwoPool", func(t *testing.T) {
|
||||||
address := fakeMulti.GetFakeIPForDomain("fakednstest.v2fly.org")
|
address := fakeMulti.GetFakeIPForDomain("fakednstest.example.com")
|
||||||
assert.Len(t, address, 2, "should be 2 address one for each pool")
|
assert.Len(t, address, 2, "should be 2 address one for each pool")
|
||||||
t.Run("eachOfThemShouldResolve:0", func(t *testing.T) {
|
t.Run("eachOfThemShouldResolve:0", func(t *testing.T) {
|
||||||
domain := fakeMulti.GetDomainFromFakeDNS(address[0])
|
domain := fakeMulti.GetDomainFromFakeDNS(address[0])
|
||||||
assert.Equal(t, "fakednstest.v2fly.org", domain)
|
assert.Equal(t, "fakednstest.example.com", domain)
|
||||||
})
|
})
|
||||||
t.Run("eachOfThemShouldResolve:1", func(t *testing.T) {
|
t.Run("eachOfThemShouldResolve:1", func(t *testing.T) {
|
||||||
domain := fakeMulti.GetDomainFromFakeDNS(address[1])
|
domain := fakeMulti.GetDomainFromFakeDNS(address[1])
|
||||||
assert.Equal(t, "fakednstest.v2fly.org", domain)
|
assert.Equal(t, "fakednstest.example.com", domain)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("understandIPTypeSelector", func(t *testing.T) {
|
t.Run("understandIPTypeSelector", func(t *testing.T) {
|
||||||
t.Run("ipv4", func(t *testing.T) {
|
t.Run("ipv4", func(t *testing.T) {
|
||||||
address := fakeMulti.GetFakeIPForDomain3("fakednstestipv4.v2fly.org", true, false)
|
address := fakeMulti.GetFakeIPForDomain3("fakednstestipv4.example.com", true, false)
|
||||||
assert.Len(t, address, 1, "should be 1 address")
|
assert.Len(t, address, 1, "should be 1 address")
|
||||||
assert.True(t, address[0].Family().IsIPv4())
|
assert.True(t, address[0].Family().IsIPv4())
|
||||||
})
|
})
|
||||||
t.Run("ipv6", func(t *testing.T) {
|
t.Run("ipv6", func(t *testing.T) {
|
||||||
address := fakeMulti.GetFakeIPForDomain3("fakednstestipv6.v2fly.org", false, true)
|
address := fakeMulti.GetFakeIPForDomain3("fakednstestipv6.example.com", false, true)
|
||||||
assert.Len(t, address, 1, "should be 1 address")
|
assert.Len(t, address, 1, "should be 1 address")
|
||||||
assert.True(t, address[0].Family().IsIPv6())
|
assert.True(t, address[0].Family().IsIPv6())
|
||||||
})
|
})
|
||||||
t.Run("ipv46", func(t *testing.T) {
|
t.Run("ipv46", func(t *testing.T) {
|
||||||
address := fakeMulti.GetFakeIPForDomain3("fakednstestipv46.v2fly.org", true, true)
|
address := fakeMulti.GetFakeIPForDomain3("fakednstestipv46.example.com", true, true)
|
||||||
assert.Len(t, address, 2, "should be 2 address")
|
assert.Len(t, address, 2, "should be 2 address")
|
||||||
assert.True(t, address[0].Family().IsIPv4())
|
assert.True(t, address[0].Family().IsIPv4())
|
||||||
assert.True(t, address[1].Family().IsIPv6())
|
assert.True(t, address[1].Family().IsIPv6())
|
||||||
|
@@ -186,7 +186,7 @@ func (c *Client) Name() string {
|
|||||||
return c.server.Name()
|
return c.server.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryIP send DNS query to the name server with the client's IP.
|
// QueryIP sends DNS query to the name server with the client's IP.
|
||||||
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, disableCache bool) ([]net.IP, error) {
|
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, disableCache bool) ([]net.IP, error) {
|
||||||
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
||||||
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, disableCache)
|
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, disableCache)
|
||||||
|
@@ -11,8 +11,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -24,6 +22,7 @@ import (
|
|||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format,
|
// DoHNameServer implemented DNS over HTTPS (RFC8484) Wire Format,
|
||||||
@@ -53,23 +52,11 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher) (*DoHNameServ
|
|||||||
TLSHandshakeTimeout: 30 * time.Second,
|
TLSHandshakeTimeout: 30 * time.Second,
|
||||||
ForceAttemptHTTP2: true,
|
ForceAttemptHTTP2: true,
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
dispatcherCtx := context.Background()
|
|
||||||
|
|
||||||
dest, err := net.ParseDestination(network + ":" + addr)
|
dest, err := net.ParseDestination(network + ":" + addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
link, err := s.dispatcher.Dispatch(toDnsContext(ctx, s.dohURL), dest)
|
||||||
dispatcherCtx = session.ContextWithContent(dispatcherCtx, session.ContentFromContext(ctx))
|
|
||||||
dispatcherCtx = session.ContextWithInbound(dispatcherCtx, session.InboundFromContext(ctx))
|
|
||||||
dispatcherCtx = log.ContextWithAccessMessage(dispatcherCtx, &log.AccessMessage{
|
|
||||||
From: "DoH",
|
|
||||||
To: s.dohURL,
|
|
||||||
Status: log.AccessAccepted,
|
|
||||||
Reason: "",
|
|
||||||
})
|
|
||||||
|
|
||||||
link, err := s.dispatcher.Dispatch(dispatcherCtx, dest)
|
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, ctx.Err()
|
return nil, ctx.Err()
|
||||||
@@ -116,7 +103,7 @@ func NewDoHLocalNameServer(url *url.URL) *DoHNameServer {
|
|||||||
}
|
}
|
||||||
conn, err := internet.DialSystem(ctx, dest, nil)
|
conn, err := internet.DialSystem(ctx, dest, nil)
|
||||||
log.Record(&log.AccessMessage{
|
log.Record(&log.AccessMessage{
|
||||||
From: "DoH",
|
From: "DNS",
|
||||||
To: s.dohURL,
|
To: s.dohURL,
|
||||||
Status: log.AccessAccepted,
|
Status: log.AccessAccepted,
|
||||||
Detour: "local",
|
Detour: "local",
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
. "github.com/xtls/xray-core/app/dns"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
@@ -3,10 +3,11 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/common/log"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/dns/localdns"
|
"github.com/xtls/xray-core/features/dns/localdns"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,6 +20,7 @@ const errEmptyResponse = "No address associated with hostname"
|
|||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) {
|
func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) {
|
||||||
|
start := time.Now()
|
||||||
ips, err = s.client.LookupIP(domain, option)
|
ips, err = s.client.LookupIP(domain, option)
|
||||||
|
|
||||||
if err != nil && strings.HasSuffix(err.Error(), errEmptyResponse) {
|
if err != nil && strings.HasSuffix(err.Error(), errEmptyResponse) {
|
||||||
@@ -27,6 +29,7 @@ func (s *LocalNameServer) QueryIP(_ context.Context, domain string, _ net.IP, op
|
|||||||
|
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
newError("Localhost got answer: ", domain, " -> ", ips).AtInfo().WriteToLog()
|
newError("Localhost got answer: ", domain, " -> ", ips).AtInfo().WriteToLog()
|
||||||
|
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@@ -5,10 +5,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
. "github.com/xtls/xray-core/app/dns"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -7,9 +7,10 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lucas-clemente/quic-go"
|
"github.com/quic-go/quic-go"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol/dns"
|
"github.com/xtls/xray-core/common/protocol/dns"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
@@ -36,7 +37,7 @@ type QUICNameServer struct {
|
|||||||
reqID uint32
|
reqID uint32
|
||||||
name string
|
name string
|
||||||
destination *net.Destination
|
destination *net.Destination
|
||||||
session quic.Session
|
connection quic.Connection
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
||||||
@@ -193,7 +194,7 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP
|
|||||||
|
|
||||||
conn, err := s.openStream(dnsCtx)
|
conn, err := s.openStream(dnsCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
newError("failed to open quic session").Base(err).AtError().WriteToLog()
|
newError("failed to open quic connection").Base(err).AtError().WriteToLog()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,6 +276,7 @@ func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP ne
|
|||||||
ips, err := s.findIPsForDomain(fqdn, option)
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
if err != errRecordNotFound {
|
if err != errRecordNotFound {
|
||||||
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
||||||
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
return ips, err
|
return ips, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -306,10 +308,12 @@ func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP ne
|
|||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
s.sendQuery(ctx, fqdn, clientIP, option)
|
s.sendQuery(ctx, fqdn, clientIP, option)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
ips, err := s.findIPsForDomain(fqdn, option)
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
if err != errRecordNotFound {
|
if err != errRecordNotFound {
|
||||||
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
return ips, err
|
return ips, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +325,7 @@ func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP ne
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isActive(s quic.Session) bool {
|
func isActive(s quic.Connection) bool {
|
||||||
select {
|
select {
|
||||||
case <-s.Context().Done():
|
case <-s.Context().Done():
|
||||||
return false
|
return false
|
||||||
@@ -330,17 +334,17 @@ func isActive(s quic.Session) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) getSession() (quic.Session, error) {
|
func (s *QUICNameServer) getConnection() (quic.Connection, error) {
|
||||||
var session quic.Session
|
var conn quic.Connection
|
||||||
s.RLock()
|
s.RLock()
|
||||||
session = s.session
|
conn = s.connection
|
||||||
if session != nil && isActive(session) {
|
if conn != nil && isActive(conn) {
|
||||||
s.RUnlock()
|
s.RUnlock()
|
||||||
return session, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
if session != nil {
|
if conn != nil {
|
||||||
// we're recreating the session, let's create a new one
|
// we're recreating the connection, let's create a new one
|
||||||
_ = session.CloseWithError(0, "")
|
_ = conn.CloseWithError(0, "")
|
||||||
}
|
}
|
||||||
s.RUnlock()
|
s.RUnlock()
|
||||||
|
|
||||||
@@ -348,42 +352,48 @@ func (s *QUICNameServer) getSession() (quic.Session, error) {
|
|||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
session, err = s.openSession()
|
conn, err = s.openConnection()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// This does not look too nice, but QUIC (or maybe quic-go)
|
// This does not look too nice, but QUIC (or maybe quic-go)
|
||||||
// doesn't seem stable enough.
|
// doesn't seem stable enough.
|
||||||
// Maybe retransmissions aren't fully implemented in quic-go?
|
// Maybe retransmissions aren't fully implemented in quic-go?
|
||||||
// Anyways, the simple solution is to make a second try when
|
// Anyways, the simple solution is to make a second try when
|
||||||
// it fails to open the QUIC session.
|
// it fails to open the QUIC connection.
|
||||||
session, err = s.openSession()
|
conn, err = s.openConnection()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.session = session
|
s.connection = conn
|
||||||
return session, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) openSession() (quic.Session, error) {
|
func (s *QUICNameServer) openConnection() (quic.Connection, error) {
|
||||||
tlsConfig := tls.Config{}
|
tlsConfig := tls.Config{}
|
||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
HandshakeIdleTimeout: handshakeTimeout,
|
HandshakeIdleTimeout: handshakeTimeout,
|
||||||
}
|
}
|
||||||
|
tlsConfig.ServerName = s.destination.Address.String()
|
||||||
session, err := quic.DialAddrContext(context.Background(), s.destination.NetAddr(), tlsConfig.GetTLSConfig(tls.WithNextProto("http/1.1", http2.NextProtoTLS, NextProtoDQ)), quicConfig)
|
conn, err := quic.DialAddr(context.Background(), s.destination.NetAddr(), tlsConfig.GetTLSConfig(tls.WithNextProto("http/1.1", http2.NextProtoTLS, NextProtoDQ)), quicConfig)
|
||||||
|
log.Record(&log.AccessMessage{
|
||||||
|
From: "DNS",
|
||||||
|
To: s.destination,
|
||||||
|
Status: log.AccessAccepted,
|
||||||
|
Detour: "local",
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return session, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) openStream(ctx context.Context) (quic.Stream, error) {
|
func (s *QUICNameServer) openStream(ctx context.Context) (quic.Stream, error) {
|
||||||
session, err := s.getSession()
|
conn, err := s.getConnection()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// open a new stream
|
// open a new stream
|
||||||
return session.OpenStreamSync(ctx)
|
return conn.OpenStreamSync(ctx)
|
||||||
}
|
}
|
||||||
|
@@ -6,13 +6,11 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/features/dns"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
. "github.com/xtls/xray-core/app/dns"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestQUICNameServer(t *testing.T) {
|
func TestQUICNameServer(t *testing.T) {
|
||||||
|
@@ -9,10 +9,9 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
"github.com/xtls/xray-core/common/protocol/dns"
|
"github.com/xtls/xray-core/common/protocol/dns"
|
||||||
@@ -22,6 +21,7 @@ import (
|
|||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TCPNameServer implemented DNS over TCP (RFC7766).
|
// TCPNameServer implemented DNS over TCP (RFC7766).
|
||||||
@@ -44,7 +44,7 @@ func NewTCPNameServer(url *url.URL, dispatcher routing.Dispatcher) (*TCPNameServ
|
|||||||
}
|
}
|
||||||
|
|
||||||
s.dial = func(ctx context.Context) (net.Conn, error) {
|
s.dial = func(ctx context.Context) (net.Conn, error) {
|
||||||
link, err := dispatcher.Dispatch(ctx, *s.destination)
|
link, err := dispatcher.Dispatch(toDnsContext(ctx, s.destination.String()), *s.destination)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -315,6 +315,7 @@ func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, clientIP net
|
|||||||
ips, err := s.findIPsForDomain(fqdn, option)
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
if err != errRecordNotFound {
|
if err != errRecordNotFound {
|
||||||
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
newError(s.name, " cache HIT ", domain, " -> ", ips).Base(err).AtDebug().WriteToLog()
|
||||||
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
return ips, err
|
return ips, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -346,10 +347,12 @@ func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, clientIP net
|
|||||||
close(done)
|
close(done)
|
||||||
}()
|
}()
|
||||||
s.sendQuery(ctx, fqdn, clientIP, option)
|
s.sendQuery(ctx, fqdn, clientIP, option)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
ips, err := s.findIPsForDomain(fqdn, option)
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
if err != errRecordNotFound {
|
if err != errRecordNotFound {
|
||||||
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
return ips, err
|
return ips, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
. "github.com/xtls/xray-core/app/dns"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
@@ -7,8 +7,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -20,6 +18,7 @@ import (
|
|||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet/udp"
|
"github.com/xtls/xray-core/transport/internet/udp"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClassicNameServer implemented traditional UDP DNS.
|
// ClassicNameServer implemented traditional UDP DNS.
|
||||||
@@ -195,21 +194,7 @@ func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, client
|
|||||||
for _, req := range reqs {
|
for _, req := range reqs {
|
||||||
s.addPendingRequest(req)
|
s.addPendingRequest(req)
|
||||||
b, _ := dns.PackMessage(req.msg)
|
b, _ := dns.PackMessage(req.msg)
|
||||||
udpCtx := context.Background()
|
s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
|
||||||
udpCtx = session.ContextWithInbound(udpCtx, inbound)
|
|
||||||
}
|
|
||||||
|
|
||||||
udpCtx = session.ContextWithContent(udpCtx, &session.Content{
|
|
||||||
Protocol: "dns",
|
|
||||||
})
|
|
||||||
udpCtx = log.ContextWithAccessMessage(udpCtx, &log.AccessMessage{
|
|
||||||
From: "DNS",
|
|
||||||
To: s.address,
|
|
||||||
Status: log.AccessAccepted,
|
|
||||||
Reason: "",
|
|
||||||
})
|
|
||||||
s.udpServer.Dispatch(udpCtx, *s.address, b)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -5,11 +5,10 @@ package command
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/log"
|
"github.com/xtls/xray-core/app/log"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LoggerServer struct {
|
type LoggerServer struct {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/log/command/config.proto
|
// source: app/log/command/config.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
|
// - protoc v4.23.1
|
||||||
|
// source: app/log/command/config.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
@@ -14,6 +18,10 @@ import (
|
|||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
|
const (
|
||||||
|
LoggerService_RestartLogger_FullMethodName = "/xray.app.log.command.LoggerService/RestartLogger"
|
||||||
|
)
|
||||||
|
|
||||||
// LoggerServiceClient is the client API for LoggerService service.
|
// LoggerServiceClient is the client API for LoggerService service.
|
||||||
//
|
//
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
@@ -31,7 +39,7 @@ func NewLoggerServiceClient(cc grpc.ClientConnInterface) LoggerServiceClient {
|
|||||||
|
|
||||||
func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *RestartLoggerRequest, opts ...grpc.CallOption) (*RestartLoggerResponse, error) {
|
func (c *loggerServiceClient) RestartLogger(ctx context.Context, in *RestartLoggerRequest, opts ...grpc.CallOption) (*RestartLoggerResponse, error) {
|
||||||
out := new(RestartLoggerResponse)
|
out := new(RestartLoggerResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.log.command.LoggerService/RestartLogger", in, out, opts...)
|
err := c.cc.Invoke(ctx, LoggerService_RestartLogger_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -76,7 +84,7 @@ func _LoggerService_RestartLogger_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.log.command.LoggerService/RestartLogger",
|
FullMethod: LoggerService_RestartLogger_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(LoggerServiceServer).RestartLogger(ctx, req.(*RestartLoggerRequest))
|
return srv.(LoggerServiceServer).RestartLogger(ctx, req.(*RestartLoggerRequest))
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/log/config.proto
|
// source: app/log/config.proto
|
||||||
|
|
||||||
package log
|
package log
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
)
|
)
|
||||||
@@ -13,16 +15,24 @@ type HandlerCreator func(LogType, HandlerCreatorOptions) (log.Handler, error)
|
|||||||
|
|
||||||
var handlerCreatorMap = make(map[LogType]HandlerCreator)
|
var handlerCreatorMap = make(map[LogType]HandlerCreator)
|
||||||
|
|
||||||
|
var handlerCreatorMapLock = &sync.RWMutex{}
|
||||||
|
|
||||||
func RegisterHandlerCreator(logType LogType, f HandlerCreator) error {
|
func RegisterHandlerCreator(logType LogType, f HandlerCreator) error {
|
||||||
if f == nil {
|
if f == nil {
|
||||||
return newError("nil HandlerCreator")
|
return newError("nil HandlerCreator")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handlerCreatorMapLock.Lock()
|
||||||
|
defer handlerCreatorMapLock.Unlock()
|
||||||
|
|
||||||
handlerCreatorMap[logType] = f
|
handlerCreatorMap[logType] = f
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createHandler(logType LogType, options HandlerCreatorOptions) (log.Handler, error) {
|
func createHandler(logType LogType, options HandlerCreatorOptions) (log.Handler, error) {
|
||||||
|
handlerCreatorMapLock.RLock()
|
||||||
|
defer handlerCreatorMapLock.RUnlock()
|
||||||
|
|
||||||
creator, found := handlerCreatorMap[logType]
|
creator, found := handlerCreatorMap[logType]
|
||||||
if !found {
|
if !found {
|
||||||
return nil, newError("unable to create log handler for ", logType)
|
return nil, newError("unable to create log handler for ", logType)
|
||||||
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/log"
|
"github.com/xtls/xray-core/app/log"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
clog "github.com/xtls/xray-core/common/log"
|
clog "github.com/xtls/xray-core/common/log"
|
||||||
|
149
app/metrics/config.pb.go
Normal file
149
app/metrics/config.pb.go
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.30.0
|
||||||
|
// protoc v4.23.1
|
||||||
|
// source: app/metrics/config.proto
|
||||||
|
|
||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config is the settings for metrics.
|
||||||
|
type Config struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
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"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) Reset() {
|
||||||
|
*x = Config{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_metrics_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_metrics_config_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_metrics_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetTag() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Tag
|
||||||
|
}
|
||||||
|
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, 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, 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 (
|
||||||
|
file_app_metrics_config_proto_rawDescOnce sync.Once
|
||||||
|
file_app_metrics_config_proto_rawDescData = file_app_metrics_config_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_app_metrics_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_app_metrics_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_app_metrics_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_metrics_config_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_app_metrics_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_app_metrics_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||||
|
var file_app_metrics_config_proto_goTypes = []interface{}{
|
||||||
|
(*Config)(nil), // 0: xray.app.metrics.Config
|
||||||
|
}
|
||||||
|
var file_app_metrics_config_proto_depIdxs = []int32{
|
||||||
|
0, // [0:0] is the sub-list for method output_type
|
||||||
|
0, // [0:0] is the sub-list for method input_type
|
||||||
|
0, // [0:0] is the sub-list for extension type_name
|
||||||
|
0, // [0:0] is the sub-list for extension extendee
|
||||||
|
0, // [0:0] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_app_metrics_config_proto_init() }
|
||||||
|
func file_app_metrics_config_proto_init() {
|
||||||
|
if File_app_metrics_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_app_metrics_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Config); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_app_metrics_config_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 1,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_app_metrics_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_app_metrics_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_app_metrics_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_app_metrics_config_proto = out.File
|
||||||
|
file_app_metrics_config_proto_rawDesc = nil
|
||||||
|
file_app_metrics_config_proto_goTypes = nil
|
||||||
|
file_app_metrics_config_proto_depIdxs = nil
|
||||||
|
}
|
13
app/metrics/config.proto
Normal file
13
app/metrics/config.proto
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.app.metrics;
|
||||||
|
option csharp_namespace = "Xray.App.Metrics";
|
||||||
|
option go_package = "github.com/xtls/xray-core/app/metrics";
|
||||||
|
option java_package = "com.xray.app.metrics";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
// Config is the settings for metrics.
|
||||||
|
message Config {
|
||||||
|
// Tag of the outbound handler that handles metrics http connections.
|
||||||
|
string tag = 1;
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package mtproto
|
package metrics
|
||||||
|
|
||||||
import "github.com/xtls/xray-core/common/errors"
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
118
app/metrics/metrics.go
Normal file
118
app/metrics/metrics.go
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"expvar"
|
||||||
|
"net/http"
|
||||||
|
_ "net/http/pprof"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/app/observatory"
|
||||||
|
"github.com/xtls/xray-core/app/stats"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/extension"
|
||||||
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
|
feature_stats "github.com/xtls/xray-core/features/stats"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MetricsHandler struct {
|
||||||
|
ohm outbound.Manager
|
||||||
|
statsManager feature_stats.Manager
|
||||||
|
observatory extension.Observatory
|
||||||
|
tag string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMetricsHandler creates a new MetricsHandler based on the given config.
|
||||||
|
func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHandler, error) {
|
||||||
|
c := &MetricsHandler{
|
||||||
|
tag: config.Tag,
|
||||||
|
}
|
||||||
|
common.Must(core.RequireFeatures(ctx, func(om outbound.Manager, sm feature_stats.Manager) {
|
||||||
|
c.statsManager = sm
|
||||||
|
c.ohm = om
|
||||||
|
}))
|
||||||
|
expvar.Publish("stats", expvar.Func(func() interface{} {
|
||||||
|
manager, ok := c.statsManager.(*stats.Manager)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
resp := map[string]map[string]map[string]int64{
|
||||||
|
"inbound": {},
|
||||||
|
"outbound": {},
|
||||||
|
"user": {},
|
||||||
|
}
|
||||||
|
manager.VisitCounters(func(name string, counter feature_stats.Counter) bool {
|
||||||
|
nameSplit := strings.Split(name, ">>>")
|
||||||
|
typeName, tagOrUser, direction := nameSplit[0], nameSplit[1], nameSplit[3]
|
||||||
|
if item, found := resp[typeName][tagOrUser]; found {
|
||||||
|
item[direction] = counter.Value()
|
||||||
|
} else {
|
||||||
|
resp[typeName][tagOrUser] = map[string]int64{
|
||||||
|
direction: counter.Value(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return resp
|
||||||
|
}))
|
||||||
|
expvar.Publish("observatory", expvar.Func(func() interface{} {
|
||||||
|
if c.observatory == nil {
|
||||||
|
common.Must(core.RequireFeatures(ctx, func(observatory extension.Observatory) error {
|
||||||
|
c.observatory = observatory
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
if c.observatory == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resp := map[string]*observatory.OutboundStatus{}
|
||||||
|
if o, err := c.observatory.GetObservation(context.Background()); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
for _, x := range o.(*observatory.ObservationResult).GetStatus() {
|
||||||
|
resp[x.OutboundTag] = x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resp
|
||||||
|
}))
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MetricsHandler) Type() interface{} {
|
||||||
|
return (*MetricsHandler)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MetricsHandler) Start() error {
|
||||||
|
listener := &OutboundListener{
|
||||||
|
buffer: make(chan net.Conn, 4),
|
||||||
|
done: done.New(),
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := http.Serve(listener, http.DefaultServeMux); err != nil {
|
||||||
|
newError("failed to start metrics server").Base(err).AtError().WriteToLog()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := p.ohm.RemoveHandler(context.Background(), p.tag); err != nil {
|
||||||
|
newError("failed to remove existing handler").WriteToLog()
|
||||||
|
}
|
||||||
|
|
||||||
|
return p.ohm.AddHandler(context.Background(), &Outbound{
|
||||||
|
tag: p.tag,
|
||||||
|
listener: listener,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MetricsHandler) Close() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
|
||||||
|
return NewMetricsHandler(ctx, cfg.(*Config))
|
||||||
|
}))
|
||||||
|
}
|
109
app/metrics/outbound.go
Normal file
109
app/metrics/outbound.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package metrics
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
|
"github.com/xtls/xray-core/transport"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OutboundListener is a net.Listener for listening metrics http connections.
|
||||||
|
type OutboundListener struct {
|
||||||
|
buffer chan net.Conn
|
||||||
|
done *done.Instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *OutboundListener) add(conn net.Conn) {
|
||||||
|
select {
|
||||||
|
case l.buffer <- conn:
|
||||||
|
case <-l.done.Wait():
|
||||||
|
conn.Close()
|
||||||
|
default:
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept implements net.Listener.
|
||||||
|
func (l *OutboundListener) Accept() (net.Conn, error) {
|
||||||
|
select {
|
||||||
|
case <-l.done.Wait():
|
||||||
|
return nil, newError("listen closed")
|
||||||
|
case c := <-l.buffer:
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close implement net.Listener.
|
||||||
|
func (l *OutboundListener) Close() error {
|
||||||
|
common.Must(l.done.Close())
|
||||||
|
L:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case c := <-l.buffer:
|
||||||
|
c.Close()
|
||||||
|
default:
|
||||||
|
break L
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Addr implements net.Listener.
|
||||||
|
func (l *OutboundListener) Addr() net.Addr {
|
||||||
|
return &net.TCPAddr{
|
||||||
|
IP: net.IP{0, 0, 0, 0},
|
||||||
|
Port: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outbound is an outbound.Handler that handles metrics http connections.
|
||||||
|
type Outbound struct {
|
||||||
|
tag string
|
||||||
|
listener *OutboundListener
|
||||||
|
access sync.RWMutex
|
||||||
|
closed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch implements outbound.Handler.
|
||||||
|
func (co *Outbound) Dispatch(ctx context.Context, link *transport.Link) {
|
||||||
|
co.access.RLock()
|
||||||
|
|
||||||
|
if co.closed {
|
||||||
|
common.Interrupt(link.Reader)
|
||||||
|
common.Interrupt(link.Writer)
|
||||||
|
co.access.RUnlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
closeSignal := done.New()
|
||||||
|
c := cnc.NewConnection(cnc.ConnectionInputMulti(link.Writer), cnc.ConnectionOutputMulti(link.Reader), cnc.ConnectionOnClose(closeSignal))
|
||||||
|
co.listener.add(c)
|
||||||
|
co.access.RUnlock()
|
||||||
|
<-closeSignal.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tag implements outbound.Handler.
|
||||||
|
func (co *Outbound) Tag() string {
|
||||||
|
return co.tag
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start implements common.Runnable.
|
||||||
|
func (co *Outbound) Start() error {
|
||||||
|
co.access.Lock()
|
||||||
|
co.closed = false
|
||||||
|
co.access.Unlock()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close implements common.Closable.
|
||||||
|
func (co *Outbound) Close() error {
|
||||||
|
co.access.Lock()
|
||||||
|
defer co.access.Unlock()
|
||||||
|
|
||||||
|
co.closed = true
|
||||||
|
return co.listener.Close()
|
||||||
|
}
|
50
app/observatory/command/command.go
Normal file
50
app/observatory/command/command.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//go:build !confonly
|
||||||
|
// +build !confonly
|
||||||
|
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/app/observatory"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
core "github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/extension"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
type service struct {
|
||||||
|
UnimplementedObservatoryServiceServer
|
||||||
|
v *core.Instance
|
||||||
|
|
||||||
|
observatory extension.Observatory
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) GetOutboundStatus(ctx context.Context, request *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) {
|
||||||
|
resp, err := s.observatory.GetObservation(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
retdata := resp.(*observatory.ObservationResult)
|
||||||
|
return &GetOutboundStatusResponse{
|
||||||
|
Status: retdata,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *service) Register(server *grpc.Server) {
|
||||||
|
RegisterObservatoryServiceServer(server, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
|
||||||
|
s := core.MustFromContext(ctx)
|
||||||
|
sv := &service{v: s}
|
||||||
|
err := s.RequireFeatures(func(Observatory extension.Observatory) {
|
||||||
|
sv.observatory = Observatory
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return sv, nil
|
||||||
|
}))
|
||||||
|
}
|
278
app/observatory/command/command.pb.go
Normal file
278
app/observatory/command/command.pb.go
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.30.0
|
||||||
|
// protoc v4.23.1
|
||||||
|
// source: app/observatory/command/command.proto
|
||||||
|
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
observatory "github.com/xtls/xray-core/app/observatory"
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetOutboundStatusRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetOutboundStatusRequest) Reset() {
|
||||||
|
*x = GetOutboundStatusRequest{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_observatory_command_command_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetOutboundStatusRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetOutboundStatusRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetOutboundStatusRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_observatory_command_command_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetOutboundStatusRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetOutboundStatusRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_observatory_command_command_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetOutboundStatusResponse struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Status *observatory.ObservationResult `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetOutboundStatusResponse) Reset() {
|
||||||
|
*x = GetOutboundStatusResponse{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_observatory_command_command_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetOutboundStatusResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetOutboundStatusResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetOutboundStatusResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_observatory_command_command_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetOutboundStatusResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetOutboundStatusResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_observatory_command_command_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetOutboundStatusResponse) GetStatus() *observatory.ObservationResult {
|
||||||
|
if x != nil {
|
||||||
|
return x.Status
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) Reset() {
|
||||||
|
*x = Config{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_observatory_command_command_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_observatory_command_command_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_observatory_command_command_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_app_observatory_command_command_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_app_observatory_command_command_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x25, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
|
||||||
|
0x79, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
||||||
|
0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
||||||
|
0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
|
||||||
|
0x72, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x1c, 0x61, 0x70, 0x70, 0x2f,
|
||||||
|
0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66,
|
||||||
|
0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x4f,
|
||||||
|
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71,
|
||||||
|
0x75, 0x65, 0x73, 0x74, 0x22, 0x61, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
||||||
|
0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||||
|
0x65, 0x12, 0x44, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70,
|
||||||
|
0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x4f, 0x62,
|
||||||
|
0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52,
|
||||||
|
0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
|
0x67, 0x32, 0xa7, 0x01, 0x0a, 0x12, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
|
||||||
|
0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x90, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x74,
|
||||||
|
0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3b,
|
||||||
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f,
|
||||||
|
0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||||
|
0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74,
|
||||||
|
0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x78, 0x72,
|
||||||
|
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65,
|
||||||
|
0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
||||||
|
0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75,
|
||||||
|
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x80, 0x01, 0x0a, 0x25,
|
||||||
|
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70,
|
||||||
|
0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x63, 0x6f,
|
||||||
|
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x31, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||||
|
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
||||||
|
0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
|
||||||
|
0x72, 0x79, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x21, 0x58, 0x72, 0x61,
|
||||||
|
0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72,
|
||||||
|
0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06,
|
||||||
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_app_observatory_command_command_proto_rawDescOnce sync.Once
|
||||||
|
file_app_observatory_command_command_proto_rawDescData = file_app_observatory_command_command_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_app_observatory_command_command_proto_rawDescGZIP() []byte {
|
||||||
|
file_app_observatory_command_command_proto_rawDescOnce.Do(func() {
|
||||||
|
file_app_observatory_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_observatory_command_command_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_app_observatory_command_command_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_app_observatory_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||||
|
var file_app_observatory_command_command_proto_goTypes = []interface{}{
|
||||||
|
(*GetOutboundStatusRequest)(nil), // 0: xray.core.app.observatory.command.GetOutboundStatusRequest
|
||||||
|
(*GetOutboundStatusResponse)(nil), // 1: xray.core.app.observatory.command.GetOutboundStatusResponse
|
||||||
|
(*Config)(nil), // 2: xray.core.app.observatory.command.Config
|
||||||
|
(*observatory.ObservationResult)(nil), // 3: xray.core.app.observatory.ObservationResult
|
||||||
|
}
|
||||||
|
var file_app_observatory_command_command_proto_depIdxs = []int32{
|
||||||
|
3, // 0: xray.core.app.observatory.command.GetOutboundStatusResponse.status:type_name -> xray.core.app.observatory.ObservationResult
|
||||||
|
0, // 1: xray.core.app.observatory.command.ObservatoryService.GetOutboundStatus:input_type -> xray.core.app.observatory.command.GetOutboundStatusRequest
|
||||||
|
1, // 2: xray.core.app.observatory.command.ObservatoryService.GetOutboundStatus:output_type -> xray.core.app.observatory.command.GetOutboundStatusResponse
|
||||||
|
2, // [2:3] is the sub-list for method output_type
|
||||||
|
1, // [1:2] is the sub-list for method input_type
|
||||||
|
1, // [1:1] is the sub-list for extension type_name
|
||||||
|
1, // [1:1] is the sub-list for extension extendee
|
||||||
|
0, // [0:1] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_app_observatory_command_command_proto_init() }
|
||||||
|
func file_app_observatory_command_command_proto_init() {
|
||||||
|
if File_app_observatory_command_command_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_app_observatory_command_command_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*GetOutboundStatusRequest); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_app_observatory_command_command_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*GetOutboundStatusResponse); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_app_observatory_command_command_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Config); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_app_observatory_command_command_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 3,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 1,
|
||||||
|
},
|
||||||
|
GoTypes: file_app_observatory_command_command_proto_goTypes,
|
||||||
|
DependencyIndexes: file_app_observatory_command_command_proto_depIdxs,
|
||||||
|
MessageInfos: file_app_observatory_command_command_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_app_observatory_command_command_proto = out.File
|
||||||
|
file_app_observatory_command_command_proto_rawDesc = nil
|
||||||
|
file_app_observatory_command_command_proto_goTypes = nil
|
||||||
|
file_app_observatory_command_command_proto_depIdxs = nil
|
||||||
|
}
|
24
app/observatory/command/command.proto
Normal file
24
app/observatory/command/command.proto
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.core.app.observatory.command;
|
||||||
|
option csharp_namespace = "Xray.Core.App.Observatory.Command";
|
||||||
|
option go_package = "github.com/xtls/xray-core/app/observatory/command";
|
||||||
|
option java_package = "com.xray.core.app.observatory.command";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
import "app/observatory/config.proto";
|
||||||
|
|
||||||
|
message GetOutboundStatusRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetOutboundStatusResponse {
|
||||||
|
xray.core.app.observatory.ObservationResult status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
service ObservatoryService {
|
||||||
|
rpc GetOutboundStatus(GetOutboundStatusRequest)
|
||||||
|
returns (GetOutboundStatusResponse) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
message Config {}
|
109
app/observatory/command/command_grpc.pb.go
Normal file
109
app/observatory/command/command_grpc.pb.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
|
// - protoc v4.23.1
|
||||||
|
// source: app/observatory/command/command.proto
|
||||||
|
|
||||||
|
package command
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
|
const (
|
||||||
|
ObservatoryService_GetOutboundStatus_FullMethodName = "/xray.core.app.observatory.command.ObservatoryService/GetOutboundStatus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ObservatoryServiceClient is the client API for ObservatoryService service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
|
type ObservatoryServiceClient interface {
|
||||||
|
GetOutboundStatus(ctx context.Context, in *GetOutboundStatusRequest, opts ...grpc.CallOption) (*GetOutboundStatusResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type observatoryServiceClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewObservatoryServiceClient(cc grpc.ClientConnInterface) ObservatoryServiceClient {
|
||||||
|
return &observatoryServiceClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *observatoryServiceClient) GetOutboundStatus(ctx context.Context, in *GetOutboundStatusRequest, opts ...grpc.CallOption) (*GetOutboundStatusResponse, error) {
|
||||||
|
out := new(GetOutboundStatusResponse)
|
||||||
|
err := c.cc.Invoke(ctx, ObservatoryService_GetOutboundStatus_FullMethodName, in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObservatoryServiceServer is the server API for ObservatoryService service.
|
||||||
|
// All implementations must embed UnimplementedObservatoryServiceServer
|
||||||
|
// for forward compatibility
|
||||||
|
type ObservatoryServiceServer interface {
|
||||||
|
GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error)
|
||||||
|
mustEmbedUnimplementedObservatoryServiceServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedObservatoryServiceServer must be embedded to have forward compatible implementations.
|
||||||
|
type UnimplementedObservatoryServiceServer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (UnimplementedObservatoryServiceServer) GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method GetOutboundStatus not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedObservatoryServiceServer) mustEmbedUnimplementedObservatoryServiceServer() {}
|
||||||
|
|
||||||
|
// UnsafeObservatoryServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
// Use of this interface is not recommended, as added methods to ObservatoryServiceServer will
|
||||||
|
// result in compilation errors.
|
||||||
|
type UnsafeObservatoryServiceServer interface {
|
||||||
|
mustEmbedUnimplementedObservatoryServiceServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterObservatoryServiceServer(s grpc.ServiceRegistrar, srv ObservatoryServiceServer) {
|
||||||
|
s.RegisterService(&ObservatoryService_ServiceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _ObservatoryService_GetOutboundStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetOutboundStatusRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(ObservatoryServiceServer).GetOutboundStatus(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: ObservatoryService_GetOutboundStatus_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(ObservatoryServiceServer).GetOutboundStatus(ctx, req.(*GetOutboundStatusRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObservatoryService_ServiceDesc is the grpc.ServiceDesc for ObservatoryService service.
|
||||||
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
var ObservatoryService_ServiceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "xray.core.app.observatory.command.ObservatoryService",
|
||||||
|
HandlerType: (*ObservatoryServiceServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "GetOutboundStatus",
|
||||||
|
Handler: _ObservatoryService_GetOutboundStatus_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "app/observatory/command/command.proto",
|
||||||
|
}
|
530
app/observatory/config.pb.go
Normal file
530
app/observatory/config.pb.go
Normal file
@@ -0,0 +1,530 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.30.0
|
||||||
|
// protoc v4.23.1
|
||||||
|
// source: app/observatory/config.proto
|
||||||
|
|
||||||
|
package observatory
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Verify that this generated code is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||||
|
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||||
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
|
)
|
||||||
|
|
||||||
|
type ObservationResult struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Status []*OutboundStatus `protobuf:"bytes,1,rep,name=status,proto3" json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ObservationResult) Reset() {
|
||||||
|
*x = ObservationResult{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ObservationResult) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ObservationResult) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ObservationResult) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[0]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ObservationResult.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ObservationResult) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_observatory_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ObservationResult) GetStatus() []*OutboundStatus {
|
||||||
|
if x != nil {
|
||||||
|
return x.Status
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type OutboundStatus struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// @Document Whether this outbound is usable
|
||||||
|
// @Restriction ReadOnlyForUser
|
||||||
|
Alive bool `protobuf:"varint,1,opt,name=alive,proto3" json:"alive,omitempty"`
|
||||||
|
// @Document The time for probe request to finish.
|
||||||
|
// @Type time.ms
|
||||||
|
// @Restriction ReadOnlyForUser
|
||||||
|
Delay int64 `protobuf:"varint,2,opt,name=delay,proto3" json:"delay,omitempty"`
|
||||||
|
// @Document The last error caused this outbound failed to relay probe request
|
||||||
|
// @Restriction NotMachineReadable
|
||||||
|
LastErrorReason string `protobuf:"bytes,3,opt,name=last_error_reason,json=lastErrorReason,proto3" json:"last_error_reason,omitempty"`
|
||||||
|
// @Document The outbound tag for this Server
|
||||||
|
// @Type id.outboundTag
|
||||||
|
OutboundTag string `protobuf:"bytes,4,opt,name=outbound_tag,json=outboundTag,proto3" json:"outbound_tag,omitempty"`
|
||||||
|
// @Document The time this outbound is known to be alive
|
||||||
|
// @Type id.outboundTag
|
||||||
|
LastSeenTime int64 `protobuf:"varint,5,opt,name=last_seen_time,json=lastSeenTime,proto3" json:"last_seen_time,omitempty"`
|
||||||
|
// @Document The time this outbound is tried
|
||||||
|
// @Type id.outboundTag
|
||||||
|
LastTryTime int64 `protobuf:"varint,6,opt,name=last_try_time,json=lastTryTime,proto3" json:"last_try_time,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) Reset() {
|
||||||
|
*x = OutboundStatus{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*OutboundStatus) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[1]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use OutboundStatus.ProtoReflect.Descriptor instead.
|
||||||
|
func (*OutboundStatus) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_observatory_config_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) GetAlive() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Alive
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) GetDelay() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Delay
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) GetLastErrorReason() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.LastErrorReason
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) GetOutboundTag() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.OutboundTag
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) GetLastSeenTime() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.LastSeenTime
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OutboundStatus) GetLastTryTime() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.LastTryTime
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProbeResult struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// @Document Whether this outbound is usable
|
||||||
|
// @Restriction ReadOnlyForUser
|
||||||
|
Alive bool `protobuf:"varint,1,opt,name=alive,proto3" json:"alive,omitempty"`
|
||||||
|
// @Document The time for probe request to finish.
|
||||||
|
// @Type time.ms
|
||||||
|
// @Restriction ReadOnlyForUser
|
||||||
|
Delay int64 `protobuf:"varint,2,opt,name=delay,proto3" json:"delay,omitempty"`
|
||||||
|
// @Document The error caused this outbound failed to relay probe request
|
||||||
|
// @Restriction NotMachineReadable
|
||||||
|
LastErrorReason string `protobuf:"bytes,3,opt,name=last_error_reason,json=lastErrorReason,proto3" json:"last_error_reason,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ProbeResult) Reset() {
|
||||||
|
*x = ProbeResult{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ProbeResult) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*ProbeResult) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *ProbeResult) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[2]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use ProbeResult.ProtoReflect.Descriptor instead.
|
||||||
|
func (*ProbeResult) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_observatory_config_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ProbeResult) GetAlive() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Alive
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ProbeResult) GetDelay() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Delay
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *ProbeResult) GetLastErrorReason() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.LastErrorReason
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type Intensity struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// @Document The time interval for a probe request in ms.
|
||||||
|
// @Type time.ms
|
||||||
|
ProbeInterval uint32 `protobuf:"varint,1,opt,name=probe_interval,json=probeInterval,proto3" json:"probe_interval,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Intensity) Reset() {
|
||||||
|
*x = Intensity{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Intensity) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Intensity) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Intensity) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[3]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Intensity.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Intensity) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_observatory_config_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Intensity) GetProbeInterval() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.ProbeInterval
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
// @Document The selectors for outbound under observation
|
||||||
|
SubjectSelector []string `protobuf:"bytes,2,rep,name=subject_selector,json=subjectSelector,proto3" json:"subject_selector,omitempty"`
|
||||||
|
ProbeUrl string `protobuf:"bytes,3,opt,name=probe_url,json=probeUrl,proto3" json:"probe_url,omitempty"`
|
||||||
|
ProbeInterval int64 `protobuf:"varint,4,opt,name=probe_interval,json=probeInterval,proto3" json:"probe_interval,omitempty"`
|
||||||
|
EnableConcurrency bool `protobuf:"varint,5,opt,name=enable_concurrency,json=enableConcurrency,proto3" json:"enable_concurrency,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) Reset() {
|
||||||
|
*x = Config{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_observatory_config_proto_msgTypes[4]
|
||||||
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_observatory_config_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetSubjectSelector() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.SubjectSelector
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetProbeUrl() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.ProbeUrl
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetProbeInterval() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.ProbeInterval
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetEnableConcurrency() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.EnableConcurrency
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_app_observatory_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
var file_app_observatory_config_proto_rawDesc = []byte{
|
||||||
|
0x0a, 0x1c, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
|
||||||
|
0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19,
|
||||||
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62,
|
||||||
|
0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x56, 0x0a, 0x11, 0x4f, 0x62, 0x73,
|
||||||
|
0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x41,
|
||||||
|
0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29,
|
||||||
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f,
|
||||||
|
0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
||||||
|
0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
|
||||||
|
0x73, 0x22, 0xd5, 0x01, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74,
|
||||||
|
0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65,
|
||||||
|
0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79,
|
||||||
|
0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x72,
|
||||||
|
0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x61, 0x73,
|
||||||
|
0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c,
|
||||||
|
0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x04, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12,
|
||||||
|
0x24, 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x5f, 0x74, 0x69, 0x6d,
|
||||||
|
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x65, 0x65,
|
||||||
|
0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x74, 0x72,
|
||||||
|
0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x6c, 0x61,
|
||||||
|
0x73, 0x74, 0x54, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x65, 0x0a, 0x0b, 0x50, 0x72, 0x6f,
|
||||||
|
0x62, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x76,
|
||||||
|
0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x14,
|
||||||
|
0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64,
|
||||||
|
0x65, 0x6c, 0x61, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72,
|
||||||
|
0x6f, 0x72, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
|
0x0f, 0x6c, 0x61, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e,
|
||||||
|
0x22, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x12, 0x25, 0x0a,
|
||||||
|
0x0e, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18,
|
||||||
|
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6e, 0x74, 0x65,
|
||||||
|
0x72, 0x76, 0x61, 0x6c, 0x22, 0xa6, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||||
|
0x29, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
|
||||||
|
0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a, 0x65,
|
||||||
|
0x63, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72,
|
||||||
|
0x6f, 0x62, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70,
|
||||||
|
0x72, 0x6f, 0x62, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x62, 0x65,
|
||||||
|
0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
|
||||||
|
0x0d, 0x70, 0x72, 0x6f, 0x62, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2d,
|
||||||
|
0x0a, 0x12, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72,
|
||||||
|
0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x11, 0x65, 0x6e, 0x61, 0x62,
|
||||||
|
0x6c, 0x65, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x5e, 0x0a,
|
||||||
|
0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62,
|
||||||
|
0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, 0x74,
|
||||||
|
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72,
|
||||||
|
0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0xaa, 0x02, 0x14, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
|
||||||
|
0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x62, 0x06, 0x70,
|
||||||
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_app_observatory_config_proto_rawDescOnce sync.Once
|
||||||
|
file_app_observatory_config_proto_rawDescData = file_app_observatory_config_proto_rawDesc
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_app_observatory_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_app_observatory_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_app_observatory_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_observatory_config_proto_rawDescData)
|
||||||
|
})
|
||||||
|
return file_app_observatory_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_app_observatory_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
|
var file_app_observatory_config_proto_goTypes = []interface{}{
|
||||||
|
(*ObservationResult)(nil), // 0: xray.core.app.observatory.ObservationResult
|
||||||
|
(*OutboundStatus)(nil), // 1: xray.core.app.observatory.OutboundStatus
|
||||||
|
(*ProbeResult)(nil), // 2: xray.core.app.observatory.ProbeResult
|
||||||
|
(*Intensity)(nil), // 3: xray.core.app.observatory.Intensity
|
||||||
|
(*Config)(nil), // 4: xray.core.app.observatory.Config
|
||||||
|
}
|
||||||
|
var file_app_observatory_config_proto_depIdxs = []int32{
|
||||||
|
1, // 0: xray.core.app.observatory.ObservationResult.status:type_name -> xray.core.app.observatory.OutboundStatus
|
||||||
|
1, // [1:1] is the sub-list for method output_type
|
||||||
|
1, // [1:1] is the sub-list for method input_type
|
||||||
|
1, // [1:1] is the sub-list for extension type_name
|
||||||
|
1, // [1:1] is the sub-list for extension extendee
|
||||||
|
0, // [0:1] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_app_observatory_config_proto_init() }
|
||||||
|
func file_app_observatory_config_proto_init() {
|
||||||
|
if File_app_observatory_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !protoimpl.UnsafeEnabled {
|
||||||
|
file_app_observatory_config_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ObservationResult); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_app_observatory_config_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*OutboundStatus); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_app_observatory_config_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*ProbeResult); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_app_observatory_config_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Intensity); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_app_observatory_config_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*Config); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: file_app_observatory_config_proto_rawDesc,
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 5,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_app_observatory_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_app_observatory_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_app_observatory_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_app_observatory_config_proto = out.File
|
||||||
|
file_app_observatory_config_proto_rawDesc = nil
|
||||||
|
file_app_observatory_config_proto_goTypes = nil
|
||||||
|
file_app_observatory_config_proto_depIdxs = nil
|
||||||
|
}
|
73
app/observatory/config.proto
Normal file
73
app/observatory/config.proto
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.core.app.observatory;
|
||||||
|
option csharp_namespace = "Xray.App.Observatory";
|
||||||
|
option go_package = "github.com/xtls/xray-core/app/observatory";
|
||||||
|
option java_package = "com.xray.app.observatory";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message ObservationResult {
|
||||||
|
repeated OutboundStatus status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message OutboundStatus{
|
||||||
|
/* @Document Whether this outbound is usable
|
||||||
|
@Restriction ReadOnlyForUser
|
||||||
|
*/
|
||||||
|
bool alive = 1;
|
||||||
|
/* @Document The time for probe request to finish.
|
||||||
|
@Type time.ms
|
||||||
|
@Restriction ReadOnlyForUser
|
||||||
|
*/
|
||||||
|
int64 delay = 2;
|
||||||
|
/* @Document The last error caused this outbound failed to relay probe request
|
||||||
|
@Restriction NotMachineReadable
|
||||||
|
*/
|
||||||
|
string last_error_reason = 3;
|
||||||
|
/* @Document The outbound tag for this Server
|
||||||
|
@Type id.outboundTag
|
||||||
|
*/
|
||||||
|
string outbound_tag = 4;
|
||||||
|
/* @Document The time this outbound is known to be alive
|
||||||
|
@Type id.outboundTag
|
||||||
|
*/
|
||||||
|
int64 last_seen_time = 5;
|
||||||
|
/* @Document The time this outbound is tried
|
||||||
|
@Type id.outboundTag
|
||||||
|
*/
|
||||||
|
int64 last_try_time = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ProbeResult{
|
||||||
|
/* @Document Whether this outbound is usable
|
||||||
|
@Restriction ReadOnlyForUser
|
||||||
|
*/
|
||||||
|
bool alive = 1;
|
||||||
|
/* @Document The time for probe request to finish.
|
||||||
|
@Type time.ms
|
||||||
|
@Restriction ReadOnlyForUser
|
||||||
|
*/
|
||||||
|
int64 delay = 2;
|
||||||
|
/* @Document The error caused this outbound failed to relay probe request
|
||||||
|
@Restriction NotMachineReadable
|
||||||
|
*/
|
||||||
|
string last_error_reason = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Intensity{
|
||||||
|
/* @Document The time interval for a probe request in ms.
|
||||||
|
@Type time.ms
|
||||||
|
*/
|
||||||
|
uint32 probe_interval = 1;
|
||||||
|
}
|
||||||
|
message Config {
|
||||||
|
/* @Document The selectors for outbound under observation
|
||||||
|
*/
|
||||||
|
repeated string subject_selector = 2;
|
||||||
|
|
||||||
|
string probe_url = 3;
|
||||||
|
|
||||||
|
int64 probe_interval = 4;
|
||||||
|
|
||||||
|
bool enable_concurrency = 5;
|
||||||
|
}
|
9
app/observatory/errors.generated.go
Normal file
9
app/observatory/errors.generated.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
package observatory
|
||||||
|
|
||||||
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
|
type errPathObjHolder struct{}
|
||||||
|
|
||||||
|
func newError(values ...interface{}) *errors.Error {
|
||||||
|
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||||
|
}
|
26
app/observatory/explainErrors.go
Normal file
26
app/observatory/explainErrors.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package observatory
|
||||||
|
|
||||||
|
import "github.com/xtls/xray-core/common/errors"
|
||||||
|
|
||||||
|
type errorCollector struct {
|
||||||
|
errors *errors.Error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *errorCollector) SubmitError(err error) {
|
||||||
|
if e.errors == nil {
|
||||||
|
e.errors = newError("underlying connection error").Base(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.errors = e.errors.Base(newError("underlying connection error").Base(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
func newErrorCollector() *errorCollector {
|
||||||
|
return &errorCollector{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *errorCollector) UnderlyingError() error {
|
||||||
|
if e.errors == nil {
|
||||||
|
return newError("failed to produce report")
|
||||||
|
}
|
||||||
|
return e.errors
|
||||||
|
}
|
3
app/observatory/observatory.go
Normal file
3
app/observatory/observatory.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package observatory
|
||||||
|
|
||||||
|
//go:generate go run github.com/xtls/xray-core/common/errors/errorgen
|
238
app/observatory/observer.go
Normal file
238
app/observatory/observer.go
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
package observatory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
v2net "github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
|
"github.com/xtls/xray-core/common/task"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/extension"
|
||||||
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/tagged"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Observer struct {
|
||||||
|
config *Config
|
||||||
|
ctx context.Context
|
||||||
|
|
||||||
|
statusLock sync.Mutex
|
||||||
|
status []*OutboundStatus
|
||||||
|
|
||||||
|
finished *done.Instance
|
||||||
|
|
||||||
|
ohm outbound.Manager
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) {
|
||||||
|
return &ObservationResult{Status: o.status}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) Type() interface{} {
|
||||||
|
return extension.ObservatoryType()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) Start() error {
|
||||||
|
if o.config != nil && len(o.config.SubjectSelector) != 0 {
|
||||||
|
o.finished = done.New()
|
||||||
|
go o.background()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) Close() error {
|
||||||
|
if o.finished != nil {
|
||||||
|
return o.finished.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) background() {
|
||||||
|
for !o.finished.Done() {
|
||||||
|
hs, ok := o.ohm.(outbound.HandlerSelector)
|
||||||
|
if !ok {
|
||||||
|
newError("outbound.Manager is not a HandlerSelector").WriteToLog()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
outbounds := hs.Select(o.config.SubjectSelector)
|
||||||
|
|
||||||
|
o.updateStatus(outbounds)
|
||||||
|
|
||||||
|
sleepTime := time.Second * 10
|
||||||
|
if o.config.ProbeInterval != 0 {
|
||||||
|
sleepTime = time.Duration(o.config.ProbeInterval)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !o.config.EnableConcurrency {
|
||||||
|
sort.Strings(outbounds)
|
||||||
|
for _, v := range outbounds {
|
||||||
|
result := o.probe(v)
|
||||||
|
o.updateStatusForResult(v, &result)
|
||||||
|
if o.finished.Done() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time.Sleep(sleepTime)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := make(chan struct{}, len(outbounds))
|
||||||
|
|
||||||
|
for _, v := range outbounds {
|
||||||
|
go func(v string) {
|
||||||
|
result := o.probe(v)
|
||||||
|
o.updateStatusForResult(v, &result)
|
||||||
|
ch <- struct{}{}
|
||||||
|
}(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
for range outbounds {
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
case <-o.finished.Wait():
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time.Sleep(sleepTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) updateStatus(outbounds []string) {
|
||||||
|
o.statusLock.Lock()
|
||||||
|
defer o.statusLock.Unlock()
|
||||||
|
// TODO should remove old inbound that is removed
|
||||||
|
_ = outbounds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) probe(outbound string) ProbeResult {
|
||||||
|
errorCollectorForRequest := newErrorCollector()
|
||||||
|
|
||||||
|
httpTransport := http.Transport{
|
||||||
|
Proxy: func(*http.Request) (*url.URL, error) {
|
||||||
|
return nil, nil
|
||||||
|
},
|
||||||
|
DialContext: func(ctx context.Context, network string, addr string) (net.Conn, error) {
|
||||||
|
var connection net.Conn
|
||||||
|
taskErr := task.Run(ctx, func() error {
|
||||||
|
// MUST use Xray's built in context system
|
||||||
|
dest, err := v2net.ParseDestination(network + ":" + addr)
|
||||||
|
if err != nil {
|
||||||
|
return newError("cannot understand address").Base(err)
|
||||||
|
}
|
||||||
|
trackedCtx := session.TrackedConnectionError(o.ctx, errorCollectorForRequest)
|
||||||
|
conn, err := tagged.Dialer(trackedCtx, dest, outbound)
|
||||||
|
if err != nil {
|
||||||
|
return newError("cannot dial remote address ", dest).Base(err)
|
||||||
|
}
|
||||||
|
connection = conn
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if taskErr != nil {
|
||||||
|
return nil, newError("cannot finish connection").Base(taskErr)
|
||||||
|
}
|
||||||
|
return connection, nil
|
||||||
|
},
|
||||||
|
TLSHandshakeTimeout: time.Second * 5,
|
||||||
|
}
|
||||||
|
httpClient := &http.Client{
|
||||||
|
Transport: &httpTransport,
|
||||||
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
return http.ErrUseLastResponse
|
||||||
|
},
|
||||||
|
Jar: nil,
|
||||||
|
Timeout: time.Second * 5,
|
||||||
|
}
|
||||||
|
var GETTime time.Duration
|
||||||
|
err := task.Run(o.ctx, func() error {
|
||||||
|
startTime := time.Now()
|
||||||
|
probeURL := "https://www.google.com/generate_204"
|
||||||
|
if o.config.ProbeUrl != "" {
|
||||||
|
probeURL = o.config.ProbeUrl
|
||||||
|
}
|
||||||
|
response, err := httpClient.Get(probeURL)
|
||||||
|
if err != nil {
|
||||||
|
return newError("outbound failed to relay connection").Base(err)
|
||||||
|
}
|
||||||
|
if response.Body != nil {
|
||||||
|
response.Body.Close()
|
||||||
|
}
|
||||||
|
endTime := time.Now()
|
||||||
|
GETTime = endTime.Sub(startTime)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
fullerr := newError("underlying connection failed").Base(errorCollectorForRequest.UnderlyingError())
|
||||||
|
fullerr = newError("with outbound handler report").Base(fullerr)
|
||||||
|
fullerr = newError("GET request failed:", err).Base(fullerr)
|
||||||
|
fullerr = newError("the outbound ", outbound, " is dead:").Base(fullerr)
|
||||||
|
fullerr = fullerr.AtInfo()
|
||||||
|
fullerr.WriteToLog()
|
||||||
|
return ProbeResult{Alive: false, LastErrorReason: fullerr.Error()}
|
||||||
|
}
|
||||||
|
newError("the outbound ", outbound, " is alive:", GETTime.Seconds()).AtInfo().WriteToLog()
|
||||||
|
return ProbeResult{Alive: true, Delay: GETTime.Milliseconds()}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) updateStatusForResult(outbound string, result *ProbeResult) {
|
||||||
|
o.statusLock.Lock()
|
||||||
|
defer o.statusLock.Unlock()
|
||||||
|
var status *OutboundStatus
|
||||||
|
if location := o.findStatusLocationLockHolderOnly(outbound); location != -1 {
|
||||||
|
status = o.status[location]
|
||||||
|
} else {
|
||||||
|
status = &OutboundStatus{}
|
||||||
|
o.status = append(o.status, status)
|
||||||
|
}
|
||||||
|
|
||||||
|
status.LastTryTime = time.Now().Unix()
|
||||||
|
status.OutboundTag = outbound
|
||||||
|
status.Alive = result.Alive
|
||||||
|
if result.Alive {
|
||||||
|
status.Delay = result.Delay
|
||||||
|
status.LastSeenTime = status.LastTryTime
|
||||||
|
status.LastErrorReason = ""
|
||||||
|
} else {
|
||||||
|
status.LastErrorReason = result.LastErrorReason
|
||||||
|
status.Delay = 99999999
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *Observer) findStatusLocationLockHolderOnly(outbound string) int {
|
||||||
|
for i, v := range o.status {
|
||||||
|
if v.OutboundTag == outbound {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, config *Config) (*Observer, error) {
|
||||||
|
var outboundManager outbound.Manager
|
||||||
|
err := core.RequireFeatures(ctx, func(om outbound.Manager) {
|
||||||
|
outboundManager = om
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("Cannot get depended features").Base(err)
|
||||||
|
}
|
||||||
|
return &Observer{
|
||||||
|
config: config,
|
||||||
|
ctx: ctx,
|
||||||
|
ohm: outboundManager,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
|
return New(ctx, config.(*Config))
|
||||||
|
}))
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/policy/config.proto
|
// source: app/policy/config.proto
|
||||||
|
|
||||||
package policy
|
package policy
|
||||||
|
@@ -3,13 +3,12 @@ package command
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/inbound"
|
"github.com/xtls/xray-core/features/inbound"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InboundOperation is the interface for operations that applies to inbound handlers.
|
// InboundOperation is the interface for operations that applies to inbound handlers.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/proxyman/command/command.proto
|
// source: app/proxyman/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
|
// - protoc v4.23.1
|
||||||
|
// source: app/proxyman/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
@@ -14,6 +18,15 @@ import (
|
|||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
|
const (
|
||||||
|
HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound"
|
||||||
|
HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound"
|
||||||
|
HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound"
|
||||||
|
HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound"
|
||||||
|
HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound"
|
||||||
|
HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound"
|
||||||
|
)
|
||||||
|
|
||||||
// HandlerServiceClient is the client API for HandlerService service.
|
// HandlerServiceClient is the client API for HandlerService service.
|
||||||
//
|
//
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
@@ -36,7 +49,7 @@ func NewHandlerServiceClient(cc grpc.ClientConnInterface) HandlerServiceClient {
|
|||||||
|
|
||||||
func (c *handlerServiceClient) AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error) {
|
func (c *handlerServiceClient) AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error) {
|
||||||
out := new(AddInboundResponse)
|
out := new(AddInboundResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.proxyman.command.HandlerService/AddInbound", in, out, opts...)
|
err := c.cc.Invoke(ctx, HandlerService_AddInbound_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -45,7 +58,7 @@ func (c *handlerServiceClient) AddInbound(ctx context.Context, in *AddInboundReq
|
|||||||
|
|
||||||
func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error) {
|
func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error) {
|
||||||
out := new(RemoveInboundResponse)
|
out := new(RemoveInboundResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.proxyman.command.HandlerService/RemoveInbound", in, out, opts...)
|
err := c.cc.Invoke(ctx, HandlerService_RemoveInbound_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -54,7 +67,7 @@ func (c *handlerServiceClient) RemoveInbound(ctx context.Context, in *RemoveInbo
|
|||||||
|
|
||||||
func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error) {
|
func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error) {
|
||||||
out := new(AlterInboundResponse)
|
out := new(AlterInboundResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.proxyman.command.HandlerService/AlterInbound", in, out, opts...)
|
err := c.cc.Invoke(ctx, HandlerService_AlterInbound_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -63,7 +76,7 @@ func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboun
|
|||||||
|
|
||||||
func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error) {
|
func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error) {
|
||||||
out := new(AddOutboundResponse)
|
out := new(AddOutboundResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.proxyman.command.HandlerService/AddOutbound", in, out, opts...)
|
err := c.cc.Invoke(ctx, HandlerService_AddOutbound_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -72,7 +85,7 @@ func (c *handlerServiceClient) AddOutbound(ctx context.Context, in *AddOutboundR
|
|||||||
|
|
||||||
func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error) {
|
func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error) {
|
||||||
out := new(RemoveOutboundResponse)
|
out := new(RemoveOutboundResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.proxyman.command.HandlerService/RemoveOutbound", in, out, opts...)
|
err := c.cc.Invoke(ctx, HandlerService_RemoveOutbound_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -81,7 +94,7 @@ func (c *handlerServiceClient) RemoveOutbound(ctx context.Context, in *RemoveOut
|
|||||||
|
|
||||||
func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error) {
|
func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error) {
|
||||||
out := new(AlterOutboundResponse)
|
out := new(AlterOutboundResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.proxyman.command.HandlerService/AlterOutbound", in, out, opts...)
|
err := c.cc.Invoke(ctx, HandlerService_AlterOutbound_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -146,7 +159,7 @@ func _HandlerService_AddInbound_Handler(srv interface{}, ctx context.Context, de
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.proxyman.command.HandlerService/AddInbound",
|
FullMethod: HandlerService_AddInbound_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(HandlerServiceServer).AddInbound(ctx, req.(*AddInboundRequest))
|
return srv.(HandlerServiceServer).AddInbound(ctx, req.(*AddInboundRequest))
|
||||||
@@ -164,7 +177,7 @@ func _HandlerService_RemoveInbound_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.proxyman.command.HandlerService/RemoveInbound",
|
FullMethod: HandlerService_RemoveInbound_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(HandlerServiceServer).RemoveInbound(ctx, req.(*RemoveInboundRequest))
|
return srv.(HandlerServiceServer).RemoveInbound(ctx, req.(*RemoveInboundRequest))
|
||||||
@@ -182,7 +195,7 @@ func _HandlerService_AlterInbound_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.proxyman.command.HandlerService/AlterInbound",
|
FullMethod: HandlerService_AlterInbound_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(HandlerServiceServer).AlterInbound(ctx, req.(*AlterInboundRequest))
|
return srv.(HandlerServiceServer).AlterInbound(ctx, req.(*AlterInboundRequest))
|
||||||
@@ -200,7 +213,7 @@ func _HandlerService_AddOutbound_Handler(srv interface{}, ctx context.Context, d
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.proxyman.command.HandlerService/AddOutbound",
|
FullMethod: HandlerService_AddOutbound_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(HandlerServiceServer).AddOutbound(ctx, req.(*AddOutboundRequest))
|
return srv.(HandlerServiceServer).AddOutbound(ctx, req.(*AddOutboundRequest))
|
||||||
@@ -218,7 +231,7 @@ func _HandlerService_RemoveOutbound_Handler(srv interface{}, ctx context.Context
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.proxyman.command.HandlerService/RemoveOutbound",
|
FullMethod: HandlerService_RemoveOutbound_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(HandlerServiceServer).RemoveOutbound(ctx, req.(*RemoveOutboundRequest))
|
return srv.(HandlerServiceServer).RemoveOutbound(ctx, req.(*RemoveOutboundRequest))
|
||||||
@@ -236,7 +249,7 @@ func _HandlerService_AlterOutbound_Handler(srv interface{}, ctx context.Context,
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.proxyman.command.HandlerService/AlterOutbound",
|
FullMethod: HandlerService_AlterOutbound_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(HandlerServiceServer).AlterOutbound(ctx, req.(*AlterOutboundRequest))
|
return srv.(HandlerServiceServer).AlterOutbound(ctx, req.(*AlterOutboundRequest))
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/proxyman/config.proto
|
// source: app/proxyman/config.proto
|
||||||
|
|
||||||
package proxyman
|
package proxyman
|
||||||
@@ -238,8 +238,10 @@ type SniffingConfig struct {
|
|||||||
DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
DestinationOverride []string `protobuf:"bytes,2,rep,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
||||||
DomainsExcluded []string `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"`
|
DomainsExcluded []string `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"`
|
||||||
// Whether should only try to sniff metadata without waiting for client input.
|
// Whether should only try to sniff metadata without waiting for client input.
|
||||||
// Can be used to support SMTP like protocol where server send the first message.
|
// Can be used to support SMTP like protocol where server send the first
|
||||||
|
// message.
|
||||||
MetadataOnly bool `protobuf:"varint,4,opt,name=metadata_only,json=metadataOnly,proto3" json:"metadata_only,omitempty"`
|
MetadataOnly bool `protobuf:"varint,4,opt,name=metadata_only,json=metadataOnly,proto3" json:"metadata_only,omitempty"`
|
||||||
|
RouteOnly bool `protobuf:"varint,5,opt,name=route_only,json=routeOnly,proto3" json:"route_only,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) Reset() {
|
func (x *SniffingConfig) Reset() {
|
||||||
@@ -302,13 +304,20 @@ func (x *SniffingConfig) GetMetadataOnly() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *SniffingConfig) GetRouteOnly() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.RouteOnly
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type ReceiverConfig struct {
|
type ReceiverConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// PortRange specifies the ports which the Receiver should listen on.
|
// PortList specifies the ports which the Receiver should listen on.
|
||||||
PortRange *net.PortRange `protobuf:"bytes,1,opt,name=port_range,json=portRange,proto3" json:"port_range,omitempty"`
|
PortList *net.PortList `protobuf:"bytes,1,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
||||||
// Listen specifies the IP address that the Receiver should listen on.
|
// Listen specifies the IP address that the Receiver should listen on.
|
||||||
Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
||||||
AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"`
|
AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"`
|
||||||
@@ -317,7 +326,7 @@ type ReceiverConfig struct {
|
|||||||
// Override domains for the given protocol.
|
// Override domains for the given protocol.
|
||||||
// Deprecated. Use sniffing_settings.
|
// Deprecated. Use sniffing_settings.
|
||||||
//
|
//
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/proxyman/config.proto.
|
||||||
DomainOverride []KnownProtocols `protobuf:"varint,7,rep,packed,name=domain_override,json=domainOverride,proto3,enum=xray.app.proxyman.KnownProtocols" json:"domain_override,omitempty"`
|
DomainOverride []KnownProtocols `protobuf:"varint,7,rep,packed,name=domain_override,json=domainOverride,proto3,enum=xray.app.proxyman.KnownProtocols" json:"domain_override,omitempty"`
|
||||||
SniffingSettings *SniffingConfig `protobuf:"bytes,8,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
|
SniffingSettings *SniffingConfig `protobuf:"bytes,8,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
|
||||||
}
|
}
|
||||||
@@ -354,9 +363,9 @@ func (*ReceiverConfig) Descriptor() ([]byte, []int) {
|
|||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{3}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReceiverConfig) GetPortRange() *net.PortRange {
|
func (x *ReceiverConfig) GetPortList() *net.PortList {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.PortRange
|
return x.PortList
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -389,7 +398,7 @@ func (x *ReceiverConfig) GetReceiveOriginalDestination() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/proxyman/config.proto.
|
||||||
func (x *ReceiverConfig) GetDomainOverride() []KnownProtocols {
|
func (x *ReceiverConfig) GetDomainOverride() []KnownProtocols {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.DomainOverride
|
return x.DomainOverride
|
||||||
@@ -585,7 +594,11 @@ type MultiplexingConfig struct {
|
|||||||
// Whether or not Mux is enabled.
|
// Whether or not Mux is enabled.
|
||||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||||
// Max number of concurrent connections that one Mux connection can handle.
|
// Max number of concurrent connections that one Mux connection can handle.
|
||||||
Concurrency uint32 `protobuf:"varint,2,opt,name=concurrency,proto3" json:"concurrency,omitempty"`
|
Concurrency int32 `protobuf:"varint,2,opt,name=concurrency,proto3" json:"concurrency,omitempty"`
|
||||||
|
// Transport XUDP in another Mux.
|
||||||
|
XudpConcurrency int32 `protobuf:"varint,3,opt,name=xudpConcurrency,proto3" json:"xudpConcurrency,omitempty"`
|
||||||
|
// "reject" (default), "allow" or "skip".
|
||||||
|
XudpProxyUDP443 string `protobuf:"bytes,4,opt,name=xudpProxyUDP443,proto3" json:"xudpProxyUDP443,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *MultiplexingConfig) Reset() {
|
func (x *MultiplexingConfig) Reset() {
|
||||||
@@ -627,13 +640,27 @@ func (x *MultiplexingConfig) GetEnabled() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *MultiplexingConfig) GetConcurrency() uint32 {
|
func (x *MultiplexingConfig) GetConcurrency() int32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Concurrency
|
return x.Concurrency
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *MultiplexingConfig) GetXudpConcurrency() int32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.XudpConcurrency
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *MultiplexingConfig) GetXudpProxyUDP443() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.XudpProxyUDP443
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type AllocationStrategy_AllocationStrategyConcurrency struct {
|
type AllocationStrategy_AllocationStrategyConcurrency struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -769,7 +796,7 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
|||||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
|
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
|
||||||
0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52,
|
0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52,
|
||||||
0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72,
|
0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72,
|
||||||
0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0xad, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69,
|
0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69,
|
||||||
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
||||||
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||||
0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
|
0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
|
||||||
@@ -780,86 +807,93 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
|||||||
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64,
|
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64,
|
||||||
0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c,
|
0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c,
|
||||||
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
||||||
0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x90, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76,
|
0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f,
|
||||||
0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74,
|
0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||||
0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78,
|
0x4f, 0x6e, 0x6c, 0x79, 0x22, 0x8d, 0x04, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50,
|
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f,
|
||||||
0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61,
|
0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x6e, 0x67, 0x65, 0x12, 0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20,
|
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12,
|
||||||
0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f,
|
0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
|
||||||
0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18,
|
0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69,
|
||||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
|
0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c,
|
0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
|
||||||
0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4e, 0x0a, 0x0f,
|
||||||
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
||||||
0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
||||||
0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
|
||||||
0x12, 0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67,
|
|
||||||
0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
|
||||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f,
|
|
||||||
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
|
|
||||||
0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65,
|
|
||||||
0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e,
|
|
||||||
0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02,
|
|
||||||
0x18, 0x01, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
|
|
||||||
0x64, 0x65, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73,
|
|
||||||
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
|
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
|
||||||
0x6e, 0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
|
||||||
0x52, 0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
|
||||||
0x67, 0x73, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62,
|
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 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, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f,
|
|
||||||
0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
|
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72,
|
|
||||||
0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
|
||||||
0x52, 0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
|
||||||
0x67, 0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74,
|
|
||||||
0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e,
|
|
||||||
0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72,
|
|
||||||
0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f,
|
|
||||||
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02,
|
|
||||||
0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d,
|
|
||||||
0x0a, 0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50,
|
|
||||||
0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a,
|
|
||||||
0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 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, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73,
|
|
||||||
0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a,
|
|
||||||
0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
|
||||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 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,
|
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
||||||
0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f,
|
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74,
|
||||||
0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75,
|
0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c,
|
||||||
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
|
||||||
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69,
|
0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69,
|
||||||
0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d,
|
0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e,
|
||||||
0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
||||||
0x22, 0x50, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67,
|
0x65, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4b, 0x6e, 0x6f, 0x77,
|
||||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
|
0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0e,
|
||||||
0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18,
|
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x4e,
|
||||||
0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x63, 0x79, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
0x6e, 0x67, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x63, 0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e,
|
||||||
0x0a, 0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
|
0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04,
|
||||||
0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
||||||
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70,
|
0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a,
|
||||||
0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61,
|
0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12,
|
||||||
0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06,
|
0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74,
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e,
|
||||||
|
0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65,
|
||||||
|
0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47,
|
||||||
|
0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
|
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
||||||
|
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65,
|
||||||
|
0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53,
|
||||||
|
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
||||||
|
0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a, 0x0c, 0x53, 0x65,
|
||||||
|
0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69,
|
||||||
|
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||||
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f,
|
||||||
|
0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72,
|
||||||
|
0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x25, 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, 0x53, 0x74, 0x72,
|
||||||
|
0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61,
|
||||||
|
0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f,
|
||||||
|
0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
|
0x0b, 0x32, 0x24, 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, 0x50, 0x72, 0x6f, 0x78,
|
||||||
|
0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65,
|
||||||
|
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
|
||||||
|
0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01,
|
||||||
|
0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
||||||
|
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78,
|
||||||
|
0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69,
|
||||||
|
0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xa4, 0x01, 0x0a,
|
||||||
|
0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
||||||
|
0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01,
|
||||||
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a,
|
||||||
|
0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01,
|
||||||
|
0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12,
|
||||||
|
0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
||||||
|
0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f,
|
||||||
|
0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64,
|
||||||
|
0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01,
|
||||||
|
0x28, 0x09, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50,
|
||||||
|
0x34, 0x34, 0x33, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74,
|
||||||
|
0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12,
|
||||||
|
0x07, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e,
|
||||||
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||||
|
0x6e, 0x50, 0x01, 0x5a, 0x26, 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, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72,
|
||||||
|
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62,
|
||||||
|
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -889,7 +923,7 @@ var file_app_proxyman_config_proto_goTypes = []interface{}{
|
|||||||
(*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig
|
(*MultiplexingConfig)(nil), // 9: xray.app.proxyman.MultiplexingConfig
|
||||||
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
||||||
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 11: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
||||||
(*net.PortRange)(nil), // 12: xray.common.net.PortRange
|
(*net.PortList)(nil), // 12: xray.common.net.PortList
|
||||||
(*net.IPOrDomain)(nil), // 13: xray.common.net.IPOrDomain
|
(*net.IPOrDomain)(nil), // 13: xray.common.net.IPOrDomain
|
||||||
(*internet.StreamConfig)(nil), // 14: xray.transport.internet.StreamConfig
|
(*internet.StreamConfig)(nil), // 14: xray.transport.internet.StreamConfig
|
||||||
(*serial.TypedMessage)(nil), // 15: xray.common.serial.TypedMessage
|
(*serial.TypedMessage)(nil), // 15: xray.common.serial.TypedMessage
|
||||||
@@ -899,7 +933,7 @@ var file_app_proxyman_config_proto_depIdxs = []int32{
|
|||||||
1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
1, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
||||||
10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
10, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
||||||
11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
11, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
||||||
12, // 3: xray.app.proxyman.ReceiverConfig.port_range:type_name -> xray.common.net.PortRange
|
12, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
||||||
13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
13, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
||||||
3, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
|
3, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
|
||||||
14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
14, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
|
@@ -27,17 +27,13 @@ message AllocationStrategy {
|
|||||||
|
|
||||||
Type type = 1;
|
Type type = 1;
|
||||||
|
|
||||||
message AllocationStrategyConcurrency {
|
message AllocationStrategyConcurrency { uint32 value = 1; }
|
||||||
uint32 value = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of handlers (ports) running in parallel.
|
// Number of handlers (ports) running in parallel.
|
||||||
// Default value is 3 if unset.
|
// Default value is 3 if unset.
|
||||||
AllocationStrategyConcurrency concurrency = 2;
|
AllocationStrategyConcurrency concurrency = 2;
|
||||||
|
|
||||||
message AllocationStrategyRefresh {
|
message AllocationStrategyRefresh { uint32 value = 1; }
|
||||||
uint32 value = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Number of minutes before a handler is regenerated.
|
// Number of minutes before a handler is regenerated.
|
||||||
// Default value is 5 if unset.
|
// Default value is 5 if unset.
|
||||||
@@ -59,13 +55,16 @@ message SniffingConfig {
|
|||||||
repeated string domains_excluded = 3;
|
repeated string domains_excluded = 3;
|
||||||
|
|
||||||
// Whether should only try to sniff metadata without waiting for client input.
|
// Whether should only try to sniff metadata without waiting for client input.
|
||||||
// Can be used to support SMTP like protocol where server send the first message.
|
// Can be used to support SMTP like protocol where server send the first
|
||||||
|
// message.
|
||||||
bool metadata_only = 4;
|
bool metadata_only = 4;
|
||||||
|
|
||||||
|
bool route_only = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ReceiverConfig {
|
message ReceiverConfig {
|
||||||
// PortRange specifies the ports which the Receiver should listen on.
|
// PortList specifies the ports which the Receiver should listen on.
|
||||||
xray.common.net.PortRange port_range = 1;
|
xray.common.net.PortList port_list = 1;
|
||||||
// Listen specifies the IP address that the Receiver should listen on.
|
// Listen specifies the IP address that the Receiver should listen on.
|
||||||
xray.common.net.IPOrDomain listen = 2;
|
xray.common.net.IPOrDomain listen = 2;
|
||||||
AllocationStrategy allocation_strategy = 3;
|
AllocationStrategy allocation_strategy = 3;
|
||||||
@@ -74,7 +73,7 @@ message ReceiverConfig {
|
|||||||
reserved 6;
|
reserved 6;
|
||||||
// Override domains for the given protocol.
|
// Override domains for the given protocol.
|
||||||
// Deprecated. Use sniffing_settings.
|
// Deprecated. Use sniffing_settings.
|
||||||
repeated KnownProtocols domain_override = 7 [deprecated = true];
|
repeated KnownProtocols domain_override = 7 [ deprecated = true ];
|
||||||
SniffingConfig sniffing_settings = 8;
|
SniffingConfig sniffing_settings = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,5 +97,9 @@ message MultiplexingConfig {
|
|||||||
// Whether or not Mux is enabled.
|
// Whether or not Mux is enabled.
|
||||||
bool enabled = 1;
|
bool enabled = 1;
|
||||||
// Max number of concurrent connections that one Mux connection can handle.
|
// Max number of concurrent connections that one Mux connection can handle.
|
||||||
uint32 concurrency = 2;
|
int32 concurrency = 2;
|
||||||
|
// Transport XUDP in another Mux.
|
||||||
|
int32 xudpConcurrency = 3;
|
||||||
|
// "reject" (default), "allow" or "skip".
|
||||||
|
string xudpProxyUDP443 = 4;
|
||||||
}
|
}
|
||||||
|
@@ -67,7 +67,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag)
|
uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag)
|
||||||
|
|
||||||
nl := p.Network()
|
nl := p.Network()
|
||||||
pr := receiverConfig.PortRange
|
pl := receiverConfig.PortList
|
||||||
address := receiverConfig.Listen.AsAddress()
|
address := receiverConfig.Listen.AsAddress()
|
||||||
if address == nil {
|
if address == nil {
|
||||||
address = net.AnyIP
|
address = net.AnyIP
|
||||||
@@ -87,7 +87,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
}
|
}
|
||||||
mss.SocketSettings.ReceiveOriginalDestAddress = true
|
mss.SocketSettings.ReceiveOriginalDestAddress = true
|
||||||
}
|
}
|
||||||
if pr == nil {
|
if pl == nil {
|
||||||
if net.HasNetwork(nl, net.Network_UNIX) {
|
if net.HasNetwork(nl, net.Network_UNIX) {
|
||||||
newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog()
|
newError("creating unix domain socket worker on ", address).AtDebug().WriteToLog()
|
||||||
|
|
||||||
@@ -105,41 +105,43 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
h.workers = append(h.workers, worker)
|
h.workers = append(h.workers, worker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pr != nil {
|
if pl != nil {
|
||||||
for port := pr.From; port <= pr.To; port++ {
|
for _, pr := range pl.Range {
|
||||||
if net.HasNetwork(nl, net.Network_TCP) {
|
for port := pr.From; port <= pr.To; port++ {
|
||||||
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
|
if net.HasNetwork(nl, net.Network_TCP) {
|
||||||
|
newError("creating stream worker on ", address, ":", port).AtDebug().WriteToLog()
|
||||||
|
|
||||||
worker := &tcpWorker{
|
worker := &tcpWorker{
|
||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
proxy: p,
|
proxy: p,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
}
|
||||||
|
h.workers = append(h.workers, worker)
|
||||||
}
|
}
|
||||||
h.workers = append(h.workers, worker)
|
|
||||||
}
|
|
||||||
|
|
||||||
if net.HasNetwork(nl, net.Network_UDP) {
|
if net.HasNetwork(nl, net.Network_UDP) {
|
||||||
worker := &udpWorker{
|
worker := &udpWorker{
|
||||||
tag: tag,
|
tag: tag,
|
||||||
proxy: p,
|
proxy: p,
|
||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
|
}
|
||||||
|
h.workers = append(h.workers, worker)
|
||||||
}
|
}
|
||||||
h.workers = append(h.workers, worker)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -69,15 +69,18 @@ func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *p
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) allocatePort() net.Port {
|
func (h *DynamicInboundHandler) allocatePort() net.Port {
|
||||||
from := int(h.receiverConfig.PortRange.From)
|
allPorts := []int32{}
|
||||||
delta := int(h.receiverConfig.PortRange.To) - from + 1
|
for _, pr := range h.receiverConfig.PortList.Range {
|
||||||
|
for i := pr.From; i <= pr.To; i++ {
|
||||||
|
allPorts = append(allPorts, int32(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
h.portMutex.Lock()
|
h.portMutex.Lock()
|
||||||
defer h.portMutex.Unlock()
|
defer h.portMutex.Unlock()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
r := dice.Roll(delta)
|
r := dice.Roll(len(allPorts))
|
||||||
port := net.Port(from + r)
|
port := net.Port(allPorts[r])
|
||||||
_, used := h.portsInUse[port]
|
_, used := h.portsInUse[port]
|
||||||
if !used {
|
if !used {
|
||||||
h.portsInUse[port] = true
|
h.portsInUse[port] = true
|
||||||
|
@@ -6,8 +6,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
@@ -20,6 +18,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tcp"
|
"github.com/xtls/xray-core/transport/internet/tcp"
|
||||||
"github.com/xtls/xray-core/transport/internet/udp"
|
"github.com/xtls/xray-core/transport/internet/udp"
|
||||||
"github.com/xtls/xray-core/transport/pipe"
|
"github.com/xtls/xray-core/transport/pipe"
|
||||||
@@ -101,6 +100,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
|||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||||
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
||||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
||||||
|
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
|
||||||
@@ -108,9 +108,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
|||||||
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
cancel()
|
cancel()
|
||||||
if err := conn.Close(); err != nil {
|
conn.Close()
|
||||||
newError("failed to close connection").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *tcpWorker) Proxy() proxy.Inbound {
|
func (w *tcpWorker) Proxy() proxy.Inbound {
|
||||||
@@ -160,6 +158,11 @@ type udpConn struct {
|
|||||||
done *done.Instance
|
done *done.Instance
|
||||||
uplink stats.Counter
|
uplink stats.Counter
|
||||||
downlink stats.Counter
|
downlink stats.Counter
|
||||||
|
inactive bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *udpConn) setInactive() {
|
||||||
|
c.inactive = true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConn) updateActivity() {
|
func (c *udpConn) updateActivity() {
|
||||||
@@ -320,13 +323,18 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
|||||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
||||||
|
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
|
if err := w.proxy.Process(ctx, net.Network_UDP, conn, w.dispatcher); err != nil {
|
||||||
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
newError("connection ends").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||||
}
|
}
|
||||||
conn.Close()
|
conn.Close()
|
||||||
w.removeConn(id)
|
// conn not removed by checker TODO may be lock worker here is better
|
||||||
|
if !conn.inactive {
|
||||||
|
conn.setInactive()
|
||||||
|
w.removeConn(id)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -354,8 +362,11 @@ func (w *udpWorker) clean() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for addr, conn := range w.activeConn {
|
for addr, conn := range w.activeConn {
|
||||||
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 300 {
|
if nowSec-atomic.LoadInt64(&conn.lastActivityTime) > 2*60 {
|
||||||
delete(w.activeConn, addr)
|
if !conn.inactive {
|
||||||
|
conn.setInactive()
|
||||||
|
delete(w.activeConn, addr)
|
||||||
|
}
|
||||||
conn.Close()
|
conn.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,6 +474,7 @@ func (w *dsWorker) callback(conn stat.Connection) {
|
|||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
||||||
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
||||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
||||||
|
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
|
||||||
|
@@ -2,8 +2,9 @@ package outbound
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
@@ -18,6 +19,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
"github.com/xtls/xray-core/transport/pipe"
|
"github.com/xtls/xray-core/transport/pipe"
|
||||||
)
|
)
|
||||||
@@ -55,11 +57,13 @@ type Handler struct {
|
|||||||
proxy proxy.Outbound
|
proxy proxy.Outbound
|
||||||
outboundManager outbound.Manager
|
outboundManager outbound.Manager
|
||||||
mux *mux.ClientManager
|
mux *mux.ClientManager
|
||||||
|
xudp *mux.ClientManager
|
||||||
|
udp443 string
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHandler create a new Handler based on the given configuration.
|
// NewHandler creates a new Handler based on the given configuration.
|
||||||
func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbound.Handler, error) {
|
func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbound.Handler, error) {
|
||||||
v := core.MustFromContext(ctx)
|
v := core.MustFromContext(ctx)
|
||||||
uplinkCounter, downlinkCounter := getStatCounter(v, config.Tag)
|
uplinkCounter, downlinkCounter := getStatCounter(v, config.Tag)
|
||||||
@@ -104,22 +108,50 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
|
|||||||
}
|
}
|
||||||
|
|
||||||
if h.senderSettings != nil && h.senderSettings.MultiplexSettings != nil {
|
if h.senderSettings != nil && h.senderSettings.MultiplexSettings != nil {
|
||||||
config := h.senderSettings.MultiplexSettings
|
if config := h.senderSettings.MultiplexSettings; config.Enabled {
|
||||||
if config.Concurrency < 1 || config.Concurrency > 1024 {
|
if config.Concurrency < 0 {
|
||||||
return nil, newError("invalid mux concurrency: ", config.Concurrency).AtWarning()
|
h.mux = &mux.ClientManager{Enabled: false}
|
||||||
}
|
}
|
||||||
h.mux = &mux.ClientManager{
|
if config.Concurrency == 0 {
|
||||||
Enabled: h.senderSettings.MultiplexSettings.Enabled,
|
config.Concurrency = 8 // same as before
|
||||||
Picker: &mux.IncrementalWorkerPicker{
|
}
|
||||||
Factory: &mux.DialingWorkerFactory{
|
if config.Concurrency > 0 {
|
||||||
Proxy: proxyHandler,
|
h.mux = &mux.ClientManager{
|
||||||
Dialer: h,
|
Enabled: true,
|
||||||
Strategy: mux.ClientStrategy{
|
Picker: &mux.IncrementalWorkerPicker{
|
||||||
MaxConcurrency: config.Concurrency,
|
Factory: &mux.DialingWorkerFactory{
|
||||||
MaxConnection: 128,
|
Proxy: proxyHandler,
|
||||||
|
Dialer: h,
|
||||||
|
Strategy: mux.ClientStrategy{
|
||||||
|
MaxConcurrency: uint32(config.Concurrency),
|
||||||
|
MaxConnection: 128,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
},
|
}
|
||||||
|
if config.XudpConcurrency < 0 {
|
||||||
|
h.xudp = &mux.ClientManager{Enabled: false}
|
||||||
|
}
|
||||||
|
if config.XudpConcurrency == 0 {
|
||||||
|
h.xudp = nil // same as before
|
||||||
|
}
|
||||||
|
if config.XudpConcurrency > 0 {
|
||||||
|
h.xudp = &mux.ClientManager{
|
||||||
|
Enabled: true,
|
||||||
|
Picker: &mux.IncrementalWorkerPicker{
|
||||||
|
Factory: &mux.DialingWorkerFactory{
|
||||||
|
Proxy: proxyHandler,
|
||||||
|
Dialer: h,
|
||||||
|
Strategy: mux.ClientStrategy{
|
||||||
|
MaxConcurrency: uint32(config.XudpConcurrency),
|
||||||
|
MaxConnection: 128,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h.udp443 = config.XudpProxyUDP443
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,21 +166,54 @@ func (h *Handler) Tag() string {
|
|||||||
|
|
||||||
// Dispatch implements proxy.Outbound.Dispatch.
|
// Dispatch implements proxy.Outbound.Dispatch.
|
||||||
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
||||||
if h.mux != nil && (h.mux.Enabled || session.MuxPreferedFromContext(ctx)) {
|
if h.mux != nil {
|
||||||
if err := h.mux.Dispatch(ctx, link); err != nil {
|
test := func(err error) {
|
||||||
newError("failed to process mux outbound traffic").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
if err != nil {
|
||||||
common.Interrupt(link.Writer)
|
err := newError("failed to process mux outbound traffic").Base(err)
|
||||||
|
session.SubmitOutboundErrorToOriginator(ctx, err)
|
||||||
|
err.WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
common.Interrupt(link.Writer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
outbound := session.OutboundFromContext(ctx)
|
||||||
if err := h.proxy.Process(ctx, link, h); err != nil {
|
if outbound.Target.Network == net.Network_UDP && outbound.Target.Port == 443 {
|
||||||
// Ensure outbound ray is properly closed.
|
switch h.udp443 {
|
||||||
newError("failed to process outbound traffic").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
case "reject":
|
||||||
common.Interrupt(link.Writer)
|
test(newError("XUDP rejected UDP/443 traffic").AtInfo())
|
||||||
} else {
|
return
|
||||||
common.Must(common.Close(link.Writer))
|
case "skip":
|
||||||
|
goto out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if h.xudp != nil && outbound.Target.Network == net.Network_UDP {
|
||||||
|
if !h.xudp.Enabled {
|
||||||
|
goto out
|
||||||
|
}
|
||||||
|
test(h.xudp.Dispatch(ctx, link))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if h.mux.Enabled {
|
||||||
|
test(h.mux.Dispatch(ctx, link))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
common.Interrupt(link.Reader)
|
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
|
err := h.proxy.Process(ctx, link, h)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrClosedPipe) || errors.Is(err, context.Canceled) {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
// Ensure outbound ray is properly closed.
|
||||||
|
err := newError("failed to process outbound traffic").Base(err)
|
||||||
|
session.SubmitOutboundErrorToOriginator(ctx, err)
|
||||||
|
err.WriteToLog(session.ExportIDToError(ctx))
|
||||||
|
common.Interrupt(link.Writer)
|
||||||
|
} else {
|
||||||
|
common.Close(link.Writer)
|
||||||
|
}
|
||||||
|
common.Interrupt(link.Reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address implements internet.Dialer.
|
// Address implements internet.Dialer.
|
||||||
@@ -199,6 +264,10 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
|
||||||
|
return conn, err
|
||||||
|
}
|
||||||
|
|
||||||
conn, err := internet.Dial(ctx, dest, h.streamSettings)
|
conn, err := internet.Dial(ctx, dest, h.streamSettings)
|
||||||
return h.getStatCouterConnection(conn), err
|
return h.getStatCouterConnection(conn), err
|
||||||
}
|
}
|
||||||
|
@@ -4,8 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/policy"
|
"github.com/xtls/xray-core/app/policy"
|
||||||
. "github.com/xtls/xray-core/app/proxyman/outbound"
|
. "github.com/xtls/xray-core/app/proxyman/outbound"
|
||||||
"github.com/xtls/xray-core/app/stats"
|
"github.com/xtls/xray-core/app/stats"
|
||||||
@@ -14,6 +12,7 @@ import (
|
|||||||
core "github.com/xtls/xray-core/core"
|
core "github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/proxy/freedom"
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInterfaces(t *testing.T) {
|
func TestInterfaces(t *testing.T) {
|
||||||
|
31
app/proxyman/outbound/uot.go
Normal file
31
app/proxyman/outbound/uot.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package outbound
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing/common/uot"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (h *Handler) getUoTConnection(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
||||||
|
if !dest.Address.Family().IsDomain() {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
var uotVersion int
|
||||||
|
if dest.Address.Domain() == uot.MagicAddress {
|
||||||
|
uotVersion = uot.Version
|
||||||
|
} else if dest.Address.Domain() == uot.LegacyMagicAddress {
|
||||||
|
uotVersion = uot.LegacyVersion
|
||||||
|
} else {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
packetConn, err := internet.ListenSystemPacket(ctx, &net.UDPAddr{IP: net.AnyIP.IP(), Port: 0}, h.streamSettings.SocketSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, newError("unable to listen socket").Base(err)
|
||||||
|
}
|
||||||
|
conn := uot.NewServerConn(packetConn, uotVersion)
|
||||||
|
return h.getStatCouterConnection(conn), nil
|
||||||
|
}
|
@@ -5,7 +5,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
@@ -147,7 +146,7 @@ func (w *BridgeWorker) Connections() uint32 {
|
|||||||
return w.worker.ActiveConnections()
|
return w.worker.ActiveConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *BridgeWorker) handleInternalConn(link transport.Link) {
|
func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
|
||||||
go func() {
|
go func() {
|
||||||
reader := link.Reader
|
reader := link.Reader
|
||||||
for {
|
for {
|
||||||
@@ -181,7 +180,7 @@ func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*tra
|
|||||||
uplinkReader, uplinkWriter := pipe.New(opt...)
|
uplinkReader, uplinkWriter := pipe.New(opt...)
|
||||||
downlinkReader, downlinkWriter := pipe.New(opt...)
|
downlinkReader, downlinkWriter := pipe.New(opt...)
|
||||||
|
|
||||||
w.handleInternalConn(transport.Link{
|
w.handleInternalConn(&transport.Link{
|
||||||
Reader: downlinkReader,
|
Reader: downlinkReader,
|
||||||
Writer: uplinkWriter,
|
Writer: uplinkWriter,
|
||||||
})
|
})
|
||||||
@@ -191,3 +190,16 @@ func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*tra
|
|||||||
Writer: downlinkWriter,
|
Writer: downlinkWriter,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *BridgeWorker) DispatchLink(ctx context.Context, dest net.Destination, link *transport.Link) error {
|
||||||
|
if !isInternalDomain(dest) {
|
||||||
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
|
Tag: w.tag,
|
||||||
|
})
|
||||||
|
return w.dispatcher.DispatchLink(ctx, dest, link)
|
||||||
|
}
|
||||||
|
|
||||||
|
w.handleInternalConn(link)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/reverse/config.proto
|
// source: app/reverse/config.proto
|
||||||
|
|
||||||
package reverse
|
package reverse
|
||||||
|
@@ -6,7 +6,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
|
@@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
internalDomain = "reverse.internal.example.com"
|
internalDomain = "reverse.internal.v2fly.org" // make reverse proxy compatible with v2fly
|
||||||
)
|
)
|
||||||
|
|
||||||
func isDomain(dest net.Destination, domain string) bool {
|
func isDomain(dest net.Destination, domain string) bool {
|
||||||
|
@@ -1,7 +1,10 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
"github.com/xtls/xray-core/common/dice"
|
||||||
|
"github.com/xtls/xray-core/features/extension"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -41,3 +44,9 @@ func (b *Balancer) PickOutbound() (string, error) {
|
|||||||
}
|
}
|
||||||
return tag, nil
|
return tag, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *Balancer) InjectContext(ctx context.Context) {
|
||||||
|
if contextReceiver, ok := b.strategy.(extension.ContextReceiver); ok {
|
||||||
|
contextReceiver.InjectContext(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -6,12 +6,11 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// routingServer is an implementation of RoutingService.
|
// routingServer is an implementation of RoutingService.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/router/command/command.proto
|
// source: app/router/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
@@ -163,18 +163,19 @@ func (x *RoutingContext) GetOutboundTag() string {
|
|||||||
// opened by xray-core.
|
// opened by xray-core.
|
||||||
// * FieldSelectors selects a subset of fields in routing statistics to return.
|
// * FieldSelectors selects a subset of fields in routing statistics to return.
|
||||||
// Valid selectors:
|
// Valid selectors:
|
||||||
// - inbound: Selects connection's inbound tag.
|
// - inbound: Selects connection's inbound tag.
|
||||||
// - network: Selects connection's network.
|
// - network: Selects connection's network.
|
||||||
// - ip: Equivalent as "ip_source" and "ip_target", selects both source and
|
// - ip: Equivalent as "ip_source" and "ip_target", selects both source and
|
||||||
// target IP.
|
// target IP.
|
||||||
// - port: Equivalent as "port_source" and "port_target", selects both source
|
// - port: Equivalent as "port_source" and "port_target", selects both source
|
||||||
// and target port.
|
// and target port.
|
||||||
// - domain: Selects target domain.
|
// - domain: Selects target domain.
|
||||||
// - protocol: Select connection's protocol.
|
// - protocol: Select connection's protocol.
|
||||||
// - user: Select connection's inbound user email.
|
// - user: Select connection's inbound user email.
|
||||||
// - attributes: Select connection's additional attributes.
|
// - attributes: Select connection's additional attributes.
|
||||||
// - outbound: Equivalent as "outbound" and "outbound_group", select both
|
// - outbound: Equivalent as "outbound" and "outbound_group", select both
|
||||||
// outbound tag and outbound group tags.
|
// outbound tag and outbound group tags.
|
||||||
|
//
|
||||||
// * If FieldSelectors is left empty, all fields will be returned.
|
// * If FieldSelectors is left empty, all fields will be returned.
|
||||||
type SubscribeRoutingStatsRequest struct {
|
type SubscribeRoutingStatsRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
|
// - protoc v4.23.1
|
||||||
|
// source: app/router/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
@@ -14,6 +18,11 @@ import (
|
|||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
|
const (
|
||||||
|
RoutingService_SubscribeRoutingStats_FullMethodName = "/xray.app.router.command.RoutingService/SubscribeRoutingStats"
|
||||||
|
RoutingService_TestRoute_FullMethodName = "/xray.app.router.command.RoutingService/TestRoute"
|
||||||
|
)
|
||||||
|
|
||||||
// RoutingServiceClient is the client API for RoutingService service.
|
// RoutingServiceClient is the client API for RoutingService service.
|
||||||
//
|
//
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
@@ -31,7 +40,7 @@ func NewRoutingServiceClient(cc grpc.ClientConnInterface) RoutingServiceClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *routingServiceClient) SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (RoutingService_SubscribeRoutingStatsClient, error) {
|
func (c *routingServiceClient) SubscribeRoutingStats(ctx context.Context, in *SubscribeRoutingStatsRequest, opts ...grpc.CallOption) (RoutingService_SubscribeRoutingStatsClient, error) {
|
||||||
stream, err := c.cc.NewStream(ctx, &RoutingService_ServiceDesc.Streams[0], "/xray.app.router.command.RoutingService/SubscribeRoutingStats", opts...)
|
stream, err := c.cc.NewStream(ctx, &RoutingService_ServiceDesc.Streams[0], RoutingService_SubscribeRoutingStats_FullMethodName, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -64,7 +73,7 @@ func (x *routingServiceSubscribeRoutingStatsClient) Recv() (*RoutingContext, err
|
|||||||
|
|
||||||
func (c *routingServiceClient) TestRoute(ctx context.Context, in *TestRouteRequest, opts ...grpc.CallOption) (*RoutingContext, error) {
|
func (c *routingServiceClient) TestRoute(ctx context.Context, in *TestRouteRequest, opts ...grpc.CallOption) (*RoutingContext, error) {
|
||||||
out := new(RoutingContext)
|
out := new(RoutingContext)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.router.command.RoutingService/TestRoute", in, out, opts...)
|
err := c.cc.Invoke(ctx, RoutingService_TestRoute_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -134,7 +143,7 @@ func _RoutingService_TestRoute_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.router.command.RoutingService/TestRoute",
|
FullMethod: RoutingService_TestRoute_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(RoutingServiceServer).TestRoute(ctx, req.(*TestRouteRequest))
|
return srv.(RoutingServiceServer).TestRoute(ctx, req.(*TestRouteRequest))
|
||||||
|
@@ -8,9 +8,6 @@ import (
|
|||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/test/bufconn"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/router"
|
"github.com/xtls/xray-core/app/router"
|
||||||
. "github.com/xtls/xray-core/app/router/command"
|
. "github.com/xtls/xray-core/app/router/command"
|
||||||
"github.com/xtls/xray-core/app/stats"
|
"github.com/xtls/xray-core/app/stats"
|
||||||
@@ -18,6 +15,8 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/testing/mocks"
|
"github.com/xtls/xray-core/testing/mocks"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/test/bufconn"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServiceSubscribeRoutingStats(t *testing.T) {
|
func TestServiceSubscribeRoutingStats(t *testing.T) {
|
||||||
@@ -284,7 +283,7 @@ func TestSerivceTestRoute(t *testing.T) {
|
|||||||
r := new(router.Router)
|
r := new(router.Router)
|
||||||
mockCtl := gomock.NewController(t)
|
mockCtl := gomock.NewController(t)
|
||||||
defer mockCtl.Finish()
|
defer mockCtl.Finish()
|
||||||
common.Must(r.Init(&router.Config{
|
common.Must(r.Init(context.TODO(), &router.Config{
|
||||||
Rule: []*router.RoutingRule{
|
Rule: []*router.RoutingRule{
|
||||||
{
|
{
|
||||||
InboundTag: []string{"in"},
|
InboundTag: []string{"in"},
|
||||||
|
@@ -3,9 +3,6 @@ package router
|
|||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"go.starlark.net/starlark"
|
|
||||||
"go.starlark.net/syntax"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/strmatcher"
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
@@ -285,44 +282,22 @@ func (m *ProtocolMatcher) Apply(ctx routing.Context) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AttributeMatcher struct {
|
type AttributeMatcher struct {
|
||||||
program *starlark.Program
|
configuredKeys map[string]string
|
||||||
}
|
|
||||||
|
|
||||||
func NewAttributeMatcher(code string) (*AttributeMatcher, error) {
|
|
||||||
starFile, err := syntax.Parse("attr.star", "satisfied=("+code+")", 0)
|
|
||||||
if err != nil {
|
|
||||||
return nil, newError("attr rule").Base(err)
|
|
||||||
}
|
|
||||||
p, err := starlark.FileProgram(starFile, func(name string) bool {
|
|
||||||
return name == "attrs"
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &AttributeMatcher{
|
|
||||||
program: p,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match implements attributes matching.
|
// Match implements attributes matching.
|
||||||
func (m *AttributeMatcher) Match(attrs map[string]string) bool {
|
func (m *AttributeMatcher) Match(attrs map[string]string) bool {
|
||||||
attrsDict := new(starlark.Dict)
|
// headers are insensitive most likely. So we do a convert
|
||||||
|
httpHeaders := make(map[string]string)
|
||||||
for key, value := range attrs {
|
for key, value := range attrs {
|
||||||
attrsDict.SetKey(starlark.String(key), starlark.String(value))
|
httpHeaders[strings.ToLower(key)] = strings.ToLower(value)
|
||||||
}
|
}
|
||||||
|
for key, value := range m.configuredKeys {
|
||||||
predefined := make(starlark.StringDict)
|
if a, ok := httpHeaders[key]; !ok || !strings.Contains(a, value) {
|
||||||
predefined["attrs"] = attrsDict
|
return false
|
||||||
|
}
|
||||||
thread := &starlark.Thread{
|
|
||||||
Name: "matcher",
|
|
||||||
}
|
}
|
||||||
results, err := m.program.Init(thread, predefined)
|
return true
|
||||||
if err != nil {
|
|
||||||
newError("attr matcher").Base(err).WriteToLog()
|
|
||||||
}
|
|
||||||
satisfied := results["satisfied"]
|
|
||||||
return satisfied != nil && bool(satisfied.Truth())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply implements Condition.
|
// Apply implements Condition.
|
||||||
|
@@ -13,11 +13,12 @@ type ipv6 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GeoIPMatcher struct {
|
type GeoIPMatcher struct {
|
||||||
countryCode string
|
countryCode string
|
||||||
ip4 []uint32
|
reverseMatch bool
|
||||||
prefix4 []uint8
|
ip4 []uint32
|
||||||
ip6 []ipv6
|
prefix4 []uint8
|
||||||
prefix6 []uint8
|
ip6 []ipv6
|
||||||
|
prefix6 []uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalize4(ip uint32, prefix uint8) uint32 {
|
func normalize4(ip uint32, prefix uint8) uint32 {
|
||||||
@@ -58,7 +59,7 @@ func (m *GeoIPMatcher) Init(cidrs []*CIDR) error {
|
|||||||
m.ip6 = make([]ipv6, 0, ip6Count)
|
m.ip6 = make([]ipv6, 0, ip6Count)
|
||||||
m.prefix6 = make([]uint8, 0, ip6Count)
|
m.prefix6 = make([]uint8, 0, ip6Count)
|
||||||
|
|
||||||
for _, cidr := range cidrs {
|
for _, cidr := range cidrList {
|
||||||
ip := cidr.Ip
|
ip := cidr.Ip
|
||||||
prefix := uint8(cidr.Prefix)
|
prefix := uint8(cidr.Prefix)
|
||||||
switch len(ip) {
|
switch len(ip) {
|
||||||
@@ -80,6 +81,10 @@ func (m *GeoIPMatcher) Init(cidrs []*CIDR) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *GeoIPMatcher) SetReverseMatch(isReverseMatch bool) {
|
||||||
|
m.reverseMatch = isReverseMatch
|
||||||
|
}
|
||||||
|
|
||||||
func (m *GeoIPMatcher) match4(ip uint32) bool {
|
func (m *GeoIPMatcher) match4(ip uint32) bool {
|
||||||
if len(m.ip4) == 0 {
|
if len(m.ip4) == 0 {
|
||||||
return false
|
return false
|
||||||
@@ -147,8 +152,17 @@ func (m *GeoIPMatcher) match6(ip ipv6) bool {
|
|||||||
func (m *GeoIPMatcher) Match(ip net.IP) bool {
|
func (m *GeoIPMatcher) Match(ip net.IP) bool {
|
||||||
switch len(ip) {
|
switch len(ip) {
|
||||||
case 4:
|
case 4:
|
||||||
|
if m.reverseMatch {
|
||||||
|
return !m.match4(binary.BigEndian.Uint32(ip))
|
||||||
|
}
|
||||||
return m.match4(binary.BigEndian.Uint32(ip))
|
return m.match4(binary.BigEndian.Uint32(ip))
|
||||||
case 16:
|
case 16:
|
||||||
|
if m.reverseMatch {
|
||||||
|
return !m.match6(ipv6{
|
||||||
|
a: binary.BigEndian.Uint64(ip[0:8]),
|
||||||
|
b: binary.BigEndian.Uint64(ip[8:16]),
|
||||||
|
})
|
||||||
|
}
|
||||||
return m.match6(ipv6{
|
return m.match6(ipv6{
|
||||||
a: binary.BigEndian.Uint64(ip[0:8]),
|
a: binary.BigEndian.Uint64(ip[0:8]),
|
||||||
b: binary.BigEndian.Uint64(ip[8:16]),
|
b: binary.BigEndian.Uint64(ip[8:16]),
|
||||||
@@ -168,14 +182,15 @@ type GeoIPMatcherContainer struct {
|
|||||||
func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
|
func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
|
||||||
if len(geoip.CountryCode) > 0 {
|
if len(geoip.CountryCode) > 0 {
|
||||||
for _, m := range c.matchers {
|
for _, m := range c.matchers {
|
||||||
if m.countryCode == geoip.CountryCode {
|
if m.countryCode == geoip.CountryCode && m.reverseMatch == geoip.ReverseMatch {
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m := &GeoIPMatcher{
|
m := &GeoIPMatcher{
|
||||||
countryCode: geoip.CountryCode,
|
countryCode: geoip.CountryCode,
|
||||||
|
reverseMatch: geoip.ReverseMatch,
|
||||||
}
|
}
|
||||||
if err := m.Init(geoip.Cidr); err != nil {
|
if err := m.Init(geoip.Cidr); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@@ -6,7 +6,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/router"
|
"github.com/xtls/xray-core/app/router"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -125,6 +124,42 @@ func TestGeoIPMatcher(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGeoIPReverseMatcher(t *testing.T) {
|
||||||
|
cidrList := router.CIDRList{
|
||||||
|
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
||||||
|
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
||||||
|
}
|
||||||
|
matcher := &router.GeoIPMatcher{}
|
||||||
|
matcher.SetReverseMatch(true) // Reverse match
|
||||||
|
common.Must(matcher.Init(cidrList))
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Output bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "8.8.8.8",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "2001:cdba::3257:9652",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "91.108.255.254",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
ip := net.ParseAddress(testCase.Input).IP()
|
||||||
|
actual := matcher.Match(ip)
|
||||||
|
if actual != testCase.Output {
|
||||||
|
t.Error("expect input", testCase.Input, "to be", testCase.Output, ", but actually", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGeoIPMatcher4CN(t *testing.T) {
|
func TestGeoIPMatcher4CN(t *testing.T) {
|
||||||
ips, err := loadGeoIP("CN")
|
ips, err := loadGeoIP("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/router"
|
. "github.com/xtls/xray-core/app/router"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
@@ -308,8 +307,10 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
rule: &RoutingRule{
|
rule: &RoutingRule{
|
||||||
Protocol: []string{"http"},
|
Protocol: []string{"http"},
|
||||||
Attributes: "attrs[':path'].startswith('/test')",
|
Attributes: map[string]string{
|
||||||
|
":path": "/test",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
test: []ruleTest{
|
test: []ruleTest{
|
||||||
{
|
{
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
@@ -143,11 +145,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Attributes) > 0 {
|
if len(rr.Attributes) > 0 {
|
||||||
cond, err := NewAttributeMatcher(rr.Attributes)
|
configuredKeys := make(map[string]string)
|
||||||
if err != nil {
|
for key, value := range rr.Attributes {
|
||||||
return nil, err
|
configuredKeys[strings.ToLower(key)] = strings.ToLower(value)
|
||||||
}
|
}
|
||||||
conds.Add(cond)
|
conds.Add(&AttributeMatcher{configuredKeys})
|
||||||
}
|
}
|
||||||
|
|
||||||
if conds.Len() == 0 {
|
if conds.Len() == 0 {
|
||||||
@@ -158,9 +160,21 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) {
|
func (br *BalancingRule) Build(ohm outbound.Manager) (*Balancer, error) {
|
||||||
return &Balancer{
|
switch br.Strategy {
|
||||||
selectors: br.OutboundSelector,
|
case "leastPing":
|
||||||
strategy: &RandomStrategy{},
|
return &Balancer{
|
||||||
ohm: ohm,
|
selectors: br.OutboundSelector,
|
||||||
}, nil
|
strategy: &LeastPingStrategy{},
|
||||||
|
ohm: ohm,
|
||||||
|
}, nil
|
||||||
|
case "random":
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
return &Balancer{
|
||||||
|
selectors: br.OutboundSelector,
|
||||||
|
strategy: &RandomStrategy{},
|
||||||
|
ohm: ohm,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/router/config.proto
|
// source: app/router/config.proto
|
||||||
|
|
||||||
package router
|
package router
|
||||||
@@ -264,8 +264,9 @@ type GeoIP struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
CountryCode string `protobuf:"bytes,1,opt,name=country_code,json=countryCode,proto3" json:"country_code,omitempty"`
|
||||||
Cidr []*CIDR `protobuf:"bytes,2,rep,name=cidr,proto3" json:"cidr,omitempty"`
|
Cidr []*CIDR `protobuf:"bytes,2,rep,name=cidr,proto3" json:"cidr,omitempty"`
|
||||||
|
ReverseMatch bool `protobuf:"varint,3,opt,name=reverse_match,json=reverseMatch,proto3" json:"reverse_match,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GeoIP) Reset() {
|
func (x *GeoIP) Reset() {
|
||||||
@@ -314,6 +315,13 @@ func (x *GeoIP) GetCidr() []*CIDR {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *GeoIP) GetReverseMatch() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.ReverseMatch
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type GeoIPList struct {
|
type GeoIPList struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -469,6 +477,7 @@ type RoutingRule struct {
|
|||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// Types that are assignable to TargetTag:
|
// Types that are assignable to TargetTag:
|
||||||
|
//
|
||||||
// *RoutingRule_Tag
|
// *RoutingRule_Tag
|
||||||
// *RoutingRule_BalancingTag
|
// *RoutingRule_BalancingTag
|
||||||
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
||||||
@@ -477,7 +486,7 @@ type RoutingRule struct {
|
|||||||
// List of CIDRs for target IP address matching.
|
// List of CIDRs for target IP address matching.
|
||||||
// Deprecated. Use geoip below.
|
// Deprecated. Use geoip below.
|
||||||
//
|
//
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||||
Cidr []*CIDR `protobuf:"bytes,3,rep,name=cidr,proto3" json:"cidr,omitempty"`
|
Cidr []*CIDR `protobuf:"bytes,3,rep,name=cidr,proto3" json:"cidr,omitempty"`
|
||||||
// List of GeoIPs for target IP address matching. If this entry exists, the
|
// List of GeoIPs for target IP address matching. If this entry exists, the
|
||||||
// cidr above will have no effect. GeoIP fields with the same country code are
|
// cidr above will have no effect. GeoIP fields with the same country code are
|
||||||
@@ -487,30 +496,30 @@ type RoutingRule struct {
|
|||||||
// A range of port [from, to]. If the destination port is in this range, this
|
// A range of port [from, to]. If the destination port is in this range, this
|
||||||
// rule takes effect. Deprecated. Use port_list.
|
// rule takes effect. Deprecated. Use port_list.
|
||||||
//
|
//
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||||
PortRange *net.PortRange `protobuf:"bytes,4,opt,name=port_range,json=portRange,proto3" json:"port_range,omitempty"`
|
PortRange *net.PortRange `protobuf:"bytes,4,opt,name=port_range,json=portRange,proto3" json:"port_range,omitempty"`
|
||||||
// List of ports.
|
// List of ports.
|
||||||
PortList *net.PortList `protobuf:"bytes,14,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
PortList *net.PortList `protobuf:"bytes,14,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
||||||
// List of networks. Deprecated. Use networks.
|
// List of networks. Deprecated. Use networks.
|
||||||
//
|
//
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||||
NetworkList *net.NetworkList `protobuf:"bytes,5,opt,name=network_list,json=networkList,proto3" json:"network_list,omitempty"`
|
NetworkList *net.NetworkList `protobuf:"bytes,5,opt,name=network_list,json=networkList,proto3" json:"network_list,omitempty"`
|
||||||
// List of networks for matching.
|
// List of networks for matching.
|
||||||
Networks []net.Network `protobuf:"varint,13,rep,packed,name=networks,proto3,enum=xray.common.net.Network" json:"networks,omitempty"`
|
Networks []net.Network `protobuf:"varint,13,rep,packed,name=networks,proto3,enum=xray.common.net.Network" json:"networks,omitempty"`
|
||||||
// List of CIDRs for source IP address matching.
|
// List of CIDRs for source IP address matching.
|
||||||
//
|
//
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||||
SourceCidr []*CIDR `protobuf:"bytes,6,rep,name=source_cidr,json=sourceCidr,proto3" json:"source_cidr,omitempty"`
|
SourceCidr []*CIDR `protobuf:"bytes,6,rep,name=source_cidr,json=sourceCidr,proto3" json:"source_cidr,omitempty"`
|
||||||
// List of GeoIPs for source IP address matching. If this entry exists, the
|
// List of GeoIPs for source IP address matching. If this entry exists, the
|
||||||
// source_cidr above will have no effect.
|
// source_cidr above will have no effect.
|
||||||
SourceGeoip []*GeoIP `protobuf:"bytes,11,rep,name=source_geoip,json=sourceGeoip,proto3" json:"source_geoip,omitempty"`
|
SourceGeoip []*GeoIP `protobuf:"bytes,11,rep,name=source_geoip,json=sourceGeoip,proto3" json:"source_geoip,omitempty"`
|
||||||
// List of ports for source port matching.
|
// List of ports for source port matching.
|
||||||
SourcePortList *net.PortList `protobuf:"bytes,16,opt,name=source_port_list,json=sourcePortList,proto3" json:"source_port_list,omitempty"`
|
SourcePortList *net.PortList `protobuf:"bytes,16,opt,name=source_port_list,json=sourcePortList,proto3" json:"source_port_list,omitempty"`
|
||||||
UserEmail []string `protobuf:"bytes,7,rep,name=user_email,json=userEmail,proto3" json:"user_email,omitempty"`
|
UserEmail []string `protobuf:"bytes,7,rep,name=user_email,json=userEmail,proto3" json:"user_email,omitempty"`
|
||||||
InboundTag []string `protobuf:"bytes,8,rep,name=inbound_tag,json=inboundTag,proto3" json:"inbound_tag,omitempty"`
|
InboundTag []string `protobuf:"bytes,8,rep,name=inbound_tag,json=inboundTag,proto3" json:"inbound_tag,omitempty"`
|
||||||
Protocol []string `protobuf:"bytes,9,rep,name=protocol,proto3" json:"protocol,omitempty"`
|
Protocol []string `protobuf:"bytes,9,rep,name=protocol,proto3" json:"protocol,omitempty"`
|
||||||
Attributes string `protobuf:"bytes,15,opt,name=attributes,proto3" json:"attributes,omitempty"`
|
Attributes map[string]string `protobuf:"bytes,15,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
DomainMatcher string `protobuf:"bytes,17,opt,name=domain_matcher,json=domainMatcher,proto3" json:"domain_matcher,omitempty"`
|
DomainMatcher string `protobuf:"bytes,17,opt,name=domain_matcher,json=domainMatcher,proto3" json:"domain_matcher,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) Reset() {
|
func (x *RoutingRule) Reset() {
|
||||||
@@ -573,7 +582,7 @@ func (x *RoutingRule) GetDomain() []*Domain {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||||
func (x *RoutingRule) GetCidr() []*CIDR {
|
func (x *RoutingRule) GetCidr() []*CIDR {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Cidr
|
return x.Cidr
|
||||||
@@ -588,7 +597,7 @@ func (x *RoutingRule) GetGeoip() []*GeoIP {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||||
func (x *RoutingRule) GetPortRange() *net.PortRange {
|
func (x *RoutingRule) GetPortRange() *net.PortRange {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.PortRange
|
return x.PortRange
|
||||||
@@ -603,7 +612,7 @@ func (x *RoutingRule) GetPortList() *net.PortList {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||||
func (x *RoutingRule) GetNetworkList() *net.NetworkList {
|
func (x *RoutingRule) GetNetworkList() *net.NetworkList {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.NetworkList
|
return x.NetworkList
|
||||||
@@ -618,7 +627,7 @@ func (x *RoutingRule) GetNetworks() []net.Network {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Do not use.
|
// Deprecated: Marked as deprecated in app/router/config.proto.
|
||||||
func (x *RoutingRule) GetSourceCidr() []*CIDR {
|
func (x *RoutingRule) GetSourceCidr() []*CIDR {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.SourceCidr
|
return x.SourceCidr
|
||||||
@@ -661,11 +670,11 @@ func (x *RoutingRule) GetProtocol() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) GetAttributes() string {
|
func (x *RoutingRule) GetAttributes() map[string]string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Attributes
|
return x.Attributes
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) GetDomainMatcher() string {
|
func (x *RoutingRule) GetDomainMatcher() string {
|
||||||
@@ -700,6 +709,7 @@ type BalancingRule struct {
|
|||||||
|
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
OutboundSelector []string `protobuf:"bytes,2,rep,name=outbound_selector,json=outboundSelector,proto3" json:"outbound_selector,omitempty"`
|
OutboundSelector []string `protobuf:"bytes,2,rep,name=outbound_selector,json=outboundSelector,proto3" json:"outbound_selector,omitempty"`
|
||||||
|
Strategy string `protobuf:"bytes,3,opt,name=strategy,proto3" json:"strategy,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BalancingRule) Reset() {
|
func (x *BalancingRule) Reset() {
|
||||||
@@ -748,6 +758,13 @@ func (x *BalancingRule) GetOutboundSelector() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *BalancingRule) GetStrategy() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Strategy
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -818,6 +835,7 @@ type Domain_Attribute struct {
|
|||||||
|
|
||||||
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||||
// Types that are assignable to TypedValue:
|
// Types that are assignable to TypedValue:
|
||||||
|
//
|
||||||
// *Domain_Attribute_BoolValue
|
// *Domain_Attribute_BoolValue
|
||||||
// *Domain_Attribute_IntValue
|
// *Domain_Attribute_IntValue
|
||||||
TypedValue isDomain_Attribute_TypedValue `protobuf_oneof:"typed_value"`
|
TypedValue isDomain_Attribute_TypedValue `protobuf_oneof:"typed_value"`
|
||||||
@@ -930,105 +948,116 @@ var file_app_router_config_proto_rawDesc = []byte{
|
|||||||
0x03, 0x22, 0x2e, 0x0a, 0x04, 0x43, 0x49, 0x44, 0x52, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18,
|
0x03, 0x22, 0x2e, 0x0a, 0x04, 0x43, 0x49, 0x44, 0x52, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65,
|
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65,
|
||||||
0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69,
|
0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69,
|
||||||
0x78, 0x22, 0x55, 0x0a, 0x05, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f,
|
0x78, 0x22, 0x7a, 0x0a, 0x05, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f,
|
||||||
0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x29, 0x0a,
|
0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x29, 0x0a,
|
||||||
0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72,
|
0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49,
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49,
|
||||||
0x44, 0x52, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x22, 0x39, 0x0a, 0x09, 0x47, 0x65, 0x6f, 0x49,
|
0x44, 0x52, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, 0x65,
|
||||||
0x50, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01,
|
0x72, 0x73, 0x65, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
0x0c, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x22, 0x39, 0x0a,
|
||||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x65, 0x6e,
|
0x09, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2c, 0x0a, 0x05, 0x65, 0x6e,
|
||||||
0x74, 0x72, 0x79, 0x22, 0x5d, 0x0a, 0x07, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x12, 0x21,
|
0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x64,
|
0x50, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x5d, 0x0a, 0x07, 0x47, 0x65, 0x6f, 0x53,
|
||||||
0x65, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28,
|
0x69, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63,
|
||||||
|
0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||||
|
0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
|
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
|
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52,
|
||||||
|
0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x3d, 0x0a, 0x0b, 0x47, 0x65, 0x6f, 0x53, 0x69,
|
||||||
|
0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18,
|
||||||
|
0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||||
|
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52,
|
||||||
|
0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xa2, 0x07, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x69,
|
||||||
|
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x0d, 0x62, 0x61,
|
||||||
|
0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28,
|
||||||
|
0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x54, 0x61,
|
||||||
|
0x67, 0x12, 0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||||
0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||||
0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61,
|
0x74, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61,
|
||||||
0x69, 0x6e, 0x22, 0x3d, 0x0a, 0x0b, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73,
|
0x69, 0x6e, 0x12, 0x2d, 0x0a, 0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
|
0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||||
0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x63, 0x69, 0x64,
|
||||||
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69, 0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72,
|
0x72, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x79, 0x22, 0xb5, 0x06, 0x0a, 0x0b, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c,
|
0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||||
0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00,
|
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12,
|
||||||
0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
|
0x3d, 0x0a, 0x0a, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20,
|
||||||
0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c,
|
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||||
0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x12, 0x2f, 0x0a, 0x06,
|
0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78,
|
0x02, 0x18, 0x01, 0x52, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x36,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x44,
|
0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2d, 0x0a,
|
0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||||
0x04, 0x63, 0x69, 0x64, 0x72, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72,
|
0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49,
|
0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x43, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
|
||||||
0x44, 0x52, 0x42, 0x02, 0x18, 0x01, 0x52, 0x04, 0x63, 0x69, 0x64, 0x72, 0x12, 0x2c, 0x0a, 0x05,
|
0x6b, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78,
|
||||||
0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72,
|
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65,
|
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b,
|
||||||
0x6f, 0x49, 0x50, 0x52, 0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x3d, 0x0a, 0x0a, 0x70, 0x6f,
|
0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x08, 0x6e,
|
||||||
0x72, 0x74, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
|
0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x18, 0x2e,
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
|
|
||||||
0x2e, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x42, 0x02, 0x18, 0x01, 0x52, 0x09,
|
|
||||||
0x70, 0x6f, 0x72, 0x74, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72,
|
|
||||||
0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50,
|
|
||||||
0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73,
|
|
||||||
0x74, 0x12, 0x43, 0x0a, 0x0c, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x6c, 0x69, 0x73,
|
|
||||||
0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72,
|
|
||||||
0x6b, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x6e, 0x65, 0x74, 0x77, 0x6f,
|
|
||||||
0x72, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x34, 0x0a, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
|
|
||||||
0x6b, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f,
|
|
||||||
0x72, 0x6b, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x12, 0x3a, 0x0a, 0x0b,
|
|
||||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x06, 0x20, 0x03, 0x28,
|
|
||||||
0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
|
||||||
0x74, 0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x73, 0x6f,
|
|
||||||
0x75, 0x72, 0x63, 0x65, 0x43, 0x69, 0x64, 0x72, 0x12, 0x39, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72,
|
|
||||||
0x63, 0x65, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16,
|
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
|
||||||
0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x47, 0x65,
|
|
||||||
0x6f, 0x69, 0x70, 0x12, 0x43, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x70, 0x6f,
|
|
||||||
0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e,
|
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e,
|
||||||
0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65,
|
0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x08, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
|
||||||
0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72,
|
0x73, 0x12, 0x3a, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x69, 0x64, 0x72,
|
||||||
0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73,
|
0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x62, 0x6f, 0x75,
|
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x49, 0x44, 0x52, 0x42, 0x02, 0x18,
|
||||||
0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x6e,
|
0x01, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x69, 0x64, 0x72, 0x12, 0x39, 0x0a,
|
||||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74,
|
0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0b, 0x20,
|
||||||
0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74,
|
0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||||
0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74,
|
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0b, 0x73, 0x6f, 0x75,
|
||||||
0x65, 0x73, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
|
0x72, 0x63, 0x65, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x43, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72,
|
||||||
0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x6d,
|
0x63, 0x65, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x10, 0x20, 0x01,
|
||||||
0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x64, 0x6f,
|
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x42, 0x0c, 0x0a, 0x0a, 0x74,
|
0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x73,
|
||||||
0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0x4e, 0x0a, 0x0d, 0x42, 0x61, 0x6c,
|
0x6f, 0x75, 0x72, 0x63, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1d, 0x0a,
|
||||||
0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61,
|
0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x07, 0x20, 0x03, 0x28,
|
||||||
0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11,
|
0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x0a, 0x0b,
|
||||||
0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f,
|
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x08, 0x20, 0x03, 0x28,
|
||||||
0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
|
0x09, 0x52, 0x0a, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a,
|
||||||
0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f,
|
0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73,
|
0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x4c, 0x0a, 0x0a, 0x61, 0x74, 0x74,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e,
|
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2c, 0x2e,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e,
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72,
|
0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72,
|
||||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72,
|
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74,
|
||||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20,
|
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
0x6e, 0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c,
|
0x0d, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x1a, 0x3d,
|
||||||
0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72,
|
||||||
0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
||||||
0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52,
|
0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a,
|
||||||
0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47,
|
0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0x6a, 0x0a, 0x0d, 0x42,
|
||||||
0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03,
|
||||||
0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73,
|
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b,
|
||||||
0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e,
|
0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
|
||||||
0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44,
|
0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f,
|
||||||
0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
|
||||||
0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
||||||
0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f,
|
0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72,
|
||||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
|
0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72,
|
||||||
0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 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, 0x30, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||||
|
0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||||
|
0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52,
|
||||||
|
0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
|
||||||
|
0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e,
|
||||||
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e,
|
||||||
|
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62,
|
||||||
|
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e,
|
||||||
|
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08,
|
||||||
|
0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49,
|
||||||
|
0x70, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61,
|
||||||
|
0x74, 0x63, 0x68, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d,
|
||||||
|
0x61, 0x6e, 0x64, 0x10, 0x03, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24,
|
||||||
|
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
|
||||||
|
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f,
|
||||||
|
0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e,
|
||||||
|
0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -1044,7 +1073,7 @@ func file_app_router_config_proto_rawDescGZIP() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var file_app_router_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_app_router_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
||||||
var file_app_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
var file_app_router_config_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
|
||||||
var file_app_router_config_proto_goTypes = []interface{}{
|
var file_app_router_config_proto_goTypes = []interface{}{
|
||||||
(Domain_Type)(0), // 0: xray.app.router.Domain.Type
|
(Domain_Type)(0), // 0: xray.app.router.Domain.Type
|
||||||
(Config_DomainStrategy)(0), // 1: xray.app.router.Config.DomainStrategy
|
(Config_DomainStrategy)(0), // 1: xray.app.router.Config.DomainStrategy
|
||||||
@@ -1058,10 +1087,11 @@ var file_app_router_config_proto_goTypes = []interface{}{
|
|||||||
(*BalancingRule)(nil), // 9: xray.app.router.BalancingRule
|
(*BalancingRule)(nil), // 9: xray.app.router.BalancingRule
|
||||||
(*Config)(nil), // 10: xray.app.router.Config
|
(*Config)(nil), // 10: xray.app.router.Config
|
||||||
(*Domain_Attribute)(nil), // 11: xray.app.router.Domain.Attribute
|
(*Domain_Attribute)(nil), // 11: xray.app.router.Domain.Attribute
|
||||||
(*net.PortRange)(nil), // 12: xray.common.net.PortRange
|
nil, // 12: xray.app.router.RoutingRule.AttributesEntry
|
||||||
(*net.PortList)(nil), // 13: xray.common.net.PortList
|
(*net.PortRange)(nil), // 13: xray.common.net.PortRange
|
||||||
(*net.NetworkList)(nil), // 14: xray.common.net.NetworkList
|
(*net.PortList)(nil), // 14: xray.common.net.PortList
|
||||||
(net.Network)(0), // 15: xray.common.net.Network
|
(*net.NetworkList)(nil), // 15: xray.common.net.NetworkList
|
||||||
|
(net.Network)(0), // 16: xray.common.net.Network
|
||||||
}
|
}
|
||||||
var file_app_router_config_proto_depIdxs = []int32{
|
var file_app_router_config_proto_depIdxs = []int32{
|
||||||
0, // 0: xray.app.router.Domain.type:type_name -> xray.app.router.Domain.Type
|
0, // 0: xray.app.router.Domain.type:type_name -> xray.app.router.Domain.Type
|
||||||
@@ -1073,21 +1103,22 @@ var file_app_router_config_proto_depIdxs = []int32{
|
|||||||
2, // 6: xray.app.router.RoutingRule.domain:type_name -> xray.app.router.Domain
|
2, // 6: xray.app.router.RoutingRule.domain:type_name -> xray.app.router.Domain
|
||||||
3, // 7: xray.app.router.RoutingRule.cidr:type_name -> xray.app.router.CIDR
|
3, // 7: xray.app.router.RoutingRule.cidr:type_name -> xray.app.router.CIDR
|
||||||
4, // 8: xray.app.router.RoutingRule.geoip:type_name -> xray.app.router.GeoIP
|
4, // 8: xray.app.router.RoutingRule.geoip:type_name -> xray.app.router.GeoIP
|
||||||
12, // 9: xray.app.router.RoutingRule.port_range:type_name -> xray.common.net.PortRange
|
13, // 9: xray.app.router.RoutingRule.port_range:type_name -> xray.common.net.PortRange
|
||||||
13, // 10: xray.app.router.RoutingRule.port_list:type_name -> xray.common.net.PortList
|
14, // 10: xray.app.router.RoutingRule.port_list:type_name -> xray.common.net.PortList
|
||||||
14, // 11: xray.app.router.RoutingRule.network_list:type_name -> xray.common.net.NetworkList
|
15, // 11: xray.app.router.RoutingRule.network_list:type_name -> xray.common.net.NetworkList
|
||||||
15, // 12: xray.app.router.RoutingRule.networks:type_name -> xray.common.net.Network
|
16, // 12: xray.app.router.RoutingRule.networks:type_name -> xray.common.net.Network
|
||||||
3, // 13: xray.app.router.RoutingRule.source_cidr:type_name -> xray.app.router.CIDR
|
3, // 13: xray.app.router.RoutingRule.source_cidr:type_name -> xray.app.router.CIDR
|
||||||
4, // 14: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
|
4, // 14: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
|
||||||
13, // 15: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
|
14, // 15: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
|
||||||
1, // 16: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
12, // 16: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
|
||||||
8, // 17: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
1, // 17: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
||||||
9, // 18: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
8, // 18: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
||||||
19, // [19:19] is the sub-list for method output_type
|
9, // 19: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
||||||
19, // [19:19] is the sub-list for method input_type
|
20, // [20:20] is the sub-list for method output_type
|
||||||
19, // [19:19] is the sub-list for extension type_name
|
20, // [20:20] is the sub-list for method input_type
|
||||||
19, // [19:19] is the sub-list for extension extendee
|
20, // [20:20] is the sub-list for extension type_name
|
||||||
0, // [0:19] is the sub-list for field type_name
|
20, // [20:20] is the sub-list for extension extendee
|
||||||
|
0, // [0:20] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_router_config_proto_init() }
|
func init() { file_app_router_config_proto_init() }
|
||||||
@@ -1231,7 +1262,7 @@ func file_app_router_config_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_router_config_proto_rawDesc,
|
RawDescriptor: file_app_router_config_proto_rawDesc,
|
||||||
NumEnums: 2,
|
NumEnums: 2,
|
||||||
NumMessages: 10,
|
NumMessages: 11,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
@@ -54,6 +54,7 @@ message CIDR {
|
|||||||
message GeoIP {
|
message GeoIP {
|
||||||
string country_code = 1;
|
string country_code = 1;
|
||||||
repeated CIDR cidr = 2;
|
repeated CIDR cidr = 2;
|
||||||
|
bool reverse_match = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GeoIPList {
|
message GeoIPList {
|
||||||
@@ -118,7 +119,7 @@ message RoutingRule {
|
|||||||
repeated string inbound_tag = 8;
|
repeated string inbound_tag = 8;
|
||||||
repeated string protocol = 9;
|
repeated string protocol = 9;
|
||||||
|
|
||||||
string attributes = 15;
|
map<string, string> attributes = 15;
|
||||||
|
|
||||||
string domain_matcher = 17;
|
string domain_matcher = 17;
|
||||||
}
|
}
|
||||||
@@ -126,6 +127,7 @@ message RoutingRule {
|
|||||||
message BalancingRule {
|
message BalancingRule {
|
||||||
string tag = 1;
|
string tag = 1;
|
||||||
repeated string outbound_selector = 2;
|
repeated string outbound_selector = 2;
|
||||||
|
string strategy = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
|
@@ -29,7 +29,7 @@ type Route struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes the Router.
|
// Init initializes the Router.
|
||||||
func (r *Router) Init(config *Config, d dns.Client, ohm outbound.Manager) error {
|
func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm outbound.Manager) error {
|
||||||
r.domainStrategy = config.DomainStrategy
|
r.domainStrategy = config.DomainStrategy
|
||||||
r.dns = d
|
r.dns = d
|
||||||
|
|
||||||
@@ -39,6 +39,7 @@ func (r *Router) Init(config *Config, d dns.Client, ohm outbound.Manager) error
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
balancer.InjectContext(ctx)
|
||||||
r.balancers[rule.Tag] = balancer
|
r.balancers[rule.Tag] = balancer
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,7 +122,7 @@ func (*Router) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type implement common.HasType.
|
// Type implements common.HasType.
|
||||||
func (*Router) Type() interface{} {
|
func (*Router) Type() interface{} {
|
||||||
return routing.RouterType()
|
return routing.RouterType()
|
||||||
}
|
}
|
||||||
@@ -140,7 +141,7 @@ func init() {
|
|||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager) error {
|
if err := core.RequireFeatures(ctx, func(d dns.Client, ohm outbound.Manager) error {
|
||||||
return r.Init(config.(*Config), d, ohm)
|
return r.Init(ctx, config.(*Config), d, ohm)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -4,14 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/features/dns"
|
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
|
||||||
. "github.com/xtls/xray-core/app/router"
|
. "github.com/xtls/xray-core/app/router"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
routing_session "github.com/xtls/xray-core/features/routing/session"
|
routing_session "github.com/xtls/xray-core/features/routing/session"
|
||||||
"github.com/xtls/xray-core/testing/mocks"
|
"github.com/xtls/xray-core/testing/mocks"
|
||||||
@@ -42,7 +40,7 @@ func TestSimpleRouter(t *testing.T) {
|
|||||||
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
|
mockHs := mocks.NewOutboundHandlerSelector(mockCtl)
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(config, mockDNS, &mockOutboundManager{
|
common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
|
||||||
Manager: mockOhm,
|
Manager: mockOhm,
|
||||||
HandlerSelector: mockHs,
|
HandlerSelector: mockHs,
|
||||||
}))
|
}))
|
||||||
@@ -83,7 +81,7 @@ func TestSimpleBalancer(t *testing.T) {
|
|||||||
mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test"})
|
mockHs.EXPECT().Select(gomock.Eq([]string{"test-"})).Return([]string{"test"})
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(config, mockDNS, &mockOutboundManager{
|
common.Must(r.Init(context.TODO(), config, mockDNS, &mockOutboundManager{
|
||||||
Manager: mockOhm,
|
Manager: mockOhm,
|
||||||
HandlerSelector: mockHs,
|
HandlerSelector: mockHs,
|
||||||
}))
|
}))
|
||||||
@@ -125,7 +123,7 @@ func TestIPOnDemand(t *testing.T) {
|
|||||||
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(config, mockDNS, nil))
|
common.Must(r.Init(context.TODO(), config, mockDNS, nil))
|
||||||
|
|
||||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
|
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
|
||||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||||
@@ -164,7 +162,7 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
|||||||
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(config, mockDNS, nil))
|
common.Must(r.Init(context.TODO(), config, mockDNS, nil))
|
||||||
|
|
||||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
|
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
|
||||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||||
@@ -198,7 +196,7 @@ func TestIPIfNonMatchIP(t *testing.T) {
|
|||||||
mockDNS := mocks.NewDNSClient(mockCtl)
|
mockDNS := mocks.NewDNSClient(mockCtl)
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(config, mockDNS, nil))
|
common.Must(r.Init(context.TODO(), config, mockDNS, nil))
|
||||||
|
|
||||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.LocalHostIP, 80)})
|
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.LocalHostIP, 80)})
|
||||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||||
|
61
app/router/strategy_leastping.go
Normal file
61
app/router/strategy_leastping.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/app/observatory"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/extension"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LeastPingStrategy struct {
|
||||||
|
ctx context.Context
|
||||||
|
observatory extension.Observatory
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LeastPingStrategy) InjectContext(ctx context.Context) {
|
||||||
|
l.ctx = ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LeastPingStrategy) PickOutbound(strings []string) string {
|
||||||
|
if l.observatory == nil {
|
||||||
|
common.Must(core.RequireFeatures(l.ctx, func(observatory extension.Observatory) error {
|
||||||
|
l.observatory = observatory
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
observeReport, err := l.observatory.GetObservation(l.ctx)
|
||||||
|
if err != nil {
|
||||||
|
newError("cannot get observe report").Base(err).WriteToLog()
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
outboundsList := outboundList(strings)
|
||||||
|
if result, ok := observeReport.(*observatory.ObservationResult); ok {
|
||||||
|
status := result.Status
|
||||||
|
leastPing := int64(99999999)
|
||||||
|
selectedOutboundName := ""
|
||||||
|
for _, v := range status {
|
||||||
|
if outboundsList.contains(v.OutboundTag) && v.Alive && v.Delay < leastPing {
|
||||||
|
selectedOutboundName = v.OutboundTag
|
||||||
|
leastPing = v.Delay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selectedOutboundName
|
||||||
|
}
|
||||||
|
|
||||||
|
// No way to understand observeReport
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type outboundList []string
|
||||||
|
|
||||||
|
func (o outboundList) contains(name string) bool {
|
||||||
|
for _, v := range o {
|
||||||
|
if v == name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
@@ -7,13 +7,12 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/stats"
|
"github.com/xtls/xray-core/app/stats"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/strmatcher"
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
feature_stats "github.com/xtls/xray-core/features/stats"
|
feature_stats "github.com/xtls/xray-core/features/stats"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
// statsServer is an implementation of StatsService.
|
// statsServer is an implementation of StatsService.
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/stats/command/command.proto
|
// source: app/stats/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
@@ -1,4 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.3.0
|
||||||
|
// - protoc v4.23.1
|
||||||
|
// source: app/stats/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
@@ -14,6 +18,12 @@ import (
|
|||||||
// Requires gRPC-Go v1.32.0 or later.
|
// Requires gRPC-Go v1.32.0 or later.
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
const _ = grpc.SupportPackageIsVersion7
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatsService_GetStats_FullMethodName = "/xray.app.stats.command.StatsService/GetStats"
|
||||||
|
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.
|
// StatsServiceClient is the client API for StatsService service.
|
||||||
//
|
//
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||||
@@ -33,7 +43,7 @@ func NewStatsServiceClient(cc grpc.ClientConnInterface) StatsServiceClient {
|
|||||||
|
|
||||||
func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error) {
|
func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsResponse, error) {
|
||||||
out := new(GetStatsResponse)
|
out := new(GetStatsResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.stats.command.StatsService/GetStats", in, out, opts...)
|
err := c.cc.Invoke(ctx, StatsService_GetStats_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -42,7 +52,7 @@ func (c *statsServiceClient) GetStats(ctx context.Context, in *GetStatsRequest,
|
|||||||
|
|
||||||
func (c *statsServiceClient) QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, error) {
|
func (c *statsServiceClient) QueryStats(ctx context.Context, in *QueryStatsRequest, opts ...grpc.CallOption) (*QueryStatsResponse, error) {
|
||||||
out := new(QueryStatsResponse)
|
out := new(QueryStatsResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.stats.command.StatsService/QueryStats", in, out, opts...)
|
err := c.cc.Invoke(ctx, StatsService_QueryStats_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -51,7 +61,7 @@ func (c *statsServiceClient) QueryStats(ctx context.Context, in *QueryStatsReque
|
|||||||
|
|
||||||
func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error) {
|
func (c *statsServiceClient) GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error) {
|
||||||
out := new(SysStatsResponse)
|
out := new(SysStatsResponse)
|
||||||
err := c.cc.Invoke(ctx, "/xray.app.stats.command.StatsService/GetSysStats", in, out, opts...)
|
err := c.cc.Invoke(ctx, StatsService_GetSysStats_FullMethodName, in, out, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -104,7 +114,7 @@ func _StatsService_GetStats_Handler(srv interface{}, ctx context.Context, dec fu
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.stats.command.StatsService/GetStats",
|
FullMethod: StatsService_GetStats_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(StatsServiceServer).GetStats(ctx, req.(*GetStatsRequest))
|
return srv.(StatsServiceServer).GetStats(ctx, req.(*GetStatsRequest))
|
||||||
@@ -122,7 +132,7 @@ func _StatsService_QueryStats_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.stats.command.StatsService/QueryStats",
|
FullMethod: StatsService_QueryStats_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(StatsServiceServer).QueryStats(ctx, req.(*QueryStatsRequest))
|
return srv.(StatsServiceServer).QueryStats(ctx, req.(*QueryStatsRequest))
|
||||||
@@ -140,7 +150,7 @@ func _StatsService_GetSysStats_Handler(srv interface{}, ctx context.Context, dec
|
|||||||
}
|
}
|
||||||
info := &grpc.UnaryServerInfo{
|
info := &grpc.UnaryServerInfo{
|
||||||
Server: srv,
|
Server: srv,
|
||||||
FullMethod: "/xray.app.stats.command.StatsService/GetSysStats",
|
FullMethod: StatsService_GetSysStats_FullMethodName,
|
||||||
}
|
}
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
return srv.(StatsServiceServer).GetSysStats(ctx, req.(*SysStatsRequest))
|
return srv.(StatsServiceServer).GetSysStats(ctx, req.(*SysStatsRequest))
|
||||||
|
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/stats"
|
"github.com/xtls/xray-core/app/stats"
|
||||||
. "github.com/xtls/xray-core/app/stats/command"
|
. "github.com/xtls/xray-core/app/stats/command"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.27.1
|
// protoc-gen-go v1.30.0
|
||||||
// protoc v3.18.0
|
// protoc v4.23.1
|
||||||
// source: app/stats/config.proto
|
// source: app/stats/config.proto
|
||||||
|
|
||||||
package stats
|
package stats
|
||||||
|
6
common/antireplay/antireplay.go
Normal file
6
common/antireplay/antireplay.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package antireplay
|
||||||
|
|
||||||
|
type GeneralizedReplayFilter interface {
|
||||||
|
Interval() int64
|
||||||
|
Check(sum []byte) bool
|
||||||
|
}
|
36
common/antireplay/bloomring.go
Normal file
36
common/antireplay/bloomring.go
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package antireplay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
ss_bloomring "github.com/v2fly/ss-bloomring"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BloomRing struct {
|
||||||
|
*ss_bloomring.BloomRing
|
||||||
|
lock *sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BloomRing) Interval() int64 {
|
||||||
|
return 9999999
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b BloomRing) Check(sum []byte) bool {
|
||||||
|
b.lock.Lock()
|
||||||
|
defer b.lock.Unlock()
|
||||||
|
if b.Test(sum) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
b.Add(sum)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBloomRing() BloomRing {
|
||||||
|
const (
|
||||||
|
DefaultSFCapacity = 1e6
|
||||||
|
// FalsePositiveRate
|
||||||
|
DefaultSFFPR = 1e-6
|
||||||
|
DefaultSFSlot = 10
|
||||||
|
)
|
||||||
|
return BloomRing{ss_bloomring.NewBloomRing(DefaultSFSlot, DefaultSFCapacity, DefaultSFFPR), &sync.Mutex{}}
|
||||||
|
}
|
@@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
const replayFilterCapacity = 100000
|
const replayFilterCapacity = 100000
|
||||||
|
|
||||||
// ReplayFilter check for replay attacks.
|
// ReplayFilter checks for replay attacks.
|
||||||
type ReplayFilter struct {
|
type ReplayFilter struct {
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
poolA *cuckoo.Filter
|
poolA *cuckoo.Filter
|
||||||
@@ -31,7 +31,7 @@ func (filter *ReplayFilter) Interval() int64 {
|
|||||||
return filter.interval
|
return filter.interval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check determine if there are duplicate records.
|
// Check determines if there are duplicate records.
|
||||||
func (filter *ReplayFilter) Check(sum []byte) bool {
|
func (filter *ReplayFilter) Check(sum []byte) bool {
|
||||||
filter.lock.Lock()
|
filter.lock.Lock()
|
||||||
defer filter.lock.Unlock()
|
defer filter.lock.Unlock()
|
||||||
|
@@ -18,10 +18,11 @@ var pool = bytespool.GetPool(Size)
|
|||||||
// the buffer into an internal buffer pool, in order to recreate a buffer more
|
// the buffer into an internal buffer pool, in order to recreate a buffer more
|
||||||
// quickly.
|
// quickly.
|
||||||
type Buffer struct {
|
type Buffer struct {
|
||||||
v []byte
|
v []byte
|
||||||
start int32
|
start int32
|
||||||
end int32
|
end int32
|
||||||
UDP *net.Destination
|
unmanaged bool
|
||||||
|
UDP *net.Destination
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a Buffer with 0 length and 8K capacity.
|
// New creates a Buffer with 0 length and 8K capacity.
|
||||||
@@ -38,6 +39,7 @@ func New() *Buffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewExisted creates a managed, standard size Buffer with an existed bytearray
|
||||||
func NewExisted(b []byte) *Buffer {
|
func NewExisted(b []byte) *Buffer {
|
||||||
if cap(b) < Size {
|
if cap(b) < Size {
|
||||||
panic("Invalid buffer")
|
panic("Invalid buffer")
|
||||||
@@ -54,6 +56,15 @@ func NewExisted(b []byte) *Buffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FromBytes creates a Buffer with an existed bytearray
|
||||||
|
func FromBytes(b []byte) *Buffer {
|
||||||
|
return &Buffer{
|
||||||
|
v: b,
|
||||||
|
end: int32(len(b)),
|
||||||
|
unmanaged: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// StackNew creates a new Buffer object on stack.
|
// StackNew creates a new Buffer object on stack.
|
||||||
// This method is for buffers that is released in the same function.
|
// This method is for buffers that is released in the same function.
|
||||||
func StackNew() Buffer {
|
func StackNew() Buffer {
|
||||||
@@ -71,7 +82,7 @@ func StackNew() Buffer {
|
|||||||
|
|
||||||
// Release recycles the buffer into an internal buffer pool.
|
// Release recycles the buffer into an internal buffer pool.
|
||||||
func (b *Buffer) Release() {
|
func (b *Buffer) Release() {
|
||||||
if b == nil || b.v == nil {
|
if b == nil || b.v == nil || b.unmanaged {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +160,19 @@ func (b *Buffer) BytesTo(to int32) []byte {
|
|||||||
return b.v[b.start : b.start+to]
|
return b.v[b.start : b.start+to]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check makes sure that 0 <= b.start <= b.end.
|
||||||
|
func (b *Buffer) Check() {
|
||||||
|
if b.start < 0 {
|
||||||
|
b.start = 0
|
||||||
|
}
|
||||||
|
if b.end < 0 {
|
||||||
|
b.end = 0
|
||||||
|
}
|
||||||
|
if b.start > b.end {
|
||||||
|
b.start = b.end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Resize cuts the buffer at the given position.
|
// Resize cuts the buffer at the given position.
|
||||||
func (b *Buffer) Resize(from, to int32) {
|
func (b *Buffer) Resize(from, to int32) {
|
||||||
if from < 0 {
|
if from < 0 {
|
||||||
@@ -162,6 +186,7 @@ func (b *Buffer) Resize(from, to int32) {
|
|||||||
}
|
}
|
||||||
b.end = b.start + to
|
b.end = b.start + to
|
||||||
b.start += from
|
b.start += from
|
||||||
|
b.Check()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance cuts the buffer at the given position.
|
// Advance cuts the buffer at the given position.
|
||||||
@@ -170,6 +195,7 @@ func (b *Buffer) Advance(from int32) {
|
|||||||
from += b.Len()
|
from += b.Len()
|
||||||
}
|
}
|
||||||
b.start += from
|
b.start += from
|
||||||
|
b.Check()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Len returns the length of the buffer content.
|
// Len returns the length of the buffer content.
|
||||||
@@ -212,6 +238,28 @@ func (b *Buffer) WriteString(s string) (int, error) {
|
|||||||
return b.Write([]byte(s))
|
return b.Write([]byte(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadByte implements io.ByteReader
|
||||||
|
func (b *Buffer) ReadByte() (byte, error) {
|
||||||
|
if b.start == b.end {
|
||||||
|
return 0, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
nb := b.v[b.start]
|
||||||
|
b.start++
|
||||||
|
return nb, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadBytes implements bufio.Reader.ReadBytes
|
||||||
|
func (b *Buffer) ReadBytes(length int32) ([]byte, error) {
|
||||||
|
if b.end-b.start < length {
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
nb := b.v[b.start : b.start+length]
|
||||||
|
b.start += length
|
||||||
|
return nb, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Read implements io.Reader.Read().
|
// Read implements io.Reader.Read().
|
||||||
func (b *Buffer) Read(data []byte) (int, error) {
|
func (b *Buffer) Read(data []byte) (int, error) {
|
||||||
if b.Len() == 0 {
|
if b.Len() == 0 {
|
||||||
|
@@ -6,7 +6,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
. "github.com/xtls/xray-core/common/buf"
|
. "github.com/xtls/xray-core/common/buf"
|
||||||
)
|
)
|
||||||
|
@@ -48,7 +48,7 @@ func (e readError) Error() string {
|
|||||||
return e.error.Error()
|
return e.error.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e readError) Inner() error {
|
func (e readError) Unwrap() error {
|
||||||
return e.error
|
return e.error
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ func (e writeError) Error() string {
|
|||||||
return e.error.Error()
|
return e.error.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e writeError) Inner() error {
|
func (e writeError) Unwrap() error {
|
||||||
return e.error
|
return e.error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,7 +6,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/testing/mocks"
|
"github.com/xtls/xray-core/testing/mocks"
|
||||||
|
@@ -53,7 +53,7 @@ func MergeBytes(dest MultiBuffer, src []byte) MultiBuffer {
|
|||||||
return dest
|
return dest
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReleaseMulti release all content of the MultiBuffer, and returns an empty MultiBuffer.
|
// ReleaseMulti releases all content of the MultiBuffer, and returns an empty MultiBuffer.
|
||||||
func ReleaseMulti(mb MultiBuffer) MultiBuffer {
|
func ReleaseMulti(mb MultiBuffer) MultiBuffer {
|
||||||
for i := range mb {
|
for i := range mb {
|
||||||
mb[i].Release()
|
mb[i].Release()
|
||||||
@@ -203,6 +203,19 @@ func SplitSize(mb MultiBuffer, size int32) (MultiBuffer, MultiBuffer) {
|
|||||||
return mb, r
|
return mb, r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SplitMulti splits the beginning of the MultiBuffer into first one, the index i and after into second one
|
||||||
|
func SplitMulti(mb MultiBuffer, i int) (MultiBuffer, MultiBuffer) {
|
||||||
|
mb2 := make(MultiBuffer, 0, len(mb))
|
||||||
|
if i < len(mb) && i >= 0 {
|
||||||
|
mb2 = append(mb2, mb[i:]...)
|
||||||
|
for j := i; j < len(mb); j++ {
|
||||||
|
mb[j] = nil
|
||||||
|
}
|
||||||
|
mb = mb[:i]
|
||||||
|
}
|
||||||
|
return mb, mb2
|
||||||
|
}
|
||||||
|
|
||||||
// WriteMultiBuffer writes all buffers from the MultiBuffer to the Writer one by one, and return error if any, with leftover MultiBuffer.
|
// WriteMultiBuffer writes all buffers from the MultiBuffer to the Writer one by one, and return error if any, with leftover MultiBuffer.
|
||||||
func WriteMultiBuffer(writer io.Writer, mb MultiBuffer) (MultiBuffer, error) {
|
func WriteMultiBuffer(writer io.Writer, mb MultiBuffer) (MultiBuffer, error) {
|
||||||
for {
|
for {
|
||||||
@@ -235,7 +248,7 @@ func (mb MultiBuffer) Len() int32 {
|
|||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty return true if the MultiBuffer has no content.
|
// IsEmpty returns true if the MultiBuffer has no content.
|
||||||
func (mb MultiBuffer) IsEmpty() bool {
|
func (mb MultiBuffer) IsEmpty() bool {
|
||||||
for _, b := range mb {
|
for _, b := range mb {
|
||||||
if !b.IsEmpty() {
|
if !b.IsEmpty() {
|
||||||
@@ -283,14 +296,14 @@ func (c *MultiBufferContainer) Write(b []byte) (int, error) {
|
|||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteMultiBuffer implement Writer.
|
// WriteMultiBuffer implements Writer.
|
||||||
func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error {
|
func (c *MultiBufferContainer) WriteMultiBuffer(b MultiBuffer) error {
|
||||||
mb, _ := MergeMulti(c.MultiBuffer, b)
|
mb, _ := MergeMulti(c.MultiBuffer, b)
|
||||||
c.MultiBuffer = mb
|
c.MultiBuffer = mb
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close implement io.Closer.
|
// Close implements io.Closer.
|
||||||
func (c *MultiBufferContainer) Close() error {
|
func (c *MultiBufferContainer) Close() error {
|
||||||
c.MultiBuffer = ReleaseMulti(c.MultiBuffer)
|
c.MultiBuffer = ReleaseMulti(c.MultiBuffer)
|
||||||
return nil
|
return nil
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user