mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-25 10:30:35 +00:00
Compare commits
177
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6534bbf4b2 | ||
|
|
c7672d004b | ||
|
|
1bdb488c9e | ||
|
|
d38ba9d507 | ||
|
|
9d9eaf399f | ||
|
|
eb32d166af | ||
|
|
1dbafe629a | ||
|
|
c42deab55c | ||
|
|
906d49a271 | ||
|
|
4192ca0827 | ||
|
|
228f1e13aa | ||
|
|
15968585f3 | ||
|
|
4951994ebe | ||
|
|
756a2d1327 | ||
|
|
b279076ba1 | ||
|
|
e61eeae258 | ||
|
|
958eb9ea8f | ||
|
|
8381a5a8a6 | ||
|
|
1ead940a71 | ||
|
|
bdff2fa72e | ||
|
|
1d62941bd2 | ||
|
|
52cf9ef5d6 | ||
|
|
16568314d8 | ||
|
|
1fc6850dc4 | ||
|
|
4e87f59628 | ||
|
|
7ab0a3ccb7 | ||
|
|
2fff03720d | ||
|
|
7f7fc5a829 | ||
|
|
ff6c060168 | ||
|
|
5b552db781 | ||
|
|
108bf7ff82 | ||
|
|
1836b1c6e4 | ||
|
|
b4f08981be | ||
|
|
cd4d0baacd | ||
|
|
3bc24a3d5d | ||
|
|
fa07b34956 | ||
|
|
85a8bf5f39 | ||
|
|
d0f533f94a | ||
|
|
d1db1d6a27 | ||
|
|
1a14ffcec6 | ||
|
|
454c930d13 | ||
|
|
bc590bcb56 | ||
|
|
7cf25970de | ||
|
|
d837687368 | ||
|
|
b4650360d6 | ||
|
|
d52f15060b | ||
|
|
31ab22c33d | ||
|
|
d42c981f9c | ||
|
|
cb1106c2fb | ||
|
|
df4b97097c | ||
|
|
a9cec25b8d | ||
|
|
c5edc122b7 | ||
|
|
9dd17d55fb | ||
|
|
310b764811 | ||
|
|
3691741440 | ||
|
|
05e259c8e4 | ||
|
|
175502d807 | ||
|
|
6780045550 | ||
|
|
ff6126463b | ||
|
|
5c3d639c09 | ||
|
|
7c56b7beea | ||
|
|
5b91b152bb | ||
|
|
ef77a42063 | ||
|
|
dab99614dc | ||
|
|
14e8ecfacf | ||
|
|
7094f8dc07 | ||
|
|
d342361c89 | ||
|
|
f17fabfff5 | ||
|
|
05a11910d4 | ||
|
|
82624bcaf0 | ||
|
|
e9f7d61c2e | ||
|
|
806b8dc27d | ||
|
|
f27edc3172 | ||
|
|
c93478b891 | ||
|
|
1642fdfbdd | ||
|
|
a91a88c7b2 | ||
|
|
32937846c5 | ||
|
|
93225a1132 | ||
|
|
4d958cbfd3 | ||
|
|
e5a9fb752e | ||
|
|
6a1a13b797 | ||
|
|
6c4008edad | ||
|
|
3f608b3a58 | ||
|
|
4c3020ca6f | ||
|
|
ba88aa173c | ||
|
|
08301e272c | ||
|
|
6eccc59728 | ||
|
|
1e89a8fd98 | ||
|
|
d2758a023c | ||
|
|
8aacdbd71b | ||
|
|
14524cc3b7 | ||
|
|
cb7bfeb54c | ||
|
|
d62f5cfb62 | ||
|
|
755f0a1d12 | ||
|
|
d8a8629a14 | ||
|
|
982c95d89a | ||
|
|
ae3ddd1c06 | ||
|
|
f926ee4aa0 | ||
|
|
67a71adad1 | ||
|
|
ce66db7032 | ||
|
|
7d93062f3d | ||
|
|
2320416ca3 | ||
|
|
e0ab00f6a8 | ||
|
|
157e65b34d | ||
|
|
c1b67a961e | ||
|
|
9e09399087 | ||
|
|
bb05684407 | ||
|
|
06dc4cf8bd | ||
|
|
35800e953e | ||
|
|
50fc324728 | ||
|
|
ec732b0b40 | ||
|
|
85f1234863 | ||
|
|
695a28c424 | ||
|
|
9fd3d9a1eb | ||
|
|
e86c365572 | ||
|
|
0321cdd0d2 | ||
|
|
766fa71eb1 | ||
|
|
01951163fd | ||
|
|
acb06e831b | ||
|
|
a204873d79 | ||
|
|
ea87941b77 | ||
|
|
88a2589498 | ||
|
|
5138ffcf22 | ||
|
|
0ac13bd910 | ||
|
|
eec280262d | ||
|
|
78fc2865ea | ||
|
|
ee8eb99bed | ||
|
|
52e4abd2ba | ||
|
|
1dbac90b22 | ||
|
|
0b8ec6804f | ||
|
|
9514e988d8 | ||
|
|
7dada1da2b | ||
|
|
0bffea3390 | ||
|
|
2805774f72 | ||
|
|
e6207e3a97 | ||
|
|
f0f765f9eb | ||
|
|
efdf21efb5 | ||
|
|
07374ae5a5 | ||
|
|
b6a7609c87 | ||
|
|
b43276c6d3 | ||
|
|
6a909b2507 | ||
|
|
7abad3fac0 | ||
|
|
1fe6d4a0f5 | ||
|
|
d100be5ad5 | ||
|
|
7dc3f87cd8 | ||
|
|
a079890ef0 | ||
|
|
fb0fa80c8c | ||
|
|
e3e7b28c08 | ||
|
|
12ee51e4bb | ||
|
|
957e5a6b15 | ||
|
|
0710c2b195 | ||
|
|
4632984b66 | ||
|
|
b7a22c729b | ||
|
|
8c3f246dcb | ||
|
|
888c0d2e1f | ||
|
|
74c726ff62 | ||
|
|
d14767d4f3 | ||
|
|
af2f0484b9 | ||
|
|
25d16914ff | ||
|
|
a6ec3b6e70 | ||
|
|
20cf00c271 | ||
|
|
c180c5980c | ||
|
|
5b849d51a9 | ||
|
|
61e1153157 | ||
|
|
afcfdbca70 | ||
|
|
2c92339f95 | ||
|
|
9c46a2d55a | ||
|
|
19186edfa1 | ||
|
|
f6a7e93923 | ||
|
|
077070dbe0 | ||
|
|
c3af657c0e | ||
|
|
9a04eecaf9 | ||
|
|
1951a278ac | ||
|
|
f1aee0b7c5 | ||
|
|
5173e5c15d | ||
|
|
daf9cba29f | ||
|
|
445c0d456c |
@@ -29,6 +29,5 @@
|
|||||||
"openbsd-arm7": { "friendlyName": "openbsd-arm32-v7a" },
|
"openbsd-arm7": { "friendlyName": "openbsd-arm32-v7a" },
|
||||||
"windows-386": { "friendlyName": "windows-32" },
|
"windows-386": { "friendlyName": "windows-32" },
|
||||||
"windows-amd64": { "friendlyName": "windows-64" },
|
"windows-amd64": { "friendlyName": "windows-64" },
|
||||||
"windows-arm64": { "friendlyName": "windows-arm64-v8a" },
|
"windows-arm64": { "friendlyName": "windows-arm64-v8a" }
|
||||||
"windows-arm7": { "friendlyName": "windows-arm32-v7a" }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,9 +32,12 @@ RUN echo '{}' >/tmp/usr/local/etc/xray/03_routing.json
|
|||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/04_policy.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/04_policy.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/05_inbounds.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/05_inbounds.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/06_outbounds.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/06_outbounds.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/07_transport.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/07_stats.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/08_stats.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/08_fakedns.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/09_reverse.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/09_metrics.json
|
||||||
|
RUN echo '{}' >/tmp/usr/local/etc/xray/10_observatory.json
|
||||||
|
RUN echo '{}' >/tmp/usr/local/etc/xray/11_geodata.json
|
||||||
|
RUN echo '{}' >/tmp/usr/local/etc/xray/99_version.json
|
||||||
|
|
||||||
# Create log files
|
# Create log files
|
||||||
RUN mkdir -p /tmp/var/log/xray && touch \
|
RUN mkdir -p /tmp/var/log/xray && touch \
|
||||||
@@ -45,8 +48,8 @@ RUN mkdir -p /tmp/var/log/xray && touch \
|
|||||||
FROM gcr.io/distroless/static:nonroot
|
FROM gcr.io/distroless/static:nonroot
|
||||||
|
|
||||||
COPY --from=build --chown=0:0 --chmod=755 /src/xray /usr/local/bin/xray
|
COPY --from=build --chown=0:0 --chmod=755 /src/xray /usr/local/bin/xray
|
||||||
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/share/xray
|
COPY --from=build --chown=65532:65532 --chmod=755 /tmp/empty /usr/local/share/xray
|
||||||
COPY --from=build --chown=0:0 --chmod=644 /tmp/geodat/*.dat /usr/local/share/xray/
|
COPY --from=build --chown=65532:65532 --chmod=644 /tmp/geodat/*.dat /usr/local/share/xray/
|
||||||
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/etc/xray
|
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/etc/xray
|
||||||
COPY --from=build --chown=0:0 --chmod=644 /tmp/usr/local/etc/xray/*.json /usr/local/etc/xray/
|
COPY --from=build --chown=0:0 --chmod=644 /tmp/usr/local/etc/xray/*.json /usr/local/etc/xray/
|
||||||
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /var/log/xray
|
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /var/log/xray
|
||||||
|
|||||||
@@ -32,9 +32,12 @@ RUN echo '{}' >/tmp/usr/local/etc/xray/03_routing.json
|
|||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/04_policy.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/04_policy.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/05_inbounds.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/05_inbounds.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/06_outbounds.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/06_outbounds.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/07_transport.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/07_stats.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/08_stats.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/08_fakedns.json
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/09_reverse.json
|
RUN echo '{}' >/tmp/usr/local/etc/xray/09_metrics.json
|
||||||
|
RUN echo '{}' >/tmp/usr/local/etc/xray/10_observatory.json
|
||||||
|
RUN echo '{}' >/tmp/usr/local/etc/xray/11_geodata.json
|
||||||
|
RUN echo '{}' >/tmp/usr/local/etc/xray/99_version.json
|
||||||
|
|
||||||
# Create log files
|
# Create log files
|
||||||
RUN mkdir -p /tmp/var/log/xray && touch \
|
RUN mkdir -p /tmp/var/log/xray && touch \
|
||||||
@@ -54,8 +57,8 @@ RUN mkdir -p /tmp/var/log/xray && touch \
|
|||||||
FROM --platform=linux/amd64 gcr.io/distroless/static:nonroot
|
FROM --platform=linux/amd64 gcr.io/distroless/static:nonroot
|
||||||
|
|
||||||
COPY --from=build --chown=0:0 --chmod=755 /src/xray /usr/local/bin/xray
|
COPY --from=build --chown=0:0 --chmod=755 /src/xray /usr/local/bin/xray
|
||||||
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/share/xray
|
COPY --from=build --chown=65532:65532 --chmod=755 /tmp/empty /usr/local/share/xray
|
||||||
COPY --from=build --chown=0:0 --chmod=644 /tmp/geodat/*.dat /usr/local/share/xray/
|
COPY --from=build --chown=65532:65532 --chmod=644 /tmp/geodat/*.dat /usr/local/share/xray/
|
||||||
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/etc/xray
|
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /usr/local/etc/xray
|
||||||
COPY --from=build --chown=0:0 --chmod=644 /tmp/usr/local/etc/xray/*.json /usr/local/etc/xray/
|
COPY --from=build --chown=0:0 --chmod=644 /tmp/usr/local/etc/xray/*.json /usr/local/etc/xray/
|
||||||
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /var/log/xray
|
COPY --from=build --chown=0:0 --chmod=755 /tmp/empty /var/log/xray
|
||||||
|
|||||||
@@ -68,13 +68,13 @@ jobs:
|
|||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v4
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v4
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v4
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
@@ -82,7 +82,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build Docker image (main architectures)
|
- name: Build Docker image (main architectures)
|
||||||
id: build_main_arches
|
id: build_main_arches
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: .github/docker/Dockerfile
|
file: .github/docker/Dockerfile
|
||||||
@@ -97,7 +97,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Build Docker image (additional architectures)
|
- name: Build Docker image (additional architectures)
|
||||||
id: build_additional_arches
|
id: build_additional_arches
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v7
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: .github/docker/Dockerfile.usa
|
file: .github/docker/Dockerfile.usa
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ jobs:
|
|||||||
file_glob: true
|
file_glob: true
|
||||||
|
|
||||||
- name: Upload files to Artifacts
|
- name: Upload files to Artifacts
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: Xray-${{ env.ASSET_NAME }}
|
name: Xray-${{ env.ASSET_NAME }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ jobs:
|
|||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
LIST=('amd64' 'x86' 'arm64' 'arm')
|
LIST=('amd64' 'x86' 'arm64')
|
||||||
for ARCHITECTURE in "${LIST[@]}"
|
for ARCHITECTURE in "${LIST[@]}"
|
||||||
do
|
do
|
||||||
echo -e "Checking wintun.dll for ${ARCHITECTURE}..."
|
echo -e "Checking wintun.dll for ${ARCHITECTURE}..."
|
||||||
@@ -55,7 +55,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Trigger Asset Update Workflow if Assets Missing
|
- name: Trigger Asset Update Workflow if Assets Missing
|
||||||
if: steps.check-assets.outputs.missing == 'true'
|
if: steps.check-assets.outputs.missing == 'true'
|
||||||
uses: actions/github-script@v8
|
uses: actions/github-script@v9
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
@@ -114,9 +114,6 @@ jobs:
|
|||||||
# Windows ARM
|
# Windows ARM
|
||||||
- goos: windows
|
- goos: windows
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
- goos: windows
|
|
||||||
goarch: arm
|
|
||||||
goarm: 7
|
|
||||||
# BEGIN Other architectures
|
# BEGIN Other architectures
|
||||||
# BEGIN riscv64 & ARM64 & LOONG64
|
# BEGIN riscv64 & ARM64 & LOONG64
|
||||||
- goos: linux
|
- goos: linux
|
||||||
@@ -250,9 +247,6 @@ jobs:
|
|||||||
if [[ ${GOARCH} == 'arm64' ]]; then
|
if [[ ${GOARCH} == 'arm64' ]]; then
|
||||||
mv resources/wintun/bin/arm64/wintun.dll build_assets/
|
mv resources/wintun/bin/arm64/wintun.dll build_assets/
|
||||||
fi
|
fi
|
||||||
if [[ ${GOARCH} == 'arm' ]]; then
|
|
||||||
mv resources/wintun/bin/arm/wintun.dll build_assets/
|
|
||||||
fi
|
|
||||||
mv resources/wintun/LICENSE.txt build_assets/LICENSE-wintun.txt
|
mv resources/wintun/LICENSE.txt build_assets/LICENSE-wintun.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -286,7 +280,7 @@ jobs:
|
|||||||
file_glob: true
|
file_glob: true
|
||||||
|
|
||||||
- name: Upload files to Artifacts
|
- name: Upload files to Artifacts
|
||||||
uses: actions/upload-artifact@v6
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: Xray-${{ env.ASSET_NAME }}
|
name: Xray-${{ env.ASSET_NAME }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Update Geodat
|
- name: Update Geodat
|
||||||
id: update
|
id: update
|
||||||
uses: nick-fields/retry@v3
|
uses: nick-fields/retry@v4
|
||||||
with:
|
with:
|
||||||
timeout_minutes: 60
|
timeout_minutes: 60
|
||||||
retry_wait_seconds: 60
|
retry_wait_seconds: 60
|
||||||
@@ -82,14 +82,14 @@ jobs:
|
|||||||
|
|
||||||
- name: Update Wintun
|
- name: Update Wintun
|
||||||
id: update
|
id: update
|
||||||
uses: nick-fields/retry@v3
|
uses: nick-fields/retry@v4
|
||||||
with:
|
with:
|
||||||
timeout_minutes: 60
|
timeout_minutes: 60
|
||||||
retry_wait_seconds: 60
|
retry_wait_seconds: 60
|
||||||
max_attempts: 60
|
max_attempts: 60
|
||||||
command: |
|
command: |
|
||||||
[ -d 'resources' ] || mkdir resources
|
[ -d 'resources' ] || mkdir resources
|
||||||
LIST=('amd64' 'x86' 'arm64' 'arm')
|
LIST=('amd64' 'x86' 'arm64')
|
||||||
for ARCHITECTURE in "${LIST[@]}"
|
for ARCHITECTURE in "${LIST[@]}"
|
||||||
do
|
do
|
||||||
FILE_PATH="resources/wintun/bin/${ARCHITECTURE}/wintun.dll"
|
FILE_PATH="resources/wintun/bin/${ARCHITECTURE}/wintun.dll"
|
||||||
|
|||||||
@@ -34,6 +34,22 @@ jobs:
|
|||||||
if: steps.check-assets.outputs.missing == 'true'
|
if: steps.check-assets.outputs.missing == 'true'
|
||||||
run: sleep 90
|
run: sleep 90
|
||||||
|
|
||||||
|
check-proto:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout codebase
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
- name: Check Proto Version Header
|
||||||
|
run: |
|
||||||
|
head -n 4 core/config.pb.go > ref.txt
|
||||||
|
find . -name "*.pb.go" ! -name "*_grpc.pb.go" -print0 | while IFS= read -r -d '' file; do
|
||||||
|
if ! cmp -s ref.txt <(head -n 4 "$file"); then
|
||||||
|
echo "Error: Header mismatch in $file"
|
||||||
|
head -n 4 "$file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
test:
|
test:
|
||||||
needs: check-assets
|
needs: check-assets
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
|
|
||||||
[](https://happ.su)
|
[](https://happ.su)
|
||||||
|
|
||||||
|
[](https://blanc.link/VMTSDqW)
|
||||||
|
|
||||||
[**Sponsor Xray-core**](https://github.com/XTLS/Xray-core/issues/3668)
|
[**Sponsor Xray-core**](https://github.com/XTLS/Xray-core/issues/3668)
|
||||||
|
|
||||||
## Donation & NFTs
|
## Donation & NFTs
|
||||||
@@ -65,6 +67,7 @@
|
|||||||
- [Marzban](https://github.com/Gozargah/Marzban)
|
- [Marzban](https://github.com/Gozargah/Marzban)
|
||||||
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
|
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
|
||||||
- [TX-UI](https://github.com/AghayeCoder/tx-ui)
|
- [TX-UI](https://github.com/AghayeCoder/tx-ui)
|
||||||
|
- [CELERITY](https://github.com/ClickDevTech/CELERITY-panel)
|
||||||
- One Click
|
- 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-REALITY](https://github.com/zxcvos/Xray-script), [xray-reality](https://github.com/sajjaddg/xray-reality), [reality-ezpz](https://github.com/aleskxyz/reality-ezpz)
|
||||||
- [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool), [VPainLess](https://github.com/vpainless/vpainless)
|
- [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool), [VPainLess](https://github.com/vpainless/vpainless)
|
||||||
@@ -106,16 +109,22 @@
|
|||||||
- [Furious](https://github.com/LorenEteval/Furious)
|
- [Furious](https://github.com/LorenEteval/Furious)
|
||||||
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
|
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
|
||||||
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||||
|
- [GenyConnect](https://github.com/genyleap/GenyConnect)
|
||||||
|
- [OneXray](https://github.com/OneXray/OneXray)
|
||||||
|
- [XrayUI-dev](https://github.com/PhoenixNil/XrayUI-dev)
|
||||||
- Android
|
- Android
|
||||||
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
||||||
- [X-flutter](https://github.com/XTLS/X-flutter)
|
- [X-flutter](https://github.com/XTLS/X-flutter)
|
||||||
- [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
|
- [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
|
||||||
- [SimpleXray](https://github.com/lhear/SimpleXray)
|
- [SimpleXray](https://github.com/lhear/SimpleXray)
|
||||||
|
- [XrayFA](https://github.com/Q7DF1/XrayFA)
|
||||||
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||||
|
- [OneXray](https://github.com/OneXray/OneXray)
|
||||||
- iOS & macOS arm64 & tvOS
|
- iOS & macOS arm64 & tvOS
|
||||||
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973) | [Happ tvOS](https://apps.apple.com/us/app/happ-proxy-utility-for-tv/id6748297274)
|
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973) | [Happ tvOS](https://apps.apple.com/us/app/happ-proxy-utility-for-tv/id6748297274)
|
||||||
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
||||||
- [OneXray](https://github.com/OneXray/OneXray)
|
- [OneXray](https://github.com/OneXray/OneXray)
|
||||||
|
- [INCY](https://apps.apple.com/en/app/incy/id6756943388)
|
||||||
- macOS arm64 & x64
|
- macOS arm64 & x64
|
||||||
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973)
|
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) | [Happ RU](https://apps.apple.com/ru/app/happ-proxy-utility-plus/id6746188973)
|
||||||
- [V2rayU](https://github.com/yanue/V2rayU)
|
- [V2rayU](https://github.com/yanue/V2rayU)
|
||||||
@@ -125,6 +134,8 @@
|
|||||||
- [GoXRay](https://github.com/goxray/desktop)
|
- [GoXRay](https://github.com/goxray/desktop)
|
||||||
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||||
- [v2rayN](https://github.com/2dust/v2rayN)
|
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
|
- [GenyConnect](https://github.com/genyleap/GenyConnect)
|
||||||
|
- [INCY](https://apps.apple.com/en/app/incy/id6756943388)
|
||||||
- Linux
|
- Linux
|
||||||
- [v2rayA](https://github.com/v2rayA/v2rayA)
|
- [v2rayA](https://github.com/v2rayA/v2rayA)
|
||||||
- [Furious](https://github.com/LorenEteval/Furious)
|
- [Furious](https://github.com/LorenEteval/Furious)
|
||||||
@@ -132,12 +143,17 @@
|
|||||||
- [GoXRay](https://github.com/goxray/desktop)
|
- [GoXRay](https://github.com/goxray/desktop)
|
||||||
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||||
- [v2rayN](https://github.com/2dust/v2rayN)
|
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
|
- [GenyConnect](https://github.com/genyleap/GenyConnect)
|
||||||
|
- [OneXray](https://github.com/OneXray/OneXray)
|
||||||
|
|
||||||
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
|
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
|
||||||
|
|
||||||
- iOS & macOS arm64 & tvOS
|
- iOS & macOS arm64 & tvOS
|
||||||
|
- [Anywhere](https://github.com/NodePassProject/Anywhere)
|
||||||
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
||||||
- [Loon](https://apps.apple.com/us/app/loon/id1373567447)
|
- [Loon](https://apps.apple.com/us/app/loon/id1373567447)
|
||||||
|
- [Egern](https://apps.apple.com/us/app/egern/id1616105820)
|
||||||
|
- [Quantumult X](https://apps.apple.com/us/app/quantumult-x/id1443988620)
|
||||||
- Xray Tools
|
- Xray Tools
|
||||||
- [xray-knife](https://github.com/lilendian0x00/xray-knife)
|
- [xray-knife](https://github.com/lilendian0x00/xray-knife)
|
||||||
- [xray-checker](https://github.com/kutovoys/xray-checker)
|
- [xray-checker](https://github.com/kutovoys/xray-checker)
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"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/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"
|
||||||
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -73,14 +75,27 @@ func (c *Commander) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if len(c.listen) > 0 {
|
if len(c.listen) > 0 {
|
||||||
if l, err := net.Listen("tcp", c.listen); err != nil {
|
var addr net.Addr
|
||||||
|
|
||||||
|
if strings.HasPrefix(c.listen, "/") || strings.HasPrefix(c.listen, "@") {
|
||||||
|
addr = &net.UnixAddr{Name: c.listen, Net: "unix"}
|
||||||
|
} else {
|
||||||
|
tcpAddr, err := net.ResolveTCPAddr("tcp", c.listen)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogErrorInner(context.Background(), err, "API server failed to parse listen address ", c.listen)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
addr = tcpAddr
|
||||||
|
}
|
||||||
|
l, err := internet.ListenSystem(context.Background(), addr, nil)
|
||||||
|
if err != nil {
|
||||||
errors.LogErrorInner(context.Background(), err, "API server failed to listen on ", c.listen)
|
errors.LogErrorInner(context.Background(), err, "API server failed to listen on ", c.listen)
|
||||||
return err
|
return err
|
||||||
} else {
|
|
||||||
errors.LogInfo(context.Background(), "API server listening on ", l.Addr())
|
|
||||||
go listen(l)
|
|
||||||
}
|
}
|
||||||
|
errors.LogInfo(context.Background(), "API server listening on ", l.Addr())
|
||||||
|
go listen(l)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+21
-35
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/commander/config.proto
|
// source: app/commander/config.proto
|
||||||
|
|
||||||
package commander
|
package commander
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -23,17 +24,16 @@ const (
|
|||||||
|
|
||||||
// Config is the settings for Commander.
|
// Config is the settings for Commander.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// Tag of the outbound handler that handles grpc connections.
|
// Tag of the outbound handler that handles grpc connections.
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
// Network address of commander grpc service.
|
// Network address of commander grpc service.
|
||||||
Listen string `protobuf:"bytes,3,opt,name=listen,proto3" json:"listen,omitempty"`
|
Listen string `protobuf:"bytes,3,opt,name=listen,proto3" json:"listen,omitempty"`
|
||||||
// Services that supported by this server. All services must implement Service
|
// Services that supported by this server. All services must implement Service
|
||||||
// interface.
|
// interface.
|
||||||
Service []*serial.TypedMessage `protobuf:"bytes,2,rep,name=service,proto3" json:"service,omitempty"`
|
Service []*serial.TypedMessage `protobuf:"bytes,2,rep,name=service,proto3" json:"service,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -89,9 +89,9 @@ func (x *Config) GetService() []*serial.TypedMessage {
|
|||||||
|
|
||||||
// ReflectionConfig is the placeholder config for ReflectionService.
|
// ReflectionConfig is the placeholder config for ReflectionService.
|
||||||
type ReflectionConfig struct {
|
type ReflectionConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReflectionConfig) Reset() {
|
func (x *ReflectionConfig) Reset() {
|
||||||
@@ -126,37 +126,24 @@ func (*ReflectionConfig) Descriptor() ([]byte, []int) {
|
|||||||
|
|
||||||
var File_app_commander_config_proto protoreflect.FileDescriptor
|
var File_app_commander_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_commander_config_proto_rawDesc = []byte{
|
const file_app_commander_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x1a, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x2f,
|
"\n" +
|
||||||
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x78, 0x72,
|
"\x1aapp/commander/config.proto\x12\x12xray.app.commander\x1a!common/serial/typed_message.proto\"n\n" +
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72,
|
"\x06Config\x12\x10\n" +
|
||||||
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x12\x16\n" +
|
||||||
0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72,
|
"\x06listen\x18\x03 \x01(\tR\x06listen\x12:\n" +
|
||||||
0x6f, 0x74, 0x6f, 0x22, 0x6e, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a,
|
"\aservice\x18\x02 \x03(\v2 .xray.common.serial.TypedMessageR\aservice\"\x12\n" +
|
||||||
0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12,
|
"\x10ReflectionConfigBX\n" +
|
||||||
0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
"\x16com.xray.app.commanderP\x01Z'github.com/xtls/xray-core/app/commander\xaa\x02\x12Xray.App.Commanderb\x06proto3"
|
||||||
0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x3a, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69,
|
|
||||||
0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 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, 0x07, 0x73, 0x65, 0x72, 0x76,
|
|
||||||
0x69, 0x63, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
|
|
||||||
0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
|
|
||||||
0x72, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
|
||||||
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61,
|
|
||||||
0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0xaa, 0x02, 0x12, 0x58,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
|
|
||||||
0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_commander_config_proto_rawDescOnce sync.Once
|
file_app_commander_config_proto_rawDescOnce sync.Once
|
||||||
file_app_commander_config_proto_rawDescData = file_app_commander_config_proto_rawDesc
|
file_app_commander_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_commander_config_proto_rawDescGZIP() []byte {
|
func file_app_commander_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_commander_config_proto_rawDescOnce.Do(func() {
|
file_app_commander_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_commander_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_commander_config_proto_rawDescData)
|
file_app_commander_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_commander_config_proto_rawDesc), len(file_app_commander_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_commander_config_proto_rawDescData
|
return file_app_commander_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -185,7 +172,7 @@ func file_app_commander_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_commander_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_commander_config_proto_rawDesc), len(file_app_commander_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 2,
|
NumMessages: 2,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -196,7 +183,6 @@ func file_app_commander_config_proto_init() {
|
|||||||
MessageInfos: file_app_commander_config_proto_msgTypes,
|
MessageInfos: file_app_commander_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_commander_config_proto = out.File
|
File_app_commander_config_proto = out.File
|
||||||
file_app_commander_config_proto_rawDesc = nil
|
|
||||||
file_app_commander_config_proto_goTypes = nil
|
file_app_commander_config_proto_goTypes = nil
|
||||||
file_app_commander_config_proto_depIdxs = nil
|
file_app_commander_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-30
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/dispatcher/config.proto
|
// source: app/dispatcher/config.proto
|
||||||
|
|
||||||
package dispatcher
|
package dispatcher
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,9 +22,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type SessionConfig struct {
|
type SessionConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SessionConfig) Reset() {
|
func (x *SessionConfig) Reset() {
|
||||||
@@ -57,11 +58,10 @@ func (*SessionConfig) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Settings *SessionConfig `protobuf:"bytes,1,opt,name=settings,proto3" json:"settings,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Settings *SessionConfig `protobuf:"bytes,1,opt,name=settings,proto3" json:"settings,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -103,33 +103,22 @@ func (x *Config) GetSettings() *SessionConfig {
|
|||||||
|
|
||||||
var File_app_dispatcher_config_proto protoreflect.FileDescriptor
|
var File_app_dispatcher_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_dispatcher_config_proto_rawDesc = []byte{
|
const file_app_dispatcher_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x1b, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
|
"\n" +
|
||||||
0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x78,
|
"\x1bapp/dispatcher/config.proto\x12\x13xray.app.dispatcher\"\x15\n" +
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68,
|
"\rSessionConfigJ\x04\b\x01\x10\x02\"H\n" +
|
||||||
0x65, 0x72, 0x22, 0x15, 0x0a, 0x0d, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e,
|
"\x06Config\x12>\n" +
|
||||||
0x66, 0x69, 0x67, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x22, 0x48, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
|
"\bsettings\x18\x01 \x01(\v2\".xray.app.dispatcher.SessionConfigR\bsettingsB[\n" +
|
||||||
0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
"\x17com.xray.app.dispatcherP\x01Z(github.com/xtls/xray-core/app/dispatcher\xaa\x02\x13Xray.App.Dispatcherb\x06proto3"
|
||||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
|
||||||
0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x73, 0x73,
|
|
||||||
0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69,
|
|
||||||
0x6e, 0x67, 0x73, 0x42, 0x5b, 0x0a, 0x17, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x50, 0x01,
|
|
||||||
0x5a, 0x28, 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,
|
|
||||||
0x64, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0xaa, 0x02, 0x13, 0x58, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x69, 0x73, 0x70, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72,
|
|
||||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_dispatcher_config_proto_rawDescOnce sync.Once
|
file_app_dispatcher_config_proto_rawDescOnce sync.Once
|
||||||
file_app_dispatcher_config_proto_rawDescData = file_app_dispatcher_config_proto_rawDesc
|
file_app_dispatcher_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_dispatcher_config_proto_rawDescGZIP() []byte {
|
func file_app_dispatcher_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_dispatcher_config_proto_rawDescOnce.Do(func() {
|
file_app_dispatcher_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_dispatcher_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_dispatcher_config_proto_rawDescData)
|
file_app_dispatcher_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_dispatcher_config_proto_rawDesc), len(file_app_dispatcher_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_dispatcher_config_proto_rawDescData
|
return file_app_dispatcher_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -157,7 +146,7 @@ func file_app_dispatcher_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_dispatcher_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_dispatcher_config_proto_rawDesc), len(file_app_dispatcher_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 2,
|
NumMessages: 2,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -168,7 +157,6 @@ func file_app_dispatcher_config_proto_init() {
|
|||||||
MessageInfos: file_app_dispatcher_config_proto_msgTypes,
|
MessageInfos: file_app_dispatcher_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_dispatcher_config_proto = out.File
|
File_app_dispatcher_config_proto = out.File
|
||||||
file_app_dispatcher_config_proto_rawDesc = nil
|
|
||||||
file_app_dispatcher_config_proto_goTypes = nil
|
file_app_dispatcher_config_proto_goTypes = nil
|
||||||
file_app_dispatcher_config_proto_depIdxs = nil
|
file_app_dispatcher_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-34
@@ -2,7 +2,6 @@ package dispatcher
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -181,15 +180,7 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
|
|||||||
}
|
}
|
||||||
|
|
||||||
if p.Stats.UserOnline {
|
if p.Stats.UserOnline {
|
||||||
name := "user>>>" + user.Email + ">>>online"
|
trackOnlineIP(ctx, d.stats, user.Email, sessionInbound.Source.Address.String())
|
||||||
if om, _ := stats.GetOrRegisterOnlineMap(d.stats, name); om != nil {
|
|
||||||
sessionInbounds := session.InboundFromContext(ctx)
|
|
||||||
userIP := sessionInbounds.Source.Address.String()
|
|
||||||
om.AddIP(userIP)
|
|
||||||
// log Online user with ips
|
|
||||||
// errors.LogDebug(ctx, "user>>>" + user.Email + ">>>online", om.Count(), om.List())
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,41 +214,31 @@ func WrapLink(ctx context.Context, policyManager policy.Manager, statsManager st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.Stats.UserOnline {
|
if p.Stats.UserOnline {
|
||||||
name := "user>>>" + user.Email + ">>>online"
|
trackOnlineIP(ctx, statsManager, user.Email, sessionInbound.Source.Address.String())
|
||||||
if om, _ := stats.GetOrRegisterOnlineMap(statsManager, name); om != nil {
|
|
||||||
sessionInbounds := session.InboundFromContext(ctx)
|
|
||||||
userIP := sessionInbounds.Source.Address.String()
|
|
||||||
om.AddIP(userIP)
|
|
||||||
// log Online user with ips
|
|
||||||
// errors.LogDebug(ctx, "user>>>" + user.Email + ">>>online", om.Count(), om.List())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return link
|
return link
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func trackOnlineIP(ctx context.Context, sm stats.Manager, email, ip string) {
|
||||||
|
name := "user>>>" + email + ">>>online"
|
||||||
|
if om, _ := stats.GetOrRegisterOnlineMap(sm, name); om != nil {
|
||||||
|
om.AddIP(ip)
|
||||||
|
context.AfterFunc(ctx, func() { om.RemoveIP(ip) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DefaultDispatcher) 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 == "" {
|
if domain == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, d := range request.ExcludeForDomain {
|
if request.ExcludeForDomain != nil && request.ExcludeForDomain.MatchAny(strings.ToLower(domain)) {
|
||||||
if strings.HasPrefix(d, "regexp:") {
|
return false
|
||||||
pattern := d[7:]
|
}
|
||||||
re, err := regexp.Compile(pattern)
|
if request.ExcludeForIP != nil && destination.Address.Family().IsIP() && request.ExcludeForIP.Match(destination.Address.IP()) {
|
||||||
if err != nil {
|
return false
|
||||||
errors.LogInfo(ctx, "Unable to compile regex")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if re.MatchString(domain) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if strings.ToLower(domain) == d {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
protocolString := result.Protocol()
|
protocolString := result.Protocol()
|
||||||
if resComp, ok := result.(SnifferResultComposite); ok {
|
if resComp, ok := result.(SnifferResultComposite); ok {
|
||||||
|
|||||||
+11
-35
@@ -2,48 +2,24 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"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/uuid"
|
"github.com/xtls/xray-core/common/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
var typeMap = map[DomainMatchingType]strmatcher.Type{
|
|
||||||
DomainMatchingType_Full: strmatcher.Full,
|
|
||||||
DomainMatchingType_Subdomain: strmatcher.Domain,
|
|
||||||
DomainMatchingType_Keyword: strmatcher.Substr,
|
|
||||||
DomainMatchingType_Regex: strmatcher.Regex,
|
|
||||||
}
|
|
||||||
|
|
||||||
// References:
|
// References:
|
||||||
// https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml
|
// https://www.iana.org/assignments/special-use-domain-names/special-use-domain-names.xhtml
|
||||||
// https://unix.stackexchange.com/questions/92441/whats-the-difference-between-local-home-and-lan
|
// https://unix.stackexchange.com/questions/92441/whats-the-difference-between-local-home-and-lan
|
||||||
var localTLDsAndDotlessDomains = []*NameServer_PriorityDomain{
|
var localTLDsAndDotlessDomainsRules = []*geodata.DomainRule{
|
||||||
{Type: DomainMatchingType_Regex, Domain: "^[^.]+$"}, // This will only match domains without any dot
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Regex, Value: "^[^.]+$"}}}, // This will only match domains without any dot
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "local"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "local"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "localdomain"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "localhost"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "localhost"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "lan"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "lan"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "home.arpa"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "home.arpa"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "example"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "example"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "invalid"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "invalid"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "test"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "test"}}},
|
||||||
}
|
|
||||||
|
|
||||||
var localTLDsAndDotlessDomainsRule = &NameServer_OriginalRule{
|
|
||||||
Rule: "geosite:private",
|
|
||||||
Size: uint32(len(localTLDsAndDotlessDomains)),
|
|
||||||
}
|
|
||||||
|
|
||||||
func toStrMatcher(t DomainMatchingType, domain string) (strmatcher.Matcher, error) {
|
|
||||||
strMType, f := typeMap[t]
|
|
||||||
if !f {
|
|
||||||
return nil, errors.New("unknown mapping type", t).AtWarning()
|
|
||||||
}
|
|
||||||
matcher, err := strMType.New(domain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to create str matcher").Base(err)
|
|
||||||
}
|
|
||||||
return matcher, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func toNetIP(addrs []net.Address) ([]net.IP, error) {
|
func toNetIP(addrs []net.Address) ([]net.IP, error) {
|
||||||
|
|||||||
+131
-379
@@ -1,18 +1,19 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/dns/config.proto
|
// source: app/dns/config.proto
|
||||||
|
|
||||||
package dns
|
package dns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
router "github.com/xtls/xray-core/app/router"
|
geodata "github.com/xtls/xray-core/common/geodata"
|
||||||
net "github.com/xtls/xray-core/common/net"
|
net "github.com/xtls/xray-core/common/net"
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -22,58 +23,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
type DomainMatchingType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
DomainMatchingType_Full DomainMatchingType = 0
|
|
||||||
DomainMatchingType_Subdomain DomainMatchingType = 1
|
|
||||||
DomainMatchingType_Keyword DomainMatchingType = 2
|
|
||||||
DomainMatchingType_Regex DomainMatchingType = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for DomainMatchingType.
|
|
||||||
var (
|
|
||||||
DomainMatchingType_name = map[int32]string{
|
|
||||||
0: "Full",
|
|
||||||
1: "Subdomain",
|
|
||||||
2: "Keyword",
|
|
||||||
3: "Regex",
|
|
||||||
}
|
|
||||||
DomainMatchingType_value = map[string]int32{
|
|
||||||
"Full": 0,
|
|
||||||
"Subdomain": 1,
|
|
||||||
"Keyword": 2,
|
|
||||||
"Regex": 3,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x DomainMatchingType) Enum() *DomainMatchingType {
|
|
||||||
p := new(DomainMatchingType)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x DomainMatchingType) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (DomainMatchingType) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_app_dns_config_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (DomainMatchingType) Type() protoreflect.EnumType {
|
|
||||||
return &file_app_dns_config_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x DomainMatchingType) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use DomainMatchingType.Descriptor instead.
|
|
||||||
func (DomainMatchingType) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type QueryStrategy int32
|
type QueryStrategy int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -110,11 +59,11 @@ func (x QueryStrategy) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (QueryStrategy) Descriptor() protoreflect.EnumDescriptor {
|
func (QueryStrategy) Descriptor() protoreflect.EnumDescriptor {
|
||||||
return file_app_dns_config_proto_enumTypes[1].Descriptor()
|
return file_app_dns_config_proto_enumTypes[0].Descriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (QueryStrategy) Type() protoreflect.EnumType {
|
func (QueryStrategy) Type() protoreflect.EnumType {
|
||||||
return &file_app_dns_config_proto_enumTypes[1]
|
return &file_app_dns_config_proto_enumTypes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x QueryStrategy) Number() protoreflect.EnumNumber {
|
func (x QueryStrategy) Number() protoreflect.EnumNumber {
|
||||||
@@ -123,31 +72,29 @@ func (x QueryStrategy) Number() protoreflect.EnumNumber {
|
|||||||
|
|
||||||
// Deprecated: Use QueryStrategy.Descriptor instead.
|
// Deprecated: Use QueryStrategy.Descriptor instead.
|
||||||
func (QueryStrategy) EnumDescriptor() ([]byte, []int) {
|
func (QueryStrategy) EnumDescriptor() ([]byte, []int) {
|
||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{1}
|
return file_app_dns_config_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
type NameServer struct {
|
type NameServer struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
|
||||||
|
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
|
||||||
Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
Domain []*geodata.DomainRule `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
||||||
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
|
ExpectedIp []*geodata.IPRule `protobuf:"bytes,3,rep,name=expected_ip,json=expectedIp,proto3" json:"expected_ip,omitempty"`
|
||||||
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
|
QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
||||||
PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
|
ActPrior bool `protobuf:"varint,8,opt,name=actPrior,proto3" json:"actPrior,omitempty"`
|
||||||
ExpectedGeoip []*router.GeoIP `protobuf:"bytes,3,rep,name=expected_geoip,json=expectedGeoip,proto3" json:"expected_geoip,omitempty"`
|
Tag string `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
|
TimeoutMs uint64 `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
|
||||||
QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
DisableCache *bool `protobuf:"varint,11,opt,name=disableCache,proto3,oneof" json:"disableCache,omitempty"`
|
||||||
ActPrior bool `protobuf:"varint,8,opt,name=actPrior,proto3" json:"actPrior,omitempty"`
|
ServeStale *bool `protobuf:"varint,15,opt,name=serveStale,proto3,oneof" json:"serveStale,omitempty"`
|
||||||
Tag string `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
|
ServeExpiredTTL *uint32 `protobuf:"varint,16,opt,name=serveExpiredTTL,proto3,oneof" json:"serveExpiredTTL,omitempty"`
|
||||||
TimeoutMs uint64 `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
|
FinalQuery bool `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
|
||||||
DisableCache *bool `protobuf:"varint,11,opt,name=disableCache,proto3,oneof" json:"disableCache,omitempty"`
|
UnexpectedIp []*geodata.IPRule `protobuf:"bytes,13,rep,name=unexpected_ip,json=unexpectedIp,proto3" json:"unexpected_ip,omitempty"`
|
||||||
ServeStale *bool `protobuf:"varint,15,opt,name=serveStale,proto3,oneof" json:"serveStale,omitempty"`
|
ActUnprior bool `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
|
||||||
ServeExpiredTTL *uint32 `protobuf:"varint,16,opt,name=serveExpiredTTL,proto3,oneof" json:"serveExpiredTTL,omitempty"`
|
PolicyID uint32 `protobuf:"varint,17,opt,name=policyID,proto3" json:"policyID,omitempty"`
|
||||||
FinalQuery bool `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
|
unknownFields protoimpl.UnknownFields
|
||||||
UnexpectedGeoip []*router.GeoIP `protobuf:"bytes,13,rep,name=unexpected_geoip,json=unexpectedGeoip,proto3" json:"unexpected_geoip,omitempty"`
|
sizeCache protoimpl.SizeCache
|
||||||
ActUnprior bool `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
|
|
||||||
PolicyID uint32 `protobuf:"varint,17,opt,name=policyID,proto3" json:"policyID,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) Reset() {
|
func (x *NameServer) Reset() {
|
||||||
@@ -201,23 +148,16 @@ func (x *NameServer) GetSkipFallback() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
|
func (x *NameServer) GetDomain() []*geodata.DomainRule {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.PrioritizedDomain
|
return x.Domain
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
|
func (x *NameServer) GetExpectedIp() []*geodata.IPRule {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ExpectedGeoip
|
return x.ExpectedIp
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetOriginalRules() []*NameServer_OriginalRule {
|
|
||||||
if x != nil {
|
|
||||||
return x.OriginalRules
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -278,9 +218,9 @@ func (x *NameServer) GetFinalQuery() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetUnexpectedGeoip() []*router.GeoIP {
|
func (x *NameServer) GetUnexpectedIp() []*geodata.IPRule {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.UnexpectedGeoip
|
return x.UnexpectedIp
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -300,10 +240,7 @@ func (x *NameServer) GetPolicyID() uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// NameServer list used by this DNS client.
|
// NameServer list used by this DNS client.
|
||||||
// A special value 'localhost' as a domain address can be set to use DNS on local system.
|
// A special value 'localhost' as a domain address can be set to use DNS on local system.
|
||||||
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"`
|
||||||
@@ -321,6 +258,8 @@ type Config struct {
|
|||||||
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
|
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
|
||||||
DisableFallbackIfMatch bool `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
|
DisableFallbackIfMatch bool `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
|
||||||
EnableParallelQuery bool `protobuf:"varint,14,opt,name=enableParallelQuery,proto3" json:"enableParallelQuery,omitempty"`
|
EnableParallelQuery bool `protobuf:"varint,14,opt,name=enableParallelQuery,proto3" json:"enableParallelQuery,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -430,128 +369,20 @@ func (x *Config) GetEnableParallelQuery() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
type NameServer_PriorityDomain struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Type DomainMatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
|
|
||||||
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer_PriorityDomain) Reset() {
|
|
||||||
*x = NameServer_PriorityDomain{}
|
|
||||||
mi := &file_app_dns_config_proto_msgTypes[2]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer_PriorityDomain) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*NameServer_PriorityDomain) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *NameServer_PriorityDomain) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_dns_config_proto_msgTypes[2]
|
|
||||||
if x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use NameServer_PriorityDomain.ProtoReflect.Descriptor instead.
|
|
||||||
func (*NameServer_PriorityDomain) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer_PriorityDomain) GetType() DomainMatchingType {
|
|
||||||
if x != nil {
|
|
||||||
return x.Type
|
|
||||||
}
|
|
||||||
return DomainMatchingType_Full
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer_PriorityDomain) GetDomain() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Domain
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type NameServer_OriginalRule struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Rule string `protobuf:"bytes,1,opt,name=rule,proto3" json:"rule,omitempty"`
|
|
||||||
Size uint32 `protobuf:"varint,2,opt,name=size,proto3" json:"size,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer_OriginalRule) Reset() {
|
|
||||||
*x = NameServer_OriginalRule{}
|
|
||||||
mi := &file_app_dns_config_proto_msgTypes[3]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer_OriginalRule) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*NameServer_OriginalRule) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *NameServer_OriginalRule) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_dns_config_proto_msgTypes[3]
|
|
||||||
if x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use NameServer_OriginalRule.ProtoReflect.Descriptor instead.
|
|
||||||
func (*NameServer_OriginalRule) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{0, 1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer_OriginalRule) GetRule() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Rule
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer_OriginalRule) GetSize() uint32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Size
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config_HostMapping struct {
|
type Config_HostMapping struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Domain *geodata.DomainRule `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
Ip [][]byte `protobuf:"bytes,3,rep,name=ip,proto3" json:"ip,omitempty"`
|
||||||
|
|
||||||
Type DomainMatchingType `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.dns.DomainMatchingType" json:"type,omitempty"`
|
|
||||||
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
|
||||||
Ip [][]byte `protobuf:"bytes,3,rep,name=ip,proto3" json:"ip,omitempty"`
|
|
||||||
// ProxiedDomain indicates the mapped domain has the same IP address on this
|
// ProxiedDomain indicates the mapped domain has the same IP address on this
|
||||||
// domain. Xray will use this domain for IP queries.
|
// domain. Xray will use this domain for IP queries.
|
||||||
ProxiedDomain string `protobuf:"bytes,4,opt,name=proxied_domain,json=proxiedDomain,proto3" json:"proxied_domain,omitempty"`
|
ProxiedDomain string `protobuf:"bytes,4,opt,name=proxied_domain,json=proxiedDomain,proto3" json:"proxied_domain,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config_HostMapping) Reset() {
|
func (x *Config_HostMapping) Reset() {
|
||||||
*x = Config_HostMapping{}
|
*x = Config_HostMapping{}
|
||||||
mi := &file_app_dns_config_proto_msgTypes[4]
|
mi := &file_app_dns_config_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -563,7 +394,7 @@ func (x *Config_HostMapping) String() string {
|
|||||||
func (*Config_HostMapping) ProtoMessage() {}
|
func (*Config_HostMapping) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
|
func (x *Config_HostMapping) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_dns_config_proto_msgTypes[4]
|
mi := &file_app_dns_config_proto_msgTypes[2]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -579,18 +410,11 @@ func (*Config_HostMapping) Descriptor() ([]byte, []int) {
|
|||||||
return file_app_dns_config_proto_rawDescGZIP(), []int{1, 0}
|
return file_app_dns_config_proto_rawDescGZIP(), []int{1, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config_HostMapping) GetType() DomainMatchingType {
|
func (x *Config_HostMapping) GetDomain() *geodata.DomainRule {
|
||||||
if x != nil {
|
|
||||||
return x.Type
|
|
||||||
}
|
|
||||||
return DomainMatchingType_Full
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Config_HostMapping) GetDomain() string {
|
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Domain
|
return x.Domain
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config_HostMapping) GetIp() [][]byte {
|
func (x *Config_HostMapping) GetIp() [][]byte {
|
||||||
@@ -609,175 +433,104 @@ func (x *Config_HostMapping) GetProxiedDomain() string {
|
|||||||
|
|
||||||
var File_app_dns_config_proto protoreflect.FileDescriptor
|
var File_app_dns_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_dns_config_proto_rawDesc = []byte{
|
const file_app_dns_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
"\n" +
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
"\x14app/dns/config.proto\x12\fxray.app.dns\x1a\x1ccommon/net/destination.proto\x1a\x1bcommon/geodata/geodat.proto\"\xde\x05\n" +
|
||||||
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
"\n" +
|
||||||
0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
"NameServer\x123\n" +
|
||||||
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
"\aaddress\x18\x01 \x01(\v2\x19.xray.common.net.EndpointR\aaddress\x12\x1b\n" +
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdf, 0x07, 0x0a, 0x0a,
|
"\tclient_ip\x18\x05 \x01(\fR\bclientIp\x12\"\n" +
|
||||||
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
|
"\fskipFallback\x18\x06 \x01(\bR\fskipFallback\x127\n" +
|
||||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
"\x06domain\x18\x02 \x03(\v2\x1f.xray.common.geodata.DomainRuleR\x06domain\x12<\n" +
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
"\vexpected_ip\x18\x03 \x03(\v2\x1b.xray.common.geodata.IPRuleR\n" +
|
||||||
0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12,
|
"expectedIp\x12B\n" +
|
||||||
0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x05, 0x20, 0x01,
|
"\x0equery_strategy\x18\a \x01(\x0e2\x1b.xray.app.dns.QueryStrategyR\rqueryStrategy\x12\x1a\n" +
|
||||||
0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x22, 0x0a, 0x0c,
|
"\bactPrior\x18\b \x01(\bR\bactPrior\x12\x10\n" +
|
||||||
0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x06, 0x20, 0x01,
|
"\x03tag\x18\t \x01(\tR\x03tag\x12\x1c\n" +
|
||||||
0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
"\ttimeoutMs\x18\n" +
|
||||||
0x12, 0x56, 0x0a, 0x12, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x64, 0x5f,
|
" \x01(\x04R\ttimeoutMs\x12'\n" +
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78,
|
"\fdisableCache\x18\v \x01(\bH\x00R\fdisableCache\x88\x01\x01\x12#\n" +
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65,
|
"\n" +
|
||||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44,
|
"serveStale\x18\x0f \x01(\bH\x01R\n" +
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a,
|
"serveStale\x88\x01\x01\x12-\n" +
|
||||||
0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x65,
|
"\x0fserveExpiredTTL\x18\x10 \x01(\rH\x02R\x0fserveExpiredTTL\x88\x01\x01\x12\x1e\n" +
|
||||||
0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
|
"\n" +
|
||||||
0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
"finalQuery\x18\f \x01(\bR\n" +
|
||||||
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
|
"finalQuery\x12@\n" +
|
||||||
0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69,
|
"\runexpected_ip\x18\r \x03(\v2\x1b.xray.common.geodata.IPRuleR\funexpectedIp\x12\x1e\n" +
|
||||||
0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
"\n" +
|
||||||
0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e,
|
"actUnprior\x18\x0e \x01(\bR\n" +
|
||||||
0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
|
"actUnprior\x12\x1a\n" +
|
||||||
0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
|
"\bpolicyID\x18\x11 \x01(\rR\bpolicyIDB\x0f\n" +
|
||||||
0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73,
|
"\r_disableCacheB\r\n" +
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,
|
"\v_serveStaleB\x12\n" +
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65,
|
"\x10_serveExpiredTTLJ\x04\b\x04\x10\x05\"\x82\x05\n" +
|
||||||
0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72,
|
"\x06Config\x129\n" +
|
||||||
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x74,
|
"\vname_server\x18\x05 \x03(\v2\x18.xray.app.dns.NameServerR\n" +
|
||||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x74,
|
"nameServer\x12\x1b\n" +
|
||||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x09, 0x20, 0x01,
|
"\tclient_ip\x18\x03 \x01(\fR\bclientIp\x12C\n" +
|
||||||
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f,
|
"\fstatic_hosts\x18\x04 \x03(\v2 .xray.app.dns.Config.HostMappingR\vstaticHosts\x12\x10\n" +
|
||||||
0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
"\x03tag\x18\x06 \x01(\tR\x03tag\x12\"\n" +
|
||||||
0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
"\fdisableCache\x18\b \x01(\bR\fdisableCache\x12\x1e\n" +
|
||||||
0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0c, 0x64,
|
"\n" +
|
||||||
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x88, 0x01, 0x01, 0x12, 0x23,
|
"serveStale\x18\f \x01(\bR\n" +
|
||||||
0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x01,
|
"serveStale\x12(\n" +
|
||||||
0x28, 0x08, 0x48, 0x01, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65,
|
"\x0fserveExpiredTTL\x18\r \x01(\rR\x0fserveExpiredTTL\x12B\n" +
|
||||||
0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69,
|
"\x0equery_strategy\x18\t \x01(\x0e2\x1b.xray.app.dns.QueryStrategyR\rqueryStrategy\x12(\n" +
|
||||||
0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x02, 0x52, 0x0f,
|
"\x0fdisableFallback\x18\n" +
|
||||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x88,
|
" \x01(\bR\x0fdisableFallback\x126\n" +
|
||||||
0x01, 0x01, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79,
|
"\x16disableFallbackIfMatch\x18\v \x01(\bR\x16disableFallbackIfMatch\x120\n" +
|
||||||
0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65,
|
"\x13enableParallelQuery\x18\x0e \x01(\bR\x13enableParallelQuery\x1a}\n" +
|
||||||
0x72, 0x79, 0x12, 0x41, 0x0a, 0x10, 0x75, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
|
"\vHostMapping\x127\n" +
|
||||||
0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78,
|
"\x06domain\x18\x02 \x01(\v2\x1f.xray.common.geodata.DomainRuleR\x06domain\x12\x0e\n" +
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47,
|
"\x02ip\x18\x03 \x03(\fR\x02ip\x12%\n" +
|
||||||
0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
|
"\x0eproxied_domain\x18\x04 \x01(\tR\rproxiedDomainJ\x04\b\a\x10\b*B\n" +
|
||||||
0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72,
|
"\rQueryStrategy\x12\n" +
|
||||||
0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e,
|
"\n" +
|
||||||
0x70, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49,
|
"\x06USE_IP\x10\x00\x12\v\n" +
|
||||||
0x44, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49,
|
"\aUSE_IP4\x10\x01\x12\v\n" +
|
||||||
0x44, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d,
|
"\aUSE_IP6\x10\x02\x12\v\n" +
|
||||||
0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
"\aUSE_SYS\x10\x03BF\n" +
|
||||||
0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73,
|
"\x10com.xray.app.dnsP\x01Z!github.com/xtls/xray-core/app/dns\xaa\x02\fXray.App.Dnsb\x06proto3"
|
||||||
0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54,
|
|
||||||
0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d,
|
|
||||||
0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
|
||||||
0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c,
|
|
||||||
0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
|
||||||
0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20,
|
|
||||||
0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x64, 0x69,
|
|
||||||
0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x73,
|
|
||||||
0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65,
|
|
||||||
0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x22, 0x98, 0x05,
|
|
||||||
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65,
|
|
||||||
0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e,
|
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d,
|
|
||||||
0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
|
|
||||||
0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70,
|
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70,
|
|
||||||
0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73,
|
|
||||||
0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
|
||||||
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73,
|
|
||||||
0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63,
|
|
||||||
0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01,
|
|
||||||
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62,
|
|
||||||
0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64,
|
|
||||||
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73,
|
|
||||||
0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52,
|
|
||||||
0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73,
|
|
||||||
0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x0d,
|
|
||||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72,
|
|
||||||
0x65, 0x64, 0x54, 0x54, 0x4c, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73,
|
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,
|
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65,
|
|
||||||
0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72,
|
|
||||||
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73,
|
|
||||||
0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01,
|
|
||||||
0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62,
|
|
||||||
0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61,
|
|
||||||
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20,
|
|
||||||
0x01, 0x28, 0x08, 0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c,
|
|
||||||
0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x30, 0x0a, 0x13, 0x65,
|
|
||||||
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x51, 0x75, 0x65,
|
|
||||||
0x72, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
|
||||||
0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x92, 0x01,
|
|
||||||
0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a,
|
|
||||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
|
||||||
0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
|
|
||||||
0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
|
||||||
0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70,
|
|
||||||
0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61,
|
|
||||||
0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61,
|
|
||||||
0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08,
|
|
||||||
0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64,
|
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f,
|
|
||||||
0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a,
|
|
||||||
0x42, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
|
||||||
0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07,
|
|
||||||
0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45,
|
|
||||||
0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x53, 0x59,
|
|
||||||
0x53, 0x10, 0x03, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 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, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_dns_config_proto_rawDescOnce sync.Once
|
file_app_dns_config_proto_rawDescOnce sync.Once
|
||||||
file_app_dns_config_proto_rawDescData = file_app_dns_config_proto_rawDesc
|
file_app_dns_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_dns_config_proto_rawDescGZIP() []byte {
|
func file_app_dns_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_dns_config_proto_rawDescOnce.Do(func() {
|
file_app_dns_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_dns_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_dns_config_proto_rawDescData)
|
file_app_dns_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_dns_config_proto_rawDesc), len(file_app_dns_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_dns_config_proto_rawDescData
|
return file_app_dns_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_app_dns_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
var file_app_dns_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||||
var file_app_dns_config_proto_goTypes = []any{
|
var file_app_dns_config_proto_goTypes = []any{
|
||||||
(DomainMatchingType)(0), // 0: xray.app.dns.DomainMatchingType
|
(QueryStrategy)(0), // 0: xray.app.dns.QueryStrategy
|
||||||
(QueryStrategy)(0), // 1: xray.app.dns.QueryStrategy
|
(*NameServer)(nil), // 1: xray.app.dns.NameServer
|
||||||
(*NameServer)(nil), // 2: xray.app.dns.NameServer
|
(*Config)(nil), // 2: xray.app.dns.Config
|
||||||
(*Config)(nil), // 3: xray.app.dns.Config
|
(*Config_HostMapping)(nil), // 3: xray.app.dns.Config.HostMapping
|
||||||
(*NameServer_PriorityDomain)(nil), // 4: xray.app.dns.NameServer.PriorityDomain
|
(*net.Endpoint)(nil), // 4: xray.common.net.Endpoint
|
||||||
(*NameServer_OriginalRule)(nil), // 5: xray.app.dns.NameServer.OriginalRule
|
(*geodata.DomainRule)(nil), // 5: xray.common.geodata.DomainRule
|
||||||
(*Config_HostMapping)(nil), // 6: xray.app.dns.Config.HostMapping
|
(*geodata.IPRule)(nil), // 6: xray.common.geodata.IPRule
|
||||||
(*net.Endpoint)(nil), // 7: xray.common.net.Endpoint
|
|
||||||
(*router.GeoIP)(nil), // 8: xray.app.router.GeoIP
|
|
||||||
}
|
}
|
||||||
var file_app_dns_config_proto_depIdxs = []int32{
|
var file_app_dns_config_proto_depIdxs = []int32{
|
||||||
7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
|
4, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
|
||||||
4, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
|
5, // 1: xray.app.dns.NameServer.domain:type_name -> xray.common.geodata.DomainRule
|
||||||
8, // 2: xray.app.dns.NameServer.expected_geoip:type_name -> xray.app.router.GeoIP
|
6, // 2: xray.app.dns.NameServer.expected_ip:type_name -> xray.common.geodata.IPRule
|
||||||
5, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
|
0, // 3: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
||||||
1, // 4: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
6, // 4: xray.app.dns.NameServer.unexpected_ip:type_name -> xray.common.geodata.IPRule
|
||||||
8, // 5: xray.app.dns.NameServer.unexpected_geoip:type_name -> xray.app.router.GeoIP
|
1, // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
|
||||||
2, // 6: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
|
3, // 6: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
|
||||||
6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
|
0, // 7: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
||||||
1, // 8: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
5, // 8: xray.app.dns.Config.HostMapping.domain:type_name -> xray.common.geodata.DomainRule
|
||||||
0, // 9: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
|
9, // [9:9] is the sub-list for method output_type
|
||||||
0, // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
|
9, // [9:9] is the sub-list for method input_type
|
||||||
11, // [11:11] is the sub-list for method output_type
|
9, // [9:9] is the sub-list for extension type_name
|
||||||
11, // [11:11] is the sub-list for method input_type
|
9, // [9:9] is the sub-list for extension extendee
|
||||||
11, // [11:11] is the sub-list for extension type_name
|
0, // [0:9] is the sub-list for field type_name
|
||||||
11, // [11:11] is the sub-list for extension extendee
|
|
||||||
0, // [0:11] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_dns_config_proto_init() }
|
func init() { file_app_dns_config_proto_init() }
|
||||||
@@ -790,9 +543,9 @@ func file_app_dns_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_dns_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_dns_config_proto_rawDesc), len(file_app_dns_config_proto_rawDesc)),
|
||||||
NumEnums: 2,
|
NumEnums: 1,
|
||||||
NumMessages: 5,
|
NumMessages: 3,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
@@ -802,7 +555,6 @@ func file_app_dns_config_proto_init() {
|
|||||||
MessageInfos: file_app_dns_config_proto_msgTypes,
|
MessageInfos: file_app_dns_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_dns_config_proto = out.File
|
File_app_dns_config_proto = out.File
|
||||||
file_app_dns_config_proto_rawDesc = nil
|
|
||||||
file_app_dns_config_proto_goTypes = nil
|
file_app_dns_config_proto_goTypes = nil
|
||||||
file_app_dns_config_proto_depIdxs = nil
|
file_app_dns_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-25
@@ -7,26 +7,15 @@ option java_package = "com.xray.app.dns";
|
|||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
|
|
||||||
import "common/net/destination.proto";
|
import "common/net/destination.proto";
|
||||||
import "app/router/config.proto";
|
import "common/geodata/geodat.proto";
|
||||||
|
|
||||||
message NameServer {
|
message NameServer {
|
||||||
xray.common.net.Endpoint address = 1;
|
xray.common.net.Endpoint address = 1;
|
||||||
bytes client_ip = 5;
|
bytes client_ip = 5;
|
||||||
bool skipFallback = 6;
|
bool skipFallback = 6;
|
||||||
|
repeated xray.common.geodata.DomainRule domain = 2;
|
||||||
message PriorityDomain {
|
repeated xray.common.geodata.IPRule expected_ip = 3;
|
||||||
DomainMatchingType type = 1;
|
reserved 4;
|
||||||
string domain = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message OriginalRule {
|
|
||||||
string rule = 1;
|
|
||||||
uint32 size = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
repeated PriorityDomain prioritized_domain = 2;
|
|
||||||
repeated xray.app.router.GeoIP expected_geoip = 3;
|
|
||||||
repeated OriginalRule original_rules = 4;
|
|
||||||
QueryStrategy query_strategy = 7;
|
QueryStrategy query_strategy = 7;
|
||||||
bool actPrior = 8;
|
bool actPrior = 8;
|
||||||
string tag = 9;
|
string tag = 9;
|
||||||
@@ -35,18 +24,11 @@ message NameServer {
|
|||||||
optional bool serveStale = 15;
|
optional bool serveStale = 15;
|
||||||
optional uint32 serveExpiredTTL = 16;
|
optional uint32 serveExpiredTTL = 16;
|
||||||
bool finalQuery = 12;
|
bool finalQuery = 12;
|
||||||
repeated xray.app.router.GeoIP unexpected_geoip = 13;
|
repeated xray.common.geodata.IPRule unexpected_ip = 13;
|
||||||
bool actUnprior = 14;
|
bool actUnprior = 14;
|
||||||
uint32 policyID = 17;
|
uint32 policyID = 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DomainMatchingType {
|
|
||||||
Full = 0;
|
|
||||||
Subdomain = 1;
|
|
||||||
Keyword = 2;
|
|
||||||
Regex = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum QueryStrategy {
|
enum QueryStrategy {
|
||||||
USE_IP = 0;
|
USE_IP = 0;
|
||||||
USE_IP4 = 1;
|
USE_IP4 = 1;
|
||||||
@@ -64,8 +46,7 @@ message Config {
|
|||||||
bytes client_ip = 3;
|
bytes client_ip = 3;
|
||||||
|
|
||||||
message HostMapping {
|
message HostMapping {
|
||||||
DomainMatchingType type = 1;
|
xray.common.geodata.DomainRule domain = 2;
|
||||||
string domain = 2;
|
|
||||||
|
|
||||||
repeated bytes ip = 3;
|
repeated bytes ip = 3;
|
||||||
|
|
||||||
|
|||||||
+70
-113
@@ -5,18 +5,16 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
go_errors "errors"
|
go_errors "errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/common/strmatcher"
|
"github.com/xtls/xray-core/common/utils"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,15 +28,15 @@ type DNS struct {
|
|||||||
hosts *StaticHosts
|
hosts *StaticHosts
|
||||||
clients []*Client
|
clients []*Client
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
domainMatcher strmatcher.IndexMatcher
|
domainMatcher geodata.DomainMatcher
|
||||||
matcherInfos []*DomainMatcherInfo
|
matcherInfos []*DomainMatcherInfo
|
||||||
checkSystem bool
|
checkSystem bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
|
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher.
|
||||||
type DomainMatcherInfo struct {
|
type DomainMatcherInfo struct {
|
||||||
clientIdx uint16
|
clientIdx uint16
|
||||||
domainRuleIdx uint16
|
domainRule string
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new DNS server with given configuration.
|
// New creates a new DNS server with given configuration.
|
||||||
@@ -88,29 +86,35 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
return nil, errors.New("failed to create hosts").Base(err)
|
return nil, errors.New("failed to create hosts").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var clients []*Client
|
|
||||||
domainRuleCount := 0
|
|
||||||
|
|
||||||
var defaultTag = config.Tag
|
var defaultTag = config.Tag
|
||||||
if len(config.Tag) == 0 {
|
if len(config.Tag) == 0 {
|
||||||
defaultTag = generateRandomTag()
|
defaultTag = generateRandomTag()
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ns := range config.NameServer {
|
clients := make([]*Client, 0, len(config.NameServer))
|
||||||
domainRuleCount += len(ns.PrioritizedDomain)
|
matcherInfos := make([]*DomainMatcherInfo, 0)
|
||||||
}
|
effectiveRules := make([]*geodata.DomainRule, 0)
|
||||||
|
|
||||||
// MatcherInfos is ensured to cover the maximum index domainMatcher could return, where matcher's index starts from 1
|
|
||||||
matcherInfos := make([]*DomainMatcherInfo, domainRuleCount+1)
|
|
||||||
domainMatcher := &strmatcher.MatcherGroup{}
|
|
||||||
|
|
||||||
for _, ns := range config.NameServer {
|
for _, ns := range config.NameServer {
|
||||||
clientIdx := len(clients)
|
clientIdx := len(clients)
|
||||||
updateDomain := func(domainRule strmatcher.Matcher, originalRuleIdx int, matcherInfos []*DomainMatcherInfo) {
|
updateRules := func(isLocalNameServer bool) {
|
||||||
midx := domainMatcher.Add(domainRule)
|
// Prioritize local domains with specific TLDs or those without any dot for the local DNS
|
||||||
matcherInfos[midx] = &DomainMatcherInfo{
|
if isLocalNameServer {
|
||||||
clientIdx: uint16(clientIdx),
|
effectiveRules = append(effectiveRules, localTLDsAndDotlessDomainsRules...)
|
||||||
domainRuleIdx: uint16(originalRuleIdx),
|
for _, rule := range localTLDsAndDotlessDomainsRules {
|
||||||
|
matcherInfos = append(matcherInfos, &DomainMatcherInfo{
|
||||||
|
clientIdx: uint16(clientIdx),
|
||||||
|
domainRule: rule.String(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
effectiveRules = append(effectiveRules, ns.Domain...)
|
||||||
|
for _, rule := range ns.Domain {
|
||||||
|
matcherInfos = append(matcherInfos, &DomainMatcherInfo{
|
||||||
|
clientIdx: uint16(clientIdx),
|
||||||
|
domainRule: rule.String(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,18 +143,27 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
if len(ns.Tag) > 0 {
|
if len(ns.Tag) > 0 {
|
||||||
tag = ns.Tag
|
tag = ns.Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
clientIPOption := ResolveIpOptionOverride(ns.QueryStrategy, ipOption)
|
clientIPOption := ResolveIpOptionOverride(ns.QueryStrategy, ipOption)
|
||||||
if !clientIPOption.IPv4Enable && !clientIPOption.IPv6Enable {
|
if !clientIPOption.IPv4Enable && !clientIPOption.IPv6Enable {
|
||||||
return nil, errors.New("no QueryStrategy available for ", ns.Address)
|
return nil, errors.New("no QueryStrategy available for ", ns.Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := NewClient(ctx, ns, myClientIP, disableCache, serveStale, serveExpiredTTL, tag, clientIPOption, &matcherInfos, updateDomain)
|
client, err := NewClient(ctx, ns, myClientIP, disableCache, serveStale, serveExpiredTTL, tag, clientIPOption, updateRules)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to create client").Base(err)
|
return nil, errors.New("failed to create client").Base(err)
|
||||||
}
|
}
|
||||||
clients = append(clients, client)
|
clients = append(clients, client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var domainMatcher geodata.DomainMatcher
|
||||||
|
if len(effectiveRules) > 0 {
|
||||||
|
domainMatcher, err = geodata.DomainReg.BuildDomainMatcher(effectiveRules)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If there is no DNS client in config, add a `localhost` DNS client
|
// If there is no DNS client in config, add a `localhost` DNS client
|
||||||
if len(clients) == 0 {
|
if len(clients) == 0 {
|
||||||
clients = append(clients, NewLocalDNSClient(ipOption))
|
clients = append(clients, NewLocalDNSClient(ipOption))
|
||||||
@@ -208,7 +221,7 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.checkSystem {
|
if s.checkSystem {
|
||||||
supportIPv4, supportIPv6 := checkRoutes()
|
supportIPv4, supportIPv6 := utils.CheckRoutes()
|
||||||
option.IPv4Enable = option.IPv4Enable && supportIPv4
|
option.IPv4Enable = option.IPv4Enable && supportIPv4
|
||||||
option.IPv6Enable = option.IPv6Enable && supportIPv6
|
option.IPv6Enable = option.IPv6Enable && supportIPv6
|
||||||
} else {
|
} else {
|
||||||
@@ -259,24 +272,27 @@ func (s *DNS) sortClients(domain string) []*Client {
|
|||||||
|
|
||||||
// Priority domain matching
|
// Priority domain matching
|
||||||
hasMatch := false
|
hasMatch := false
|
||||||
MatchSlice := s.domainMatcher.Match(domain)
|
if s.domainMatcher != nil {
|
||||||
sort.Slice(MatchSlice, func(i, j int) bool {
|
matchSlice := s.domainMatcher.Match(strings.ToLower(domain))
|
||||||
return MatchSlice[i] < MatchSlice[j]
|
sort.Slice(matchSlice, func(i, j int) bool {
|
||||||
})
|
return matchSlice[i] < matchSlice[j]
|
||||||
for _, match := range MatchSlice {
|
})
|
||||||
info := s.matcherInfos[match]
|
for _, match := range matchSlice {
|
||||||
client := s.clients[info.clientIdx]
|
info := s.matcherInfos[match]
|
||||||
domainRule := client.domains[info.domainRuleIdx]
|
client := s.clients[info.clientIdx]
|
||||||
domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", domainRule, info.clientIdx))
|
domainRule := info.domainRule
|
||||||
if clientUsed[info.clientIdx] {
|
domainRules = append(domainRules, fmt.Sprintf("%s(DNS idx:%d)", domainRule, info.clientIdx))
|
||||||
continue
|
if clientUsed[info.clientIdx] {
|
||||||
}
|
continue
|
||||||
clientUsed[info.clientIdx] = true
|
}
|
||||||
clients = append(clients, client)
|
clientUsed[info.clientIdx] = true
|
||||||
clientNames = append(clientNames, client.Name())
|
clients = append(clients, client)
|
||||||
hasMatch = true
|
clientNames = append(clientNames, client.Name())
|
||||||
if client.finalQuery {
|
hasMatch = true
|
||||||
return clients
|
if client.finalQuery {
|
||||||
|
logDecision(s.ctx, domain, domainRules, clientNames)
|
||||||
|
return clients
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,17 +306,13 @@ func (s *DNS) sortClients(domain string) []*Client {
|
|||||||
clients = append(clients, client)
|
clients = append(clients, client)
|
||||||
clientNames = append(clientNames, client.Name())
|
clientNames = append(clientNames, client.Name())
|
||||||
if client.finalQuery {
|
if client.finalQuery {
|
||||||
|
logDecision(s.ctx, domain, domainRules, clientNames)
|
||||||
return clients
|
return clients
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(domainRules) > 0 {
|
logDecision(s.ctx, domain, domainRules, clientNames)
|
||||||
errors.LogDebug(s.ctx, "domain ", domain, " matches following rules: ", domainRules)
|
|
||||||
}
|
|
||||||
if len(clientNames) > 0 {
|
|
||||||
errors.LogDebug(s.ctx, "domain ", domain, " will use DNS in order: ", clientNames)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(clients) == 0 {
|
if len(clients) == 0 {
|
||||||
if len(s.clients) > 0 {
|
if len(s.clients) > 0 {
|
||||||
@@ -315,6 +327,15 @@ func (s *DNS) sortClients(domain string) []*Client {
|
|||||||
return clients
|
return clients
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func logDecision(ctx context.Context, domain string, domainRules []string, clientNames []string) {
|
||||||
|
if len(domainRules) > 0 {
|
||||||
|
errors.LogDebug(ctx, "domain ", domain, " matches following rules: ", domainRules)
|
||||||
|
}
|
||||||
|
if len(clientNames) > 0 {
|
||||||
|
errors.LogDebug(ctx, "domain ", domain, " will use DNS in order: ", clientNames)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func mergeQueryErrors(domain string, errs []error) error {
|
func mergeQueryErrors(domain string, errs []error) error {
|
||||||
if len(errs) == 0 {
|
if len(errs) == 0 {
|
||||||
return dns.ErrEmptyResponse
|
return dns.ErrEmptyResponse
|
||||||
@@ -516,67 +537,3 @@ func init() {
|
|||||||
return New(ctx, config.(*Config))
|
return New(ctx, config.(*Config))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func probeRoutes() (ipv4 bool, ipv6 bool) {
|
|
||||||
if conn, err := net.Dial("udp4", "192.33.4.12:53"); err == nil {
|
|
||||||
ipv4 = true
|
|
||||||
conn.Close()
|
|
||||||
}
|
|
||||||
if conn, err := net.Dial("udp6", "[2001:500:2::c]:53"); err == nil {
|
|
||||||
ipv6 = true
|
|
||||||
conn.Close()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var routeCache struct {
|
|
||||||
sync.Once
|
|
||||||
sync.RWMutex
|
|
||||||
expire time.Time
|
|
||||||
ipv4, ipv6 bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkRoutes() (bool, bool) {
|
|
||||||
if !isGUIPlatform {
|
|
||||||
routeCache.Once.Do(func() {
|
|
||||||
routeCache.ipv4, routeCache.ipv6 = probeRoutes()
|
|
||||||
})
|
|
||||||
return routeCache.ipv4, routeCache.ipv6
|
|
||||||
}
|
|
||||||
|
|
||||||
routeCache.RWMutex.RLock()
|
|
||||||
now := time.Now()
|
|
||||||
if routeCache.expire.After(now) {
|
|
||||||
routeCache.RWMutex.RUnlock()
|
|
||||||
return routeCache.ipv4, routeCache.ipv6
|
|
||||||
}
|
|
||||||
routeCache.RWMutex.RUnlock()
|
|
||||||
|
|
||||||
routeCache.RWMutex.Lock()
|
|
||||||
defer routeCache.RWMutex.Unlock()
|
|
||||||
|
|
||||||
now = time.Now()
|
|
||||||
if routeCache.expire.After(now) { // double-check
|
|
||||||
return routeCache.ipv4, routeCache.ipv6
|
|
||||||
}
|
|
||||||
routeCache.ipv4, routeCache.ipv6 = probeRoutes() // ~2ms
|
|
||||||
routeCache.expire = now.Add(100 * time.Millisecond) // ttl
|
|
||||||
return routeCache.ipv4, routeCache.ipv6
|
|
||||||
}
|
|
||||||
|
|
||||||
var isGUIPlatform = detectGUIPlatform()
|
|
||||||
|
|
||||||
func detectGUIPlatform() bool {
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "android", "ios", "windows", "darwin":
|
|
||||||
return true
|
|
||||||
case "linux", "freebsd", "openbsd":
|
|
||||||
if t := os.Getenv("XDG_SESSION_TYPE"); t == "wayland" || t == "x11" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if os.Getenv("DISPLAY") != "" || os.Getenv("WAYLAND_DISPLAY") != "" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|||||||
+68
-100
@@ -11,9 +11,9 @@ import (
|
|||||||
"github.com/xtls/xray-core/app/policy"
|
"github.com/xtls/xray-core/app/policy"
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
_ "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/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/geodata"
|
||||||
"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"
|
||||||
@@ -147,7 +147,9 @@ func TestUDPServerSubnet(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -207,7 +209,9 @@ func TestUDPServer(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -331,10 +335,9 @@ func TestPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*NameServer_PriorityDomain{
|
Domain: []*geodata.DomainRule{
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Full, Value: "google.com"}},
|
||||||
Domain: "google.com",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -346,7 +349,9 @@ func TestPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -415,7 +420,9 @@ func TestUDPServerIPv6(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -471,8 +478,7 @@ func TestStaticHostDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
StaticHosts: []*Config_HostMapping{
|
StaticHosts: []*Config_HostMapping{
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Full, Value: "example.com"}}},
|
||||||
Domain: "example.com",
|
|
||||||
ProxiedDomain: "google.com",
|
ProxiedDomain: "google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -483,7 +489,9 @@ func TestStaticHostDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -539,17 +547,9 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
ExpectedIp: []*geodata.IPRule{
|
||||||
{
|
// inner ip, will not match
|
||||||
CountryCode: "local",
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{192, 168, 11, 1}, Prefix: 32}}}},
|
||||||
Cidr: []*router.CIDR{
|
|
||||||
{
|
|
||||||
// inner ip, will not match
|
|
||||||
Ip: []byte{192, 168, 11, 1},
|
|
||||||
Prefix: 32,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// second dns, match ip
|
// second dns, match ip
|
||||||
@@ -563,25 +563,9 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
ExpectedIp: []*geodata.IPRule{
|
||||||
{
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 8}, Prefix: 32}}}},
|
||||||
CountryCode: "test",
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 4}, Prefix: 32}}}},
|
||||||
Cidr: []*router.CIDR{
|
|
||||||
{
|
|
||||||
Ip: []byte{8, 8, 8, 8},
|
|
||||||
Prefix: 32,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
CountryCode: "test",
|
|
||||||
Cidr: []*router.CIDR{
|
|
||||||
{
|
|
||||||
Ip: []byte{8, 8, 8, 4},
|
|
||||||
Prefix: 32,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -592,7 +576,9 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -663,19 +649,15 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*NameServer_PriorityDomain{
|
Domain: []*geodata.DomainRule{
|
||||||
// Equivalent of dotless:localhost
|
// Equivalent of dotless:localhost
|
||||||
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Regex, Value: "^[^.]*localhost[^.]*$"}}},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
ExpectedIp: []*geodata.IPRule{
|
||||||
{ // Will match localhost, localhost-a and localhost-b,
|
// Will match localhost, localhost-a and localhost-b,
|
||||||
CountryCode: "local",
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 2}, Prefix: 32}}}},
|
||||||
Cidr: []*router.CIDR{
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 3}, Prefix: 32}}}},
|
||||||
{Ip: []byte{127, 0, 0, 2}, Prefix: 32},
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 4}, Prefix: 32}}}},
|
||||||
{Ip: []byte{127, 0, 0, 3}, Prefix: 32},
|
|
||||||
{Ip: []byte{127, 0, 0, 4}, Prefix: 32},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -688,23 +670,21 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*NameServer_PriorityDomain{
|
Domain: []*geodata.DomainRule{
|
||||||
// Equivalent of dotless: and domain:local
|
// Equivalent of dotless: and domain:local
|
||||||
{Type: DomainMatchingType_Regex, Domain: "^[^.]*$"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Regex, Value: "^[^.]*$"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "local"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "local"}}},
|
||||||
{Type: DomainMatchingType_Subdomain, Domain: "localdomain"},
|
{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "localdomain"}}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
StaticHosts: []*Config_HostMapping{
|
StaticHosts: []*Config_HostMapping{
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Full, Value: "hostnamestatic"}}},
|
||||||
Domain: "hostnamestatic",
|
|
||||||
Ip: [][]byte{{127, 0, 0, 53}},
|
Ip: [][]byte{{127, 0, 0, 53}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Full, Value: "hostnamealias"}}},
|
||||||
Domain: "hostnamealias",
|
|
||||||
ProxiedDomain: "hostname.localdomain",
|
ProxiedDomain: "hostname.localdomain",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -715,7 +695,9 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -891,19 +873,15 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*NameServer_PriorityDomain{
|
Domain: []*geodata.DomainRule{
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Subdomain,
|
Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "google.com"}},
|
||||||
Domain: "google.com",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
ExpectedIp: []*geodata.IPRule{
|
||||||
{ // Will only match 8.8.8.8 and 8.8.4.4
|
// Will only match 8.8.8.8 and 8.8.4.4
|
||||||
Cidr: []*router.CIDR{
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 8}, Prefix: 32}}}},
|
||||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 4, 4}, Prefix: 32}}}},
|
||||||
{Ip: []byte{8, 8, 4, 4}, Prefix: 32},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -916,18 +894,14 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*NameServer_PriorityDomain{
|
Domain: []*geodata.DomainRule{
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Subdomain,
|
Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "google.com"}},
|
||||||
Domain: "google.com",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
ExpectedIp: []*geodata.IPRule{
|
||||||
{ // Will match 8.8.8.8 and 8.8.8.7, etc
|
// Will match 8.8.8.8 and 8.8.8.7, etc
|
||||||
Cidr: []*router.CIDR{
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 7}, Prefix: 24}}}},
|
||||||
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -940,18 +914,14 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*NameServer_PriorityDomain{
|
Domain: []*geodata.DomainRule{
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Subdomain,
|
Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "api.google.com"}},
|
||||||
Domain: "api.google.com",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
ExpectedIp: []*geodata.IPRule{
|
||||||
{ // Will only match 8.8.7.7 (api.google.com)
|
// Will only match 8.8.7.7 (api.google.com)
|
||||||
Cidr: []*router.CIDR{
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 7, 7}, Prefix: 32}}}},
|
||||||
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -964,18 +934,14 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
PrioritizedDomain: []*NameServer_PriorityDomain{
|
Domain: []*geodata.DomainRule{
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Full, Value: "v2.api.google.com"}},
|
||||||
Domain: "v2.api.google.com",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
ExpectedIp: []*geodata.IPRule{
|
||||||
{ // Will only match 8.8.7.8 (v2.api.google.com)
|
// Will only match 8.8.7.8 (v2.api.google.com)
|
||||||
Cidr: []*router.CIDR{
|
{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{8, 8, 7, 8}, Prefix: 32}}}},
|
||||||
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -986,7 +952,9 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
Outbound: []*core.OutboundHandlerConfig{
|
||||||
{
|
{
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
|
FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}},
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-12
@@ -17,7 +17,7 @@ import (
|
|||||||
type Holder struct {
|
type Holder struct {
|
||||||
domainToIP cache.Lru
|
domainToIP cache.Lru
|
||||||
ipRange *net.IPNet
|
ipRange *net.IPNet
|
||||||
mu *sync.Mutex
|
mu sync.Mutex
|
||||||
|
|
||||||
config *FakeDnsPool
|
config *FakeDnsPool
|
||||||
}
|
}
|
||||||
@@ -49,9 +49,7 @@ func (fkdns *Holder) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fkdns *Holder) Close() error {
|
func (fkdns *Holder) Close() error {
|
||||||
fkdns.domainToIP = nil
|
// nothing to do for now, just wait GC
|
||||||
fkdns.ipRange = nil
|
|
||||||
fkdns.mu = nil
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +68,7 @@ func NewFakeDNSHolder() (*Holder, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) {
|
func NewFakeDNSHolderConfigOnly(conf *FakeDnsPool) (*Holder, error) {
|
||||||
return &Holder{nil, nil, nil, conf}, nil
|
return &Holder{config: conf}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fkdns *Holder) initializeFromConfig() error {
|
func (fkdns *Holder) initializeFromConfig() error {
|
||||||
@@ -92,7 +90,6 @@ 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
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +100,7 @@ func (fkdns *Holder) GetFakeIPForDomain(domain string) []net.Address {
|
|||||||
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)}
|
||||||
}
|
}
|
||||||
currentTimeMillis := uint64(time.Now().UnixNano() / 1e6)
|
currentTimeMillis := uint64(time.Now().UnixMilli())
|
||||||
ones, bits := fkdns.ipRange.Mask.Size()
|
ones, bits := fkdns.ipRange.Mask.Size()
|
||||||
rooms := bits - ones
|
rooms := bits - ones
|
||||||
if rooms < 64 {
|
if rooms < 64 {
|
||||||
@@ -202,12 +199,11 @@ func (h *HolderMulti) Start() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *HolderMulti) Close() error {
|
func (h *HolderMulti) Close() error {
|
||||||
|
var errs []error
|
||||||
for _, v := range h.holders {
|
for _, v := range h.holders {
|
||||||
if err := v.Close(); err != nil {
|
errs = append(errs, v.Close())
|
||||||
return errors.New("Cannot close all fake dns pools").Base(err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return errors.Combine(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *HolderMulti) createHolderGroups() error {
|
func (h *HolderMulti) createHolderGroups() error {
|
||||||
@@ -222,7 +218,7 @@ func (h *HolderMulti) createHolderGroups() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewFakeDNSHolderMulti(conf *FakeDnsPoolMulti) (*HolderMulti, error) {
|
func NewFakeDNSHolderMulti(conf *FakeDnsPoolMulti) (*HolderMulti, error) {
|
||||||
holderMulti := &HolderMulti{nil, conf}
|
holderMulti := &HolderMulti{config: conf}
|
||||||
if err := holderMulti.createHolderGroups(); err != nil {
|
if err := holderMulti.createHolderGroups(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/dns/fakedns/fakedns.proto
|
// source: app/dns/fakedns/fakedns.proto
|
||||||
|
|
||||||
package fakedns
|
package fakedns
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,12 +22,11 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type FakeDnsPool struct {
|
type FakeDnsPool struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
IpPool string `protobuf:"bytes,1,opt,name=ip_pool,json=ipPool,proto3" json:"ip_pool,omitempty"` //CIDR of IP pool used as fake DNS IP
|
||||||
|
LruSize int64 `protobuf:"varint,2,opt,name=lruSize,proto3" json:"lruSize,omitempty"` //Size of Pool for remembering relationship between domain name and IP address
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
IpPool string `protobuf:"bytes,1,opt,name=ip_pool,json=ipPool,proto3" json:"ip_pool,omitempty"` //CIDR of IP pool used as fake DNS IP
|
|
||||||
LruSize int64 `protobuf:"varint,2,opt,name=lruSize,proto3" json:"lruSize,omitempty"` //Size of Pool for remembering relationship between domain name and IP address
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FakeDnsPool) Reset() {
|
func (x *FakeDnsPool) Reset() {
|
||||||
@@ -74,11 +74,10 @@ func (x *FakeDnsPool) GetLruSize() int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FakeDnsPoolMulti struct {
|
type FakeDnsPoolMulti struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Pools []*FakeDnsPool `protobuf:"bytes,1,rep,name=pools,proto3" json:"pools,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Pools []*FakeDnsPool `protobuf:"bytes,1,rep,name=pools,proto3" json:"pools,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *FakeDnsPoolMulti) Reset() {
|
func (x *FakeDnsPoolMulti) Reset() {
|
||||||
@@ -120,36 +119,24 @@ func (x *FakeDnsPoolMulti) GetPools() []*FakeDnsPool {
|
|||||||
|
|
||||||
var File_app_dns_fakedns_fakedns_proto protoreflect.FileDescriptor
|
var File_app_dns_fakedns_fakedns_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_dns_fakedns_fakedns_proto_rawDesc = []byte{
|
const file_app_dns_fakedns_fakedns_proto_rawDesc = "" +
|
||||||
0x0a, 0x1d, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e,
|
"\n" +
|
||||||
0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
|
"\x1dapp/dns/fakedns/fakedns.proto\x12\x14xray.app.dns.fakedns\"@\n" +
|
||||||
0x14, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61,
|
"\vFakeDnsPool\x12\x17\n" +
|
||||||
0x6b, 0x65, 0x64, 0x6e, 0x73, 0x22, 0x40, 0x0a, 0x0b, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73,
|
"\aip_pool\x18\x01 \x01(\tR\x06ipPool\x12\x18\n" +
|
||||||
0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x70, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18,
|
"\alruSize\x18\x02 \x01(\x03R\alruSize\"K\n" +
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x18, 0x0a,
|
"\x10FakeDnsPoolMulti\x127\n" +
|
||||||
0x07, 0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07,
|
"\x05pools\x18\x01 \x03(\v2!.xray.app.dns.fakedns.FakeDnsPoolR\x05poolsB^\n" +
|
||||||
0x6c, 0x72, 0x75, 0x53, 0x69, 0x7a, 0x65, 0x22, 0x4b, 0x0a, 0x10, 0x46, 0x61, 0x6b, 0x65, 0x44,
|
"\x18com.xray.app.dns.fakednsP\x01Z)github.com/xtls/xray-core/app/dns/fakedns\xaa\x02\x14Xray.App.Dns.Fakednsb\x06proto3"
|
||||||
0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x12, 0x37, 0x0a, 0x05, 0x70,
|
|
||||||
0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e,
|
|
||||||
0x73, 0x2e, 0x46, 0x61, 0x6b, 0x65, 0x44, 0x6e, 0x73, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x05, 0x70,
|
|
||||||
0x6f, 0x6f, 0x6c, 0x73, 0x42, 0x5e, 0x0a, 0x18, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73,
|
|
||||||
0x50, 0x01, 0x5a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
|
||||||
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70,
|
|
||||||
0x70, 0x2f, 0x64, 0x6e, 0x73, 0x2f, 0x66, 0x61, 0x6b, 0x65, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x14,
|
|
||||||
0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x2e, 0x46, 0x61, 0x6b,
|
|
||||||
0x65, 0x64, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_dns_fakedns_fakedns_proto_rawDescOnce sync.Once
|
file_app_dns_fakedns_fakedns_proto_rawDescOnce sync.Once
|
||||||
file_app_dns_fakedns_fakedns_proto_rawDescData = file_app_dns_fakedns_fakedns_proto_rawDesc
|
file_app_dns_fakedns_fakedns_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_dns_fakedns_fakedns_proto_rawDescGZIP() []byte {
|
func file_app_dns_fakedns_fakedns_proto_rawDescGZIP() []byte {
|
||||||
file_app_dns_fakedns_fakedns_proto_rawDescOnce.Do(func() {
|
file_app_dns_fakedns_fakedns_proto_rawDescOnce.Do(func() {
|
||||||
file_app_dns_fakedns_fakedns_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_dns_fakedns_fakedns_proto_rawDescData)
|
file_app_dns_fakedns_fakedns_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_dns_fakedns_fakedns_proto_rawDesc), len(file_app_dns_fakedns_fakedns_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_dns_fakedns_fakedns_proto_rawDescData
|
return file_app_dns_fakedns_fakedns_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -177,7 +164,7 @@ func file_app_dns_fakedns_fakedns_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_dns_fakedns_fakedns_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_dns_fakedns_fakedns_proto_rawDesc), len(file_app_dns_fakedns_fakedns_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 2,
|
NumMessages: 2,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -188,7 +175,6 @@ func file_app_dns_fakedns_fakedns_proto_init() {
|
|||||||
MessageInfos: file_app_dns_fakedns_fakedns_proto_msgTypes,
|
MessageInfos: file_app_dns_fakedns_fakedns_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_dns_fakedns_fakedns_proto = out.File
|
File_app_dns_fakedns_fakedns_proto = out.File
|
||||||
file_app_dns_fakedns_fakedns_proto_rawDesc = nil
|
|
||||||
file_app_dns_fakedns_fakedns_proto_goTypes = nil
|
file_app_dns_fakedns_fakedns_proto_goTypes = nil
|
||||||
file_app_dns_fakedns_fakedns_proto_depIdxs = nil
|
file_app_dns_fakedns_fakedns_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-30
@@ -3,35 +3,27 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"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/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StaticHosts represents static domain-ip mapping in DNS server.
|
// StaticHosts represents static domain-ip mapping in DNS server.
|
||||||
type StaticHosts struct {
|
type StaticHosts struct {
|
||||||
ips [][]net.Address
|
responses [][]net.Address
|
||||||
matchers *strmatcher.MatcherGroup
|
matcher geodata.DomainMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewStaticHosts creates a new StaticHosts instance.
|
// NewStaticHosts creates a new StaticHosts instance.
|
||||||
func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
|
func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
|
||||||
g := new(strmatcher.MatcherGroup)
|
reps := make([][]net.Address, 0, len(hosts))
|
||||||
sh := &StaticHosts{
|
rules := make([]*geodata.DomainRule, 0, len(hosts))
|
||||||
ips: make([][]net.Address, len(hosts)+16),
|
|
||||||
matchers: g,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, mapping := range hosts {
|
for _, mapping := range hosts {
|
||||||
matcher, err := toStrMatcher(mapping.Type, mapping.Domain)
|
rep := make([]net.Address, 0, len(mapping.Ip))
|
||||||
if err != nil {
|
|
||||||
errors.LogErrorInner(context.Background(), err, "failed to create domain matcher, ignore domain rule [type: ", mapping.Type, ", domain: ", mapping.Domain, "]")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
id := g.Add(matcher)
|
|
||||||
ips := make([]net.Address, 0, len(mapping.Ip)+1)
|
|
||||||
switch {
|
switch {
|
||||||
case len(mapping.ProxiedDomain) > 0:
|
case len(mapping.ProxiedDomain) > 0:
|
||||||
if mapping.ProxiedDomain[0] == '#' {
|
if mapping.ProxiedDomain[0] == '#' {
|
||||||
@@ -39,28 +31,36 @@ func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ips = append(ips, dns.RCodeError(rcode))
|
rep = append(rep, dns.RCodeError(rcode))
|
||||||
} else {
|
} else {
|
||||||
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
|
rep = append(rep, net.DomainAddress(mapping.ProxiedDomain))
|
||||||
}
|
}
|
||||||
case len(mapping.Ip) > 0:
|
case len(mapping.Ip) > 0:
|
||||||
for _, ip := range mapping.Ip {
|
for _, ip := range mapping.Ip {
|
||||||
addr := net.IPAddress(ip)
|
addr := net.IPAddress(ip)
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
errors.LogError(context.Background(), "invalid IP address in static hosts: ", ip, ", ignore this ip for rule [type: ", mapping.Type, ", domain: ", mapping.Domain, "]")
|
errors.LogError(context.Background(), "invalid IP address in static hosts: ", ip, ", ignore this ip for rule: ", mapping.Domain)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ips = append(ips, addr)
|
rep = append(rep, addr)
|
||||||
}
|
|
||||||
if len(ips) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
reps = append(reps, rep)
|
||||||
sh.ips[id] = ips
|
rules = append(rules, mapping.Domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
return sh, nil
|
if len(rules) == 0 {
|
||||||
|
return &StaticHosts{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
matcher, err := geodata.DomainReg.BuildDomainMatcher(rules)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &StaticHosts{
|
||||||
|
responses: reps,
|
||||||
|
matcher: matcher,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
||||||
@@ -76,16 +76,16 @@ func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
|||||||
func (h *StaticHosts) lookupInternal(domain string) ([]net.Address, error) {
|
func (h *StaticHosts) lookupInternal(domain string) ([]net.Address, error) {
|
||||||
ips := make([]net.Address, 0)
|
ips := make([]net.Address, 0)
|
||||||
found := false
|
found := false
|
||||||
for _, id := range h.matchers.Match(domain) {
|
for _, idx := range h.matcher.Match(domain) {
|
||||||
for _, v := range h.ips[id] {
|
for _, rep := range h.responses[idx] {
|
||||||
if err, ok := v.(dns.RCodeError); ok {
|
if err, ok := rep.(dns.RCodeError); ok {
|
||||||
if uint16(err) == 0 {
|
if uint16(err) == 0 {
|
||||||
return nil, dns.ErrEmptyResponse
|
return nil, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ips = append(ips, h.ips[id]...)
|
ips = append(ips, h.responses[idx]...)
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
@@ -95,10 +95,13 @@ func (h *StaticHosts) lookupInternal(domain string) ([]net.Address, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) ([]net.Address, error) {
|
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) ([]net.Address, error) {
|
||||||
|
domain = strings.ToLower(domain)
|
||||||
switch addrs, err := h.lookupInternal(domain); {
|
switch addrs, err := h.lookupInternal(domain); {
|
||||||
case err != nil:
|
case err != nil:
|
||||||
return nil, err
|
return nil, err
|
||||||
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
case addrs == nil: // Not recorded in static hosts, return nil
|
||||||
|
return nil, nil
|
||||||
|
case len(addrs) == 0: // Domain recorded, but no valid IP returned
|
||||||
return addrs, nil
|
return addrs, nil
|
||||||
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
|
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
|
||||||
errors.LogDebug(context.Background(), "found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it")
|
errors.LogDebug(context.Background(), "found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it")
|
||||||
@@ -119,5 +122,8 @@ func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) (
|
|||||||
|
|
||||||
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
|
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
|
||||||
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) ([]net.Address, error) {
|
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) ([]net.Address, error) {
|
||||||
|
if h.matcher == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
return h.lookup(domain, option, 5)
|
return h.lookup(domain, option, 5)
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-12
@@ -6,6 +6,7 @@ import (
|
|||||||
"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/geodata"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
@@ -13,20 +14,17 @@ import (
|
|||||||
func TestStaticHosts(t *testing.T) {
|
func TestStaticHosts(t *testing.T) {
|
||||||
pb := []*Config_HostMapping{
|
pb := []*Config_HostMapping{
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Subdomain,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "lan"}}},
|
||||||
Domain: "lan",
|
|
||||||
ProxiedDomain: "#3",
|
ProxiedDomain: "#3",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Full, Value: "example.com"}}},
|
||||||
Domain: "example.com",
|
|
||||||
Ip: [][]byte{
|
Ip: [][]byte{
|
||||||
{1, 1, 1, 1},
|
{1, 1, 1, 1},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Full, Value: "proxy.xray.com"}}},
|
||||||
Domain: "proxy.xray.com",
|
|
||||||
Ip: [][]byte{
|
Ip: [][]byte{
|
||||||
{1, 2, 3, 4},
|
{1, 2, 3, 4},
|
||||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
@@ -34,20 +32,17 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
ProxiedDomain: "another-proxy.xray.com",
|
ProxiedDomain: "another-proxy.xray.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Full, Value: "proxy2.xray.com"}}},
|
||||||
Domain: "proxy2.xray.com",
|
|
||||||
ProxiedDomain: "proxy.xray.com",
|
ProxiedDomain: "proxy.xray.com",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Subdomain,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "example.cn"}}},
|
||||||
Domain: "example.cn",
|
|
||||||
Ip: [][]byte{
|
Ip: [][]byte{
|
||||||
{2, 2, 2, 2},
|
{2, 2, 2, 2},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Subdomain,
|
Domain: &geodata.DomainRule{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "baidu.com"}}},
|
||||||
Domain: "baidu.com",
|
|
||||||
Ip: [][]byte{
|
Ip: [][]byte{
|
||||||
{127, 0, 0, 1},
|
{127, 0, 0, 1},
|
||||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
||||||
|
|||||||
+14
-62
@@ -6,11 +6,11 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/router"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/common/strmatcher"
|
"github.com/xtls/xray-core/common/utils"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
@@ -31,9 +31,8 @@ type Server interface {
|
|||||||
type Client struct {
|
type Client struct {
|
||||||
server Server
|
server Server
|
||||||
skipFallback bool
|
skipFallback bool
|
||||||
domains []string
|
expectedIPs geodata.IPMatcher
|
||||||
expectedIPs router.GeoIPMatcher
|
unexpectedIPs geodata.IPMatcher
|
||||||
unexpectedIPs router.GeoIPMatcher
|
|
||||||
actPrior bool
|
actPrior bool
|
||||||
actUnprior bool
|
actUnprior bool
|
||||||
tag string
|
tag string
|
||||||
@@ -96,11 +95,9 @@ func NewClient(
|
|||||||
disableCache bool, serveStale bool, serveExpiredTTL uint32,
|
disableCache bool, serveStale bool, serveExpiredTTL uint32,
|
||||||
tag string,
|
tag string,
|
||||||
ipOption dns.IPOption,
|
ipOption dns.IPOption,
|
||||||
matcherInfos *[]*DomainMatcherInfo,
|
updateRules func(bool),
|
||||||
updateDomainRule func(strmatcher.Matcher, int, []*DomainMatcherInfo),
|
|
||||||
) (*Client, error) {
|
) (*Client, error) {
|
||||||
client := &Client{}
|
client := &Client{}
|
||||||
|
|
||||||
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
||||||
// Create a new server for each client for now
|
// Create a new server for each client for now
|
||||||
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
|
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
@@ -108,66 +105,22 @@ func NewClient(
|
|||||||
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prioritize local domains with specific TLDs or those without any dot for the local DNS
|
_, isLocalDNS := server.(*LocalNameServer)
|
||||||
if _, isLocalDNS := server.(*LocalNameServer); isLocalDNS {
|
updateRules(isLocalDNS)
|
||||||
ns.PrioritizedDomain = append(ns.PrioritizedDomain, localTLDsAndDotlessDomains...)
|
|
||||||
ns.OriginalRules = append(ns.OriginalRules, localTLDsAndDotlessDomainsRule)
|
|
||||||
// The following lines is a solution to avoid core panics(rule index out of range) when setting `localhost` DNS client in config.
|
|
||||||
// Because the `localhost` DNS client will append len(localTLDsAndDotlessDomains) rules into matcherInfos to match `geosite:private` default rule.
|
|
||||||
// But `matcherInfos` has no enough length to add rules, which leads to core panics (rule index out of range).
|
|
||||||
// To avoid this, the length of `matcherInfos` must be equal to the expected, so manually append it with Golang default zero value first for later modification.
|
|
||||||
// Related issues:
|
|
||||||
// https://github.com/v2fly/v2ray-core/issues/529
|
|
||||||
// https://github.com/v2fly/v2ray-core/issues/719
|
|
||||||
for i := 0; i < len(localTLDsAndDotlessDomains); i++ {
|
|
||||||
*matcherInfos = append(*matcherInfos, &DomainMatcherInfo{
|
|
||||||
clientIdx: uint16(0),
|
|
||||||
domainRuleIdx: uint16(0),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establish domain rules
|
|
||||||
var rules []string
|
|
||||||
ruleCurr := 0
|
|
||||||
ruleIter := 0
|
|
||||||
for _, domain := range ns.PrioritizedDomain {
|
|
||||||
domainRule, err := toStrMatcher(domain.Type, domain.Domain)
|
|
||||||
if err != nil {
|
|
||||||
errors.LogErrorInner(ctx, err, "failed to create domain matcher, ignore domain rule [type: ", domain.Type, ", domain: ", domain.Domain, "]")
|
|
||||||
domainRule, _ = toStrMatcher(DomainMatchingType_Full, "hack.fix.index.for.illegal.domain.rule")
|
|
||||||
}
|
|
||||||
originalRuleIdx := ruleCurr
|
|
||||||
if ruleCurr < len(ns.OriginalRules) {
|
|
||||||
rule := ns.OriginalRules[ruleCurr]
|
|
||||||
if ruleCurr >= len(rules) {
|
|
||||||
rules = append(rules, rule.Rule)
|
|
||||||
}
|
|
||||||
ruleIter++
|
|
||||||
if ruleIter >= int(rule.Size) {
|
|
||||||
ruleIter = 0
|
|
||||||
ruleCurr++
|
|
||||||
}
|
|
||||||
} else { // No original rule, generate one according to current domain matcher (majorly for compatibility with tests)
|
|
||||||
rules = append(rules, domainRule.String())
|
|
||||||
ruleCurr++
|
|
||||||
}
|
|
||||||
updateDomainRule(domainRule, originalRuleIdx, *matcherInfos)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Establish expected IPs
|
// Establish expected IPs
|
||||||
var expectedMatcher router.GeoIPMatcher
|
var expectedMatcher geodata.IPMatcher
|
||||||
if len(ns.ExpectedGeoip) > 0 {
|
if len(ns.ExpectedIp) > 0 {
|
||||||
expectedMatcher, err = router.BuildOptimizedGeoIPMatcher(ns.ExpectedGeoip...)
|
expectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.ExpectedIp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
|
return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Establish unexpected IPs
|
// Establish unexpected IPs
|
||||||
var unexpectedMatcher router.GeoIPMatcher
|
var unexpectedMatcher geodata.IPMatcher
|
||||||
if len(ns.UnexpectedGeoip) > 0 {
|
if len(ns.UnexpectedIp) > 0 {
|
||||||
unexpectedMatcher, err = router.BuildOptimizedGeoIPMatcher(ns.UnexpectedGeoip...)
|
unexpectedMatcher, err = geodata.IPReg.BuildIPMatcher(ns.UnexpectedIp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
|
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
@@ -191,7 +144,6 @@ func NewClient(
|
|||||||
|
|
||||||
client.server = server
|
client.server = server
|
||||||
client.skipFallback = ns.SkipFallback
|
client.skipFallback = ns.SkipFallback
|
||||||
client.domains = rules
|
|
||||||
client.expectedIPs = expectedMatcher
|
client.expectedIPs = expectedMatcher
|
||||||
client.unexpectedIPs = unexpectedMatcher
|
client.unexpectedIPs = unexpectedMatcher
|
||||||
client.actPrior = ns.ActPrior
|
client.actPrior = ns.ActPrior
|
||||||
@@ -215,7 +167,7 @@ func (c *Client) Name() string {
|
|||||||
// QueryIP sends 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) ([]net.IP, uint32, error) {
|
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
if c.checkSystem {
|
if c.checkSystem {
|
||||||
supportIPv4, supportIPv6 := checkRoutes()
|
supportIPv4, supportIPv6 := utils.CheckRoutes()
|
||||||
option.IPv4Enable = option.IPv4Enable && supportIPv4
|
option.IPv4Enable = option.IPv4Enable && supportIPv4
|
||||||
option.IPv6Enable = option.IPv6Enable && supportIPv6
|
option.IPv6Enable = option.IPv6Enable && supportIPv6
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
utls "github.com/refraction-networking/utls"
|
utls "github.com/refraction-networking/utls"
|
||||||
@@ -20,6 +19,7 @@ import (
|
|||||||
"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"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/utils"
|
||||||
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"
|
||||||
@@ -214,8 +214,8 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
|
|||||||
|
|
||||||
req.Header.Add("Accept", "application/dns-message")
|
req.Header.Add("Accept", "application/dns-message")
|
||||||
req.Header.Add("Content-Type", "application/dns-message")
|
req.Header.Add("Content-Type", "application/dns-message")
|
||||||
|
utils.TryDefaultHeadersWith(req.Header, "fetch")
|
||||||
req.Header.Set("X-Padding", strings.Repeat("X", int(crypto.RandBetween(100, 1000))))
|
req.Header.Set("X-Padding", utils.H2Base62Pad(crypto.RandBetween(100, 1000)))
|
||||||
|
|
||||||
hc := s.httpClient
|
hc := s.httpClient
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,198 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.11
|
||||||
|
// protoc v6.33.5
|
||||||
|
// source: app/geodata/config.proto
|
||||||
|
|
||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 Asset struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
|
||||||
|
File string `protobuf:"bytes,2,opt,name=file,proto3" json:"file,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Asset) Reset() {
|
||||||
|
*x = Asset{}
|
||||||
|
mi := &file_app_geodata_config_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Asset) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Asset) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Asset) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_geodata_config_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Asset.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Asset) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_geodata_config_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Asset) GetUrl() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Url
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Asset) GetFile() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.File
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Cron string `protobuf:"bytes,1,opt,name=cron,proto3" json:"cron,omitempty"`
|
||||||
|
Outbound string `protobuf:"bytes,2,opt,name=outbound,proto3" json:"outbound,omitempty"`
|
||||||
|
Assets []*Asset `protobuf:"bytes,3,rep,name=assets,proto3" json:"assets,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) Reset() {
|
||||||
|
*x = Config{}
|
||||||
|
mi := &file_app_geodata_config_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_geodata_config_proto_msgTypes[1]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_geodata_config_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetCron() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Cron
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetOutbound() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Outbound
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetAssets() []*Asset {
|
||||||
|
if x != nil {
|
||||||
|
return x.Assets
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var File_app_geodata_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_app_geodata_config_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
"\x18app/geodata/config.proto\x12\x10xray.app.geodata\"-\n" +
|
||||||
|
"\x05Asset\x12\x10\n" +
|
||||||
|
"\x03url\x18\x01 \x01(\tR\x03url\x12\x12\n" +
|
||||||
|
"\x04file\x18\x02 \x01(\tR\x04file\"i\n" +
|
||||||
|
"\x06Config\x12\x12\n" +
|
||||||
|
"\x04cron\x18\x01 \x01(\tR\x04cron\x12\x1a\n" +
|
||||||
|
"\boutbound\x18\x02 \x01(\tR\boutbound\x12/\n" +
|
||||||
|
"\x06assets\x18\x03 \x03(\v2\x17.xray.app.geodata.AssetR\x06assetsBR\n" +
|
||||||
|
"\x14com.xray.app.geodataP\x01Z%github.com/xtls/xray-core/app/geodata\xaa\x02\x10Xray.App.Geodatab\x06proto3"
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_app_geodata_config_proto_rawDescOnce sync.Once
|
||||||
|
file_app_geodata_config_proto_rawDescData []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_app_geodata_config_proto_rawDescGZIP() []byte {
|
||||||
|
file_app_geodata_config_proto_rawDescOnce.Do(func() {
|
||||||
|
file_app_geodata_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_geodata_config_proto_rawDesc), len(file_app_geodata_config_proto_rawDesc)))
|
||||||
|
})
|
||||||
|
return file_app_geodata_config_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_app_geodata_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||||
|
var file_app_geodata_config_proto_goTypes = []any{
|
||||||
|
(*Asset)(nil), // 0: xray.app.geodata.Asset
|
||||||
|
(*Config)(nil), // 1: xray.app.geodata.Config
|
||||||
|
}
|
||||||
|
var file_app_geodata_config_proto_depIdxs = []int32{
|
||||||
|
0, // 0: xray.app.geodata.Config.assets:type_name -> xray.app.geodata.Asset
|
||||||
|
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_geodata_config_proto_init() }
|
||||||
|
func file_app_geodata_config_proto_init() {
|
||||||
|
if File_app_geodata_config_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_geodata_config_proto_rawDesc), len(file_app_geodata_config_proto_rawDesc)),
|
||||||
|
NumEnums: 0,
|
||||||
|
NumMessages: 2,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_app_geodata_config_proto_goTypes,
|
||||||
|
DependencyIndexes: file_app_geodata_config_proto_depIdxs,
|
||||||
|
MessageInfos: file_app_geodata_config_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_app_geodata_config_proto = out.File
|
||||||
|
file_app_geodata_config_proto_goTypes = nil
|
||||||
|
file_app_geodata_config_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.app.geodata;
|
||||||
|
option csharp_namespace = "Xray.App.Geodata";
|
||||||
|
option go_package = "github.com/xtls/xray-core/app/geodata";
|
||||||
|
option java_package = "com.xray.app.geodata";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message Asset {
|
||||||
|
string url = 1;
|
||||||
|
|
||||||
|
string file = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Config {
|
||||||
|
string cron = 1;
|
||||||
|
|
||||||
|
string outbound = 2;
|
||||||
|
|
||||||
|
repeated Asset assets = 3;
|
||||||
|
}
|
||||||
@@ -0,0 +1,304 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
go_errors "errors"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||||
|
"github.com/xtls/xray-core/common/task"
|
||||||
|
"github.com/xtls/xray-core/common/utils"
|
||||||
|
"github.com/xtls/xray-core/features/routing"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/tagged"
|
||||||
|
)
|
||||||
|
|
||||||
|
const idleTimeout = 30 * time.Second
|
||||||
|
|
||||||
|
type stage struct {
|
||||||
|
target string
|
||||||
|
temp string
|
||||||
|
}
|
||||||
|
|
||||||
|
type downloader struct {
|
||||||
|
ctx context.Context
|
||||||
|
client *http.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type idleConn struct {
|
||||||
|
net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *idleConn) Read(b []byte) (int, error) {
|
||||||
|
t := time.AfterFunc(idleTimeout, func() {
|
||||||
|
_ = c.Close()
|
||||||
|
})
|
||||||
|
|
||||||
|
n, err := c.Conn.Read(b)
|
||||||
|
if !t.Stop() {
|
||||||
|
_ = c.Close()
|
||||||
|
return n, errors.New("connection idle timeout")
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *idleConn) Write(b []byte) (int, error) {
|
||||||
|
return c.Conn.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDownloader(ctx context.Context, dispatcher routing.Dispatcher, outbound string) *downloader {
|
||||||
|
return &downloader{
|
||||||
|
ctx: ctx,
|
||||||
|
client: newClient(ctx, dispatcher, outbound),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newClient(baseCtx context.Context, dispatcher routing.Dispatcher, outbound string) *http.Client {
|
||||||
|
return &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
Proxy: nil,
|
||||||
|
DisableKeepAlives: true,
|
||||||
|
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||||
|
var conn net.Conn
|
||||||
|
err := task.Run(ctx, func() error {
|
||||||
|
if tagged.Dialer == nil {
|
||||||
|
return errors.New("tagged dialer is not initialized")
|
||||||
|
}
|
||||||
|
dest, err := net.ParseDestination(network + ":" + address)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("cannot understand address").Base(err)
|
||||||
|
}
|
||||||
|
c, err := tagged.Dialer(baseCtx, dispatcher, dest, outbound)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("cannot dial remote address ", dest).Base(err)
|
||||||
|
}
|
||||||
|
conn = c
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("cannot finish connection").Base(err)
|
||||||
|
}
|
||||||
|
return &idleConn{
|
||||||
|
Conn: conn,
|
||||||
|
}, nil
|
||||||
|
},
|
||||||
|
TLSHandshakeTimeout: idleTimeout,
|
||||||
|
ResponseHeaderTimeout: idleTimeout,
|
||||||
|
},
|
||||||
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
if req.URL.Scheme != "https" {
|
||||||
|
return errors.New("redirected to non-https URL: ", req.URL.String())
|
||||||
|
}
|
||||||
|
if len(via) >= 10 {
|
||||||
|
return errors.New("stopped after 10 redirects")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *downloader) download(assets []*Asset) ([]stage, error) {
|
||||||
|
staged := make([]stage, 0, len(assets))
|
||||||
|
for _, asset := range assets {
|
||||||
|
stage, err := d.downloadOne(asset)
|
||||||
|
if err != nil {
|
||||||
|
clean(staged)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
staged = append(staged, stage)
|
||||||
|
}
|
||||||
|
return staged, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *downloader) downloadOne(asset *Asset) (stage, error) {
|
||||||
|
target, err := filesystem.ResolveAsset(asset.File)
|
||||||
|
if err != nil {
|
||||||
|
return stage{}, err
|
||||||
|
}
|
||||||
|
errors.LogInfo(d.ctx, "downloading geodata asset from ", asset.Url, " to ", target)
|
||||||
|
|
||||||
|
temp, err := tempFile(target, ".tmp")
|
||||||
|
if err != nil {
|
||||||
|
return stage{}, err
|
||||||
|
}
|
||||||
|
tempName := temp.Name()
|
||||||
|
keepTemp := false
|
||||||
|
defer func() {
|
||||||
|
if !keepTemp {
|
||||||
|
os.Remove(tempName)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := d.fetch(asset.Url, temp); err != nil {
|
||||||
|
temp.Close()
|
||||||
|
return stage{}, err
|
||||||
|
}
|
||||||
|
if err := temp.Chmod(0o644); err != nil {
|
||||||
|
temp.Close()
|
||||||
|
return stage{}, err
|
||||||
|
}
|
||||||
|
if err := temp.Close(); err != nil {
|
||||||
|
return stage{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
keepTemp = true
|
||||||
|
return stage{
|
||||||
|
target: target,
|
||||||
|
temp: tempName,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *downloader) fetch(rawURL string, writer io.Writer) error {
|
||||||
|
req, err := http.NewRequestWithContext(d.ctx, http.MethodGet, rawURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
utils.TryDefaultHeadersWith(req.Header, "nav")
|
||||||
|
|
||||||
|
resp, err := d.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
|
||||||
|
io.Copy(io.Discard, resp.Body)
|
||||||
|
return errors.New("unexpected status code: ", resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
n, err := io.Copy(writer, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
return errors.New("empty response body")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func clean(assets []stage) {
|
||||||
|
for _, asset := range assets {
|
||||||
|
if asset.temp != "" {
|
||||||
|
os.Remove(asset.temp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type tx struct {
|
||||||
|
swaps []swap
|
||||||
|
}
|
||||||
|
|
||||||
|
type swap struct {
|
||||||
|
target string
|
||||||
|
backup string
|
||||||
|
hadOriginal bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func swapAll(assets []stage) (*tx, error) {
|
||||||
|
t := &tx{}
|
||||||
|
for _, asset := range assets {
|
||||||
|
s, err := swapOne(asset)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Combine(err, t.rollback())
|
||||||
|
}
|
||||||
|
t.swaps = append(t.swaps, s)
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func swapOne(asset stage) (swap, error) {
|
||||||
|
backup, err := backupFile(asset.target)
|
||||||
|
if err != nil {
|
||||||
|
return swap{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
s := swap{
|
||||||
|
target: asset.target,
|
||||||
|
backup: backup,
|
||||||
|
}
|
||||||
|
if err := os.Rename(asset.target, backup); err != nil {
|
||||||
|
if !go_errors.Is(err, os.ErrNotExist) {
|
||||||
|
return swap{}, err
|
||||||
|
}
|
||||||
|
if err := os.Remove(backup); err != nil && !go_errors.Is(err, os.ErrNotExist) {
|
||||||
|
return swap{}, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
s.hadOriginal = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := os.Rename(asset.temp, asset.target); err != nil {
|
||||||
|
if s.hadOriginal {
|
||||||
|
if restoreErr := os.Rename(backup, asset.target); restoreErr != nil {
|
||||||
|
return swap{}, errors.Combine(err, restoreErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return swap{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tx) rollback() error {
|
||||||
|
var errs []error
|
||||||
|
for i := len(t.swaps) - 1; i >= 0; i-- {
|
||||||
|
if err := t.swaps[i].rollback(); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.Combine(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s swap) rollback() error {
|
||||||
|
var errs []error
|
||||||
|
if err := os.Remove(s.target); err != nil && !go_errors.Is(err, os.ErrNotExist) {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
if s.hadOriginal {
|
||||||
|
if err := os.Rename(s.backup, s.target); err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
} else if err := os.Remove(s.backup); err != nil && !go_errors.Is(err, os.ErrNotExist) {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
return errors.Combine(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *tx) commit() error {
|
||||||
|
var errs []error
|
||||||
|
for _, swap := range t.swaps {
|
||||||
|
if err := os.Remove(swap.backup); err != nil && !go_errors.Is(err, os.ErrNotExist) {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.Combine(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func tempFile(target string, suffix string) (*os.File, error) {
|
||||||
|
dir := filepath.Dir(target)
|
||||||
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return os.CreateTemp(dir, "."+filepath.Base(target)+".*"+suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
func backupFile(target string) (string, error) {
|
||||||
|
file, err := tempFile(target, ".bak")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
name := file.Name()
|
||||||
|
if err := file.Close(); err != nil {
|
||||||
|
os.Remove(name)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if err := os.Remove(name); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return name, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
commongeodata "github.com/xtls/xray-core/common/geodata"
|
||||||
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/routing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Instance struct {
|
||||||
|
assets []*Asset
|
||||||
|
downloader *downloader
|
||||||
|
tasker *cron.Cron
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
|
running bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(ctx context.Context, config *Config) (*Instance, error) {
|
||||||
|
if config.Cron == "" {
|
||||||
|
return &Instance{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
g := &Instance{
|
||||||
|
assets: config.Assets,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(g.assets) > 0 {
|
||||||
|
var dispatcher routing.Dispatcher
|
||||||
|
if err := core.RequireFeatures(ctx, func(d routing.Dispatcher) {
|
||||||
|
dispatcher = d
|
||||||
|
}); err != nil {
|
||||||
|
return nil, errors.New("failed to get dispatcher for geodata downloader").Base(err)
|
||||||
|
}
|
||||||
|
g.downloader = newDownloader(ctx, dispatcher, config.Outbound)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.tasker = cron.New(
|
||||||
|
cron.WithChain(cron.SkipIfStillRunning(cron.DiscardLogger)),
|
||||||
|
cron.WithLogger(cron.DiscardLogger),
|
||||||
|
)
|
||||||
|
if _, err := g.tasker.AddFunc(config.Cron, g.execute); err != nil {
|
||||||
|
return nil, errors.New("invalid geodata cron").Base(err)
|
||||||
|
}
|
||||||
|
errors.LogInfo(ctx, "scheduled geodata reload with cron: ", config.Cron)
|
||||||
|
|
||||||
|
return g, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Instance) execute() {
|
||||||
|
var err error
|
||||||
|
if g.downloader != nil {
|
||||||
|
err = g.reloadWithUpdate()
|
||||||
|
} else {
|
||||||
|
err = reload()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
errors.LogErrorInner(context.Background(), err, "scheduled geodata reload failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Instance) reloadWithUpdate() error {
|
||||||
|
staged, err := g.downloader.download(g.assets)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer clean(staged)
|
||||||
|
|
||||||
|
tx, err := swapAll(staged)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := reload(); err != nil {
|
||||||
|
errors.LogErrorInner(context.Background(), err, "failed to reload geodata after downloading assets, rolling back")
|
||||||
|
rollbackErr := tx.rollback()
|
||||||
|
return errors.Combine(err, rollbackErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return tx.commit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func reload() error {
|
||||||
|
return errors.Combine(commongeodata.IPReg.Reload(), commongeodata.DomainReg.Reload())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Instance) Type() interface{} {
|
||||||
|
return (*Instance)(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Instance) Start() error {
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
|
||||||
|
if g.running {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.tasker != nil {
|
||||||
|
g.tasker.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
g.running = true
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Instance) Close() error {
|
||||||
|
g.mu.Lock()
|
||||||
|
defer g.mu.Unlock()
|
||||||
|
|
||||||
|
if !g.running {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.tasker != nil {
|
||||||
|
<-g.tasker.Stop().Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
g.running = false
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, cfg interface{}) (interface{}, error) {
|
||||||
|
return New(ctx, cfg.(*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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/log/command/config.proto
|
// source: app/log/command/config.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,9 +22,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -57,9 +58,9 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RestartLoggerRequest struct {
|
type RestartLoggerRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RestartLoggerRequest) Reset() {
|
func (x *RestartLoggerRequest) Reset() {
|
||||||
@@ -93,9 +94,9 @@ func (*RestartLoggerRequest) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RestartLoggerResponse struct {
|
type RestartLoggerResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RestartLoggerResponse) Reset() {
|
func (x *RestartLoggerResponse) Reset() {
|
||||||
@@ -130,39 +131,24 @@ func (*RestartLoggerResponse) Descriptor() ([]byte, []int) {
|
|||||||
|
|
||||||
var File_app_log_command_config_proto protoreflect.FileDescriptor
|
var File_app_log_command_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_log_command_config_proto_rawDesc = []byte{
|
const file_app_log_command_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x1c, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
"\n" +
|
||||||
0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14,
|
"\x1capp/log/command/config.proto\x12\x14xray.app.log.command\"\b\n" +
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x63, 0x6f, 0x6d,
|
"\x06Config\"\x16\n" +
|
||||||
0x6d, 0x61, 0x6e, 0x64, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x16,
|
"\x14RestartLoggerRequest\"\x17\n" +
|
||||||
0x0a, 0x14, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x52,
|
"\x15RestartLoggerResponse2{\n" +
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x17, 0x0a, 0x15, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72,
|
"\rLoggerService\x12j\n" +
|
||||||
0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32,
|
"\rRestartLogger\x12*.xray.app.log.command.RestartLoggerRequest\x1a+.xray.app.log.command.RestartLoggerResponse\"\x00B^\n" +
|
||||||
0x7b, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
"\x18com.xray.app.log.commandP\x01Z)github.com/xtls/xray-core/app/log/command\xaa\x02\x14Xray.App.Log.Commandb\x06proto3"
|
||||||
0x12, 0x6a, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65,
|
|
||||||
0x72, 0x12, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67,
|
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74,
|
|
||||||
0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e,
|
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4c, 0x6f, 0x67, 0x67,
|
|
||||||
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x5e, 0x0a, 0x18,
|
|
||||||
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67,
|
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 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, 0x6c, 0x6f, 0x67, 0x2f, 0x63, 0x6f,
|
|
||||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x14, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70,
|
|
||||||
0x2e, 0x4c, 0x6f, 0x67, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72,
|
|
||||||
0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_log_command_config_proto_rawDescOnce sync.Once
|
file_app_log_command_config_proto_rawDescOnce sync.Once
|
||||||
file_app_log_command_config_proto_rawDescData = file_app_log_command_config_proto_rawDesc
|
file_app_log_command_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_log_command_config_proto_rawDescGZIP() []byte {
|
func file_app_log_command_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_log_command_config_proto_rawDescOnce.Do(func() {
|
file_app_log_command_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_log_command_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_log_command_config_proto_rawDescData)
|
file_app_log_command_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_log_command_config_proto_rawDesc), len(file_app_log_command_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_log_command_config_proto_rawDescData
|
return file_app_log_command_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -192,7 +178,7 @@ func file_app_log_command_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_log_command_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_log_command_config_proto_rawDesc), len(file_app_log_command_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 3,
|
NumMessages: 3,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -203,7 +189,6 @@ func file_app_log_command_config_proto_init() {
|
|||||||
MessageInfos: file_app_log_command_config_proto_msgTypes,
|
MessageInfos: file_app_log_command_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_log_command_config_proto = out.File
|
File_app_log_command_config_proto = out.File
|
||||||
file_app_log_command_config_proto_rawDesc = nil
|
|
||||||
file_app_log_command_config_proto_goTypes = nil
|
file_app_log_command_config_proto_goTypes = nil
|
||||||
file_app_log_command_config_proto_depIdxs = nil
|
file_app_log_command_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.5.1
|
// - protoc-gen-go-grpc v1.6.0
|
||||||
// - protoc v5.28.2
|
// - protoc v6.33.5
|
||||||
// source: app/log/command/config.proto
|
// source: app/log/command/config.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
@@ -63,7 +63,7 @@ type LoggerServiceServer interface {
|
|||||||
type UnimplementedLoggerServiceServer struct{}
|
type UnimplementedLoggerServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedLoggerServiceServer) RestartLogger(context.Context, *RestartLoggerRequest) (*RestartLoggerResponse, error) {
|
func (UnimplementedLoggerServiceServer) RestartLogger(context.Context, *RestartLoggerRequest) (*RestartLoggerResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method RestartLogger not implemented")
|
return nil, status.Error(codes.Unimplemented, "method RestartLogger not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedLoggerServiceServer) mustEmbedUnimplementedLoggerServiceServer() {}
|
func (UnimplementedLoggerServiceServer) mustEmbedUnimplementedLoggerServiceServer() {}
|
||||||
func (UnimplementedLoggerServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedLoggerServiceServer) testEmbeddedByValue() {}
|
||||||
@@ -76,7 +76,7 @@ type UnsafeLoggerServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterLoggerServiceServer(s grpc.ServiceRegistrar, srv LoggerServiceServer) {
|
func RegisterLoggerServiceServer(s grpc.ServiceRegistrar, srv LoggerServiceServer) {
|
||||||
// If the following call pancis, it indicates UnimplementedLoggerServiceServer was
|
// If the following call panics, it indicates UnimplementedLoggerServiceServer was
|
||||||
// embedded by pointer and is nil. This will cause panics if an
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
// unimplemented method is ever invoked, so we test this at initialization
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
// time to prevent it from happening at runtime later due to I/O.
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
|||||||
+32
-53
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/log/config.proto
|
// source: app/log/config.proto
|
||||||
|
|
||||||
package log
|
package log
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -74,17 +75,16 @@ func (LogType) EnumDescriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
ErrorLogType LogType `protobuf:"varint,1,opt,name=error_log_type,json=errorLogType,proto3,enum=xray.app.log.LogType" json:"error_log_type,omitempty"`
|
||||||
|
ErrorLogLevel log.Severity `protobuf:"varint,2,opt,name=error_log_level,json=errorLogLevel,proto3,enum=xray.common.log.Severity" json:"error_log_level,omitempty"`
|
||||||
|
ErrorLogPath string `protobuf:"bytes,3,opt,name=error_log_path,json=errorLogPath,proto3" json:"error_log_path,omitempty"`
|
||||||
|
AccessLogType LogType `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,proto3,enum=xray.app.log.LogType" json:"access_log_type,omitempty"`
|
||||||
|
AccessLogPath string `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath,proto3" json:"access_log_path,omitempty"`
|
||||||
|
EnableDnsLog bool `protobuf:"varint,6,opt,name=enable_dns_log,json=enableDnsLog,proto3" json:"enable_dns_log,omitempty"`
|
||||||
|
MaskAddress string `protobuf:"bytes,7,opt,name=mask_address,json=maskAddress,proto3" json:"mask_address,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
ErrorLogType LogType `protobuf:"varint,1,opt,name=error_log_type,json=errorLogType,proto3,enum=xray.app.log.LogType" json:"error_log_type,omitempty"`
|
|
||||||
ErrorLogLevel log.Severity `protobuf:"varint,2,opt,name=error_log_level,json=errorLogLevel,proto3,enum=xray.common.log.Severity" json:"error_log_level,omitempty"`
|
|
||||||
ErrorLogPath string `protobuf:"bytes,3,opt,name=error_log_path,json=errorLogPath,proto3" json:"error_log_path,omitempty"`
|
|
||||||
AccessLogType LogType `protobuf:"varint,4,opt,name=access_log_type,json=accessLogType,proto3,enum=xray.app.log.LogType" json:"access_log_type,omitempty"`
|
|
||||||
AccessLogPath string `protobuf:"bytes,5,opt,name=access_log_path,json=accessLogPath,proto3" json:"access_log_path,omitempty"`
|
|
||||||
EnableDnsLog bool `protobuf:"varint,6,opt,name=enable_dns_log,json=enableDnsLog,proto3" json:"enable_dns_log,omitempty"`
|
|
||||||
MaskAddress string `protobuf:"bytes,7,opt,name=mask_address,json=maskAddress,proto3" json:"mask_address,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -168,52 +168,32 @@ func (x *Config) GetMaskAddress() string {
|
|||||||
|
|
||||||
var File_app_log_config_proto protoreflect.FileDescriptor
|
var File_app_log_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_log_config_proto_rawDesc = []byte{
|
const file_app_log_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x14, 0x61, 0x70, 0x70, 0x2f, 0x6c, 0x6f, 0x67, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
"\n" +
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0c, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
"\x14app/log/config.proto\x12\fxray.app.log\x1a\x14common/log/log.proto\"\xde\x02\n" +
|
||||||
0x2e, 0x6c, 0x6f, 0x67, 0x1a, 0x14, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6c, 0x6f, 0x67,
|
"\x06Config\x12;\n" +
|
||||||
0x2f, 0x6c, 0x6f, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xde, 0x02, 0x0a, 0x06, 0x43,
|
"\x0eerror_log_type\x18\x01 \x01(\x0e2\x15.xray.app.log.LogTypeR\ferrorLogType\x12A\n" +
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3b, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6c,
|
"\x0ferror_log_level\x18\x02 \x01(\x0e2\x19.xray.common.log.SeverityR\rerrorLogLevel\x12$\n" +
|
||||||
0x6f, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e,
|
"\x0eerror_log_path\x18\x03 \x01(\tR\ferrorLogPath\x12=\n" +
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x4c, 0x6f, 0x67,
|
"\x0faccess_log_type\x18\x04 \x01(\x0e2\x15.xray.app.log.LogTypeR\raccessLogType\x12&\n" +
|
||||||
0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4c, 0x6f, 0x67, 0x54, 0x79,
|
"\x0faccess_log_path\x18\x05 \x01(\tR\raccessLogPath\x12$\n" +
|
||||||
0x70, 0x65, 0x12, 0x41, 0x0a, 0x0f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x5f,
|
"\x0eenable_dns_log\x18\x06 \x01(\bR\fenableDnsLog\x12!\n" +
|
||||||
0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
"\fmask_address\x18\a \x01(\tR\vmaskAddress*5\n" +
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6c, 0x6f, 0x67, 0x2e, 0x53, 0x65,
|
"\aLogType\x12\b\n" +
|
||||||
0x76, 0x65, 0x72, 0x69, 0x74, 0x79, 0x52, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4c, 0x6f, 0x67,
|
"\x04None\x10\x00\x12\v\n" +
|
||||||
0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6c,
|
"\aConsole\x10\x01\x12\b\n" +
|
||||||
0x6f, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65,
|
"\x04File\x10\x02\x12\t\n" +
|
||||||
0x72, 0x72, 0x6f, 0x72, 0x4c, 0x6f, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x3d, 0x0a, 0x0f, 0x61,
|
"\x05Event\x10\x03BF\n" +
|
||||||
0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04,
|
"\x10com.xray.app.logP\x01Z!github.com/xtls/xray-core/app/log\xaa\x02\fXray.App.Logb\x06proto3"
|
||||||
0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
|
||||||
0x6c, 0x6f, 0x67, 0x2e, 0x4c, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0d, 0x61, 0x63, 0x63,
|
|
||||||
0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x61, 0x63,
|
|
||||||
0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x6f, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x05, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x6f, 0x67, 0x50, 0x61,
|
|
||||||
0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x6e, 0x73,
|
|
||||||
0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x65, 0x6e, 0x61, 0x62,
|
|
||||||
0x6c, 0x65, 0x44, 0x6e, 0x73, 0x4c, 0x6f, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x61, 0x73, 0x6b,
|
|
||||||
0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
|
|
||||||
0x6d, 0x61, 0x73, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x2a, 0x35, 0x0a, 0x07, 0x4c,
|
|
||||||
0x6f, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00,
|
|
||||||
0x12, 0x0b, 0x0a, 0x07, 0x43, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x10, 0x01, 0x12, 0x08, 0x0a,
|
|
||||||
0x04, 0x46, 0x69, 0x6c, 0x65, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74,
|
|
||||||
0x10, 0x03, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
|
||||||
0x70, 0x70, 0x2e, 0x6c, 0x6f, 0x67, 0x50, 0x01, 0x5a, 0x21, 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, 0x6c, 0x6f, 0x67, 0xaa, 0x02, 0x0c, 0x58, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4c, 0x6f, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
|
||||||
0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_log_config_proto_rawDescOnce sync.Once
|
file_app_log_config_proto_rawDescOnce sync.Once
|
||||||
file_app_log_config_proto_rawDescData = file_app_log_config_proto_rawDesc
|
file_app_log_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_log_config_proto_rawDescGZIP() []byte {
|
func file_app_log_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_log_config_proto_rawDescOnce.Do(func() {
|
file_app_log_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_log_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_log_config_proto_rawDescData)
|
file_app_log_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_log_config_proto_rawDesc), len(file_app_log_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_log_config_proto_rawDescData
|
return file_app_log_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -245,7 +225,7 @@ func file_app_log_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_log_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_log_config_proto_rawDesc), len(file_app_log_config_proto_rawDesc)),
|
||||||
NumEnums: 1,
|
NumEnums: 1,
|
||||||
NumMessages: 1,
|
NumMessages: 1,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -257,7 +237,6 @@ func file_app_log_config_proto_init() {
|
|||||||
MessageInfos: file_app_log_config_proto_msgTypes,
|
MessageInfos: file_app_log_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_log_config_proto = out.File
|
File_app_log_config_proto = out.File
|
||||||
file_app_log_config_proto_rawDesc = nil
|
|
||||||
file_app_log_config_proto_goTypes = nil
|
file_app_log_config_proto_goTypes = nil
|
||||||
file_app_log_config_proto_depIdxs = nil
|
file_app_log_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-26
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/metrics/config.proto
|
// source: app/metrics/config.proto
|
||||||
|
|
||||||
package metrics
|
package metrics
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -22,13 +23,12 @@ const (
|
|||||||
|
|
||||||
// Config is the settings for metrics.
|
// Config is the settings for metrics.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// Tag of the outbound handler that handles metrics http connections.
|
// Tag of the outbound handler that handles metrics http connections.
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
Listen string `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
Listen string `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -77,29 +77,22 @@ func (x *Config) GetListen() string {
|
|||||||
|
|
||||||
var File_app_metrics_config_proto protoreflect.FileDescriptor
|
var File_app_metrics_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_metrics_config_proto_rawDesc = []byte{
|
const file_app_metrics_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x63, 0x6f,
|
"\n" +
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79,
|
"\x18app/metrics/config.proto\x12\x10xray.app.metrics\"2\n" +
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x22, 0x32, 0x0a, 0x06,
|
"\x06Config\x12\x10\n" +
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x12\x16\n" +
|
||||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74,
|
"\x06listen\x18\x02 \x01(\tR\x06listenBR\n" +
|
||||||
0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e,
|
"\x14com.xray.app.metricsP\x01Z%github.com/xtls/xray-core/app/metrics\xaa\x02\x10Xray.App.Metricsb\x06proto3"
|
||||||
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 (
|
var (
|
||||||
file_app_metrics_config_proto_rawDescOnce sync.Once
|
file_app_metrics_config_proto_rawDescOnce sync.Once
|
||||||
file_app_metrics_config_proto_rawDescData = file_app_metrics_config_proto_rawDesc
|
file_app_metrics_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_metrics_config_proto_rawDescGZIP() []byte {
|
func file_app_metrics_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_metrics_config_proto_rawDescOnce.Do(func() {
|
file_app_metrics_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_metrics_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_metrics_config_proto_rawDescData)
|
file_app_metrics_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_metrics_config_proto_rawDesc), len(file_app_metrics_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_metrics_config_proto_rawDescData
|
return file_app_metrics_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -125,7 +118,7 @@ func file_app_metrics_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_metrics_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_metrics_config_proto_rawDesc), len(file_app_metrics_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 1,
|
NumMessages: 1,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -136,7 +129,6 @@ func file_app_metrics_config_proto_init() {
|
|||||||
MessageInfos: file_app_metrics_config_proto_msgTypes,
|
MessageInfos: file_app_metrics_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_metrics_config_proto = out.File
|
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_goTypes = nil
|
||||||
file_app_metrics_config_proto_depIdxs = nil
|
file_app_metrics_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/observatory"
|
"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"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -39,16 +38,12 @@ func NewMetricsHandler(ctx context.Context, config *Config) (*MetricsHandler, er
|
|||||||
c.ohm = om
|
c.ohm = om
|
||||||
}))
|
}))
|
||||||
expvar.Publish("stats", expvar.Func(func() interface{} {
|
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{
|
resp := map[string]map[string]map[string]int64{
|
||||||
"inbound": {},
|
"inbound": {},
|
||||||
"outbound": {},
|
"outbound": {},
|
||||||
"user": {},
|
"user": {},
|
||||||
}
|
}
|
||||||
manager.VisitCounters(func(name string, counter feature_stats.Counter) bool {
|
c.statsManager.VisitCounters(func(name string, counter feature_stats.Counter) bool {
|
||||||
nameSplit := strings.Split(name, ">>>")
|
nameSplit := strings.Split(name, ">>>")
|
||||||
typeName, tagOrUser, direction := nameSplit[0], nameSplit[1], nameSplit[3]
|
typeName, tagOrUser, direction := nameSplit[0], nameSplit[1], nameSplit[3]
|
||||||
if item, found := resp[typeName][tagOrUser]; found {
|
if item, found := resp[typeName][tagOrUser]; found {
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ func (o *Observer) GetObservation(ctx context.Context) (proto.Message, error) {
|
|||||||
return &observatory.ObservationResult{Status: o.createResult()}, nil
|
return &observatory.ObservationResult{Status: o.createResult()}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Observer) Check(tag []string) {
|
||||||
|
o.hp.Check(tag)
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Observer) createResult() []*observatory.OutboundStatus {
|
func (o *Observer) createResult() []*observatory.OutboundStatus {
|
||||||
var result []*observatory.OutboundStatus
|
var result []*observatory.OutboundStatus
|
||||||
o.hp.access.Lock()
|
o.hp.access.Lock()
|
||||||
|
|||||||
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/observatory/burst/config.proto
|
// source: app/observatory/burst/config.proto
|
||||||
|
|
||||||
package burst
|
package burst
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,13 +22,12 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// @Document The selectors for outbound under observation
|
// @Document The selectors for outbound under observation
|
||||||
SubjectSelector []string `protobuf:"bytes,2,rep,name=subject_selector,json=subjectSelector,proto3" json:"subject_selector,omitempty"`
|
SubjectSelector []string `protobuf:"bytes,2,rep,name=subject_selector,json=subjectSelector,proto3" json:"subject_selector,omitempty"`
|
||||||
PingConfig *HealthPingConfig `protobuf:"bytes,3,opt,name=ping_config,json=pingConfig,proto3" json:"ping_config,omitempty"`
|
PingConfig *HealthPingConfig `protobuf:"bytes,3,opt,name=ping_config,json=pingConfig,proto3" json:"ping_config,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -75,10 +75,7 @@ func (x *Config) GetPingConfig() *HealthPingConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HealthPingConfig struct {
|
type HealthPingConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// destination url, need 204 for success return
|
// destination url, need 204 for success return
|
||||||
// default https://connectivitycheck.gstatic.com/generate_204
|
// default https://connectivitycheck.gstatic.com/generate_204
|
||||||
Destination string `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"`
|
Destination string `protobuf:"bytes,1,opt,name=destination,proto3" json:"destination,omitempty"`
|
||||||
@@ -91,7 +88,9 @@ type HealthPingConfig struct {
|
|||||||
// ping timeout, int64 values of time.Duration
|
// ping timeout, int64 values of time.Duration
|
||||||
Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
||||||
// http method to make request
|
// http method to make request
|
||||||
HttpMethod string `protobuf:"bytes,6,opt,name=httpMethod,proto3" json:"httpMethod,omitempty"`
|
HttpMethod string `protobuf:"bytes,6,opt,name=httpMethod,proto3" json:"httpMethod,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *HealthPingConfig) Reset() {
|
func (x *HealthPingConfig) Reset() {
|
||||||
@@ -168,51 +167,32 @@ func (x *HealthPingConfig) GetHttpMethod() string {
|
|||||||
|
|
||||||
var File_app_observatory_burst_config_proto protoreflect.FileDescriptor
|
var File_app_observatory_burst_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_observatory_burst_config_proto_rawDesc = []byte{
|
const file_app_observatory_burst_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x22, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
|
"\n" +
|
||||||
0x79, 0x2f, 0x62, 0x75, 0x72, 0x73, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70,
|
"\"app/observatory/burst/config.proto\x12\x1fxray.core.app.observatory.burst\"\x87\x01\n" +
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1f, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e,
|
"\x06Config\x12)\n" +
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e,
|
"\x10subject_selector\x18\x02 \x03(\tR\x0fsubjectSelector\x12R\n" +
|
||||||
0x62, 0x75, 0x72, 0x73, 0x74, 0x22, 0x87, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
"\vping_config\x18\x03 \x01(\v21.xray.core.app.observatory.burst.HealthPingConfigR\n" +
|
||||||
0x12, 0x29, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x6c, 0x65,
|
"pingConfig\"\xd4\x01\n" +
|
||||||
0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x73, 0x75, 0x62, 0x6a,
|
"\x10HealthPingConfig\x12 \n" +
|
||||||
0x65, 0x63, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x52, 0x0a, 0x0b, 0x70,
|
"\vdestination\x18\x01 \x01(\tR\vdestination\x12\"\n" +
|
||||||
0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b,
|
"\fconnectivity\x18\x02 \x01(\tR\fconnectivity\x12\x1a\n" +
|
||||||
0x32, 0x31, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70,
|
"\binterval\x18\x03 \x01(\x03R\binterval\x12$\n" +
|
||||||
0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72,
|
"\rsamplingCount\x18\x04 \x01(\x05R\rsamplingCount\x12\x18\n" +
|
||||||
0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
"\atimeout\x18\x05 \x01(\x03R\atimeout\x12\x1e\n" +
|
||||||
0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
|
"\n" +
|
||||||
0xd4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
"httpMethod\x18\x06 \x01(\tR\n" +
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
"httpMethodBp\n" +
|
||||||
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69,
|
"\x1ecom.xray.app.observatory.burstP\x01Z/github.com/xtls/xray-core/app/observatory/burst\xaa\x02\x1aXray.App.Observatory.Burstb\x06proto3"
|
||||||
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
|
||||||
0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6f,
|
|
||||||
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e,
|
|
||||||
0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x69, 0x6e,
|
|
||||||
0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x69,
|
|
||||||
0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73,
|
|
||||||
0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07,
|
|
||||||
0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74,
|
|
||||||
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x4d, 0x65,
|
|
||||||
0x74, 0x68, 0x6f, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x74, 0x74, 0x70,
|
|
||||||
0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
|
|
||||||
0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 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, 0x62, 0x75, 0x72, 0x73, 0x74, 0xaa, 0x02, 0x1a, 0x58, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
|
|
||||||
0x72, 0x79, 0x2e, 0x42, 0x75, 0x72, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_observatory_burst_config_proto_rawDescOnce sync.Once
|
file_app_observatory_burst_config_proto_rawDescOnce sync.Once
|
||||||
file_app_observatory_burst_config_proto_rawDescData = file_app_observatory_burst_config_proto_rawDesc
|
file_app_observatory_burst_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_observatory_burst_config_proto_rawDescGZIP() []byte {
|
func file_app_observatory_burst_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_observatory_burst_config_proto_rawDescOnce.Do(func() {
|
file_app_observatory_burst_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_observatory_burst_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_observatory_burst_config_proto_rawDescData)
|
file_app_observatory_burst_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_observatory_burst_config_proto_rawDesc), len(file_app_observatory_burst_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_observatory_burst_config_proto_rawDescData
|
return file_app_observatory_burst_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -240,7 +220,7 @@ func file_app_observatory_burst_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_observatory_burst_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_observatory_burst_config_proto_rawDesc), len(file_app_observatory_burst_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 2,
|
NumMessages: 2,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -251,7 +231,6 @@ func file_app_observatory_burst_config_proto_init() {
|
|||||||
MessageInfos: file_app_observatory_burst_config_proto_msgTypes,
|
MessageInfos: file_app_observatory_burst_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_observatory_burst_config_proto = out.File
|
File_app_observatory_burst_config_proto = out.File
|
||||||
file_app_observatory_burst_config_proto_rawDesc = nil
|
|
||||||
file_app_observatory_burst_config_proto_goTypes = nil
|
file_app_observatory_burst_config_proto_goTypes = nil
|
||||||
file_app_observatory_burst_config_proto_depIdxs = nil
|
file_app_observatory_burst_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/utils"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet/tagged"
|
"github.com/xtls/xray-core/transport/internet/tagged"
|
||||||
)
|
)
|
||||||
@@ -61,6 +62,7 @@ func (s *pingClient) MeasureDelay(httpMethod string) (time.Duration, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return rttFailed, err
|
return rttFailed, err
|
||||||
}
|
}
|
||||||
|
utils.TryDefaultHeadersWith(req.Header, "nav")
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
resp, err := s.httpClient.Do(req)
|
resp, err := s.httpClient.Do(req)
|
||||||
|
|||||||
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/observatory/command/command.proto
|
// source: app/observatory/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -22,9 +23,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type GetOutboundStatusRequest struct {
|
type GetOutboundStatusRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetOutboundStatusRequest) Reset() {
|
func (x *GetOutboundStatusRequest) Reset() {
|
||||||
@@ -58,11 +59,10 @@ func (*GetOutboundStatusRequest) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetOutboundStatusResponse struct {
|
type GetOutboundStatusResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Status *observatory.ObservationResult `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Status *observatory.ObservationResult `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetOutboundStatusResponse) Reset() {
|
func (x *GetOutboundStatusResponse) Reset() {
|
||||||
@@ -103,9 +103,9 @@ func (x *GetOutboundStatusResponse) GetStatus() *observatory.ObservationResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -140,52 +140,25 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
|
|
||||||
var File_app_observatory_command_command_proto protoreflect.FileDescriptor
|
var File_app_observatory_command_command_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_observatory_command_command_proto_rawDesc = []byte{
|
const file_app_observatory_command_command_proto_rawDesc = "" +
|
||||||
0x0a, 0x25, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
|
"\n" +
|
||||||
0x79, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
"%app/observatory/command/command.proto\x12!xray.core.app.observatory.command\x1a\x1capp/observatory/config.proto\"\x1a\n" +
|
||||||
0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
"\x18GetOutboundStatusRequest\"a\n" +
|
||||||
0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
|
"\x19GetOutboundStatusResponse\x12D\n" +
|
||||||
0x72, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a, 0x1c, 0x61, 0x70, 0x70, 0x2f,
|
"\x06status\x18\x01 \x01(\v2,.xray.core.app.observatory.ObservationResultR\x06status\"\b\n" +
|
||||||
0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66,
|
"\x06Config2\xa7\x01\n" +
|
||||||
0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x4f,
|
"\x12ObservatoryService\x12\x90\x01\n" +
|
||||||
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71,
|
"\x11GetOutboundStatus\x12;.xray.core.app.observatory.command.GetOutboundStatusRequest\x1a<.xray.core.app.observatory.command.GetOutboundStatusResponse\"\x00B\x80\x01\n" +
|
||||||
0x75, 0x65, 0x73, 0x74, 0x22, 0x61, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
"%com.xray.core.app.observatory.commandP\x01Z1github.com/xtls/xray-core/app/observatory/command\xaa\x02!Xray.Core.App.Observatory.Commandb\x06proto3"
|
||||||
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 (
|
var (
|
||||||
file_app_observatory_command_command_proto_rawDescOnce sync.Once
|
file_app_observatory_command_command_proto_rawDescOnce sync.Once
|
||||||
file_app_observatory_command_command_proto_rawDescData = file_app_observatory_command_command_proto_rawDesc
|
file_app_observatory_command_command_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_observatory_command_command_proto_rawDescGZIP() []byte {
|
func file_app_observatory_command_command_proto_rawDescGZIP() []byte {
|
||||||
file_app_observatory_command_command_proto_rawDescOnce.Do(func() {
|
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)
|
file_app_observatory_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_observatory_command_command_proto_rawDesc), len(file_app_observatory_command_command_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_observatory_command_command_proto_rawDescData
|
return file_app_observatory_command_command_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -217,7 +190,7 @@ func file_app_observatory_command_command_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_observatory_command_command_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_observatory_command_command_proto_rawDesc), len(file_app_observatory_command_command_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 3,
|
NumMessages: 3,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -228,7 +201,6 @@ func file_app_observatory_command_command_proto_init() {
|
|||||||
MessageInfos: file_app_observatory_command_command_proto_msgTypes,
|
MessageInfos: file_app_observatory_command_command_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_observatory_command_command_proto = out.File
|
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_goTypes = nil
|
||||||
file_app_observatory_command_command_proto_depIdxs = nil
|
file_app_observatory_command_command_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.5.1
|
// - protoc-gen-go-grpc v1.6.0
|
||||||
// - protoc v5.28.2
|
// - protoc v6.33.5
|
||||||
// source: app/observatory/command/command.proto
|
// source: app/observatory/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
@@ -63,7 +63,7 @@ type ObservatoryServiceServer interface {
|
|||||||
type UnimplementedObservatoryServiceServer struct{}
|
type UnimplementedObservatoryServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedObservatoryServiceServer) GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) {
|
func (UnimplementedObservatoryServiceServer) GetOutboundStatus(context.Context, *GetOutboundStatusRequest) (*GetOutboundStatusResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetOutboundStatus not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetOutboundStatus not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedObservatoryServiceServer) mustEmbedUnimplementedObservatoryServiceServer() {}
|
func (UnimplementedObservatoryServiceServer) mustEmbedUnimplementedObservatoryServiceServer() {}
|
||||||
func (UnimplementedObservatoryServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedObservatoryServiceServer) testEmbeddedByValue() {}
|
||||||
@@ -76,7 +76,7 @@ type UnsafeObservatoryServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterObservatoryServiceServer(s grpc.ServiceRegistrar, srv ObservatoryServiceServer) {
|
func RegisterObservatoryServiceServer(s grpc.ServiceRegistrar, srv ObservatoryServiceServer) {
|
||||||
// If the following call pancis, it indicates UnimplementedObservatoryServiceServer was
|
// If the following call panics, it indicates UnimplementedObservatoryServiceServer was
|
||||||
// embedded by pointer and is nil. This will cause panics if an
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
// unimplemented method is ever invoked, so we test this at initialization
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
// time to prevent it from happening at runtime later due to I/O.
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
|||||||
+64
-104
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/observatory/config.proto
|
// source: app/observatory/config.proto
|
||||||
|
|
||||||
package observatory
|
package observatory
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,11 +22,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ObservationResult struct {
|
type ObservationResult struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Status []*OutboundStatus `protobuf:"bytes,1,rep,name=status,proto3" json:"status,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Status []*OutboundStatus `protobuf:"bytes,1,rep,name=status,proto3" json:"status,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ObservationResult) Reset() {
|
func (x *ObservationResult) Reset() {
|
||||||
@@ -66,16 +66,15 @@ func (x *ObservationResult) GetStatus() []*OutboundStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HealthPingMeasurementResult struct {
|
type HealthPingMeasurementResult struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
All int64 `protobuf:"varint,1,opt,name=all,proto3" json:"all,omitempty"`
|
||||||
|
Fail int64 `protobuf:"varint,2,opt,name=fail,proto3" json:"fail,omitempty"`
|
||||||
|
Deviation int64 `protobuf:"varint,3,opt,name=deviation,proto3" json:"deviation,omitempty"`
|
||||||
|
Average int64 `protobuf:"varint,4,opt,name=average,proto3" json:"average,omitempty"`
|
||||||
|
Max int64 `protobuf:"varint,5,opt,name=max,proto3" json:"max,omitempty"`
|
||||||
|
Min int64 `protobuf:"varint,6,opt,name=min,proto3" json:"min,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
All int64 `protobuf:"varint,1,opt,name=all,proto3" json:"all,omitempty"`
|
|
||||||
Fail int64 `protobuf:"varint,2,opt,name=fail,proto3" json:"fail,omitempty"`
|
|
||||||
Deviation int64 `protobuf:"varint,3,opt,name=deviation,proto3" json:"deviation,omitempty"`
|
|
||||||
Average int64 `protobuf:"varint,4,opt,name=average,proto3" json:"average,omitempty"`
|
|
||||||
Max int64 `protobuf:"varint,5,opt,name=max,proto3" json:"max,omitempty"`
|
|
||||||
Min int64 `protobuf:"varint,6,opt,name=min,proto3" json:"min,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *HealthPingMeasurementResult) Reset() {
|
func (x *HealthPingMeasurementResult) Reset() {
|
||||||
@@ -151,10 +150,7 @@ func (x *HealthPingMeasurementResult) GetMin() int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OutboundStatus struct {
|
type OutboundStatus struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// @Document Whether this outbound is usable
|
// @Document Whether this outbound is usable
|
||||||
// @Restriction ReadOnlyForUser
|
// @Restriction ReadOnlyForUser
|
||||||
Alive bool `protobuf:"varint,1,opt,name=alive,proto3" json:"alive,omitempty"`
|
Alive bool `protobuf:"varint,1,opt,name=alive,proto3" json:"alive,omitempty"`
|
||||||
@@ -173,8 +169,10 @@ type OutboundStatus struct {
|
|||||||
LastSeenTime int64 `protobuf:"varint,5,opt,name=last_seen_time,json=lastSeenTime,proto3" json:"last_seen_time,omitempty"`
|
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
|
// @Document The time this outbound is tried
|
||||||
// @Type id.outboundTag
|
// @Type id.outboundTag
|
||||||
LastTryTime int64 `protobuf:"varint,6,opt,name=last_try_time,json=lastTryTime,proto3" json:"last_try_time,omitempty"`
|
LastTryTime int64 `protobuf:"varint,6,opt,name=last_try_time,json=lastTryTime,proto3" json:"last_try_time,omitempty"`
|
||||||
HealthPing *HealthPingMeasurementResult `protobuf:"bytes,7,opt,name=health_ping,json=healthPing,proto3" json:"health_ping,omitempty"`
|
HealthPing *HealthPingMeasurementResult `protobuf:"bytes,7,opt,name=health_ping,json=healthPing,proto3" json:"health_ping,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *OutboundStatus) Reset() {
|
func (x *OutboundStatus) Reset() {
|
||||||
@@ -257,10 +255,7 @@ func (x *OutboundStatus) GetHealthPing() *HealthPingMeasurementResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ProbeResult struct {
|
type ProbeResult struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// @Document Whether this outbound is usable
|
// @Document Whether this outbound is usable
|
||||||
// @Restriction ReadOnlyForUser
|
// @Restriction ReadOnlyForUser
|
||||||
Alive bool `protobuf:"varint,1,opt,name=alive,proto3" json:"alive,omitempty"`
|
Alive bool `protobuf:"varint,1,opt,name=alive,proto3" json:"alive,omitempty"`
|
||||||
@@ -271,6 +266,8 @@ type ProbeResult struct {
|
|||||||
// @Document The error caused this outbound failed to relay probe request
|
// @Document The error caused this outbound failed to relay probe request
|
||||||
// @Restriction NotMachineReadable
|
// @Restriction NotMachineReadable
|
||||||
LastErrorReason string `protobuf:"bytes,3,opt,name=last_error_reason,json=lastErrorReason,proto3" json:"last_error_reason,omitempty"`
|
LastErrorReason string `protobuf:"bytes,3,opt,name=last_error_reason,json=lastErrorReason,proto3" json:"last_error_reason,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ProbeResult) Reset() {
|
func (x *ProbeResult) Reset() {
|
||||||
@@ -325,13 +322,12 @@ func (x *ProbeResult) GetLastErrorReason() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Intensity struct {
|
type Intensity struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// @Document The time interval for a probe request in ms.
|
// @Document The time interval for a probe request in ms.
|
||||||
// @Type time.ms
|
// @Type time.ms
|
||||||
ProbeInterval uint32 `protobuf:"varint,1,opt,name=probe_interval,json=probeInterval,proto3" json:"probe_interval,omitempty"`
|
ProbeInterval uint32 `protobuf:"varint,1,opt,name=probe_interval,json=probeInterval,proto3" json:"probe_interval,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Intensity) Reset() {
|
func (x *Intensity) Reset() {
|
||||||
@@ -372,15 +368,14 @@ func (x *Intensity) GetProbeInterval() uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// @Document The selectors for outbound under observation
|
// @Document The selectors for outbound under observation
|
||||||
SubjectSelector []string `protobuf:"bytes,2,rep,name=subject_selector,json=subjectSelector,proto3" json:"subject_selector,omitempty"`
|
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"`
|
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"`
|
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"`
|
EnableConcurrency bool `protobuf:"varint,5,opt,name=enable_concurrency,json=enableConcurrency,proto3" json:"enable_concurrency,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -443,82 +438,48 @@ func (x *Config) GetEnableConcurrency() bool {
|
|||||||
|
|
||||||
var File_app_observatory_config_proto protoreflect.FileDescriptor
|
var File_app_observatory_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_observatory_config_proto_rawDesc = []byte{
|
const file_app_observatory_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x1c, 0x61, 0x70, 0x70, 0x2f, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72,
|
"\n" +
|
||||||
0x79, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19,
|
"\x1capp/observatory/config.proto\x12\x19xray.core.app.observatory\"V\n" +
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62,
|
"\x11ObservationResult\x12A\n" +
|
||||||
0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x56, 0x0a, 0x11, 0x4f, 0x62, 0x73,
|
"\x06status\x18\x01 \x03(\v2).xray.core.app.observatory.OutboundStatusR\x06status\"\x9f\x01\n" +
|
||||||
0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x41,
|
"\x1bHealthPingMeasurementResult\x12\x10\n" +
|
||||||
0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29,
|
"\x03all\x18\x01 \x01(\x03R\x03all\x12\x12\n" +
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f,
|
"\x04fail\x18\x02 \x01(\x03R\x04fail\x12\x1c\n" +
|
||||||
0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
"\tdeviation\x18\x03 \x01(\x03R\tdeviation\x12\x18\n" +
|
||||||
0x75, 0x6e, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
|
"\aaverage\x18\x04 \x01(\x03R\aaverage\x12\x10\n" +
|
||||||
0x73, 0x22, 0x9f, 0x01, 0x0a, 0x1b, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67,
|
"\x03max\x18\x05 \x01(\x03R\x03max\x12\x10\n" +
|
||||||
0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c,
|
"\x03min\x18\x06 \x01(\x03R\x03min\"\xae\x02\n" +
|
||||||
0x74, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x6c, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03,
|
"\x0eOutboundStatus\x12\x14\n" +
|
||||||
0x61, 0x6c, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28,
|
"\x05alive\x18\x01 \x01(\bR\x05alive\x12\x14\n" +
|
||||||
0x03, 0x52, 0x04, 0x66, 0x61, 0x69, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x76, 0x69, 0x61,
|
"\x05delay\x18\x02 \x01(\x03R\x05delay\x12*\n" +
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x64, 0x65, 0x76, 0x69,
|
"\x11last_error_reason\x18\x03 \x01(\tR\x0flastErrorReason\x12!\n" +
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65,
|
"\foutbound_tag\x18\x04 \x01(\tR\voutboundTag\x12$\n" +
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x61, 0x76, 0x65, 0x72, 0x61, 0x67, 0x65, 0x12,
|
"\x0elast_seen_time\x18\x05 \x01(\x03R\flastSeenTime\x12\"\n" +
|
||||||
0x10, 0x0a, 0x03, 0x6d, 0x61, 0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03, 0x6d, 0x61,
|
"\rlast_try_time\x18\x06 \x01(\x03R\vlastTryTime\x12W\n" +
|
||||||
0x78, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x03,
|
"\vhealth_ping\x18\a \x01(\v26.xray.core.app.observatory.HealthPingMeasurementResultR\n" +
|
||||||
0x6d, 0x69, 0x6e, 0x22, 0xae, 0x02, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
"healthPing\"e\n" +
|
||||||
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x18,
|
"\vProbeResult\x12\x14\n" +
|
||||||
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x12, 0x14, 0x0a, 0x05,
|
"\x05alive\x18\x01 \x01(\bR\x05alive\x12\x14\n" +
|
||||||
0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x64, 0x65, 0x6c,
|
"\x05delay\x18\x02 \x01(\x03R\x05delay\x12*\n" +
|
||||||
0x61, 0x79, 0x12, 0x2a, 0x0a, 0x11, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72,
|
"\x11last_error_reason\x18\x03 \x01(\tR\x0flastErrorReason\"2\n" +
|
||||||
0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c,
|
"\tIntensity\x12%\n" +
|
||||||
0x61, 0x73, 0x74, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x21,
|
"\x0eprobe_interval\x18\x01 \x01(\rR\rprobeInterval\"\xa6\x01\n" +
|
||||||
0x0a, 0x0c, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x04,
|
"\x06Config\x12)\n" +
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61,
|
"\x10subject_selector\x18\x02 \x03(\tR\x0fsubjectSelector\x12\x1b\n" +
|
||||||
0x67, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x65, 0x65, 0x6e, 0x5f, 0x74,
|
"\tprobe_url\x18\x03 \x01(\tR\bprobeUrl\x12%\n" +
|
||||||
0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6c, 0x61, 0x73, 0x74, 0x53,
|
"\x0eprobe_interval\x18\x04 \x01(\x03R\rprobeInterval\x12-\n" +
|
||||||
0x65, 0x65, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6c, 0x61, 0x73, 0x74, 0x5f,
|
"\x12enable_concurrency\x18\x05 \x01(\bR\x11enableConcurrencyB^\n" +
|
||||||
0x74, 0x72, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
|
"\x18com.xray.app.observatoryP\x01Z)github.com/xtls/xray-core/app/observatory\xaa\x02\x14Xray.App.Observatoryb\x06proto3"
|
||||||
0x6c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x57, 0x0a, 0x0b, 0x68,
|
|
||||||
0x65, 0x61, 0x6c, 0x74, 0x68, 0x5f, 0x70, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b,
|
|
||||||
0x32, 0x36, 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, 0x48, 0x65, 0x61,
|
|
||||||
0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65,
|
|
||||||
0x6e, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x0a, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68,
|
|
||||||
0x50, 0x69, 0x6e, 0x67, 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 (
|
var (
|
||||||
file_app_observatory_config_proto_rawDescOnce sync.Once
|
file_app_observatory_config_proto_rawDescOnce sync.Once
|
||||||
file_app_observatory_config_proto_rawDescData = file_app_observatory_config_proto_rawDesc
|
file_app_observatory_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_observatory_config_proto_rawDescGZIP() []byte {
|
func file_app_observatory_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_observatory_config_proto_rawDescOnce.Do(func() {
|
file_app_observatory_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_observatory_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_observatory_config_proto_rawDescData)
|
file_app_observatory_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_observatory_config_proto_rawDesc), len(file_app_observatory_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_observatory_config_proto_rawDescData
|
return file_app_observatory_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -551,7 +512,7 @@ func file_app_observatory_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_observatory_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_observatory_config_proto_rawDesc), len(file_app_observatory_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 6,
|
NumMessages: 6,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -562,7 +523,6 @@ func file_app_observatory_config_proto_init() {
|
|||||||
MessageInfos: file_app_observatory_config_proto_msgTypes,
|
MessageInfos: file_app_observatory_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_observatory_config_proto = out.File
|
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_goTypes = nil
|
||||||
file_app_observatory_config_proto_depIdxs = nil
|
file_app_observatory_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -15,6 +16,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
|
"github.com/xtls/xray-core/common/utils"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/extension"
|
"github.com/xtls/xray-core/features/extension"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
@@ -69,7 +71,7 @@ func (o *Observer) background() {
|
|||||||
|
|
||||||
outbounds := hs.Select(o.config.SubjectSelector)
|
outbounds := hs.Select(o.config.SubjectSelector)
|
||||||
|
|
||||||
o.updateStatus(outbounds)
|
o.clearRemovedOutbounds(outbounds)
|
||||||
|
|
||||||
sleepTime := time.Second * 10
|
sleepTime := time.Second * 10
|
||||||
if o.config.ProbeInterval != 0 {
|
if o.config.ProbeInterval != 0 {
|
||||||
@@ -110,11 +112,19 @@ func (o *Observer) background() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Observer) updateStatus(outbounds []string) {
|
func (o *Observer) clearRemovedOutbounds(outbounds []string) {
|
||||||
o.statusLock.Lock()
|
o.statusLock.Lock()
|
||||||
defer o.statusLock.Unlock()
|
defer o.statusLock.Unlock()
|
||||||
// TODO should remove old inbound that is removed
|
if len(o.status) == 0 {
|
||||||
_ = outbounds
|
return
|
||||||
|
}
|
||||||
|
var pruned []*OutboundStatus
|
||||||
|
for _, status := range o.status {
|
||||||
|
if slices.Contains(outbounds, status.OutboundTag) {
|
||||||
|
pruned = append(pruned, status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o.status = pruned
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Observer) probe(outbound string) ProbeResult {
|
func (o *Observer) probe(outbound string) ProbeResult {
|
||||||
@@ -162,7 +172,9 @@ func (o *Observer) probe(outbound string) ProbeResult {
|
|||||||
if o.config.ProbeUrl != "" {
|
if o.config.ProbeUrl != "" {
|
||||||
probeURL = o.config.ProbeUrl
|
probeURL = o.config.ProbeUrl
|
||||||
}
|
}
|
||||||
response, err := httpClient.Get(probeURL)
|
req, _ := http.NewRequest(http.MethodGet, probeURL, nil)
|
||||||
|
utils.TryDefaultHeadersWith(req.Header, "nav")
|
||||||
|
response, err := httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("outbound failed to relay connection").Base(err)
|
return errors.New("outbound failed to relay connection").Base(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,64 @@
|
|||||||
|
package observatory
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestObserverUpdateStatusPrunesStaleOutbounds(t *testing.T) {
|
||||||
|
observer := &Observer{
|
||||||
|
status: []*OutboundStatus{
|
||||||
|
{
|
||||||
|
OutboundTag: "keep",
|
||||||
|
Alive: true,
|
||||||
|
Delay: 42,
|
||||||
|
LastErrorReason: "",
|
||||||
|
LastSeenTime: 111,
|
||||||
|
LastTryTime: 222,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
OutboundTag: "drop",
|
||||||
|
Alive: false,
|
||||||
|
Delay: 99999999,
|
||||||
|
LastErrorReason: "probe failed",
|
||||||
|
LastSeenTime: 333,
|
||||||
|
LastTryTime: 444,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
observer.clearRemovedOutbounds([]string{"keep"})
|
||||||
|
|
||||||
|
if len(observer.status) != 1 {
|
||||||
|
t.Fatalf("expected 1 status after pruning, got %d", len(observer.status))
|
||||||
|
}
|
||||||
|
|
||||||
|
got := observer.status[0]
|
||||||
|
if got.OutboundTag != "keep" {
|
||||||
|
t.Fatalf("expected remaining status for keep, got %q", got.OutboundTag)
|
||||||
|
}
|
||||||
|
if !got.Alive {
|
||||||
|
t.Fatal("expected remaining status to preserve Alive field")
|
||||||
|
}
|
||||||
|
if got.Delay != 42 {
|
||||||
|
t.Fatalf("expected remaining status to preserve Delay, got %d", got.Delay)
|
||||||
|
}
|
||||||
|
if got.LastSeenTime != 111 {
|
||||||
|
t.Fatalf("expected remaining status to preserve LastSeenTime, got %d", got.LastSeenTime)
|
||||||
|
}
|
||||||
|
if got.LastTryTime != 222 {
|
||||||
|
t.Fatalf("expected remaining status to preserve LastTryTime, got %d", got.LastTryTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestObserverUpdateStatusClearsWhenNoOutboundsRemain(t *testing.T) {
|
||||||
|
observer := &Observer{
|
||||||
|
status: []*OutboundStatus{
|
||||||
|
{OutboundTag: "drop-1"},
|
||||||
|
{OutboundTag: "drop-2"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
observer.clearRemovedOutbounds(nil)
|
||||||
|
|
||||||
|
if len(observer.status) != 0 {
|
||||||
|
t.Fatalf("expected all statuses to be removed, got %d", len(observer.status))
|
||||||
|
}
|
||||||
|
}
|
||||||
+84
-130
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/policy/config.proto
|
// source: app/policy/config.proto
|
||||||
|
|
||||||
package policy
|
package policy
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,11 +22,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Second struct {
|
type Second struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Second) Reset() {
|
func (x *Second) Reset() {
|
||||||
@@ -66,13 +66,12 @@ func (x *Second) GetValue() uint32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Policy struct {
|
type Policy struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Timeout *Policy_Timeout `protobuf:"bytes,1,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
||||||
|
Stats *Policy_Stats `protobuf:"bytes,2,opt,name=stats,proto3" json:"stats,omitempty"`
|
||||||
|
Buffer *Policy_Buffer `protobuf:"bytes,3,opt,name=buffer,proto3" json:"buffer,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Timeout *Policy_Timeout `protobuf:"bytes,1,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
|
||||||
Stats *Policy_Stats `protobuf:"bytes,2,opt,name=stats,proto3" json:"stats,omitempty"`
|
|
||||||
Buffer *Policy_Buffer `protobuf:"bytes,3,opt,name=buffer,proto3" json:"buffer,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Policy) Reset() {
|
func (x *Policy) Reset() {
|
||||||
@@ -127,11 +126,10 @@ func (x *Policy) GetBuffer() *Policy_Buffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SystemPolicy struct {
|
type SystemPolicy struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Stats *SystemPolicy_Stats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Stats *SystemPolicy_Stats `protobuf:"bytes,1,opt,name=stats,proto3" json:"stats,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SystemPolicy) Reset() {
|
func (x *SystemPolicy) Reset() {
|
||||||
@@ -172,12 +170,11 @@ func (x *SystemPolicy) GetStats() *SystemPolicy_Stats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Level map[uint32]*Policy `protobuf:"bytes,1,rep,name=level,proto3" json:"level,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
|
||||||
|
System *SystemPolicy `protobuf:"bytes,2,opt,name=system,proto3" json:"system,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Level map[uint32]*Policy `protobuf:"bytes,1,rep,name=level,proto3" json:"level,omitempty" protobuf_key:"varint,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
|
||||||
System *SystemPolicy `protobuf:"bytes,2,opt,name=system,proto3" json:"system,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -226,14 +223,13 @@ func (x *Config) GetSystem() *SystemPolicy {
|
|||||||
|
|
||||||
// Timeout is a message for timeout settings in various stages, in seconds.
|
// Timeout is a message for timeout settings in various stages, in seconds.
|
||||||
type Policy_Timeout struct {
|
type Policy_Timeout struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Handshake *Second `protobuf:"bytes,1,opt,name=handshake,proto3" json:"handshake,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
ConnectionIdle *Second `protobuf:"bytes,2,opt,name=connection_idle,json=connectionIdle,proto3" json:"connection_idle,omitempty"`
|
||||||
|
UplinkOnly *Second `protobuf:"bytes,3,opt,name=uplink_only,json=uplinkOnly,proto3" json:"uplink_only,omitempty"`
|
||||||
Handshake *Second `protobuf:"bytes,1,opt,name=handshake,proto3" json:"handshake,omitempty"`
|
DownlinkOnly *Second `protobuf:"bytes,4,opt,name=downlink_only,json=downlinkOnly,proto3" json:"downlink_only,omitempty"`
|
||||||
ConnectionIdle *Second `protobuf:"bytes,2,opt,name=connection_idle,json=connectionIdle,proto3" json:"connection_idle,omitempty"`
|
unknownFields protoimpl.UnknownFields
|
||||||
UplinkOnly *Second `protobuf:"bytes,3,opt,name=uplink_only,json=uplinkOnly,proto3" json:"uplink_only,omitempty"`
|
sizeCache protoimpl.SizeCache
|
||||||
DownlinkOnly *Second `protobuf:"bytes,4,opt,name=downlink_only,json=downlinkOnly,proto3" json:"downlink_only,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Policy_Timeout) Reset() {
|
func (x *Policy_Timeout) Reset() {
|
||||||
@@ -295,13 +291,12 @@ func (x *Policy_Timeout) GetDownlinkOnly() *Second {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Policy_Stats struct {
|
type Policy_Stats struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
UserUplink bool `protobuf:"varint,1,opt,name=user_uplink,json=userUplink,proto3" json:"user_uplink,omitempty"`
|
||||||
|
UserDownlink bool `protobuf:"varint,2,opt,name=user_downlink,json=userDownlink,proto3" json:"user_downlink,omitempty"`
|
||||||
|
UserOnline bool `protobuf:"varint,3,opt,name=user_online,json=userOnline,proto3" json:"user_online,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
UserUplink bool `protobuf:"varint,1,opt,name=user_uplink,json=userUplink,proto3" json:"user_uplink,omitempty"`
|
|
||||||
UserDownlink bool `protobuf:"varint,2,opt,name=user_downlink,json=userDownlink,proto3" json:"user_downlink,omitempty"`
|
|
||||||
UserOnline bool `protobuf:"varint,3,opt,name=user_online,json=userOnline,proto3" json:"user_online,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Policy_Stats) Reset() {
|
func (x *Policy_Stats) Reset() {
|
||||||
@@ -356,12 +351,11 @@ func (x *Policy_Stats) GetUserOnline() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Policy_Buffer struct {
|
type Policy_Buffer struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// Buffer size per connection, in bytes. -1 for unlimited buffer.
|
// Buffer size per connection, in bytes. -1 for unlimited buffer.
|
||||||
Connection int32 `protobuf:"varint,1,opt,name=connection,proto3" json:"connection,omitempty"`
|
Connection int32 `protobuf:"varint,1,opt,name=connection,proto3" json:"connection,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Policy_Buffer) Reset() {
|
func (x *Policy_Buffer) Reset() {
|
||||||
@@ -402,14 +396,13 @@ func (x *Policy_Buffer) GetConnection() int32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SystemPolicy_Stats struct {
|
type SystemPolicy_Stats struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
InboundUplink bool `protobuf:"varint,1,opt,name=inbound_uplink,json=inboundUplink,proto3" json:"inbound_uplink,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
InboundDownlink bool `protobuf:"varint,2,opt,name=inbound_downlink,json=inboundDownlink,proto3" json:"inbound_downlink,omitempty"`
|
||||||
|
OutboundUplink bool `protobuf:"varint,3,opt,name=outbound_uplink,json=outboundUplink,proto3" json:"outbound_uplink,omitempty"`
|
||||||
InboundUplink bool `protobuf:"varint,1,opt,name=inbound_uplink,json=inboundUplink,proto3" json:"inbound_uplink,omitempty"`
|
OutboundDownlink bool `protobuf:"varint,4,opt,name=outbound_downlink,json=outboundDownlink,proto3" json:"outbound_downlink,omitempty"`
|
||||||
InboundDownlink bool `protobuf:"varint,2,opt,name=inbound_downlink,json=inboundDownlink,proto3" json:"inbound_downlink,omitempty"`
|
unknownFields protoimpl.UnknownFields
|
||||||
OutboundUplink bool `protobuf:"varint,3,opt,name=outbound_uplink,json=outboundUplink,proto3" json:"outbound_uplink,omitempty"`
|
sizeCache protoimpl.SizeCache
|
||||||
OutboundDownlink bool `protobuf:"varint,4,opt,name=outbound_downlink,json=outboundDownlink,proto3" json:"outbound_downlink,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SystemPolicy_Stats) Reset() {
|
func (x *SystemPolicy_Stats) Reset() {
|
||||||
@@ -472,93 +465,55 @@ func (x *SystemPolicy_Stats) GetOutboundDownlink() bool {
|
|||||||
|
|
||||||
var File_app_policy_config_proto protoreflect.FileDescriptor
|
var File_app_policy_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_policy_config_proto_rawDesc = []byte{
|
const file_app_policy_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2f, 0x63, 0x6f, 0x6e,
|
"\n" +
|
||||||
0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
"\x17app/policy/config.proto\x12\x0fxray.app.policy\"\x1e\n" +
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x22, 0x1e, 0x0a, 0x06, 0x53, 0x65,
|
"\x06Second\x12\x14\n" +
|
||||||
0x63, 0x6f, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20,
|
"\x05value\x18\x01 \x01(\rR\x05value\"\xc7\x04\n" +
|
||||||
0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc7, 0x04, 0x0a, 0x06, 0x50,
|
"\x06Policy\x129\n" +
|
||||||
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
|
"\atimeout\x18\x01 \x01(\v2\x1f.xray.app.policy.Policy.TimeoutR\atimeout\x123\n" +
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
"\x05stats\x18\x02 \x01(\v2\x1d.xray.app.policy.Policy.StatsR\x05stats\x126\n" +
|
||||||
0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
|
"\x06buffer\x18\x03 \x01(\v2\x1e.xray.app.policy.Policy.BufferR\x06buffer\x1a\xfa\x01\n" +
|
||||||
0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
|
"\aTimeout\x125\n" +
|
||||||
0x12, 0x33, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
"\thandshake\x18\x01 \x01(\v2\x17.xray.app.policy.SecondR\thandshake\x12@\n" +
|
||||||
0x1d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63,
|
"\x0fconnection_idle\x18\x02 \x01(\v2\x17.xray.app.policy.SecondR\x0econnectionIdle\x128\n" +
|
||||||
0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05,
|
"\vuplink_only\x18\x03 \x01(\v2\x17.xray.app.policy.SecondR\n" +
|
||||||
0x73, 0x74, 0x61, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x18,
|
"uplinkOnly\x12<\n" +
|
||||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
"\rdownlink_only\x18\x04 \x01(\v2\x17.xray.app.policy.SecondR\fdownlinkOnly\x1an\n" +
|
||||||
0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x42,
|
"\x05Stats\x12\x1f\n" +
|
||||||
0x75, 0x66, 0x66, 0x65, 0x72, 0x52, 0x06, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x1a, 0xfa, 0x01,
|
"\vuser_uplink\x18\x01 \x01(\bR\n" +
|
||||||
0x0a, 0x07, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x35, 0x0a, 0x09, 0x68, 0x61, 0x6e,
|
"userUplink\x12#\n" +
|
||||||
0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78,
|
"\ruser_downlink\x18\x02 \x01(\bR\fuserDownlink\x12\x1f\n" +
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53,
|
"\vuser_online\x18\x03 \x01(\bR\n" +
|
||||||
0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x09, 0x68, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65,
|
"userOnline\x1a(\n" +
|
||||||
0x12, 0x40, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69,
|
"\x06Buffer\x12\x1e\n" +
|
||||||
0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
"\n" +
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f,
|
"connection\x18\x01 \x01(\x05R\n" +
|
||||||
0x6e, 0x64, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64,
|
"connection\"\xfb\x01\n" +
|
||||||
0x6c, 0x65, 0x12, 0x38, 0x0a, 0x0b, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x6f, 0x6e, 0x6c,
|
"\fSystemPolicy\x129\n" +
|
||||||
0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
"\x05stats\x18\x01 \x01(\v2#.xray.app.policy.SystemPolicy.StatsR\x05stats\x1a\xaf\x01\n" +
|
||||||
0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64,
|
"\x05Stats\x12%\n" +
|
||||||
0x52, 0x0a, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x3c, 0x0a, 0x0d,
|
"\x0einbound_uplink\x18\x01 \x01(\bR\rinboundUplink\x12)\n" +
|
||||||
0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x04, 0x20,
|
"\x10inbound_downlink\x18\x02 \x01(\bR\x0finboundDownlink\x12'\n" +
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
|
"\x0foutbound_uplink\x18\x03 \x01(\bR\x0eoutboundUplink\x12+\n" +
|
||||||
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x52, 0x0c, 0x64, 0x6f,
|
"\x11outbound_downlink\x18\x04 \x01(\bR\x10outboundDownlink\"\xcc\x01\n" +
|
||||||
0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x4f, 0x6e, 0x6c, 0x79, 0x1a, 0x6e, 0x0a, 0x05, 0x53, 0x74,
|
"\x06Config\x128\n" +
|
||||||
0x61, 0x74, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x6c, 0x69,
|
"\x05level\x18\x01 \x03(\v2\".xray.app.policy.Config.LevelEntryR\x05level\x125\n" +
|
||||||
0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x55, 0x70,
|
"\x06system\x18\x02 \x01(\v2\x1d.xray.app.policy.SystemPolicyR\x06system\x1aQ\n" +
|
||||||
0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x64, 0x6f, 0x77,
|
"\n" +
|
||||||
0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x75, 0x73, 0x65,
|
"LevelEntry\x12\x10\n" +
|
||||||
0x72, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x73, 0x65,
|
"\x03key\x18\x01 \x01(\rR\x03key\x12-\n" +
|
||||||
0x72, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a,
|
"\x05value\x18\x02 \x01(\v2\x17.xray.app.policy.PolicyR\x05value:\x028\x01BO\n" +
|
||||||
0x75, 0x73, 0x65, 0x72, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x1a, 0x28, 0x0a, 0x06, 0x42, 0x75,
|
"\x13com.xray.app.policyP\x01Z$github.com/xtls/xray-core/app/policy\xaa\x02\x0fXray.App.Policyb\x06proto3"
|
||||||
0x66, 0x66, 0x65, 0x72, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69,
|
|
||||||
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x22, 0xfb, 0x01, 0x0a, 0x0c, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50,
|
|
||||||
0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x39, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x01,
|
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
|
||||||
0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x50, 0x6f, 0x6c,
|
|
||||||
0x69, 0x63, 0x79, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73,
|
|
||||||
0x1a, 0xaf, 0x01, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x69, 0x6e,
|
|
||||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x01, 0x20, 0x01,
|
|
||||||
0x28, 0x08, 0x52, 0x0d, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x70, 0x6c, 0x69, 0x6e,
|
|
||||||
0x6b, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x64, 0x6f, 0x77,
|
|
||||||
0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x69, 0x6e, 0x62,
|
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x27, 0x0a, 0x0f,
|
|
||||||
0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x75, 0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x18,
|
|
||||||
0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55,
|
|
||||||
0x70, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
|
|
||||||
0x64, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
|
|
||||||
0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x69,
|
|
||||||
0x6e, 0x6b, 0x22, 0xcc, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x38, 0x0a,
|
|
||||||
0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x43,
|
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
|
||||||
0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x35, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65,
|
|
||||||
0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
|
||||||
0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
|
|
||||||
0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x1a, 0x51,
|
|
||||||
0x0a, 0x0a, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
|
|
||||||
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2d,
|
|
||||||
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
|
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e,
|
|
||||||
0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
|
||||||
0x01, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
|
||||||
0x70, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 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, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79,
|
|
||||||
0xaa, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x69,
|
|
||||||
0x63, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_policy_config_proto_rawDescOnce sync.Once
|
file_app_policy_config_proto_rawDescOnce sync.Once
|
||||||
file_app_policy_config_proto_rawDescData = file_app_policy_config_proto_rawDesc
|
file_app_policy_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_policy_config_proto_rawDescGZIP() []byte {
|
func file_app_policy_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_policy_config_proto_rawDescOnce.Do(func() {
|
file_app_policy_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_policy_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_policy_config_proto_rawDescData)
|
file_app_policy_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_policy_config_proto_rawDesc), len(file_app_policy_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_policy_config_proto_rawDescData
|
return file_app_policy_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -603,7 +558,7 @@ func file_app_policy_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_policy_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_policy_config_proto_rawDesc), len(file_app_policy_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 9,
|
NumMessages: 9,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -614,7 +569,6 @@ func file_app_policy_config_proto_init() {
|
|||||||
MessageInfos: file_app_policy_config_proto_msgTypes,
|
MessageInfos: file_app_policy_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_policy_config_proto = out.File
|
File_app_policy_config_proto = out.File
|
||||||
file_app_policy_config_proto_rawDesc = nil
|
|
||||||
file_app_policy_config_proto_goTypes = nil
|
file_app_policy_config_proto_goTypes = nil
|
||||||
file_app_policy_config_proto_depIdxs = nil
|
file_app_policy_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
+124
-249
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/proxyman/command/command.proto
|
// source: app/proxyman/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -24,11 +25,10 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type AddUserOperation struct {
|
type AddUserOperation struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
User *protocol.User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
User *protocol.User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AddUserOperation) Reset() {
|
func (x *AddUserOperation) Reset() {
|
||||||
@@ -69,11 +69,10 @@ func (x *AddUserOperation) GetUser() *protocol.User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RemoveUserOperation struct {
|
type RemoveUserOperation struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RemoveUserOperation) Reset() {
|
func (x *RemoveUserOperation) Reset() {
|
||||||
@@ -114,11 +113,10 @@ func (x *RemoveUserOperation) GetEmail() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddInboundRequest struct {
|
type AddInboundRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Inbound *core.InboundHandlerConfig `protobuf:"bytes,1,opt,name=inbound,proto3" json:"inbound,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Inbound *core.InboundHandlerConfig `protobuf:"bytes,1,opt,name=inbound,proto3" json:"inbound,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AddInboundRequest) Reset() {
|
func (x *AddInboundRequest) Reset() {
|
||||||
@@ -159,9 +157,9 @@ func (x *AddInboundRequest) GetInbound() *core.InboundHandlerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddInboundResponse struct {
|
type AddInboundResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AddInboundResponse) Reset() {
|
func (x *AddInboundResponse) Reset() {
|
||||||
@@ -195,11 +193,10 @@ func (*AddInboundResponse) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RemoveInboundRequest struct {
|
type RemoveInboundRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RemoveInboundRequest) Reset() {
|
func (x *RemoveInboundRequest) Reset() {
|
||||||
@@ -240,9 +237,9 @@ func (x *RemoveInboundRequest) GetTag() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RemoveInboundResponse struct {
|
type RemoveInboundResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RemoveInboundResponse) Reset() {
|
func (x *RemoveInboundResponse) Reset() {
|
||||||
@@ -276,12 +273,11 @@ func (*RemoveInboundResponse) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AlterInboundRequest struct {
|
type AlterInboundRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
|
Operation *serial.TypedMessage `protobuf:"bytes,2,opt,name=operation,proto3" json:"operation,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
|
||||||
Operation *serial.TypedMessage `protobuf:"bytes,2,opt,name=operation,proto3" json:"operation,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AlterInboundRequest) Reset() {
|
func (x *AlterInboundRequest) Reset() {
|
||||||
@@ -329,9 +325,9 @@ func (x *AlterInboundRequest) GetOperation() *serial.TypedMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AlterInboundResponse struct {
|
type AlterInboundResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AlterInboundResponse) Reset() {
|
func (x *AlterInboundResponse) Reset() {
|
||||||
@@ -365,11 +361,10 @@ func (*AlterInboundResponse) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListInboundsRequest struct {
|
type ListInboundsRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
IsOnlyTags bool `protobuf:"varint,1,opt,name=isOnlyTags,proto3" json:"isOnlyTags,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
IsOnlyTags bool `protobuf:"varint,1,opt,name=isOnlyTags,proto3" json:"isOnlyTags,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListInboundsRequest) Reset() {
|
func (x *ListInboundsRequest) Reset() {
|
||||||
@@ -410,11 +405,10 @@ func (x *ListInboundsRequest) GetIsOnlyTags() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListInboundsResponse struct {
|
type ListInboundsResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Inbounds []*core.InboundHandlerConfig `protobuf:"bytes,1,rep,name=inbounds,proto3" json:"inbounds,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Inbounds []*core.InboundHandlerConfig `protobuf:"bytes,1,rep,name=inbounds,proto3" json:"inbounds,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListInboundsResponse) Reset() {
|
func (x *ListInboundsResponse) Reset() {
|
||||||
@@ -455,12 +449,11 @@ func (x *ListInboundsResponse) GetInbounds() []*core.InboundHandlerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetInboundUserRequest struct {
|
type GetInboundUserRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
|
Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
|
||||||
Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUserRequest) Reset() {
|
func (x *GetInboundUserRequest) Reset() {
|
||||||
@@ -508,11 +501,10 @@ func (x *GetInboundUserRequest) GetEmail() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetInboundUserResponse struct {
|
type GetInboundUserResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Users []*protocol.User `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUserResponse) Reset() {
|
func (x *GetInboundUserResponse) Reset() {
|
||||||
@@ -553,11 +545,10 @@ func (x *GetInboundUserResponse) GetUsers() []*protocol.User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type GetInboundUsersCountResponse struct {
|
type GetInboundUsersCountResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Count int64 `protobuf:"varint,1,opt,name=count,proto3" json:"count,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUsersCountResponse) Reset() {
|
func (x *GetInboundUsersCountResponse) Reset() {
|
||||||
@@ -598,11 +589,10 @@ func (x *GetInboundUsersCountResponse) GetCount() int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddOutboundRequest struct {
|
type AddOutboundRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Outbound *core.OutboundHandlerConfig `protobuf:"bytes,1,opt,name=outbound,proto3" json:"outbound,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Outbound *core.OutboundHandlerConfig `protobuf:"bytes,1,opt,name=outbound,proto3" json:"outbound,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AddOutboundRequest) Reset() {
|
func (x *AddOutboundRequest) Reset() {
|
||||||
@@ -643,9 +633,9 @@ func (x *AddOutboundRequest) GetOutbound() *core.OutboundHandlerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AddOutboundResponse struct {
|
type AddOutboundResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AddOutboundResponse) Reset() {
|
func (x *AddOutboundResponse) Reset() {
|
||||||
@@ -679,11 +669,10 @@ func (*AddOutboundResponse) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RemoveOutboundRequest struct {
|
type RemoveOutboundRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RemoveOutboundRequest) Reset() {
|
func (x *RemoveOutboundRequest) Reset() {
|
||||||
@@ -724,9 +713,9 @@ func (x *RemoveOutboundRequest) GetTag() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RemoveOutboundResponse struct {
|
type RemoveOutboundResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RemoveOutboundResponse) Reset() {
|
func (x *RemoveOutboundResponse) Reset() {
|
||||||
@@ -760,12 +749,11 @@ func (*RemoveOutboundResponse) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AlterOutboundRequest struct {
|
type AlterOutboundRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
|
Operation *serial.TypedMessage `protobuf:"bytes,2,opt,name=operation,proto3" json:"operation,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
|
||||||
Operation *serial.TypedMessage `protobuf:"bytes,2,opt,name=operation,proto3" json:"operation,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AlterOutboundRequest) Reset() {
|
func (x *AlterOutboundRequest) Reset() {
|
||||||
@@ -813,9 +801,9 @@ func (x *AlterOutboundRequest) GetOperation() *serial.TypedMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AlterOutboundResponse struct {
|
type AlterOutboundResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AlterOutboundResponse) Reset() {
|
func (x *AlterOutboundResponse) Reset() {
|
||||||
@@ -849,9 +837,9 @@ func (*AlterOutboundResponse) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListOutboundsRequest struct {
|
type ListOutboundsRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListOutboundsRequest) Reset() {
|
func (x *ListOutboundsRequest) Reset() {
|
||||||
@@ -885,11 +873,10 @@ func (*ListOutboundsRequest) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ListOutboundsResponse struct {
|
type ListOutboundsResponse struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Outbounds []*core.OutboundHandlerConfig `protobuf:"bytes,1,rep,name=outbounds,proto3" json:"outbounds,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Outbounds []*core.OutboundHandlerConfig `protobuf:"bytes,1,rep,name=outbounds,proto3" json:"outbounds,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ListOutboundsResponse) Reset() {
|
func (x *ListOutboundsResponse) Reset() {
|
||||||
@@ -930,9 +917,9 @@ func (x *ListOutboundsResponse) GetOutbounds() []*core.OutboundHandlerConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -967,183 +954,72 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
|
|
||||||
var File_app_proxyman_command_command_proto protoreflect.FileDescriptor
|
var File_app_proxyman_command_command_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_proxyman_command_command_proto_rawDesc = []byte{
|
const file_app_proxyman_command_command_proto_rawDesc = "" +
|
||||||
0x0a, 0x22, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63,
|
"\n" +
|
||||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70,
|
"\"app/proxyman/command/command.proto\x12\x19xray.app.proxyman.command\x1a\x1acommon/protocol/user.proto\x1a!common/serial/typed_message.proto\x1a\x11core/config.proto\"B\n" +
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x19, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
|
"\x10AddUserOperation\x12.\n" +
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x1a,
|
"\x04user\x18\x01 \x01(\v2\x1a.xray.common.protocol.UserR\x04user\"+\n" +
|
||||||
0x1a, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c,
|
"\x13RemoveUserOperation\x12\x14\n" +
|
||||||
0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d,
|
"\x05email\x18\x01 \x01(\tR\x05email\"N\n" +
|
||||||
0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64,
|
"\x11AddInboundRequest\x129\n" +
|
||||||
0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x11,
|
"\ainbound\x18\x01 \x01(\v2\x1f.xray.core.InboundHandlerConfigR\ainbound\"\x14\n" +
|
||||||
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
"\x12AddInboundResponse\"(\n" +
|
||||||
0x6f, 0x22, 0x42, 0x0a, 0x10, 0x41, 0x64, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x72,
|
"\x14RemoveInboundRequest\x12\x10\n" +
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2e, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, 0x20,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\"\x17\n" +
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
"\x15RemoveInboundResponse\"g\n" +
|
||||||
0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52,
|
"\x13AlterInboundRequest\x12\x10\n" +
|
||||||
0x04, 0x75, 0x73, 0x65, 0x72, 0x22, 0x2b, 0x0a, 0x13, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x12>\n" +
|
||||||
0x73, 0x65, 0x72, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05,
|
"\toperation\x18\x02 \x01(\v2 .xray.common.serial.TypedMessageR\toperation\"\x16\n" +
|
||||||
0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61,
|
"\x14AlterInboundResponse\"5\n" +
|
||||||
0x69, 0x6c, 0x22, 0x4e, 0x0a, 0x11, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
"\x13ListInboundsRequest\x12\x1e\n" +
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x39, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75,
|
"\n" +
|
||||||
0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
"isOnlyTags\x18\x01 \x01(\bR\n" +
|
||||||
0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64,
|
"isOnlyTags\"S\n" +
|
||||||
0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75,
|
"\x14ListInboundsResponse\x12;\n" +
|
||||||
0x6e, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
"\binbounds\x18\x01 \x03(\v2\x1f.xray.core.InboundHandlerConfigR\binbounds\"?\n" +
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f,
|
"\x15GetInboundUserRequest\x12\x10\n" +
|
||||||
0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x12\x14\n" +
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
|
"\x05email\x18\x02 \x01(\tR\x05email\"J\n" +
|
||||||
0x61, 0x67, 0x22, 0x17, 0x0a, 0x15, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f,
|
"\x16GetInboundUserResponse\x120\n" +
|
||||||
0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x67, 0x0a, 0x13, 0x41,
|
"\x05users\x18\x01 \x03(\v2\x1a.xray.common.protocol.UserR\x05users\"4\n" +
|
||||||
0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
|
"\x1cGetInboundUsersCountResponse\x12\x14\n" +
|
||||||
0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
"\x05count\x18\x01 \x01(\x03R\x05count\"R\n" +
|
||||||
0x03, 0x74, 0x61, 0x67, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
"\x12AddOutboundRequest\x12<\n" +
|
||||||
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
"\boutbound\x18\x01 \x01(\v2 .xray.core.OutboundHandlerConfigR\boutbound\"\x15\n" +
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70,
|
"\x13AddOutboundResponse\")\n" +
|
||||||
0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61,
|
"\x15RemoveOutboundRequest\x12\x10\n" +
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\"\x18\n" +
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x13,
|
"\x16RemoveOutboundResponse\"h\n" +
|
||||||
0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75,
|
"\x14AlterOutboundRequest\x12\x10\n" +
|
||||||
0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x54, 0x61, 0x67,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x12>\n" +
|
||||||
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x54,
|
"\toperation\x18\x02 \x01(\v2 .xray.common.serial.TypedMessageR\toperation\"\x17\n" +
|
||||||
0x61, 0x67, 0x73, 0x22, 0x53, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75,
|
"\x15AlterOutboundResponse\"\x16\n" +
|
||||||
0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x69,
|
"\x14ListOutboundsRequest\"W\n" +
|
||||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
|
"\x15ListOutboundsResponse\x12>\n" +
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
"\toutbounds\x18\x01 \x03(\v2 .xray.core.OutboundHandlerConfigR\toutbounds\"\b\n" +
|
||||||
0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08,
|
"\x06Config2\xae\t\n" +
|
||||||
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x3f, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49,
|
"\x0eHandlerService\x12k\n" +
|
||||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
"\n" +
|
||||||
0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
"AddInbound\x12,.xray.app.proxyman.command.AddInboundRequest\x1a-.xray.app.proxyman.command.AddInboundResponse\"\x00\x12t\n" +
|
||||||
0x74, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01,
|
"\rRemoveInbound\x12/.xray.app.proxyman.command.RemoveInboundRequest\x1a0.xray.app.proxyman.command.RemoveInboundResponse\"\x00\x12q\n" +
|
||||||
0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a, 0x16, 0x47, 0x65, 0x74,
|
"\fAlterInbound\x12..xray.app.proxyman.command.AlterInboundRequest\x1a/.xray.app.proxyman.command.AlterInboundResponse\"\x00\x12q\n" +
|
||||||
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
"\fListInbounds\x12..xray.app.proxyman.command.ListInboundsRequest\x1a/.xray.app.proxyman.command.ListInboundsResponse\"\x00\x12x\n" +
|
||||||
0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03,
|
"\x0fGetInboundUsers\x120.xray.app.proxyman.command.GetInboundUserRequest\x1a1.xray.app.proxyman.command.GetInboundUserResponse\"\x00\x12\x83\x01\n" +
|
||||||
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
"\x14GetInboundUsersCount\x120.xray.app.proxyman.command.GetInboundUserRequest\x1a7.xray.app.proxyman.command.GetInboundUsersCountResponse\"\x00\x12n\n" +
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05,
|
"\vAddOutbound\x12-.xray.app.proxyman.command.AddOutboundRequest\x1a..xray.app.proxyman.command.AddOutboundResponse\"\x00\x12w\n" +
|
||||||
0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f,
|
"\x0eRemoveOutbound\x120.xray.app.proxyman.command.RemoveOutboundRequest\x1a1.xray.app.proxyman.command.RemoveOutboundResponse\"\x00\x12t\n" +
|
||||||
0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73,
|
"\rAlterOutbound\x12/.xray.app.proxyman.command.AlterOutboundRequest\x1a0.xray.app.proxyman.command.AlterOutboundResponse\"\x00\x12t\n" +
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01,
|
"\rListOutbounds\x12/.xray.app.proxyman.command.ListOutboundsRequest\x1a0.xray.app.proxyman.command.ListOutboundsResponse\"\x00Bm\n" +
|
||||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x52, 0x0a, 0x12, 0x41,
|
"\x1dcom.xray.app.proxyman.commandP\x01Z.github.com/xtls/xray-core/app/proxyman/command\xaa\x02\x19Xray.App.Proxyman.Commandb\x06proto3"
|
||||||
0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
|
||||||
0x74, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20,
|
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e,
|
|
||||||
0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43,
|
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22,
|
|
||||||
0x15, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65,
|
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x15, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
|
||||||
0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
|
||||||
0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61,
|
|
||||||
0x67, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
|
||||||
0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x14, 0x41,
|
|
||||||
0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
|
||||||
0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
|
||||||
0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
|
|
||||||
0x6f, 0x6e, 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, 0x09, 0x6f, 0x70, 0x65, 0x72,
|
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75,
|
|
||||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16,
|
|
||||||
0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52,
|
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x57, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75,
|
|
||||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
|
||||||
0x3e, 0x0a, 0x09, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03,
|
|
||||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f,
|
|
||||||
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f,
|
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22,
|
|
||||||
0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xae, 0x09, 0x0a, 0x0e, 0x48, 0x61,
|
|
||||||
0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x0a,
|
|
||||||
0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63,
|
|
||||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
|
||||||
0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52,
|
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, 0x52, 0x65, 0x6d,
|
|
||||||
0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63,
|
|
||||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62,
|
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72,
|
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e,
|
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e,
|
|
||||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
|
||||||
0x71, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12,
|
|
||||||
0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
|
||||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
|
||||||
0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
|
||||||
0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
|
||||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
|
||||||
0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
|
||||||
0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
|
||||||
0x64, 0x73, 0x12, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
|
||||||
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c,
|
|
||||||
0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
|
||||||
0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
|
||||||
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c,
|
|
||||||
0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
|
||||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x78, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f,
|
|
||||||
0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55,
|
|
||||||
0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63,
|
|
||||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
|
||||||
0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
|
||||||
0x83, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73,
|
|
||||||
0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
|
||||||
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55,
|
|
||||||
0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61,
|
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63,
|
|
||||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
|
||||||
0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
|
||||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6e, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62,
|
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
|
|
||||||
0x2e, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
|
||||||
0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
|
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
|
||||||
0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
|
||||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x77, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f,
|
|
||||||
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
|
||||||
0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
|
||||||
0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
|
||||||
0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f,
|
|
||||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62,
|
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74,
|
|
||||||
0x0a, 0x0d, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12,
|
|
||||||
0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
|
||||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
|
||||||
0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
|
||||||
0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
|
||||||
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74,
|
|
||||||
0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
|
||||||
0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62,
|
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
|
||||||
0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52,
|
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
|
||||||
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
|
||||||
0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73,
|
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f,
|
|
||||||
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
|
||||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2e, 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, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x19,
|
|
||||||
0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
|
||||||
0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
|
||||||
0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_proxyman_command_command_proto_rawDescOnce sync.Once
|
file_app_proxyman_command_command_proto_rawDescOnce sync.Once
|
||||||
file_app_proxyman_command_command_proto_rawDescData = file_app_proxyman_command_command_proto_rawDesc
|
file_app_proxyman_command_command_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_proxyman_command_command_proto_rawDescGZIP() []byte {
|
func file_app_proxyman_command_command_proto_rawDescGZIP() []byte {
|
||||||
file_app_proxyman_command_command_proto_rawDescOnce.Do(func() {
|
file_app_proxyman_command_command_proto_rawDescOnce.Do(func() {
|
||||||
file_app_proxyman_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_proxyman_command_command_proto_rawDescData)
|
file_app_proxyman_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_proxyman_command_command_proto_rawDesc), len(file_app_proxyman_command_command_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_proxyman_command_command_proto_rawDescData
|
return file_app_proxyman_command_command_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -1222,7 +1098,7 @@ func file_app_proxyman_command_command_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_proxyman_command_command_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_proxyman_command_command_proto_rawDesc), len(file_app_proxyman_command_command_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 22,
|
NumMessages: 22,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -1233,7 +1109,6 @@ func file_app_proxyman_command_command_proto_init() {
|
|||||||
MessageInfos: file_app_proxyman_command_command_proto_msgTypes,
|
MessageInfos: file_app_proxyman_command_command_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_proxyman_command_command_proto = out.File
|
File_app_proxyman_command_command_proto = out.File
|
||||||
file_app_proxyman_command_command_proto_rawDesc = nil
|
|
||||||
file_app_proxyman_command_command_proto_goTypes = nil
|
file_app_proxyman_command_command_proto_goTypes = nil
|
||||||
file_app_proxyman_command_command_proto_depIdxs = nil
|
file_app_proxyman_command_command_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.5.1
|
// - protoc-gen-go-grpc v1.6.0
|
||||||
// - protoc v5.28.2
|
// - protoc v6.33.5
|
||||||
// source: app/proxyman/command/command.proto
|
// source: app/proxyman/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
@@ -180,34 +180,34 @@ type HandlerServiceServer interface {
|
|||||||
type UnimplementedHandlerServiceServer struct{}
|
type UnimplementedHandlerServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedHandlerServiceServer) AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error) {
|
func (UnimplementedHandlerServiceServer) AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method AddInbound not implemented")
|
return nil, status.Error(codes.Unimplemented, "method AddInbound not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error) {
|
func (UnimplementedHandlerServiceServer) RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method RemoveInbound not implemented")
|
return nil, status.Error(codes.Unimplemented, "method RemoveInbound not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) {
|
func (UnimplementedHandlerServiceServer) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method AlterInbound not implemented")
|
return nil, status.Error(codes.Unimplemented, "method AlterInbound not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error) {
|
func (UnimplementedHandlerServiceServer) ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ListInbounds not implemented")
|
return nil, status.Error(codes.Unimplemented, "method ListInbounds not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error) {
|
func (UnimplementedHandlerServiceServer) GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetInboundUsers not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetInboundUsers not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error) {
|
func (UnimplementedHandlerServiceServer) GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetInboundUsersCount not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetInboundUsersCount not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error) {
|
func (UnimplementedHandlerServiceServer) AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method AddOutbound not implemented")
|
return nil, status.Error(codes.Unimplemented, "method AddOutbound not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error) {
|
func (UnimplementedHandlerServiceServer) RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method RemoveOutbound not implemented")
|
return nil, status.Error(codes.Unimplemented, "method RemoveOutbound not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error) {
|
func (UnimplementedHandlerServiceServer) AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method AlterOutbound not implemented")
|
return nil, status.Error(codes.Unimplemented, "method AlterOutbound not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error) {
|
func (UnimplementedHandlerServiceServer) ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ListOutbounds not implemented")
|
return nil, status.Error(codes.Unimplemented, "method ListOutbounds not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
||||||
func (UnimplementedHandlerServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedHandlerServiceServer) testEmbeddedByValue() {}
|
||||||
@@ -220,7 +220,7 @@ type UnsafeHandlerServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterHandlerServiceServer(s grpc.ServiceRegistrar, srv HandlerServiceServer) {
|
func RegisterHandlerServiceServer(s grpc.ServiceRegistrar, srv HandlerServiceServer) {
|
||||||
// If the following call pancis, it indicates UnimplementedHandlerServiceServer was
|
// If the following call panics, it indicates UnimplementedHandlerServiceServer was
|
||||||
// embedded by pointer and is nil. This will cause panics if an
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
// unimplemented method is ever invoked, so we test this at initialization
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
// time to prevent it from happening at runtime later due to I/O.
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
|
|||||||
@@ -1 +1,34 @@
|
|||||||
package proxyman
|
package proxyman
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BuildSniffingRequest(config *SniffingConfig) (session.SniffingRequest, error) {
|
||||||
|
if config == nil {
|
||||||
|
return session.SniffingRequest{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
request := session.SniffingRequest{
|
||||||
|
Enabled: config.Enabled,
|
||||||
|
OverrideDestinationForProtocol: config.DestinationOverride,
|
||||||
|
MetadataOnly: config.MetadataOnly,
|
||||||
|
RouteOnly: config.RouteOnly,
|
||||||
|
}
|
||||||
|
if len(config.DomainsExcluded) > 0 {
|
||||||
|
excludeForDomain, err := geodata.DomainReg.BuildDomainMatcher(config.DomainsExcluded)
|
||||||
|
if err != nil {
|
||||||
|
return session.SniffingRequest{}, err
|
||||||
|
}
|
||||||
|
request.ExcludeForDomain = excludeForDomain
|
||||||
|
}
|
||||||
|
if len(config.IpsExcluded) > 0 {
|
||||||
|
excludeForIP, err := geodata.IPReg.BuildIPMatcher(config.IpsExcluded)
|
||||||
|
if err != nil {
|
||||||
|
return session.SniffingRequest{}, err
|
||||||
|
}
|
||||||
|
request.ExcludeForIP = excludeForIP
|
||||||
|
}
|
||||||
|
return request, nil
|
||||||
|
}
|
||||||
|
|||||||
+104
-165
@@ -1,12 +1,13 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/proxyman/config.proto
|
// source: app/proxyman/config.proto
|
||||||
|
|
||||||
package proxyman
|
package proxyman
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
geodata "github.com/xtls/xray-core/common/geodata"
|
||||||
net "github.com/xtls/xray-core/common/net"
|
net "github.com/xtls/xray-core/common/net"
|
||||||
serial "github.com/xtls/xray-core/common/serial"
|
serial "github.com/xtls/xray-core/common/serial"
|
||||||
internet "github.com/xtls/xray-core/transport/internet"
|
internet "github.com/xtls/xray-core/transport/internet"
|
||||||
@@ -14,6 +15,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -24,9 +26,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type InboundConfig struct {
|
type InboundConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *InboundConfig) Reset() {
|
func (x *InboundConfig) Reset() {
|
||||||
@@ -60,21 +62,21 @@ func (*InboundConfig) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SniffingConfig struct {
|
type SniffingConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// Whether or not to enable content sniffing on an inbound connection.
|
// Whether or not to enable content sniffing on an inbound connection.
|
||||||
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
|
||||||
// Override target destination if sniff'ed protocol is in the given list.
|
// Override target destination if sniff'ed protocol is in the given list.
|
||||||
// Supported values are "http", "tls", "fakedns".
|
// Supported values are "http", "tls", "fakedns".
|
||||||
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 []*geodata.DomainRule `protobuf:"bytes,3,rep,name=domains_excluded,json=domainsExcluded,proto3" json:"domains_excluded,omitempty"`
|
||||||
|
IpsExcluded []*geodata.IPRule `protobuf:"bytes,6,rep,name=ips_excluded,json=ipsExcluded,proto3" json:"ips_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
|
// Can be used to support SMTP like protocol where server send the first
|
||||||
// message.
|
// 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"`
|
RouteOnly bool `protobuf:"varint,5,opt,name=route_only,json=routeOnly,proto3" json:"route_only,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) Reset() {
|
func (x *SniffingConfig) Reset() {
|
||||||
@@ -121,13 +123,20 @@ func (x *SniffingConfig) GetDestinationOverride() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) GetDomainsExcluded() []string {
|
func (x *SniffingConfig) GetDomainsExcluded() []*geodata.DomainRule {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.DomainsExcluded
|
return x.DomainsExcluded
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *SniffingConfig) GetIpsExcluded() []*geodata.IPRule {
|
||||||
|
if x != nil {
|
||||||
|
return x.IpsExcluded
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) GetMetadataOnly() bool {
|
func (x *SniffingConfig) GetMetadataOnly() bool {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.MetadataOnly
|
return x.MetadataOnly
|
||||||
@@ -143,10 +152,7 @@ func (x *SniffingConfig) GetRouteOnly() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ReceiverConfig struct {
|
type ReceiverConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// PortList specifies the ports which the Receiver should listen on.
|
// PortList specifies the ports which the Receiver should listen on.
|
||||||
PortList *net.PortList `protobuf:"bytes,1,opt,name=port_list,json=portList,proto3" json:"port_list,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.
|
||||||
@@ -154,6 +160,8 @@ type ReceiverConfig struct {
|
|||||||
StreamSettings *internet.StreamConfig `protobuf:"bytes,3,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
StreamSettings *internet.StreamConfig `protobuf:"bytes,3,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
||||||
ReceiveOriginalDestination bool `protobuf:"varint,4,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"`
|
ReceiveOriginalDestination bool `protobuf:"varint,4,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"`
|
||||||
SniffingSettings *SniffingConfig `protobuf:"bytes,6,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
|
SniffingSettings *SniffingConfig `protobuf:"bytes,6,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReceiverConfig) Reset() {
|
func (x *ReceiverConfig) Reset() {
|
||||||
@@ -222,13 +230,12 @@ func (x *ReceiverConfig) GetSniffingSettings() *SniffingConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type InboundHandlerConfig struct {
|
type InboundHandlerConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
ReceiverSettings *serial.TypedMessage `protobuf:"bytes,2,opt,name=receiver_settings,json=receiverSettings,proto3" json:"receiver_settings,omitempty"`
|
||||||
|
ProxySettings *serial.TypedMessage `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings,proto3" json:"proxy_settings,omitempty"`
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
unknownFields protoimpl.UnknownFields
|
||||||
ReceiverSettings *serial.TypedMessage `protobuf:"bytes,2,opt,name=receiver_settings,json=receiverSettings,proto3" json:"receiver_settings,omitempty"`
|
sizeCache protoimpl.SizeCache
|
||||||
ProxySettings *serial.TypedMessage `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings,proto3" json:"proxy_settings,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *InboundHandlerConfig) Reset() {
|
func (x *InboundHandlerConfig) Reset() {
|
||||||
@@ -283,9 +290,9 @@ func (x *InboundHandlerConfig) GetProxySettings() *serial.TypedMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OutboundConfig struct {
|
type OutboundConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *OutboundConfig) Reset() {
|
func (x *OutboundConfig) Reset() {
|
||||||
@@ -319,10 +326,7 @@ func (*OutboundConfig) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SenderConfig struct {
|
type SenderConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// Send traffic through the given IP. Only IP is allowed.
|
// Send traffic through the given IP. Only IP is allowed.
|
||||||
Via *net.IPOrDomain `protobuf:"bytes,1,opt,name=via,proto3" json:"via,omitempty"`
|
Via *net.IPOrDomain `protobuf:"bytes,1,opt,name=via,proto3" json:"via,omitempty"`
|
||||||
StreamSettings *internet.StreamConfig `protobuf:"bytes,2,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
StreamSettings *internet.StreamConfig `protobuf:"bytes,2,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
||||||
@@ -330,6 +334,8 @@ type SenderConfig struct {
|
|||||||
MultiplexSettings *MultiplexingConfig `protobuf:"bytes,4,opt,name=multiplex_settings,json=multiplexSettings,proto3" json:"multiplex_settings,omitempty"`
|
MultiplexSettings *MultiplexingConfig `protobuf:"bytes,4,opt,name=multiplex_settings,json=multiplexSettings,proto3" json:"multiplex_settings,omitempty"`
|
||||||
ViaCidr string `protobuf:"bytes,5,opt,name=via_cidr,json=viaCidr,proto3" json:"via_cidr,omitempty"`
|
ViaCidr string `protobuf:"bytes,5,opt,name=via_cidr,json=viaCidr,proto3" json:"via_cidr,omitempty"`
|
||||||
TargetStrategy internet.DomainStrategy `protobuf:"varint,6,opt,name=target_strategy,json=targetStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"target_strategy,omitempty"`
|
TargetStrategy internet.DomainStrategy `protobuf:"varint,6,opt,name=target_strategy,json=targetStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"target_strategy,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SenderConfig) Reset() {
|
func (x *SenderConfig) Reset() {
|
||||||
@@ -405,10 +411,7 @@ func (x *SenderConfig) GetTargetStrategy() internet.DomainStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MultiplexingConfig struct {
|
type MultiplexingConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
// 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.
|
||||||
@@ -417,6 +420,8 @@ type MultiplexingConfig struct {
|
|||||||
XudpConcurrency int32 `protobuf:"varint,3,opt,name=xudpConcurrency,proto3" json:"xudpConcurrency,omitempty"`
|
XudpConcurrency int32 `protobuf:"varint,3,opt,name=xudpConcurrency,proto3" json:"xudpConcurrency,omitempty"`
|
||||||
// "reject" (default), "allow" or "skip".
|
// "reject" (default), "allow" or "skip".
|
||||||
XudpProxyUDP443 string `protobuf:"bytes,4,opt,name=xudpProxyUDP443,proto3" json:"xudpProxyUDP443,omitempty"`
|
XudpProxyUDP443 string `protobuf:"bytes,4,opt,name=xudpProxyUDP443,proto3" json:"xudpProxyUDP443,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *MultiplexingConfig) Reset() {
|
func (x *MultiplexingConfig) Reset() {
|
||||||
@@ -479,120 +484,51 @@ func (x *MultiplexingConfig) GetXudpProxyUDP443() string {
|
|||||||
|
|
||||||
var File_app_proxyman_config_proto protoreflect.FileDescriptor
|
var File_app_proxyman_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_proxyman_config_proto_rawDesc = []byte{
|
const file_app_proxyman_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x19, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63,
|
"\n" +
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x78, 0x72, 0x61,
|
"\x19app/proxyman/config.proto\x12\x11xray.app.proxyman\x1a\x18common/net/address.proto\x1a\x15common/net/port.proto\x1a\x1ftransport/internet/config.proto\x1a!common/serial/typed_message.proto\x1a\x1bcommon/geodata/geodat.proto\"\x0f\n" +
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x1a, 0x18,
|
"\rInboundConfig\"\xad\x02\n" +
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x61, 0x64, 0x64, 0x72, 0x65,
|
"\x0eSniffingConfig\x12\x18\n" +
|
||||||
0x73, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x15, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
"\aenabled\x18\x01 \x01(\bR\aenabled\x121\n" +
|
||||||
0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a,
|
"\x14destination_override\x18\x02 \x03(\tR\x13destinationOverride\x12J\n" +
|
||||||
0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
"\x10domains_excluded\x18\x03 \x03(\v2\x1f.xray.common.geodata.DomainRuleR\x0fdomainsExcluded\x12>\n" +
|
||||||
0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
"\fips_excluded\x18\x06 \x03(\v2\x1b.xray.common.geodata.IPRuleR\vipsExcluded\x12#\n" +
|
||||||
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f,
|
"\rmetadata_only\x18\x04 \x01(\bR\fmetadataOnly\x12\x1d\n" +
|
||||||
0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72,
|
"\n" +
|
||||||
0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f,
|
"route_only\x18\x05 \x01(\bR\trouteOnly\"\xe5\x02\n" +
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e,
|
"\x0eReceiverConfig\x126\n" +
|
||||||
0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
"\tport_list\x18\x01 \x01(\v2\x19.xray.common.net.PortListR\bportList\x123\n" +
|
||||||
0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
"\x06listen\x18\x02 \x01(\v2\x1b.xray.common.net.IPOrDomainR\x06listen\x12N\n" +
|
||||||
0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
"\x0fstream_settings\x18\x03 \x01(\v2%.xray.transport.internet.StreamConfigR\x0estreamSettings\x12@\n" +
|
||||||
0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
|
"\x1creceive_original_destination\x18\x04 \x01(\bR\x1areceiveOriginalDestination\x12N\n" +
|
||||||
0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72,
|
"\x11sniffing_settings\x18\x06 \x01(\v2!.xray.app.proxyman.SniffingConfigR\x10sniffingSettingsJ\x04\b\x05\x10\x06\"\xc0\x01\n" +
|
||||||
0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x5f,
|
"\x14InboundHandlerConfig\x12\x10\n" +
|
||||||
0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x12M\n" +
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x12,
|
"\x11receiver_settings\x18\x02 \x01(\v2 .xray.common.serial.TypedMessageR\x10receiverSettings\x12G\n" +
|
||||||
0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, 0x79,
|
"\x0eproxy_settings\x18\x03 \x01(\v2 .xray.common.serial.TypedMessageR\rproxySettings\"\x10\n" +
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
"\x0eOutboundConfig\"\x9d\x03\n" +
|
||||||
0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f, 0x6e,
|
"\fSenderConfig\x12-\n" +
|
||||||
0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x4f,
|
"\x03via\x18\x01 \x01(\v2\x1b.xray.common.net.IPOrDomainR\x03via\x12N\n" +
|
||||||
0x6e, 0x6c, 0x79, 0x22, 0xe5, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72,
|
"\x0fstream_settings\x18\x02 \x01(\v2%.xray.transport.internet.StreamConfigR\x0estreamSettings\x12K\n" +
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c,
|
"\x0eproxy_settings\x18\x03 \x01(\v2$.xray.transport.internet.ProxyConfigR\rproxySettings\x12T\n" +
|
||||||
0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
"\x12multiplex_settings\x18\x04 \x01(\v2%.xray.app.proxyman.MultiplexingConfigR\x11multiplexSettings\x12\x19\n" +
|
||||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74,
|
"\bvia_cidr\x18\x05 \x01(\tR\aviaCidr\x12P\n" +
|
||||||
0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33,
|
"\x0ftarget_strategy\x18\x06 \x01(\x0e2'.xray.transport.internet.DomainStrategyR\x0etargetStrategy\"\xa4\x01\n" +
|
||||||
0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
|
"\x12MultiplexingConfig\x12\x18\n" +
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
|
"\aenabled\x18\x01 \x01(\bR\aenabled\x12 \n" +
|
||||||
0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69, 0x73,
|
"\vconcurrency\x18\x02 \x01(\x05R\vconcurrency\x12(\n" +
|
||||||
0x74, 0x65, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65,
|
"\x0fxudpConcurrency\x18\x03 \x01(\x05R\x0fxudpConcurrency\x12(\n" +
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78,
|
"\x0fxudpProxyUDP443\x18\x04 \x01(\tR\x0fxudpProxyUDP443BU\n" +
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
"\x15com.xray.app.proxymanP\x01Z&github.com/xtls/xray-core/app/proxyman\xaa\x02\x11Xray.App.Proxymanb\x06proto3"
|
||||||
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, 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, 0x04, 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, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e,
|
|
||||||
0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 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, 0x05, 0x10, 0x06, 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, 0x9d, 0x03, 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, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x69, 0x61, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18,
|
|
||||||
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x12, 0x50,
|
|
||||||
0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
|
||||||
0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 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, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
|
||||||
0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
|
||||||
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, 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 (
|
||||||
file_app_proxyman_config_proto_rawDescOnce sync.Once
|
file_app_proxyman_config_proto_rawDescOnce sync.Once
|
||||||
file_app_proxyman_config_proto_rawDescData = file_app_proxyman_config_proto_rawDesc
|
file_app_proxyman_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_proxyman_config_proto_rawDescGZIP() []byte {
|
func file_app_proxyman_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_proxyman_config_proto_rawDescOnce.Do(func() {
|
file_app_proxyman_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_proxyman_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_proxyman_config_proto_rawDescData)
|
file_app_proxyman_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_proxyman_config_proto_rawDesc), len(file_app_proxyman_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_proxyman_config_proto_rawDescData
|
return file_app_proxyman_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -606,30 +542,34 @@ var file_app_proxyman_config_proto_goTypes = []any{
|
|||||||
(*OutboundConfig)(nil), // 4: xray.app.proxyman.OutboundConfig
|
(*OutboundConfig)(nil), // 4: xray.app.proxyman.OutboundConfig
|
||||||
(*SenderConfig)(nil), // 5: xray.app.proxyman.SenderConfig
|
(*SenderConfig)(nil), // 5: xray.app.proxyman.SenderConfig
|
||||||
(*MultiplexingConfig)(nil), // 6: xray.app.proxyman.MultiplexingConfig
|
(*MultiplexingConfig)(nil), // 6: xray.app.proxyman.MultiplexingConfig
|
||||||
(*net.PortList)(nil), // 7: xray.common.net.PortList
|
(*geodata.DomainRule)(nil), // 7: xray.common.geodata.DomainRule
|
||||||
(*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain
|
(*geodata.IPRule)(nil), // 8: xray.common.geodata.IPRule
|
||||||
(*internet.StreamConfig)(nil), // 9: xray.transport.internet.StreamConfig
|
(*net.PortList)(nil), // 9: xray.common.net.PortList
|
||||||
(*serial.TypedMessage)(nil), // 10: xray.common.serial.TypedMessage
|
(*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
|
||||||
(*internet.ProxyConfig)(nil), // 11: xray.transport.internet.ProxyConfig
|
(*internet.StreamConfig)(nil), // 11: xray.transport.internet.StreamConfig
|
||||||
(internet.DomainStrategy)(0), // 12: xray.transport.internet.DomainStrategy
|
(*serial.TypedMessage)(nil), // 12: xray.common.serial.TypedMessage
|
||||||
|
(*internet.ProxyConfig)(nil), // 13: xray.transport.internet.ProxyConfig
|
||||||
|
(internet.DomainStrategy)(0), // 14: xray.transport.internet.DomainStrategy
|
||||||
}
|
}
|
||||||
var file_app_proxyman_config_proto_depIdxs = []int32{
|
var file_app_proxyman_config_proto_depIdxs = []int32{
|
||||||
7, // 0: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
7, // 0: xray.app.proxyman.SniffingConfig.domains_excluded:type_name -> xray.common.geodata.DomainRule
|
||||||
8, // 1: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
8, // 1: xray.app.proxyman.SniffingConfig.ips_excluded:type_name -> xray.common.geodata.IPRule
|
||||||
9, // 2: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
9, // 2: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
||||||
1, // 3: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
10, // 3: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
||||||
10, // 4: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
11, // 4: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
10, // 5: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
1, // 5: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
||||||
8, // 6: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
12, // 6: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
9, // 7: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
12, // 7: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
11, // 8: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
10, // 8: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
||||||
6, // 9: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
11, // 9: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
12, // 10: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy
|
13, // 10: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
||||||
11, // [11:11] is the sub-list for method output_type
|
6, // 11: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
||||||
11, // [11:11] is the sub-list for method input_type
|
14, // 12: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||||
11, // [11:11] is the sub-list for extension type_name
|
13, // [13:13] is the sub-list for method output_type
|
||||||
11, // [11:11] is the sub-list for extension extendee
|
13, // [13:13] is the sub-list for method input_type
|
||||||
0, // [0:11] is the sub-list for field type_name
|
13, // [13:13] is the sub-list for extension type_name
|
||||||
|
13, // [13:13] is the sub-list for extension extendee
|
||||||
|
0, // [0:13] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_proxyman_config_proto_init() }
|
func init() { file_app_proxyman_config_proto_init() }
|
||||||
@@ -641,7 +581,7 @@ func file_app_proxyman_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_proxyman_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_proxyman_config_proto_rawDesc), len(file_app_proxyman_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 7,
|
NumMessages: 7,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -652,7 +592,6 @@ func file_app_proxyman_config_proto_init() {
|
|||||||
MessageInfos: file_app_proxyman_config_proto_msgTypes,
|
MessageInfos: file_app_proxyman_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_proxyman_config_proto = out.File
|
File_app_proxyman_config_proto = out.File
|
||||||
file_app_proxyman_config_proto_rawDesc = nil
|
|
||||||
file_app_proxyman_config_proto_goTypes = nil
|
file_app_proxyman_config_proto_goTypes = nil
|
||||||
file_app_proxyman_config_proto_depIdxs = nil
|
file_app_proxyman_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import "common/net/address.proto";
|
|||||||
import "common/net/port.proto";
|
import "common/net/port.proto";
|
||||||
import "transport/internet/config.proto";
|
import "transport/internet/config.proto";
|
||||||
import "common/serial/typed_message.proto";
|
import "common/serial/typed_message.proto";
|
||||||
|
import "common/geodata/geodat.proto";
|
||||||
|
|
||||||
message InboundConfig {}
|
message InboundConfig {}
|
||||||
|
|
||||||
@@ -20,7 +21,10 @@ message SniffingConfig {
|
|||||||
// Override target destination if sniff'ed protocol is in the given list.
|
// Override target destination if sniff'ed protocol is in the given list.
|
||||||
// Supported values are "http", "tls", "fakedns".
|
// Supported values are "http", "tls", "fakedns".
|
||||||
repeated string destination_override = 2;
|
repeated string destination_override = 2;
|
||||||
repeated string domains_excluded = 3;
|
|
||||||
|
repeated xray.common.geodata.DomainRule domains_excluded = 3;
|
||||||
|
|
||||||
|
repeated xray.common.geodata.IPRule ips_excluded = 6;
|
||||||
|
|
||||||
// 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
|
// Can be used to support SMTP like protocol where server send the first
|
||||||
|
|||||||
@@ -53,18 +53,17 @@ type AlwaysOnInboundHandler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) {
|
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) {
|
||||||
|
sniffingRequest, err := proxyman.BuildSniffingRequest(receiverConfig.SniffingSettings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Set tag and sniffing config in context before creating proxy
|
// Set tag and sniffing config in context before creating proxy
|
||||||
// This allows proxies like TUN to access these settings
|
// This allows proxies like TUN to access these settings
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: tag})
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: tag})
|
||||||
if receiverConfig.SniffingSettings != nil {
|
if receiverConfig.SniffingSettings != nil {
|
||||||
ctx = session.ContextWithContent(ctx, &session.Content{
|
ctx = session.ContextWithContent(ctx, &session.Content{
|
||||||
SniffingRequest: session.SniffingRequest{
|
SniffingRequest: sniffingRequest,
|
||||||
Enabled: receiverConfig.SniffingSettings.Enabled,
|
|
||||||
OverrideDestinationForProtocol: receiverConfig.SniffingSettings.DestinationOverride,
|
|
||||||
ExcludeForDomain: receiverConfig.SniffingSettings.DomainsExcluded,
|
|
||||||
MetadataOnly: receiverConfig.SniffingSettings.MetadataOnly,
|
|
||||||
RouteOnly: receiverConfig.SniffingSettings.RouteOnly,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
rawProxy, err := common.CreateObject(ctx, proxyConfig)
|
rawProxy, err := common.CreateObject(ctx, proxyConfig)
|
||||||
@@ -117,7 +116,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
stream: mss,
|
stream: mss,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.SniffingSettings,
|
sniffingRequest: sniffingRequest,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -139,7 +138,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.SniffingSettings,
|
sniffingRequest: sniffingRequest,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -154,7 +153,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.SniffingSettings,
|
sniffingRequest: sniffingRequest,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
@@ -186,6 +185,7 @@ func (h *AlwaysOnInboundHandler) Close() error {
|
|||||||
errs = append(errs, worker.Close())
|
errs = append(errs, worker.Close())
|
||||||
}
|
}
|
||||||
errs = append(errs, h.mux.Close())
|
errs = append(errs, h.mux.Close())
|
||||||
|
errs = append(errs, common.Close(h.proxy))
|
||||||
if err := errors.Combine(errs...); err != nil {
|
if err := errors.Combine(errs...); err != nil {
|
||||||
return errors.New("failed to close all resources").Base(err)
|
return errors.New("failed to close all resources").Base(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"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"
|
||||||
c "github.com/xtls/xray-core/common/ctx"
|
c "github.com/xtls/xray-core/common/ctx"
|
||||||
@@ -19,7 +18,9 @@ import (
|
|||||||
"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"
|
||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
|
hysteria_proxy "github.com/xtls/xray-core/proxy/hysteria"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"github.com/xtls/xray-core/transport/internet/hysteria"
|
||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"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"
|
||||||
@@ -41,7 +42,7 @@ type tcpWorker struct {
|
|||||||
recvOrigDest bool
|
recvOrigDest bool
|
||||||
tag string
|
tag string
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
sniffingConfig *proxyman.SniffingConfig
|
sniffingRequest session.SniffingRequest
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
@@ -116,13 +117,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
content := new(session.Content)
|
content := new(session.Content)
|
||||||
if w.sniffingConfig != nil {
|
content.SniffingRequest = w.sniffingRequest
|
||||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
|
||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
|
||||||
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
|
||||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
|
||||||
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
|
|
||||||
}
|
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
|
||||||
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
|
if err := w.proxy.Process(ctx, net.Network_TCP, conn, w.dispatcher); err != nil {
|
||||||
@@ -138,6 +133,11 @@ func (w *tcpWorker) Proxy() proxy.Inbound {
|
|||||||
|
|
||||||
func (w *tcpWorker) Start() error {
|
func (w *tcpWorker) Start() error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
|
if v, ok := w.proxy.(*hysteria_proxy.Server); ok {
|
||||||
|
ctx = hysteria.ContextWithValidator(ctx, v.HysteriaInboundValidator())
|
||||||
|
}
|
||||||
|
|
||||||
hub, err := internet.ListenTCP(ctx, w.address, w.port, w.stream, func(conn stat.Connection) {
|
hub, err := internet.ListenTCP(ctx, w.address, w.port, w.stream, func(conn stat.Connection) {
|
||||||
go w.callback(conn)
|
go w.callback(conn)
|
||||||
})
|
})
|
||||||
@@ -266,7 +266,7 @@ type udpWorker struct {
|
|||||||
tag string
|
tag string
|
||||||
stream *internet.MemoryStreamConfig
|
stream *internet.MemoryStreamConfig
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
sniffingConfig *proxyman.SniffingConfig
|
sniffingRequest session.SniffingRequest
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
@@ -356,13 +356,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
|||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
})
|
})
|
||||||
content := new(session.Content)
|
content := new(session.Content)
|
||||||
if w.sniffingConfig != nil {
|
content.SniffingRequest = w.sniffingRequest
|
||||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
|
||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
|
||||||
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
|
||||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
|
||||||
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
|
|
||||||
}
|
|
||||||
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 {
|
||||||
errors.LogInfoInner(ctx, err, "connection ends")
|
errors.LogInfoInner(ctx, err, "connection ends")
|
||||||
@@ -478,7 +472,7 @@ type dsWorker struct {
|
|||||||
stream *internet.MemoryStreamConfig
|
stream *internet.MemoryStreamConfig
|
||||||
tag string
|
tag string
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
sniffingConfig *proxyman.SniffingConfig
|
sniffingRequest session.SniffingRequest
|
||||||
uplinkCounter stats.Counter
|
uplinkCounter stats.Counter
|
||||||
downlinkCounter stats.Counter
|
downlinkCounter stats.Counter
|
||||||
|
|
||||||
@@ -508,13 +502,7 @@ func (w *dsWorker) callback(conn stat.Connection) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
content := new(session.Content)
|
content := new(session.Content)
|
||||||
if w.sniffingConfig != nil {
|
content.SniffingRequest = w.sniffingRequest
|
||||||
content.SniffingRequest.Enabled = w.sniffingConfig.Enabled
|
|
||||||
content.SniffingRequest.OverrideDestinationForProtocol = w.sniffingConfig.DestinationOverride
|
|
||||||
content.SniffingRequest.ExcludeForDomain = w.sniffingConfig.DomainsExcluded
|
|
||||||
content.SniffingRequest.MetadataOnly = w.sniffingConfig.MetadataOnly
|
|
||||||
content.SniffingRequest.RouteOnly = w.sniffingConfig.RouteOnly
|
|
||||||
}
|
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
|
|
||||||
if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil {
|
if err := w.proxy.Process(ctx, net.Network_UNIX, conn, w.dispatcher); err != nil {
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ func TestOutboundWithoutStatCounter(t *testing.T) {
|
|||||||
ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{{}})
|
ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{{}})
|
||||||
h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{
|
h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{
|
||||||
Tag: "tag",
|
Tag: "tag",
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}}}),
|
||||||
})
|
})
|
||||||
conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
|
conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
|
||||||
_, ok := conn.(*stat.CounterConnection)
|
_, ok := conn.(*stat.CounterConnection)
|
||||||
@@ -78,7 +78,7 @@ func TestOutboundWithStatCounter(t *testing.T) {
|
|||||||
ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{{}})
|
ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{{}})
|
||||||
h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{
|
h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{
|
||||||
Tag: "tag",
|
Tag: "tag",
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}}}),
|
||||||
})
|
})
|
||||||
conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
|
conn, _ := h.(*Handler).Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), 13146))
|
||||||
_, ok := conn.(*stat.CounterConnection)
|
_, ok := conn.(*stat.CounterConnection)
|
||||||
@@ -118,7 +118,7 @@ func TestTagsCache(t *testing.T) {
|
|||||||
tag := fmt.Sprintf("%s%d", tags_prefix, idx)
|
tag := fmt.Sprintf("%s%d", tags_prefix, idx)
|
||||||
cfg := &core.OutboundHandlerConfig{
|
cfg := &core.OutboundHandlerConfig{
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{FinalRules: []*freedom.FinalRuleConfig{{Action: freedom.RuleAction_Allow}}}),
|
||||||
}
|
}
|
||||||
if h, err := NewHandler(ctx, cfg); err == nil {
|
if h, err := NewHandler(ctx, cfg); err == nil {
|
||||||
if err := ohm.AddHandler(ctx, h); err == nil {
|
if err := ohm.AddHandler(ctx, h); err == nil {
|
||||||
|
|||||||
+42
-61
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/reverse/config.proto
|
// source: app/reverse/config.proto
|
||||||
|
|
||||||
package reverse
|
package reverse
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -67,12 +68,11 @@ func (Control_State) EnumDescriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Control struct {
|
type Control struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
State Control_State `protobuf:"varint,1,opt,name=state,proto3,enum=xray.app.reverse.Control_State" json:"state,omitempty"`
|
||||||
|
Random []byte `protobuf:"bytes,99,opt,name=random,proto3" json:"random,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
State Control_State `protobuf:"varint,1,opt,name=state,proto3,enum=xray.app.reverse.Control_State" json:"state,omitempty"`
|
|
||||||
Random []byte `protobuf:"bytes,99,opt,name=random,proto3" json:"random,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Control) Reset() {
|
func (x *Control) Reset() {
|
||||||
@@ -120,12 +120,11 @@ func (x *Control) GetRandom() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BridgeConfig struct {
|
type BridgeConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
|
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
|
||||||
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BridgeConfig) Reset() {
|
func (x *BridgeConfig) Reset() {
|
||||||
@@ -173,12 +172,11 @@ func (x *BridgeConfig) GetDomain() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PortalConfig struct {
|
type PortalConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
|
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
|
||||||
Domain string `protobuf:"bytes,2,opt,name=domain,proto3" json:"domain,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *PortalConfig) Reset() {
|
func (x *PortalConfig) Reset() {
|
||||||
@@ -226,12 +224,11 @@ func (x *PortalConfig) GetDomain() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
BridgeConfig []*BridgeConfig `protobuf:"bytes,1,rep,name=bridge_config,json=bridgeConfig,proto3" json:"bridge_config,omitempty"`
|
||||||
|
PortalConfig []*PortalConfig `protobuf:"bytes,2,rep,name=portal_config,json=portalConfig,proto3" json:"portal_config,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
BridgeConfig []*BridgeConfig `protobuf:"bytes,1,rep,name=bridge_config,json=bridgeConfig,proto3" json:"bridge_config,omitempty"`
|
|
||||||
PortalConfig []*PortalConfig `protobuf:"bytes,2,rep,name=portal_config,json=portalConfig,proto3" json:"portal_config,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -280,50 +277,35 @@ func (x *Config) GetPortalConfig() []*PortalConfig {
|
|||||||
|
|
||||||
var File_app_reverse_config_proto protoreflect.FileDescriptor
|
var File_app_reverse_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_reverse_config_proto_rawDesc = []byte{
|
const file_app_reverse_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x2f, 0x63, 0x6f,
|
"\n" +
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79,
|
"\x18app/reverse/config.proto\x12\x10xray.app.reverse\"x\n" +
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x22, 0x78, 0x0a, 0x07,
|
"\aControl\x125\n" +
|
||||||
0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x35, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65,
|
"\x05state\x18\x01 \x01(\x0e2\x1f.xray.app.reverse.Control.StateR\x05state\x12\x16\n" +
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
"\x06random\x18c \x01(\fR\x06random\"\x1e\n" +
|
||||||
0x70, 0x2e, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
"\x05State\x12\n" +
|
||||||
0x6c, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x16,
|
"\n" +
|
||||||
0x0a, 0x06, 0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x18, 0x63, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06,
|
"\x06ACTIVE\x10\x00\x12\t\n" +
|
||||||
0x72, 0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x22, 0x1e, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12,
|
"\x05DRAIN\x10\x01\"8\n" +
|
||||||
0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44,
|
"\fBridgeConfig\x12\x10\n" +
|
||||||
0x52, 0x41, 0x49, 0x4e, 0x10, 0x01, 0x22, 0x38, 0x0a, 0x0c, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x12\x16\n" +
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
|
"\x06domain\x18\x02 \x01(\tR\x06domain\"8\n" +
|
||||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61,
|
"\fPortalConfig\x12\x10\n" +
|
||||||
0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
"\x03tag\x18\x01 \x01(\tR\x03tag\x12\x16\n" +
|
||||||
0x22, 0x38, 0x0a, 0x0c, 0x50, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
"\x06domain\x18\x02 \x01(\tR\x06domain\"\x92\x01\n" +
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74,
|
"\x06Config\x12C\n" +
|
||||||
0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01,
|
"\rbridge_config\x18\x01 \x03(\v2\x1e.xray.app.reverse.BridgeConfigR\fbridgeConfig\x12C\n" +
|
||||||
0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x92, 0x01, 0x0a, 0x06, 0x43,
|
"\rportal_config\x18\x02 \x03(\v2\x1e.xray.app.reverse.PortalConfigR\fportalConfigBV\n" +
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x43, 0x0a, 0x0d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x5f,
|
"\x16com.xray.proxy.reverseP\x01Z%github.com/xtls/xray-core/app/reverse\xaa\x02\x12Xray.Proxy.Reverseb\x06proto3"
|
||||||
0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x2e,
|
|
||||||
0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0c, 0x62, 0x72,
|
|
||||||
0x69, 0x64, 0x67, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x43, 0x0a, 0x0d, 0x70, 0x6f,
|
|
||||||
0x72, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x03, 0x28,
|
|
||||||
0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x65, 0x76,
|
|
||||||
0x65, 0x72, 0x73, 0x65, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
|
||||||
0x67, 0x52, 0x0c, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42,
|
|
||||||
0x56, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
|
||||||
0x79, 0x2e, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 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, 0x72, 0x65, 0x76, 0x65, 0x72,
|
|
||||||
0x73, 0x65, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
|
||||||
0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_reverse_config_proto_rawDescOnce sync.Once
|
file_app_reverse_config_proto_rawDescOnce sync.Once
|
||||||
file_app_reverse_config_proto_rawDescData = file_app_reverse_config_proto_rawDesc
|
file_app_reverse_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_reverse_config_proto_rawDescGZIP() []byte {
|
func file_app_reverse_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_reverse_config_proto_rawDescOnce.Do(func() {
|
file_app_reverse_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_reverse_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_reverse_config_proto_rawDescData)
|
file_app_reverse_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_reverse_config_proto_rawDesc), len(file_app_reverse_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_reverse_config_proto_rawDescData
|
return file_app_reverse_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -357,7 +339,7 @@ func file_app_reverse_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_reverse_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_reverse_config_proto_rawDesc), len(file_app_reverse_config_proto_rawDesc)),
|
||||||
NumEnums: 1,
|
NumEnums: 1,
|
||||||
NumMessages: 4,
|
NumMessages: 4,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -369,7 +351,6 @@ func file_app_reverse_config_proto_init() {
|
|||||||
MessageInfos: file_app_reverse_config_proto_msgTypes,
|
MessageInfos: file_app_reverse_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_reverse_config_proto = out.File
|
File_app_reverse_config_proto = out.File
|
||||||
file_app_reverse_config_proto_rawDesc = nil
|
|
||||||
file_app_reverse_config_proto_goTypes = nil
|
file_app_reverse_config_proto_goTypes = nil
|
||||||
file_app_reverse_config_proto_depIdxs = nil
|
file_app_reverse_config_proto_depIdxs = 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.36.11
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v6.33.2
|
// protoc v6.33.5
|
||||||
// source: app/router/command/command.proto
|
// source: app/router/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.6.0
|
// - protoc-gen-go-grpc v1.6.0
|
||||||
// - protoc v6.33.2
|
// - protoc v6.33.5
|
||||||
// source: app/router/command/command.proto
|
// source: app/router/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
. "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"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"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"
|
||||||
@@ -303,12 +304,12 @@ func TestServiceTestRoute(t *testing.T) {
|
|||||||
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Domain: []*router.Domain{{Type: router.Domain_Domain, Value: "com"}},
|
Domain: []*geodata.DomainRule{{Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "com"}}}},
|
||||||
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
SourceGeoip: []*router.GeoIP{{CountryCode: "private", Cidr: []*router.CIDR{{Ip: []byte{127, 0, 0, 0}, Prefix: 8}}}},
|
SourceIp: []*geodata.IPRule{{Value: &geodata.IPRule_Custom{Custom: &geodata.CIDRRule{Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 0}, Prefix: 8}}}}},
|
||||||
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
TargetTag: &router.RoutingRule_Tag{Tag: "out"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
UserEmail: []string{"example@example.com"},
|
UserEmail: []string{"example@example.com"},
|
||||||
|
|||||||
+31
-39
@@ -9,9 +9,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
"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/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
|
"github.com/xtls/xray-core/features/routing/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Condition interface {
|
type Condition interface {
|
||||||
@@ -44,39 +45,18 @@ func (v *ConditionChan) Len() int {
|
|||||||
return len(*v)
|
return len(*v)
|
||||||
}
|
}
|
||||||
|
|
||||||
var matcherTypeMap = map[Domain_Type]strmatcher.Type{
|
type DomainMatcher struct{ geodata.DomainMatcher }
|
||||||
Domain_Plain: strmatcher.Substr,
|
|
||||||
Domain_Regex: strmatcher.Regex,
|
|
||||||
Domain_Domain: strmatcher.Domain,
|
|
||||||
Domain_Full: strmatcher.Full,
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainMatcher struct {
|
func NewDomainMatcher(rules []*geodata.DomainRule) (*DomainMatcher, error) {
|
||||||
matchers strmatcher.IndexMatcher
|
m, err := geodata.DomainReg.BuildDomainMatcher(rules)
|
||||||
}
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
|
|
||||||
g := strmatcher.NewMphMatcherGroup()
|
|
||||||
for _, d := range domains {
|
|
||||||
matcherType, f := matcherTypeMap[d.Type]
|
|
||||||
if !f {
|
|
||||||
errors.LogError(context.Background(), "ignore unsupported domain type ", d.Type, " of rule ", d.Value)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
_, err := g.AddPattern(d.Value, matcherType)
|
|
||||||
if err != nil {
|
|
||||||
errors.LogErrorInner(context.Background(), err, "ignore domain rule ", d.Type, " ", d.Value)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g.Build()
|
return &DomainMatcher{DomainMatcher: m}, nil
|
||||||
return &DomainMatcher{
|
|
||||||
matchers: g,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *DomainMatcher) ApplyDomain(domain string) bool {
|
func (m *DomainMatcher) ApplyDomain(domain string) bool {
|
||||||
return len(m.matchers.Match(strings.ToLower(domain))) > 0
|
return m.DomainMatcher.MatchAny(strings.ToLower(domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply implements Condition.
|
// Apply implements Condition.
|
||||||
@@ -85,7 +65,7 @@ func (m *DomainMatcher) Apply(ctx routing.Context) bool {
|
|||||||
if len(domain) == 0 {
|
if len(domain) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return m.ApplyDomain(domain)
|
return m.DomainMatcher.MatchAny(strings.ToLower(domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
type MatcherAsType byte
|
type MatcherAsType byte
|
||||||
@@ -98,16 +78,16 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type IPMatcher struct {
|
type IPMatcher struct {
|
||||||
matcher GeoIPMatcher
|
matcher geodata.IPMatcher
|
||||||
asType MatcherAsType
|
asType MatcherAsType
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIPMatcher(geoips []*GeoIP, asType MatcherAsType) (*IPMatcher, error) {
|
func NewIPMatcher(rules []*geodata.IPRule, asType MatcherAsType) (*IPMatcher, error) {
|
||||||
matcher, err := BuildOptimizedGeoIPMatcher(geoips...)
|
m, err := geodata.IPReg.BuildIPMatcher(rules)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &IPMatcher{matcher: matcher, asType: asType}, nil
|
return &IPMatcher{matcher: m, asType: asType}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply implements Condition.
|
// Apply implements Condition.
|
||||||
@@ -361,8 +341,10 @@ func (m *ProcessNameMatcher) Apply(ctx routing.Context) bool {
|
|||||||
if len(ctx.GetSourceIPs()) == 0 {
|
if len(ctx.GetSourceIPs()) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
srcPort := ctx.GetSourcePort().String()
|
|
||||||
|
srcPort := uint16(ctx.GetSourcePort())
|
||||||
srcIP := ctx.GetSourceIPs()[0].String()
|
srcIP := ctx.GetSourceIPs()[0].String()
|
||||||
|
|
||||||
var network string
|
var network string
|
||||||
switch ctx.GetNetwork() {
|
switch ctx.GetNetwork() {
|
||||||
case net.Network_TCP:
|
case net.Network_TCP:
|
||||||
@@ -372,11 +354,21 @@ func (m *ProcessNameMatcher) Apply(ctx routing.Context) bool {
|
|||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
src, err := net.ParseDestination(strings.Join([]string{network, srcIP, srcPort}, ":"))
|
|
||||||
if err != nil {
|
var dstIP string
|
||||||
return false
|
var dstPort uint16 = 0
|
||||||
|
|
||||||
|
// do not use resolved IP because Android process lookup needs original dst ip
|
||||||
|
resolvableContext, ok := ctx.(*dns.ResolvableContext)
|
||||||
|
if ok && len(resolvableContext.Context.GetTargetIPs()) > 0 {
|
||||||
|
dstIP = resolvableContext.Context.GetTargetIPs()[0].String()
|
||||||
|
dstPort = uint16(resolvableContext.Context.GetTargetPort())
|
||||||
|
} else if len(ctx.GetTargetIPs()) > 0 {
|
||||||
|
dstIP = ctx.GetTargetIPs()[0].String()
|
||||||
|
dstPort = uint16(ctx.GetTargetPort())
|
||||||
}
|
}
|
||||||
pid, name, absPath, err := net.FindProcess(src)
|
|
||||||
|
pid, name, absPath, err := net.FindProcess(network, srcIP, uint16(srcPort), dstIP, uint16(dstPort))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != net.ErrNotLocal {
|
if err != net.ErrNotLocal {
|
||||||
errors.LogError(context.Background(), "Unables to find local process name: ", err)
|
errors.LogError(context.Background(), "Unables to find local process name: ", err)
|
||||||
|
|||||||
@@ -1,266 +0,0 @@
|
|||||||
package router_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/router"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/platform"
|
|
||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
func getAssetPath(file string) (string, error) {
|
|
||||||
path := platform.GetAssetLocation(file)
|
|
||||||
_, err := os.Stat(path)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
path := filepath.Join("..", "..", "resources", file)
|
|
||||||
_, err := os.Stat(path)
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return "", fmt.Errorf("can't find %s in standard asset locations or {project_root}/resources", file)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("can't stat %s: %v", path, err)
|
|
||||||
}
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("can't stat %s: %v", path, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGeoIPMatcher(t *testing.T) {
|
|
||||||
cidrList := []*router.CIDR{
|
|
||||||
{Ip: []byte{0, 0, 0, 0}, Prefix: 8},
|
|
||||||
{Ip: []byte{10, 0, 0, 0}, Prefix: 8},
|
|
||||||
{Ip: []byte{100, 64, 0, 0}, Prefix: 10},
|
|
||||||
{Ip: []byte{127, 0, 0, 0}, Prefix: 8},
|
|
||||||
{Ip: []byte{169, 254, 0, 0}, Prefix: 16},
|
|
||||||
{Ip: []byte{172, 16, 0, 0}, Prefix: 12},
|
|
||||||
{Ip: []byte{192, 0, 0, 0}, Prefix: 24},
|
|
||||||
{Ip: []byte{192, 0, 2, 0}, Prefix: 24},
|
|
||||||
{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
|
|
||||||
{Ip: []byte{192, 18, 0, 0}, Prefix: 15},
|
|
||||||
{Ip: []byte{198, 51, 100, 0}, Prefix: 24},
|
|
||||||
{Ip: []byte{203, 0, 113, 0}, Prefix: 24},
|
|
||||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
|
||||||
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
|
||||||
Cidr: cidrList,
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
Input string
|
|
||||||
Output bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Input: "192.168.1.1",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "192.0.0.0",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "192.0.1.0",
|
|
||||||
Output: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "0.1.0.0",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "1.0.0.1",
|
|
||||||
Output: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "8.8.8.7",
|
|
||||||
Output: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "8.8.8.8",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "2001:cdba::3257:9652",
|
|
||||||
Output: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "91.108.255.254",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
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 TestGeoIPMatcherRegression(t *testing.T) {
|
|
||||||
cidrList := []*router.CIDR{
|
|
||||||
{Ip: []byte{98, 108, 20, 0}, Prefix: 22},
|
|
||||||
{Ip: []byte{98, 108, 20, 0}, Prefix: 23},
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
|
||||||
Cidr: cidrList,
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
Input string
|
|
||||||
Output bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
Input: "98.108.22.11",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Input: "98.108.25.0",
|
|
||||||
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 TestGeoIPReverseMatcher(t *testing.T) {
|
|
||||||
cidrList := []*router.CIDR{
|
|
||||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
|
||||||
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
|
||||||
}
|
|
||||||
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
|
||||||
Cidr: cidrList,
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
matcher.SetReverse(true) // Reverse match
|
|
||||||
|
|
||||||
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) {
|
|
||||||
ips, err := loadGeoIP("CN")
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
|
||||||
Cidr: ips,
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
if matcher.Match([]byte{8, 8, 8, 8}) {
|
|
||||||
t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGeoIPMatcher6US(t *testing.T) {
|
|
||||||
ips, err := loadGeoIP("US")
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
|
||||||
Cidr: ips,
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
|
|
||||||
t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadGeoIP(country string) ([]*router.CIDR, error) {
|
|
||||||
path, err := getAssetPath("geoip.dat")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
geoipBytes, err := filesystem.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var geoipList router.GeoIPList
|
|
||||||
if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, geoip := range geoipList.Entry {
|
|
||||||
if geoip.CountryCode == country {
|
|
||||||
return geoip.Cidr, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panic("country not found: " + country)
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkGeoIPMatcher4CN(b *testing.B) {
|
|
||||||
ips, err := loadGeoIP("CN")
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
|
||||||
Cidr: ips,
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_ = matcher.Match([]byte{8, 8, 8, 8})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkGeoIPMatcher6US(b *testing.B) {
|
|
||||||
ips, err := loadGeoIP("US")
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
|
||||||
Cidr: ips,
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
_ = matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,19 @@
|
|||||||
package router_test
|
package router_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
. "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/geodata"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/platform/filesystem"
|
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/protocol/http"
|
"github.com/xtls/xray-core/common/protocol/http"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
routing_session "github.com/xtls/xray-core/features/routing/session"
|
routing_session "github.com/xtls/xray-core/features/routing/session"
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func withBackground() routing.Context {
|
func withBackground() routing.Context {
|
||||||
@@ -45,18 +44,15 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
rule: &RoutingRule{
|
rule: &RoutingRule{
|
||||||
Domain: []*Domain{
|
Domain: []*geodata.DomainRule{
|
||||||
{
|
{
|
||||||
Value: "example.com",
|
Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Substr, Value: "example.com"}},
|
||||||
Type: Domain_Plain,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Value: "google.com",
|
Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Domain, Value: "google.com"}},
|
||||||
Type: Domain_Domain,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Value: "^facebook\\.com$",
|
Value: &geodata.DomainRule_Custom{Custom: &geodata.Domain{Type: geodata.Domain_Regex, Value: "^facebook\\.com$"}},
|
||||||
Type: Domain_Regex,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -93,20 +89,25 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
rule: &RoutingRule{
|
rule: &RoutingRule{
|
||||||
Geoip: []*GeoIP{
|
Ip: []*geodata.IPRule{
|
||||||
{
|
{
|
||||||
Cidr: []*CIDR{
|
Value: &geodata.IPRule_Custom{
|
||||||
{
|
Custom: &geodata.CIDRRule{
|
||||||
Ip: []byte{8, 8, 8, 8},
|
Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
||||||
Prefix: 32,
|
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
Ip: []byte{8, 8, 8, 8},
|
},
|
||||||
Prefix: 32,
|
{
|
||||||
|
Value: &geodata.IPRule_Custom{
|
||||||
|
Custom: &geodata.CIDRRule{
|
||||||
|
Cidr: &geodata.CIDR{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
Ip: net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334").IP(),
|
},
|
||||||
Prefix: 128,
|
{
|
||||||
|
Value: &geodata.IPRule_Custom{
|
||||||
|
Custom: &geodata.CIDRRule{
|
||||||
|
Cidr: &geodata.CIDR{Ip: net.ParseAddress("2001:0db8:85a3:0000:0000:8a2e:0370:7334").IP(), Prefix: 128},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -133,12 +134,11 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
rule: &RoutingRule{
|
rule: &RoutingRule{
|
||||||
SourceGeoip: []*GeoIP{
|
SourceIp: []*geodata.IPRule{
|
||||||
{
|
{
|
||||||
Cidr: []*CIDR{
|
Value: &geodata.IPRule_Custom{
|
||||||
{
|
Custom: &geodata.CIDRRule{
|
||||||
Ip: []byte{192, 168, 0, 0},
|
Cidr: &geodata.CIDR{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
|
||||||
Prefix: 16,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -300,35 +300,12 @@ func TestRoutingRule(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadGeoSite(country string) ([]*Domain, error) {
|
|
||||||
path, err := getAssetPath("geosite.dat")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
geositeBytes, err := filesystem.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var geositeList GeoSiteList
|
|
||||||
if err := proto.Unmarshal(geositeBytes, &geositeList); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, site := range geositeList.Entry {
|
|
||||||
if site.CountryCode == country {
|
|
||||||
return site.Domain, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.New("country not found: " + country)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestChinaSites(t *testing.T) {
|
func TestChinaSites(t *testing.T) {
|
||||||
domains, err := loadGeoSite("CN")
|
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
rules, err := geodata.ParseDomainRules([]string{"geosite:cn"}, geodata.Domain_Substr)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
acMatcher, err := NewMphMatcherGroup(domains)
|
matcher, err := NewDomainMatcher(rules)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
@@ -359,18 +336,19 @@ func TestChinaSites(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
r := acMatcher.ApplyDomain(testCase.Domain)
|
r := matcher.ApplyDomain(testCase.Domain)
|
||||||
if r != testCase.Output {
|
if r != testCase.Output {
|
||||||
t.Error("ACDomainMatcher expected output ", testCase.Output, " for domain ", testCase.Domain, " but got ", r)
|
t.Error("DomainMatcher expected output ", testCase.Output, " for domain ", testCase.Domain, " but got ", r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMphDomainMatcher(b *testing.B) {
|
func BenchmarkMphDomainMatcher(b *testing.B) {
|
||||||
domains, err := loadGeoSite("CN")
|
b.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
rules, err := geodata.ParseDomainRules([]string{"geosite:cn"}, geodata.Domain_Substr)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher, err := NewMphMatcherGroup(domains)
|
matcher, err := NewDomainMatcher(rules)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
type TestCase struct {
|
type TestCase struct {
|
||||||
@@ -409,45 +387,11 @@ func BenchmarkMphDomainMatcher(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
||||||
var geoips []*GeoIP
|
b.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
rules, err := geodata.ParseIPRules([]string{"geoip:cn", "geoip:jp", "geoip:ca", "geoip:us"})
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
{
|
matcher, err := NewIPMatcher(rules, MatcherAsType_Target)
|
||||||
ips, err := loadGeoIP("CN")
|
|
||||||
common.Must(err)
|
|
||||||
geoips = append(geoips, &GeoIP{
|
|
||||||
CountryCode: "CN",
|
|
||||||
Cidr: ips,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
ips, err := loadGeoIP("JP")
|
|
||||||
common.Must(err)
|
|
||||||
geoips = append(geoips, &GeoIP{
|
|
||||||
CountryCode: "JP",
|
|
||||||
Cidr: ips,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
ips, err := loadGeoIP("CA")
|
|
||||||
common.Must(err)
|
|
||||||
geoips = append(geoips, &GeoIP{
|
|
||||||
CountryCode: "CA",
|
|
||||||
Cidr: ips,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
ips, err := loadGeoIP("US")
|
|
||||||
common.Must(err)
|
|
||||||
geoips = append(geoips, &GeoIP{
|
|
||||||
CountryCode: "US",
|
|
||||||
Cidr: ips,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher, err := NewIPMatcher(geoips, MatcherAsType_Target)
|
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
||||||
|
|||||||
+10
-10
@@ -15,6 +15,7 @@ type Rule struct {
|
|||||||
RuleTag string
|
RuleTag string
|
||||||
Balancer *Balancer
|
Balancer *Balancer
|
||||||
Condition Condition
|
Condition Condition
|
||||||
|
Webhook *WebhookNotifier
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rule) GetTag() (string, error) {
|
func (r *Rule) GetTag() (string, error) {
|
||||||
@@ -72,24 +73,24 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
conds.Add(&AttributeMatcher{configuredKeys})
|
conds.Add(&AttributeMatcher{configuredKeys})
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Geoip) > 0 {
|
if len(rr.Ip) > 0 {
|
||||||
cond, err := NewIPMatcher(rr.Geoip, MatcherAsType_Target)
|
cond, err := NewIPMatcher(rr.Ip, MatcherAsType_Target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conds.Add(cond)
|
conds.Add(cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.SourceGeoip) > 0 {
|
if len(rr.SourceIp) > 0 {
|
||||||
cond, err := NewIPMatcher(rr.SourceGeoip, MatcherAsType_Source)
|
cond, err := NewIPMatcher(rr.SourceIp, MatcherAsType_Source)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conds.Add(cond)
|
conds.Add(cond)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.LocalGeoip) > 0 {
|
if len(rr.LocalIp) > 0 {
|
||||||
cond, err := NewIPMatcher(rr.LocalGeoip, MatcherAsType_Local)
|
cond, err := NewIPMatcher(rr.LocalIp, MatcherAsType_Local)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -98,12 +99,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Domain) > 0 {
|
if len(rr.Domain) > 0 {
|
||||||
matcher, err := NewMphMatcherGroup(rr.Domain)
|
cond, err := NewDomainMatcher(rr.Domain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build domain condition with MphDomainMatcher").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)")
|
conds.Add(cond)
|
||||||
conds.Add(matcher)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Process) > 0 {
|
if len(rr.Process) > 0 {
|
||||||
|
|||||||
+256
-771
File diff suppressed because it is too large
Load Diff
+22
-75
@@ -9,67 +9,7 @@ option java_multiple_files = true;
|
|||||||
import "common/serial/typed_message.proto";
|
import "common/serial/typed_message.proto";
|
||||||
import "common/net/port.proto";
|
import "common/net/port.proto";
|
||||||
import "common/net/network.proto";
|
import "common/net/network.proto";
|
||||||
|
import "common/geodata/geodat.proto";
|
||||||
// Domain for routing decision.
|
|
||||||
message Domain {
|
|
||||||
// Type of domain value.
|
|
||||||
enum Type {
|
|
||||||
// The value is used as is.
|
|
||||||
Plain = 0;
|
|
||||||
// The value is used as a regular expression.
|
|
||||||
Regex = 1;
|
|
||||||
// The value is a root domain.
|
|
||||||
Domain = 2;
|
|
||||||
// The value is a domain.
|
|
||||||
Full = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain matching type.
|
|
||||||
Type type = 1;
|
|
||||||
|
|
||||||
// Domain value.
|
|
||||||
string value = 2;
|
|
||||||
|
|
||||||
message Attribute {
|
|
||||||
string key = 1;
|
|
||||||
|
|
||||||
oneof typed_value {
|
|
||||||
bool bool_value = 2;
|
|
||||||
int64 int_value = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attributes of this domain. May be used for filtering.
|
|
||||||
repeated Attribute attribute = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IP for routing decision, in CIDR form.
|
|
||||||
message CIDR {
|
|
||||||
// IP address, should be either 4 or 16 bytes.
|
|
||||||
bytes ip = 1;
|
|
||||||
|
|
||||||
// Number of leading ones in the network mask.
|
|
||||||
uint32 prefix = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoIP {
|
|
||||||
string country_code = 1;
|
|
||||||
repeated CIDR cidr = 2;
|
|
||||||
bool reverse_match = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoIPList {
|
|
||||||
repeated GeoIP entry = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoSite {
|
|
||||||
string country_code = 1;
|
|
||||||
repeated Domain domain = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GeoSiteList {
|
|
||||||
repeated GeoSite entry = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message RoutingRule {
|
message RoutingRule {
|
||||||
oneof target_tag {
|
oneof target_tag {
|
||||||
@@ -79,26 +19,23 @@ message RoutingRule {
|
|||||||
// Tag of routing balancer.
|
// Tag of routing balancer.
|
||||||
string balancing_tag = 12;
|
string balancing_tag = 12;
|
||||||
}
|
}
|
||||||
string rule_tag = 19;
|
|
||||||
|
string rule_tag = 19;
|
||||||
|
|
||||||
// List of domains for target domain matching.
|
// List of domains for target domain matching.
|
||||||
repeated Domain domain = 2;
|
repeated xray.common.geodata.DomainRule domain = 2;
|
||||||
|
|
||||||
// List of GeoIPs for target IP address matching. If this entry exists, the
|
// List of IPs for target IP address matching.
|
||||||
// cidr above will have no effect. GeoIP fields with the same country code are
|
repeated xray.common.geodata.IPRule ip = 10;
|
||||||
// supposed to contain exactly same content. They will be merged during
|
|
||||||
// runtime. For customized GeoIPs, please leave country code empty.
|
|
||||||
repeated GeoIP geoip = 10;
|
|
||||||
|
|
||||||
// List of ports.
|
// List of ports for target port matching.
|
||||||
xray.common.net.PortList port_list = 14;
|
xray.common.net.PortList port_list = 14;
|
||||||
|
|
||||||
// List of networks for matching.
|
// List of networks for matching.
|
||||||
repeated xray.common.net.Network networks = 13;
|
repeated xray.common.net.Network networks = 13;
|
||||||
|
|
||||||
// List of GeoIPs for source IP address matching. If this entry exists, the
|
// List of IPs for source IP address matching.
|
||||||
// source_cidr above will have no effect.
|
repeated xray.common.geodata.IPRule source_ip = 11;
|
||||||
repeated GeoIP source_geoip = 11;
|
|
||||||
|
|
||||||
// List of ports for source port matching.
|
// List of ports for source port matching.
|
||||||
xray.common.net.PortList source_port_list = 16;
|
xray.common.net.PortList source_port_list = 16;
|
||||||
@@ -109,11 +46,22 @@ message RoutingRule {
|
|||||||
|
|
||||||
map<string, string> attributes = 15;
|
map<string, string> attributes = 15;
|
||||||
|
|
||||||
repeated GeoIP local_geoip = 17;
|
// List of IPs for local IP address matching.
|
||||||
|
repeated xray.common.geodata.IPRule local_ip = 17;
|
||||||
|
|
||||||
|
// List of ports for local port matching.
|
||||||
xray.common.net.PortList local_port_list = 18;
|
xray.common.net.PortList local_port_list = 18;
|
||||||
|
|
||||||
xray.common.net.PortList vless_route_list = 20;
|
xray.common.net.PortList vless_route_list = 20;
|
||||||
|
|
||||||
repeated string process = 21;
|
repeated string process = 21;
|
||||||
|
WebhookConfig webhook = 22;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WebhookConfig {
|
||||||
|
string url = 1;
|
||||||
|
uint32 deduplication = 2;
|
||||||
|
map<string, string> headers = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BalancingRule {
|
message BalancingRule {
|
||||||
@@ -148,8 +96,7 @@ message Config {
|
|||||||
// Use domain as is.
|
// Use domain as is.
|
||||||
AsIs = 0;
|
AsIs = 0;
|
||||||
|
|
||||||
// [Deprecated] Always resolve IP for domains.
|
reserved 1;
|
||||||
// UseIp = 1;
|
|
||||||
|
|
||||||
// Resolve to IP if the domain doesn't match any rules.
|
// Resolve to IP if the domain doesn't match any rules.
|
||||||
IpIfNonMatch = 2;
|
IpIfNonMatch = 2;
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm out
|
|||||||
for _, rule := range config.Rule {
|
for _, rule := range config.Rule {
|
||||||
cond, err := rule.BuildCondition()
|
cond, err := rule.BuildCondition()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
r.closeWebhooks()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rr := &Rule{
|
rr := &Rule{
|
||||||
@@ -64,10 +65,22 @@ func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm out
|
|||||||
Tag: rule.GetTag(),
|
Tag: rule.GetTag(),
|
||||||
RuleTag: rule.GetRuleTag(),
|
RuleTag: rule.GetRuleTag(),
|
||||||
}
|
}
|
||||||
|
if wh := rule.GetWebhook(); wh != nil {
|
||||||
|
notifier, err := NewWebhookNotifier(wh)
|
||||||
|
if err != nil {
|
||||||
|
r.closeWebhooks()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rr.Webhook = notifier
|
||||||
|
}
|
||||||
btag := rule.GetBalancingTag()
|
btag := rule.GetBalancingTag()
|
||||||
if len(btag) > 0 {
|
if len(btag) > 0 {
|
||||||
brule, found := r.balancers[btag]
|
brule, found := r.balancers[btag]
|
||||||
if !found {
|
if !found {
|
||||||
|
if rr.Webhook != nil {
|
||||||
|
rr.Webhook.Close()
|
||||||
|
}
|
||||||
|
r.closeWebhooks()
|
||||||
return errors.New("balancer ", btag, " not found")
|
return errors.New("balancer ", btag, " not found")
|
||||||
}
|
}
|
||||||
rr.Balancer = brule
|
rr.Balancer = brule
|
||||||
@@ -80,6 +93,7 @@ func (r *Router) Init(ctx context.Context, config *Config, d dns.Client, ohm out
|
|||||||
|
|
||||||
// PickRoute implements routing.Router.
|
// PickRoute implements routing.Router.
|
||||||
func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
|
func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
|
||||||
|
originalCtx := ctx
|
||||||
rule, ctx, err := r.pickRouteInternal(ctx)
|
rule, ctx, err := r.pickRouteInternal(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -88,6 +102,9 @@ func (r *Router) PickRoute(ctx routing.Context) (routing.Route, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if rule.Webhook != nil {
|
||||||
|
rule.Webhook.Fire(originalCtx, tag)
|
||||||
|
}
|
||||||
return &Route{Context: ctx, outboundTag: tag, ruleTag: rule.RuleTag}, nil
|
return &Route{Context: ctx, outboundTag: tag, ruleTag: rule.RuleTag}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +126,11 @@ func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
|
|||||||
defer r.mu.Unlock()
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
if !shouldAppend {
|
if !shouldAppend {
|
||||||
|
for _, rule := range r.rules {
|
||||||
|
if rule.Webhook != nil {
|
||||||
|
rule.Webhook.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
|
r.balancers = make(map[string]*Balancer, len(config.BalancingRule))
|
||||||
r.rules = make([]*Rule, 0, len(config.Rule))
|
r.rules = make([]*Rule, 0, len(config.Rule))
|
||||||
}
|
}
|
||||||
@@ -125,12 +147,24 @@ func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
|
|||||||
r.balancers[rule.Tag] = balancer
|
r.balancers[rule.Tag] = balancer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startIdx := len(r.rules)
|
||||||
|
closeNewWebhooks := func() {
|
||||||
|
for i := startIdx; i < len(r.rules); i++ {
|
||||||
|
if r.rules[i].Webhook != nil {
|
||||||
|
r.rules[i].Webhook.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.rules = r.rules[:startIdx]
|
||||||
|
}
|
||||||
|
|
||||||
for _, rule := range config.Rule {
|
for _, rule := range config.Rule {
|
||||||
if r.RuleExists(rule.GetRuleTag()) {
|
if r.RuleExists(rule.GetRuleTag()) {
|
||||||
|
closeNewWebhooks()
|
||||||
return errors.New("duplicate ruleTag ", rule.GetRuleTag())
|
return errors.New("duplicate ruleTag ", rule.GetRuleTag())
|
||||||
}
|
}
|
||||||
cond, err := rule.BuildCondition()
|
cond, err := rule.BuildCondition()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
closeNewWebhooks()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
rr := &Rule{
|
rr := &Rule{
|
||||||
@@ -138,10 +172,22 @@ func (r *Router) ReloadRules(config *Config, shouldAppend bool) error {
|
|||||||
Tag: rule.GetTag(),
|
Tag: rule.GetTag(),
|
||||||
RuleTag: rule.GetRuleTag(),
|
RuleTag: rule.GetRuleTag(),
|
||||||
}
|
}
|
||||||
|
if wh := rule.GetWebhook(); wh != nil {
|
||||||
|
notifier, err := NewWebhookNotifier(wh)
|
||||||
|
if err != nil {
|
||||||
|
closeNewWebhooks()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rr.Webhook = notifier
|
||||||
|
}
|
||||||
btag := rule.GetBalancingTag()
|
btag := rule.GetBalancingTag()
|
||||||
if len(btag) > 0 {
|
if len(btag) > 0 {
|
||||||
brule, found := r.balancers[btag]
|
brule, found := r.balancers[btag]
|
||||||
if !found {
|
if !found {
|
||||||
|
if rr.Webhook != nil {
|
||||||
|
rr.Webhook.Close()
|
||||||
|
}
|
||||||
|
closeNewWebhooks()
|
||||||
return errors.New("balancer ", btag, " not found")
|
return errors.New("balancer ", btag, " not found")
|
||||||
}
|
}
|
||||||
rr.Balancer = brule
|
rr.Balancer = brule
|
||||||
@@ -173,6 +219,8 @@ func (r *Router) RemoveRule(tag string) error {
|
|||||||
for _, rule := range r.rules {
|
for _, rule := range r.rules {
|
||||||
if rule.RuleTag != tag {
|
if rule.RuleTag != tag {
|
||||||
newRules = append(newRules, rule)
|
newRules = append(newRules, rule)
|
||||||
|
} else if rule.Webhook != nil {
|
||||||
|
rule.Webhook.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.rules = newRules
|
r.rules = newRules
|
||||||
@@ -233,8 +281,20 @@ func (r *Router) Start() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// closeWebhooks closes all webhook notifiers in the current rule set.
|
||||||
|
func (r *Router) closeWebhooks() {
|
||||||
|
for _, rule := range r.rules {
|
||||||
|
if rule.Webhook != nil {
|
||||||
|
rule.Webhook.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Close implements common.Closable.
|
// Close implements common.Closable.
|
||||||
func (r *Router) Close() error {
|
func (r *Router) Close() error {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
r.closeWebhooks()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-15
@@ -7,6 +7,7 @@ import (
|
|||||||
"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/geodata"
|
||||||
"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/dns"
|
||||||
@@ -155,12 +156,11 @@ func TestIPOnDemand(t *testing.T) {
|
|||||||
TargetTag: &RoutingRule_Tag{
|
TargetTag: &RoutingRule_Tag{
|
||||||
Tag: "test",
|
Tag: "test",
|
||||||
},
|
},
|
||||||
Geoip: []*GeoIP{
|
Ip: []*geodata.IPRule{
|
||||||
{
|
{
|
||||||
Cidr: []*CIDR{
|
Value: &geodata.IPRule_Custom{
|
||||||
{
|
Custom: &geodata.CIDRRule{
|
||||||
Ip: []byte{192, 168, 0, 0},
|
Cidr: &geodata.CIDR{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
|
||||||
Prefix: 16,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -200,12 +200,11 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
|||||||
TargetTag: &RoutingRule_Tag{
|
TargetTag: &RoutingRule_Tag{
|
||||||
Tag: "test",
|
Tag: "test",
|
||||||
},
|
},
|
||||||
Geoip: []*GeoIP{
|
Ip: []*geodata.IPRule{
|
||||||
{
|
{
|
||||||
Cidr: []*CIDR{
|
Value: &geodata.IPRule_Custom{
|
||||||
{
|
Custom: &geodata.CIDRRule{
|
||||||
Ip: []byte{192, 168, 0, 0},
|
Cidr: &geodata.CIDR{Ip: []byte{192, 168, 0, 0}, Prefix: 16},
|
||||||
Prefix: 16,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -245,12 +244,11 @@ func TestIPIfNonMatchIP(t *testing.T) {
|
|||||||
TargetTag: &RoutingRule_Tag{
|
TargetTag: &RoutingRule_Tag{
|
||||||
Tag: "test",
|
Tag: "test",
|
||||||
},
|
},
|
||||||
Geoip: []*GeoIP{
|
Ip: []*geodata.IPRule{
|
||||||
{
|
{
|
||||||
Cidr: []*CIDR{
|
Value: &geodata.IPRule_Custom{
|
||||||
{
|
Custom: &geodata.CIDRRule{
|
||||||
Ip: []byte{127, 0, 0, 0},
|
Cidr: &geodata.CIDR{Ip: []byte{127, 0, 0, 0}, Prefix: 8},
|
||||||
Prefix: 8,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,287 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/features/routing"
|
||||||
|
routing_session "github.com/xtls/xray-core/features/routing/session"
|
||||||
|
)
|
||||||
|
|
||||||
|
// parseURL splits a webhook URL into an HTTP URL and an optional Unix socket
|
||||||
|
// path. For regular http/https URLs the input is returned unchanged with an
|
||||||
|
// empty socketPath. For Unix sockets the format is:
|
||||||
|
//
|
||||||
|
// /path/to/socket.sock:/http/path
|
||||||
|
// @abstract:/http/path
|
||||||
|
// @@padded:/http/path
|
||||||
|
//
|
||||||
|
// The :/ separator after the socket path delimits the HTTP request path.
|
||||||
|
// If omitted, "/" is used.
|
||||||
|
func parseURL(raw string) (httpURL, socketPath string) {
|
||||||
|
if len(raw) == 0 || (!filepath.IsAbs(raw) && raw[0] != '@') {
|
||||||
|
return raw, ""
|
||||||
|
}
|
||||||
|
if idx := strings.Index(raw, ":/"); idx >= 0 {
|
||||||
|
return "http://localhost" + raw[idx+1:], raw[:idx]
|
||||||
|
}
|
||||||
|
return "http://localhost/", raw
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolveSocketPath applies platform-specific transformations to a Unix
|
||||||
|
// socket path, matching the behaviour of the listen side in
|
||||||
|
// transport/internet/system_listener.go.
|
||||||
|
//
|
||||||
|
// For abstract sockets (prefix @) on Linux/Android:
|
||||||
|
// - single @ — used as-is (lock-free abstract socket)
|
||||||
|
// - double @@ — stripped to single @ and padded to
|
||||||
|
// syscall.RawSockaddrUnix{}.Path length (HAProxy compat)
|
||||||
|
func resolveSocketPath(path string) string {
|
||||||
|
if len(path) == 0 || path[0] != '@' {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
if runtime.GOOS != "linux" && runtime.GOOS != "android" {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
if len(path) > 1 && path[1] == '@' {
|
||||||
|
fullAddr := make([]byte, len(syscall.RawSockaddrUnix{}.Path))
|
||||||
|
copy(fullAddr, path[1:])
|
||||||
|
return string(fullAddr)
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
func ptr[T any](v T) *T { return &v }
|
||||||
|
|
||||||
|
type event struct {
|
||||||
|
Email *string `json:"email"`
|
||||||
|
Level *uint32 `json:"level"`
|
||||||
|
Protocol *string `json:"protocol"`
|
||||||
|
Network *string `json:"network"`
|
||||||
|
Source *string `json:"source"`
|
||||||
|
Destination *string `json:"destination"`
|
||||||
|
OriginalTarget *string `json:"originalTarget"`
|
||||||
|
RouteTarget *string `json:"routeTarget"`
|
||||||
|
InboundTag *string `json:"inboundTag"`
|
||||||
|
InboundName *string `json:"inboundName"`
|
||||||
|
InboundLocal *string `json:"inboundLocal"`
|
||||||
|
OutboundTag *string `json:"outboundTag"`
|
||||||
|
Timestamp int64 `json:"ts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebhookNotifier struct {
|
||||||
|
url string
|
||||||
|
headers map[string]string
|
||||||
|
deduplication uint32
|
||||||
|
client *http.Client
|
||||||
|
seen sync.Map
|
||||||
|
done chan struct{}
|
||||||
|
wg sync.WaitGroup
|
||||||
|
closeOnce sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWebhookNotifier(cfg *WebhookConfig) (*WebhookNotifier, error) {
|
||||||
|
if cfg == nil || cfg.Url == "" {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
httpURL, socketPath := parseURL(cfg.Url)
|
||||||
|
h := &WebhookNotifier{
|
||||||
|
url: httpURL,
|
||||||
|
deduplication: cfg.Deduplication,
|
||||||
|
client: &http.Client{
|
||||||
|
Timeout: 5 * time.Second,
|
||||||
|
},
|
||||||
|
done: make(chan struct{}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if socketPath != "" {
|
||||||
|
dialAddr := resolveSocketPath(socketPath)
|
||||||
|
h.client.Transport = &http.Transport{
|
||||||
|
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||||
|
var d net.Dialer
|
||||||
|
return d.DialContext(ctx, "unix", dialAddr)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cfg.Headers) > 0 {
|
||||||
|
h.headers = make(map[string]string, len(cfg.Headers))
|
||||||
|
for k, v := range cfg.Headers {
|
||||||
|
h.headers[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if h.deduplication > 0 {
|
||||||
|
h.wg.Add(1)
|
||||||
|
go h.cleanupLoop()
|
||||||
|
}
|
||||||
|
|
||||||
|
return h, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *WebhookNotifier) Fire(ctx routing.Context, outboundTag string) {
|
||||||
|
ev := buildEvent(ctx, outboundTag)
|
||||||
|
|
||||||
|
email := ""
|
||||||
|
if ev.Email != nil {
|
||||||
|
email = *ev.Email
|
||||||
|
}
|
||||||
|
if h.isDuplicate(email) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
h.wg.Add(1)
|
||||||
|
select {
|
||||||
|
case <-h.done:
|
||||||
|
h.wg.Done()
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
defer h.wg.Done()
|
||||||
|
h.post(ev)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildEvent(ctx routing.Context, outboundTag string) *event {
|
||||||
|
ev := &event{
|
||||||
|
Timestamp: time.Now().Unix(),
|
||||||
|
OutboundTag: ptr(outboundTag),
|
||||||
|
InboundTag: ptr(ctx.GetInboundTag()),
|
||||||
|
Protocol: ptr(ctx.GetProtocol()),
|
||||||
|
Network: ptr(ctx.GetNetwork().SystemString()),
|
||||||
|
}
|
||||||
|
|
||||||
|
if user := ctx.GetUser(); user != "" {
|
||||||
|
ev.Email = ptr(user)
|
||||||
|
}
|
||||||
|
|
||||||
|
if srcIPs := ctx.GetSourceIPs(); len(srcIPs) > 0 {
|
||||||
|
srcPort := ctx.GetSourcePort()
|
||||||
|
ev.Source = ptr(net.JoinHostPort(srcIPs[0].String(), srcPort.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
targetPort := ctx.GetTargetPort()
|
||||||
|
if domain := ctx.GetTargetDomain(); domain != "" {
|
||||||
|
ev.Destination = ptr(net.JoinHostPort(domain, targetPort.String()))
|
||||||
|
} else if targetIPs := ctx.GetTargetIPs(); len(targetIPs) > 0 {
|
||||||
|
ev.Destination = ptr(net.JoinHostPort(targetIPs[0].String(), targetPort.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if localIPs := ctx.GetLocalIPs(); len(localIPs) > 0 {
|
||||||
|
localPort := ctx.GetLocalPort()
|
||||||
|
ev.InboundLocal = ptr(net.JoinHostPort(localIPs[0].String(), localPort.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
if sctx, ok := ctx.(*routing_session.Context); ok {
|
||||||
|
enrichFromSession(ev, sctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ev
|
||||||
|
}
|
||||||
|
|
||||||
|
func enrichFromSession(ev *event, sctx *routing_session.Context) {
|
||||||
|
if sctx.Inbound != nil {
|
||||||
|
ev.InboundName = ptr(sctx.Inbound.Name)
|
||||||
|
if sctx.Inbound.User != nil {
|
||||||
|
ev.Level = ptr(sctx.Inbound.User.Level)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if sctx.Outbound != nil {
|
||||||
|
if sctx.Outbound.OriginalTarget.Address != nil {
|
||||||
|
ev.OriginalTarget = ptr(sctx.Outbound.OriginalTarget.String())
|
||||||
|
}
|
||||||
|
if sctx.Outbound.RouteTarget.Address != nil {
|
||||||
|
ev.RouteTarget = ptr(sctx.Outbound.RouteTarget.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *WebhookNotifier) post(ev *event) {
|
||||||
|
body, err := json.Marshal(ev)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogWarning(context.Background(), "webhook: marshal failed: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, h.url, bytes.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
errors.LogWarning(context.Background(), "webhook: request build failed: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
for k, v := range h.headers {
|
||||||
|
req.Header.Set(k, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := h.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogInfo(context.Background(), "webhook: POST failed: ", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
io.Copy(io.Discard, resp.Body)
|
||||||
|
resp.Body.Close()
|
||||||
|
}()
|
||||||
|
if resp.StatusCode >= 400 {
|
||||||
|
errors.LogWarning(context.Background(), "webhook: POST returned status ", resp.StatusCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *WebhookNotifier) isDuplicate(email string) bool {
|
||||||
|
if h.deduplication == 0 || email == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
ttl := time.Duration(h.deduplication) * time.Second
|
||||||
|
now := time.Now()
|
||||||
|
if v, loaded := h.seen.LoadOrStore(email, now); loaded {
|
||||||
|
if now.Sub(v.(time.Time)) < ttl {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
h.seen.Store(email, now)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *WebhookNotifier) cleanupLoop() {
|
||||||
|
defer h.wg.Done()
|
||||||
|
ttl := time.Duration(h.deduplication) * time.Second
|
||||||
|
ticker := time.NewTicker(ttl)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-h.done:
|
||||||
|
return
|
||||||
|
case <-ticker.C:
|
||||||
|
now := time.Now()
|
||||||
|
h.seen.Range(func(key, value any) bool {
|
||||||
|
if now.Sub(value.(time.Time)) >= ttl {
|
||||||
|
h.seen.Delete(key)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *WebhookNotifier) Close() error {
|
||||||
|
h.closeOnce.Do(func() {
|
||||||
|
close(h.done)
|
||||||
|
})
|
||||||
|
h.wg.Wait()
|
||||||
|
h.client.CloseIdleConnections()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -3,12 +3,10 @@ package command
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"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/errors"
|
|
||||||
"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"
|
grpc "google.golang.org/grpc"
|
||||||
@@ -70,9 +68,10 @@ func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStat
|
|||||||
}
|
}
|
||||||
|
|
||||||
ips := make(map[string]int64)
|
ips := make(map[string]int64)
|
||||||
for ip, t := range c.IpTimeMap() {
|
c.ForEach(func(ip string, lastSeen int64) bool {
|
||||||
ips[ip] = t.Unix()
|
ips[ip] = lastSeen
|
||||||
}
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
return &GetStatsOnlineIpListResponse{
|
return &GetStatsOnlineIpListResponse{
|
||||||
Name: request.Name,
|
Name: request.Name,
|
||||||
@@ -86,21 +85,87 @@ func (s *statsServer) GetAllOnlineUsers(ctx context.Context, request *GetAllOnli
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
|
func (s *statsServer) GetUsersStats(ctx context.Context, request *GetUsersStatsRequest) (*GetUsersStatsResponse, error) {
|
||||||
matcher, err := strmatcher.Substr.New(request.Pattern)
|
userMap := make(map[string]*UserStat)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
s.stats.VisitOnlineMaps(func(name string, om feature_stats.OnlineMap) bool {
|
||||||
|
if om.Count() == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
_, rest, _ := strings.Cut(name, ">>>")
|
||||||
|
email, _, _ := strings.Cut(rest, ">>>")
|
||||||
|
|
||||||
|
user := &UserStat{Email: email}
|
||||||
|
om.ForEach(func(ip string, lastSeen int64) bool {
|
||||||
|
user.Ips = append(user.Ips, &OnlineIPEntry{
|
||||||
|
Ip: ip,
|
||||||
|
LastSeen: lastSeen,
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
if len(user.Ips) > 0 {
|
||||||
|
userMap[email] = user
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
if request.IncludeTraffic {
|
||||||
|
for _, u := range userMap {
|
||||||
|
u.Traffic = &TrafficUserStat{}
|
||||||
|
}
|
||||||
|
const (
|
||||||
|
prefixUser = "user>>>"
|
||||||
|
suffixUplink = ">>>traffic>>>uplink"
|
||||||
|
suffixDownlink = ">>>traffic>>>downlink"
|
||||||
|
)
|
||||||
|
s.stats.VisitCounters(func(name string, c feature_stats.Counter) bool {
|
||||||
|
var email string
|
||||||
|
var isUplink bool
|
||||||
|
|
||||||
|
if strings.HasSuffix(name, suffixUplink) {
|
||||||
|
email = name[len(prefixUser) : len(name)-len(suffixUplink)]
|
||||||
|
isUplink = true
|
||||||
|
} else if strings.HasSuffix(name, suffixDownlink) {
|
||||||
|
email = name[len(prefixUser) : len(name)-len(suffixDownlink)]
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
u, ok := userMap[email]
|
||||||
|
if !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var value int64
|
||||||
|
if request.Reset_ {
|
||||||
|
value = c.Set(0)
|
||||||
|
} else {
|
||||||
|
value = c.Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
if isUplink {
|
||||||
|
u.Traffic.Uplink = value
|
||||||
|
} else {
|
||||||
|
u.Traffic.Downlink = value
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resp := &GetUsersStatsResponse{}
|
||||||
|
for _, u := range userMap {
|
||||||
|
resp.Users = append(resp.Users, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *statsServer) QueryStats(ctx context.Context, request *QueryStatsRequest) (*QueryStatsResponse, error) {
|
||||||
response := &QueryStatsResponse{}
|
response := &QueryStatsResponse{}
|
||||||
|
|
||||||
manager, ok := s.stats.(*stats.Manager)
|
s.stats.VisitCounters(func(name string, c feature_stats.Counter) bool {
|
||||||
if !ok {
|
if strings.Contains(name, request.Pattern) {
|
||||||
return nil, errors.New("QueryStats only works its own stats.Manager.")
|
|
||||||
}
|
|
||||||
|
|
||||||
manager.VisitCounters(func(name string, c feature_stats.Counter) bool {
|
|
||||||
if matcher.Match(name) {
|
|
||||||
var value int64
|
var value int64
|
||||||
if request.Reset_ {
|
if request.Reset_ {
|
||||||
value = c.Set(0)
|
value = c.Set(0)
|
||||||
|
|||||||
+368
-82
@@ -1,8 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.36.8
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v6.32.0
|
// protoc v6.33.5
|
||||||
// source: command.proto
|
// source: app/stats/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ type GetStatsRequest struct {
|
|||||||
|
|
||||||
func (x *GetStatsRequest) Reset() {
|
func (x *GetStatsRequest) Reset() {
|
||||||
*x = GetStatsRequest{}
|
*x = GetStatsRequest{}
|
||||||
mi := &file_command_proto_msgTypes[0]
|
mi := &file_app_stats_command_command_proto_msgTypes[0]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ func (x *GetStatsRequest) String() string {
|
|||||||
func (*GetStatsRequest) ProtoMessage() {}
|
func (*GetStatsRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[0]
|
mi := &file_app_stats_command_command_proto_msgTypes[0]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -58,7 +58,7 @@ func (x *GetStatsRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetStatsRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetStatsRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*GetStatsRequest) Descriptor() ([]byte, []int) {
|
func (*GetStatsRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{0}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetStatsRequest) GetName() string {
|
func (x *GetStatsRequest) GetName() string {
|
||||||
@@ -85,7 +85,7 @@ type Stat struct {
|
|||||||
|
|
||||||
func (x *Stat) Reset() {
|
func (x *Stat) Reset() {
|
||||||
*x = Stat{}
|
*x = Stat{}
|
||||||
mi := &file_command_proto_msgTypes[1]
|
mi := &file_app_stats_command_command_proto_msgTypes[1]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -97,7 +97,7 @@ func (x *Stat) String() string {
|
|||||||
func (*Stat) ProtoMessage() {}
|
func (*Stat) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Stat) ProtoReflect() protoreflect.Message {
|
func (x *Stat) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[1]
|
mi := &file_app_stats_command_command_proto_msgTypes[1]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -110,7 +110,7 @@ func (x *Stat) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Stat.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Stat.ProtoReflect.Descriptor instead.
|
||||||
func (*Stat) Descriptor() ([]byte, []int) {
|
func (*Stat) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{1}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Stat) GetName() string {
|
func (x *Stat) GetName() string {
|
||||||
@@ -136,7 +136,7 @@ type GetStatsResponse struct {
|
|||||||
|
|
||||||
func (x *GetStatsResponse) Reset() {
|
func (x *GetStatsResponse) Reset() {
|
||||||
*x = GetStatsResponse{}
|
*x = GetStatsResponse{}
|
||||||
mi := &file_command_proto_msgTypes[2]
|
mi := &file_app_stats_command_command_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ func (x *GetStatsResponse) String() string {
|
|||||||
func (*GetStatsResponse) ProtoMessage() {}
|
func (*GetStatsResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
|
func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[2]
|
mi := &file_app_stats_command_command_proto_msgTypes[2]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -161,7 +161,7 @@ func (x *GetStatsResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetStatsResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetStatsResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*GetStatsResponse) Descriptor() ([]byte, []int) {
|
func (*GetStatsResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{2}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetStatsResponse) GetStat() *Stat {
|
func (x *GetStatsResponse) GetStat() *Stat {
|
||||||
@@ -181,7 +181,7 @@ type QueryStatsRequest struct {
|
|||||||
|
|
||||||
func (x *QueryStatsRequest) Reset() {
|
func (x *QueryStatsRequest) Reset() {
|
||||||
*x = QueryStatsRequest{}
|
*x = QueryStatsRequest{}
|
||||||
mi := &file_command_proto_msgTypes[3]
|
mi := &file_app_stats_command_command_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -193,7 +193,7 @@ func (x *QueryStatsRequest) String() string {
|
|||||||
func (*QueryStatsRequest) ProtoMessage() {}
|
func (*QueryStatsRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
|
func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[3]
|
mi := &file_app_stats_command_command_proto_msgTypes[3]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -206,7 +206,7 @@ func (x *QueryStatsRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use QueryStatsRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use QueryStatsRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*QueryStatsRequest) Descriptor() ([]byte, []int) {
|
func (*QueryStatsRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{3}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *QueryStatsRequest) GetPattern() string {
|
func (x *QueryStatsRequest) GetPattern() string {
|
||||||
@@ -232,7 +232,7 @@ type QueryStatsResponse struct {
|
|||||||
|
|
||||||
func (x *QueryStatsResponse) Reset() {
|
func (x *QueryStatsResponse) Reset() {
|
||||||
*x = QueryStatsResponse{}
|
*x = QueryStatsResponse{}
|
||||||
mi := &file_command_proto_msgTypes[4]
|
mi := &file_app_stats_command_command_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ func (x *QueryStatsResponse) String() string {
|
|||||||
func (*QueryStatsResponse) ProtoMessage() {}
|
func (*QueryStatsResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
|
func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[4]
|
mi := &file_app_stats_command_command_proto_msgTypes[4]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -257,7 +257,7 @@ func (x *QueryStatsResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use QueryStatsResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use QueryStatsResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*QueryStatsResponse) Descriptor() ([]byte, []int) {
|
func (*QueryStatsResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{4}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *QueryStatsResponse) GetStat() []*Stat {
|
func (x *QueryStatsResponse) GetStat() []*Stat {
|
||||||
@@ -275,7 +275,7 @@ type SysStatsRequest struct {
|
|||||||
|
|
||||||
func (x *SysStatsRequest) Reset() {
|
func (x *SysStatsRequest) Reset() {
|
||||||
*x = SysStatsRequest{}
|
*x = SysStatsRequest{}
|
||||||
mi := &file_command_proto_msgTypes[5]
|
mi := &file_app_stats_command_command_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -287,7 +287,7 @@ func (x *SysStatsRequest) String() string {
|
|||||||
func (*SysStatsRequest) ProtoMessage() {}
|
func (*SysStatsRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
|
func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[5]
|
mi := &file_app_stats_command_command_proto_msgTypes[5]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -300,7 +300,7 @@ func (x *SysStatsRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use SysStatsRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use SysStatsRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*SysStatsRequest) Descriptor() ([]byte, []int) {
|
func (*SysStatsRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{5}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SysStatsResponse struct {
|
type SysStatsResponse struct {
|
||||||
@@ -321,7 +321,7 @@ type SysStatsResponse struct {
|
|||||||
|
|
||||||
func (x *SysStatsResponse) Reset() {
|
func (x *SysStatsResponse) Reset() {
|
||||||
*x = SysStatsResponse{}
|
*x = SysStatsResponse{}
|
||||||
mi := &file_command_proto_msgTypes[6]
|
mi := &file_app_stats_command_command_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -333,7 +333,7 @@ func (x *SysStatsResponse) String() string {
|
|||||||
func (*SysStatsResponse) ProtoMessage() {}
|
func (*SysStatsResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
|
func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[6]
|
mi := &file_app_stats_command_command_proto_msgTypes[6]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -346,7 +346,7 @@ func (x *SysStatsResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use SysStatsResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use SysStatsResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*SysStatsResponse) Descriptor() ([]byte, []int) {
|
func (*SysStatsResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{6}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SysStatsResponse) GetNumGoroutine() uint32 {
|
func (x *SysStatsResponse) GetNumGoroutine() uint32 {
|
||||||
@@ -429,7 +429,7 @@ type GetStatsOnlineIpListResponse struct {
|
|||||||
|
|
||||||
func (x *GetStatsOnlineIpListResponse) Reset() {
|
func (x *GetStatsOnlineIpListResponse) Reset() {
|
||||||
*x = GetStatsOnlineIpListResponse{}
|
*x = GetStatsOnlineIpListResponse{}
|
||||||
mi := &file_command_proto_msgTypes[7]
|
mi := &file_app_stats_command_command_proto_msgTypes[7]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -441,7 +441,7 @@ func (x *GetStatsOnlineIpListResponse) String() string {
|
|||||||
func (*GetStatsOnlineIpListResponse) ProtoMessage() {}
|
func (*GetStatsOnlineIpListResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetStatsOnlineIpListResponse) ProtoReflect() protoreflect.Message {
|
func (x *GetStatsOnlineIpListResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[7]
|
mi := &file_app_stats_command_command_proto_msgTypes[7]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -454,7 +454,7 @@ func (x *GetStatsOnlineIpListResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetStatsOnlineIpListResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetStatsOnlineIpListResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*GetStatsOnlineIpListResponse) Descriptor() ([]byte, []int) {
|
func (*GetStatsOnlineIpListResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{7}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetStatsOnlineIpListResponse) GetName() string {
|
func (x *GetStatsOnlineIpListResponse) GetName() string {
|
||||||
@@ -479,7 +479,7 @@ type GetAllOnlineUsersRequest struct {
|
|||||||
|
|
||||||
func (x *GetAllOnlineUsersRequest) Reset() {
|
func (x *GetAllOnlineUsersRequest) Reset() {
|
||||||
*x = GetAllOnlineUsersRequest{}
|
*x = GetAllOnlineUsersRequest{}
|
||||||
mi := &file_command_proto_msgTypes[8]
|
mi := &file_app_stats_command_command_proto_msgTypes[8]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -491,7 +491,7 @@ func (x *GetAllOnlineUsersRequest) String() string {
|
|||||||
func (*GetAllOnlineUsersRequest) ProtoMessage() {}
|
func (*GetAllOnlineUsersRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetAllOnlineUsersRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetAllOnlineUsersRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[8]
|
mi := &file_app_stats_command_command_proto_msgTypes[8]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -504,7 +504,7 @@ func (x *GetAllOnlineUsersRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetAllOnlineUsersRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetAllOnlineUsersRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*GetAllOnlineUsersRequest) Descriptor() ([]byte, []int) {
|
func (*GetAllOnlineUsersRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{8}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{8}
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetAllOnlineUsersResponse struct {
|
type GetAllOnlineUsersResponse struct {
|
||||||
@@ -516,7 +516,7 @@ type GetAllOnlineUsersResponse struct {
|
|||||||
|
|
||||||
func (x *GetAllOnlineUsersResponse) Reset() {
|
func (x *GetAllOnlineUsersResponse) Reset() {
|
||||||
*x = GetAllOnlineUsersResponse{}
|
*x = GetAllOnlineUsersResponse{}
|
||||||
mi := &file_command_proto_msgTypes[9]
|
mi := &file_app_stats_command_command_proto_msgTypes[9]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -528,7 +528,7 @@ func (x *GetAllOnlineUsersResponse) String() string {
|
|||||||
func (*GetAllOnlineUsersResponse) ProtoMessage() {}
|
func (*GetAllOnlineUsersResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetAllOnlineUsersResponse) ProtoReflect() protoreflect.Message {
|
func (x *GetAllOnlineUsersResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[9]
|
mi := &file_app_stats_command_command_proto_msgTypes[9]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -541,7 +541,7 @@ func (x *GetAllOnlineUsersResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetAllOnlineUsersResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetAllOnlineUsersResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*GetAllOnlineUsersResponse) Descriptor() ([]byte, []int) {
|
func (*GetAllOnlineUsersResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{9}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{9}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetAllOnlineUsersResponse) GetUsers() []string {
|
func (x *GetAllOnlineUsersResponse) GetUsers() []string {
|
||||||
@@ -551,6 +551,266 @@ func (x *GetAllOnlineUsersResponse) GetUsers() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OnlineIPEntry struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Ip string `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||||
|
LastSeen int64 `protobuf:"varint,2,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OnlineIPEntry) Reset() {
|
||||||
|
*x = OnlineIPEntry{}
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[10]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OnlineIPEntry) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*OnlineIPEntry) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *OnlineIPEntry) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[10]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use OnlineIPEntry.ProtoReflect.Descriptor instead.
|
||||||
|
func (*OnlineIPEntry) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{10}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OnlineIPEntry) GetIp() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Ip
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *OnlineIPEntry) GetLastSeen() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.LastSeen
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type TrafficUserStat struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Uplink int64 `protobuf:"varint,1,opt,name=uplink,proto3" json:"uplink,omitempty"`
|
||||||
|
Downlink int64 `protobuf:"varint,2,opt,name=downlink,proto3" json:"downlink,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TrafficUserStat) Reset() {
|
||||||
|
*x = TrafficUserStat{}
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[11]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TrafficUserStat) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*TrafficUserStat) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *TrafficUserStat) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[11]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use TrafficUserStat.ProtoReflect.Descriptor instead.
|
||||||
|
func (*TrafficUserStat) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{11}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TrafficUserStat) GetUplink() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Uplink
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TrafficUserStat) GetDownlink() int64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Downlink
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserStat struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
|
||||||
|
Ips []*OnlineIPEntry `protobuf:"bytes,2,rep,name=ips,proto3" json:"ips,omitempty"`
|
||||||
|
Traffic *TrafficUserStat `protobuf:"bytes,3,opt,name=traffic,proto3" json:"traffic,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserStat) Reset() {
|
||||||
|
*x = UserStat{}
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[12]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserStat) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UserStat) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *UserStat) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[12]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use UserStat.ProtoReflect.Descriptor instead.
|
||||||
|
func (*UserStat) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{12}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserStat) GetEmail() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Email
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserStat) GetIps() []*OnlineIPEntry {
|
||||||
|
if x != nil {
|
||||||
|
return x.Ips
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *UserStat) GetTraffic() *TrafficUserStat {
|
||||||
|
if x != nil {
|
||||||
|
return x.Traffic
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetUsersStatsRequest struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
IncludeTraffic bool `protobuf:"varint,1,opt,name=include_traffic,json=includeTraffic,proto3" json:"include_traffic,omitempty"`
|
||||||
|
Reset_ bool `protobuf:"varint,2,opt,name=reset,proto3" json:"reset,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsRequest) Reset() {
|
||||||
|
*x = GetUsersStatsRequest{}
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[13]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsRequest) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetUsersStatsRequest) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsRequest) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[13]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetUsersStatsRequest.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetUsersStatsRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{13}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsRequest) GetIncludeTraffic() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.IncludeTraffic
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsRequest) GetReset_() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.Reset_
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetUsersStatsResponse struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Users []*UserStat `protobuf:"bytes,1,rep,name=users,proto3" json:"users,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsResponse) Reset() {
|
||||||
|
*x = GetUsersStatsResponse{}
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[14]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsResponse) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GetUsersStatsResponse) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsResponse) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_app_stats_command_command_proto_msgTypes[14]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GetUsersStatsResponse.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GetUsersStatsResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{14}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GetUsersStatsResponse) GetUsers() []*UserStat {
|
||||||
|
if x != nil {
|
||||||
|
return x.Users
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
@@ -559,7 +819,7 @@ type Config struct {
|
|||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
*x = Config{}
|
*x = Config{}
|
||||||
mi := &file_command_proto_msgTypes[10]
|
mi := &file_app_stats_command_command_proto_msgTypes[15]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -571,7 +831,7 @@ func (x *Config) String() string {
|
|||||||
func (*Config) ProtoMessage() {}
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_command_proto_msgTypes[10]
|
mi := &file_app_stats_command_command_proto_msgTypes[15]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -584,14 +844,14 @@ func (x *Config) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
func (*Config) Descriptor() ([]byte, []int) {
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
return file_command_proto_rawDescGZIP(), []int{10}
|
return file_app_stats_command_command_proto_rawDescGZIP(), []int{15}
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_command_proto protoreflect.FileDescriptor
|
var File_app_stats_command_command_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
const file_command_proto_rawDesc = "" +
|
const file_app_stats_command_command_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"\rcommand.proto\x12\x16xray.app.stats.command\";\n" +
|
"\x1fapp/stats/command/command.proto\x12\x16xray.app.stats.command\";\n" +
|
||||||
"\x0fGetStatsRequest\x12\x12\n" +
|
"\x0fGetStatsRequest\x12\x12\n" +
|
||||||
"\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
|
"\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" +
|
||||||
"\x05reset\x18\x02 \x01(\bR\x05reset\"0\n" +
|
"\x05reset\x18\x02 \x01(\bR\x05reset\"0\n" +
|
||||||
@@ -628,8 +888,23 @@ const file_command_proto_rawDesc = "" +
|
|||||||
"\x05value\x18\x02 \x01(\x03R\x05value:\x028\x01\"\x1a\n" +
|
"\x05value\x18\x02 \x01(\x03R\x05value:\x028\x01\"\x1a\n" +
|
||||||
"\x18GetAllOnlineUsersRequest\"1\n" +
|
"\x18GetAllOnlineUsersRequest\"1\n" +
|
||||||
"\x19GetAllOnlineUsersResponse\x12\x14\n" +
|
"\x19GetAllOnlineUsersResponse\x12\x14\n" +
|
||||||
"\x05users\x18\x01 \x03(\tR\x05users\"\b\n" +
|
"\x05users\x18\x01 \x03(\tR\x05users\"<\n" +
|
||||||
"\x06Config2\x96\x05\n" +
|
"\rOnlineIPEntry\x12\x0e\n" +
|
||||||
|
"\x02ip\x18\x01 \x01(\tR\x02ip\x12\x1b\n" +
|
||||||
|
"\tlast_seen\x18\x02 \x01(\x03R\blastSeen\"E\n" +
|
||||||
|
"\x0fTrafficUserStat\x12\x16\n" +
|
||||||
|
"\x06uplink\x18\x01 \x01(\x03R\x06uplink\x12\x1a\n" +
|
||||||
|
"\bdownlink\x18\x02 \x01(\x03R\bdownlink\"\x9c\x01\n" +
|
||||||
|
"\bUserStat\x12\x14\n" +
|
||||||
|
"\x05email\x18\x01 \x01(\tR\x05email\x127\n" +
|
||||||
|
"\x03ips\x18\x02 \x03(\v2%.xray.app.stats.command.OnlineIPEntryR\x03ips\x12A\n" +
|
||||||
|
"\atraffic\x18\x03 \x01(\v2'.xray.app.stats.command.TrafficUserStatR\atraffic\"U\n" +
|
||||||
|
"\x14GetUsersStatsRequest\x12'\n" +
|
||||||
|
"\x0finclude_traffic\x18\x01 \x01(\bR\x0eincludeTraffic\x12\x14\n" +
|
||||||
|
"\x05reset\x18\x02 \x01(\bR\x05reset\"O\n" +
|
||||||
|
"\x15GetUsersStatsResponse\x126\n" +
|
||||||
|
"\x05users\x18\x01 \x03(\v2 .xray.app.stats.command.UserStatR\x05users\"\b\n" +
|
||||||
|
"\x06Config2\x86\x06\n" +
|
||||||
"\fStatsService\x12_\n" +
|
"\fStatsService\x12_\n" +
|
||||||
"\bGetStats\x12'.xray.app.stats.command.GetStatsRequest\x1a(.xray.app.stats.command.GetStatsResponse\"\x00\x12e\n" +
|
"\bGetStats\x12'.xray.app.stats.command.GetStatsRequest\x1a(.xray.app.stats.command.GetStatsResponse\"\x00\x12e\n" +
|
||||||
"\x0eGetStatsOnline\x12'.xray.app.stats.command.GetStatsRequest\x1a(.xray.app.stats.command.GetStatsResponse\"\x00\x12e\n" +
|
"\x0eGetStatsOnline\x12'.xray.app.stats.command.GetStatsRequest\x1a(.xray.app.stats.command.GetStatsResponse\"\x00\x12e\n" +
|
||||||
@@ -637,23 +912,24 @@ const file_command_proto_rawDesc = "" +
|
|||||||
"QueryStats\x12).xray.app.stats.command.QueryStatsRequest\x1a*.xray.app.stats.command.QueryStatsResponse\"\x00\x12b\n" +
|
"QueryStats\x12).xray.app.stats.command.QueryStatsRequest\x1a*.xray.app.stats.command.QueryStatsResponse\"\x00\x12b\n" +
|
||||||
"\vGetSysStats\x12'.xray.app.stats.command.SysStatsRequest\x1a(.xray.app.stats.command.SysStatsResponse\"\x00\x12w\n" +
|
"\vGetSysStats\x12'.xray.app.stats.command.SysStatsRequest\x1a(.xray.app.stats.command.SysStatsResponse\"\x00\x12w\n" +
|
||||||
"\x14GetStatsOnlineIpList\x12'.xray.app.stats.command.GetStatsRequest\x1a4.xray.app.stats.command.GetStatsOnlineIpListResponse\"\x00\x12z\n" +
|
"\x14GetStatsOnlineIpList\x12'.xray.app.stats.command.GetStatsRequest\x1a4.xray.app.stats.command.GetStatsOnlineIpListResponse\"\x00\x12z\n" +
|
||||||
"\x11GetAllOnlineUsers\x120.xray.app.stats.command.GetAllOnlineUsersRequest\x1a1.xray.app.stats.command.GetAllOnlineUsersResponse\"\x00Bd\n" +
|
"\x11GetAllOnlineUsers\x120.xray.app.stats.command.GetAllOnlineUsersRequest\x1a1.xray.app.stats.command.GetAllOnlineUsersResponse\"\x00\x12n\n" +
|
||||||
|
"\rGetUsersStats\x12,.xray.app.stats.command.GetUsersStatsRequest\x1a-.xray.app.stats.command.GetUsersStatsResponse\"\x00Bd\n" +
|
||||||
"\x1acom.xray.app.stats.commandP\x01Z+github.com/xtls/xray-core/app/stats/command\xaa\x02\x16Xray.App.Stats.Commandb\x06proto3"
|
"\x1acom.xray.app.stats.commandP\x01Z+github.com/xtls/xray-core/app/stats/command\xaa\x02\x16Xray.App.Stats.Commandb\x06proto3"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_command_proto_rawDescOnce sync.Once
|
file_app_stats_command_command_proto_rawDescOnce sync.Once
|
||||||
file_command_proto_rawDescData []byte
|
file_app_stats_command_command_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_command_proto_rawDescGZIP() []byte {
|
func file_app_stats_command_command_proto_rawDescGZIP() []byte {
|
||||||
file_command_proto_rawDescOnce.Do(func() {
|
file_app_stats_command_command_proto_rawDescOnce.Do(func() {
|
||||||
file_command_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_command_proto_rawDesc), len(file_command_proto_rawDesc)))
|
file_app_stats_command_command_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_stats_command_command_proto_rawDesc), len(file_app_stats_command_command_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_command_proto_rawDescData
|
return file_app_stats_command_command_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_command_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
|
var file_app_stats_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
|
||||||
var file_command_proto_goTypes = []any{
|
var file_app_stats_command_command_proto_goTypes = []any{
|
||||||
(*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest
|
(*GetStatsRequest)(nil), // 0: xray.app.stats.command.GetStatsRequest
|
||||||
(*Stat)(nil), // 1: xray.app.stats.command.Stat
|
(*Stat)(nil), // 1: xray.app.stats.command.Stat
|
||||||
(*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse
|
(*GetStatsResponse)(nil), // 2: xray.app.stats.command.GetStatsResponse
|
||||||
@@ -664,52 +940,62 @@ var file_command_proto_goTypes = []any{
|
|||||||
(*GetStatsOnlineIpListResponse)(nil), // 7: xray.app.stats.command.GetStatsOnlineIpListResponse
|
(*GetStatsOnlineIpListResponse)(nil), // 7: xray.app.stats.command.GetStatsOnlineIpListResponse
|
||||||
(*GetAllOnlineUsersRequest)(nil), // 8: xray.app.stats.command.GetAllOnlineUsersRequest
|
(*GetAllOnlineUsersRequest)(nil), // 8: xray.app.stats.command.GetAllOnlineUsersRequest
|
||||||
(*GetAllOnlineUsersResponse)(nil), // 9: xray.app.stats.command.GetAllOnlineUsersResponse
|
(*GetAllOnlineUsersResponse)(nil), // 9: xray.app.stats.command.GetAllOnlineUsersResponse
|
||||||
(*Config)(nil), // 10: xray.app.stats.command.Config
|
(*OnlineIPEntry)(nil), // 10: xray.app.stats.command.OnlineIPEntry
|
||||||
nil, // 11: xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
|
(*TrafficUserStat)(nil), // 11: xray.app.stats.command.TrafficUserStat
|
||||||
|
(*UserStat)(nil), // 12: xray.app.stats.command.UserStat
|
||||||
|
(*GetUsersStatsRequest)(nil), // 13: xray.app.stats.command.GetUsersStatsRequest
|
||||||
|
(*GetUsersStatsResponse)(nil), // 14: xray.app.stats.command.GetUsersStatsResponse
|
||||||
|
(*Config)(nil), // 15: xray.app.stats.command.Config
|
||||||
|
nil, // 16: xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
|
||||||
}
|
}
|
||||||
var file_command_proto_depIdxs = []int32{
|
var file_app_stats_command_command_proto_depIdxs = []int32{
|
||||||
1, // 0: xray.app.stats.command.GetStatsResponse.stat:type_name -> xray.app.stats.command.Stat
|
1, // 0: xray.app.stats.command.GetStatsResponse.stat:type_name -> xray.app.stats.command.Stat
|
||||||
1, // 1: xray.app.stats.command.QueryStatsResponse.stat:type_name -> xray.app.stats.command.Stat
|
1, // 1: xray.app.stats.command.QueryStatsResponse.stat:type_name -> xray.app.stats.command.Stat
|
||||||
11, // 2: xray.app.stats.command.GetStatsOnlineIpListResponse.ips:type_name -> xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
|
16, // 2: xray.app.stats.command.GetStatsOnlineIpListResponse.ips:type_name -> xray.app.stats.command.GetStatsOnlineIpListResponse.IpsEntry
|
||||||
0, // 3: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest
|
10, // 3: xray.app.stats.command.UserStat.ips:type_name -> xray.app.stats.command.OnlineIPEntry
|
||||||
0, // 4: xray.app.stats.command.StatsService.GetStatsOnline:input_type -> xray.app.stats.command.GetStatsRequest
|
11, // 4: xray.app.stats.command.UserStat.traffic:type_name -> xray.app.stats.command.TrafficUserStat
|
||||||
3, // 5: xray.app.stats.command.StatsService.QueryStats:input_type -> xray.app.stats.command.QueryStatsRequest
|
12, // 5: xray.app.stats.command.GetUsersStatsResponse.users:type_name -> xray.app.stats.command.UserStat
|
||||||
5, // 6: xray.app.stats.command.StatsService.GetSysStats:input_type -> xray.app.stats.command.SysStatsRequest
|
0, // 6: xray.app.stats.command.StatsService.GetStats:input_type -> xray.app.stats.command.GetStatsRequest
|
||||||
0, // 7: xray.app.stats.command.StatsService.GetStatsOnlineIpList:input_type -> xray.app.stats.command.GetStatsRequest
|
0, // 7: xray.app.stats.command.StatsService.GetStatsOnline:input_type -> xray.app.stats.command.GetStatsRequest
|
||||||
8, // 8: xray.app.stats.command.StatsService.GetAllOnlineUsers:input_type -> xray.app.stats.command.GetAllOnlineUsersRequest
|
3, // 8: xray.app.stats.command.StatsService.QueryStats:input_type -> xray.app.stats.command.QueryStatsRequest
|
||||||
2, // 9: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse
|
5, // 9: xray.app.stats.command.StatsService.GetSysStats:input_type -> xray.app.stats.command.SysStatsRequest
|
||||||
2, // 10: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse
|
0, // 10: xray.app.stats.command.StatsService.GetStatsOnlineIpList:input_type -> xray.app.stats.command.GetStatsRequest
|
||||||
4, // 11: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse
|
8, // 11: xray.app.stats.command.StatsService.GetAllOnlineUsers:input_type -> xray.app.stats.command.GetAllOnlineUsersRequest
|
||||||
6, // 12: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse
|
13, // 12: xray.app.stats.command.StatsService.GetUsersStats:input_type -> xray.app.stats.command.GetUsersStatsRequest
|
||||||
7, // 13: xray.app.stats.command.StatsService.GetStatsOnlineIpList:output_type -> xray.app.stats.command.GetStatsOnlineIpListResponse
|
2, // 13: xray.app.stats.command.StatsService.GetStats:output_type -> xray.app.stats.command.GetStatsResponse
|
||||||
9, // 14: xray.app.stats.command.StatsService.GetAllOnlineUsers:output_type -> xray.app.stats.command.GetAllOnlineUsersResponse
|
2, // 14: xray.app.stats.command.StatsService.GetStatsOnline:output_type -> xray.app.stats.command.GetStatsResponse
|
||||||
9, // [9:15] is the sub-list for method output_type
|
4, // 15: xray.app.stats.command.StatsService.QueryStats:output_type -> xray.app.stats.command.QueryStatsResponse
|
||||||
3, // [3:9] is the sub-list for method input_type
|
6, // 16: xray.app.stats.command.StatsService.GetSysStats:output_type -> xray.app.stats.command.SysStatsResponse
|
||||||
3, // [3:3] is the sub-list for extension type_name
|
7, // 17: xray.app.stats.command.StatsService.GetStatsOnlineIpList:output_type -> xray.app.stats.command.GetStatsOnlineIpListResponse
|
||||||
3, // [3:3] is the sub-list for extension extendee
|
9, // 18: xray.app.stats.command.StatsService.GetAllOnlineUsers:output_type -> xray.app.stats.command.GetAllOnlineUsersResponse
|
||||||
0, // [0:3] is the sub-list for field type_name
|
14, // 19: xray.app.stats.command.StatsService.GetUsersStats:output_type -> xray.app.stats.command.GetUsersStatsResponse
|
||||||
|
13, // [13:20] is the sub-list for method output_type
|
||||||
|
6, // [6:13] is the sub-list for method input_type
|
||||||
|
6, // [6:6] is the sub-list for extension type_name
|
||||||
|
6, // [6:6] is the sub-list for extension extendee
|
||||||
|
0, // [0:6] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_command_proto_init() }
|
func init() { file_app_stats_command_command_proto_init() }
|
||||||
func file_command_proto_init() {
|
func file_app_stats_command_command_proto_init() {
|
||||||
if File_command_proto != nil {
|
if File_app_stats_command_command_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_command_proto_rawDesc), len(file_command_proto_rawDesc)),
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_stats_command_command_proto_rawDesc), len(file_app_stats_command_command_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 12,
|
NumMessages: 17,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
GoTypes: file_command_proto_goTypes,
|
GoTypes: file_app_stats_command_command_proto_goTypes,
|
||||||
DependencyIndexes: file_command_proto_depIdxs,
|
DependencyIndexes: file_app_stats_command_command_proto_depIdxs,
|
||||||
MessageInfos: file_command_proto_msgTypes,
|
MessageInfos: file_app_stats_command_command_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_command_proto = out.File
|
File_app_stats_command_command_proto = out.File
|
||||||
file_command_proto_goTypes = nil
|
file_app_stats_command_command_proto_goTypes = nil
|
||||||
file_command_proto_depIdxs = nil
|
file_app_stats_command_command_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,31 @@ message GetAllOnlineUsersResponse {
|
|||||||
repeated string users = 1;
|
repeated string users = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message OnlineIPEntry {
|
||||||
|
string ip = 1;
|
||||||
|
int64 last_seen = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TrafficUserStat {
|
||||||
|
int64 uplink = 1;
|
||||||
|
int64 downlink = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserStat {
|
||||||
|
string email = 1;
|
||||||
|
repeated OnlineIPEntry ips = 2;
|
||||||
|
TrafficUserStat traffic = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetUsersStatsRequest {
|
||||||
|
bool include_traffic = 1;
|
||||||
|
bool reset = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetUsersStatsResponse {
|
||||||
|
repeated UserStat users = 1;
|
||||||
|
}
|
||||||
|
|
||||||
service StatsService {
|
service StatsService {
|
||||||
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
|
rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {}
|
||||||
rpc GetStatsOnline(GetStatsRequest) returns (GetStatsResponse) {}
|
rpc GetStatsOnline(GetStatsRequest) returns (GetStatsResponse) {}
|
||||||
@@ -64,6 +89,7 @@ service StatsService {
|
|||||||
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
|
rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {}
|
||||||
rpc GetStatsOnlineIpList(GetStatsRequest) returns (GetStatsOnlineIpListResponse) {}
|
rpc GetStatsOnlineIpList(GetStatsRequest) returns (GetStatsOnlineIpListResponse) {}
|
||||||
rpc GetAllOnlineUsers(GetAllOnlineUsersRequest) returns (GetAllOnlineUsersResponse) {}
|
rpc GetAllOnlineUsers(GetAllOnlineUsersRequest) returns (GetAllOnlineUsersResponse) {}
|
||||||
|
rpc GetUsersStats(GetUsersStatsRequest) returns (GetUsersStatsResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {}
|
message Config {}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// - protoc-gen-go-grpc v1.5.1
|
// - protoc-gen-go-grpc v1.6.0
|
||||||
// - protoc v6.32.0
|
// - protoc v6.33.5
|
||||||
// source: command.proto
|
// source: app/stats/command/command.proto
|
||||||
|
|
||||||
package command
|
package command
|
||||||
|
|
||||||
@@ -25,6 +25,7 @@ const (
|
|||||||
StatsService_GetSysStats_FullMethodName = "/xray.app.stats.command.StatsService/GetSysStats"
|
StatsService_GetSysStats_FullMethodName = "/xray.app.stats.command.StatsService/GetSysStats"
|
||||||
StatsService_GetStatsOnlineIpList_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnlineIpList"
|
StatsService_GetStatsOnlineIpList_FullMethodName = "/xray.app.stats.command.StatsService/GetStatsOnlineIpList"
|
||||||
StatsService_GetAllOnlineUsers_FullMethodName = "/xray.app.stats.command.StatsService/GetAllOnlineUsers"
|
StatsService_GetAllOnlineUsers_FullMethodName = "/xray.app.stats.command.StatsService/GetAllOnlineUsers"
|
||||||
|
StatsService_GetUsersStats_FullMethodName = "/xray.app.stats.command.StatsService/GetUsersStats"
|
||||||
)
|
)
|
||||||
|
|
||||||
// StatsServiceClient is the client API for StatsService service.
|
// StatsServiceClient is the client API for StatsService service.
|
||||||
@@ -37,6 +38,7 @@ type StatsServiceClient interface {
|
|||||||
GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error)
|
GetSysStats(ctx context.Context, in *SysStatsRequest, opts ...grpc.CallOption) (*SysStatsResponse, error)
|
||||||
GetStatsOnlineIpList(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsOnlineIpListResponse, error)
|
GetStatsOnlineIpList(ctx context.Context, in *GetStatsRequest, opts ...grpc.CallOption) (*GetStatsOnlineIpListResponse, error)
|
||||||
GetAllOnlineUsers(ctx context.Context, in *GetAllOnlineUsersRequest, opts ...grpc.CallOption) (*GetAllOnlineUsersResponse, error)
|
GetAllOnlineUsers(ctx context.Context, in *GetAllOnlineUsersRequest, opts ...grpc.CallOption) (*GetAllOnlineUsersResponse, error)
|
||||||
|
GetUsersStats(ctx context.Context, in *GetUsersStatsRequest, opts ...grpc.CallOption) (*GetUsersStatsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type statsServiceClient struct {
|
type statsServiceClient struct {
|
||||||
@@ -107,6 +109,16 @@ func (c *statsServiceClient) GetAllOnlineUsers(ctx context.Context, in *GetAllOn
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *statsServiceClient) GetUsersStats(ctx context.Context, in *GetUsersStatsRequest, opts ...grpc.CallOption) (*GetUsersStatsResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(GetUsersStatsResponse)
|
||||||
|
err := c.cc.Invoke(ctx, StatsService_GetUsersStats_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// StatsServiceServer is the server API for StatsService service.
|
// StatsServiceServer is the server API for StatsService service.
|
||||||
// All implementations must embed UnimplementedStatsServiceServer
|
// All implementations must embed UnimplementedStatsServiceServer
|
||||||
// for forward compatibility.
|
// for forward compatibility.
|
||||||
@@ -117,6 +129,7 @@ type StatsServiceServer interface {
|
|||||||
GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error)
|
GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error)
|
||||||
GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error)
|
GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error)
|
||||||
GetAllOnlineUsers(context.Context, *GetAllOnlineUsersRequest) (*GetAllOnlineUsersResponse, error)
|
GetAllOnlineUsers(context.Context, *GetAllOnlineUsersRequest) (*GetAllOnlineUsersResponse, error)
|
||||||
|
GetUsersStats(context.Context, *GetUsersStatsRequest) (*GetUsersStatsResponse, error)
|
||||||
mustEmbedUnimplementedStatsServiceServer()
|
mustEmbedUnimplementedStatsServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,22 +141,25 @@ type StatsServiceServer interface {
|
|||||||
type UnimplementedStatsServiceServer struct{}
|
type UnimplementedStatsServiceServer struct{}
|
||||||
|
|
||||||
func (UnimplementedStatsServiceServer) GetStats(context.Context, *GetStatsRequest) (*GetStatsResponse, error) {
|
func (UnimplementedStatsServiceServer) GetStats(context.Context, *GetStatsRequest) (*GetStatsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetStats not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetStats not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedStatsServiceServer) GetStatsOnline(context.Context, *GetStatsRequest) (*GetStatsResponse, error) {
|
func (UnimplementedStatsServiceServer) GetStatsOnline(context.Context, *GetStatsRequest) (*GetStatsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetStatsOnline not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetStatsOnline not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedStatsServiceServer) QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error) {
|
func (UnimplementedStatsServiceServer) QueryStats(context.Context, *QueryStatsRequest) (*QueryStatsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method QueryStats not implemented")
|
return nil, status.Error(codes.Unimplemented, "method QueryStats not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error) {
|
func (UnimplementedStatsServiceServer) GetSysStats(context.Context, *SysStatsRequest) (*SysStatsResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetSysStats not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetSysStats not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedStatsServiceServer) GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
|
func (UnimplementedStatsServiceServer) GetStatsOnlineIpList(context.Context, *GetStatsRequest) (*GetStatsOnlineIpListResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetStatsOnlineIpList not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetStatsOnlineIpList not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedStatsServiceServer) GetAllOnlineUsers(context.Context, *GetAllOnlineUsersRequest) (*GetAllOnlineUsersResponse, error) {
|
func (UnimplementedStatsServiceServer) GetAllOnlineUsers(context.Context, *GetAllOnlineUsersRequest) (*GetAllOnlineUsersResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetAllOnlineUsers not implemented")
|
return nil, status.Error(codes.Unimplemented, "method GetAllOnlineUsers not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedStatsServiceServer) GetUsersStats(context.Context, *GetUsersStatsRequest) (*GetUsersStatsResponse, error) {
|
||||||
|
return nil, status.Error(codes.Unimplemented, "method GetUsersStats not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServiceServer() {}
|
func (UnimplementedStatsServiceServer) mustEmbedUnimplementedStatsServiceServer() {}
|
||||||
func (UnimplementedStatsServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedStatsServiceServer) testEmbeddedByValue() {}
|
||||||
@@ -156,7 +172,7 @@ type UnsafeStatsServiceServer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func RegisterStatsServiceServer(s grpc.ServiceRegistrar, srv StatsServiceServer) {
|
func RegisterStatsServiceServer(s grpc.ServiceRegistrar, srv StatsServiceServer) {
|
||||||
// If the following call pancis, it indicates UnimplementedStatsServiceServer was
|
// If the following call panics, it indicates UnimplementedStatsServiceServer was
|
||||||
// embedded by pointer and is nil. This will cause panics if an
|
// embedded by pointer and is nil. This will cause panics if an
|
||||||
// unimplemented method is ever invoked, so we test this at initialization
|
// unimplemented method is ever invoked, so we test this at initialization
|
||||||
// time to prevent it from happening at runtime later due to I/O.
|
// time to prevent it from happening at runtime later due to I/O.
|
||||||
@@ -274,6 +290,24 @@ func _StatsService_GetAllOnlineUsers_Handler(srv interface{}, ctx context.Contex
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _StatsService_GetUsersStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetUsersStatsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(StatsServiceServer).GetUsersStats(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: StatsService_GetUsersStats_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(StatsServiceServer).GetUsersStats(ctx, req.(*GetUsersStatsRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// StatsService_ServiceDesc is the grpc.ServiceDesc for StatsService service.
|
// StatsService_ServiceDesc is the grpc.ServiceDesc for StatsService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@@ -305,7 +339,11 @@ var StatsService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "GetAllOnlineUsers",
|
MethodName: "GetAllOnlineUsers",
|
||||||
Handler: _StatsService_GetAllOnlineUsers_Handler,
|
Handler: _StatsService_GetAllOnlineUsers_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "GetUsersStats",
|
||||||
|
Handler: _StatsService_GetUsersStats_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "command.proto",
|
Metadata: "app/stats/command/command.proto",
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-33
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/stats/config.proto
|
// source: app/stats/config.proto
|
||||||
|
|
||||||
package stats
|
package stats
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,9 +22,9 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -57,13 +58,12 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ChannelConfig struct {
|
type ChannelConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
Blocking bool `protobuf:"varint,1,opt,name=Blocking,proto3" json:"Blocking,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
SubscriberLimit int32 `protobuf:"varint,2,opt,name=SubscriberLimit,proto3" json:"SubscriberLimit,omitempty"`
|
||||||
|
BufferSize int32 `protobuf:"varint,3,opt,name=BufferSize,proto3" json:"BufferSize,omitempty"`
|
||||||
Blocking bool `protobuf:"varint,1,opt,name=Blocking,proto3" json:"Blocking,omitempty"`
|
unknownFields protoimpl.UnknownFields
|
||||||
SubscriberLimit int32 `protobuf:"varint,2,opt,name=SubscriberLimit,proto3" json:"SubscriberLimit,omitempty"`
|
sizeCache protoimpl.SizeCache
|
||||||
BufferSize int32 `protobuf:"varint,3,opt,name=BufferSize,proto3" json:"BufferSize,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ChannelConfig) Reset() {
|
func (x *ChannelConfig) Reset() {
|
||||||
@@ -119,33 +119,26 @@ func (x *ChannelConfig) GetBufferSize() int32 {
|
|||||||
|
|
||||||
var File_app_stats_config_proto protoreflect.FileDescriptor
|
var File_app_stats_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_stats_config_proto_rawDesc = []byte{
|
const file_app_stats_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x16, 0x61, 0x70, 0x70, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x66,
|
"\n" +
|
||||||
0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
"\x16app/stats/config.proto\x12\x0exray.app.stats\"\b\n" +
|
||||||
0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
"\x06Config\"u\n" +
|
||||||
0x69, 0x67, 0x22, 0x75, 0x0a, 0x0d, 0x43, 0x68, 0x61, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e,
|
"\rChannelConfig\x12\x1a\n" +
|
||||||
0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x18,
|
"\bBlocking\x18\x01 \x01(\bR\bBlocking\x12(\n" +
|
||||||
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x12,
|
"\x0fSubscriberLimit\x18\x02 \x01(\x05R\x0fSubscriberLimit\x12\x1e\n" +
|
||||||
0x28, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x72, 0x4c, 0x69, 0x6d,
|
"\n" +
|
||||||
0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72,
|
"BufferSize\x18\x03 \x01(\x05R\n" +
|
||||||
0x69, 0x62, 0x65, 0x72, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x42, 0x75, 0x66,
|
"BufferSizeBL\n" +
|
||||||
0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x42,
|
"\x12com.xray.app.statsP\x01Z#github.com/xtls/xray-core/app/stats\xaa\x02\x0eXray.App.Statsb\x06proto3"
|
||||||
0x75, 0x66, 0x66, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x42, 0x4c, 0x0a, 0x12, 0x63, 0x6f, 0x6d,
|
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x73, 0x50,
|
|
||||||
0x01, 0x5a, 0x23, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
|
|
||||||
0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70,
|
|
||||||
0x2f, 0x73, 0x74, 0x61, 0x74, 0x73, 0xaa, 0x02, 0x0e, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
|
|
||||||
0x70, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_stats_config_proto_rawDescOnce sync.Once
|
file_app_stats_config_proto_rawDescOnce sync.Once
|
||||||
file_app_stats_config_proto_rawDescData = file_app_stats_config_proto_rawDesc
|
file_app_stats_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_stats_config_proto_rawDescGZIP() []byte {
|
func file_app_stats_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_stats_config_proto_rawDescOnce.Do(func() {
|
file_app_stats_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_stats_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_stats_config_proto_rawDescData)
|
file_app_stats_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_stats_config_proto_rawDesc), len(file_app_stats_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_stats_config_proto_rawDescData
|
return file_app_stats_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -172,7 +165,7 @@ func file_app_stats_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_stats_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_stats_config_proto_rawDesc), len(file_app_stats_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 2,
|
NumMessages: 2,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -183,7 +176,6 @@ func file_app_stats_config_proto_init() {
|
|||||||
MessageInfos: file_app_stats_config_proto_msgTypes,
|
MessageInfos: file_app_stats_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_stats_config_proto = out.File
|
File_app_stats_config_proto = out.File
|
||||||
file_app_stats_config_proto_rawDesc = nil
|
|
||||||
file_app_stats_config_proto_goTypes = nil
|
file_app_stats_config_proto_goTypes = nil
|
||||||
file_app_stats_config_proto_depIdxs = nil
|
file_app_stats_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-65
@@ -2,84 +2,86 @@ package stats
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// OnlineMap is an implementation of stats.OnlineMap.
|
const (
|
||||||
type OnlineMap struct {
|
localhostIPv4 = "127.0.0.1"
|
||||||
ipList map[string]time.Time
|
localhostIPv6 = "[::1]"
|
||||||
access sync.RWMutex
|
)
|
||||||
lastCleanup time.Time
|
|
||||||
cleanupPeriod time.Duration
|
type ipEntry struct {
|
||||||
|
refCount int
|
||||||
|
lastSeen int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOnlineMap creates a new instance of OnlineMap.
|
// OnlineMap is a refcount-based implementation of stats.OnlineMap.
|
||||||
|
// IPs are tracked by reference counting: AddIP increments, RemoveIP decrements.
|
||||||
|
// An IP is removed from the map when its reference count reaches zero.
|
||||||
|
type OnlineMap struct {
|
||||||
|
entries map[string]ipEntry
|
||||||
|
access sync.Mutex
|
||||||
|
count atomic.Int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOnlineMap creates a new OnlineMap instance.
|
||||||
func NewOnlineMap() *OnlineMap {
|
func NewOnlineMap() *OnlineMap {
|
||||||
return &OnlineMap{
|
return &OnlineMap{
|
||||||
ipList: make(map[string]time.Time),
|
entries: make(map[string]ipEntry),
|
||||||
lastCleanup: time.Now(),
|
}
|
||||||
cleanupPeriod: 10 * time.Second,
|
}
|
||||||
|
|
||||||
|
// AddIP implements stats.OnlineMap.
|
||||||
|
func (om *OnlineMap) AddIP(ip string) {
|
||||||
|
if ip == localhostIPv4 || ip == localhostIPv6 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
now := time.Now().Unix()
|
||||||
|
om.access.Lock()
|
||||||
|
defer om.access.Unlock()
|
||||||
|
if e, ok := om.entries[ip]; ok {
|
||||||
|
e.refCount++
|
||||||
|
e.lastSeen = now
|
||||||
|
om.entries[ip] = e
|
||||||
|
} else {
|
||||||
|
om.entries[ip] = ipEntry{
|
||||||
|
refCount: 1,
|
||||||
|
lastSeen: now,
|
||||||
|
}
|
||||||
|
om.count.Add(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveIP implements stats.OnlineMap.
|
||||||
|
func (om *OnlineMap) RemoveIP(ip string) {
|
||||||
|
om.access.Lock()
|
||||||
|
defer om.access.Unlock()
|
||||||
|
e, ok := om.entries[ip]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.refCount--
|
||||||
|
if e.refCount <= 0 {
|
||||||
|
delete(om.entries, ip)
|
||||||
|
om.count.Add(-1)
|
||||||
|
} else {
|
||||||
|
om.entries[ip] = e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count implements stats.OnlineMap.
|
// Count implements stats.OnlineMap.
|
||||||
func (c *OnlineMap) Count() int {
|
func (om *OnlineMap) Count() int {
|
||||||
c.access.RLock()
|
return int(om.count.Load())
|
||||||
defer c.access.RUnlock()
|
|
||||||
|
|
||||||
return len(c.ipList)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List implements stats.OnlineMap.
|
// ForEach calls fn for each online IP. If fn returns false, iteration stops.
|
||||||
func (c *OnlineMap) List() []string {
|
func (om *OnlineMap) ForEach(fn func(string, int64) bool) {
|
||||||
return c.GetKeys()
|
om.access.Lock()
|
||||||
}
|
defer om.access.Unlock()
|
||||||
|
for ip, e := range om.entries {
|
||||||
// AddIP implements stats.OnlineMap.
|
if !fn(ip, e.lastSeen) {
|
||||||
func (c *OnlineMap) AddIP(ip string) {
|
break
|
||||||
if ip == "127.0.0.1" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.access.Lock()
|
|
||||||
c.ipList[ip] = time.Now()
|
|
||||||
c.access.Unlock()
|
|
||||||
|
|
||||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
|
||||||
c.RemoveExpiredIPs()
|
|
||||||
c.lastCleanup = time.Now()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *OnlineMap) GetKeys() []string {
|
|
||||||
c.access.RLock()
|
|
||||||
defer c.access.RUnlock()
|
|
||||||
|
|
||||||
keys := []string{}
|
|
||||||
for k := range c.ipList {
|
|
||||||
keys = append(keys, k)
|
|
||||||
}
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *OnlineMap) RemoveExpiredIPs() {
|
|
||||||
c.access.Lock()
|
|
||||||
defer c.access.Unlock()
|
|
||||||
|
|
||||||
now := time.Now()
|
|
||||||
for k, t := range c.ipList {
|
|
||||||
diff := now.Sub(t)
|
|
||||||
if diff.Seconds() > 20 {
|
|
||||||
delete(c.ipList, k)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
|
|
||||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
|
||||||
c.RemoveExpiredIPs()
|
|
||||||
c.lastCleanup = time.Now()
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.ipList
|
|
||||||
}
|
|
||||||
|
|||||||
+37
-21
@@ -11,19 +11,19 @@ import (
|
|||||||
|
|
||||||
// Manager is an implementation of stats.Manager.
|
// Manager is an implementation of stats.Manager.
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
access sync.RWMutex
|
access sync.RWMutex
|
||||||
counters map[string]*Counter
|
counters map[string]*Counter
|
||||||
onlineMap map[string]*OnlineMap
|
onlineMaps map[string]*OnlineMap
|
||||||
channels map[string]*Channel
|
channels map[string]*Channel
|
||||||
running bool
|
running bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewManager creates an instance of Statistics Manager.
|
// NewManager creates an instance of Statistics Manager.
|
||||||
func NewManager(ctx context.Context, config *Config) (*Manager, error) {
|
func NewManager(ctx context.Context, config *Config) (*Manager, error) {
|
||||||
m := &Manager{
|
m := &Manager{
|
||||||
counters: make(map[string]*Counter),
|
counters: make(map[string]*Counter),
|
||||||
onlineMap: make(map[string]*OnlineMap),
|
onlineMaps: make(map[string]*OnlineMap),
|
||||||
channels: make(map[string]*Channel),
|
channels: make(map[string]*Channel),
|
||||||
}
|
}
|
||||||
|
|
||||||
return m, nil
|
return m, nil
|
||||||
@@ -88,12 +88,12 @@ func (m *Manager) RegisterOnlineMap(name string) (stats.OnlineMap, error) {
|
|||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
defer m.access.Unlock()
|
defer m.access.Unlock()
|
||||||
|
|
||||||
if _, found := m.onlineMap[name]; found {
|
if _, found := m.onlineMaps[name]; found {
|
||||||
return nil, errors.New("onlineMap ", name, " already registered.")
|
return nil, errors.New("OnlineMap ", name, " already registered.")
|
||||||
}
|
}
|
||||||
errors.LogDebug(context.Background(), "create new onlineMap ", name)
|
errors.LogDebug(context.Background(), "create new OnlineMap ", name)
|
||||||
om := NewOnlineMap()
|
om := NewOnlineMap()
|
||||||
m.onlineMap[name] = om
|
m.onlineMaps[name] = om
|
||||||
return om, nil
|
return om, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,9 +102,9 @@ func (m *Manager) UnregisterOnlineMap(name string) error {
|
|||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
defer m.access.Unlock()
|
defer m.access.Unlock()
|
||||||
|
|
||||||
if _, found := m.onlineMap[name]; found {
|
if _, found := m.onlineMaps[name]; found {
|
||||||
errors.LogDebug(context.Background(), "remove onlineMap ", name)
|
errors.LogDebug(context.Background(), "remove OnlineMap ", name)
|
||||||
delete(m.onlineMap, name)
|
delete(m.onlineMaps, name)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -114,12 +114,24 @@ func (m *Manager) GetOnlineMap(name string) stats.OnlineMap {
|
|||||||
m.access.RLock()
|
m.access.RLock()
|
||||||
defer m.access.RUnlock()
|
defer m.access.RUnlock()
|
||||||
|
|
||||||
if om, found := m.onlineMap[name]; found {
|
if om, found := m.onlineMaps[name]; found {
|
||||||
return om
|
return om
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VisitOnlineMaps calls visitor function on all managed online maps.
|
||||||
|
// The visitor runs under a read lock; it must not call RegisterOnlineMap or UnregisterOnlineMap (would deadlock).
|
||||||
|
func (m *Manager) VisitOnlineMaps(visitor func(string, stats.OnlineMap) bool) {
|
||||||
|
m.access.RLock()
|
||||||
|
defer m.access.RUnlock()
|
||||||
|
for name, om := range m.onlineMaps {
|
||||||
|
if !visitor(name, om) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterChannel implements stats.Manager.
|
// RegisterChannel implements stats.Manager.
|
||||||
func (m *Manager) RegisterChannel(name string) (stats.Channel, error) {
|
func (m *Manager) RegisterChannel(name string) (stats.Channel, error) {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
@@ -163,12 +175,12 @@ func (m *Manager) GetChannel(name string) stats.Channel {
|
|||||||
|
|
||||||
// GetAllOnlineUsers implements stats.Manager.
|
// GetAllOnlineUsers implements stats.Manager.
|
||||||
func (m *Manager) GetAllOnlineUsers() []string {
|
func (m *Manager) GetAllOnlineUsers() []string {
|
||||||
m.access.Lock()
|
m.access.RLock()
|
||||||
defer m.access.Unlock()
|
defer m.access.RUnlock()
|
||||||
|
|
||||||
usersOnline := make([]string, 0, len(m.onlineMap))
|
usersOnline := make([]string, 0, len(m.onlineMaps))
|
||||||
for user, onlineMap := range m.onlineMap {
|
for user, om := range m.onlineMaps {
|
||||||
if len(onlineMap.IpTimeMap()) > 0 {
|
if om.Count() > 0 {
|
||||||
usersOnline = append(usersOnline, user)
|
usersOnline = append(usersOnline, user)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,6 +210,10 @@ func (m *Manager) Close() error {
|
|||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
defer m.access.Unlock()
|
defer m.access.Unlock()
|
||||||
m.running = false
|
m.running = false
|
||||||
|
for name := range m.onlineMaps {
|
||||||
|
errors.LogDebug(context.Background(), "remove OnlineMap ", name)
|
||||||
|
delete(m.onlineMaps, name)
|
||||||
|
}
|
||||||
errs := []error{}
|
errs := []error{}
|
||||||
for name, channel := range m.channels {
|
for name, channel := range m.channels {
|
||||||
errors.LogDebug(context.Background(), "remove channel ", name)
|
errors.LogDebug(context.Background(), "remove channel ", name)
|
||||||
|
|||||||
+21
-30
@@ -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.35.1
|
// protoc-gen-go v1.36.11
|
||||||
// protoc v5.28.2
|
// protoc v6.33.5
|
||||||
// source: app/version/config.proto
|
// source: app/version/config.proto
|
||||||
|
|
||||||
package version
|
package version
|
||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,13 +22,12 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
sizeCache protoimpl.SizeCache
|
CoreVersion string `protobuf:"bytes,1,opt,name=core_version,json=coreVersion,proto3" json:"core_version,omitempty"`
|
||||||
|
MinVersion string `protobuf:"bytes,2,opt,name=min_version,json=minVersion,proto3" json:"min_version,omitempty"`
|
||||||
|
MaxVersion string `protobuf:"bytes,3,opt,name=max_version,json=maxVersion,proto3" json:"max_version,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
CoreVersion string `protobuf:"bytes,1,opt,name=core_version,json=coreVersion,proto3" json:"core_version,omitempty"`
|
|
||||||
MinVersion string `protobuf:"bytes,2,opt,name=min_version,json=minVersion,proto3" json:"min_version,omitempty"`
|
|
||||||
MaxVersion string `protobuf:"bytes,3,opt,name=max_version,json=maxVersion,proto3" json:"max_version,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -83,33 +83,25 @@ func (x *Config) GetMaxVersion() string {
|
|||||||
|
|
||||||
var File_app_version_config_proto protoreflect.FileDescriptor
|
var File_app_version_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_version_config_proto_rawDesc = []byte{
|
const file_app_version_config_proto_rawDesc = "" +
|
||||||
0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f,
|
"\n" +
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79,
|
"\x18app/version/config.proto\x12\x10xray.app.version\"m\n" +
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x06,
|
"\x06Config\x12!\n" +
|
||||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x76,
|
"\fcore_version\x18\x01 \x01(\tR\vcoreVersion\x12\x1f\n" +
|
||||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f,
|
"\vmin_version\x18\x02 \x01(\tR\n" +
|
||||||
0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x69, 0x6e,
|
"minVersion\x12\x1f\n" +
|
||||||
0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
|
"\vmax_version\x18\x03 \x01(\tR\n" +
|
||||||
0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61,
|
"maxVersionBR\n" +
|
||||||
0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
"\x14com.xray.app.versionP\x01Z%github.com/xtls/xray-core/app/version\xaa\x02\x10Xray.App.Versionb\x06proto3"
|
||||||
0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x52, 0x0a, 0x14, 0x63,
|
|
||||||
0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x76, 0x65, 0x72, 0x73,
|
|
||||||
0x69, 0x6f, 0x6e, 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, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xaa, 0x02, 0x10, 0x58,
|
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62,
|
|
||||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
file_app_version_config_proto_rawDescOnce sync.Once
|
file_app_version_config_proto_rawDescOnce sync.Once
|
||||||
file_app_version_config_proto_rawDescData = file_app_version_config_proto_rawDesc
|
file_app_version_config_proto_rawDescData []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
func file_app_version_config_proto_rawDescGZIP() []byte {
|
func file_app_version_config_proto_rawDescGZIP() []byte {
|
||||||
file_app_version_config_proto_rawDescOnce.Do(func() {
|
file_app_version_config_proto_rawDescOnce.Do(func() {
|
||||||
file_app_version_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_version_config_proto_rawDescData)
|
file_app_version_config_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_app_version_config_proto_rawDesc), len(file_app_version_config_proto_rawDesc)))
|
||||||
})
|
})
|
||||||
return file_app_version_config_proto_rawDescData
|
return file_app_version_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
@@ -135,7 +127,7 @@ func file_app_version_config_proto_init() {
|
|||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_version_config_proto_rawDesc,
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_app_version_config_proto_rawDesc), len(file_app_version_config_proto_rawDesc)),
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 1,
|
NumMessages: 1,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
@@ -146,7 +138,6 @@ func file_app_version_config_proto_init() {
|
|||||||
MessageInfos: file_app_version_config_proto_msgTypes,
|
MessageInfos: file_app_version_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_version_config_proto = out.File
|
File_app_version_config_proto = out.File
|
||||||
file_app_version_config_proto_rawDesc = nil
|
|
||||||
file_app_version_config_proto_goTypes = nil
|
file_app_version_config_proto_goTypes = nil
|
||||||
file_app_version_config_proto_depIdxs = nil
|
file_app_version_config_proto_depIdxs = nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
package antireplay
|
|
||||||
|
|
||||||
type GeneralizedReplayFilter interface {
|
|
||||||
Interval() int64
|
|
||||||
Check(sum []byte) bool
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package antireplay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"crypto/rand"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkMapFilter(b *testing.B) {
|
||||||
|
filter := NewMapFilter[[16]byte](120)
|
||||||
|
var sample [16]byte
|
||||||
|
reader := bufio.NewReader(rand.Reader)
|
||||||
|
reader.Read(sample[:])
|
||||||
|
b.ResetTimer()
|
||||||
|
for range b.N {
|
||||||
|
reader.Read(sample[:])
|
||||||
|
filter.Check(sample)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMapFilter(t *testing.T) {
|
||||||
|
filter := NewMapFilter[[16]byte](120)
|
||||||
|
var sample [16]byte
|
||||||
|
rand.Read(sample[:])
|
||||||
|
filter.Check(sample)
|
||||||
|
if filter.Check(sample) {
|
||||||
|
t.Error("Unexpected true negative")
|
||||||
|
}
|
||||||
|
sample[0]++
|
||||||
|
if !filter.Check(sample) {
|
||||||
|
t.Error("Unexpected false positive")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
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{}}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package antireplay
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ReplayFilter checks for replay attacks.
|
||||||
|
type ReplayFilter[T comparable] struct {
|
||||||
|
lock sync.Mutex
|
||||||
|
poolA map[T]struct{}
|
||||||
|
poolB map[T]struct{}
|
||||||
|
interval time.Duration
|
||||||
|
lastClean time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMapFilter create a new filter with specifying the expiration time interval in seconds.
|
||||||
|
func NewMapFilter[T comparable](interval int64) *ReplayFilter[T] {
|
||||||
|
filter := &ReplayFilter[T]{
|
||||||
|
poolA: make(map[T]struct{}),
|
||||||
|
poolB: make(map[T]struct{}),
|
||||||
|
interval: time.Duration(interval) * time.Second,
|
||||||
|
lastClean: time.Now(),
|
||||||
|
}
|
||||||
|
return filter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check determines if there are duplicate records.
|
||||||
|
func (filter *ReplayFilter[T]) Check(sum T) bool {
|
||||||
|
filter.lock.Lock()
|
||||||
|
defer filter.lock.Unlock()
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
if now.Sub(filter.lastClean) >= filter.interval {
|
||||||
|
filter.poolB = filter.poolA
|
||||||
|
filter.poolA = make(map[T]struct{})
|
||||||
|
filter.lastClean = now
|
||||||
|
}
|
||||||
|
|
||||||
|
_, existsA := filter.poolA[sum]
|
||||||
|
_, existsB := filter.poolB[sum]
|
||||||
|
if !existsA && !existsB {
|
||||||
|
filter.poolA[sum] = struct{}{}
|
||||||
|
}
|
||||||
|
return !(existsA || existsB)
|
||||||
|
}
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
package antireplay
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
cuckoo "github.com/seiflotfy/cuckoofilter"
|
|
||||||
)
|
|
||||||
|
|
||||||
const replayFilterCapacity = 100000
|
|
||||||
|
|
||||||
// ReplayFilter checks for replay attacks.
|
|
||||||
type ReplayFilter struct {
|
|
||||||
lock sync.Mutex
|
|
||||||
poolA *cuckoo.Filter
|
|
||||||
poolB *cuckoo.Filter
|
|
||||||
poolSwap bool
|
|
||||||
lastSwap int64
|
|
||||||
interval int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewReplayFilter create a new filter with specifying the expiration time interval in seconds.
|
|
||||||
func NewReplayFilter(interval int64) *ReplayFilter {
|
|
||||||
filter := &ReplayFilter{}
|
|
||||||
filter.interval = interval
|
|
||||||
return filter
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interval in second for expiration time for duplicate records.
|
|
||||||
func (filter *ReplayFilter) Interval() int64 {
|
|
||||||
return filter.interval
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check determines if there are duplicate records.
|
|
||||||
func (filter *ReplayFilter) Check(sum []byte) bool {
|
|
||||||
filter.lock.Lock()
|
|
||||||
defer filter.lock.Unlock()
|
|
||||||
|
|
||||||
now := time.Now().Unix()
|
|
||||||
if filter.lastSwap == 0 {
|
|
||||||
filter.lastSwap = now
|
|
||||||
filter.poolA = cuckoo.NewFilter(replayFilterCapacity)
|
|
||||||
filter.poolB = cuckoo.NewFilter(replayFilterCapacity)
|
|
||||||
}
|
|
||||||
|
|
||||||
elapsed := now - filter.lastSwap
|
|
||||||
if elapsed >= filter.Interval() {
|
|
||||||
if filter.poolSwap {
|
|
||||||
filter.poolA.Reset()
|
|
||||||
} else {
|
|
||||||
filter.poolB.Reset()
|
|
||||||
}
|
|
||||||
filter.poolSwap = !filter.poolSwap
|
|
||||||
filter.lastSwap = now
|
|
||||||
}
|
|
||||||
|
|
||||||
return filter.poolA.InsertUnique(sum) && filter.poolB.InsertUnique(sum)
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build !windows && !wasm && !illumos
|
//go:build !windows && !wasm && !illumos && !openbsd
|
||||||
// +build !windows,!wasm,!illumos
|
// +build !windows,!wasm,!illumos,!openbsd
|
||||||
|
|
||||||
package buf
|
package buf
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build !wasm
|
//go:build !wasm && !openbsd
|
||||||
// +build !wasm
|
// +build !wasm,!openbsd
|
||||||
|
|
||||||
package buf
|
package buf
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//go:build wasm || openbsd
|
||||||
|
// +build wasm openbsd
|
||||||
|
|
||||||
|
package buf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/features/stats"
|
||||||
|
)
|
||||||
|
|
||||||
|
const useReadv = false
|
||||||
|
|
||||||
|
func NewReadVReader(reader io.Reader, rawConn syscall.RawConn, counter stats.Counter) Reader {
|
||||||
|
panic("not implemented")
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
//go:build wasm
|
|
||||||
// +build wasm
|
|
||||||
|
|
||||||
package buf
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
const useReadv = false
|
|
||||||
|
|
||||||
func NewReadVReader(reader io.Reader, rawConn syscall.RawConn) Reader {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build !wasm
|
//go:build !wasm && !openbsd
|
||||||
// +build !wasm
|
// +build !wasm,!openbsd
|
||||||
|
|
||||||
package buf_test
|
package buf_test
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,11 @@ package crypto // import "github.com/xtls/xray-core/common/crypto"
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// [,)
|
||||||
func RandBetween(from int64, to int64) int64 {
|
func RandBetween(from int64, to int64) int64 {
|
||||||
if from == to {
|
if from == to {
|
||||||
return from
|
return from
|
||||||
@@ -16,3 +19,20 @@ func RandBetween(from int64, to int64) int64 {
|
|||||||
bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from))
|
bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from))
|
||||||
return from + bigInt.Int64()
|
return from + bigInt.Int64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [,]
|
||||||
|
func RandBytesBetween(b []byte, from, to byte) {
|
||||||
|
common.Must2(rand.Read(b))
|
||||||
|
|
||||||
|
if from > to {
|
||||||
|
from, to = to, from
|
||||||
|
}
|
||||||
|
|
||||||
|
if to-from == 255 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range b {
|
||||||
|
b[i] = from + b[i]%(to-from+1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,238 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/geodata/strmatcher"
|
||||||
|
"github.com/xtls/xray-core/common/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DomainMatcher interface {
|
||||||
|
// Match returns the indices of all rules that match the input domain.
|
||||||
|
// The returned slice is owned by the caller and may be safely modified.
|
||||||
|
// Note: the slice may contain duplicates and the order is unspecified.
|
||||||
|
Match(input string) []uint32
|
||||||
|
|
||||||
|
MatchAny(input string) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainMatcherFactory interface {
|
||||||
|
BuildMatcher(rules []*DomainRule) (DomainMatcher, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type MphDomainMatcherFactory struct {
|
||||||
|
sync.Mutex
|
||||||
|
shared *utils.WeakCacheMap[string, strmatcher.MphValueMatcher]
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildDomainRulesKey(rules []*DomainRule) string {
|
||||||
|
var sb strings.Builder
|
||||||
|
cache := false
|
||||||
|
for _, r := range rules {
|
||||||
|
switch v := r.Value.(type) {
|
||||||
|
case *DomainRule_Custom:
|
||||||
|
sb.WriteString(v.Custom.Type.String())
|
||||||
|
sb.WriteString(":")
|
||||||
|
sb.WriteString(v.Custom.Value)
|
||||||
|
sb.WriteString(",")
|
||||||
|
case *DomainRule_Geosite:
|
||||||
|
cache = true
|
||||||
|
sb.WriteString(v.Geosite.File)
|
||||||
|
sb.WriteString(":")
|
||||||
|
sb.WriteString(v.Geosite.Code)
|
||||||
|
sb.WriteString("@")
|
||||||
|
sb.WriteString(v.Geosite.Attrs)
|
||||||
|
sb.WriteString(",")
|
||||||
|
default:
|
||||||
|
panic("unknown domain rule type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !cache {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildMatcher implements DomainMatcherFactory.
|
||||||
|
func (f *MphDomainMatcherFactory) BuildMatcher(rules []*DomainRule) (DomainMatcher, error) {
|
||||||
|
if len(rules) == 0 {
|
||||||
|
return nil, errors.New("empty domain rule list")
|
||||||
|
}
|
||||||
|
key := buildDomainRulesKey(rules)
|
||||||
|
if key != "" {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
if g, ok := f.shared.Load(key); ok {
|
||||||
|
errors.LogDebug(context.Background(), "geodata mph domain matcher cache HIT for ", len(rules), " rules")
|
||||||
|
return g, nil
|
||||||
|
}
|
||||||
|
errors.LogDebug(context.Background(), "geodata mph domain matcher cache MISS for ", len(rules), " rules")
|
||||||
|
}
|
||||||
|
g := strmatcher.NewMphValueMatcher()
|
||||||
|
for i, r := range rules {
|
||||||
|
switch v := r.Value.(type) {
|
||||||
|
case *DomainRule_Custom:
|
||||||
|
m, err := parseDomain(v.Custom)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
g.Add(m, uint32(i))
|
||||||
|
case *DomainRule_Geosite:
|
||||||
|
domains, err := loadSiteWithAttrs(v.Geosite.File, v.Geosite.Code, v.Geosite.Attrs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for j, d := range domains {
|
||||||
|
domains[j] = nil // peak mem
|
||||||
|
m, err := parseDomain(d)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogError(context.Background(), "ignore invalid geosite entry in ", v.Geosite.File, ":", v.Geosite.Code, " at index ", j, ", ", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
g.Add(m, uint32(i))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("unknown domain rule type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := g.Build(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if key != "" {
|
||||||
|
f.shared.Store(key, g)
|
||||||
|
}
|
||||||
|
return g, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CompactDomainMatcherFactory struct {
|
||||||
|
sync.Mutex
|
||||||
|
shared *utils.WeakCacheMap[string, strmatcher.LinearAnyMatcher]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *CompactDomainMatcherFactory) getOrCreateFrom(rule *GeoSiteRule) (strmatcher.MatcherSet, error) {
|
||||||
|
key := rule.File + ":" + rule.Code + "@" + rule.Attrs
|
||||||
|
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
if s, ok := f.shared.Load(key); ok {
|
||||||
|
errors.LogDebug(context.Background(), "geodata geosite matcher cache HIT ", key)
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
errors.LogDebug(context.Background(), "geodata geosite matcher cache MISS ", key)
|
||||||
|
|
||||||
|
s := strmatcher.NewLinearAnyMatcher()
|
||||||
|
domains, err := loadSiteWithAttrs(rule.File, rule.Code, rule.Attrs)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for i, d := range domains {
|
||||||
|
domains[i] = nil // peak mem
|
||||||
|
m, err := parseDomain(d)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogError(context.Background(), "ignore invalid geosite entry in ", rule.File, ":", rule.Code, " at index ", i, ", ", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
s.Add(m)
|
||||||
|
}
|
||||||
|
f.shared.Store(key, s)
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// BuildMatcher implements DomainMatcherFactory.
|
||||||
|
func (f *CompactDomainMatcherFactory) BuildMatcher(rules []*DomainRule) (DomainMatcher, error) {
|
||||||
|
if len(rules) == 0 {
|
||||||
|
return nil, errors.New("empty domain rule list")
|
||||||
|
}
|
||||||
|
compact := &CompactDomainMatcher{
|
||||||
|
matchers: make([]strmatcher.MatcherSet, 0, len(rules)),
|
||||||
|
values: make([]uint32, 0, len(rules)),
|
||||||
|
}
|
||||||
|
for i, r := range rules {
|
||||||
|
switch v := r.Value.(type) {
|
||||||
|
case *DomainRule_Custom:
|
||||||
|
m, err := parseDomain(v.Custom)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if compact.custom == nil {
|
||||||
|
compact.custom = strmatcher.NewLinearValueMatcher()
|
||||||
|
}
|
||||||
|
compact.custom.Add(m, uint32(i))
|
||||||
|
case *DomainRule_Geosite:
|
||||||
|
m, err := f.getOrCreateFrom(v.Geosite)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
compact.matchers = append(compact.matchers, m)
|
||||||
|
compact.values = append(compact.values, uint32(i))
|
||||||
|
default:
|
||||||
|
panic("unknown domain rule type")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return compact, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CompactDomainMatcher struct {
|
||||||
|
custom strmatcher.ValueMatcher
|
||||||
|
matchers []strmatcher.MatcherSet
|
||||||
|
values []uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match implements DomainMatcher.
|
||||||
|
func (c *CompactDomainMatcher) Match(input string) []uint32 {
|
||||||
|
var result []uint32
|
||||||
|
if c.custom != nil {
|
||||||
|
result = append(result, c.custom.Match(input)...)
|
||||||
|
}
|
||||||
|
for i, m := range c.matchers {
|
||||||
|
if m.MatchAny(input) {
|
||||||
|
result = append(result, c.values[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchAny implements DomainMatcher.
|
||||||
|
func (c *CompactDomainMatcher) MatchAny(input string) bool {
|
||||||
|
if c.custom != nil && c.custom.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for _, m := range c.matchers {
|
||||||
|
if m.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDomain(d *Domain) (strmatcher.Matcher, error) {
|
||||||
|
if d == nil {
|
||||||
|
return nil, errors.New("domain must not be nil")
|
||||||
|
}
|
||||||
|
switch d.Type {
|
||||||
|
case Domain_Substr:
|
||||||
|
return strmatcher.Substr.New(strings.ToLower(d.Value))
|
||||||
|
case Domain_Regex:
|
||||||
|
return strmatcher.Regex.New(d.Value)
|
||||||
|
case Domain_Domain:
|
||||||
|
return strmatcher.Domain.New(d.Value)
|
||||||
|
case Domain_Full:
|
||||||
|
return strmatcher.Full.New(strings.ToLower(d.Value))
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unknown domain type: ", d.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDomainMatcherFactory() DomainMatcherFactory {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "ios", "android":
|
||||||
|
return &CompactDomainMatcherFactory{shared: utils.NewWeakCacheMap[string, strmatcher.LinearAnyMatcher]()}
|
||||||
|
default:
|
||||||
|
return &MphDomainMatcherFactory{shared: utils.NewWeakCacheMap[string, strmatcher.MphValueMatcher]()}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/geodata/strmatcher"
|
||||||
|
"github.com/xtls/xray-core/common/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCompactDomainMatcher_PreservesCustomRuleIndices(t *testing.T) {
|
||||||
|
factory := &CompactDomainMatcherFactory{shared: utils.NewWeakCacheMap[string, strmatcher.LinearAnyMatcher]()}
|
||||||
|
matcher, err := factory.BuildMatcher([]*DomainRule{
|
||||||
|
{Value: &DomainRule_Custom{Custom: &Domain{Type: Domain_Full, Value: "example.com"}}},
|
||||||
|
{Value: &DomainRule_Custom{Custom: &Domain{Type: Domain_Domain, Value: "example.com"}}},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("BuildMatcher() failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := matcher.Match("example.com")
|
||||||
|
slices.Sort(got)
|
||||||
|
|
||||||
|
want := []uint32{0, 1}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("Match() = %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCompactDomainMatcher_PreservesMixedRuleIndices(t *testing.T) {
|
||||||
|
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
|
||||||
|
factory := &CompactDomainMatcherFactory{shared: utils.NewWeakCacheMap[string, strmatcher.LinearAnyMatcher]()}
|
||||||
|
matcher, err := factory.BuildMatcher([]*DomainRule{
|
||||||
|
{Value: &DomainRule_Geosite{Geosite: &GeoSiteRule{File: DefaultGeoSiteDat, Code: "CN"}}},
|
||||||
|
{Value: &DomainRule_Custom{Custom: &Domain{Type: Domain_Full, Value: "163.com"}}},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("BuildMatcher() failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := matcher.Match("163.com")
|
||||||
|
slices.Sort(got)
|
||||||
|
|
||||||
|
want := []uint32{0, 1}
|
||||||
|
if !reflect.DeepEqual(got, want) {
|
||||||
|
t.Fatalf("Match() = %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMphDomainMatcher_MatchReturnsDetachedSlice(t *testing.T) {
|
||||||
|
matcher, err := (&MphDomainMatcherFactory{shared: utils.NewWeakCacheMap[string, strmatcher.MphValueMatcher]()}).
|
||||||
|
BuildMatcher([]*DomainRule{
|
||||||
|
{Value: &DomainRule_Custom{Custom: &Domain{Type: Domain_Full, Value: "example.com"}}},
|
||||||
|
{Value: &DomainRule_Custom{Custom: &Domain{Type: Domain_Domain, Value: "example.com"}}},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("BuildMatcher() failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := matcher.Match("example.com")
|
||||||
|
if !reflect.DeepEqual(got, []uint32{0, 1}) {
|
||||||
|
t.Fatalf("Match() = %v, want %v", got, []uint32{0, 1})
|
||||||
|
}
|
||||||
|
|
||||||
|
got[0] = 1
|
||||||
|
|
||||||
|
gotAgain := matcher.Match("example.com")
|
||||||
|
if !reflect.DeepEqual(gotAgain, []uint32{0, 1}) {
|
||||||
|
t.Fatalf("Match() after caller mutation = %v, want %v", gotAgain, []uint32{0, 1})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DomainRegistry struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
factory DomainMatcherFactory
|
||||||
|
matchers []*DynamicDomainMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DomainRegistry) BuildDomainMatcher(rules []*DomainRule) (DomainMatcher, error) {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
m, err := r.factory.BuildMatcher(rules)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
d := NewDynamicDomainMatcher(rules, m)
|
||||||
|
r.matchers = append(r.matchers, d)
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *DomainRegistry) Reload() error {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
errors.LogInfo(context.Background(), "reloading GeoSite data for ", len(r.matchers), " domain matcher(s)")
|
||||||
|
|
||||||
|
factory := newDomainMatcherFactory()
|
||||||
|
type reloadEntry struct {
|
||||||
|
dynamic *DynamicDomainMatcher
|
||||||
|
matcher DomainMatcher
|
||||||
|
}
|
||||||
|
reloaded := make([]reloadEntry, len(r.matchers))
|
||||||
|
for i, d := range r.matchers {
|
||||||
|
m, err := factory.BuildMatcher(d.rules)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogErrorInner(context.Background(), err, "failed to reload GeoSite data for domain matcher ", i)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
reloaded[i] = reloadEntry{dynamic: d, matcher: m}
|
||||||
|
}
|
||||||
|
for _, entry := range reloaded {
|
||||||
|
entry.dynamic.Reload(entry.matcher)
|
||||||
|
}
|
||||||
|
r.factory = factory
|
||||||
|
errors.LogInfo(context.Background(), "reloaded GeoSite data for ", len(r.matchers), " domain matcher(s)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDomainRegistry() *DomainRegistry {
|
||||||
|
return &DomainRegistry{
|
||||||
|
factory: newDomainMatcherFactory(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var DomainReg = newDomainRegistry()
|
||||||
|
|
||||||
|
type domainMatcherState struct {
|
||||||
|
matcher DomainMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
type DynamicDomainMatcher struct {
|
||||||
|
rules []*DomainRule
|
||||||
|
state atomic.Pointer[domainMatcherState]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match implements DomainMatcher.
|
||||||
|
func (d *DynamicDomainMatcher) Match(input string) []uint32 {
|
||||||
|
return d.state.Load().matcher.Match(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchAny implements DomainMatcher.
|
||||||
|
func (d *DynamicDomainMatcher) MatchAny(input string) bool {
|
||||||
|
return d.state.Load().matcher.MatchAny(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DynamicDomainMatcher) Reload(newMatcher DomainMatcher) {
|
||||||
|
d.state.Store(&domainMatcherState{matcher: newMatcher})
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDynamicDomainMatcher(rules []*DomainRule, matcher DomainMatcher) *DynamicDomainMatcher {
|
||||||
|
d := &DynamicDomainMatcher{rules: rules}
|
||||||
|
d.Reload(matcher)
|
||||||
|
return d
|
||||||
|
}
|
||||||
@@ -0,0 +1,965 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// protoc-gen-go v1.36.11
|
||||||
|
// protoc v6.33.5
|
||||||
|
// source: common/geodata/geodat.proto
|
||||||
|
|
||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
unsafe "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 of domain value.
|
||||||
|
type Domain_Type int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
// The value is used as a sub string.
|
||||||
|
Domain_Substr Domain_Type = 0
|
||||||
|
// The value is used as a regular expression.
|
||||||
|
Domain_Regex Domain_Type = 1
|
||||||
|
// The value is a domain.
|
||||||
|
Domain_Domain Domain_Type = 2
|
||||||
|
// The value is a full domain.
|
||||||
|
Domain_Full Domain_Type = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for Domain_Type.
|
||||||
|
var (
|
||||||
|
Domain_Type_name = map[int32]string{
|
||||||
|
0: "Substr",
|
||||||
|
1: "Regex",
|
||||||
|
2: "Domain",
|
||||||
|
3: "Full",
|
||||||
|
}
|
||||||
|
Domain_Type_value = map[string]int32{
|
||||||
|
"Substr": 0,
|
||||||
|
"Regex": 1,
|
||||||
|
"Domain": 2,
|
||||||
|
"Full": 3,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x Domain_Type) Enum() *Domain_Type {
|
||||||
|
p := new(Domain_Type)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Domain_Type) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Domain_Type) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_common_geodata_geodat_proto_enumTypes[0].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Domain_Type) Type() protoreflect.EnumType {
|
||||||
|
return &file_common_geodata_geodat_proto_enumTypes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Domain_Type) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Domain_Type.Descriptor instead.
|
||||||
|
func (Domain_Type) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Domain struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// Domain matching type.
|
||||||
|
Type Domain_Type `protobuf:"varint,1,opt,name=type,proto3,enum=xray.common.geodata.Domain_Type" json:"type,omitempty"`
|
||||||
|
// Domain value.
|
||||||
|
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
|
||||||
|
// Attributes of this domain. May be used for filtering.
|
||||||
|
Attribute []*Domain_Attribute `protobuf:"bytes,3,rep,name=attribute,proto3" json:"attribute,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain) Reset() {
|
||||||
|
*x = Domain{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[0]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Domain) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Domain) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[0]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Domain.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Domain) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain) GetType() Domain_Type {
|
||||||
|
if x != nil {
|
||||||
|
return x.Type
|
||||||
|
}
|
||||||
|
return Domain_Substr
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain) GetValue() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Value
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain) GetAttribute() []*Domain_Attribute {
|
||||||
|
if x != nil {
|
||||||
|
return x.Attribute
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GeoSite struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||||
|
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSite) Reset() {
|
||||||
|
*x = GeoSite{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[1]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSite) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GeoSite) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GeoSite) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[1]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GeoSite.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GeoSite) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSite) GetCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Code
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSite) GetDomain() []*Domain {
|
||||||
|
if x != nil {
|
||||||
|
return x.Domain
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GeoSiteList struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Entry []*GeoSite `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSiteList) Reset() {
|
||||||
|
*x = GeoSiteList{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[2]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSiteList) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GeoSiteList) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GeoSiteList) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[2]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GeoSiteList.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GeoSiteList) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSiteList) GetEntry() []*GeoSite {
|
||||||
|
if x != nil {
|
||||||
|
return x.Entry
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GeoSiteRule struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
File string `protobuf:"bytes,1,opt,name=file,proto3" json:"file,omitempty"`
|
||||||
|
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
|
||||||
|
Attrs string `protobuf:"bytes,3,opt,name=attrs,proto3" json:"attrs,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSiteRule) Reset() {
|
||||||
|
*x = GeoSiteRule{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[3]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSiteRule) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GeoSiteRule) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GeoSiteRule) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[3]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GeoSiteRule.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GeoSiteRule) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSiteRule) GetFile() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.File
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSiteRule) GetCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Code
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoSiteRule) GetAttrs() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Attrs
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainRule struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// Types that are valid to be assigned to Value:
|
||||||
|
//
|
||||||
|
// *DomainRule_Geosite
|
||||||
|
// *DomainRule_Custom
|
||||||
|
Value isDomainRule_Value `protobuf_oneof:"value"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DomainRule) Reset() {
|
||||||
|
*x = DomainRule{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DomainRule) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DomainRule) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *DomainRule) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[4]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use DomainRule.ProtoReflect.Descriptor instead.
|
||||||
|
func (*DomainRule) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DomainRule) GetValue() isDomainRule_Value {
|
||||||
|
if x != nil {
|
||||||
|
return x.Value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DomainRule) GetGeosite() *GeoSiteRule {
|
||||||
|
if x != nil {
|
||||||
|
if x, ok := x.Value.(*DomainRule_Geosite); ok {
|
||||||
|
return x.Geosite
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *DomainRule) GetCustom() *Domain {
|
||||||
|
if x != nil {
|
||||||
|
if x, ok := x.Value.(*DomainRule_Custom); ok {
|
||||||
|
return x.Custom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type isDomainRule_Value interface {
|
||||||
|
isDomainRule_Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainRule_Geosite struct {
|
||||||
|
Geosite *GeoSiteRule `protobuf:"bytes,1,opt,name=geosite,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DomainRule_Custom struct {
|
||||||
|
Custom *Domain `protobuf:"bytes,2,opt,name=custom,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*DomainRule_Geosite) isDomainRule_Value() {}
|
||||||
|
|
||||||
|
func (*DomainRule_Custom) isDomainRule_Value() {}
|
||||||
|
|
||||||
|
type CIDR struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// IP address, should be either 4 or 16 bytes.
|
||||||
|
Ip []byte `protobuf:"bytes,1,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||||
|
// Number of leading ones in the network mask.
|
||||||
|
Prefix uint32 `protobuf:"varint,2,opt,name=prefix,proto3" json:"prefix,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CIDR) Reset() {
|
||||||
|
*x = CIDR{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[5]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CIDR) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CIDR) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *CIDR) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[5]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use CIDR.ProtoReflect.Descriptor instead.
|
||||||
|
func (*CIDR) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CIDR) GetIp() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Ip
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CIDR) GetPrefix() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.Prefix
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type CIDRRule struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Cidr *CIDR `protobuf:"bytes,1,opt,name=cidr,proto3" json:"cidr,omitempty"`
|
||||||
|
ReverseMatch bool `protobuf:"varint,2,opt,name=reverse_match,json=reverseMatch,proto3" json:"reverse_match,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CIDRRule) Reset() {
|
||||||
|
*x = CIDRRule{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[6]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CIDRRule) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CIDRRule) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *CIDRRule) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[6]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use CIDRRule.ProtoReflect.Descriptor instead.
|
||||||
|
func (*CIDRRule) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{6}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CIDRRule) GetCidr() *CIDR {
|
||||||
|
if x != nil {
|
||||||
|
return x.Cidr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CIDRRule) GetReverseMatch() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.ReverseMatch
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type GeoIP struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,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"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIP) Reset() {
|
||||||
|
*x = GeoIP{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[7]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIP) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GeoIP) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GeoIP) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[7]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GeoIP.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GeoIP) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{7}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIP) GetCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Code
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIP) GetCidr() []*CIDR {
|
||||||
|
if x != nil {
|
||||||
|
return x.Cidr
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIP) GetReverseMatch() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.ReverseMatch
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type GeoIPList struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Entry []*GeoIP `protobuf:"bytes,1,rep,name=entry,proto3" json:"entry,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIPList) Reset() {
|
||||||
|
*x = GeoIPList{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[8]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIPList) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GeoIPList) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GeoIPList) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[8]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GeoIPList.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GeoIPList) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{8}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIPList) GetEntry() []*GeoIP {
|
||||||
|
if x != nil {
|
||||||
|
return x.Entry
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type GeoIPRule struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
File string `protobuf:"bytes,1,opt,name=file,proto3" json:"file,omitempty"`
|
||||||
|
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
|
||||||
|
ReverseMatch bool `protobuf:"varint,3,opt,name=reverse_match,json=reverseMatch,proto3" json:"reverse_match,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIPRule) Reset() {
|
||||||
|
*x = GeoIPRule{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[9]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIPRule) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*GeoIPRule) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *GeoIPRule) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[9]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use GeoIPRule.ProtoReflect.Descriptor instead.
|
||||||
|
func (*GeoIPRule) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{9}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIPRule) GetFile() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.File
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIPRule) GetCode() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Code
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *GeoIPRule) GetReverseMatch() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.ReverseMatch
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPRule struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
// Types that are valid to be assigned to Value:
|
||||||
|
//
|
||||||
|
// *IPRule_Geoip
|
||||||
|
// *IPRule_Custom
|
||||||
|
Value isIPRule_Value `protobuf_oneof:"value"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *IPRule) Reset() {
|
||||||
|
*x = IPRule{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[10]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *IPRule) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*IPRule) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *IPRule) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[10]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use IPRule.ProtoReflect.Descriptor instead.
|
||||||
|
func (*IPRule) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{10}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *IPRule) GetValue() isIPRule_Value {
|
||||||
|
if x != nil {
|
||||||
|
return x.Value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *IPRule) GetGeoip() *GeoIPRule {
|
||||||
|
if x != nil {
|
||||||
|
if x, ok := x.Value.(*IPRule_Geoip); ok {
|
||||||
|
return x.Geoip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *IPRule) GetCustom() *CIDRRule {
|
||||||
|
if x != nil {
|
||||||
|
if x, ok := x.Value.(*IPRule_Custom); ok {
|
||||||
|
return x.Custom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type isIPRule_Value interface {
|
||||||
|
isIPRule_Value()
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPRule_Geoip struct {
|
||||||
|
Geoip *GeoIPRule `protobuf:"bytes,1,opt,name=geoip,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type IPRule_Custom struct {
|
||||||
|
Custom *CIDRRule `protobuf:"bytes,2,opt,name=custom,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*IPRule_Geoip) isIPRule_Value() {}
|
||||||
|
|
||||||
|
func (*IPRule_Custom) isIPRule_Value() {}
|
||||||
|
|
||||||
|
type Domain_Attribute struct {
|
||||||
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
|
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
|
||||||
|
// Types that are valid to be assigned to TypedValue:
|
||||||
|
//
|
||||||
|
// *Domain_Attribute_BoolValue
|
||||||
|
// *Domain_Attribute_IntValue
|
||||||
|
TypedValue isDomain_Attribute_TypedValue `protobuf_oneof:"typed_value"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain_Attribute) Reset() {
|
||||||
|
*x = Domain_Attribute{}
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[11]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain_Attribute) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Domain_Attribute) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *Domain_Attribute) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_common_geodata_geodat_proto_msgTypes[11]
|
||||||
|
if x != nil {
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
if ms.LoadMessageInfo() == nil {
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
return mi.MessageOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Domain_Attribute.ProtoReflect.Descriptor instead.
|
||||||
|
func (*Domain_Attribute) Descriptor() ([]byte, []int) {
|
||||||
|
return file_common_geodata_geodat_proto_rawDescGZIP(), []int{0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain_Attribute) GetKey() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.Key
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain_Attribute) GetTypedValue() isDomain_Attribute_TypedValue {
|
||||||
|
if x != nil {
|
||||||
|
return x.TypedValue
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain_Attribute) GetBoolValue() bool {
|
||||||
|
if x != nil {
|
||||||
|
if x, ok := x.TypedValue.(*Domain_Attribute_BoolValue); ok {
|
||||||
|
return x.BoolValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Domain_Attribute) GetIntValue() int64 {
|
||||||
|
if x != nil {
|
||||||
|
if x, ok := x.TypedValue.(*Domain_Attribute_IntValue); ok {
|
||||||
|
return x.IntValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type isDomain_Attribute_TypedValue interface {
|
||||||
|
isDomain_Attribute_TypedValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Domain_Attribute_BoolValue struct {
|
||||||
|
BoolValue bool `protobuf:"varint,2,opt,name=bool_value,json=boolValue,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Domain_Attribute_IntValue struct {
|
||||||
|
IntValue int64 `protobuf:"varint,3,opt,name=int_value,json=intValue,proto3,oneof"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*Domain_Attribute_BoolValue) isDomain_Attribute_TypedValue() {}
|
||||||
|
|
||||||
|
func (*Domain_Attribute_IntValue) isDomain_Attribute_TypedValue() {}
|
||||||
|
|
||||||
|
var File_common_geodata_geodat_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
|
const file_common_geodata_geodat_proto_rawDesc = "" +
|
||||||
|
"\n" +
|
||||||
|
"\x1bcommon/geodata/geodat.proto\x12\x13xray.common.geodata\"\xbc\x02\n" +
|
||||||
|
"\x06Domain\x124\n" +
|
||||||
|
"\x04type\x18\x01 \x01(\x0e2 .xray.common.geodata.Domain.TypeR\x04type\x12\x14\n" +
|
||||||
|
"\x05value\x18\x02 \x01(\tR\x05value\x12C\n" +
|
||||||
|
"\tattribute\x18\x03 \x03(\v2%.xray.common.geodata.Domain.AttributeR\tattribute\x1al\n" +
|
||||||
|
"\tAttribute\x12\x10\n" +
|
||||||
|
"\x03key\x18\x01 \x01(\tR\x03key\x12\x1f\n" +
|
||||||
|
"\n" +
|
||||||
|
"bool_value\x18\x02 \x01(\bH\x00R\tboolValue\x12\x1d\n" +
|
||||||
|
"\tint_value\x18\x03 \x01(\x03H\x00R\bintValueB\r\n" +
|
||||||
|
"\vtyped_value\"3\n" +
|
||||||
|
"\x04Type\x12\n" +
|
||||||
|
"\n" +
|
||||||
|
"\x06Substr\x10\x00\x12\t\n" +
|
||||||
|
"\x05Regex\x10\x01\x12\n" +
|
||||||
|
"\n" +
|
||||||
|
"\x06Domain\x10\x02\x12\b\n" +
|
||||||
|
"\x04Full\x10\x03\"R\n" +
|
||||||
|
"\aGeoSite\x12\x12\n" +
|
||||||
|
"\x04code\x18\x01 \x01(\tR\x04code\x123\n" +
|
||||||
|
"\x06domain\x18\x02 \x03(\v2\x1b.xray.common.geodata.DomainR\x06domain\"A\n" +
|
||||||
|
"\vGeoSiteList\x122\n" +
|
||||||
|
"\x05entry\x18\x01 \x03(\v2\x1c.xray.common.geodata.GeoSiteR\x05entry\"K\n" +
|
||||||
|
"\vGeoSiteRule\x12\x12\n" +
|
||||||
|
"\x04file\x18\x01 \x01(\tR\x04file\x12\x12\n" +
|
||||||
|
"\x04code\x18\x02 \x01(\tR\x04code\x12\x14\n" +
|
||||||
|
"\x05attrs\x18\x03 \x01(\tR\x05attrs\"\x8a\x01\n" +
|
||||||
|
"\n" +
|
||||||
|
"DomainRule\x12<\n" +
|
||||||
|
"\ageosite\x18\x01 \x01(\v2 .xray.common.geodata.GeoSiteRuleH\x00R\ageosite\x125\n" +
|
||||||
|
"\x06custom\x18\x02 \x01(\v2\x1b.xray.common.geodata.DomainH\x00R\x06customB\a\n" +
|
||||||
|
"\x05value\".\n" +
|
||||||
|
"\x04CIDR\x12\x0e\n" +
|
||||||
|
"\x02ip\x18\x01 \x01(\fR\x02ip\x12\x16\n" +
|
||||||
|
"\x06prefix\x18\x02 \x01(\rR\x06prefix\"^\n" +
|
||||||
|
"\bCIDRRule\x12-\n" +
|
||||||
|
"\x04cidr\x18\x01 \x01(\v2\x19.xray.common.geodata.CIDRR\x04cidr\x12#\n" +
|
||||||
|
"\rreverse_match\x18\x02 \x01(\bR\freverseMatch\"o\n" +
|
||||||
|
"\x05GeoIP\x12\x12\n" +
|
||||||
|
"\x04code\x18\x01 \x01(\tR\x04code\x12-\n" +
|
||||||
|
"\x04cidr\x18\x02 \x03(\v2\x19.xray.common.geodata.CIDRR\x04cidr\x12#\n" +
|
||||||
|
"\rreverse_match\x18\x03 \x01(\bR\freverseMatch\"=\n" +
|
||||||
|
"\tGeoIPList\x120\n" +
|
||||||
|
"\x05entry\x18\x01 \x03(\v2\x1a.xray.common.geodata.GeoIPR\x05entry\"X\n" +
|
||||||
|
"\tGeoIPRule\x12\x12\n" +
|
||||||
|
"\x04file\x18\x01 \x01(\tR\x04file\x12\x12\n" +
|
||||||
|
"\x04code\x18\x02 \x01(\tR\x04code\x12#\n" +
|
||||||
|
"\rreverse_match\x18\x03 \x01(\bR\freverseMatch\"\x82\x01\n" +
|
||||||
|
"\x06IPRule\x126\n" +
|
||||||
|
"\x05geoip\x18\x01 \x01(\v2\x1e.xray.common.geodata.GeoIPRuleH\x00R\x05geoip\x127\n" +
|
||||||
|
"\x06custom\x18\x02 \x01(\v2\x1d.xray.common.geodata.CIDRRuleH\x00R\x06customB\a\n" +
|
||||||
|
"\x05valueB[\n" +
|
||||||
|
"\x17com.xray.common.geodataP\x01Z(github.com/xtls/xray-core/common/geodata\xaa\x02\x13Xray.Common.Geodatab\x06proto3"
|
||||||
|
|
||||||
|
var (
|
||||||
|
file_common_geodata_geodat_proto_rawDescOnce sync.Once
|
||||||
|
file_common_geodata_geodat_proto_rawDescData []byte
|
||||||
|
)
|
||||||
|
|
||||||
|
func file_common_geodata_geodat_proto_rawDescGZIP() []byte {
|
||||||
|
file_common_geodata_geodat_proto_rawDescOnce.Do(func() {
|
||||||
|
file_common_geodata_geodat_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_common_geodata_geodat_proto_rawDesc), len(file_common_geodata_geodat_proto_rawDesc)))
|
||||||
|
})
|
||||||
|
return file_common_geodata_geodat_proto_rawDescData
|
||||||
|
}
|
||||||
|
|
||||||
|
var file_common_geodata_geodat_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
|
var file_common_geodata_geodat_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
|
||||||
|
var file_common_geodata_geodat_proto_goTypes = []any{
|
||||||
|
(Domain_Type)(0), // 0: xray.common.geodata.Domain.Type
|
||||||
|
(*Domain)(nil), // 1: xray.common.geodata.Domain
|
||||||
|
(*GeoSite)(nil), // 2: xray.common.geodata.GeoSite
|
||||||
|
(*GeoSiteList)(nil), // 3: xray.common.geodata.GeoSiteList
|
||||||
|
(*GeoSiteRule)(nil), // 4: xray.common.geodata.GeoSiteRule
|
||||||
|
(*DomainRule)(nil), // 5: xray.common.geodata.DomainRule
|
||||||
|
(*CIDR)(nil), // 6: xray.common.geodata.CIDR
|
||||||
|
(*CIDRRule)(nil), // 7: xray.common.geodata.CIDRRule
|
||||||
|
(*GeoIP)(nil), // 8: xray.common.geodata.GeoIP
|
||||||
|
(*GeoIPList)(nil), // 9: xray.common.geodata.GeoIPList
|
||||||
|
(*GeoIPRule)(nil), // 10: xray.common.geodata.GeoIPRule
|
||||||
|
(*IPRule)(nil), // 11: xray.common.geodata.IPRule
|
||||||
|
(*Domain_Attribute)(nil), // 12: xray.common.geodata.Domain.Attribute
|
||||||
|
}
|
||||||
|
var file_common_geodata_geodat_proto_depIdxs = []int32{
|
||||||
|
0, // 0: xray.common.geodata.Domain.type:type_name -> xray.common.geodata.Domain.Type
|
||||||
|
12, // 1: xray.common.geodata.Domain.attribute:type_name -> xray.common.geodata.Domain.Attribute
|
||||||
|
1, // 2: xray.common.geodata.GeoSite.domain:type_name -> xray.common.geodata.Domain
|
||||||
|
2, // 3: xray.common.geodata.GeoSiteList.entry:type_name -> xray.common.geodata.GeoSite
|
||||||
|
4, // 4: xray.common.geodata.DomainRule.geosite:type_name -> xray.common.geodata.GeoSiteRule
|
||||||
|
1, // 5: xray.common.geodata.DomainRule.custom:type_name -> xray.common.geodata.Domain
|
||||||
|
6, // 6: xray.common.geodata.CIDRRule.cidr:type_name -> xray.common.geodata.CIDR
|
||||||
|
6, // 7: xray.common.geodata.GeoIP.cidr:type_name -> xray.common.geodata.CIDR
|
||||||
|
8, // 8: xray.common.geodata.GeoIPList.entry:type_name -> xray.common.geodata.GeoIP
|
||||||
|
10, // 9: xray.common.geodata.IPRule.geoip:type_name -> xray.common.geodata.GeoIPRule
|
||||||
|
7, // 10: xray.common.geodata.IPRule.custom:type_name -> xray.common.geodata.CIDRRule
|
||||||
|
11, // [11:11] is the sub-list for method output_type
|
||||||
|
11, // [11:11] is the sub-list for method input_type
|
||||||
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
|
11, // [11:11] is the sub-list for extension extendee
|
||||||
|
0, // [0:11] is the sub-list for field type_name
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { file_common_geodata_geodat_proto_init() }
|
||||||
|
func file_common_geodata_geodat_proto_init() {
|
||||||
|
if File_common_geodata_geodat_proto != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file_common_geodata_geodat_proto_msgTypes[4].OneofWrappers = []any{
|
||||||
|
(*DomainRule_Geosite)(nil),
|
||||||
|
(*DomainRule_Custom)(nil),
|
||||||
|
}
|
||||||
|
file_common_geodata_geodat_proto_msgTypes[10].OneofWrappers = []any{
|
||||||
|
(*IPRule_Geoip)(nil),
|
||||||
|
(*IPRule_Custom)(nil),
|
||||||
|
}
|
||||||
|
file_common_geodata_geodat_proto_msgTypes[11].OneofWrappers = []any{
|
||||||
|
(*Domain_Attribute_BoolValue)(nil),
|
||||||
|
(*Domain_Attribute_IntValue)(nil),
|
||||||
|
}
|
||||||
|
type x struct{}
|
||||||
|
out := protoimpl.TypeBuilder{
|
||||||
|
File: protoimpl.DescBuilder{
|
||||||
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
|
RawDescriptor: unsafe.Slice(unsafe.StringData(file_common_geodata_geodat_proto_rawDesc), len(file_common_geodata_geodat_proto_rawDesc)),
|
||||||
|
NumEnums: 1,
|
||||||
|
NumMessages: 12,
|
||||||
|
NumExtensions: 0,
|
||||||
|
NumServices: 0,
|
||||||
|
},
|
||||||
|
GoTypes: file_common_geodata_geodat_proto_goTypes,
|
||||||
|
DependencyIndexes: file_common_geodata_geodat_proto_depIdxs,
|
||||||
|
EnumInfos: file_common_geodata_geodat_proto_enumTypes,
|
||||||
|
MessageInfos: file_common_geodata_geodat_proto_msgTypes,
|
||||||
|
}.Build()
|
||||||
|
File_common_geodata_geodat_proto = out.File
|
||||||
|
file_common_geodata_geodat_proto_goTypes = nil
|
||||||
|
file_common_geodata_geodat_proto_depIdxs = nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package xray.common.geodata;
|
||||||
|
option csharp_namespace = "Xray.Common.Geodata";
|
||||||
|
option go_package = "github.com/xtls/xray-core/common/geodata";
|
||||||
|
option java_package = "com.xray.common.geodata";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
|
||||||
|
message Domain {
|
||||||
|
// Type of domain value.
|
||||||
|
enum Type {
|
||||||
|
// The value is used as a sub string.
|
||||||
|
Substr = 0;
|
||||||
|
// The value is used as a regular expression.
|
||||||
|
Regex = 1;
|
||||||
|
// The value is a domain.
|
||||||
|
Domain = 2;
|
||||||
|
// The value is a full domain.
|
||||||
|
Full = 3;
|
||||||
|
}
|
||||||
|
// Domain matching type.
|
||||||
|
Type type = 1;
|
||||||
|
|
||||||
|
// Domain value.
|
||||||
|
string value = 2;
|
||||||
|
|
||||||
|
message Attribute {
|
||||||
|
string key = 1;
|
||||||
|
|
||||||
|
oneof typed_value {
|
||||||
|
bool bool_value = 2;
|
||||||
|
int64 int_value = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Attributes of this domain. May be used for filtering.
|
||||||
|
repeated Attribute attribute = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoSite {
|
||||||
|
string code = 1;
|
||||||
|
repeated Domain domain = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoSiteList {
|
||||||
|
repeated GeoSite entry = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoSiteRule {
|
||||||
|
string file = 1;
|
||||||
|
string code = 2;
|
||||||
|
string attrs = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DomainRule {
|
||||||
|
oneof value {
|
||||||
|
GeoSiteRule geosite = 1;
|
||||||
|
Domain custom = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message CIDR {
|
||||||
|
// IP address, should be either 4 or 16 bytes.
|
||||||
|
bytes ip = 1;
|
||||||
|
|
||||||
|
// Number of leading ones in the network mask.
|
||||||
|
uint32 prefix = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CIDRRule {
|
||||||
|
CIDR cidr = 1;
|
||||||
|
bool reverse_match = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoIP {
|
||||||
|
string code = 1;
|
||||||
|
repeated CIDR cidr = 2;
|
||||||
|
bool reverse_match = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoIPList {
|
||||||
|
repeated GeoIP entry = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GeoIPRule {
|
||||||
|
string file = 1;
|
||||||
|
string code = 2;
|
||||||
|
bool reverse_match = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message IPRule {
|
||||||
|
oneof value {
|
||||||
|
GeoIPRule geoip = 1;
|
||||||
|
CIDRRule custom = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/platform/filesystem"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkFile(file, code string) error {
|
||||||
|
r, err := filesystem.OpenAsset(file)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("failed to open ", file).Base(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
if _, err := find(r, []byte(code), false); err != nil {
|
||||||
|
return errors.New("failed to check code ", code, " from ", file).Base(err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadFile(file, code string) ([]byte, error) {
|
||||||
|
runtime.GC() // peak mem
|
||||||
|
r, err := filesystem.OpenAsset(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to open ", file).Base(err)
|
||||||
|
}
|
||||||
|
defer r.Close()
|
||||||
|
bs, err := find(r, []byte(code), true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to load code ", code, " from ", file).Base(err)
|
||||||
|
}
|
||||||
|
return bs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadIP(file, code string) ([]*CIDR, error) {
|
||||||
|
bs, err := loadFile(file, code)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer runtime.GC() // peak mem
|
||||||
|
var geoip GeoIP
|
||||||
|
if err := proto.Unmarshal(bs, &geoip); err != nil {
|
||||||
|
return nil, errors.New("error unmarshal IP in ", file, ":", code).Base(err)
|
||||||
|
}
|
||||||
|
return geoip.Cidr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSite(file, code string) ([]*Domain, error) {
|
||||||
|
bs, err := loadFile(file, code)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer runtime.GC() // peak mem
|
||||||
|
var geosite GeoSite
|
||||||
|
if err := proto.Unmarshal(bs, &geosite); err != nil {
|
||||||
|
return nil, errors.New("error unmarshal Site in ", file, ":", code).Base(err)
|
||||||
|
}
|
||||||
|
return geosite.Domain, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodeVarint(br *bufio.Reader) (uint64, error) {
|
||||||
|
var x uint64
|
||||||
|
for shift := uint(0); shift < 64; shift += 7 {
|
||||||
|
b, err := br.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
x |= (uint64(b) & 0x7F) << shift
|
||||||
|
if (b & 0x80) == 0 {
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The number is too large to represent in a 64-bit value.
|
||||||
|
return 0, errors.New("varint overflow")
|
||||||
|
}
|
||||||
|
|
||||||
|
func find(r io.Reader, code []byte, readBody bool) ([]byte, error) {
|
||||||
|
codeL := len(code)
|
||||||
|
if codeL == 0 {
|
||||||
|
return nil, errors.New("empty code")
|
||||||
|
}
|
||||||
|
|
||||||
|
br := bufio.NewReaderSize(r, 64*1024)
|
||||||
|
need := 2 + codeL // TODO: if code too long
|
||||||
|
prefixBuf := make([]byte, need)
|
||||||
|
|
||||||
|
for {
|
||||||
|
if _, err := br.ReadByte(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
x, err := decodeVarint(br)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
bodyL := int(x)
|
||||||
|
if bodyL <= 0 {
|
||||||
|
return nil, errors.New("invalid body length: ", bodyL)
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixL := bodyL
|
||||||
|
if prefixL > need {
|
||||||
|
prefixL = need
|
||||||
|
}
|
||||||
|
prefix := prefixBuf[:prefixL]
|
||||||
|
if _, err := io.ReadFull(br, prefix); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
match := false
|
||||||
|
if bodyL >= need {
|
||||||
|
if int(prefix[1]) == codeL && bytes.Equal(prefix[2:need], code) {
|
||||||
|
if !readBody {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
match = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
remain := bodyL - prefixL
|
||||||
|
if match {
|
||||||
|
out := make([]byte, bodyL)
|
||||||
|
copy(out, prefix)
|
||||||
|
if remain > 0 {
|
||||||
|
if _, err := io.ReadFull(br, out[prefixL:]); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if remain > 0 {
|
||||||
|
if _, err := br.Discard(remain); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type AttributeMatcher interface {
|
||||||
|
Match(*Domain) bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type HasAttrMatcher string
|
||||||
|
|
||||||
|
// Match reports whether this matcher matches any attribute on the domain.
|
||||||
|
func (m HasAttrMatcher) Match(domain *Domain) bool {
|
||||||
|
for _, attr := range domain.Attribute {
|
||||||
|
if attr.Key == string(m) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
type AllAttrsMatcher struct {
|
||||||
|
matchers []AttributeMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match reports whether the domain matches every matcher in the list.
|
||||||
|
func (m *AllAttrsMatcher) Match(domain *Domain) bool {
|
||||||
|
for _, matcher := range m.matchers {
|
||||||
|
if !matcher.Match(domain) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAllAttrsMatcher(attrs string) AttributeMatcher {
|
||||||
|
if attrs == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
m := new(AllAttrsMatcher)
|
||||||
|
for _, attr := range strings.Split(attrs, "@") {
|
||||||
|
m.matchers = append(m.matchers, HasAttrMatcher(attr))
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSiteWithAttrs(file, code, attrs string) ([]*Domain, error) {
|
||||||
|
domains, err := loadSite(file, code)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
matcher := NewAllAttrsMatcher(attrs)
|
||||||
|
if matcher == nil {
|
||||||
|
return domains, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered := make([]*Domain, 0, len(domains))
|
||||||
|
for _, d := range domains {
|
||||||
|
if matcher.Match(d) {
|
||||||
|
filtered = append(filtered, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filtered, nil
|
||||||
|
}
|
||||||
@@ -1,19 +1,22 @@
|
|||||||
package router
|
package geodata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"runtime"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/utils"
|
||||||
|
|
||||||
"go4.org/netipx"
|
"go4.org/netipx"
|
||||||
)
|
)
|
||||||
|
|
||||||
type GeoIPMatcher interface {
|
type IPMatcher interface {
|
||||||
// TODO: (PERF) all net.IP -> netipx.Addr
|
// TODO: (PERF) all net.IP -> netipx.Addr
|
||||||
|
|
||||||
// Invalid IP always return false.
|
// Invalid IP always return false.
|
||||||
@@ -33,13 +36,13 @@ type GeoIPMatcher interface {
|
|||||||
SetReverse(reverse bool)
|
SetReverse(reverse bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
type GeoIPSet struct {
|
type IPSet struct {
|
||||||
ipv4, ipv6 *netipx.IPSet
|
ipv4, ipv6 *netipx.IPSet
|
||||||
max4, max6 uint8
|
max4, max6 uint8
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeuristicGeoIPMatcher struct {
|
type HeuristicIPMatcher struct {
|
||||||
ipset *GeoIPSet
|
ipset *IPSet
|
||||||
reverse bool
|
reverse bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,8 +51,8 @@ type ipBucket struct {
|
|||||||
ips []net.IP
|
ips []net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match implements GeoIPMatcher.
|
// Match implements IPMatcher.
|
||||||
func (m *HeuristicGeoIPMatcher) Match(ip net.IP) bool {
|
func (m *HeuristicIPMatcher) Match(ip net.IP) bool {
|
||||||
ipx, ok := netipx.FromStdIP(ip)
|
ipx, ok := netipx.FromStdIP(ip)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
@@ -57,18 +60,24 @@ func (m *HeuristicGeoIPMatcher) Match(ip net.IP) bool {
|
|||||||
return m.matchAddr(ipx)
|
return m.matchAddr(ipx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HeuristicGeoIPMatcher) matchAddr(ipx netip.Addr) bool {
|
func (m *HeuristicIPMatcher) matchAddr(ipx netip.Addr) bool {
|
||||||
if ipx.Is4() {
|
if ipx.Is4() {
|
||||||
|
if m.ipset.max4 == 0xff {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return m.ipset.ipv4.Contains(ipx) != m.reverse
|
return m.ipset.ipv4.Contains(ipx) != m.reverse
|
||||||
}
|
}
|
||||||
if ipx.Is6() {
|
if ipx.Is6() {
|
||||||
|
if m.ipset.max6 == 0xff {
|
||||||
|
return false
|
||||||
|
}
|
||||||
return m.ipset.ipv6.Contains(ipx) != m.reverse
|
return m.ipset.ipv6.Contains(ipx) != m.reverse
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnyMatch implements GeoIPMatcher.
|
// AnyMatch implements IPMatcher.
|
||||||
func (m *HeuristicGeoIPMatcher) AnyMatch(ips []net.IP) bool {
|
func (m *HeuristicIPMatcher) AnyMatch(ips []net.IP) bool {
|
||||||
n := len(ips)
|
n := len(ips)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return false
|
return false
|
||||||
@@ -117,8 +126,8 @@ func (m *HeuristicGeoIPMatcher) AnyMatch(ips []net.IP) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches implements GeoIPMatcher.
|
// Matches implements IPMatcher.
|
||||||
func (m *HeuristicGeoIPMatcher) Matches(ips []net.IP) bool {
|
func (m *HeuristicIPMatcher) Matches(ips []net.IP) bool {
|
||||||
n := len(ips)
|
n := len(ips)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return false
|
return false
|
||||||
@@ -205,8 +214,8 @@ func prefixKeyFromIP(ip net.IP) (key [9]byte, ok bool) {
|
|||||||
return key, false // illegal
|
return key, false // illegal
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterIPs implements GeoIPMatcher.
|
// FilterIPs implements IPMatcher.
|
||||||
func (m *HeuristicGeoIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, unmatched []net.IP) {
|
func (m *HeuristicIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, unmatched []net.IP) {
|
||||||
n := len(ips)
|
n := len(ips)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return []net.IP{}, []net.IP{}
|
return []net.IP{}, []net.IP{}
|
||||||
@@ -295,22 +304,22 @@ func (m *HeuristicGeoIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, unmat
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToggleReverse implements GeoIPMatcher.
|
// ToggleReverse implements IPMatcher.
|
||||||
func (m *HeuristicGeoIPMatcher) ToggleReverse() {
|
func (m *HeuristicIPMatcher) ToggleReverse() {
|
||||||
m.reverse = !m.reverse
|
m.reverse = !m.reverse
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetReverse implements GeoIPMatcher.
|
// SetReverse implements IPMatcher.
|
||||||
func (m *HeuristicGeoIPMatcher) SetReverse(reverse bool) {
|
func (m *HeuristicIPMatcher) SetReverse(reverse bool) {
|
||||||
m.reverse = reverse
|
m.reverse = reverse
|
||||||
}
|
}
|
||||||
|
|
||||||
type GeneralMultiGeoIPMatcher struct {
|
type GeneralMultiIPMatcher struct {
|
||||||
matchers []GeoIPMatcher
|
matchers []IPMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match implements GeoIPMatcher.
|
// Match implements IPMatcher.
|
||||||
func (mm *GeneralMultiGeoIPMatcher) Match(ip net.IP) bool {
|
func (mm *GeneralMultiIPMatcher) Match(ip net.IP) bool {
|
||||||
for _, m := range mm.matchers {
|
for _, m := range mm.matchers {
|
||||||
if m.Match(ip) {
|
if m.Match(ip) {
|
||||||
return true
|
return true
|
||||||
@@ -319,8 +328,8 @@ func (mm *GeneralMultiGeoIPMatcher) Match(ip net.IP) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnyMatch implements GeoIPMatcher.
|
// AnyMatch implements IPMatcher.
|
||||||
func (mm *GeneralMultiGeoIPMatcher) AnyMatch(ips []net.IP) bool {
|
func (mm *GeneralMultiIPMatcher) AnyMatch(ips []net.IP) bool {
|
||||||
for _, m := range mm.matchers {
|
for _, m := range mm.matchers {
|
||||||
if m.AnyMatch(ips) {
|
if m.AnyMatch(ips) {
|
||||||
return true
|
return true
|
||||||
@@ -329,8 +338,8 @@ func (mm *GeneralMultiGeoIPMatcher) AnyMatch(ips []net.IP) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches implements GeoIPMatcher.
|
// Matches implements IPMatcher.
|
||||||
func (mm *GeneralMultiGeoIPMatcher) Matches(ips []net.IP) bool {
|
func (mm *GeneralMultiIPMatcher) Matches(ips []net.IP) bool {
|
||||||
for _, m := range mm.matchers {
|
for _, m := range mm.matchers {
|
||||||
if m.Matches(ips) {
|
if m.Matches(ips) {
|
||||||
return true
|
return true
|
||||||
@@ -339,8 +348,8 @@ func (mm *GeneralMultiGeoIPMatcher) Matches(ips []net.IP) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterIPs implements GeoIPMatcher.
|
// FilterIPs implements IPMatcher.
|
||||||
func (mm *GeneralMultiGeoIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, unmatched []net.IP) {
|
func (mm *GeneralMultiIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, unmatched []net.IP) {
|
||||||
matched = make([]net.IP, 0, len(ips))
|
matched = make([]net.IP, 0, len(ips))
|
||||||
unmatched = ips
|
unmatched = ips
|
||||||
for _, m := range mm.matchers {
|
for _, m := range mm.matchers {
|
||||||
@@ -356,26 +365,26 @@ func (mm *GeneralMultiGeoIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, u
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToggleReverse implements GeoIPMatcher.
|
// ToggleReverse implements IPMatcher.
|
||||||
func (mm *GeneralMultiGeoIPMatcher) ToggleReverse() {
|
func (mm *GeneralMultiIPMatcher) ToggleReverse() {
|
||||||
for _, m := range mm.matchers {
|
for _, m := range mm.matchers {
|
||||||
m.ToggleReverse()
|
m.ToggleReverse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetReverse implements GeoIPMatcher.
|
// SetReverse implements IPMatcher.
|
||||||
func (mm *GeneralMultiGeoIPMatcher) SetReverse(reverse bool) {
|
func (mm *GeneralMultiIPMatcher) SetReverse(reverse bool) {
|
||||||
for _, m := range mm.matchers {
|
for _, m := range mm.matchers {
|
||||||
m.SetReverse(reverse)
|
m.SetReverse(reverse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type HeuristicMultiGeoIPMatcher struct {
|
type HeuristicMultiIPMatcher struct {
|
||||||
matchers []*HeuristicGeoIPMatcher
|
matchers []*HeuristicIPMatcher
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match implements GeoIPMatcher.
|
// Match implements IPMatcher.
|
||||||
func (mm *HeuristicMultiGeoIPMatcher) Match(ip net.IP) bool {
|
func (mm *HeuristicMultiIPMatcher) Match(ip net.IP) bool {
|
||||||
ipx, ok := netipx.FromStdIP(ip)
|
ipx, ok := netipx.FromStdIP(ip)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
@@ -389,8 +398,8 @@ func (mm *HeuristicMultiGeoIPMatcher) Match(ip net.IP) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// AnyMatch implements GeoIPMatcher.
|
// AnyMatch implements IPMatcher.
|
||||||
func (mm *HeuristicMultiGeoIPMatcher) AnyMatch(ips []net.IP) bool {
|
func (mm *HeuristicMultiIPMatcher) AnyMatch(ips []net.IP) bool {
|
||||||
n := len(ips)
|
n := len(ips)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return false
|
return false
|
||||||
@@ -439,8 +448,8 @@ func (mm *HeuristicMultiGeoIPMatcher) AnyMatch(ips []net.IP) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Matches implements GeoIPMatcher.
|
// Matches implements IPMatcher.
|
||||||
func (mm *HeuristicMultiGeoIPMatcher) Matches(ips []net.IP) bool {
|
func (mm *HeuristicMultiIPMatcher) Matches(ips []net.IP) bool {
|
||||||
n := len(ips)
|
n := len(ips)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return false
|
return false
|
||||||
@@ -503,7 +512,7 @@ type ipViews struct {
|
|||||||
precise4, precise6 []netip.Addr
|
precise4, precise6 []netip.Addr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ipViews) ensureForMatcher(m *HeuristicGeoIPMatcher, ips []net.IP) bool {
|
func (v *ipViews) ensureForMatcher(m *HeuristicIPMatcher, ips []net.IP) bool {
|
||||||
needHeur4 := m.ipset.max4 <= 24 && v.buckets4 == nil
|
needHeur4 := m.ipset.max4 <= 24 && v.buckets4 == nil
|
||||||
needHeur6 := m.ipset.max6 <= 64 && v.buckets6 == nil
|
needHeur6 := m.ipset.max6 <= 64 && v.buckets6 == nil
|
||||||
needPrec4 := m.ipset.max4 > 24 && v.precise4 == nil
|
needPrec4 := m.ipset.max4 > 24 && v.precise4 == nil
|
||||||
@@ -581,8 +590,8 @@ func (v *ipViews) ensureForMatcher(m *HeuristicGeoIPMatcher, ips []net.IP) bool
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// FilterIPs implements GeoIPMatcher.
|
// FilterIPs implements IPMatcher.
|
||||||
func (mm *HeuristicMultiGeoIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, unmatched []net.IP) {
|
func (mm *HeuristicMultiIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, unmatched []net.IP) {
|
||||||
n := len(ips)
|
n := len(ips)
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
return []net.IP{}, []net.IP{}
|
return []net.IP{}, []net.IP{}
|
||||||
@@ -694,7 +703,7 @@ type ipBucketViews struct {
|
|||||||
precise4, precise6 map[netip.Addr]net.IP
|
precise4, precise6 map[netip.Addr]net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *ipBucketViews) ensureForMatcher(m *HeuristicGeoIPMatcher, ips []net.IP) {
|
func (v *ipBucketViews) ensureForMatcher(m *HeuristicIPMatcher, ips []net.IP) {
|
||||||
needHeur4 := m.ipset.max4 <= 24 && v.buckets4 == nil
|
needHeur4 := m.ipset.max4 <= 24 && v.buckets4 == nil
|
||||||
needHeur6 := m.ipset.max6 <= 64 && v.buckets6 == nil
|
needHeur6 := m.ipset.max6 <= 64 && v.buckets6 == nil
|
||||||
needPrec4 := m.ipset.max4 > 24 && v.precise4 == nil
|
needPrec4 := m.ipset.max4 > 24 && v.precise4 == nil
|
||||||
@@ -782,69 +791,123 @@ func (v *ipBucketViews) ensureForMatcher(m *HeuristicGeoIPMatcher, ips []net.IP)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToggleReverse implements GeoIPMatcher.
|
// ToggleReverse implements IPMatcher.
|
||||||
func (mm *HeuristicMultiGeoIPMatcher) ToggleReverse() {
|
func (mm *HeuristicMultiIPMatcher) ToggleReverse() {
|
||||||
for _, m := range mm.matchers {
|
for _, m := range mm.matchers {
|
||||||
m.ToggleReverse()
|
m.ToggleReverse()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetReverse implements GeoIPMatcher.
|
// SetReverse implements IPMatcher.
|
||||||
func (mm *HeuristicMultiGeoIPMatcher) SetReverse(reverse bool) {
|
func (mm *HeuristicMultiIPMatcher) SetReverse(reverse bool) {
|
||||||
for _, m := range mm.matchers {
|
for _, m := range mm.matchers {
|
||||||
m.SetReverse(reverse)
|
m.SetReverse(reverse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type GeoIPSetFactory struct {
|
type IPSetFactory struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
shared map[string]*GeoIPSet // TODO: cleanup
|
shared *utils.WeakCacheMap[string, IPSet]
|
||||||
}
|
}
|
||||||
|
|
||||||
var ipsetFactory = GeoIPSetFactory{shared: make(map[string]*GeoIPSet)}
|
func (f *IPSetFactory) GetOrCreateFromGeoIPRules(rules []*GeoIPRule) (*IPSet, error) {
|
||||||
|
key := buildGeoIPRulesKey(rules)
|
||||||
|
|
||||||
func (f *GeoIPSetFactory) GetOrCreate(key string, cidrGroups [][]*CIDR) (*GeoIPSet, error) {
|
|
||||||
f.Lock()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
|
||||||
if ipset := f.shared[key]; ipset != nil {
|
if ipset, ok := f.shared.Load(key); ok {
|
||||||
|
errors.LogDebug(context.Background(), "geodata geoip matcher cache HIT ", key)
|
||||||
return ipset, nil
|
return ipset, nil
|
||||||
}
|
}
|
||||||
|
errors.LogDebug(context.Background(), "geodata geoip matcher cache MISS ", key)
|
||||||
|
|
||||||
ipset, err := f.Create(cidrGroups...)
|
ipset, err := f.createFrom(func(add func(*CIDR)) error {
|
||||||
|
for _, r := range rules {
|
||||||
|
cidrs, err := loadIP(r.File, r.Code)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for i, c := range cidrs {
|
||||||
|
add(c)
|
||||||
|
cidrs[i] = nil // peak mem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
f.shared[key] = ipset
|
f.shared.Store(key, ipset)
|
||||||
}
|
}
|
||||||
return ipset, err
|
return ipset, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *GeoIPSetFactory) Create(cidrGroups ...[]*CIDR) (*GeoIPSet, error) {
|
func buildGeoIPRulesKey(rules []*GeoIPRule) string {
|
||||||
var ipv4Builder, ipv6Builder netipx.IPSetBuilder
|
rules = slices.Clone(rules)
|
||||||
|
|
||||||
for _, cidrGroup := range cidrGroups {
|
sort.Slice(rules, func(i, j int) bool {
|
||||||
for _, cidrEntry := range cidrGroup {
|
ri, rj := rules[i], rules[j]
|
||||||
ipBytes := cidrEntry.GetIp()
|
if ri.File != rj.File {
|
||||||
prefixLen := int(cidrEntry.GetPrefix())
|
return ri.File < rj.File
|
||||||
|
}
|
||||||
|
return ri.Code < rj.Code
|
||||||
|
})
|
||||||
|
|
||||||
addr, ok := netip.AddrFromSlice(ipBytes)
|
var sb strings.Builder
|
||||||
if !ok {
|
sb.Grow(len(rules) * 20) // geoip.dat:xx,
|
||||||
errors.LogError(context.Background(), "ignore invalid IP byte slice: ", ipBytes)
|
var last *GeoIPRule
|
||||||
continue
|
for i, r := range rules {
|
||||||
}
|
if i == 0 || (r.File != last.File || r.Code != last.Code) {
|
||||||
|
last = r
|
||||||
prefix := netip.PrefixFrom(addr, prefixLen)
|
sb.WriteString(r.File)
|
||||||
if !prefix.IsValid() {
|
sb.WriteString(":")
|
||||||
errors.LogError(context.Background(), "ignore created invalid prefix from addr ", addr, " and length ", prefixLen)
|
sb.WriteString(r.Code)
|
||||||
continue
|
sb.WriteString(",")
|
||||||
}
|
|
||||||
|
|
||||||
if addr.Is4() {
|
|
||||||
ipv4Builder.AddPrefix(prefix)
|
|
||||||
} else if addr.Is6() {
|
|
||||||
ipv6Builder.AddPrefix(prefix)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPSetFactory) CreateFromCIDRs(cidrs []*CIDR) (*IPSet, error) {
|
||||||
|
return f.createFrom(func(add func(*CIDR)) error {
|
||||||
|
for _, c := range cidrs {
|
||||||
|
add(c)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *IPSetFactory) createFrom(yield func(func(*CIDR)) error) (*IPSet, error) {
|
||||||
|
var ipv4Builder, ipv6Builder netipx.IPSetBuilder
|
||||||
|
|
||||||
|
err := yield(func(c *CIDR) {
|
||||||
|
ipBytes := c.GetIp()
|
||||||
|
prefixLen := int(c.GetPrefix())
|
||||||
|
|
||||||
|
addr, ok := netip.AddrFromSlice(ipBytes)
|
||||||
|
if !ok {
|
||||||
|
errors.LogError(context.Background(), "ignore invalid IP byte slice: ", ipBytes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix := netip.PrefixFrom(addr, prefixLen)
|
||||||
|
if !prefix.IsValid() {
|
||||||
|
errors.LogError(context.Background(), "ignore created invalid prefix from addr ", addr, " and length ", prefixLen)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if addr.Is4() {
|
||||||
|
ipv4Builder.AddPrefix(prefix)
|
||||||
|
} else if addr.Is6() {
|
||||||
|
ipv6Builder.AddPrefix(prefix)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// peak mem
|
||||||
|
runtime.GC()
|
||||||
|
defer runtime.GC()
|
||||||
|
|
||||||
ipv4, err := ipv4Builder.IPSet()
|
ipv4, err := ipv4Builder.IPSet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -855,107 +918,106 @@ func (f *GeoIPSetFactory) Create(cidrGroups ...[]*CIDR) (*GeoIPSet, error) {
|
|||||||
return nil, errors.New("failed to build IPv6 set").Base(err)
|
return nil, errors.New("failed to build IPv6 set").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var has4, has6 bool
|
||||||
var max4, max6 int
|
var max4, max6 int
|
||||||
|
|
||||||
for _, p := range ipv4.Prefixes() {
|
for _, p := range ipv4.Prefixes() {
|
||||||
|
has4 = true
|
||||||
if b := p.Bits(); b > max4 {
|
if b := p.Bits(); b > max4 {
|
||||||
max4 = b
|
max4 = b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, p := range ipv6.Prefixes() {
|
for _, p := range ipv6.Prefixes() {
|
||||||
|
has6 = true
|
||||||
if b := p.Bits(); b > max6 {
|
if b := p.Bits(); b > max6 {
|
||||||
max6 = b
|
max6 = b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if max4 == 0 {
|
if !has4 {
|
||||||
max4 = 0xff
|
max4 = 0xff
|
||||||
|
} else if max4 == 0 {
|
||||||
|
max4 = 0xfe
|
||||||
}
|
}
|
||||||
if max6 == 0 {
|
if !has6 {
|
||||||
max6 = 0xff
|
max6 = 0xff
|
||||||
|
} else if max6 == 0 {
|
||||||
|
max6 = 0xfe
|
||||||
}
|
}
|
||||||
|
|
||||||
return &GeoIPSet{ipv4: ipv4, ipv6: ipv6, max4: uint8(max4), max6: uint8(max6)}, nil
|
return &IPSet{ipv4: ipv4, ipv6: ipv6, max4: uint8(max4), max6: uint8(max6)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildOptimizedGeoIPMatcher(geoips ...*GeoIP) (GeoIPMatcher, error) {
|
func buildOptimizedIPMatcher(f *IPSetFactory, rules []*IPRule) (IPMatcher, error) {
|
||||||
n := len(geoips)
|
n := len(rules)
|
||||||
if n == 0 {
|
posCustom := make([]*CIDR, 0, n)
|
||||||
return nil, errors.New("no geoip configs provided")
|
negCustom := make([]*CIDR, 0, n)
|
||||||
}
|
posGeoip := make([]*GeoIPRule, 0, n)
|
||||||
|
negGeoip := make([]*GeoIPRule, 0, n)
|
||||||
|
|
||||||
var subs []*HeuristicGeoIPMatcher
|
for _, r := range rules {
|
||||||
pos := make([]*GeoIP, 0, n)
|
switch v := r.Value.(type) {
|
||||||
neg := make([]*GeoIP, 0, n/2)
|
case *IPRule_Custom:
|
||||||
|
if !v.Custom.ReverseMatch {
|
||||||
for _, geoip := range geoips {
|
posCustom = append(posCustom, v.Custom.Cidr)
|
||||||
if geoip == nil {
|
} else {
|
||||||
return nil, errors.New("geoip entry is nil")
|
negCustom = append(negCustom, v.Custom.Cidr)
|
||||||
}
|
|
||||||
if geoip.CountryCode == "" {
|
|
||||||
ipset, err := ipsetFactory.Create(geoip.Cidr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
subs = append(subs, &HeuristicGeoIPMatcher{ipset: ipset, reverse: geoip.ReverseMatch})
|
case *IPRule_Geoip:
|
||||||
continue
|
if !v.Geoip.ReverseMatch {
|
||||||
}
|
posGeoip = append(posGeoip, v.Geoip)
|
||||||
if !geoip.ReverseMatch {
|
} else {
|
||||||
pos = append(pos, geoip)
|
negGeoip = append(negGeoip, v.Geoip)
|
||||||
} else {
|
|
||||||
neg = append(neg, geoip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildIPSet := func(mergeables []*GeoIP) (*GeoIPSet, error) {
|
|
||||||
n := len(mergeables)
|
|
||||||
if n == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Slice(mergeables, func(i, j int) bool {
|
|
||||||
gi, gj := mergeables[i], mergeables[j]
|
|
||||||
return gi.CountryCode < gj.CountryCode
|
|
||||||
})
|
|
||||||
|
|
||||||
var sb strings.Builder
|
|
||||||
sb.Grow(n * 3) // xx,
|
|
||||||
cidrGroups := make([][]*CIDR, 0, n)
|
|
||||||
var last *GeoIP
|
|
||||||
for i, geoip := range mergeables {
|
|
||||||
if i == 0 || (geoip.CountryCode != last.CountryCode) {
|
|
||||||
last = geoip
|
|
||||||
sb.WriteString(geoip.CountryCode)
|
|
||||||
sb.WriteString(",")
|
|
||||||
cidrGroups = append(cidrGroups, geoip.Cidr)
|
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
panic("unknown ip rule type")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ipsetFactory.GetOrCreate(sb.String(), cidrGroups)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ipset, err := buildIPSet(pos)
|
subs := make([]*HeuristicIPMatcher, 0, 4)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
if len(posCustom) > 0 {
|
||||||
}
|
ipset, err := f.CreateFromCIDRs(posCustom)
|
||||||
if ipset != nil {
|
if err != nil {
|
||||||
subs = append(subs, &HeuristicGeoIPMatcher{ipset: ipset, reverse: false})
|
return nil, err
|
||||||
|
}
|
||||||
|
subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: false})
|
||||||
}
|
}
|
||||||
|
|
||||||
ipset, err = buildIPSet(neg)
|
if len(negCustom) > 0 {
|
||||||
if err != nil {
|
ipset, err := f.CreateFromCIDRs(negCustom)
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: true})
|
||||||
}
|
}
|
||||||
if ipset != nil {
|
|
||||||
subs = append(subs, &HeuristicGeoIPMatcher{ipset: ipset, reverse: true})
|
if len(posGeoip) > 0 {
|
||||||
|
ipset, err := f.GetOrCreateFromGeoIPRules(posGeoip)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: false})
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(negGeoip) > 0 {
|
||||||
|
ipset, err := f.GetOrCreateFromGeoIPRules(negGeoip)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
subs = append(subs, &HeuristicIPMatcher{ipset: ipset, reverse: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
switch len(subs) {
|
switch len(subs) {
|
||||||
case 0:
|
case 0:
|
||||||
return nil, errors.New("no valid geoip matcher")
|
return nil, errors.New("no valid ip matcher")
|
||||||
case 1:
|
case 1:
|
||||||
return subs[0], nil
|
return subs[0], nil
|
||||||
default:
|
default:
|
||||||
return &HeuristicMultiGeoIPMatcher{matchers: subs}, nil
|
return &HeuristicMultiIPMatcher{matchers: subs}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newIPSetFactory() *IPSetFactory {
|
||||||
|
return &IPSetFactory{shared: utils.NewWeakCacheMap[string, IPSet]()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,437 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
|
"slices"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
xnet "github.com/xtls/xray-core/common/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
func buildIPMatcher(rawRules ...string) IPMatcher {
|
||||||
|
rules, err := ParseIPRules(rawRules)
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
|
matcher, err := newIPRegistry().BuildIPMatcher(rules)
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
|
return matcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortIPStrings(ips []net.IP) []string {
|
||||||
|
output := make([]string, 0, len(ips))
|
||||||
|
for _, ip := range ips {
|
||||||
|
output = append(output, ip.String())
|
||||||
|
}
|
||||||
|
slices.Sort(output)
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMatcher(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher(
|
||||||
|
"0.0.0.0/8",
|
||||||
|
"10.0.0.0/8",
|
||||||
|
"100.64.0.0/10",
|
||||||
|
"127.0.0.0/8",
|
||||||
|
"169.254.0.0/16",
|
||||||
|
"172.16.0.0/12",
|
||||||
|
"192.0.0.0/24",
|
||||||
|
"192.0.2.0/24",
|
||||||
|
"192.168.0.0/16",
|
||||||
|
"192.18.0.0/15",
|
||||||
|
"198.51.100.0/24",
|
||||||
|
"203.0.113.0/24",
|
||||||
|
"8.8.8.8/32",
|
||||||
|
"91.108.4.0/16",
|
||||||
|
)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Output bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "192.168.1.1",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "192.0.0.0",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "192.0.1.0",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "0.1.0.0",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "1.0.0.1",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "8.8.8.7",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "8.8.8.8",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "2001:cdba::3257:9652",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "91.108.255.254",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
if v := matcher.Match(xnet.ParseAddress(test.Input).IP()); v != test.Output {
|
||||||
|
t.Error("unexpected output: ", v, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMatcherFullCIDR4(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher(
|
||||||
|
"0.0.0.0/0",
|
||||||
|
)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Output bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "192.168.1.1",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "0.0.0.0",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "255.255.255.255",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "2001:cdba::3257:9652",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "::0",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
if v := matcher.Match(xnet.ParseAddress(test.Input).IP()); v != test.Output {
|
||||||
|
t.Error("unexpected output: ", v, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMatcherFullCIDR6(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher(
|
||||||
|
"::0/0",
|
||||||
|
)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Output bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "192.168.1.1",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "0.0.0.0",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "255.255.255.255",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "2001:cdba::3257:9652",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "::0",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
if v := matcher.Match(xnet.ParseAddress(test.Input).IP()); v != test.Output {
|
||||||
|
t.Error("unexpected output: ", v, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMatcherRegression(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher(
|
||||||
|
"98.108.20.0/22",
|
||||||
|
"98.108.20.0/23",
|
||||||
|
)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Output bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "98.108.22.11",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "98.108.25.0",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
if v := matcher.Match(xnet.ParseAddress(test.Input).IP()); v != test.Output {
|
||||||
|
t.Error("unexpected output: ", v, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPReverseMatcher(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher(
|
||||||
|
"8.8.8.8/32",
|
||||||
|
"91.108.4.0/16",
|
||||||
|
)
|
||||||
|
matcher.SetReverse(true)
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Output bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "8.8.8.8",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "2001:cdba::3257:9652",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "91.108.255.254",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
if v := matcher.Match(xnet.ParseAddress(test.Input).IP()); v != test.Output {
|
||||||
|
t.Error("unexpected output: ", v, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPReverseMatcher2(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher(
|
||||||
|
"8.8.8.8/32",
|
||||||
|
"91.108.4.0/16",
|
||||||
|
"fe80::", // Keep IPv6 family non-empty so reverse matching can evaluate IPv6 input.
|
||||||
|
)
|
||||||
|
matcher.SetReverse(true)
|
||||||
|
|
||||||
|
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 _, test := range testCases {
|
||||||
|
if v := matcher.Match(xnet.ParseAddress(test.Input).IP()); v != test.Output {
|
||||||
|
t.Error("unexpected output: ", v, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPCustomReverseMatcher(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher("!8.8.8.8/32")
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
Input string
|
||||||
|
Output bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "8.8.8.8",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "1.1.1.1",
|
||||||
|
Output: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "2001:cdba::3257:9652",
|
||||||
|
Output: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range testCases {
|
||||||
|
if v := matcher.Match(xnet.ParseAddress(test.Input).IP()); v != test.Output {
|
||||||
|
t.Error("unexpected output: ", v, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMatcherAnyMatchAndMatches(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher(
|
||||||
|
"8.8.8.8/32",
|
||||||
|
"2001:4860:4860::8888/128",
|
||||||
|
)
|
||||||
|
ip := func(raw string) net.IP {
|
||||||
|
return xnet.ParseAddress(raw).IP()
|
||||||
|
}
|
||||||
|
|
||||||
|
if matcher.AnyMatch(nil) {
|
||||||
|
t.Fatal("expect AnyMatch(nil) to be false")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !matcher.AnyMatch([]net.IP{
|
||||||
|
net.IP{},
|
||||||
|
ip("1.1.1.1"),
|
||||||
|
ip("8.8.8.8"),
|
||||||
|
}) {
|
||||||
|
t.Fatal("expect AnyMatch to ignore invalid IPs and return true when one valid IP matches")
|
||||||
|
}
|
||||||
|
|
||||||
|
if matcher.AnyMatch([]net.IP{
|
||||||
|
ip("1.1.1.1"),
|
||||||
|
ip("2001:db8::1"),
|
||||||
|
}) {
|
||||||
|
t.Fatal("expect AnyMatch to be false when no valid IP matches")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !matcher.Matches([]net.IP{
|
||||||
|
ip("8.8.8.8"),
|
||||||
|
ip("2001:4860:4860::8888"),
|
||||||
|
}) {
|
||||||
|
t.Fatal("expect Matches to be true when all valid IPs match")
|
||||||
|
}
|
||||||
|
|
||||||
|
if matcher.Matches([]net.IP{
|
||||||
|
ip("8.8.8.8"),
|
||||||
|
ip("1.1.1.1"),
|
||||||
|
}) {
|
||||||
|
t.Fatal("expect Matches to be false when one valid IP does not match")
|
||||||
|
}
|
||||||
|
|
||||||
|
if matcher.Matches([]net.IP{
|
||||||
|
ip("8.8.8.8"),
|
||||||
|
net.IP{},
|
||||||
|
}) {
|
||||||
|
t.Fatal("expect Matches to be false when any IP is invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMatcherFilterIPs(t *testing.T) {
|
||||||
|
matcher := buildIPMatcher(
|
||||||
|
"8.8.8.8/32",
|
||||||
|
"91.108.4.0/16",
|
||||||
|
"2001:4860:4860::8888/128",
|
||||||
|
)
|
||||||
|
ip := func(raw string) net.IP {
|
||||||
|
return xnet.ParseAddress(raw).IP()
|
||||||
|
}
|
||||||
|
|
||||||
|
matched, unmatched := matcher.FilterIPs([]net.IP{
|
||||||
|
net.IP{},
|
||||||
|
ip("8.8.8.8"),
|
||||||
|
ip("91.108.255.254"),
|
||||||
|
ip("1.1.1.1"),
|
||||||
|
ip("2001:4860:4860::8888"),
|
||||||
|
ip("2001:db8::1"),
|
||||||
|
})
|
||||||
|
|
||||||
|
wantMatched := []string{
|
||||||
|
"2001:4860:4860::8888",
|
||||||
|
"8.8.8.8",
|
||||||
|
"91.108.255.254",
|
||||||
|
}
|
||||||
|
slices.Sort(wantMatched)
|
||||||
|
if v := sortIPStrings(matched); !reflect.DeepEqual(v, wantMatched) {
|
||||||
|
t.Error("unexpected output: ", v, " want ", wantMatched)
|
||||||
|
}
|
||||||
|
|
||||||
|
wantUnmatched := []string{
|
||||||
|
"1.1.1.1",
|
||||||
|
"2001:db8::1",
|
||||||
|
}
|
||||||
|
slices.Sort(wantUnmatched)
|
||||||
|
if v := sortIPStrings(unmatched); !reflect.DeepEqual(v, wantUnmatched) {
|
||||||
|
t.Error("unexpected output: ", v, " want ", wantUnmatched)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMatcher4CN(t *testing.T) {
|
||||||
|
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
|
||||||
|
matcher := buildIPMatcher("geoip:cn")
|
||||||
|
|
||||||
|
if matcher.Match([]byte{8, 8, 8, 8}) {
|
||||||
|
t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIPMatcher6US(t *testing.T) {
|
||||||
|
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
|
||||||
|
matcher := buildIPMatcher("geoip:us")
|
||||||
|
|
||||||
|
if !matcher.Match(xnet.ParseAddress("2001:4860:4860::8888").IP()) {
|
||||||
|
t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIPMatcher4CN(b *testing.B) {
|
||||||
|
b.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
|
||||||
|
matcher := buildIPMatcher("geoip:cn")
|
||||||
|
ip := net.IP{8, 8, 8, 8}
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = matcher.Match(ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkIPMatcher6US(b *testing.B) {
|
||||||
|
b.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
|
||||||
|
matcher := buildIPMatcher("geoip:us")
|
||||||
|
ip := xnet.ParseAddress("2001:4860:4860::8888").IP()
|
||||||
|
|
||||||
|
b.ResetTimer()
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = matcher.Match(ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
type IPRegistry struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
ipsetFactory *IPSetFactory
|
||||||
|
matchers []*DynamicIPMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *IPRegistry) BuildIPMatcher(rules []*IPRule) (IPMatcher, error) {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
m, err := buildOptimizedIPMatcher(r.ipsetFactory, rules)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
d := NewDynamicIPMatcher(rules, m)
|
||||||
|
r.matchers = append(r.matchers, d)
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *IPRegistry) Reload() error {
|
||||||
|
r.mu.Lock()
|
||||||
|
defer r.mu.Unlock()
|
||||||
|
|
||||||
|
errors.LogInfo(context.Background(), "reloading GeoIP data for ", len(r.matchers), " IP matcher(s)")
|
||||||
|
|
||||||
|
factory := newIPSetFactory()
|
||||||
|
type reloadEntry struct {
|
||||||
|
dynamic *DynamicIPMatcher
|
||||||
|
matcher IPMatcher
|
||||||
|
}
|
||||||
|
reloaded := make([]reloadEntry, len(r.matchers))
|
||||||
|
for i, d := range r.matchers {
|
||||||
|
m, err := buildOptimizedIPMatcher(factory, d.rules)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogErrorInner(context.Background(), err, "failed to reload GeoIP data for IP matcher ", i)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
reloaded[i] = reloadEntry{dynamic: d, matcher: m}
|
||||||
|
}
|
||||||
|
for _, entry := range reloaded {
|
||||||
|
entry.dynamic.Reload(entry.matcher)
|
||||||
|
}
|
||||||
|
r.ipsetFactory = factory
|
||||||
|
errors.LogInfo(context.Background(), "reloaded GeoIP data for ", len(r.matchers), " IP matcher(s)")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newIPRegistry() *IPRegistry {
|
||||||
|
return &IPRegistry{
|
||||||
|
ipsetFactory: newIPSetFactory(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var IPReg = newIPRegistry()
|
||||||
|
|
||||||
|
type ipMatcherState struct {
|
||||||
|
matcher IPMatcher
|
||||||
|
}
|
||||||
|
|
||||||
|
type DynamicIPMatcher struct {
|
||||||
|
rules []*IPRule
|
||||||
|
state atomic.Pointer[ipMatcherState]
|
||||||
|
mu sync.Mutex
|
||||||
|
reverse bool
|
||||||
|
reverseSet bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match implements IPMatcher.
|
||||||
|
func (d *DynamicIPMatcher) Match(ip net.IP) bool {
|
||||||
|
return d.state.Load().matcher.Match(ip)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AnyMatch implements IPMatcher.
|
||||||
|
func (d *DynamicIPMatcher) AnyMatch(ips []net.IP) bool {
|
||||||
|
return d.state.Load().matcher.AnyMatch(ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches implements IPMatcher.
|
||||||
|
func (d *DynamicIPMatcher) Matches(ips []net.IP) bool {
|
||||||
|
return d.state.Load().matcher.Matches(ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilterIPs implements IPMatcher.
|
||||||
|
func (d *DynamicIPMatcher) FilterIPs(ips []net.IP) (matched []net.IP, unmatched []net.IP) {
|
||||||
|
return d.state.Load().matcher.FilterIPs(ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleReverse implements IPMatcher.
|
||||||
|
func (d *DynamicIPMatcher) ToggleReverse() {
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
|
d.reverse = !d.reverse
|
||||||
|
d.state.Load().matcher.ToggleReverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReverse implements IPMatcher.
|
||||||
|
func (d *DynamicIPMatcher) SetReverse(reverse bool) {
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
|
d.reverse = reverse
|
||||||
|
d.reverseSet = true
|
||||||
|
d.state.Load().matcher.SetReverse(reverse)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DynamicIPMatcher) Reload(newMatcher IPMatcher) {
|
||||||
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
|
if d.reverseSet {
|
||||||
|
newMatcher.SetReverse(d.reverse)
|
||||||
|
} else if d.reverse {
|
||||||
|
newMatcher.ToggleReverse()
|
||||||
|
}
|
||||||
|
d.state.Store(&ipMatcherState{matcher: newMatcher})
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDynamicIPMatcher(rules []*IPRule, matcher IPMatcher) *DynamicIPMatcher {
|
||||||
|
d := &DynamicIPMatcher{rules: rules}
|
||||||
|
d.Reload(matcher)
|
||||||
|
return d
|
||||||
|
}
|
||||||
@@ -0,0 +1,265 @@
|
|||||||
|
package geodata
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/errors"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DefaultGeoIPDat = "geoip.dat"
|
||||||
|
DefaultGeoSiteDat = "geosite.dat"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseIPRules(rules []string) ([]*IPRule, error) {
|
||||||
|
var ipRules []*IPRule
|
||||||
|
|
||||||
|
for i, r := range rules {
|
||||||
|
r, reverse := cutReversePrefix(r)
|
||||||
|
|
||||||
|
if strings.HasPrefix(r, "geoip:") {
|
||||||
|
r = "ext:" + DefaultGeoIPDat + ":" + r[len("geoip:"):]
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix := 0
|
||||||
|
for _, ext := range [...]string{"ext:", "ext-ip:"} {
|
||||||
|
if strings.HasPrefix(r, ext) {
|
||||||
|
prefix = len(ext)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rule isIPRule_Value
|
||||||
|
var err error
|
||||||
|
if prefix > 0 {
|
||||||
|
rule, err = parseGeoIPRule(r[prefix:], reverse)
|
||||||
|
} else {
|
||||||
|
rule, err = parseCustomIPRule(r, reverse)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("illegal ip rule: ", rules[i]).Base(err)
|
||||||
|
}
|
||||||
|
ipRules = append(ipRules, &IPRule{Value: rule})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ipRules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func cutReversePrefix(s string) (string, bool) {
|
||||||
|
reverse := false
|
||||||
|
for strings.HasPrefix(s, "!") {
|
||||||
|
s = s[1:]
|
||||||
|
reverse = !reverse
|
||||||
|
}
|
||||||
|
return s, reverse
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGeoIPRule(rule string, reverse bool) (*IPRule_Geoip, error) {
|
||||||
|
file, code, ok := strings.Cut(rule, ":")
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("syntax error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if file == "" {
|
||||||
|
return nil, errors.New("empty file")
|
||||||
|
}
|
||||||
|
|
||||||
|
code, codeReverse := cutReversePrefix(code)
|
||||||
|
reverse = reverse != codeReverse
|
||||||
|
if code == "" {
|
||||||
|
return nil, errors.New("empty code")
|
||||||
|
}
|
||||||
|
code = strings.ToUpper(code)
|
||||||
|
|
||||||
|
if err := checkFile(file, code); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &IPRule_Geoip{
|
||||||
|
Geoip: &GeoIPRule{
|
||||||
|
File: file,
|
||||||
|
Code: code,
|
||||||
|
ReverseMatch: reverse,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCustomIPRule(rule string, reverse bool) (*IPRule_Custom, error) {
|
||||||
|
cidr, err := parseCIDR(rule)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &IPRule_Custom{
|
||||||
|
Custom: &CIDRRule{
|
||||||
|
Cidr: cidr,
|
||||||
|
ReverseMatch: reverse,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCIDR(s string) (*CIDR, error) {
|
||||||
|
ipStr, prefixStr, _ := strings.Cut(s, "/")
|
||||||
|
|
||||||
|
ipAddr := net.ParseAddress(ipStr)
|
||||||
|
|
||||||
|
var maxPrefix uint32
|
||||||
|
switch ipAddr.Family() {
|
||||||
|
case net.AddressFamilyIPv4:
|
||||||
|
maxPrefix = 32
|
||||||
|
case net.AddressFamilyIPv6:
|
||||||
|
maxPrefix = 128
|
||||||
|
default:
|
||||||
|
return nil, errors.New("unsupported address family")
|
||||||
|
}
|
||||||
|
|
||||||
|
prefixBits := maxPrefix
|
||||||
|
if prefixStr != "" {
|
||||||
|
parsedPrefix, err := strconv.ParseUint(prefixStr, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("invalid CIDR prefix length: ", prefixStr).Base(err)
|
||||||
|
}
|
||||||
|
prefixBits = uint32(parsedPrefix)
|
||||||
|
}
|
||||||
|
if prefixBits > maxPrefix {
|
||||||
|
return nil, errors.New("CIDR prefix length ", prefixBits, " exceeds max ", maxPrefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &CIDR{
|
||||||
|
Ip: []byte(ipAddr.IP()),
|
||||||
|
Prefix: prefixBits,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDomainRule(r string, defaultType Domain_Type) (*DomainRule, error) {
|
||||||
|
if strings.HasPrefix(r, "geosite:") {
|
||||||
|
r = "ext:" + DefaultGeoSiteDat + ":" + r[len("geosite:"):]
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix := 0
|
||||||
|
for _, ext := range [...]string{"ext:", "ext-domain:"} {
|
||||||
|
if strings.HasPrefix(r, ext) {
|
||||||
|
prefix = len(ext)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rule isDomainRule_Value
|
||||||
|
var err error
|
||||||
|
if prefix > 0 {
|
||||||
|
rule, err = parseGeoSiteRule(r[prefix:])
|
||||||
|
} else {
|
||||||
|
rule, err = parseCustomDomainRule(r, defaultType)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("illegal domain rule: ", r).Base(err)
|
||||||
|
}
|
||||||
|
return &DomainRule{Value: rule}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseDomainRules(rules []string, defaultType Domain_Type) ([]*DomainRule, error) {
|
||||||
|
var domainRules []*DomainRule
|
||||||
|
|
||||||
|
for i, r := range rules {
|
||||||
|
if strings.HasPrefix(r, "geosite:") {
|
||||||
|
r = "ext:" + DefaultGeoSiteDat + ":" + r[len("geosite:"):]
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix := 0
|
||||||
|
for _, ext := range [...]string{"ext:", "ext-domain:"} {
|
||||||
|
if strings.HasPrefix(r, ext) {
|
||||||
|
prefix = len(ext)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var rule isDomainRule_Value
|
||||||
|
var err error
|
||||||
|
if prefix > 0 {
|
||||||
|
rule, err = parseGeoSiteRule(r[prefix:])
|
||||||
|
} else {
|
||||||
|
rule, err = parseCustomDomainRule(r, defaultType)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("illegal domain rule: ", rules[i]).Base(err)
|
||||||
|
}
|
||||||
|
domainRules = append(domainRules, &DomainRule{Value: rule})
|
||||||
|
}
|
||||||
|
|
||||||
|
return domainRules, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseGeoSiteRule(rule string) (*DomainRule_Geosite, error) {
|
||||||
|
file, codeWithAttrs, ok := strings.Cut(rule, ":")
|
||||||
|
if !ok {
|
||||||
|
return nil, errors.New("syntax error")
|
||||||
|
}
|
||||||
|
|
||||||
|
if file == "" {
|
||||||
|
return nil, errors.New("empty file")
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(codeWithAttrs, "@") || strings.Contains(codeWithAttrs, "@@") {
|
||||||
|
return nil, errors.New("empty attr")
|
||||||
|
}
|
||||||
|
code, attrs, _ := strings.Cut(codeWithAttrs, "@")
|
||||||
|
|
||||||
|
if code == "" {
|
||||||
|
return nil, errors.New("empty code")
|
||||||
|
}
|
||||||
|
code = strings.ToUpper(code)
|
||||||
|
|
||||||
|
if err := checkFile(file, code); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DomainRule_Geosite{
|
||||||
|
Geosite: &GeoSiteRule{
|
||||||
|
File: file,
|
||||||
|
Code: code,
|
||||||
|
Attrs: strings.ToLower(attrs),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCustomDomainRule(rule string, defaultType Domain_Type) (*DomainRule_Custom, error) {
|
||||||
|
domain := new(Domain)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(rule, "regexp:"):
|
||||||
|
domain.Type = Domain_Regex
|
||||||
|
domain.Value = rule[7:]
|
||||||
|
|
||||||
|
case strings.HasPrefix(rule, "domain:"):
|
||||||
|
domain.Type = Domain_Domain
|
||||||
|
domain.Value = rule[7:]
|
||||||
|
|
||||||
|
case strings.HasPrefix(rule, "full:"):
|
||||||
|
domain.Type = Domain_Full
|
||||||
|
domain.Value = rule[5:]
|
||||||
|
|
||||||
|
case strings.HasPrefix(rule, "keyword:"):
|
||||||
|
domain.Type = Domain_Substr
|
||||||
|
domain.Value = rule[8:]
|
||||||
|
|
||||||
|
case strings.HasPrefix(rule, "dotless:"):
|
||||||
|
domain.Type = Domain_Regex
|
||||||
|
switch substr := rule[8:]; {
|
||||||
|
case substr == "":
|
||||||
|
domain.Value = "^[^.]*$"
|
||||||
|
case !strings.Contains(substr, "."):
|
||||||
|
domain.Value = "^[^.]*" + substr + "[^.]*$"
|
||||||
|
default:
|
||||||
|
return nil, errors.New("substr in dotless rule should not contain a dot")
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
domain.Type = defaultType
|
||||||
|
domain.Value = rule
|
||||||
|
}
|
||||||
|
|
||||||
|
return &DomainRule_Custom{
|
||||||
|
Custom: domain,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package geodata_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/geodata"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseIPRules(t *testing.T) {
|
||||||
|
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
|
||||||
|
rules := []string{
|
||||||
|
"geoip:us",
|
||||||
|
"geoip:cn",
|
||||||
|
"!geoip:cn",
|
||||||
|
"!!geoip:cn",
|
||||||
|
"geoip:!cn",
|
||||||
|
"geoip:!!cn",
|
||||||
|
"!geoip:!cn",
|
||||||
|
"ext:geoip.dat:!cn",
|
||||||
|
"ext:geoip.dat:!!cn",
|
||||||
|
"ext:geoip.dat:ca",
|
||||||
|
"ext-ip:geoip.dat:!cn",
|
||||||
|
"ext-ip:geoip.dat:!ca",
|
||||||
|
"192.168.0.0/24",
|
||||||
|
"!192.168.0.0/24",
|
||||||
|
"!!192.168.0.0/24",
|
||||||
|
"!!!192.168.0.0/24",
|
||||||
|
"192.168.0.1",
|
||||||
|
"fe80::/64",
|
||||||
|
"fe80::",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := geodata.ParseIPRules(rules)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to parse ip rules, got %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseIPRuleReverse(t *testing.T) {
|
||||||
|
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
|
||||||
|
for _, tt := range []struct {
|
||||||
|
rule string
|
||||||
|
reverse bool
|
||||||
|
}{
|
||||||
|
{rule: "!192.168.0.0/24", reverse: true},
|
||||||
|
{rule: "!!192.168.0.0/24", reverse: false},
|
||||||
|
{rule: "!!!192.168.0.0/24", reverse: true},
|
||||||
|
{rule: "!!!!192.168.0.0/24", reverse: false},
|
||||||
|
{rule: "geoip:cn", reverse: false},
|
||||||
|
{rule: "!geoip:cn", reverse: true},
|
||||||
|
{rule: "!!geoip:cn", reverse: false},
|
||||||
|
{rule: "geoip:!cn", reverse: true},
|
||||||
|
{rule: "geoip:!!cn", reverse: false},
|
||||||
|
{rule: "!geoip:!cn", reverse: false},
|
||||||
|
{rule: "!!geoip:!cn", reverse: true},
|
||||||
|
{rule: "!geoip:!!cn", reverse: true},
|
||||||
|
{rule: "ext:geoip.dat:!!!cn", reverse: true},
|
||||||
|
} {
|
||||||
|
t.Run(tt.rule, func(t *testing.T) {
|
||||||
|
rules, err := geodata.ParseIPRules([]string{tt.rule})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to parse ip rules, got %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rules) != 1 {
|
||||||
|
t.Fatalf("Expected 1 rule, got %d", len(rules))
|
||||||
|
}
|
||||||
|
|
||||||
|
switch rule := rules[0]; {
|
||||||
|
case rule.GetGeoip() != nil:
|
||||||
|
if rule.GetGeoip().GetReverseMatch() != tt.reverse {
|
||||||
|
t.Fatalf("Expected geoip reverse match to be %t", tt.reverse)
|
||||||
|
}
|
||||||
|
case rule.GetCustom() != nil:
|
||||||
|
if rule.GetCustom().GetReverseMatch() != tt.reverse {
|
||||||
|
t.Fatalf("Expected custom reverse match to be %t", tt.reverse)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
t.Fatal("Expected ip rule")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseDomainRules(t *testing.T) {
|
||||||
|
t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources"))
|
||||||
|
|
||||||
|
rules := []string{
|
||||||
|
"geosite:cn",
|
||||||
|
"geosite:geolocation-!cn",
|
||||||
|
"geosite:cn@!cn",
|
||||||
|
"ext:geosite.dat:geolocation-!cn",
|
||||||
|
"ext:geosite.dat:cn@!cn",
|
||||||
|
"ext-site:geosite.dat:geolocation-!cn",
|
||||||
|
"ext-site:geosite.dat:cn@!cn",
|
||||||
|
"domain:google.com",
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := geodata.ParseDomainRules(rules, geodata.Domain_Domain)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to parse domain rules, got %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package strmatcher
|
||||||
|
|
||||||
|
// LinearAnyMatcher is an implementation of AnyMatcher.
|
||||||
|
type LinearAnyMatcher struct {
|
||||||
|
full *FullMatcherSet
|
||||||
|
domain *DomainMatcherSet
|
||||||
|
substr *SubstrMatcherSet
|
||||||
|
regex *SimpleMatcherSet
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLinearAnyMatcher() *LinearAnyMatcher {
|
||||||
|
return new(LinearAnyMatcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add implements AnyMatcher.Add.
|
||||||
|
func (s *LinearAnyMatcher) Add(matcher Matcher) {
|
||||||
|
switch matcher := matcher.(type) {
|
||||||
|
case FullMatcher:
|
||||||
|
if s.full == nil {
|
||||||
|
s.full = NewFullMatcherSet()
|
||||||
|
}
|
||||||
|
s.full.AddFullMatcher(matcher)
|
||||||
|
case DomainMatcher:
|
||||||
|
if s.domain == nil {
|
||||||
|
s.domain = NewDomainMatcherSet()
|
||||||
|
}
|
||||||
|
s.domain.AddDomainMatcher(matcher)
|
||||||
|
case SubstrMatcher:
|
||||||
|
if s.substr == nil {
|
||||||
|
s.substr = new(SubstrMatcherSet)
|
||||||
|
}
|
||||||
|
s.substr.AddSubstrMatcher(matcher)
|
||||||
|
default:
|
||||||
|
if s.regex == nil {
|
||||||
|
s.regex = new(SimpleMatcherSet)
|
||||||
|
}
|
||||||
|
s.regex.AddMatcher(matcher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchAny implements AnyMatcher.MatchAny.
|
||||||
|
func (s *LinearAnyMatcher) MatchAny(input string) bool {
|
||||||
|
if s.full != nil && s.full.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if s.domain != nil && s.domain.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if s.substr != nil && s.substr.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return s.regex != nil && s.regex.MatchAny(input)
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package strmatcher_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/xtls/xray-core/common/geodata/strmatcher"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkLinearIndexMatcher(b *testing.B) {
|
||||||
|
benchmarkIndexMatcher(b, func() IndexMatcher {
|
||||||
|
return NewLinearIndexMatcher()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkMphIndexMatcher(b *testing.B) {
|
||||||
|
benchmarkIndexMatcher(b, func() IndexMatcher {
|
||||||
|
return NewMphIndexMatcher()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkIndexMatcher(b *testing.B, ctor func() IndexMatcher) {
|
||||||
|
b.Run("Match", func(b *testing.B) {
|
||||||
|
b.Run("Domain------------", func(b *testing.B) {
|
||||||
|
benchmarkMatch(b, ctor(), map[Type]bool{Domain: true})
|
||||||
|
})
|
||||||
|
b.Run("Domain+Full-------", func(b *testing.B) {
|
||||||
|
benchmarkMatch(b, ctor(), map[Type]bool{Domain: true, Full: true})
|
||||||
|
})
|
||||||
|
b.Run("Domain+Full+Substr", func(b *testing.B) {
|
||||||
|
benchmarkMatch(b, ctor(), map[Type]bool{Domain: true, Full: true, Substr: true})
|
||||||
|
})
|
||||||
|
b.Run("All-Fail----------", func(b *testing.B) {
|
||||||
|
benchmarkMatch(b, ctor(), map[Type]bool{Domain: false, Full: false, Substr: false})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("Match/Dotless", func(b *testing.B) { // Dotless domain matcher automatically inserted in DNS app when "localhost" DNS is used.
|
||||||
|
b.Run("All-Succ", func(b *testing.B) {
|
||||||
|
benchmarkMatch(b, ctor(), map[Type]bool{Domain: true, Full: true, Substr: true, Regex: true})
|
||||||
|
})
|
||||||
|
b.Run("All-Fail", func(b *testing.B) {
|
||||||
|
benchmarkMatch(b, ctor(), map[Type]bool{Domain: false, Full: false, Substr: false, Regex: false})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("MatchAny", func(b *testing.B) {
|
||||||
|
b.Run("First-Full--", func(b *testing.B) {
|
||||||
|
benchmarkMatchAny(b, ctor(), map[Type]bool{Full: true, Domain: true, Substr: true})
|
||||||
|
})
|
||||||
|
b.Run("First-Domain", func(b *testing.B) {
|
||||||
|
benchmarkMatchAny(b, ctor(), map[Type]bool{Full: false, Domain: true, Substr: true})
|
||||||
|
})
|
||||||
|
b.Run("First-Substr", func(b *testing.B) {
|
||||||
|
benchmarkMatchAny(b, ctor(), map[Type]bool{Full: false, Domain: false, Substr: true})
|
||||||
|
})
|
||||||
|
b.Run("All-Fail----", func(b *testing.B) {
|
||||||
|
benchmarkMatchAny(b, ctor(), map[Type]bool{Full: false, Domain: false, Substr: false})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package strmatcher_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
. "github.com/xtls/xray-core/common/geodata/strmatcher"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkFullMatcher(b *testing.B) {
|
||||||
|
b.Run("SimpleMatcherGroup------", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Full, func() MatcherGroup {
|
||||||
|
return new(SimpleMatcherGroup)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("FullMatcherGroup--------", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Full, func() MatcherGroup {
|
||||||
|
return NewFullMatcherGroup()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("ACAutomationMatcherGroup", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Full, func() MatcherGroup {
|
||||||
|
return NewACAutomatonMatcherGroup()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("MphMatcherGroup---------", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Full, func() MatcherGroup {
|
||||||
|
return NewMphMatcherGroup()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkDomainMatcher(b *testing.B) {
|
||||||
|
b.Run("SimpleMatcherGroup------", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Domain, func() MatcherGroup {
|
||||||
|
return new(SimpleMatcherGroup)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("DomainMatcherGroup------", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Domain, func() MatcherGroup {
|
||||||
|
return NewDomainMatcherGroup()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("ACAutomationMatcherGroup", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Domain, func() MatcherGroup {
|
||||||
|
return NewACAutomatonMatcherGroup()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("MphMatcherGroup---------", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Domain, func() MatcherGroup {
|
||||||
|
return NewMphMatcherGroup()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkSubstrMatcher(b *testing.B) {
|
||||||
|
b.Run("SimpleMatcherGroup------", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Substr, func() MatcherGroup {
|
||||||
|
return new(SimpleMatcherGroup)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("SubstrMatcherGroup------", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Substr, func() MatcherGroup {
|
||||||
|
return new(SubstrMatcherGroup)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("ACAutomationMatcherGroup", func(b *testing.B) {
|
||||||
|
benchmarkMatcherType(b, Substr, func() MatcherGroup {
|
||||||
|
return NewACAutomatonMatcherGroup()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility functions for benchmark
|
||||||
|
|
||||||
|
func benchmarkMatcherType(b *testing.B, t Type, ctor func() MatcherGroup) {
|
||||||
|
b.Run("Match", func(b *testing.B) {
|
||||||
|
b.Run("Succ", func(b *testing.B) {
|
||||||
|
benchmarkMatch(b, ctor(), map[Type]bool{t: true})
|
||||||
|
})
|
||||||
|
b.Run("Fail", func(b *testing.B) {
|
||||||
|
benchmarkMatch(b, ctor(), map[Type]bool{t: false})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("MatchAny", func(b *testing.B) {
|
||||||
|
b.Run("Succ", func(b *testing.B) {
|
||||||
|
benchmarkMatchAny(b, ctor(), map[Type]bool{t: true})
|
||||||
|
})
|
||||||
|
b.Run("Fail", func(b *testing.B) {
|
||||||
|
benchmarkMatchAny(b, ctor(), map[Type]bool{t: false})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkMatch(b *testing.B, g MatcherGroup, enabledTypes map[Type]bool) {
|
||||||
|
prepareMatchers(g, enabledTypes)
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = g.Match("0.example.com")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func benchmarkMatchAny(b *testing.B, g MatcherGroup, enabledTypes map[Type]bool) {
|
||||||
|
prepareMatchers(g, enabledTypes)
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
_ = g.MatchAny("0.example.com")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareMatchers(g MatcherGroup, enabledTypes map[Type]bool) {
|
||||||
|
for matcherType, hasMatch := range enabledTypes {
|
||||||
|
switch matcherType {
|
||||||
|
case Domain:
|
||||||
|
if hasMatch {
|
||||||
|
AddMatcherToGroup(g, DomainMatcher("example.com"), 0)
|
||||||
|
}
|
||||||
|
for i := 1; i < 1024; i++ {
|
||||||
|
AddMatcherToGroup(g, DomainMatcher(strconv.Itoa(i)+".example.com"), uint32(i))
|
||||||
|
}
|
||||||
|
case Full:
|
||||||
|
if hasMatch {
|
||||||
|
AddMatcherToGroup(g, FullMatcher("0.example.com"), 0)
|
||||||
|
}
|
||||||
|
for i := 1; i < 64; i++ {
|
||||||
|
AddMatcherToGroup(g, FullMatcher(strconv.Itoa(i)+".example.com"), uint32(i))
|
||||||
|
}
|
||||||
|
case Substr:
|
||||||
|
if hasMatch {
|
||||||
|
AddMatcherToGroup(g, SubstrMatcher("example.com"), 0)
|
||||||
|
}
|
||||||
|
for i := 1; i < 4; i++ {
|
||||||
|
AddMatcherToGroup(g, SubstrMatcher(strconv.Itoa(i)+".example.com"), uint32(i))
|
||||||
|
}
|
||||||
|
case Regex:
|
||||||
|
matcher, err := Regex.New("^[^.]*$") // Dotless domain matcher automatically inserted in DNS app when "localhost" DNS is used.
|
||||||
|
common.Must(err)
|
||||||
|
AddMatcherToGroup(g, matcher, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g, ok := g.(buildable); ok {
|
||||||
|
common.Must(g.Build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type buildable interface {
|
||||||
|
Build() error
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package strmatcher
|
||||||
|
|
||||||
|
// LinearIndexMatcher is an implementation of IndexMatcher.
|
||||||
|
type LinearIndexMatcher struct {
|
||||||
|
count uint32
|
||||||
|
full *FullMatcherGroup
|
||||||
|
domain *DomainMatcherGroup
|
||||||
|
substr *SubstrMatcherGroup
|
||||||
|
regex *SimpleMatcherGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLinearIndexMatcher() *LinearIndexMatcher {
|
||||||
|
return new(LinearIndexMatcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add implements IndexMatcher.Add.
|
||||||
|
func (g *LinearIndexMatcher) Add(matcher Matcher) uint32 {
|
||||||
|
g.count++
|
||||||
|
index := g.count
|
||||||
|
|
||||||
|
switch matcher := matcher.(type) {
|
||||||
|
case FullMatcher:
|
||||||
|
if g.full == nil {
|
||||||
|
g.full = NewFullMatcherGroup()
|
||||||
|
}
|
||||||
|
g.full.AddFullMatcher(matcher, index)
|
||||||
|
case DomainMatcher:
|
||||||
|
if g.domain == nil {
|
||||||
|
g.domain = NewDomainMatcherGroup()
|
||||||
|
}
|
||||||
|
g.domain.AddDomainMatcher(matcher, index)
|
||||||
|
case SubstrMatcher:
|
||||||
|
if g.substr == nil {
|
||||||
|
g.substr = new(SubstrMatcherGroup)
|
||||||
|
}
|
||||||
|
g.substr.AddSubstrMatcher(matcher, index)
|
||||||
|
default:
|
||||||
|
if g.regex == nil {
|
||||||
|
g.regex = new(SimpleMatcherGroup)
|
||||||
|
}
|
||||||
|
g.regex.AddMatcher(matcher, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build implements IndexMatcher.Build.
|
||||||
|
func (*LinearIndexMatcher) Build() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match implements IndexMatcher.Match.
|
||||||
|
func (g *LinearIndexMatcher) Match(input string) []uint32 {
|
||||||
|
// Allocate capacity to prevent matches escaping to heap
|
||||||
|
result := make([][]uint32, 0, 5)
|
||||||
|
if g.full != nil {
|
||||||
|
if matches := g.full.Match(input); len(matches) > 0 {
|
||||||
|
result = append(result, matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.domain != nil {
|
||||||
|
if matches := g.domain.Match(input); len(matches) > 0 {
|
||||||
|
result = append(result, matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.substr != nil {
|
||||||
|
if matches := g.substr.Match(input); len(matches) > 0 {
|
||||||
|
result = append(result, matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.regex != nil {
|
||||||
|
if matches := g.regex.Match(input); len(matches) > 0 {
|
||||||
|
result = append(result, matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CompositeMatches(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchAny implements IndexMatcher.MatchAny.
|
||||||
|
func (g *LinearIndexMatcher) MatchAny(input string) bool {
|
||||||
|
if g.full != nil && g.full.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if g.domain != nil && g.domain.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if g.substr != nil && g.substr.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return g.regex != nil && g.regex.MatchAny(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size implements IndexMatcher.Size.
|
||||||
|
func (g *LinearIndexMatcher) Size() uint32 {
|
||||||
|
return g.count
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package strmatcher_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
. "github.com/xtls/xray-core/common/geodata/strmatcher"
|
||||||
|
)
|
||||||
|
|
||||||
|
// See https://github.com/v2fly/v2ray-core/issues/92#issuecomment-673238489
|
||||||
|
func TestLinearIndexMatcher(t *testing.T) {
|
||||||
|
rules := []struct {
|
||||||
|
Type Type
|
||||||
|
Domain string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Type: Regex,
|
||||||
|
Domain: "apis\\.us$",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Substr,
|
||||||
|
Domain: "apis",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Domain,
|
||||||
|
Domain: "googleapis.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Domain,
|
||||||
|
Domain: "com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Full,
|
||||||
|
Domain: "www.baidu.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Substr,
|
||||||
|
Domain: "apis",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Domain,
|
||||||
|
Domain: "googleapis.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Full,
|
||||||
|
Domain: "fonts.googleapis.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Full,
|
||||||
|
Domain: "www.baidu.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Domain,
|
||||||
|
Domain: "example.com",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cases := []struct {
|
||||||
|
Input string
|
||||||
|
Output []uint32
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "www.baidu.com",
|
||||||
|
Output: []uint32{5, 9, 4},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "fonts.googleapis.com",
|
||||||
|
Output: []uint32{8, 3, 7, 4, 2, 6},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "example.googleapis.com",
|
||||||
|
Output: []uint32{3, 7, 4, 2, 6},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "testapis.us",
|
||||||
|
Output: []uint32{2, 6, 1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "example.com",
|
||||||
|
Output: []uint32{10, 4},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
matcherGroup := NewLinearIndexMatcher()
|
||||||
|
for _, rule := range rules {
|
||||||
|
matcher, err := rule.Type.New(rule.Domain)
|
||||||
|
common.Must(err)
|
||||||
|
matcherGroup.Add(matcher)
|
||||||
|
}
|
||||||
|
matcherGroup.Build()
|
||||||
|
for _, test := range cases {
|
||||||
|
if m := matcherGroup.Match(test.Input); !reflect.DeepEqual(m, test.Output) {
|
||||||
|
t.Error("unexpected output: ", m, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package strmatcher
|
||||||
|
|
||||||
|
import "runtime"
|
||||||
|
|
||||||
|
// A MphIndexMatcher is divided into three parts:
|
||||||
|
// 1. `full` and `domain` patterns are matched by Rabin-Karp algorithm and minimal perfect hash table;
|
||||||
|
// 2. `substr` patterns are matched by ac automaton;
|
||||||
|
// 3. `regex` patterns are matched with the regex library.
|
||||||
|
type MphIndexMatcher struct {
|
||||||
|
count uint32
|
||||||
|
mph *MphMatcherGroup
|
||||||
|
ac *ACAutomatonMatcherGroup
|
||||||
|
regex *SimpleMatcherGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMphIndexMatcher() *MphIndexMatcher {
|
||||||
|
return new(MphIndexMatcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add implements IndexMatcher.Add.
|
||||||
|
func (g *MphIndexMatcher) Add(matcher Matcher) uint32 {
|
||||||
|
g.count++
|
||||||
|
index := g.count
|
||||||
|
|
||||||
|
switch matcher := matcher.(type) {
|
||||||
|
case FullMatcher:
|
||||||
|
if g.mph == nil {
|
||||||
|
g.mph = NewMphMatcherGroup()
|
||||||
|
}
|
||||||
|
g.mph.AddFullMatcher(matcher, index)
|
||||||
|
case DomainMatcher:
|
||||||
|
if g.mph == nil {
|
||||||
|
g.mph = NewMphMatcherGroup()
|
||||||
|
}
|
||||||
|
g.mph.AddDomainMatcher(matcher, index)
|
||||||
|
case SubstrMatcher:
|
||||||
|
if g.ac == nil {
|
||||||
|
g.ac = NewACAutomatonMatcherGroup()
|
||||||
|
}
|
||||||
|
g.ac.AddSubstrMatcher(matcher, index)
|
||||||
|
case *RegexMatcher:
|
||||||
|
if g.regex == nil {
|
||||||
|
g.regex = &SimpleMatcherGroup{}
|
||||||
|
}
|
||||||
|
g.regex.AddMatcher(matcher, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build implements IndexMatcher.Build.
|
||||||
|
func (g *MphIndexMatcher) Build() error {
|
||||||
|
if g.mph != nil {
|
||||||
|
runtime.GC() // peak mem
|
||||||
|
g.mph.Build()
|
||||||
|
}
|
||||||
|
runtime.GC() // peak mem
|
||||||
|
if g.ac != nil {
|
||||||
|
g.ac.Build()
|
||||||
|
runtime.GC() // peak mem
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match implements IndexMatcher.Match.
|
||||||
|
func (g *MphIndexMatcher) Match(input string) []uint32 {
|
||||||
|
result := make([][]uint32, 0, 5)
|
||||||
|
if g.mph != nil {
|
||||||
|
if matches := g.mph.Match(input); len(matches) > 0 {
|
||||||
|
result = append(result, matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.ac != nil {
|
||||||
|
if matches := g.ac.Match(input); len(matches) > 0 {
|
||||||
|
result = append(result, matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.regex != nil {
|
||||||
|
if matches := g.regex.Match(input); len(matches) > 0 {
|
||||||
|
result = append(result, matches)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CompositeMatches(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MatchAny implements IndexMatcher.MatchAny.
|
||||||
|
func (g *MphIndexMatcher) MatchAny(input string) bool {
|
||||||
|
if g.mph != nil && g.mph.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if g.ac != nil && g.ac.MatchAny(input) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return g.regex != nil && g.regex.MatchAny(input)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size implements IndexMatcher.Size.
|
||||||
|
func (g *MphIndexMatcher) Size() uint32 {
|
||||||
|
return g.count
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
package strmatcher_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
|
. "github.com/xtls/xray-core/common/geodata/strmatcher"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMphIndexMatcher(t *testing.T) {
|
||||||
|
rules := []struct {
|
||||||
|
Type Type
|
||||||
|
Domain string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Type: Regex,
|
||||||
|
Domain: "apis\\.us$",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Substr,
|
||||||
|
Domain: "apis",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Domain,
|
||||||
|
Domain: "googleapis.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Domain,
|
||||||
|
Domain: "com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Full,
|
||||||
|
Domain: "www.baidu.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Substr,
|
||||||
|
Domain: "apis",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Domain,
|
||||||
|
Domain: "googleapis.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Full,
|
||||||
|
Domain: "fonts.googleapis.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Full,
|
||||||
|
Domain: "www.baidu.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: Domain,
|
||||||
|
Domain: "example.com",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cases := []struct {
|
||||||
|
Input string
|
||||||
|
Output []uint32
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Input: "www.baidu.com",
|
||||||
|
Output: []uint32{5, 9, 4},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "fonts.googleapis.com",
|
||||||
|
Output: []uint32{8, 3, 7, 4, 2, 6},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "example.googleapis.com",
|
||||||
|
Output: []uint32{3, 7, 4, 2, 6},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "testapis.us",
|
||||||
|
Output: []uint32{2, 6, 1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Input: "example.com",
|
||||||
|
Output: []uint32{10, 4},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
matcherGroup := NewMphIndexMatcher()
|
||||||
|
for _, rule := range rules {
|
||||||
|
matcher, err := rule.Type.New(rule.Domain)
|
||||||
|
common.Must(err)
|
||||||
|
matcherGroup.Add(matcher)
|
||||||
|
}
|
||||||
|
matcherGroup.Build()
|
||||||
|
for _, test := range cases {
|
||||||
|
if m := matcherGroup.Match(test.Input); !reflect.DeepEqual(m, test.Output) {
|
||||||
|
t.Error("unexpected output: ", m, " for test case ", test)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user