mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-07-02 01:12:03 +08:00
Compare commits
No commits in common. "main" and "v25.3.6" have entirely different histories.
72
.github/docker/Dockerfile
vendored
72
.github/docker/Dockerfile
vendored
@ -1,62 +1,28 @@
|
|||||||
# syntax=docker/dockerfile:latest
|
# syntax=docker/dockerfile:1
|
||||||
FROM --platform=$BUILDPLATFORM golang:latest AS build
|
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||||
|
|
||||||
# Build xray-core
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . .
|
COPY . .
|
||||||
ARG TARGETOS
|
ARG TARGETOS
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
|
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
|
||||||
|
ADD https://github.com/v2fly/geoip/releases/latest/download/geoip.dat /v2fly/geoip.dat
|
||||||
|
ADD https://github.com/v2fly/domain-list-community/releases/latest/download/dlc.dat /v2fly/geosite.dat
|
||||||
|
ADD https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat /loyalsoldier/geoip.dat
|
||||||
|
ADD https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat /loyalsoldier/geosite.dat
|
||||||
|
|
||||||
# Download geodat into a staging directory
|
# chainguard/static contains only tzdata and ca-certificates, can be built with multiarch static binaries.
|
||||||
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat /tmp/geodat/geoip.dat
|
FROM --platform=linux/amd64 chainguard/static:latest
|
||||||
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat /tmp/geodat/geosite.dat
|
WORKDIR /var/log/xray
|
||||||
|
COPY .github/docker/files/config.json /etc/xray/config.json
|
||||||
|
COPY --from=build --chmod=755 /src/xray /usr/bin/xray
|
||||||
|
|
||||||
RUN mkdir -p /tmp/empty
|
USER root
|
||||||
|
WORKDIR /root
|
||||||
# Create config files with empty JSON content
|
VOLUME /etc/xray
|
||||||
RUN mkdir -p /tmp/usr/local/etc/xray
|
ARG TZ=Asia/Shanghai
|
||||||
RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
|
|
||||||
{
|
|
||||||
"log": {
|
|
||||||
"error": "/var/log/xray/error.log",
|
|
||||||
"loglevel": "warning",
|
|
||||||
"access": "none",
|
|
||||||
"dnsLog": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/01_api.json
|
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/02_dns.json
|
|
||||||
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/05_inbounds.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/08_stats.json
|
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/09_reverse.json
|
|
||||||
|
|
||||||
# Create log files
|
|
||||||
RUN mkdir -p /tmp/var/log/xray && touch \
|
|
||||||
/tmp/var/log/xray/access.log \
|
|
||||||
/tmp/var/log/xray/error.log
|
|
||||||
|
|
||||||
# Build finally image
|
|
||||||
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 /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=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=755 /tmp/empty /var/log/xray
|
|
||||||
COPY --from=build --chown=65532:65532 --chmod=600 /tmp/var/log/xray/*.log /var/log/xray/
|
|
||||||
|
|
||||||
VOLUME /usr/local/etc/xray
|
|
||||||
VOLUME /var/log/xray
|
|
||||||
|
|
||||||
ARG TZ=Etc/UTC
|
|
||||||
ENV TZ=$TZ
|
ENV TZ=$TZ
|
||||||
|
ENTRYPOINT [ "/usr/bin/xray" ]
|
||||||
|
CMD [ "-confdir", "/etc/xray/" ]
|
||||||
|
|
||||||
ENTRYPOINT [ "/usr/local/bin/xray" ]
|
ARG flavor=v2fly
|
||||||
CMD [ "-confdir", "/usr/local/etc/xray/" ]
|
COPY --from=build --chmod=644 /$flavor /usr/share/xray
|
||||||
|
71
.github/docker/Dockerfile.usa
vendored
71
.github/docker/Dockerfile.usa
vendored
@ -1,71 +0,0 @@
|
|||||||
# syntax=docker/dockerfile:latest
|
|
||||||
FROM --platform=$BUILDPLATFORM golang:latest AS build
|
|
||||||
|
|
||||||
# Build xray-core
|
|
||||||
WORKDIR /src
|
|
||||||
COPY . .
|
|
||||||
ARG TARGETOS
|
|
||||||
ARG TARGETARCH
|
|
||||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
|
|
||||||
|
|
||||||
# Download geodat into a staging directory
|
|
||||||
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat /tmp/geodat/geoip.dat
|
|
||||||
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat /tmp/geodat/geosite.dat
|
|
||||||
|
|
||||||
RUN mkdir -p /tmp/empty
|
|
||||||
|
|
||||||
# Create config files with empty JSON content
|
|
||||||
RUN mkdir -p /tmp/usr/local/etc/xray
|
|
||||||
RUN cat <<EOF >/tmp/usr/local/etc/xray/00_log.json
|
|
||||||
{
|
|
||||||
"log": {
|
|
||||||
"error": "/var/log/xray/error.log",
|
|
||||||
"loglevel": "warning",
|
|
||||||
"access": "none",
|
|
||||||
"dnsLog": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/01_api.json
|
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/02_dns.json
|
|
||||||
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/05_inbounds.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/08_stats.json
|
|
||||||
RUN echo '{}' >/tmp/usr/local/etc/xray/09_reverse.json
|
|
||||||
|
|
||||||
# Create log files
|
|
||||||
RUN mkdir -p /tmp/var/log/xray && touch \
|
|
||||||
/tmp/var/log/xray/access.log \
|
|
||||||
/tmp/var/log/xray/error.log
|
|
||||||
|
|
||||||
# Build finally image
|
|
||||||
# Note on Distroless Base Image and Architecture Support:
|
|
||||||
# - The official 'gcr.io/distroless/static' image provided by Google only supports a limited set of architectures for Linux:
|
|
||||||
# - linux/amd64
|
|
||||||
# - linux/arm/v7
|
|
||||||
# - linux/arm64/v8
|
|
||||||
# - linux/ppc64le
|
|
||||||
# - linux/s390x
|
|
||||||
# - Upon inspection, the blob contents of the Distroless images across these architectures are nearly identical, with only minor differences in metadata (e.g., 'Architecture' field in the manifest).
|
|
||||||
# - Due to this similarity in content, it is feasible to forcibly specify a single platform (e.g., '--platform=linux/amd64') for unsupported architectures, as the core image content remains compatible with statically compiled binaries like Go applications.
|
|
||||||
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 /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=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=755 /tmp/empty /var/log/xray
|
|
||||||
COPY --from=build --chown=65532:65532 --chmod=600 /tmp/var/log/xray/*.log /var/log/xray/
|
|
||||||
|
|
||||||
VOLUME /usr/local/etc/xray
|
|
||||||
VOLUME /var/log/xray
|
|
||||||
|
|
||||||
ARG TZ=Etc/UTC
|
|
||||||
ENV TZ=$TZ
|
|
||||||
|
|
||||||
ENTRYPOINT [ "/usr/local/bin/xray" ]
|
|
||||||
CMD [ "-confdir", "/usr/local/etc/xray/" ]
|
|
18
.github/docker/files/config.json
vendored
Normal file
18
.github/docker/files/config.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"inbounds": [{
|
||||||
|
"port": 9000,
|
||||||
|
"protocol": "vmess",
|
||||||
|
"settings": {
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"id": "1eb6e917-774b-4a84-aff6-b058577c60a5",
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"outbounds": [{
|
||||||
|
"protocol": "freedom",
|
||||||
|
"settings": {}
|
||||||
|
}]
|
||||||
|
}
|
61
.github/workflows/docker.yml
vendored
61
.github/workflows/docker.yml
vendored
@ -3,6 +3,9 @@ name: Build docker image
|
|||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-image:
|
build-image:
|
||||||
@ -11,7 +14,6 @@ jobs:
|
|||||||
packages: write
|
packages: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Docker metadata
|
- name: Docker metadata
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
@ -19,73 +21,56 @@ jobs:
|
|||||||
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
||||||
flavor: latest=auto
|
flavor: latest=auto
|
||||||
tags: |
|
tags: |
|
||||||
|
type=sha
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
|
- name: Docker metadata Loyalsoldier flavor
|
||||||
- name: Docker metadata (unsupported architectures)
|
id: loyalsoldier
|
||||||
id: metausa
|
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
||||||
flavor: |
|
flavor: |
|
||||||
latest=auto
|
latest=auto
|
||||||
suffix=-usa,onlatest=true
|
suffix=-ls,onlatest=true
|
||||||
tags: |
|
tags: |
|
||||||
|
type=sha
|
||||||
|
type=ref,event=branch
|
||||||
|
type=ref,event=pr
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: |
|
platforms: |
|
||||||
linux/amd64
|
linux/amd64
|
||||||
linux/arm/v7
|
linux/arm64
|
||||||
linux/arm64/v8
|
linux/loong64
|
||||||
linux/ppc64le
|
linux/riscv64
|
||||||
linux/s390x
|
|
||||||
provenance: false
|
provenance: false
|
||||||
file: .github/docker/Dockerfile
|
file: .github/docker/Dockerfile
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
- name: Build and push Loyalsoldier flavor
|
||||||
- name: Build and push (unsupported architectures)
|
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: |
|
platforms: |
|
||||||
linux/386
|
linux/amd64
|
||||||
linux/arm/v6
|
linux/arm64
|
||||||
linux/riscv64
|
|
||||||
linux/loong64
|
linux/loong64
|
||||||
|
linux/riscv64
|
||||||
provenance: false
|
provenance: false
|
||||||
file: .github/docker/Dockerfile.usa
|
file: .github/docker/Dockerfile
|
||||||
|
build-args: flavor=loyalsoldier
|
||||||
push: true
|
push: true
|
||||||
tags: ${{ steps.metausa.outputs.tags }}
|
tags: |
|
||||||
|
${{ steps.loyalsoldier.outputs.tags }}
|
||||||
- name: Merge Multi-Arch Manifests
|
|
||||||
run: |
|
|
||||||
echo "Starting to merge multi-architecture manifests..."
|
|
||||||
|
|
||||||
# Convert newlines to spaces and split into array
|
|
||||||
TAGS=($(echo "${{ steps.meta.outputs.tags }}" | tr '\n' ' '))
|
|
||||||
|
|
||||||
echo "Total tags to process: ${#TAGS[@]}"
|
|
||||||
for tag in "${TAGS[@]}"; do
|
|
||||||
echo "Merging tag: $tag with unsupported architectures ($tag-usa)"
|
|
||||||
docker buildx imagetools create --append --tag "$tag" "$tag-usa"
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Error: Failed to merge $tag-usa into $tag"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Multi-architecture manifest merge completed successfully."
|
|
||||||
|
33
.github/workflows/release-win7.yml
vendored
33
.github/workflows/release-win7.yml
vendored
@ -9,38 +9,7 @@ on:
|
|||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-assets:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Restore Geodat Cache
|
|
||||||
uses: actions/cache/restore@v4
|
|
||||||
with:
|
|
||||||
path: resources
|
|
||||||
key: xray-geodat-
|
|
||||||
|
|
||||||
- name: Check Assets Existence
|
|
||||||
id: check-assets
|
|
||||||
run: |
|
|
||||||
[ -d 'resources' ] || mkdir resources
|
|
||||||
LIST=('geoip.dat' 'geosite.dat')
|
|
||||||
for FILE_NAME in "${LIST[@]}"
|
|
||||||
do
|
|
||||||
echo -e "Checking ${FILE_NAME}..."
|
|
||||||
if [ -s "./resources/${FILE_NAME}" ]; then
|
|
||||||
echo -e "${FILE_NAME} exists."
|
|
||||||
else
|
|
||||||
echo -e "${FILE_NAME} does not exist."
|
|
||||||
echo "missing=true" >> $GITHUB_OUTPUT
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Sleep for 90 seconds if Assets Missing
|
|
||||||
if: steps.check-assets.outputs.missing == 'true'
|
|
||||||
run: sleep 90
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: check-assets
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
strategy:
|
strategy:
|
||||||
@ -82,7 +51,7 @@ jobs:
|
|||||||
GOSDK=$(go env GOROOT)
|
GOSDK=$(go env GOROOT)
|
||||||
rm -r $GOSDK/*
|
rm -r $GOSDK/*
|
||||||
cd $GOSDK
|
cd $GOSDK
|
||||||
curl -O -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" https://github.com/XTLS/go-win7/releases/latest/download/go-for-win7-linux-amd64.zip
|
curl -O -L https://github.com/XTLS/go-win7/releases/latest/download/go-for-win7-linux-amd64.zip
|
||||||
unzip ./go-for-win7-linux-amd64.zip -d $GOSDK
|
unzip ./go-for-win7-linux-amd64.zip -d $GOSDK
|
||||||
rm ./go-for-win7-linux-amd64.zip
|
rm ./go-for-win7-linux-amd64.zip
|
||||||
|
|
||||||
|
64
.github/workflows/release.yml
vendored
64
.github/workflows/release.yml
vendored
@ -9,53 +9,7 @@ on:
|
|||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-assets:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Restore Geodat Cache
|
|
||||||
uses: actions/cache/restore@v4
|
|
||||||
with:
|
|
||||||
path: resources
|
|
||||||
key: xray-geodat-
|
|
||||||
|
|
||||||
- name: Check Assets Existence
|
|
||||||
id: check-assets
|
|
||||||
run: |
|
|
||||||
[ -d 'resources' ] || mkdir resources
|
|
||||||
LIST=('geoip.dat' 'geosite.dat')
|
|
||||||
for FILE_NAME in "${LIST[@]}"
|
|
||||||
do
|
|
||||||
echo -e "Checking ${FILE_NAME}..."
|
|
||||||
if [ -s "./resources/${FILE_NAME}" ]; then
|
|
||||||
echo -e "${FILE_NAME} exists."
|
|
||||||
else
|
|
||||||
echo -e "${FILE_NAME} does not exist."
|
|
||||||
echo "missing=true" >> $GITHUB_OUTPUT
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Trigger Asset Update Workflow if Assets Missing
|
|
||||||
if: steps.check-assets.outputs.missing == 'true'
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
script: |
|
|
||||||
const { owner, repo } = context.repo;
|
|
||||||
await github.rest.actions.createWorkflowDispatch({
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
workflow_id: 'scheduled-assets-update.yml',
|
|
||||||
ref: context.ref
|
|
||||||
});
|
|
||||||
console.log('Triggered scheduled-assets-update.yml due to missing assets on branch:', context.ref);
|
|
||||||
|
|
||||||
- name: Sleep for 90 seconds if Assets Missing
|
|
||||||
if: steps.check-assets.outputs.missing == 'true'
|
|
||||||
run: sleep 90
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: check-assets
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
strategy:
|
strategy:
|
||||||
@ -88,11 +42,6 @@ jobs:
|
|||||||
- goos: android
|
- goos: android
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
# END Android ARM 8
|
# END Android ARM 8
|
||||||
# BEGIN Android AMD64
|
|
||||||
- goos: android
|
|
||||||
goarch: amd64
|
|
||||||
patch-assetname: android-amd64
|
|
||||||
# END Android AMD64
|
|
||||||
# Windows ARM
|
# Windows ARM
|
||||||
- goos: windows
|
- goos: windows
|
||||||
goarch: arm64
|
goarch: arm64
|
||||||
@ -155,19 +104,6 @@ jobs:
|
|||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up NDK
|
|
||||||
if: matrix.goos == 'android'
|
|
||||||
run: |
|
|
||||||
wget -qO android-ndk.zip https://dl.google.com/android/repository/android-ndk-r28b-linux.zip
|
|
||||||
unzip android-ndk.zip
|
|
||||||
rm android-ndk.zip
|
|
||||||
declare -A arches=(
|
|
||||||
["amd64"]="x86_64-linux-android24-clang"
|
|
||||||
["arm64"]="aarch64-linux-android24-clang"
|
|
||||||
)
|
|
||||||
echo CC="$(realpath android-ndk-*/toolchains/llvm/prebuilt/linux-x86_64/bin)/${arches[${{ matrix.goarch }}]}" >> $GITHUB_ENV
|
|
||||||
echo CGO_ENABLED=1 >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Show workflow information
|
- name: Show workflow information
|
||||||
run: |
|
run: |
|
||||||
_NAME=${{ matrix.patch-assetname }}
|
_NAME=${{ matrix.patch-assetname }}
|
||||||
|
@ -9,7 +9,7 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
schedule:
|
schedule:
|
||||||
# Update GeoData on every day (22:30 UTC)
|
# Update GeoData on every day (22:30 UTC)
|
||||||
- cron: "30 22 * * *"
|
- cron: '30 22 * * *'
|
||||||
push:
|
push:
|
||||||
# Prevent triggering update request storm
|
# Prevent triggering update request storm
|
||||||
paths:
|
paths:
|
||||||
@ -45,12 +45,12 @@ jobs:
|
|||||||
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3,$4}'))
|
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3,$4}'))
|
||||||
FILE_NAME="${INFO[3]}.dat"
|
FILE_NAME="${INFO[3]}.dat"
|
||||||
echo -e "Verifying HASH key..."
|
echo -e "Verifying HASH key..."
|
||||||
HASH="$(curl -sL -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
|
HASH="$(curl -sL "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat.sha256sum" | awk -F ' ' '{print $1}')"
|
||||||
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
|
if [ -s "./resources/${FILE_NAME}" ] && [ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ]; then
|
||||||
continue
|
continue
|
||||||
else
|
else
|
||||||
echo -e "Downloading https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat..."
|
echo -e "Downloading https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat..."
|
||||||
curl -L -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat" -o ./resources/${FILE_NAME}
|
curl -L "https://raw.githubusercontent.com/${INFO[0]}/${INFO[1]}/release/${INFO[2]}.dat" -o ./resources/${FILE_NAME}
|
||||||
echo -e "Verifying HASH key..."
|
echo -e "Verifying HASH key..."
|
||||||
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
|
[ "$(sha256sum "./resources/${FILE_NAME}" | awk -F ' ' '{print $1}')" == "${HASH}" ] || { echo -e "The HASH key of ${FILE_NAME} does not match cloud one."; exit 1; }
|
||||||
echo "unhit=true" >> $GITHUB_OUTPUT
|
echo "unhit=true" >> $GITHUB_OUTPUT
|
||||||
|
29
.github/workflows/test.yml
vendored
29
.github/workflows/test.yml
vendored
@ -6,36 +6,7 @@ on:
|
|||||||
types: [opened, synchronize, reopened]
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-assets:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Restore Geodat Cache
|
|
||||||
uses: actions/cache/restore@v4
|
|
||||||
with:
|
|
||||||
path: resources
|
|
||||||
key: xray-geodat-
|
|
||||||
- name: Check Assets Existence
|
|
||||||
id: check-assets
|
|
||||||
run: |
|
|
||||||
[ -d 'resources' ] || mkdir resources
|
|
||||||
LIST=('geoip.dat' 'geosite.dat')
|
|
||||||
for FILE_NAME in "${LIST[@]}"
|
|
||||||
do
|
|
||||||
echo -e "Checking ${FILE_NAME}..."
|
|
||||||
if [ -s "./resources/${FILE_NAME}" ]; then
|
|
||||||
echo -e "${FILE_NAME} exists."
|
|
||||||
else
|
|
||||||
echo -e "${FILE_NAME} does not exist."
|
|
||||||
echo "missing=true" >> $GITHUB_OUTPUT
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
- name: Sleep for 90 seconds if Assets Missing
|
|
||||||
if: steps.check-assets.outputs.missing == 'true'
|
|
||||||
run: sleep 90
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
needs: check-assets
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
17
.gitignore
vendored
17
.gitignore
vendored
@ -14,18 +14,10 @@
|
|||||||
# Dependency directories (remove the comment below to include it)
|
# Dependency directories (remove the comment below to include it)
|
||||||
# vendor/
|
# vendor/
|
||||||
|
|
||||||
# macOS specific files
|
|
||||||
*.DS_Store
|
*.DS_Store
|
||||||
|
.idea
|
||||||
# IDE specific files
|
|
||||||
.idea/
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
# Archive files
|
|
||||||
*.zip
|
*.zip
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
|
||||||
# Binaries
|
|
||||||
xray
|
xray
|
||||||
xray_softfloat
|
xray_softfloat
|
||||||
mockgen
|
mockgen
|
||||||
@ -34,13 +26,8 @@ vprotogen
|
|||||||
errorgen
|
errorgen
|
||||||
!common/errors/errorgen/
|
!common/errors/errorgen/
|
||||||
*.dat
|
*.dat
|
||||||
|
.vscode
|
||||||
# Build assets
|
|
||||||
/build_assets
|
/build_assets
|
||||||
|
|
||||||
# Output from dlv test
|
# Output from dlv test
|
||||||
**/debug.*
|
**/debug.*
|
||||||
|
|
||||||
# Certificates
|
|
||||||
*.crt
|
|
||||||
*.key
|
|
||||||
|
19
README.md
19
README.md
@ -38,13 +38,12 @@
|
|||||||
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
|
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
|
||||||
- [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
|
- [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
|
||||||
- Web Panel - **WARNING: Please DO NOT USE plain HTTP panels like 3X-UI**, as they are believed to be bribed by Iran GFW for supporting plain HTTP by default and refused to change (https://github.com/XTLS/Xray-core/pull/3884#issuecomment-2439595331), which has already put many users' data security in danger in the past few years. **If you are already using 3X-UI, please switch to the following panels, which are verified to support HTTPS and SSH port forwarding only:**
|
- Web Panel - **WARNING: Please DO NOT USE plain HTTP panels like 3X-UI**, as they are believed to be bribed by Iran GFW for supporting plain HTTP by default and refused to change (https://github.com/XTLS/Xray-core/pull/3884#issuecomment-2439595331), which has already put many users' data security in danger in the past few years. **If you are already using 3X-UI, please switch to the following panels, which are verified to support HTTPS and SSH port forwarding only:**
|
||||||
- [Remnawave](https://github.com/remnawave/panel)
|
|
||||||
- [Marzban](https://github.com/Gozargah/Marzban)
|
- [Marzban](https://github.com/Gozargah/Marzban)
|
||||||
- [Xray-UI](https://github.com/qist/xray-ui)
|
- [Xray-UI](https://github.com/qist/xray-ui)
|
||||||
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
|
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
|
||||||
- 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)
|
||||||
- [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
|
- [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
|
||||||
- Magisk
|
- Magisk
|
||||||
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
|
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
|
||||||
@ -85,32 +84,28 @@
|
|||||||
- [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)
|
|
||||||
- iOS & macOS arm64
|
- iOS & macOS arm64
|
||||||
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
|
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
|
||||||
|
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
||||||
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
||||||
- [OneXray](https://github.com/OneXray/OneXray)
|
|
||||||
- macOS arm64 & x64
|
- macOS arm64 & x64
|
||||||
- [V2rayU](https://github.com/yanue/V2rayU)
|
- [V2rayU](https://github.com/yanue/V2rayU)
|
||||||
- [V2RayXS](https://github.com/tzmax/V2RayXS)
|
- [V2RayXS](https://github.com/tzmax/V2RayXS)
|
||||||
- [Furious](https://github.com/LorenEteval/Furious)
|
- [Furious](https://github.com/LorenEteval/Furious)
|
||||||
- [OneXray](https://github.com/OneXray/OneXray)
|
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
||||||
- 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)
|
||||||
- [GorzRay](https://github.com/ketetefid/GorzRay)
|
|
||||||
|
|
||||||
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
|
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
|
||||||
|
|
||||||
- iOS & macOS arm64
|
- iOS & macOS arm64
|
||||||
- [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)
|
|
||||||
- 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)
|
||||||
- Xray Wrapper
|
- Xray Wrapper
|
||||||
- [XTLS/libXray](https://github.com/XTLS/libXray)
|
- [XTLS/libXray](https://github.com/XTLS/libXray)
|
||||||
- [xtls-sdk](https://github.com/remnawave/xtls-sdk)
|
|
||||||
- [xtlsapi](https://github.com/hiddify/xtlsapi)
|
- [xtlsapi](https://github.com/hiddify/xtlsapi)
|
||||||
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
|
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
|
||||||
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
|
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
|
||||||
@ -118,17 +113,15 @@
|
|||||||
- [XrayR](https://github.com/XrayR-project/XrayR)
|
- [XrayR](https://github.com/XrayR-project/XrayR)
|
||||||
- [XrayR-release](https://github.com/XrayR-project/XrayR-release)
|
- [XrayR-release](https://github.com/XrayR-project/XrayR-release)
|
||||||
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
|
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
|
||||||
- Cores
|
- [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta)
|
||||||
- [Amnezia VPN](https://github.com/amnezia-vpn)
|
- [clashN](https://github.com/2dust/clashN)
|
||||||
- [mihomo](https://github.com/MetaCubeX/mihomo)
|
- [Clash Meta for Android](https://github.com/MetaCubeX/ClashMetaForAndroid)
|
||||||
- [sing-box](https://github.com/SagerNet/sing-box)
|
- [sing-box](https://github.com/SagerNet/sing-box)
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
[Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)
|
[Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)
|
||||||
|
|
||||||
[](https://deepwiki.com/XTLS/Xray-core)
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases).
|
- [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases).
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
)
|
)
|
||||||
@ -109,13 +108,3 @@ func (co *Outbound) Close() error {
|
|||||||
co.closed = true
|
co.closed = true
|
||||||
return co.listener.Close()
|
return co.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SenderSettings implements outbound.Handler.
|
|
||||||
func (co *Outbound) SenderSettings() *serial.TypedMessage {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProxySettings implements outbound.Handler.
|
|
||||||
func (co *Outbound) ProxySettings() *serial.TypedMessage {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -33,21 +33,23 @@ type cachedReader struct {
|
|||||||
cache buf.MultiBuffer
|
cache buf.MultiBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *cachedReader) Cache(b *buf.Buffer, deadline time.Duration) error {
|
func (r *cachedReader) Cache(b *buf.Buffer) {
|
||||||
mb, err := r.reader.ReadMultiBufferTimeout(deadline)
|
mb, _ := r.reader.ReadMultiBufferTimeout(time.Millisecond * 100)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r.Lock()
|
r.Lock()
|
||||||
if !mb.IsEmpty() {
|
if !mb.IsEmpty() {
|
||||||
r.cache, _ = buf.MergeMulti(r.cache, mb)
|
r.cache, _ = buf.MergeMulti(r.cache, mb)
|
||||||
}
|
}
|
||||||
|
cacheLen := r.cache.Len()
|
||||||
|
if cacheLen <= b.Cap() {
|
||||||
b.Clear()
|
b.Clear()
|
||||||
rawBytes := b.Extend(min(r.cache.Len(), b.Cap()))
|
} else {
|
||||||
|
b.Release()
|
||||||
|
*b = *buf.NewWithSize(cacheLen)
|
||||||
|
}
|
||||||
|
rawBytes := b.Extend(cacheLen)
|
||||||
n := r.cache.Copy(rawBytes)
|
n := r.cache.Copy(rawBytes)
|
||||||
b.Resize(0, int32(n))
|
b.Resize(0, int32(n))
|
||||||
r.Unlock()
|
r.Unlock()
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *cachedReader) readInternal() buf.MultiBuffer {
|
func (r *cachedReader) readInternal() buf.MultiBuffer {
|
||||||
@ -96,6 +98,7 @@ type DefaultDispatcher struct {
|
|||||||
router routing.Router
|
router routing.Router
|
||||||
policy policy.Manager
|
policy policy.Manager
|
||||||
stats stats.Manager
|
stats stats.Manager
|
||||||
|
dns dns.Client
|
||||||
fdns dns.FakeDNSEngine
|
fdns dns.FakeDNSEngine
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +109,7 @@ func init() {
|
|||||||
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||||
d.fdns = fdns
|
d.fdns = fdns
|
||||||
})
|
})
|
||||||
return d.Init(config.(*Config), om, router, pm, sm)
|
return d.Init(config.(*Config), om, router, pm, sm, dc)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -115,11 +118,12 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes DefaultDispatcher.
|
// Init initializes DefaultDispatcher.
|
||||||
func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager) error {
|
func (d *DefaultDispatcher) Init(config *Config, om outbound.Manager, router routing.Router, pm policy.Manager, sm stats.Manager, dns dns.Client) error {
|
||||||
d.ohm = om
|
d.ohm = om
|
||||||
d.router = router
|
d.router = router
|
||||||
d.policy = pm
|
d.policy = pm
|
||||||
d.stats = sm
|
d.stats = sm
|
||||||
|
d.dns = dns
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +355,7 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
|
|||||||
}
|
}
|
||||||
|
|
||||||
func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, network net.Network) (SniffResult, error) {
|
func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, network net.Network) (SniffResult, error) {
|
||||||
payload := buf.NewWithSize(32767)
|
payload := buf.New()
|
||||||
defer payload.Release()
|
defer payload.Release()
|
||||||
|
|
||||||
sniffer := NewSniffer(ctx)
|
sniffer := NewSniffer(ctx)
|
||||||
@ -363,36 +367,26 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
|
|||||||
}
|
}
|
||||||
|
|
||||||
contentResult, contentErr := func() (SniffResult, error) {
|
contentResult, contentErr := func() (SniffResult, error) {
|
||||||
cacheDeadline := 200 * time.Millisecond
|
|
||||||
totalAttempt := 0
|
totalAttempt := 0
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return nil, ctx.Err()
|
return nil, ctx.Err()
|
||||||
default:
|
default:
|
||||||
cachingStartingTimeStamp := time.Now()
|
totalAttempt++
|
||||||
err := cReader.Cache(payload, cacheDeadline)
|
if totalAttempt > 2 {
|
||||||
if err != nil {
|
return nil, errSniffingTimeout
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
cachingTimeElapsed := time.Since(cachingStartingTimeStamp)
|
|
||||||
cacheDeadline -= cachingTimeElapsed
|
|
||||||
|
|
||||||
|
cReader.Cache(payload)
|
||||||
if !payload.IsEmpty() {
|
if !payload.IsEmpty() {
|
||||||
result, err := sniffer.Sniff(ctx, payload.Bytes(), network)
|
result, err := sniffer.Sniff(ctx, payload.Bytes(), network)
|
||||||
switch err {
|
if err != common.ErrNoClue {
|
||||||
case common.ErrNoClue: // No Clue: protocol not matches, and sniffer cannot determine whether there will be a match or not
|
|
||||||
totalAttempt++
|
|
||||||
case protocol.ErrProtoNeedMoreData: // Protocol Need More Data: protocol matches, but need more data to complete sniffing
|
|
||||||
// in this case, do not add totalAttempt(allow to read until timeout)
|
|
||||||
default:
|
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
totalAttempt++
|
|
||||||
}
|
}
|
||||||
if totalAttempt >= 2 || cacheDeadline <= 0 {
|
if payload.IsFull() {
|
||||||
return nil, errSniffingTimeout
|
return nil, errUnknownContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -408,6 +402,18 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
|
|||||||
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
|
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
|
||||||
outbounds := session.OutboundsFromContext(ctx)
|
outbounds := session.OutboundsFromContext(ctx)
|
||||||
ob := outbounds[len(outbounds)-1]
|
ob := outbounds[len(outbounds)-1]
|
||||||
|
if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() {
|
||||||
|
proxied := hosts.LookupHosts(ob.Target.String())
|
||||||
|
if proxied != nil {
|
||||||
|
ro := ob.RouteTarget == destination
|
||||||
|
destination.Address = *proxied
|
||||||
|
if ro {
|
||||||
|
ob.RouteTarget = destination
|
||||||
|
} else {
|
||||||
|
ob.Target = destination
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var handler outbound.Handler
|
var handler outbound.Handler
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"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"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
|
||||||
"github.com/xtls/xray-core/common/protocol/bittorrent"
|
"github.com/xtls/xray-core/common/protocol/bittorrent"
|
||||||
"github.com/xtls/xray-core/common/protocol/http"
|
"github.com/xtls/xray-core/common/protocol/http"
|
||||||
"github.com/xtls/xray-core/common/protocol/quic"
|
"github.com/xtls/xray-core/common/protocol/quic"
|
||||||
@ -59,17 +58,14 @@ var errUnknownContent = errors.New("unknown content")
|
|||||||
func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
|
func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
|
||||||
var pendingSniffer []protocolSnifferWithMetadata
|
var pendingSniffer []protocolSnifferWithMetadata
|
||||||
for _, si := range s.sniffer {
|
for _, si := range s.sniffer {
|
||||||
protocolSniffer := si.protocolSniffer
|
s := si.protocolSniffer
|
||||||
if si.metadataSniffer || si.network != network {
|
if si.metadataSniffer || si.network != network {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
result, err := protocolSniffer(c, payload)
|
result, err := s(c, payload)
|
||||||
if err == common.ErrNoClue {
|
if err == common.ErrNoClue {
|
||||||
pendingSniffer = append(pendingSniffer, si)
|
pendingSniffer = append(pendingSniffer, si)
|
||||||
continue
|
continue
|
||||||
} else if err == protocol.ErrProtoNeedMoreData { // Sniffer protocol matched, but need more data to complete sniffing
|
|
||||||
s.sniffer = []protocolSnifferWithMetadata{si}
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil && result != nil {
|
if err == nil && result != nil {
|
||||||
|
@ -1,188 +0,0 @@
|
|||||||
package dns
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
go_errors "errors"
|
|
||||||
"github.com/xtls/xray-core/common"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/signal/pubsub"
|
|
||||||
"github.com/xtls/xray-core/common/task"
|
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type CacheController struct {
|
|
||||||
sync.RWMutex
|
|
||||||
ips map[string]*record
|
|
||||||
pub *pubsub.Service
|
|
||||||
cacheCleanup *task.Periodic
|
|
||||||
name string
|
|
||||||
disableCache bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCacheController(name string, disableCache bool) *CacheController {
|
|
||||||
c := &CacheController{
|
|
||||||
name: name,
|
|
||||||
disableCache: disableCache,
|
|
||||||
ips: make(map[string]*record),
|
|
||||||
pub: pubsub.NewService(),
|
|
||||||
}
|
|
||||||
|
|
||||||
c.cacheCleanup = &task.Periodic{
|
|
||||||
Interval: time.Minute,
|
|
||||||
Execute: c.CacheCleanup,
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// CacheCleanup clears expired items from cache
|
|
||||||
func (c *CacheController) CacheCleanup() error {
|
|
||||||
now := time.Now()
|
|
||||||
c.Lock()
|
|
||||||
defer c.Unlock()
|
|
||||||
|
|
||||||
if len(c.ips) == 0 {
|
|
||||||
return errors.New("nothing to do. stopping...")
|
|
||||||
}
|
|
||||||
|
|
||||||
for domain, record := range c.ips {
|
|
||||||
if record.A != nil && record.A.Expire.Before(now) {
|
|
||||||
record.A = nil
|
|
||||||
}
|
|
||||||
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
|
|
||||||
record.AAAA = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if record.A == nil && record.AAAA == nil {
|
|
||||||
errors.LogDebug(context.Background(), c.name, "cache cleanup ", domain)
|
|
||||||
delete(c.ips, domain)
|
|
||||||
} else {
|
|
||||||
c.ips[domain] = record
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.ips) == 0 {
|
|
||||||
c.ips = make(map[string]*record)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CacheController) updateIP(req *dnsRequest, ipRec *IPRecord) {
|
|
||||||
elapsed := time.Since(req.start)
|
|
||||||
|
|
||||||
c.Lock()
|
|
||||||
rec, found := c.ips[req.domain]
|
|
||||||
if !found {
|
|
||||||
rec = &record{}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch req.reqType {
|
|
||||||
case dnsmessage.TypeA:
|
|
||||||
rec.A = ipRec
|
|
||||||
case dnsmessage.TypeAAAA:
|
|
||||||
rec.AAAA = ipRec
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.LogInfo(context.Background(), c.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
|
|
||||||
c.ips[req.domain] = rec
|
|
||||||
|
|
||||||
switch req.reqType {
|
|
||||||
case dnsmessage.TypeA:
|
|
||||||
c.pub.Publish(req.domain+"4", nil)
|
|
||||||
if !c.disableCache {
|
|
||||||
_, _, err := rec.AAAA.getIPs()
|
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
|
||||||
c.pub.Publish(req.domain+"6", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case dnsmessage.TypeAAAA:
|
|
||||||
c.pub.Publish(req.domain+"6", nil)
|
|
||||||
if !c.disableCache {
|
|
||||||
_, _, err := rec.A.getIPs()
|
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
|
||||||
c.pub.Publish(req.domain+"4", nil)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Unlock()
|
|
||||||
common.Must(c.cacheCleanup.Start())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CacheController) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
|
||||||
c.RLock()
|
|
||||||
record, found := c.ips[domain]
|
|
||||||
c.RUnlock()
|
|
||||||
|
|
||||||
if !found {
|
|
||||||
return nil, 0, errRecordNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
var errs []error
|
|
||||||
var allIPs []net.IP
|
|
||||||
var rTTL uint32 = dns_feature.DefaultTTL
|
|
||||||
|
|
||||||
mergeReq := option.IPv4Enable && option.IPv6Enable
|
|
||||||
|
|
||||||
if option.IPv4Enable {
|
|
||||||
ips, ttl, err := record.A.getIPs()
|
|
||||||
if !mergeReq || go_errors.Is(err, errRecordNotFound) {
|
|
||||||
return ips, ttl, err
|
|
||||||
}
|
|
||||||
if ttl < rTTL {
|
|
||||||
rTTL = ttl
|
|
||||||
}
|
|
||||||
if len(ips) > 0 {
|
|
||||||
allIPs = append(allIPs, ips...)
|
|
||||||
} else {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if option.IPv6Enable {
|
|
||||||
ips, ttl, err := record.AAAA.getIPs()
|
|
||||||
if !mergeReq || go_errors.Is(err, errRecordNotFound) {
|
|
||||||
return ips, ttl, err
|
|
||||||
}
|
|
||||||
if ttl < rTTL {
|
|
||||||
rTTL = ttl
|
|
||||||
}
|
|
||||||
if len(ips) > 0 {
|
|
||||||
allIPs = append(allIPs, ips...)
|
|
||||||
} else {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(allIPs) > 0 {
|
|
||||||
return allIPs, rTTL, nil
|
|
||||||
}
|
|
||||||
if go_errors.Is(errs[0], errs[1]) {
|
|
||||||
return nil, rTTL, errs[0]
|
|
||||||
}
|
|
||||||
return nil, rTTL, errors.Combine(errs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *CacheController) registerSubscribers(domain string, option dns_feature.IPOption) (sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
|
|
||||||
// ipv4 and ipv6 belong to different subscription groups
|
|
||||||
if option.IPv4Enable {
|
|
||||||
sub4 = c.pub.Subscribe(domain + "4")
|
|
||||||
}
|
|
||||||
if option.IPv6Enable {
|
|
||||||
sub6 = c.pub.Subscribe(domain + "6")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func closeSubscribers(sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
|
|
||||||
if sub4 != nil {
|
|
||||||
sub4.Close()
|
|
||||||
}
|
|
||||||
if sub6 != nil {
|
|
||||||
sub6.Close()
|
|
||||||
}
|
|
||||||
}
|
|
@ -80,7 +80,6 @@ const (
|
|||||||
QueryStrategy_USE_IP QueryStrategy = 0
|
QueryStrategy_USE_IP QueryStrategy = 0
|
||||||
QueryStrategy_USE_IP4 QueryStrategy = 1
|
QueryStrategy_USE_IP4 QueryStrategy = 1
|
||||||
QueryStrategy_USE_IP6 QueryStrategy = 2
|
QueryStrategy_USE_IP6 QueryStrategy = 2
|
||||||
QueryStrategy_USE_SYS QueryStrategy = 3
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for QueryStrategy.
|
// Enum value maps for QueryStrategy.
|
||||||
@ -89,13 +88,11 @@ var (
|
|||||||
0: "USE_IP",
|
0: "USE_IP",
|
||||||
1: "USE_IP4",
|
1: "USE_IP4",
|
||||||
2: "USE_IP6",
|
2: "USE_IP6",
|
||||||
3: "USE_SYS",
|
|
||||||
}
|
}
|
||||||
QueryStrategy_value = map[string]int32{
|
QueryStrategy_value = map[string]int32{
|
||||||
"USE_IP": 0,
|
"USE_IP": 0,
|
||||||
"USE_IP4": 1,
|
"USE_IP4": 1,
|
||||||
"USE_IP6": 2,
|
"USE_IP6": 2,
|
||||||
"USE_SYS": 3,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -135,16 +132,9 @@ type NameServer struct {
|
|||||||
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
|
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"`
|
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
|
||||||
PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
|
PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
|
||||||
ExpectedGeoip []*router.GeoIP `protobuf:"bytes,3,rep,name=expected_geoip,json=expectedGeoip,proto3" json:"expected_geoip,omitempty"`
|
Geoip []*router.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
|
||||||
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
|
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
|
||||||
QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
||||||
ActPrior bool `protobuf:"varint,8,opt,name=actPrior,proto3" json:"actPrior,omitempty"`
|
|
||||||
Tag string `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
|
|
||||||
TimeoutMs uint64 `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
|
|
||||||
DisableCache bool `protobuf:"varint,11,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
|
|
||||||
FinalQuery bool `protobuf:"varint,12,opt,name=finalQuery,proto3" json:"finalQuery,omitempty"`
|
|
||||||
UnexpectedGeoip []*router.GeoIP `protobuf:"bytes,13,rep,name=unexpected_geoip,json=unexpectedGeoip,proto3" json:"unexpected_geoip,omitempty"`
|
|
||||||
ActUnprior bool `protobuf:"varint,14,opt,name=actUnprior,proto3" json:"actUnprior,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) Reset() {
|
func (x *NameServer) Reset() {
|
||||||
@ -205,9 +195,9 @@ func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
|
func (x *NameServer) GetGeoip() []*router.GeoIP {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.ExpectedGeoip
|
return x.Geoip
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -226,55 +216,6 @@ func (x *NameServer) GetQueryStrategy() QueryStrategy {
|
|||||||
return QueryStrategy_USE_IP
|
return QueryStrategy_USE_IP
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetActPrior() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.ActPrior
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetTag() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Tag
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetTimeoutMs() uint64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.TimeoutMs
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetDisableCache() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.DisableCache
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetFinalQuery() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.FinalQuery
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetUnexpectedGeoip() []*router.GeoIP {
|
|
||||||
if x != nil {
|
|
||||||
return x.UnexpectedGeoip
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *NameServer) GetActUnprior() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.ActUnprior
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -567,7 +508,7 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
|||||||
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
||||||
0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb6, 0x06, 0x0a, 0x0a,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb2, 0x04, 0x0a, 0x0a,
|
||||||
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
|
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
|
||||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
||||||
@ -581,92 +522,75 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
|||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65,
|
||||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44,
|
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a,
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a,
|
||||||
0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x65,
|
0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69,
|
||||||
0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
|
0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||||
0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52,
|
||||||
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
|
0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
|
||||||
0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69,
|
0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
|
||||||
0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61,
|
||||||
0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e,
|
0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
|
||||||
0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
|
0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52,
|
||||||
0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
|
0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74,
|
||||||
0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73,
|
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65,
|
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79,
|
||||||
0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72,
|
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f,
|
||||||
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x74,
|
0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79,
|
||||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x74,
|
0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x09, 0x20, 0x01,
|
0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61,
|
||||||
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f,
|
0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||||
0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67,
|
||||||
0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73,
|
0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
||||||
0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6e,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||||
0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66,
|
0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65,
|
||||||
0x69, 0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x41, 0x0a, 0x10, 0x75, 0x6e, 0x65,
|
0x22, 0x9c, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x6e,
|
||||||
0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0d, 0x20,
|
0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e,
|
||||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65,
|
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65,
|
||||||
0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a,
|
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||||
0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08,
|
0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||||
0x52, 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x1a, 0x5e, 0x0a, 0x0e,
|
0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f,
|
||||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34,
|
0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61,
|
0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61,
|
||||||
0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
|
0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
|
||||||
0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02,
|
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c,
|
0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08,
|
||||||
0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x42,
|
||||||
0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04,
|
0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x73, 0x69, 0x7a, 0x65, 0x22, 0x9c, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74,
|
||||||
0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05,
|
0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
|
||||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c,
|
||||||
0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a,
|
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x73,
|
||||||
0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
|
0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a, 0x16,
|
||||||
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63,
|
0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49,
|
||||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69,
|
0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x64, 0x69,
|
||||||
0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e,
|
0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e,
|
0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70,
|
||||||
0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52,
|
0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
|
0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e,
|
||||||
0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22,
|
0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67,
|
||||||
0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08,
|
0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f,
|
||||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63,
|
0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61,
|
||||||
0x68, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61,
|
0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02,
|
||||||
0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
|
0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f,
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
|
0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
|
0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a,
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e,
|
||||||
0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52,
|
0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12,
|
||||||
0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b,
|
||||||
0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62,
|
0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52,
|
||||||
0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08,
|
0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
|
||||||
0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
||||||
0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73,
|
0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01,
|
||||||
0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
|
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x42, 0x46, 0x0a,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e,
|
||||||
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63,
|
0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||||
0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16,
|
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61,
|
||||||
0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03,
|
0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
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 (
|
||||||
@ -697,20 +621,19 @@ var file_app_dns_config_proto_goTypes = []any{
|
|||||||
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
|
7, // 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
|
4, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
|
||||||
8, // 2: xray.app.dns.NameServer.expected_geoip:type_name -> xray.app.router.GeoIP
|
8, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.app.router.GeoIP
|
||||||
5, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
|
5, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
|
||||||
1, // 4: 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
|
||||||
8, // 5: xray.app.dns.NameServer.unexpected_geoip:type_name -> xray.app.router.GeoIP
|
2, // 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
|
6, // 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
|
1, // 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
|
0, // 8: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
|
||||||
0, // 9: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
|
0, // 9: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
|
||||||
0, // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
|
10, // [10:10] is the sub-list for method output_type
|
||||||
11, // [11:11] is the sub-list for method output_type
|
10, // [10:10] is the sub-list for method input_type
|
||||||
11, // [11:11] is the sub-list for method input_type
|
10, // [10:10] is the sub-list for extension type_name
|
||||||
11, // [11:11] is the sub-list for extension type_name
|
10, // [10:10] is the sub-list for extension extendee
|
||||||
11, // [11:11] is the sub-list for extension extendee
|
0, // [0:10] is the sub-list for field type_name
|
||||||
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() }
|
||||||
|
@ -25,16 +25,9 @@ message NameServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repeated PriorityDomain prioritized_domain = 2;
|
repeated PriorityDomain prioritized_domain = 2;
|
||||||
repeated xray.app.router.GeoIP expected_geoip = 3;
|
repeated xray.app.router.GeoIP geoip = 3;
|
||||||
repeated OriginalRule original_rules = 4;
|
repeated OriginalRule original_rules = 4;
|
||||||
QueryStrategy query_strategy = 7;
|
QueryStrategy query_strategy = 7;
|
||||||
bool actPrior = 8;
|
|
||||||
string tag = 9;
|
|
||||||
uint64 timeoutMs = 10;
|
|
||||||
bool disableCache = 11;
|
|
||||||
bool finalQuery = 12;
|
|
||||||
repeated xray.app.router.GeoIP unexpected_geoip = 13;
|
|
||||||
bool actUnprior = 14;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DomainMatchingType {
|
enum DomainMatchingType {
|
||||||
@ -48,7 +41,6 @@ enum QueryStrategy {
|
|||||||
USE_IP = 0;
|
USE_IP = 0;
|
||||||
USE_IP4 = 1;
|
USE_IP4 = 1;
|
||||||
USE_IP6 = 2;
|
USE_IP6 = 2;
|
||||||
USE_SYS = 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
|
184
app/dns/dns.go
184
app/dns/dns.go
@ -3,12 +3,11 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
go_errors "errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"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/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@ -20,6 +19,8 @@ import (
|
|||||||
// DNS is a DNS rely server.
|
// DNS is a DNS rely server.
|
||||||
type DNS struct {
|
type DNS struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
tag string
|
||||||
|
disableCache bool
|
||||||
disableFallback bool
|
disableFallback bool
|
||||||
disableFallbackIfMatch bool
|
disableFallbackIfMatch bool
|
||||||
ipOption *dns.IPOption
|
ipOption *dns.IPOption
|
||||||
@ -28,7 +29,6 @@ type DNS struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
domainMatcher strmatcher.IndexMatcher
|
domainMatcher strmatcher.IndexMatcher
|
||||||
matcherInfos []*DomainMatcherInfo
|
matcherInfos []*DomainMatcherInfo
|
||||||
checkSystem bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
|
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
|
||||||
@ -39,6 +39,13 @@ type DomainMatcherInfo struct {
|
|||||||
|
|
||||||
// New creates a new DNS server with given configuration.
|
// New creates a new DNS server with given configuration.
|
||||||
func New(ctx context.Context, config *Config) (*DNS, error) {
|
func New(ctx context.Context, config *Config) (*DNS, error) {
|
||||||
|
var tag string
|
||||||
|
if len(config.Tag) > 0 {
|
||||||
|
tag = config.Tag
|
||||||
|
} else {
|
||||||
|
tag = generateRandomTag()
|
||||||
|
}
|
||||||
|
|
||||||
var clientIP net.IP
|
var clientIP net.IP
|
||||||
switch len(config.ClientIp) {
|
switch len(config.ClientIp) {
|
||||||
case 0, net.IPv4len, net.IPv6len:
|
case 0, net.IPv4len, net.IPv6len:
|
||||||
@ -47,36 +54,26 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
return nil, errors.New("unexpected client IP length ", len(config.ClientIp))
|
return nil, errors.New("unexpected client IP length ", len(config.ClientIp))
|
||||||
}
|
}
|
||||||
|
|
||||||
var ipOption dns.IPOption
|
var ipOption *dns.IPOption
|
||||||
checkSystem := false
|
|
||||||
switch config.QueryStrategy {
|
switch config.QueryStrategy {
|
||||||
case QueryStrategy_USE_IP:
|
case QueryStrategy_USE_IP:
|
||||||
ipOption = dns.IPOption{
|
ipOption = &dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
}
|
}
|
||||||
case QueryStrategy_USE_SYS:
|
|
||||||
ipOption = dns.IPOption{
|
|
||||||
IPv4Enable: true,
|
|
||||||
IPv6Enable: true,
|
|
||||||
FakeEnable: false,
|
|
||||||
}
|
|
||||||
checkSystem = true
|
|
||||||
case QueryStrategy_USE_IP4:
|
case QueryStrategy_USE_IP4:
|
||||||
ipOption = dns.IPOption{
|
ipOption = &dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: false,
|
IPv6Enable: false,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
}
|
}
|
||||||
case QueryStrategy_USE_IP6:
|
case QueryStrategy_USE_IP6:
|
||||||
ipOption = dns.IPOption{
|
ipOption = &dns.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: false,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
return nil, errors.New("unexpected query strategy ", config.QueryStrategy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hosts, err := NewStaticHosts(config.StaticHosts)
|
hosts, err := NewStaticHosts(config.StaticHosts)
|
||||||
@ -84,14 +81,8 @@ 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
|
clients := []*Client{}
|
||||||
domainRuleCount := 0
|
domainRuleCount := 0
|
||||||
|
|
||||||
var defaultTag = config.Tag
|
|
||||||
if len(config.Tag) == 0 {
|
|
||||||
defaultTag = generateRandomTag()
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ns := range config.NameServer {
|
for _, ns := range config.NameServer {
|
||||||
domainRuleCount += len(ns.PrioritizedDomain)
|
domainRuleCount += len(ns.PrioritizedDomain)
|
||||||
}
|
}
|
||||||
@ -99,6 +90,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
// MatcherInfos is ensured to cover the maximum index domainMatcher could return, where matcher's index starts from 1
|
// MatcherInfos is ensured to cover the maximum index domainMatcher could return, where matcher's index starts from 1
|
||||||
matcherInfos := make([]*DomainMatcherInfo, domainRuleCount+1)
|
matcherInfos := make([]*DomainMatcherInfo, domainRuleCount+1)
|
||||||
domainMatcher := &strmatcher.MatcherGroup{}
|
domainMatcher := &strmatcher.MatcherGroup{}
|
||||||
|
geoipContainer := router.GeoIPMatcherContainer{}
|
||||||
|
|
||||||
for _, ns := range config.NameServer {
|
for _, ns := range config.NameServer {
|
||||||
clientIdx := len(clients)
|
clientIdx := len(clients)
|
||||||
@ -116,19 +108,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
case net.IPv4len, net.IPv6len:
|
case net.IPv4len, net.IPv6len:
|
||||||
myClientIP = net.IP(ns.ClientIp)
|
myClientIP = net.IP(ns.ClientIp)
|
||||||
}
|
}
|
||||||
|
client, err := NewClient(ctx, ns, myClientIP, geoipContainer, &matcherInfos, updateDomain)
|
||||||
disableCache := config.DisableCache || ns.DisableCache
|
|
||||||
|
|
||||||
var tag = defaultTag
|
|
||||||
if len(ns.Tag) > 0 {
|
|
||||||
tag = ns.Tag
|
|
||||||
}
|
|
||||||
clientIPOption := ResolveIpOptionOverride(ns.QueryStrategy, ipOption)
|
|
||||||
if !clientIPOption.IPv4Enable && !clientIPOption.IPv6Enable {
|
|
||||||
return nil, errors.New("no QueryStrategy available for ", ns.Address)
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := NewClient(ctx, ns, myClientIP, disableCache, tag, clientIPOption, &matcherInfos, updateDomain)
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
@ -137,19 +117,20 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
|
|
||||||
// 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())
|
||||||
}
|
}
|
||||||
|
|
||||||
return &DNS{
|
return &DNS{
|
||||||
|
tag: tag,
|
||||||
hosts: hosts,
|
hosts: hosts,
|
||||||
ipOption: &ipOption,
|
ipOption: ipOption,
|
||||||
clients: clients,
|
clients: clients,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
domainMatcher: domainMatcher,
|
domainMatcher: domainMatcher,
|
||||||
matcherInfos: matcherInfos,
|
matcherInfos: matcherInfos,
|
||||||
|
disableCache: config.DisableCache,
|
||||||
disableFallback: config.DisableFallback,
|
disableFallback: config.DisableFallback,
|
||||||
disableFallbackIfMatch: config.DisableFallbackIfMatch,
|
disableFallbackIfMatch: config.DisableFallbackIfMatch,
|
||||||
checkSystem: checkSystem,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,96 +152,94 @@ func (s *DNS) Close() error {
|
|||||||
// IsOwnLink implements proxy.dns.ownLinkVerifier
|
// IsOwnLink implements proxy.dns.ownLinkVerifier
|
||||||
func (s *DNS) IsOwnLink(ctx context.Context) bool {
|
func (s *DNS) IsOwnLink(ctx context.Context) bool {
|
||||||
inbound := session.InboundFromContext(ctx)
|
inbound := session.InboundFromContext(ctx)
|
||||||
if inbound == nil {
|
return inbound != nil && inbound.Tag == s.tag
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, client := range s.clients {
|
|
||||||
if client.tag == inbound.Tag {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupIP implements dns.Client.
|
// LookupIP implements dns.Client.
|
||||||
func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
|
||||||
// Normalize the FQDN form query
|
|
||||||
domain = strings.TrimSuffix(domain, ".")
|
|
||||||
if domain == "" {
|
if domain == "" {
|
||||||
return nil, 0, errors.New("empty domain name")
|
return nil, errors.New("empty domain name")
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.checkSystem {
|
|
||||||
supportIPv4, supportIPv6 := checkSystemNetwork()
|
|
||||||
option.IPv4Enable = option.IPv4Enable && supportIPv4
|
|
||||||
option.IPv6Enable = option.IPv6Enable && supportIPv6
|
|
||||||
} else {
|
|
||||||
option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable
|
option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable
|
||||||
option.IPv6Enable = option.IPv6Enable && s.ipOption.IPv6Enable
|
option.IPv6Enable = option.IPv6Enable && s.ipOption.IPv6Enable
|
||||||
}
|
|
||||||
|
|
||||||
if !option.IPv4Enable && !option.IPv6Enable {
|
if !option.IPv4Enable && !option.IPv6Enable {
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
return nil, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize the FQDN form query
|
||||||
|
domain = strings.TrimSuffix(domain, ".")
|
||||||
|
|
||||||
// Static host lookup
|
// Static host lookup
|
||||||
switch addrs := s.hosts.Lookup(domain, option); {
|
switch addrs := s.hosts.Lookup(domain, option); {
|
||||||
case addrs == nil: // Domain not recorded in static host
|
case addrs == nil: // Domain not recorded in static host
|
||||||
break
|
break
|
||||||
case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
|
case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
return nil, dns.ErrEmptyResponse
|
||||||
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement
|
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Domain replacement
|
||||||
errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].Domain())
|
errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].Domain())
|
||||||
domain = addrs[0].Domain()
|
domain = addrs[0].Domain()
|
||||||
default: // Successfully found ip records in static host
|
default: // Successfully found ip records in static host
|
||||||
errors.LogInfo(s.ctx, "returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs)
|
errors.LogInfo(s.ctx, "returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs)
|
||||||
ips, err := toNetIP(addrs)
|
return toNetIP(addrs)
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
return ips, 10, nil // Hosts ttl is 10
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name servers lookup
|
// Name servers lookup
|
||||||
var errs []error
|
errs := []error{}
|
||||||
|
ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag})
|
||||||
for _, client := range s.sortClients(domain) {
|
for _, client := range s.sortClients(domain) {
|
||||||
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
||||||
errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
|
errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
ips, err := client.QueryIP(ctx, domain, option, s.disableCache)
|
||||||
ips, ttl, err := client.QueryIP(s.ctx, domain, option)
|
|
||||||
|
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
if ttl == 0 {
|
return ips, nil
|
||||||
ttl = 1
|
|
||||||
}
|
}
|
||||||
return ips, ttl, nil
|
if err != nil {
|
||||||
}
|
|
||||||
|
|
||||||
errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name())
|
errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name())
|
||||||
if err == nil {
|
|
||||||
err = dns.ErrEmptyResponse
|
|
||||||
}
|
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
if client.IsFinalQuery() {
|
// 5 for RcodeRefused in miekg/dns, hardcode to reduce binary size
|
||||||
break
|
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch && err != dns.ErrEmptyResponse && dns.RCodeFromError(err) != 5 {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errs) > 0 {
|
return nil, errors.New("returning nil for domain ", domain).Base(errors.Combine(errs...))
|
||||||
allErrs := errors.Combine(errs...)
|
|
||||||
err0 := errs[0]
|
|
||||||
if errors.AllEqual(err0, allErrs) {
|
|
||||||
if go_errors.Is(err0, dns.ErrEmptyResponse) {
|
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
|
||||||
}
|
}
|
||||||
return nil, 0, errors.New("returning nil for domain ", domain).Base(err0)
|
|
||||||
|
// LookupHosts implements dns.HostsLookup.
|
||||||
|
func (s *DNS) LookupHosts(domain string) *net.Address {
|
||||||
|
domain = strings.TrimSuffix(domain, ".")
|
||||||
|
if domain == "" {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
return nil, 0, errors.New("returning nil for domain ", domain).Base(allErrs)
|
// Normalize the FQDN form query
|
||||||
|
addrs := s.hosts.Lookup(domain, *s.ipOption)
|
||||||
|
if len(addrs) > 0 {
|
||||||
|
errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].String())
|
||||||
|
return &addrs[0]
|
||||||
}
|
}
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetIPOption implements ClientWithIPOption.
|
||||||
|
func (s *DNS) GetIPOption() *dns.IPOption {
|
||||||
|
return s.ipOption
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetQueryOption implements ClientWithIPOption.
|
||||||
|
func (s *DNS) SetQueryOption(isIPv4Enable, isIPv6Enable bool) {
|
||||||
|
s.ipOption.IPv4Enable = isIPv4Enable
|
||||||
|
s.ipOption.IPv6Enable = isIPv6Enable
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetFakeDNSOption implements ClientWithIPOption.
|
||||||
|
func (s *DNS) SetFakeDNSOption(isFakeEnable bool) {
|
||||||
|
s.ipOption.FakeEnable = isFakeEnable
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DNS) sortClients(domain string) []*Client {
|
func (s *DNS) sortClients(domain string) []*Client {
|
||||||
@ -271,11 +250,7 @@ func (s *DNS) sortClients(domain string) []*Client {
|
|||||||
|
|
||||||
// Priority domain matching
|
// Priority domain matching
|
||||||
hasMatch := false
|
hasMatch := false
|
||||||
MatchSlice := s.domainMatcher.Match(domain)
|
for _, match := range s.domainMatcher.Match(domain) {
|
||||||
sort.Slice(MatchSlice, func(i, j int) bool {
|
|
||||||
return MatchSlice[i] < MatchSlice[j]
|
|
||||||
})
|
|
||||||
for _, match := range MatchSlice {
|
|
||||||
info := s.matcherInfos[match]
|
info := s.matcherInfos[match]
|
||||||
client := s.clients[info.clientIdx]
|
client := s.clients[info.clientIdx]
|
||||||
domainRule := client.domains[info.domainRuleIdx]
|
domainRule := client.domains[info.domainRuleIdx]
|
||||||
@ -322,22 +297,3 @@ func init() {
|
|||||||
return New(ctx, config.(*Config))
|
return New(ctx, config.(*Config))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSystemNetwork() (supportIPv4 bool, supportIPv6 bool) {
|
|
||||||
conn4, err4 := net.Dial("udp4", "8.8.8.8:53")
|
|
||||||
if err4 != nil {
|
|
||||||
supportIPv4 = false
|
|
||||||
} else {
|
|
||||||
supportIPv4 = true
|
|
||||||
conn4.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
conn6, err6 := net.Dial("udp6", "[2001:4860:4860::8888]:53")
|
|
||||||
if err6 != nil {
|
|
||||||
supportIPv6 = false
|
|
||||||
} else {
|
|
||||||
supportIPv6 = true
|
|
||||||
conn6.Close()
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
@ -76,9 +76,6 @@ func (*staticHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
|
|||||||
case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA:
|
case q.Name == "notexist.google.com." && q.Qtype == dns.TypeAAAA:
|
||||||
ans.MsgHdr.Rcode = dns.RcodeNameError
|
ans.MsgHdr.Rcode = dns.RcodeNameError
|
||||||
|
|
||||||
case q.Name == "notexist.google.com." && q.Qtype == dns.TypeA:
|
|
||||||
ans.MsgHdr.Rcode = dns.RcodeNameError
|
|
||||||
|
|
||||||
case q.Name == "hostname." && q.Qtype == dns.TypeA:
|
case q.Name == "hostname." && q.Qtype == dns.TypeA:
|
||||||
rr, _ := dns.NewRR("hostname. IN A 127.0.0.1")
|
rr, _ := dns.NewRR("hostname. IN A 127.0.0.1")
|
||||||
ans.Answer = append(ans.Answer, rr)
|
ans.Answer = append(ans.Answer, rr)
|
||||||
@ -120,6 +117,7 @@ func TestUDPServerSubnet(t *testing.T) {
|
|||||||
Handler: &staticHandler{},
|
Handler: &staticHandler{},
|
||||||
UDPSize: 1200,
|
UDPSize: 1200,
|
||||||
}
|
}
|
||||||
|
|
||||||
go dnsServer.ListenAndServe()
|
go dnsServer.ListenAndServe()
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
@ -157,7 +155,7 @@ func TestUDPServerSubnet(t *testing.T) {
|
|||||||
|
|
||||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
|
|
||||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -218,7 +216,7 @@ func TestUDPServer(t *testing.T) {
|
|||||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -233,7 +231,7 @@ func TestUDPServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, _, err := client.LookupIP("facebook.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("facebook.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -248,7 +246,7 @@ func TestUDPServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
_, _, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{
|
_, err := client.LookupIP("notexist.google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -262,7 +260,7 @@ func TestUDPServer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, _, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("ipv4only.google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: false,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -278,7 +276,7 @@ func TestUDPServer(t *testing.T) {
|
|||||||
dnsServer.Shutdown()
|
dnsServer.Shutdown()
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -359,7 +357,7 @@ func TestPrioritizedDomain(t *testing.T) {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -425,7 +423,7 @@ func TestUDPServerIPv6(t *testing.T) {
|
|||||||
|
|
||||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
{
|
{
|
||||||
ips, _, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: false,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -494,7 +492,7 @@ func TestStaticHostDomain(t *testing.T) {
|
|||||||
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
client := v.GetFeature(feature_dns.ClientType()).(feature_dns.Client)
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, _, err := client.LookupIP("example.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("example.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -539,7 +537,7 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{
|
{
|
||||||
CountryCode: "local",
|
CountryCode: "local",
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
@ -563,7 +561,7 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{
|
{
|
||||||
CountryCode: "test",
|
CountryCode: "test",
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
@ -605,7 +603,7 @@ func TestIPMatch(t *testing.T) {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
{
|
{
|
||||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -667,7 +665,7 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
// Equivalent of dotless:localhost
|
// Equivalent of dotless:localhost
|
||||||
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
|
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // Will match localhost, localhost-a and localhost-b,
|
{ // Will match localhost, localhost-a and localhost-b,
|
||||||
CountryCode: "local",
|
CountryCode: "local",
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
@ -728,7 +726,7 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
{ // Will match dotless:
|
{ // Will match dotless:
|
||||||
ips, _, err := client.LookupIP("hostname", feature_dns.IPOption{
|
ips, err := client.LookupIP("hostname", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -743,7 +741,7 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match domain:local
|
{ // Will match domain:local
|
||||||
ips, _, err := client.LookupIP("hostname.local", feature_dns.IPOption{
|
ips, err := client.LookupIP("hostname.local", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -758,7 +756,7 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match static ip
|
{ // Will match static ip
|
||||||
ips, _, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
|
ips, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -773,7 +771,7 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match domain replacing
|
{ // Will match domain replacing
|
||||||
ips, _, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
|
ips, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -787,8 +785,8 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match dotless:localhost, but not expectedIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
|
{ // Will match dotless:localhost, but not expectIPs: 127.0.0.2, 127.0.0.3, then matches at dotless:
|
||||||
ips, _, err := client.LookupIP("localhost", feature_dns.IPOption{
|
ips, err := client.LookupIP("localhost", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -802,8 +800,8 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match dotless:localhost, and expectedIPs: 127.0.0.2, 127.0.0.3
|
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
||||||
ips, _, err := client.LookupIP("localhost-a", feature_dns.IPOption{
|
ips, err := client.LookupIP("localhost-a", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -817,8 +815,8 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match dotless:localhost, and expectedIPs: 127.0.0.2, 127.0.0.3
|
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
||||||
ips, _, err := client.LookupIP("localhost-b", feature_dns.IPOption{
|
ips, err := client.LookupIP("localhost-b", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -833,7 +831,7 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match dotless:
|
{ // Will match dotless:
|
||||||
ips, _, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
|
ips, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -897,7 +895,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
Domain: "google.com",
|
Domain: "google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // 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{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
||||||
@ -922,7 +920,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
Domain: "google.com",
|
Domain: "google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // 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{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
|
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
|
||||||
@ -946,7 +944,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
Domain: "api.google.com",
|
Domain: "api.google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // Will only match 8.8.7.7 (api.google.com)
|
{ // Will only match 8.8.7.7 (api.google.com)
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
|
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
|
||||||
@ -970,7 +968,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
Domain: "v2.api.google.com",
|
Domain: "v2.api.google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ExpectedGeoip: []*router.GeoIP{
|
Geoip: []*router.GeoIP{
|
||||||
{ // 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{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
|
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
|
||||||
@ -999,7 +997,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
{ // Will match server 1,2 and server 1 returns expected ip
|
{ // Will match server 1,2 and server 1 returns expected ip
|
||||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -1014,7 +1012,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
|
{ // Will match server 1,2 and server 1 returns unexpected ip, then server 2 returns expected one
|
||||||
ips, _, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: false,
|
IPv6Enable: false,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -1029,7 +1027,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match server 3,1,2 and server 3 returns expected one
|
{ // Will match server 3,1,2 and server 3 returns expected one
|
||||||
ips, _, err := client.LookupIP("api.google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("api.google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
@ -1044,7 +1042,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{ // Will match server 4,3,1,2 and server 4 returns expected one
|
{ // Will match server 4,3,1,2 and server 4 returns expected one
|
||||||
ips, _, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{
|
ips, err := client.LookupIP("v2.api.google.com", feature_dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
|
@ -32,30 +32,29 @@ type record struct {
|
|||||||
// IPRecord is a cacheable item for a resolved domain
|
// IPRecord is a cacheable item for a resolved domain
|
||||||
type IPRecord struct {
|
type IPRecord struct {
|
||||||
ReqID uint16
|
ReqID uint16
|
||||||
IP []net.IP
|
IP []net.Address
|
||||||
Expire time.Time
|
Expire time.Time
|
||||||
RCode dnsmessage.RCode
|
RCode dnsmessage.RCode
|
||||||
RawHeader *dnsmessage.Header
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *IPRecord) getIPs() ([]net.IP, uint32, error) {
|
func (r *IPRecord) getIPs() ([]net.Address, error) {
|
||||||
if r == nil {
|
if r == nil || r.Expire.Before(time.Now()) {
|
||||||
return nil, 0, errRecordNotFound
|
return nil, errRecordNotFound
|
||||||
}
|
}
|
||||||
untilExpire := time.Until(r.Expire)
|
|
||||||
if untilExpire <= 0 {
|
|
||||||
return nil, 0, errRecordNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
ttl := uint32(untilExpire/time.Second) + uint32(1)
|
|
||||||
if r.RCode != dnsmessage.RCodeSuccess {
|
if r.RCode != dnsmessage.RCodeSuccess {
|
||||||
return nil, ttl, dns_feature.RCodeError(r.RCode)
|
return nil, dns_feature.RCodeError(r.RCode)
|
||||||
}
|
}
|
||||||
if len(r.IP) == 0 {
|
return r.IP, nil
|
||||||
return nil, ttl, dns_feature.ErrEmptyResponse
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.IP, ttl, nil
|
func isNewer(baseRec *IPRecord, newRec *IPRecord) bool {
|
||||||
|
if newRec == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if baseRec == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return baseRec.Expire.Before(newRec.Expire)
|
||||||
}
|
}
|
||||||
|
|
||||||
var errRecordNotFound = errors.New("record not found")
|
var errRecordNotFound = errors.New("record not found")
|
||||||
@ -68,20 +67,11 @@ type dnsRequest struct {
|
|||||||
msg *dnsmessage.Message
|
msg *dnsmessage.Message
|
||||||
}
|
}
|
||||||
|
|
||||||
func genEDNS0Options(clientIP net.IP, padding int) *dnsmessage.Resource {
|
func genEDNS0Options(clientIP net.IP) *dnsmessage.Resource {
|
||||||
if len(clientIP) == 0 && padding == 0 {
|
if len(clientIP) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const EDNS0SUBNET = 0x8
|
|
||||||
const EDNS0PADDING = 0xc
|
|
||||||
|
|
||||||
opt := new(dnsmessage.Resource)
|
|
||||||
common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
|
|
||||||
body := dnsmessage.OPTResource{}
|
|
||||||
opt.Body = &body
|
|
||||||
|
|
||||||
if len(clientIP) != 0 {
|
|
||||||
var netmask int
|
var netmask int
|
||||||
var family uint16
|
var family uint16
|
||||||
|
|
||||||
@ -108,19 +98,18 @@ func genEDNS0Options(clientIP net.IP, padding int) *dnsmessage.Resource {
|
|||||||
b = append(b, ip[:needLength]...)
|
b = append(b, ip[:needLength]...)
|
||||||
}
|
}
|
||||||
|
|
||||||
body.Options = append(body.Options,
|
const EDNS0SUBNET = 0x08
|
||||||
dnsmessage.Option{
|
|
||||||
|
opt := new(dnsmessage.Resource)
|
||||||
|
common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
|
||||||
|
|
||||||
|
opt.Body = &dnsmessage.OPTResource{
|
||||||
|
Options: []dnsmessage.Option{
|
||||||
|
{
|
||||||
Code: EDNS0SUBNET,
|
Code: EDNS0SUBNET,
|
||||||
Data: b,
|
Data: b,
|
||||||
})
|
},
|
||||||
}
|
},
|
||||||
|
|
||||||
if padding != 0 {
|
|
||||||
body.Options = append(body.Options,
|
|
||||||
dnsmessage.Option{
|
|
||||||
Code: EDNS0PADDING,
|
|
||||||
Data: make([]byte, padding),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return opt
|
return opt
|
||||||
@ -192,8 +181,7 @@ func parseResponse(payload []byte) (*IPRecord, error) {
|
|||||||
ipRecord := &IPRecord{
|
ipRecord := &IPRecord{
|
||||||
ReqID: h.ID,
|
ReqID: h.ID,
|
||||||
RCode: h.RCode,
|
RCode: h.RCode,
|
||||||
Expire: now.Add(time.Second * dns_feature.DefaultTTL),
|
Expire: now.Add(time.Second * 600),
|
||||||
RawHeader: &h,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
L:
|
L:
|
||||||
@ -208,7 +196,7 @@ L:
|
|||||||
|
|
||||||
ttl := ah.TTL
|
ttl := ah.TTL
|
||||||
if ttl == 0 {
|
if ttl == 0 {
|
||||||
ttl = 1
|
ttl = 600
|
||||||
}
|
}
|
||||||
expire := now.Add(time.Duration(ttl) * time.Second)
|
expire := now.Add(time.Duration(ttl) * time.Second)
|
||||||
if ipRecord.Expire.After(expire) {
|
if ipRecord.Expire.After(expire) {
|
||||||
@ -222,17 +210,14 @@ L:
|
|||||||
errors.LogInfoInner(context.Background(), err, "failed to parse A record for domain: ", ah.Name)
|
errors.LogInfoInner(context.Background(), err, "failed to parse A record for domain: ", ah.Name)
|
||||||
break L
|
break L
|
||||||
}
|
}
|
||||||
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:]).IP())
|
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:]))
|
||||||
case dnsmessage.TypeAAAA:
|
case dnsmessage.TypeAAAA:
|
||||||
ans, err := parser.AAAAResource()
|
ans, err := parser.AAAAResource()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to parse AAAA record for domain: ", ah.Name)
|
errors.LogInfoInner(context.Background(), err, "failed to parse AAAA record for domain: ", ah.Name)
|
||||||
break L
|
break L
|
||||||
}
|
}
|
||||||
newIP := net.IPAddress(ans.AAAA[:]).IP()
|
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.AAAA[:]))
|
||||||
if len(newIP) == net.IPv6len {
|
|
||||||
ipRecord.IP = append(ipRecord.IP, newIP)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
if err := parser.SkipAnswer(); err != nil {
|
if err := parser.SkipAnswer(); err != nil {
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to skip answer")
|
errors.LogInfoInner(context.Background(), err, "failed to skip answer")
|
||||||
|
@ -51,7 +51,7 @@ func Test_parseResponse(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"empty",
|
"empty",
|
||||||
&IPRecord{0, []net.IP(nil), time.Time{}, dnsmessage.RCodeSuccess, nil},
|
&IPRecord{0, []net.Address(nil), time.Time{}, dnsmessage.RCodeSuccess},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -63,16 +63,15 @@ func Test_parseResponse(t *testing.T) {
|
|||||||
"a record",
|
"a record",
|
||||||
&IPRecord{
|
&IPRecord{
|
||||||
1,
|
1,
|
||||||
[]net.IP{net.ParseIP("8.8.8.8"), net.ParseIP("8.8.4.4")},
|
[]net.Address{net.ParseAddress("8.8.8.8"), net.ParseAddress("8.8.4.4")},
|
||||||
time.Time{},
|
time.Time{},
|
||||||
dnsmessage.RCodeSuccess,
|
dnsmessage.RCodeSuccess,
|
||||||
nil,
|
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"aaaa record",
|
"aaaa record",
|
||||||
&IPRecord{2, []net.IP{net.ParseIP("2001::123:8888"), net.ParseIP("2001::123:8844")}, time.Time{}, dnsmessage.RCodeSuccess, nil},
|
&IPRecord{2, []net.Address{net.ParseAddress("2001::123:8888"), net.ParseAddress("2001::123:8844")}, time.Time{}, dnsmessage.RCodeSuccess},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -85,9 +84,8 @@ func Test_parseResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if got != nil {
|
if got != nil {
|
||||||
// reset the time and RawHeader
|
// reset the time
|
||||||
got.Expire = time.Time{}
|
got.Expire = time.Time{}
|
||||||
got.RawHeader = nil
|
|
||||||
}
|
}
|
||||||
if cmp.Diff(got, tt.want) != "" {
|
if cmp.Diff(got, tt.want) != "" {
|
||||||
t.Error(cmp.Diff(got, tt.want))
|
t.Error(cmp.Diff(got, tt.want))
|
||||||
@ -156,7 +154,7 @@ func Test_genEDNS0Options(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
if got := genEDNS0Options(tt.args.clientIP, 0); got == nil {
|
if got := genEDNS0Options(tt.args.clientIP); got == nil {
|
||||||
t.Errorf("genEDNS0Options() = %v, want %v", got, tt.want)
|
t.Errorf("genEDNS0Options() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -2,6 +2,7 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"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/strmatcher"
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
@ -40,6 +41,8 @@ func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
|
|||||||
}
|
}
|
||||||
ips = append(ips, addr)
|
ips = append(ips, addr)
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return nil, errors.New("neither IP address nor proxied domain specified for domain: ", mapping.Domain).AtWarning()
|
||||||
}
|
}
|
||||||
|
|
||||||
sh.ips[id] = ips
|
sh.ips[id] = ips
|
||||||
@ -59,14 +62,9 @@ func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *StaticHosts) lookupInternal(domain string) []net.Address {
|
func (h *StaticHosts) lookupInternal(domain string) []net.Address {
|
||||||
ips := make([]net.Address, 0)
|
var ips []net.Address
|
||||||
found := false
|
|
||||||
for _, id := range h.matchers.Match(domain) {
|
for _, id := range h.matchers.Match(domain) {
|
||||||
ips = append(ips, h.ips[id]...)
|
ips = append(ips, h.ips[id]...)
|
||||||
found = true
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
return ips
|
return ips
|
||||||
}
|
}
|
||||||
@ -74,7 +72,7 @@ func (h *StaticHosts) lookupInternal(domain string) []net.Address {
|
|||||||
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address {
|
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address {
|
||||||
switch addrs := h.lookupInternal(domain); {
|
switch addrs := h.lookupInternal(domain); {
|
||||||
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
||||||
return addrs
|
return 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")
|
||||||
if maxDepth > 0 {
|
if maxDepth > 0 {
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/app/router"
|
"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/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
|
||||||
"github.com/xtls/xray-core/common/strmatcher"
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
@ -21,27 +20,22 @@ type Server interface {
|
|||||||
// Name of the Client.
|
// Name of the Client.
|
||||||
Name() string
|
Name() string
|
||||||
// QueryIP sends IP queries to its configured server.
|
// QueryIP sends IP queries to its configured server.
|
||||||
QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error)
|
QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns.IPOption, disableCache bool) ([]net.IP, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is the interface for DNS client.
|
// Client is the interface for DNS client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
server Server
|
server Server
|
||||||
|
clientIP net.IP
|
||||||
skipFallback bool
|
skipFallback bool
|
||||||
domains []string
|
domains []string
|
||||||
expectedIPs []*router.GeoIPMatcher
|
expectIPs []*router.GeoIPMatcher
|
||||||
unexpectedIPs []*router.GeoIPMatcher
|
|
||||||
actPrior bool
|
|
||||||
actUnprior bool
|
|
||||||
tag string
|
|
||||||
timeoutMs time.Duration
|
|
||||||
finalQuery bool
|
|
||||||
ipOption *dns.IPOption
|
|
||||||
checkSystem bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errExpectedIPNonMatch = errors.New("expectIPs not match")
|
||||||
|
|
||||||
// NewServer creates a name server object according to the network destination url.
|
// NewServer creates a name server object according to the network destination url.
|
||||||
func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, disableCache bool, clientIP net.IP) (Server, error) {
|
func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) (Server, error) {
|
||||||
if address := dest.Address; address.Family().IsDomain() {
|
if address := dest.Address; address.Family().IsDomain() {
|
||||||
u, err := url.Parse(address.Domain())
|
u, err := url.Parse(address.Domain())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -49,29 +43,26 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
|||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case strings.EqualFold(u.String(), "localhost"):
|
case strings.EqualFold(u.String(), "localhost"):
|
||||||
return NewLocalNameServer(), nil
|
return NewLocalNameServer(queryStrategy), nil
|
||||||
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
|
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
|
||||||
return NewDoHNameServer(u, dispatcher, false, disableCache, clientIP), nil
|
return NewDoHNameServer(u, queryStrategy, dispatcher, false), nil
|
||||||
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
|
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
|
||||||
return NewDoHNameServer(u, dispatcher, true, disableCache, clientIP), nil
|
return NewDoHNameServer(u, queryStrategy, dispatcher, true), nil
|
||||||
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
|
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
|
||||||
return NewDoHNameServer(u, nil, false, disableCache, clientIP), nil
|
return NewDoHNameServer(u, queryStrategy, nil, false), nil
|
||||||
case strings.EqualFold(u.Scheme, "h2c+local"): // DNS-over-HTTPS h2c Local mode
|
case strings.EqualFold(u.Scheme, "h2c+local"): // DNS-over-HTTPS h2c Local mode
|
||||||
return NewDoHNameServer(u, nil, true, disableCache, clientIP), nil
|
return NewDoHNameServer(u, queryStrategy, nil, true), nil
|
||||||
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
||||||
return NewQUICNameServer(u, disableCache, clientIP)
|
return NewQUICNameServer(u, queryStrategy)
|
||||||
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
|
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
|
||||||
return NewTCPNameServer(u, dispatcher, disableCache, clientIP)
|
return NewTCPNameServer(u, dispatcher, queryStrategy)
|
||||||
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
|
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
|
||||||
return NewTCPLocalNameServer(u, disableCache, clientIP)
|
return NewTCPLocalNameServer(u, queryStrategy)
|
||||||
case strings.EqualFold(u.String(), "fakedns"):
|
case strings.EqualFold(u.String(), "fakedns"):
|
||||||
var fd dns.FakeDNSEngine
|
var fd dns.FakeDNSEngine
|
||||||
err = core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||||
fd = fdns
|
fd = fdns
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return NewFakeDNSServer(fd), nil
|
return NewFakeDNSServer(fd), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -79,7 +70,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
|||||||
dest.Network = net.Network_UDP
|
dest.Network = net.Network_UDP
|
||||||
}
|
}
|
||||||
if dest.Network == net.Network_UDP { // UDP classic DNS mode
|
if dest.Network == net.Network_UDP { // UDP classic DNS mode
|
||||||
return NewClassicNameServer(dest, dispatcher, disableCache, clientIP), nil
|
return NewClassicNameServer(dest, dispatcher, queryStrategy), nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("No available name server could be created from ", dest).AtWarning()
|
return nil, errors.New("No available name server could be created from ", dest).AtWarning()
|
||||||
}
|
}
|
||||||
@ -89,9 +80,7 @@ func NewClient(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
ns *NameServer,
|
ns *NameServer,
|
||||||
clientIP net.IP,
|
clientIP net.IP,
|
||||||
disableCache bool,
|
container router.GeoIPMatcherContainer,
|
||||||
tag string,
|
|
||||||
ipOption dns.IPOption,
|
|
||||||
matcherInfos *[]*DomainMatcherInfo,
|
matcherInfos *[]*DomainMatcherInfo,
|
||||||
updateDomainRule func(strmatcher.Matcher, int, []*DomainMatcherInfo) error,
|
updateDomainRule func(strmatcher.Matcher, int, []*DomainMatcherInfo) error,
|
||||||
) (*Client, error) {
|
) (*Client, error) {
|
||||||
@ -99,7 +88,7 @@ func NewClient(
|
|||||||
|
|
||||||
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
||||||
// Create a new server for each client for now
|
// Create a new server for each client for now
|
||||||
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, clientIP)
|
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, ns.GetQueryStrategy())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
@ -154,23 +143,13 @@ func NewClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establish expected IPs
|
// Establish expected IPs
|
||||||
var expectedMatchers []*router.GeoIPMatcher
|
var matchers []*router.GeoIPMatcher
|
||||||
for _, geoip := range ns.ExpectedGeoip {
|
for _, geoip := range ns.Geoip {
|
||||||
matcher, err := router.GlobalGeoIPContainer.Add(geoip)
|
matcher, err := container.Add(geoip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
|
return errors.New("failed to create ip matcher").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
expectedMatchers = append(expectedMatchers, matcher)
|
matchers = append(matchers, matcher)
|
||||||
}
|
|
||||||
|
|
||||||
// Establish unexpected IPs
|
|
||||||
var unexpectedMatchers []*router.GeoIPMatcher
|
|
||||||
for _, geoip := range ns.UnexpectedGeoip {
|
|
||||||
matcher, err := router.GlobalGeoIPContainer.Add(geoip)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
|
|
||||||
}
|
|
||||||
unexpectedMatchers = append(unexpectedMatchers, matcher)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clientIP) > 0 {
|
if len(clientIP) > 0 {
|
||||||
@ -178,29 +157,15 @@ func NewClient(
|
|||||||
case *net.IPOrDomain_Domain:
|
case *net.IPOrDomain_Domain:
|
||||||
errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String())
|
errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String())
|
||||||
case *net.IPOrDomain_Ip:
|
case *net.IPOrDomain_Ip:
|
||||||
errors.LogInfo(ctx, "DNS: client ", net.IP(ns.Address.Address.GetIp()), " uses clientIP ", clientIP.String())
|
errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetIp(), " uses clientIP ", clientIP.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var timeoutMs = 4000 * time.Millisecond
|
|
||||||
if ns.TimeoutMs > 0 {
|
|
||||||
timeoutMs = time.Duration(ns.TimeoutMs) * time.Millisecond
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSystem := ns.QueryStrategy == QueryStrategy_USE_SYS
|
|
||||||
|
|
||||||
client.server = server
|
client.server = server
|
||||||
|
client.clientIP = clientIP
|
||||||
client.skipFallback = ns.SkipFallback
|
client.skipFallback = ns.SkipFallback
|
||||||
client.domains = rules
|
client.domains = rules
|
||||||
client.expectedIPs = expectedMatchers
|
client.expectIPs = matchers
|
||||||
client.unexpectedIPs = unexpectedMatchers
|
|
||||||
client.actPrior = ns.ActPrior
|
|
||||||
client.actUnprior = ns.ActUnprior
|
|
||||||
client.tag = tag
|
|
||||||
client.timeoutMs = timeoutMs
|
|
||||||
client.finalQuery = ns.FinalQuery
|
|
||||||
client.ipOption = &ipOption
|
|
||||||
client.checkSystem = checkSystem
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return client, err
|
return client, err
|
||||||
@ -211,79 +176,43 @@ func (c *Client) Name() string {
|
|||||||
return c.server.Name()
|
return c.server.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) IsFinalQuery() bool {
|
|
||||||
return c.finalQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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, disableCache bool) ([]net.IP, error) {
|
||||||
if c.checkSystem {
|
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
||||||
supportIPv4, supportIPv6 := checkSystemNetwork()
|
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, disableCache)
|
||||||
option.IPv4Enable = option.IPv4Enable && supportIPv4
|
|
||||||
option.IPv6Enable = option.IPv6Enable && supportIPv6
|
|
||||||
} else {
|
|
||||||
option.IPv4Enable = option.IPv4Enable && c.ipOption.IPv4Enable
|
|
||||||
option.IPv6Enable = option.IPv6Enable && c.ipOption.IPv6Enable
|
|
||||||
}
|
|
||||||
|
|
||||||
if !option.IPv4Enable && !option.IPv6Enable {
|
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(ctx, c.timeoutMs)
|
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{Tag: c.tag})
|
|
||||||
ips, ttl, err := c.server.QueryIP(ctx, domain, option)
|
|
||||||
cancel()
|
cancel()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return ips, err
|
||||||
|
}
|
||||||
|
return c.MatchExpectedIPs(domain, ips)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ips) == 0 {
|
// MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones.
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error) {
|
||||||
|
if len(c.expectIPs) == 0 {
|
||||||
|
return ips, nil
|
||||||
}
|
}
|
||||||
|
newIps := []net.IP{}
|
||||||
if len(c.expectedIPs) > 0 && !c.actPrior {
|
for _, ip := range ips {
|
||||||
ips = router.MatchIPs(c.expectedIPs, ips, false)
|
for _, matcher := range c.expectIPs {
|
||||||
errors.LogDebug(context.Background(), "domain ", domain, " expectedIPs ", ips, " matched at server ", c.Name())
|
if matcher.Match(ip) {
|
||||||
if len(ips) == 0 {
|
newIps = append(newIps, ip)
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.unexpectedIPs) > 0 && !c.actUnprior {
|
|
||||||
ips = router.MatchIPs(c.unexpectedIPs, ips, true)
|
|
||||||
errors.LogDebug(context.Background(), "domain ", domain, " unexpectedIPs ", ips, " matched at server ", c.Name())
|
|
||||||
if len(ips) == 0 {
|
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
|
||||||
}
|
}
|
||||||
|
if len(newIps) == 0 {
|
||||||
|
return nil, errExpectedIPNonMatch
|
||||||
}
|
}
|
||||||
|
errors.LogDebug(context.Background(), "domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name())
|
||||||
if len(c.expectedIPs) > 0 && c.actPrior {
|
return newIps, nil
|
||||||
ipsNew := router.MatchIPs(c.expectedIPs, ips, false)
|
|
||||||
if len(ipsNew) > 0 {
|
|
||||||
ips = ipsNew
|
|
||||||
errors.LogDebug(context.Background(), "domain ", domain, " priorIPs ", ips, " matched at server ", c.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(c.unexpectedIPs) > 0 && c.actUnprior {
|
|
||||||
ipsNew := router.MatchIPs(c.unexpectedIPs, ips, true)
|
|
||||||
if len(ipsNew) > 0 {
|
|
||||||
ips = ipsNew
|
|
||||||
errors.LogDebug(context.Background(), "domain ", domain, " unpriorIPs ", ips, " matched at server ", c.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ips, ttl, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) dns.IPOption {
|
func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) dns.IPOption {
|
||||||
switch queryStrategy {
|
switch queryStrategy {
|
||||||
case QueryStrategy_USE_IP:
|
case QueryStrategy_USE_IP:
|
||||||
return ipOption
|
return ipOption
|
||||||
case QueryStrategy_USE_SYS:
|
|
||||||
return ipOption
|
|
||||||
case QueryStrategy_USE_IP4:
|
case QueryStrategy_USE_IP4:
|
||||||
return dns.IPOption{
|
return dns.IPOption{
|
||||||
IPv4Enable: ipOption.IPv4Enable,
|
IPv4Enable: ipOption.IPv4Enable,
|
||||||
|
@ -4,12 +4,12 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
go_errors "errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
utls "github.com/refraction-networking/utls"
|
utls "github.com/refraction-networking/utls"
|
||||||
@ -21,9 +21,12 @@ 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/signal/pubsub"
|
||||||
|
"github.com/xtls/xray-core/common/task"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -31,14 +34,18 @@ import (
|
|||||||
// which is compatible with traditional dns over udp(RFC1035),
|
// which is compatible with traditional dns over udp(RFC1035),
|
||||||
// thus most of the DOH implementation is copied from udpns.go
|
// thus most of the DOH implementation is copied from udpns.go
|
||||||
type DoHNameServer struct {
|
type DoHNameServer struct {
|
||||||
cacheController *CacheController
|
sync.RWMutex
|
||||||
|
ips map[string]*record
|
||||||
|
pub *pubsub.Service
|
||||||
|
cleanup *task.Periodic
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
dohURL string
|
dohURL string
|
||||||
clientIP net.IP
|
name string
|
||||||
|
queryStrategy QueryStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDoHNameServer creates DOH/DOHL client object for remote/local resolving.
|
// NewDoHNameServer creates DOH/DOHL client object for remote/local resolving.
|
||||||
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, disableCache bool, clientIP net.IP) *DoHNameServer {
|
func NewDoHNameServer(url *url.URL, queryStrategy QueryStrategy, dispatcher routing.Dispatcher, h2c bool) *DoHNameServer {
|
||||||
url.Scheme = "https"
|
url.Scheme = "https"
|
||||||
mode := "DOH"
|
mode := "DOH"
|
||||||
if dispatcher == nil {
|
if dispatcher == nil {
|
||||||
@ -46,9 +53,15 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, dis
|
|||||||
}
|
}
|
||||||
errors.LogInfo(context.Background(), "DNS: created ", mode, " client for ", url.String(), ", with h2c ", h2c)
|
errors.LogInfo(context.Background(), "DNS: created ", mode, " client for ", url.String(), ", with h2c ", h2c)
|
||||||
s := &DoHNameServer{
|
s := &DoHNameServer{
|
||||||
cacheController: NewCacheController(mode+"//"+url.Host, disableCache),
|
ips: make(map[string]*record),
|
||||||
|
pub: pubsub.NewService(),
|
||||||
|
name: mode + "//" + url.Host,
|
||||||
dohURL: url.String(),
|
dohURL: url.String(),
|
||||||
clientIP: clientIP,
|
queryStrategy: queryStrategy,
|
||||||
|
}
|
||||||
|
s.cleanup = &task.Periodic{
|
||||||
|
Interval: time.Minute,
|
||||||
|
Execute: s.Cleanup,
|
||||||
}
|
}
|
||||||
s.httpClient = &http.Client{
|
s.httpClient = &http.Client{
|
||||||
Transport: &http2.Transport{
|
Transport: &http2.Transport{
|
||||||
@ -114,25 +127,99 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, dis
|
|||||||
|
|
||||||
// Name implements Server.
|
// Name implements Server.
|
||||||
func (s *DoHNameServer) Name() string {
|
func (s *DoHNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup clears expired items from cache
|
||||||
|
func (s *DoHNameServer) Cleanup() error {
|
||||||
|
now := time.Now()
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
if len(s.ips) == 0 {
|
||||||
|
return errors.New("nothing to do. stopping...")
|
||||||
|
}
|
||||||
|
|
||||||
|
for domain, record := range s.ips {
|
||||||
|
if record.A != nil && record.A.Expire.Before(now) {
|
||||||
|
record.A = nil
|
||||||
|
}
|
||||||
|
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
|
||||||
|
record.AAAA = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.A == nil && record.AAAA == nil {
|
||||||
|
errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
|
||||||
|
delete(s.ips, domain)
|
||||||
|
} else {
|
||||||
|
s.ips[domain] = record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.ips) == 0 {
|
||||||
|
s.ips = make(map[string]*record)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DoHNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
|
||||||
|
elapsed := time.Since(req.start)
|
||||||
|
|
||||||
|
s.Lock()
|
||||||
|
rec, found := s.ips[req.domain]
|
||||||
|
if !found {
|
||||||
|
rec = &record{}
|
||||||
|
}
|
||||||
|
updated := false
|
||||||
|
|
||||||
|
switch req.reqType {
|
||||||
|
case dnsmessage.TypeA:
|
||||||
|
if isNewer(rec.A, ipRec) {
|
||||||
|
rec.A = ipRec
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
case dnsmessage.TypeAAAA:
|
||||||
|
addr := make([]net.Address, 0, len(ipRec.IP))
|
||||||
|
for _, ip := range ipRec.IP {
|
||||||
|
if len(ip.IP()) == net.IPv6len {
|
||||||
|
addr = append(addr, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipRec.IP = addr
|
||||||
|
if isNewer(rec.AAAA, ipRec) {
|
||||||
|
rec.AAAA = ipRec
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
|
||||||
|
|
||||||
|
if updated {
|
||||||
|
s.ips[req.domain] = rec
|
||||||
|
}
|
||||||
|
switch req.reqType {
|
||||||
|
case dnsmessage.TypeA:
|
||||||
|
s.pub.Publish(req.domain+"4", nil)
|
||||||
|
case dnsmessage.TypeAAAA:
|
||||||
|
s.pub.Publish(req.domain+"6", nil)
|
||||||
|
}
|
||||||
|
s.Unlock()
|
||||||
|
common.Must(s.cleanup.Start())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DoHNameServer) newReqID() uint16 {
|
func (s *DoHNameServer) newReqID() uint16 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||||
errors.LogInfo(ctx, s.Name(), " querying: ", domain)
|
errors.LogInfo(ctx, s.name, " querying: ", domain)
|
||||||
|
|
||||||
if s.Name()+"." == "DOH//"+domain {
|
if s.name+"." == "DOH//"+domain {
|
||||||
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead.")
|
errors.LogError(ctx, s.name, " tries to resolve itself! Use IP or set \"hosts\" instead.")
|
||||||
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// As we don't want our traffic pattern looks like DoH, we use Random-Length Padding instead of Block-Length Padding recommended in RFC 8467
|
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||||
// Although DoH server like 1.1.1.1 will pad the response to Block-Length 468, at least it is better than no padding for response at all
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, int(crypto.RandBetween(100, 300))))
|
|
||||||
|
|
||||||
var deadline time.Time
|
var deadline time.Time
|
||||||
if d, ok := ctx.Deadline(); ok {
|
if d, ok := ctx.Deadline(); ok {
|
||||||
@ -167,22 +254,19 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain)
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
|
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain)
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rec, err := parseResponse(resp)
|
rec, err := parseResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain)
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.cacheController.updateIP(r, rec)
|
s.updateIP(r, rec)
|
||||||
}(req)
|
}(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -215,50 +299,107 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
|
|||||||
return io.ReadAll(resp.Body)
|
return io.ReadAll(resp.Body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DoHNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
||||||
|
s.RLock()
|
||||||
|
record, found := s.ips[domain]
|
||||||
|
s.RUnlock()
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return nil, errRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
var err4 error
|
||||||
|
var err6 error
|
||||||
|
var ips []net.Address
|
||||||
|
var ip6 []net.Address
|
||||||
|
|
||||||
|
if option.IPv4Enable {
|
||||||
|
ips, err4 = record.A.getIPs()
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.IPv6Enable {
|
||||||
|
ip6, err6 = record.AAAA.getIPs()
|
||||||
|
ips = append(ips, ip6...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return toNetIP(ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err4 != nil {
|
||||||
|
return nil, err4
|
||||||
|
}
|
||||||
|
|
||||||
|
if err6 != nil {
|
||||||
|
return nil, err6
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option.IPv4Enable && record.A != nil) || (option.IPv6Enable && record.AAAA != nil) {
|
||||||
|
return nil, dns_feature.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) { // nolint: dupl
|
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) { // nolint: dupl
|
||||||
fqdn := Fqdn(domain)
|
fqdn := Fqdn(domain)
|
||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||||
defer closeSubscribers(sub4, sub6)
|
if !option.IPv4Enable && !option.IPv6Enable {
|
||||||
|
return nil, dns_feature.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
if s.cacheController.disableCache {
|
if disableCache {
|
||||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||||
} else {
|
} else {
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||||
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
return ips, ttl, err
|
return ips, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
// ipv4 and ipv6 belong to different subscription groups
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
var sub4, sub6 *pubsub.Subscriber
|
||||||
start := time.Now()
|
if option.IPv4Enable {
|
||||||
|
sub4 = s.pub.Subscribe(fqdn + "4")
|
||||||
|
defer sub4.Close()
|
||||||
|
}
|
||||||
|
if option.IPv6Enable {
|
||||||
|
sub6 = s.pub.Subscribe(fqdn + "6")
|
||||||
|
defer sub6.Close()
|
||||||
|
}
|
||||||
|
done := make(chan interface{})
|
||||||
|
go func() {
|
||||||
if sub4 != nil {
|
if sub4 != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub4.Wait():
|
case <-sub4.Wait():
|
||||||
sub4.Close()
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sub6 != nil {
|
if sub6 != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub6.Wait():
|
case <-sub6.Wait():
|
||||||
sub6.Close()
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
s.sendQuery(ctx, fqdn, clientIP, option)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
for {
|
||||||
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
|
if err != errRecordNotFound {
|
||||||
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
|
return ips, err
|
||||||
|
}
|
||||||
|
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
select {
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
case <-ctx.Done():
|
||||||
return ips, ttl, err
|
return nil, ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,12 +17,12 @@ func TestDOHNameServer(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, QueryStrategy_USE_IP, nil, false)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
@ -34,12 +34,12 @@ func TestDOHNameServerWithCache(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, QueryStrategy_USE_IP, nil, false)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
@ -47,10 +47,10 @@ func TestDOHNameServerWithCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips2, _, err := s.QueryIP(ctx2, "google.com", dns_feature.IPOption{
|
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, true)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if r := cmp.Diff(ips2, ips); r != "" {
|
if r := cmp.Diff(ips2, ips); r != "" {
|
||||||
@ -62,12 +62,12 @@ func TestDOHNameServerWithIPv4Override(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, QueryStrategy_USE_IP4, nil, false)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: false,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
@ -85,12 +85,12 @@ func TestDOHNameServerWithIPv6Override(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, QueryStrategy_USE_IP6, nil, false)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
|
@ -20,9 +20,9 @@ func (FakeDNSServer) Name() string {
|
|||||||
return "FakeDNS"
|
return "FakeDNS"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOption) ([]net.IP, uint32, error) {
|
func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, _ net.IP, opt dns.IPOption, _ bool) ([]net.IP, error) {
|
||||||
if f.fakeDNSEngine == nil {
|
if f.fakeDNSEngine == nil {
|
||||||
return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError()
|
return nil, errors.New("Unable to locate a fake DNS Engine").AtError()
|
||||||
}
|
}
|
||||||
|
|
||||||
var ips []net.Address
|
var ips []net.Address
|
||||||
@ -34,13 +34,13 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOp
|
|||||||
|
|
||||||
netIP, err := toNetIP(ips)
|
netIP, err := toNetIP(ips)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, errors.New("Unable to convert IP to net ip").Base(err).AtError()
|
return nil, errors.New("Unable to convert IP to net ip").Base(err).AtError()
|
||||||
}
|
}
|
||||||
|
|
||||||
errors.LogInfo(ctx, f.Name(), " got answer: ", domain, " -> ", ips)
|
errors.LogInfo(ctx, f.Name(), " got answer: ", domain, " -> ", ips)
|
||||||
|
|
||||||
if len(netIP) > 0 {
|
if len(netIP) > 0 {
|
||||||
return netIP, 1, nil // fakeIP ttl is 1
|
return netIP, nil
|
||||||
}
|
}
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
return nil, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
@ -14,13 +15,24 @@ import (
|
|||||||
// LocalNameServer is an wrapper over local DNS feature.
|
// LocalNameServer is an wrapper over local DNS feature.
|
||||||
type LocalNameServer struct {
|
type LocalNameServer struct {
|
||||||
client *localdns.Client
|
client *localdns.Client
|
||||||
|
queryStrategy QueryStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errEmptyResponse = "No address associated with hostname"
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, option dns.IPOption) (ips []net.IP, ttl uint32, err error) {
|
func (s *LocalNameServer) QueryIP(ctx context.Context, domain string, _ net.IP, option dns.IPOption, _ bool) (ips []net.IP, err error) {
|
||||||
|
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||||
|
if !option.IPv4Enable && !option.IPv6Enable {
|
||||||
|
return nil, dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
ips, ttl, err = s.client.LookupIP(domain, option)
|
ips, err = s.client.LookupIP(domain, option)
|
||||||
|
|
||||||
|
if err != nil && strings.HasSuffix(err.Error(), errEmptyResponse) {
|
||||||
|
err = dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
errors.LogInfo(ctx, "Localhost got answer: ", domain, " -> ", ips)
|
errors.LogInfo(ctx, "Localhost got answer: ", domain, " -> ", ips)
|
||||||
@ -36,14 +48,15 @@ func (s *LocalNameServer) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
|
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
|
||||||
func NewLocalNameServer() *LocalNameServer {
|
func NewLocalNameServer(queryStrategy QueryStrategy) *LocalNameServer {
|
||||||
errors.LogInfo(context.Background(), "DNS: created localhost client")
|
errors.LogInfo(context.Background(), "DNS: created localhost client")
|
||||||
return &LocalNameServer{
|
return &LocalNameServer{
|
||||||
|
queryStrategy: queryStrategy,
|
||||||
client: localdns.New(),
|
client: localdns.New(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
|
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
|
||||||
func NewLocalDNSClient(ipOption dns.IPOption) *Client {
|
func NewLocalDNSClient() *Client {
|
||||||
return &Client{server: NewLocalNameServer(), ipOption: &ipOption}
|
return &Client{server: NewLocalNameServer(QueryStrategy_USE_IP)}
|
||||||
}
|
}
|
||||||
|
@ -7,17 +7,18 @@ import (
|
|||||||
|
|
||||||
. "github.com/xtls/xray-core/app/dns"
|
. "github.com/xtls/xray-core/app/dns"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/features/dns"
|
"github.com/xtls/xray-core/features/dns"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLocalNameServer(t *testing.T) {
|
func TestLocalNameServer(t *testing.T) {
|
||||||
s := NewLocalNameServer()
|
s := NewLocalNameServer(QueryStrategy_USE_IP)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP{}, dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
|
@ -4,20 +4,23 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
go_errors "errors"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/quic-go/quic-go"
|
"github.com/quic-go/quic-go"
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"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/signal/pubsub"
|
||||||
|
"github.com/xtls/xray-core/common/task"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
"golang.org/x/net/http2"
|
"golang.org/x/net/http2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -30,14 +33,17 @@ const handshakeTimeout = time.Second * 8
|
|||||||
// QUICNameServer implemented DNS over QUIC
|
// QUICNameServer implemented DNS over QUIC
|
||||||
type QUICNameServer struct {
|
type QUICNameServer struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
cacheController *CacheController
|
ips map[string]*record
|
||||||
|
pub *pubsub.Service
|
||||||
|
cleanup *task.Periodic
|
||||||
|
name string
|
||||||
destination *net.Destination
|
destination *net.Destination
|
||||||
connection quic.Connection
|
connection quic.Connection
|
||||||
clientIP net.IP
|
queryStrategy QueryStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
||||||
func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICNameServer, error) {
|
func NewQUICNameServer(url *url.URL, queryStrategy QueryStrategy) (*QUICNameServer, error) {
|
||||||
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
|
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
@ -51,9 +57,15 @@ func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICN
|
|||||||
dest := net.UDPDestination(net.ParseAddress(url.Hostname()), port)
|
dest := net.UDPDestination(net.ParseAddress(url.Hostname()), port)
|
||||||
|
|
||||||
s := &QUICNameServer{
|
s := &QUICNameServer{
|
||||||
cacheController: NewCacheController(url.String(), disableCache),
|
ips: make(map[string]*record),
|
||||||
|
pub: pubsub.NewService(),
|
||||||
|
name: url.String(),
|
||||||
destination: &dest,
|
destination: &dest,
|
||||||
clientIP: clientIP,
|
queryStrategy: queryStrategy,
|
||||||
|
}
|
||||||
|
s.cleanup = &task.Periodic{
|
||||||
|
Interval: time.Minute,
|
||||||
|
Execute: s.Cleanup,
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
@ -61,17 +73,94 @@ func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICN
|
|||||||
|
|
||||||
// Name returns client name
|
// Name returns client name
|
||||||
func (s *QUICNameServer) Name() string {
|
func (s *QUICNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup clears expired items from cache
|
||||||
|
func (s *QUICNameServer) Cleanup() error {
|
||||||
|
now := time.Now()
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
if len(s.ips) == 0 {
|
||||||
|
return errors.New("nothing to do. stopping...")
|
||||||
|
}
|
||||||
|
|
||||||
|
for domain, record := range s.ips {
|
||||||
|
if record.A != nil && record.A.Expire.Before(now) {
|
||||||
|
record.A = nil
|
||||||
|
}
|
||||||
|
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
|
||||||
|
record.AAAA = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.A == nil && record.AAAA == nil {
|
||||||
|
errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
|
||||||
|
delete(s.ips, domain)
|
||||||
|
} else {
|
||||||
|
s.ips[domain] = record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.ips) == 0 {
|
||||||
|
s.ips = make(map[string]*record)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *QUICNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
|
||||||
|
elapsed := time.Since(req.start)
|
||||||
|
|
||||||
|
s.Lock()
|
||||||
|
rec, found := s.ips[req.domain]
|
||||||
|
if !found {
|
||||||
|
rec = &record{}
|
||||||
|
}
|
||||||
|
updated := false
|
||||||
|
|
||||||
|
switch req.reqType {
|
||||||
|
case dnsmessage.TypeA:
|
||||||
|
if isNewer(rec.A, ipRec) {
|
||||||
|
rec.A = ipRec
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
case dnsmessage.TypeAAAA:
|
||||||
|
addr := make([]net.Address, 0)
|
||||||
|
for _, ip := range ipRec.IP {
|
||||||
|
if len(ip.IP()) == net.IPv6len {
|
||||||
|
addr = append(addr, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipRec.IP = addr
|
||||||
|
if isNewer(rec.AAAA, ipRec) {
|
||||||
|
rec.AAAA = ipRec
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
|
||||||
|
|
||||||
|
if updated {
|
||||||
|
s.ips[req.domain] = rec
|
||||||
|
}
|
||||||
|
switch req.reqType {
|
||||||
|
case dnsmessage.TypeA:
|
||||||
|
s.pub.Publish(req.domain+"4", nil)
|
||||||
|
case dnsmessage.TypeAAAA:
|
||||||
|
s.pub.Publish(req.domain+"6", nil)
|
||||||
|
}
|
||||||
|
s.Unlock()
|
||||||
|
common.Must(s.cleanup.Start())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) newReqID() uint16 {
|
func (s *QUICNameServer) newReqID() uint16 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||||
errors.LogInfo(ctx, s.Name(), " querying: ", domain)
|
errors.LogInfo(ctx, s.name, " querying: ", domain)
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||||
|
|
||||||
var deadline time.Time
|
var deadline time.Time
|
||||||
if d, ok := ctx.Deadline(); ok {
|
if d, ok := ctx.Deadline(); ok {
|
||||||
@ -103,36 +192,23 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsReqBuf := buf.New()
|
dnsReqBuf := buf.New()
|
||||||
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||||
if err != nil {
|
dnsReqBuf.Write(b.Bytes())
|
||||||
errors.LogErrorInner(ctx, err, "binary write failed")
|
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = dnsReqBuf.Write(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
errors.LogErrorInner(ctx, err, "buffer write failed")
|
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b.Release()
|
b.Release()
|
||||||
|
|
||||||
conn, err := s.openStream(dnsCtx)
|
conn, err := s.openStream(dnsCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to open quic connection")
|
errors.LogErrorInner(ctx, err, "failed to open quic connection")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to send query")
|
errors.LogErrorInner(ctx, err, "failed to send query")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,81 +219,134 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var length int16
|
var length int16
|
||||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
respBuf.Clear()
|
respBuf.Clear()
|
||||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rec, err := parseResponse(respBuf.Bytes())
|
rec, err := parseResponse(respBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to handle response")
|
errors.LogErrorInner(ctx, err, "failed to handle response")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.cacheController.updateIP(r, rec)
|
s.updateIP(r, rec)
|
||||||
}(req)
|
}(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *QUICNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
||||||
|
s.RLock()
|
||||||
|
record, found := s.ips[domain]
|
||||||
|
s.RUnlock()
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return nil, errRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
var err4 error
|
||||||
|
var err6 error
|
||||||
|
var ips []net.Address
|
||||||
|
var ip6 []net.Address
|
||||||
|
|
||||||
|
if option.IPv4Enable {
|
||||||
|
ips, err4 = record.A.getIPs()
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.IPv6Enable {
|
||||||
|
ip6, err6 = record.AAAA.getIPs()
|
||||||
|
ips = append(ips, ip6...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return toNetIP(ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err4 != nil {
|
||||||
|
return nil, err4
|
||||||
|
}
|
||||||
|
|
||||||
|
if err6 != nil {
|
||||||
|
return nil, err6
|
||||||
|
}
|
||||||
|
|
||||||
|
if (option.IPv4Enable && record.A != nil) || (option.IPv6Enable && record.AAAA != nil) {
|
||||||
|
return nil, dns_feature.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, errRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
// QueryIP is called from dns.Server->queryIPTimeout
|
// QueryIP is called from dns.Server->queryIPTimeout
|
||||||
func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
func (s *QUICNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) {
|
||||||
fqdn := Fqdn(domain)
|
fqdn := Fqdn(domain)
|
||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||||
defer closeSubscribers(sub4, sub6)
|
if !option.IPv4Enable && !option.IPv6Enable {
|
||||||
|
return nil, dns_feature.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
if s.cacheController.disableCache {
|
if disableCache {
|
||||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||||
} else {
|
} else {
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||||
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
return ips, ttl, err
|
return ips, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
// ipv4 and ipv6 belong to different subscription groups
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
var sub4, sub6 *pubsub.Subscriber
|
||||||
start := time.Now()
|
if option.IPv4Enable {
|
||||||
|
sub4 = s.pub.Subscribe(fqdn + "4")
|
||||||
|
defer sub4.Close()
|
||||||
|
}
|
||||||
|
if option.IPv6Enable {
|
||||||
|
sub6 = s.pub.Subscribe(fqdn + "6")
|
||||||
|
defer sub6.Close()
|
||||||
|
}
|
||||||
|
done := make(chan interface{})
|
||||||
|
go func() {
|
||||||
if sub4 != nil {
|
if sub4 != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub4.Wait():
|
case <-sub4.Wait():
|
||||||
sub4.Close()
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sub6 != nil {
|
if sub6 != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub6.Wait():
|
case <-sub6.Wait():
|
||||||
sub6.Close()
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
s.sendQuery(ctx, fqdn, clientIP, option)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
for {
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
return ips, ttl, err
|
if err != errRecordNotFound {
|
||||||
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
|
return ips, err
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isActive(s quic.Connection) bool {
|
func isActive(s quic.Connection) bool {
|
||||||
|
@ -16,23 +16,24 @@ import (
|
|||||||
func TestQUICNameServer(t *testing.T) {
|
func TestQUICNameServer(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
t.Error("expect some ips, but got 0")
|
t.Error("expect some ips, but got 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips2, _, err := s.QueryIP(ctx2, "google.com", dns.IPOption{
|
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, true)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if r := cmp.Diff(ips2, ips); r != "" {
|
if r := cmp.Diff(ips2, ips); r != "" {
|
||||||
@ -43,13 +44,13 @@ func TestQUICNameServer(t *testing.T) {
|
|||||||
func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP4)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: false,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
@ -66,13 +67,13 @@ func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
|||||||
func TestQUICNameServerWithIPv6Override(t *testing.T) {
|
func TestQUICNameServerWithIPv6Override(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP6)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
|
@ -4,11 +4,12 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
go_errors "errors"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
@ -16,28 +17,34 @@ 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/signal/pubsub"
|
||||||
|
"github.com/xtls/xray-core/common/task"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TCPNameServer implemented DNS over TCP (RFC7766).
|
// TCPNameServer implemented DNS over TCP (RFC7766).
|
||||||
type TCPNameServer struct {
|
type TCPNameServer struct {
|
||||||
cacheController *CacheController
|
sync.RWMutex
|
||||||
|
name string
|
||||||
destination *net.Destination
|
destination *net.Destination
|
||||||
|
ips map[string]*record
|
||||||
|
pub *pubsub.Service
|
||||||
|
cleanup *task.Periodic
|
||||||
reqID uint32
|
reqID uint32
|
||||||
dial func(context.Context) (net.Conn, error)
|
dial func(context.Context) (net.Conn, error)
|
||||||
clientIP net.IP
|
queryStrategy QueryStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPNameServer creates DNS over TCP server object for remote resolving.
|
// NewTCPNameServer creates DNS over TCP server object for remote resolving.
|
||||||
func NewTCPNameServer(
|
func NewTCPNameServer(
|
||||||
url *url.URL,
|
url *url.URL,
|
||||||
dispatcher routing.Dispatcher,
|
dispatcher routing.Dispatcher,
|
||||||
disableCache bool,
|
queryStrategy QueryStrategy,
|
||||||
clientIP net.IP,
|
|
||||||
) (*TCPNameServer, error) {
|
) (*TCPNameServer, error) {
|
||||||
s, err := baseTCPNameServer(url, "TCP", disableCache, clientIP)
|
s, err := baseTCPNameServer(url, "TCP", queryStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -58,8 +65,8 @@ func NewTCPNameServer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPLocalNameServer creates DNS over TCP client object for local resolving
|
// NewTCPLocalNameServer creates DNS over TCP client object for local resolving
|
||||||
func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
|
func NewTCPLocalNameServer(url *url.URL, queryStrategy QueryStrategy) (*TCPNameServer, error) {
|
||||||
s, err := baseTCPNameServer(url, "TCPL", disableCache, clientIP)
|
s, err := baseTCPNameServer(url, "TCPL", queryStrategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -71,7 +78,7 @@ func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*T
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
|
func baseTCPNameServer(url *url.URL, prefix string, queryStrategy QueryStrategy) (*TCPNameServer, error) {
|
||||||
port := net.Port(53)
|
port := net.Port(53)
|
||||||
if url.Port() != "" {
|
if url.Port() != "" {
|
||||||
var err error
|
var err error
|
||||||
@ -82,9 +89,15 @@ func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP
|
|||||||
dest := net.TCPDestination(net.ParseAddress(url.Hostname()), port)
|
dest := net.TCPDestination(net.ParseAddress(url.Hostname()), port)
|
||||||
|
|
||||||
s := &TCPNameServer{
|
s := &TCPNameServer{
|
||||||
cacheController: NewCacheController(prefix+"//"+dest.NetAddr(), disableCache),
|
|
||||||
destination: &dest,
|
destination: &dest,
|
||||||
clientIP: clientIP,
|
ips: make(map[string]*record),
|
||||||
|
pub: pubsub.NewService(),
|
||||||
|
name: prefix + "//" + dest.NetAddr(),
|
||||||
|
queryStrategy: queryStrategy,
|
||||||
|
}
|
||||||
|
s.cleanup = &task.Periodic{
|
||||||
|
Interval: time.Minute,
|
||||||
|
Execute: s.Cleanup,
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
@ -92,17 +105,94 @@ func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP
|
|||||||
|
|
||||||
// Name implements Server.
|
// Name implements Server.
|
||||||
func (s *TCPNameServer) Name() string {
|
func (s *TCPNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup clears expired items from cache
|
||||||
|
func (s *TCPNameServer) Cleanup() error {
|
||||||
|
now := time.Now()
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
|
if len(s.ips) == 0 {
|
||||||
|
return errors.New("nothing to do. stopping...")
|
||||||
|
}
|
||||||
|
|
||||||
|
for domain, record := range s.ips {
|
||||||
|
if record.A != nil && record.A.Expire.Before(now) {
|
||||||
|
record.A = nil
|
||||||
|
}
|
||||||
|
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
|
||||||
|
record.AAAA = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.A == nil && record.AAAA == nil {
|
||||||
|
errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
|
||||||
|
delete(s.ips, domain)
|
||||||
|
} else {
|
||||||
|
s.ips[domain] = record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.ips) == 0 {
|
||||||
|
s.ips = make(map[string]*record)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TCPNameServer) updateIP(req *dnsRequest, ipRec *IPRecord) {
|
||||||
|
elapsed := time.Since(req.start)
|
||||||
|
|
||||||
|
s.Lock()
|
||||||
|
rec, found := s.ips[req.domain]
|
||||||
|
if !found {
|
||||||
|
rec = &record{}
|
||||||
|
}
|
||||||
|
updated := false
|
||||||
|
|
||||||
|
switch req.reqType {
|
||||||
|
case dnsmessage.TypeA:
|
||||||
|
if isNewer(rec.A, ipRec) {
|
||||||
|
rec.A = ipRec
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
case dnsmessage.TypeAAAA:
|
||||||
|
addr := make([]net.Address, 0)
|
||||||
|
for _, ip := range ipRec.IP {
|
||||||
|
if len(ip.IP()) == net.IPv6len {
|
||||||
|
addr = append(addr, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ipRec.IP = addr
|
||||||
|
if isNewer(rec.AAAA, ipRec) {
|
||||||
|
rec.AAAA = ipRec
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
errors.LogInfo(context.Background(), s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
|
||||||
|
|
||||||
|
if updated {
|
||||||
|
s.ips[req.domain] = rec
|
||||||
|
}
|
||||||
|
switch req.reqType {
|
||||||
|
case dnsmessage.TypeA:
|
||||||
|
s.pub.Publish(req.domain+"4", nil)
|
||||||
|
case dnsmessage.TypeAAAA:
|
||||||
|
s.pub.Publish(req.domain+"6", nil)
|
||||||
|
}
|
||||||
|
s.Unlock()
|
||||||
|
common.Must(s.cleanup.Start())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TCPNameServer) newReqID() uint16 {
|
func (s *TCPNameServer) newReqID() uint16 {
|
||||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
func (s *TCPNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||||
errors.LogDebug(ctx, s.Name(), " querying DNS for: ", domain)
|
errors.LogDebug(ctx, s.name, " querying DNS for: ", domain)
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||||
|
|
||||||
var deadline time.Time
|
var deadline time.Time
|
||||||
if d, ok := ctx.Deadline(); ok {
|
if d, ok := ctx.Deadline(); ok {
|
||||||
@ -131,36 +221,23 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := s.dial(dnsCtx)
|
conn, err := s.dial(dnsCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to dial namesever")
|
errors.LogErrorInner(ctx, err, "failed to dial namesever")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
dnsReqBuf := buf.New()
|
dnsReqBuf := buf.New()
|
||||||
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||||
if err != nil {
|
dnsReqBuf.Write(b.Bytes())
|
||||||
errors.LogErrorInner(ctx, err, "binary write failed")
|
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
_, err = dnsReqBuf.Write(b.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
errors.LogErrorInner(ctx, err, "buffer write failed")
|
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b.Release()
|
b.Release()
|
||||||
|
|
||||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to send query")
|
errors.LogErrorInner(ctx, err, "failed to send query")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dnsReqBuf.Release()
|
dnsReqBuf.Release()
|
||||||
@ -170,80 +247,129 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var length int16
|
var length int16
|
||||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
respBuf.Clear()
|
respBuf.Clear()
|
||||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rec, err := parseResponse(respBuf.Bytes())
|
rec, err := parseResponse(respBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
|
errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
|
||||||
noResponseErrCh <- err
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cacheController.updateIP(r, rec)
|
s.updateIP(r, rec)
|
||||||
}(req)
|
}(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TCPNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
||||||
|
s.RLock()
|
||||||
|
record, found := s.ips[domain]
|
||||||
|
s.RUnlock()
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return nil, errRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
var err4 error
|
||||||
|
var err6 error
|
||||||
|
var ips []net.Address
|
||||||
|
var ip6 []net.Address
|
||||||
|
|
||||||
|
if option.IPv4Enable {
|
||||||
|
ips, err4 = record.A.getIPs()
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.IPv6Enable {
|
||||||
|
ip6, err6 = record.AAAA.getIPs()
|
||||||
|
ips = append(ips, ip6...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return toNetIP(ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err4 != nil {
|
||||||
|
return nil, err4
|
||||||
|
}
|
||||||
|
|
||||||
|
if err6 != nil {
|
||||||
|
return nil, err6
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, dns_feature.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) {
|
||||||
fqdn := Fqdn(domain)
|
fqdn := Fqdn(domain)
|
||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||||
defer closeSubscribers(sub4, sub6)
|
if !option.IPv4Enable && !option.IPv6Enable {
|
||||||
|
return nil, dns_feature.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
if s.cacheController.disableCache {
|
if disableCache {
|
||||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||||
} else {
|
} else {
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||||
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
return ips, ttl, err
|
return ips, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
// ipv4 and ipv6 belong to different subscription groups
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
var sub4, sub6 *pubsub.Subscriber
|
||||||
start := time.Now()
|
if option.IPv4Enable {
|
||||||
|
sub4 = s.pub.Subscribe(fqdn + "4")
|
||||||
|
defer sub4.Close()
|
||||||
|
}
|
||||||
|
if option.IPv6Enable {
|
||||||
|
sub6 = s.pub.Subscribe(fqdn + "6")
|
||||||
|
defer sub6.Close()
|
||||||
|
}
|
||||||
|
done := make(chan interface{})
|
||||||
|
go func() {
|
||||||
if sub4 != nil {
|
if sub4 != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub4.Wait():
|
case <-sub4.Wait():
|
||||||
sub4.Close()
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sub6 != nil {
|
if sub6 != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub6.Wait():
|
case <-sub6.Wait():
|
||||||
sub6.Close()
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
s.sendQuery(ctx, fqdn, clientIP, option)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
for {
|
||||||
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
|
if err != errRecordNotFound {
|
||||||
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
|
return ips, err
|
||||||
|
}
|
||||||
|
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
select {
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
case <-ctx.Done():
|
||||||
return ips, ttl, err
|
return nil, ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,13 +16,13 @@ import (
|
|||||||
func TestTCPLocalNameServer(t *testing.T) {
|
func TestTCPLocalNameServer(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
@ -33,13 +33,13 @@ func TestTCPLocalNameServer(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithCache(t *testing.T) {
|
func TestTCPLocalNameServerWithCache(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if len(ips) == 0 {
|
if len(ips) == 0 {
|
||||||
@ -47,10 +47,10 @@ func TestTCPLocalNameServerWithCache(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx2, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips2, _, err := s.QueryIP(ctx2, "google.com", dns_feature.IPOption{
|
ips2, err := s.QueryIP(ctx2, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, true)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
if r := cmp.Diff(ips2, ips); r != "" {
|
if r := cmp.Diff(ips2, ips); r != "" {
|
||||||
@ -61,13 +61,13 @@ func TestTCPLocalNameServerWithCache(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP4)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: false,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
@ -85,13 +85,13 @@ func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {
|
func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP6)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
}, false)
|
||||||
cancel()
|
cancel()
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
go_errors "errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -14,6 +13,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol/dns"
|
"github.com/xtls/xray-core/common/protocol/dns"
|
||||||
udp_proto "github.com/xtls/xray-core/common/protocol/udp"
|
udp_proto "github.com/xtls/xray-core/common/protocol/udp"
|
||||||
|
"github.com/xtls/xray-core/common/signal/pubsub"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
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"
|
||||||
@ -24,36 +24,35 @@ import (
|
|||||||
// ClassicNameServer implemented traditional UDP DNS.
|
// ClassicNameServer implemented traditional UDP DNS.
|
||||||
type ClassicNameServer struct {
|
type ClassicNameServer struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
cacheController *CacheController
|
name string
|
||||||
address *net.Destination
|
address *net.Destination
|
||||||
requests map[uint16]*udpDnsRequest
|
ips map[string]*record
|
||||||
|
requests map[uint16]*dnsRequest
|
||||||
|
pub *pubsub.Service
|
||||||
udpServer *udp.Dispatcher
|
udpServer *udp.Dispatcher
|
||||||
requestsCleanup *task.Periodic
|
cleanup *task.Periodic
|
||||||
reqID uint32
|
reqID uint32
|
||||||
clientIP net.IP
|
queryStrategy QueryStrategy
|
||||||
}
|
|
||||||
|
|
||||||
type udpDnsRequest struct {
|
|
||||||
dnsRequest
|
|
||||||
ctx context.Context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClassicNameServer creates udp server object for remote resolving.
|
// NewClassicNameServer creates udp server object for remote resolving.
|
||||||
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, disableCache bool, clientIP net.IP) *ClassicNameServer {
|
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, queryStrategy QueryStrategy) *ClassicNameServer {
|
||||||
// default to 53 if unspecific
|
// default to 53 if unspecific
|
||||||
if address.Port == 0 {
|
if address.Port == 0 {
|
||||||
address.Port = net.Port(53)
|
address.Port = net.Port(53)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &ClassicNameServer{
|
s := &ClassicNameServer{
|
||||||
cacheController: NewCacheController(strings.ToUpper(address.String()), disableCache),
|
|
||||||
address: &address,
|
address: &address,
|
||||||
requests: make(map[uint16]*udpDnsRequest),
|
ips: make(map[string]*record),
|
||||||
clientIP: clientIP,
|
requests: make(map[uint16]*dnsRequest),
|
||||||
|
pub: pubsub.NewService(),
|
||||||
|
name: strings.ToUpper(address.String()),
|
||||||
|
queryStrategy: queryStrategy,
|
||||||
}
|
}
|
||||||
s.requestsCleanup = &task.Periodic{
|
s.cleanup = &task.Periodic{
|
||||||
Interval: time.Minute,
|
Interval: time.Minute,
|
||||||
Execute: s.RequestsCleanup,
|
Execute: s.Cleanup,
|
||||||
}
|
}
|
||||||
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
|
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
|
||||||
errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
|
errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
|
||||||
@ -62,17 +61,37 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
|
|||||||
|
|
||||||
// Name implements Server.
|
// Name implements Server.
|
||||||
func (s *ClassicNameServer) Name() string {
|
func (s *ClassicNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.name
|
||||||
}
|
}
|
||||||
|
|
||||||
// RequestsCleanup clears expired items from cache
|
// Cleanup clears expired items from cache
|
||||||
func (s *ClassicNameServer) RequestsCleanup() error {
|
func (s *ClassicNameServer) Cleanup() error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
|
|
||||||
if len(s.requests) == 0 {
|
if len(s.ips) == 0 && len(s.requests) == 0 {
|
||||||
return errors.New(s.Name(), " nothing to do. stopping...")
|
return errors.New(s.name, " nothing to do. stopping...")
|
||||||
|
}
|
||||||
|
|
||||||
|
for domain, record := range s.ips {
|
||||||
|
if record.A != nil && record.A.Expire.Before(now) {
|
||||||
|
record.A = nil
|
||||||
|
}
|
||||||
|
if record.AAAA != nil && record.AAAA.Expire.Before(now) {
|
||||||
|
record.AAAA = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if record.A == nil && record.AAAA == nil {
|
||||||
|
errors.LogDebug(context.Background(), s.name, " cleanup ", domain)
|
||||||
|
delete(s.ips, domain)
|
||||||
|
} else {
|
||||||
|
s.ips[domain] = record
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.ips) == 0 {
|
||||||
|
s.ips = make(map[string]*record)
|
||||||
}
|
}
|
||||||
|
|
||||||
for id, req := range s.requests {
|
for id, req := range s.requests {
|
||||||
@ -82,7 +101,7 @@ func (s *ClassicNameServer) RequestsCleanup() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(s.requests) == 0 {
|
if len(s.requests) == 0 {
|
||||||
s.requests = make(map[uint16]*udpDnsRequest)
|
s.requests = make(map[uint16]*dnsRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -92,7 +111,7 @@ func (s *ClassicNameServer) RequestsCleanup() error {
|
|||||||
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
|
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
|
||||||
ipRec, err := parseResponse(packet.Payload.Bytes())
|
ipRec, err := parseResponse(packet.Payload.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogError(ctx, s.Name(), " fail to parse responded DNS udp")
|
errors.LogError(ctx, s.name, " fail to parse responded DNS udp")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,107 +124,179 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
|
|||||||
}
|
}
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
if !ok {
|
if !ok {
|
||||||
errors.LogError(ctx, s.Name(), " cannot find the pending request")
|
errors.LogError(ctx, s.name, " cannot find the pending request")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// if truncated, retry with EDNS0 option(udp payload size: 1350)
|
var rec record
|
||||||
if ipRec.RawHeader.Truncated {
|
switch req.reqType {
|
||||||
// if already has EDNS0 option, no need to retry
|
case dnsmessage.TypeA:
|
||||||
if len(req.msg.Additionals) == 0 {
|
rec.A = ipRec
|
||||||
// copy necessary meta data from original request
|
case dnsmessage.TypeAAAA:
|
||||||
// and add EDNS0 option
|
rec.AAAA = ipRec
|
||||||
opt := new(dnsmessage.Resource)
|
}
|
||||||
common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
|
|
||||||
opt.Body = &dnsmessage.OPTResource{}
|
elapsed := time.Since(req.start)
|
||||||
newMsg := *req.msg
|
errors.LogInfo(ctx, s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
|
||||||
newReq := *req
|
if len(req.domain) > 0 && (rec.A != nil || rec.AAAA != nil) {
|
||||||
newMsg.Additionals = append(newMsg.Additionals, *opt)
|
s.updateIP(req.domain, &rec)
|
||||||
newMsg.ID = s.newReqID()
|
|
||||||
newReq.msg = &newMsg
|
|
||||||
s.addPendingRequest(&newReq)
|
|
||||||
b, _ := dns.PackMessage(newReq.msg)
|
|
||||||
s.udpServer.Dispatch(toDnsContext(newReq.ctx, s.address.String()), *s.address, b)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cacheController.updateIP(&req.dnsRequest, ipRec)
|
func (s *ClassicNameServer) updateIP(domain string, newRec *record) {
|
||||||
|
s.Lock()
|
||||||
|
|
||||||
|
rec, found := s.ips[domain]
|
||||||
|
if !found {
|
||||||
|
rec = &record{}
|
||||||
|
}
|
||||||
|
|
||||||
|
updated := false
|
||||||
|
if isNewer(rec.A, newRec.A) {
|
||||||
|
rec.A = newRec.A
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
if isNewer(rec.AAAA, newRec.AAAA) {
|
||||||
|
rec.AAAA = newRec.AAAA
|
||||||
|
updated = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if updated {
|
||||||
|
errors.LogDebug(context.Background(), s.name, " updating IP records for domain:", domain)
|
||||||
|
s.ips[domain] = rec
|
||||||
|
}
|
||||||
|
if newRec.A != nil {
|
||||||
|
s.pub.Publish(domain+"4", nil)
|
||||||
|
}
|
||||||
|
if newRec.AAAA != nil {
|
||||||
|
s.pub.Publish(domain+"6", nil)
|
||||||
|
}
|
||||||
|
s.Unlock()
|
||||||
|
common.Must(s.cleanup.Start())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClassicNameServer) newReqID() uint16 {
|
func (s *ClassicNameServer) newReqID() uint16 {
|
||||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClassicNameServer) addPendingRequest(req *udpDnsRequest) {
|
func (s *ClassicNameServer) addPendingRequest(req *dnsRequest) {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
|
||||||
id := req.msg.ID
|
id := req.msg.ID
|
||||||
req.expire = time.Now().Add(time.Second * 8)
|
req.expire = time.Now().Add(time.Second * 8)
|
||||||
s.requests[id] = req
|
s.requests[id] = req
|
||||||
s.Unlock()
|
|
||||||
common.Must(s.requestsCleanup.Start())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, domain string, option dns_feature.IPOption) {
|
func (s *ClassicNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||||
errors.LogDebug(ctx, s.Name(), " querying DNS for: ", domain)
|
errors.LogDebug(ctx, s.name, " querying DNS for: ", domain)
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||||
|
|
||||||
for _, req := range reqs {
|
for _, req := range reqs {
|
||||||
udpReq := &udpDnsRequest{
|
s.addPendingRequest(req)
|
||||||
dnsRequest: *req,
|
|
||||||
ctx: ctx,
|
|
||||||
}
|
|
||||||
s.addPendingRequest(udpReq)
|
|
||||||
b, _ := dns.PackMessage(req.msg)
|
b, _ := dns.PackMessage(req.msg)
|
||||||
s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
|
s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ClassicNameServer) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, error) {
|
||||||
|
s.RLock()
|
||||||
|
record, found := s.ips[domain]
|
||||||
|
s.RUnlock()
|
||||||
|
|
||||||
|
if !found {
|
||||||
|
return nil, errRecordNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
var err4 error
|
||||||
|
var err6 error
|
||||||
|
var ips []net.Address
|
||||||
|
var ip6 []net.Address
|
||||||
|
|
||||||
|
if option.IPv4Enable {
|
||||||
|
ips, err4 = record.A.getIPs()
|
||||||
|
}
|
||||||
|
|
||||||
|
if option.IPv6Enable {
|
||||||
|
ip6, err6 = record.AAAA.getIPs()
|
||||||
|
ips = append(ips, ip6...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return toNetIP(ips)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err4 != nil {
|
||||||
|
return nil, err4
|
||||||
|
}
|
||||||
|
|
||||||
|
if err6 != nil {
|
||||||
|
return nil, err6
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, dns_feature.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption, disableCache bool) ([]net.IP, error) {
|
||||||
fqdn := Fqdn(domain)
|
fqdn := Fqdn(domain)
|
||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||||
defer closeSubscribers(sub4, sub6)
|
if !option.IPv4Enable && !option.IPv6Enable {
|
||||||
|
return nil, dns_feature.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
if s.cacheController.disableCache {
|
if disableCache {
|
||||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||||
} else {
|
} else {
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||||
errors.LogDebugInner(ctx, err, s.Name(), " cache HIT ", domain, " -> ", ips)
|
errors.LogDebugInner(ctx, err, s.name, " cache HIT ", domain, " -> ", ips)
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
return ips, ttl, err
|
return ips, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
// ipv4 and ipv6 belong to different subscription groups
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
var sub4, sub6 *pubsub.Subscriber
|
||||||
start := time.Now()
|
if option.IPv4Enable {
|
||||||
|
sub4 = s.pub.Subscribe(fqdn + "4")
|
||||||
|
defer sub4.Close()
|
||||||
|
}
|
||||||
|
if option.IPv6Enable {
|
||||||
|
sub6 = s.pub.Subscribe(fqdn + "6")
|
||||||
|
defer sub6.Close()
|
||||||
|
}
|
||||||
|
done := make(chan interface{})
|
||||||
|
go func() {
|
||||||
if sub4 != nil {
|
if sub4 != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub4.Wait():
|
case <-sub4.Wait():
|
||||||
sub4.Close()
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sub6 != nil {
|
if sub6 != nil {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub6.Wait():
|
case <-sub6.Wait():
|
||||||
sub6.Close()
|
case <-ctx.Done():
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(done)
|
||||||
|
}()
|
||||||
|
s.sendQuery(ctx, fqdn, clientIP, option)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
for {
|
||||||
|
ips, err := s.findIPsForDomain(fqdn, option)
|
||||||
|
if err != errRecordNotFound {
|
||||||
|
log.Record(&log.DNSLog{Server: s.name, Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
|
return ips, err
|
||||||
|
}
|
||||||
|
|
||||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
select {
|
||||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
case <-ctx.Done():
|
||||||
return ips, ttl, err
|
return nil, ctx.Err()
|
||||||
|
case <-done:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
)
|
)
|
||||||
@ -109,13 +108,3 @@ func (co *Outbound) Close() error {
|
|||||||
co.closed = true
|
co.closed = true
|
||||||
return co.listener.Close()
|
return co.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SenderSettings implements outbound.Handler.
|
|
||||||
func (co *Outbound) SenderSettings() *serial.TypedMessage {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProxySettings implements outbound.Handler.
|
|
||||||
func (co *Outbound) ProxySettings() *serial.TypedMessage {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -90,8 +90,6 @@ type HealthPingConfig struct {
|
|||||||
SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"`
|
SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"`
|
||||||
// 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
|
|
||||||
HttpMethod string `protobuf:"bytes,6,opt,name=httpMethod,proto3" json:"httpMethod,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *HealthPingConfig) Reset() {
|
func (x *HealthPingConfig) Reset() {
|
||||||
@ -159,13 +157,6 @@ func (x *HealthPingConfig) GetTimeout() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *HealthPingConfig) GetHttpMethod() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.HttpMethod
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
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{
|
var file_app_observatory_burst_config_proto_rawDesc = []byte{
|
||||||
@ -182,7 +173,7 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{
|
|||||||
0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72,
|
0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72,
|
||||||
0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
||||||
0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
|
0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
|
||||||
0xd4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
0xb4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
||||||
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69,
|
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69,
|
||||||
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||||
@ -193,9 +184,7 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{
|
|||||||
0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73,
|
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,
|
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,
|
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,
|
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
||||||
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,
|
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,
|
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,
|
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
|
||||||
|
@ -26,7 +26,4 @@ message HealthPingConfig {
|
|||||||
int32 samplingCount = 4;
|
int32 samplingCount = 4;
|
||||||
// ping timeout, int64 values of time.Duration
|
// ping timeout, int64 values of time.Duration
|
||||||
int64 timeout = 5;
|
int64 timeout = 5;
|
||||||
// http method to make request
|
|
||||||
string httpMethod = 6;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,6 @@ type HealthPingSettings struct {
|
|||||||
Interval time.Duration `json:"interval"`
|
Interval time.Duration `json:"interval"`
|
||||||
SamplingCount int `json:"sampling"`
|
SamplingCount int `json:"sampling"`
|
||||||
Timeout time.Duration `json:"timeout"`
|
Timeout time.Duration `json:"timeout"`
|
||||||
HttpMethod string `json:"httpMethod"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthPing is the health checker for balancers
|
// HealthPing is the health checker for balancers
|
||||||
@ -38,21 +37,12 @@ type HealthPing struct {
|
|||||||
func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *HealthPingConfig) *HealthPing {
|
func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *HealthPingConfig) *HealthPing {
|
||||||
settings := &HealthPingSettings{}
|
settings := &HealthPingSettings{}
|
||||||
if config != nil {
|
if config != nil {
|
||||||
|
|
||||||
var httpMethod string
|
|
||||||
if config.HttpMethod == "" {
|
|
||||||
httpMethod = "HEAD"
|
|
||||||
} else {
|
|
||||||
httpMethod = strings.TrimSpace(config.HttpMethod)
|
|
||||||
}
|
|
||||||
|
|
||||||
settings = &HealthPingSettings{
|
settings = &HealthPingSettings{
|
||||||
Connectivity: strings.TrimSpace(config.Connectivity),
|
Connectivity: strings.TrimSpace(config.Connectivity),
|
||||||
Destination: strings.TrimSpace(config.Destination),
|
Destination: strings.TrimSpace(config.Destination),
|
||||||
Interval: time.Duration(config.Interval),
|
Interval: time.Duration(config.Interval),
|
||||||
SamplingCount: int(config.SamplingCount),
|
SamplingCount: int(config.SamplingCount),
|
||||||
Timeout: time.Duration(config.Timeout),
|
Timeout: time.Duration(config.Timeout),
|
||||||
HttpMethod: httpMethod,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if settings.Destination == "" {
|
if settings.Destination == "" {
|
||||||
@ -174,7 +164,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
|
|||||||
}
|
}
|
||||||
time.AfterFunc(delay, func() {
|
time.AfterFunc(delay, func() {
|
||||||
errors.LogDebug(h.ctx, "checking ", handler)
|
errors.LogDebug(h.ctx, "checking ", handler)
|
||||||
delay, err := client.MeasureDelay(h.Settings.HttpMethod)
|
delay, err := client.MeasureDelay()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ch <- &rtt{
|
ch <- &rtt{
|
||||||
handler: handler,
|
handler: handler,
|
||||||
@ -261,7 +251,7 @@ func (h *HealthPing) checkConnectivity() bool {
|
|||||||
h.Settings.Connectivity,
|
h.Settings.Connectivity,
|
||||||
h.Settings.Timeout,
|
h.Settings.Timeout,
|
||||||
)
|
)
|
||||||
if _, err := tester.MeasureDelay(h.Settings.HttpMethod); err != nil {
|
if _, err := tester.MeasureDelay(); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -2,7 +2,6 @@ package burst
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -52,28 +51,20 @@ func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MeasureDelay returns the delay time of the request to dest
|
// MeasureDelay returns the delay time of the request to dest
|
||||||
func (s *pingClient) MeasureDelay(httpMethod string) (time.Duration, error) {
|
func (s *pingClient) MeasureDelay() (time.Duration, error) {
|
||||||
if s.httpClient == nil {
|
if s.httpClient == nil {
|
||||||
panic("pingClient not initialized")
|
panic("pingClient not initialized")
|
||||||
}
|
}
|
||||||
|
req, err := http.NewRequest(http.MethodHead, s.destination, nil)
|
||||||
req, err := http.NewRequest(httpMethod, s.destination, nil)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rttFailed, err
|
return rttFailed, err
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
resp, err := s.httpClient.Do(req)
|
resp, err := s.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rttFailed, err
|
return rttFailed, err
|
||||||
}
|
}
|
||||||
if httpMethod == http.MethodGet {
|
// don't wait for body
|
||||||
_, err = io.Copy(io.Discard, resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
return rttFailed, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
|
|
||||||
return time.Since(start), nil
|
return time.Since(start), nil
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package command
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/commander"
|
|
||||||
"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/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
@ -100,19 +99,6 @@ func (s *handlerServer) AlterInbound(ctx context.Context, request *AlterInboundR
|
|||||||
return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler)
|
return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *handlerServer) ListInbounds(ctx context.Context, request *ListInboundsRequest) (*ListInboundsResponse, error) {
|
|
||||||
handlers := s.ihm.ListHandlers(ctx)
|
|
||||||
response := &ListInboundsResponse{}
|
|
||||||
for _, handler := range handlers {
|
|
||||||
response.Inbounds = append(response.Inbounds, &core.InboundHandlerConfig{
|
|
||||||
Tag: handler.Tag(),
|
|
||||||
ReceiverSettings: handler.ReceiverSettings(),
|
|
||||||
ProxySettings: handler.ProxySettings(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *handlerServer) GetInboundUsers(ctx context.Context, request *GetInboundUserRequest) (*GetInboundUserResponse, error) {
|
func (s *handlerServer) GetInboundUsers(ctx context.Context, request *GetInboundUserRequest) (*GetInboundUserResponse, error) {
|
||||||
handler, err := s.ihm.GetHandler(ctx, request.Tag)
|
handler, err := s.ihm.GetHandler(ctx, request.Tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -178,23 +164,6 @@ func (s *handlerServer) AlterOutbound(ctx context.Context, request *AlterOutboun
|
|||||||
return &AlterOutboundResponse{}, operation.ApplyOutbound(ctx, handler)
|
return &AlterOutboundResponse{}, operation.ApplyOutbound(ctx, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *handlerServer) ListOutbounds(ctx context.Context, request *ListOutboundsRequest) (*ListOutboundsResponse, error) {
|
|
||||||
handlers := s.ohm.ListHandlers(ctx)
|
|
||||||
response := &ListOutboundsResponse{}
|
|
||||||
for _, handler := range handlers {
|
|
||||||
// Ignore gRPC outbound
|
|
||||||
if _, ok := handler.(*commander.Outbound); ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
response.Outbounds = append(response.Outbounds, &core.OutboundHandlerConfig{
|
|
||||||
Tag: handler.Tag(),
|
|
||||||
SenderSettings: handler.SenderSettings(),
|
|
||||||
ProxySettings: handler.ProxySettings(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *handlerServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
func (s *handlerServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
|
@ -364,87 +364,6 @@ func (*AlterInboundResponse) Descriptor() ([]byte, []int) {
|
|||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{7}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListInboundsRequest struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListInboundsRequest) Reset() {
|
|
||||||
*x = ListInboundsRequest{}
|
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[8]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListInboundsRequest) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*ListInboundsRequest) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *ListInboundsRequest) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_command_command_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 ListInboundsRequest.ProtoReflect.Descriptor instead.
|
|
||||||
func (*ListInboundsRequest) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{8}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListInboundsResponse struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Inbounds []*core.InboundHandlerConfig `protobuf:"bytes,1,rep,name=inbounds,proto3" json:"inbounds,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListInboundsResponse) Reset() {
|
|
||||||
*x = ListInboundsResponse{}
|
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[9]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListInboundsResponse) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*ListInboundsResponse) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *ListInboundsResponse) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_command_command_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 ListInboundsResponse.ProtoReflect.Descriptor instead.
|
|
||||||
func (*ListInboundsResponse) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{9}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListInboundsResponse) GetInbounds() []*core.InboundHandlerConfig {
|
|
||||||
if x != nil {
|
|
||||||
return x.Inbounds
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type GetInboundUserRequest struct {
|
type GetInboundUserRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -456,7 +375,7 @@ type GetInboundUserRequest struct {
|
|||||||
|
|
||||||
func (x *GetInboundUserRequest) Reset() {
|
func (x *GetInboundUserRequest) Reset() {
|
||||||
*x = GetInboundUserRequest{}
|
*x = GetInboundUserRequest{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[10]
|
mi := &file_app_proxyman_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)
|
||||||
}
|
}
|
||||||
@ -468,7 +387,7 @@ func (x *GetInboundUserRequest) String() string {
|
|||||||
func (*GetInboundUserRequest) ProtoMessage() {}
|
func (*GetInboundUserRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[10]
|
mi := &file_app_proxyman_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 {
|
||||||
@ -481,7 +400,7 @@ func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetInboundUserRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetInboundUserRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*GetInboundUserRequest) Descriptor() ([]byte, []int) {
|
func (*GetInboundUserRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{10}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{8}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUserRequest) GetTag() string {
|
func (x *GetInboundUserRequest) GetTag() string {
|
||||||
@ -508,7 +427,7 @@ type GetInboundUserResponse struct {
|
|||||||
|
|
||||||
func (x *GetInboundUserResponse) Reset() {
|
func (x *GetInboundUserResponse) Reset() {
|
||||||
*x = GetInboundUserResponse{}
|
*x = GetInboundUserResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[11]
|
mi := &file_app_proxyman_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)
|
||||||
}
|
}
|
||||||
@ -520,7 +439,7 @@ func (x *GetInboundUserResponse) String() string {
|
|||||||
func (*GetInboundUserResponse) ProtoMessage() {}
|
func (*GetInboundUserResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message {
|
func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[11]
|
mi := &file_app_proxyman_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 {
|
||||||
@ -533,7 +452,7 @@ func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetInboundUserResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetInboundUserResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*GetInboundUserResponse) Descriptor() ([]byte, []int) {
|
func (*GetInboundUserResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{11}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{9}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUserResponse) GetUsers() []*protocol.User {
|
func (x *GetInboundUserResponse) GetUsers() []*protocol.User {
|
||||||
@ -553,7 +472,7 @@ type GetInboundUsersCountResponse struct {
|
|||||||
|
|
||||||
func (x *GetInboundUsersCountResponse) Reset() {
|
func (x *GetInboundUsersCountResponse) Reset() {
|
||||||
*x = GetInboundUsersCountResponse{}
|
*x = GetInboundUsersCountResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[12]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[10]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -565,7 +484,7 @@ func (x *GetInboundUsersCountResponse) String() string {
|
|||||||
func (*GetInboundUsersCountResponse) ProtoMessage() {}
|
func (*GetInboundUsersCountResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Message {
|
func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[12]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[10]
|
||||||
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 {
|
||||||
@ -578,7 +497,7 @@ func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetInboundUsersCountResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetInboundUsersCountResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*GetInboundUsersCountResponse) Descriptor() ([]byte, []int) {
|
func (*GetInboundUsersCountResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{12}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{10}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUsersCountResponse) GetCount() int64 {
|
func (x *GetInboundUsersCountResponse) GetCount() int64 {
|
||||||
@ -598,7 +517,7 @@ type AddOutboundRequest struct {
|
|||||||
|
|
||||||
func (x *AddOutboundRequest) Reset() {
|
func (x *AddOutboundRequest) Reset() {
|
||||||
*x = AddOutboundRequest{}
|
*x = AddOutboundRequest{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[13]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[11]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -610,7 +529,7 @@ func (x *AddOutboundRequest) String() string {
|
|||||||
func (*AddOutboundRequest) ProtoMessage() {}
|
func (*AddOutboundRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message {
|
func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[13]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[11]
|
||||||
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 {
|
||||||
@ -623,7 +542,7 @@ func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AddOutboundRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AddOutboundRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*AddOutboundRequest) Descriptor() ([]byte, []int) {
|
func (*AddOutboundRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{13}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{11}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AddOutboundRequest) GetOutbound() *core.OutboundHandlerConfig {
|
func (x *AddOutboundRequest) GetOutbound() *core.OutboundHandlerConfig {
|
||||||
@ -641,7 +560,7 @@ type AddOutboundResponse struct {
|
|||||||
|
|
||||||
func (x *AddOutboundResponse) Reset() {
|
func (x *AddOutboundResponse) Reset() {
|
||||||
*x = AddOutboundResponse{}
|
*x = AddOutboundResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[14]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[12]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -653,7 +572,7 @@ func (x *AddOutboundResponse) String() string {
|
|||||||
func (*AddOutboundResponse) ProtoMessage() {}
|
func (*AddOutboundResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message {
|
func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[14]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[12]
|
||||||
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 {
|
||||||
@ -666,7 +585,7 @@ func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AddOutboundResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AddOutboundResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*AddOutboundResponse) Descriptor() ([]byte, []int) {
|
func (*AddOutboundResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{14}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{12}
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveOutboundRequest struct {
|
type RemoveOutboundRequest struct {
|
||||||
@ -679,7 +598,7 @@ type RemoveOutboundRequest struct {
|
|||||||
|
|
||||||
func (x *RemoveOutboundRequest) Reset() {
|
func (x *RemoveOutboundRequest) Reset() {
|
||||||
*x = RemoveOutboundRequest{}
|
*x = RemoveOutboundRequest{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[15]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[13]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -691,7 +610,7 @@ func (x *RemoveOutboundRequest) String() string {
|
|||||||
func (*RemoveOutboundRequest) ProtoMessage() {}
|
func (*RemoveOutboundRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message {
|
func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[15]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[13]
|
||||||
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 {
|
||||||
@ -704,7 +623,7 @@ func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use RemoveOutboundRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RemoveOutboundRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*RemoveOutboundRequest) Descriptor() ([]byte, []int) {
|
func (*RemoveOutboundRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{15}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{13}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RemoveOutboundRequest) GetTag() string {
|
func (x *RemoveOutboundRequest) GetTag() string {
|
||||||
@ -722,7 +641,7 @@ type RemoveOutboundResponse struct {
|
|||||||
|
|
||||||
func (x *RemoveOutboundResponse) Reset() {
|
func (x *RemoveOutboundResponse) Reset() {
|
||||||
*x = RemoveOutboundResponse{}
|
*x = RemoveOutboundResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[16]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[14]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -734,7 +653,7 @@ func (x *RemoveOutboundResponse) String() string {
|
|||||||
func (*RemoveOutboundResponse) ProtoMessage() {}
|
func (*RemoveOutboundResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message {
|
func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[16]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[14]
|
||||||
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 {
|
||||||
@ -747,7 +666,7 @@ func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use RemoveOutboundResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RemoveOutboundResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*RemoveOutboundResponse) Descriptor() ([]byte, []int) {
|
func (*RemoveOutboundResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{16}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{14}
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlterOutboundRequest struct {
|
type AlterOutboundRequest struct {
|
||||||
@ -761,7 +680,7 @@ type AlterOutboundRequest struct {
|
|||||||
|
|
||||||
func (x *AlterOutboundRequest) Reset() {
|
func (x *AlterOutboundRequest) Reset() {
|
||||||
*x = AlterOutboundRequest{}
|
*x = AlterOutboundRequest{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[17]
|
mi := &file_app_proxyman_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)
|
||||||
}
|
}
|
||||||
@ -773,7 +692,7 @@ func (x *AlterOutboundRequest) String() string {
|
|||||||
func (*AlterOutboundRequest) ProtoMessage() {}
|
func (*AlterOutboundRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message {
|
func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[17]
|
mi := &file_app_proxyman_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 {
|
||||||
@ -786,7 +705,7 @@ func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AlterOutboundRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AlterOutboundRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*AlterOutboundRequest) Descriptor() ([]byte, []int) {
|
func (*AlterOutboundRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{17}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{15}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AlterOutboundRequest) GetTag() string {
|
func (x *AlterOutboundRequest) GetTag() string {
|
||||||
@ -811,7 +730,7 @@ type AlterOutboundResponse struct {
|
|||||||
|
|
||||||
func (x *AlterOutboundResponse) Reset() {
|
func (x *AlterOutboundResponse) Reset() {
|
||||||
*x = AlterOutboundResponse{}
|
*x = AlterOutboundResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[18]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[16]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -823,7 +742,7 @@ func (x *AlterOutboundResponse) String() string {
|
|||||||
func (*AlterOutboundResponse) ProtoMessage() {}
|
func (*AlterOutboundResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message {
|
func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[18]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[16]
|
||||||
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 {
|
||||||
@ -836,88 +755,7 @@ func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AlterOutboundResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AlterOutboundResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*AlterOutboundResponse) Descriptor() ([]byte, []int) {
|
func (*AlterOutboundResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{18}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{16}
|
||||||
}
|
|
||||||
|
|
||||||
type ListOutboundsRequest struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListOutboundsRequest) Reset() {
|
|
||||||
*x = ListOutboundsRequest{}
|
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[19]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListOutboundsRequest) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*ListOutboundsRequest) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *ListOutboundsRequest) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[19]
|
|
||||||
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 ListOutboundsRequest.ProtoReflect.Descriptor instead.
|
|
||||||
func (*ListOutboundsRequest) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{19}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ListOutboundsResponse struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Outbounds []*core.OutboundHandlerConfig `protobuf:"bytes,1,rep,name=outbounds,proto3" json:"outbounds,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListOutboundsResponse) Reset() {
|
|
||||||
*x = ListOutboundsResponse{}
|
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[20]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListOutboundsResponse) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*ListOutboundsResponse) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *ListOutboundsResponse) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[20]
|
|
||||||
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 ListOutboundsResponse.ProtoReflect.Descriptor instead.
|
|
||||||
func (*ListOutboundsResponse) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{20}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ListOutboundsResponse) GetOutbounds() []*core.OutboundHandlerConfig {
|
|
||||||
if x != nil {
|
|
||||||
return x.Outbounds
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@ -928,7 +766,7 @@ type Config struct {
|
|||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
*x = Config{}
|
*x = Config{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[21]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[17]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@ -940,7 +778,7 @@ func (x *Config) String() string {
|
|||||||
func (*Config) ProtoMessage() {}
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[21]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[17]
|
||||||
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 {
|
||||||
@ -953,7 +791,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
func (*Config) Descriptor() ([]byte, []int) {
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{21}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{17}
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_app_proxyman_command_command_proto protoreflect.FileDescriptor
|
var File_app_proxyman_command_command_proto protoreflect.FileDescriptor
|
||||||
@ -993,82 +831,61 @@ var file_app_proxyman_command_command_proto_rawDesc = []byte{
|
|||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70,
|
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,
|
0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62,
|
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62,
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x0a, 0x13,
|
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x15,
|
||||||
0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75,
|
0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65,
|
||||||
0x65, 0x73, 0x74, 0x22, 0x53, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x69,
|
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c,
|
||||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52,
|
||||||
0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08,
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73,
|
||||||
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x3f, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49,
|
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
||||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73,
|
||||||
0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x1c, 0x47, 0x65, 0x74,
|
||||||
0x74, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01,
|
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e,
|
||||||
0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a, 0x16, 0x47, 0x65, 0x74,
|
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75,
|
||||||
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22,
|
||||||
0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03,
|
0x52, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65,
|
||||||
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05,
|
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||||
0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f,
|
0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64,
|
||||||
0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73,
|
0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f,
|
||||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01,
|
0x75, 0x6e, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
||||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x52, 0x0a, 0x12, 0x41,
|
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x15, 0x52, 0x65,
|
||||||
0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
||||||
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,
|
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,
|
0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f,
|
||||||
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79,
|
0x68, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
||||||
0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72,
|
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65,
|
||||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16,
|
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78,
|
||||||
0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52,
|
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x57, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75,
|
0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09,
|
||||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74,
|
||||||
0x3e, 0x0a, 0x09, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03,
|
0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f,
|
0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xc5, 0x07, 0x0a,
|
||||||
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f,
|
0x0e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22,
|
0x6b, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e,
|
||||||
0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xae, 0x09, 0x0a, 0x0e, 0x48, 0x61,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||||
0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x0a,
|
0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62,
|
||||||
0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x78, 0x72, 0x61,
|
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x72,
|
||||||
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,
|
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,
|
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75,
|
||||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d,
|
||||||
0x71, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12,
|
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e,
|
||||||
0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
||||||
0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
|
||||||
0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d,
|
||||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76,
|
||||||
0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
0x65, 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,
|
0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75,
|
||||||
0x64, 0x73, 0x12, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
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, 0x4c,
|
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41,
|
||||||
0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
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,
|
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,
|
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41,
|
||||||
0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x78, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 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,
|
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,
|
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
@ -1107,22 +924,14 @@ var file_app_proxyman_command_command_proto_rawDesc = []byte{
|
|||||||
0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
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,
|
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,
|
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,
|
0x73, 0x65, 0x22, 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f,
|
||||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||||
0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52,
|
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f,
|
||||||
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x19, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41,
|
||||||
0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73,
|
0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f,
|
0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
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 (
|
||||||
@ -1137,7 +946,7 @@ func file_app_proxyman_command_command_proto_rawDescGZIP() []byte {
|
|||||||
return file_app_proxyman_command_command_proto_rawDescData
|
return file_app_proxyman_command_command_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_app_proxyman_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
|
var file_app_proxyman_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
|
||||||
var file_app_proxyman_command_command_proto_goTypes = []any{
|
var file_app_proxyman_command_command_proto_goTypes = []any{
|
||||||
(*AddUserOperation)(nil), // 0: xray.app.proxyman.command.AddUserOperation
|
(*AddUserOperation)(nil), // 0: xray.app.proxyman.command.AddUserOperation
|
||||||
(*RemoveUserOperation)(nil), // 1: xray.app.proxyman.command.RemoveUserOperation
|
(*RemoveUserOperation)(nil), // 1: xray.app.proxyman.command.RemoveUserOperation
|
||||||
@ -1147,59 +956,49 @@ var file_app_proxyman_command_command_proto_goTypes = []any{
|
|||||||
(*RemoveInboundResponse)(nil), // 5: xray.app.proxyman.command.RemoveInboundResponse
|
(*RemoveInboundResponse)(nil), // 5: xray.app.proxyman.command.RemoveInboundResponse
|
||||||
(*AlterInboundRequest)(nil), // 6: xray.app.proxyman.command.AlterInboundRequest
|
(*AlterInboundRequest)(nil), // 6: xray.app.proxyman.command.AlterInboundRequest
|
||||||
(*AlterInboundResponse)(nil), // 7: xray.app.proxyman.command.AlterInboundResponse
|
(*AlterInboundResponse)(nil), // 7: xray.app.proxyman.command.AlterInboundResponse
|
||||||
(*ListInboundsRequest)(nil), // 8: xray.app.proxyman.command.ListInboundsRequest
|
(*GetInboundUserRequest)(nil), // 8: xray.app.proxyman.command.GetInboundUserRequest
|
||||||
(*ListInboundsResponse)(nil), // 9: xray.app.proxyman.command.ListInboundsResponse
|
(*GetInboundUserResponse)(nil), // 9: xray.app.proxyman.command.GetInboundUserResponse
|
||||||
(*GetInboundUserRequest)(nil), // 10: xray.app.proxyman.command.GetInboundUserRequest
|
(*GetInboundUsersCountResponse)(nil), // 10: xray.app.proxyman.command.GetInboundUsersCountResponse
|
||||||
(*GetInboundUserResponse)(nil), // 11: xray.app.proxyman.command.GetInboundUserResponse
|
(*AddOutboundRequest)(nil), // 11: xray.app.proxyman.command.AddOutboundRequest
|
||||||
(*GetInboundUsersCountResponse)(nil), // 12: xray.app.proxyman.command.GetInboundUsersCountResponse
|
(*AddOutboundResponse)(nil), // 12: xray.app.proxyman.command.AddOutboundResponse
|
||||||
(*AddOutboundRequest)(nil), // 13: xray.app.proxyman.command.AddOutboundRequest
|
(*RemoveOutboundRequest)(nil), // 13: xray.app.proxyman.command.RemoveOutboundRequest
|
||||||
(*AddOutboundResponse)(nil), // 14: xray.app.proxyman.command.AddOutboundResponse
|
(*RemoveOutboundResponse)(nil), // 14: xray.app.proxyman.command.RemoveOutboundResponse
|
||||||
(*RemoveOutboundRequest)(nil), // 15: xray.app.proxyman.command.RemoveOutboundRequest
|
(*AlterOutboundRequest)(nil), // 15: xray.app.proxyman.command.AlterOutboundRequest
|
||||||
(*RemoveOutboundResponse)(nil), // 16: xray.app.proxyman.command.RemoveOutboundResponse
|
(*AlterOutboundResponse)(nil), // 16: xray.app.proxyman.command.AlterOutboundResponse
|
||||||
(*AlterOutboundRequest)(nil), // 17: xray.app.proxyman.command.AlterOutboundRequest
|
(*Config)(nil), // 17: xray.app.proxyman.command.Config
|
||||||
(*AlterOutboundResponse)(nil), // 18: xray.app.proxyman.command.AlterOutboundResponse
|
(*protocol.User)(nil), // 18: xray.common.protocol.User
|
||||||
(*ListOutboundsRequest)(nil), // 19: xray.app.proxyman.command.ListOutboundsRequest
|
(*core.InboundHandlerConfig)(nil), // 19: xray.core.InboundHandlerConfig
|
||||||
(*ListOutboundsResponse)(nil), // 20: xray.app.proxyman.command.ListOutboundsResponse
|
(*serial.TypedMessage)(nil), // 20: xray.common.serial.TypedMessage
|
||||||
(*Config)(nil), // 21: xray.app.proxyman.command.Config
|
(*core.OutboundHandlerConfig)(nil), // 21: xray.core.OutboundHandlerConfig
|
||||||
(*protocol.User)(nil), // 22: xray.common.protocol.User
|
|
||||||
(*core.InboundHandlerConfig)(nil), // 23: xray.core.InboundHandlerConfig
|
|
||||||
(*serial.TypedMessage)(nil), // 24: xray.common.serial.TypedMessage
|
|
||||||
(*core.OutboundHandlerConfig)(nil), // 25: xray.core.OutboundHandlerConfig
|
|
||||||
}
|
}
|
||||||
var file_app_proxyman_command_command_proto_depIdxs = []int32{
|
var file_app_proxyman_command_command_proto_depIdxs = []int32{
|
||||||
22, // 0: xray.app.proxyman.command.AddUserOperation.user:type_name -> xray.common.protocol.User
|
18, // 0: xray.app.proxyman.command.AddUserOperation.user:type_name -> xray.common.protocol.User
|
||||||
23, // 1: xray.app.proxyman.command.AddInboundRequest.inbound:type_name -> xray.core.InboundHandlerConfig
|
19, // 1: xray.app.proxyman.command.AddInboundRequest.inbound:type_name -> xray.core.InboundHandlerConfig
|
||||||
24, // 2: xray.app.proxyman.command.AlterInboundRequest.operation:type_name -> xray.common.serial.TypedMessage
|
20, // 2: xray.app.proxyman.command.AlterInboundRequest.operation:type_name -> xray.common.serial.TypedMessage
|
||||||
23, // 3: xray.app.proxyman.command.ListInboundsResponse.inbounds:type_name -> xray.core.InboundHandlerConfig
|
18, // 3: xray.app.proxyman.command.GetInboundUserResponse.users:type_name -> xray.common.protocol.User
|
||||||
22, // 4: xray.app.proxyman.command.GetInboundUserResponse.users:type_name -> xray.common.protocol.User
|
21, // 4: xray.app.proxyman.command.AddOutboundRequest.outbound:type_name -> xray.core.OutboundHandlerConfig
|
||||||
25, // 5: xray.app.proxyman.command.AddOutboundRequest.outbound:type_name -> xray.core.OutboundHandlerConfig
|
20, // 5: xray.app.proxyman.command.AlterOutboundRequest.operation:type_name -> xray.common.serial.TypedMessage
|
||||||
24, // 6: xray.app.proxyman.command.AlterOutboundRequest.operation:type_name -> xray.common.serial.TypedMessage
|
2, // 6: xray.app.proxyman.command.HandlerService.AddInbound:input_type -> xray.app.proxyman.command.AddInboundRequest
|
||||||
25, // 7: xray.app.proxyman.command.ListOutboundsResponse.outbounds:type_name -> xray.core.OutboundHandlerConfig
|
4, // 7: xray.app.proxyman.command.HandlerService.RemoveInbound:input_type -> xray.app.proxyman.command.RemoveInboundRequest
|
||||||
2, // 8: xray.app.proxyman.command.HandlerService.AddInbound:input_type -> xray.app.proxyman.command.AddInboundRequest
|
6, // 8: xray.app.proxyman.command.HandlerService.AlterInbound:input_type -> xray.app.proxyman.command.AlterInboundRequest
|
||||||
4, // 9: xray.app.proxyman.command.HandlerService.RemoveInbound:input_type -> xray.app.proxyman.command.RemoveInboundRequest
|
8, // 9: xray.app.proxyman.command.HandlerService.GetInboundUsers:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
||||||
6, // 10: xray.app.proxyman.command.HandlerService.AlterInbound:input_type -> xray.app.proxyman.command.AlterInboundRequest
|
8, // 10: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
||||||
8, // 11: xray.app.proxyman.command.HandlerService.ListInbounds:input_type -> xray.app.proxyman.command.ListInboundsRequest
|
11, // 11: xray.app.proxyman.command.HandlerService.AddOutbound:input_type -> xray.app.proxyman.command.AddOutboundRequest
|
||||||
10, // 12: xray.app.proxyman.command.HandlerService.GetInboundUsers:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
13, // 12: xray.app.proxyman.command.HandlerService.RemoveOutbound:input_type -> xray.app.proxyman.command.RemoveOutboundRequest
|
||||||
10, // 13: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
15, // 13: xray.app.proxyman.command.HandlerService.AlterOutbound:input_type -> xray.app.proxyman.command.AlterOutboundRequest
|
||||||
13, // 14: xray.app.proxyman.command.HandlerService.AddOutbound:input_type -> xray.app.proxyman.command.AddOutboundRequest
|
3, // 14: xray.app.proxyman.command.HandlerService.AddInbound:output_type -> xray.app.proxyman.command.AddInboundResponse
|
||||||
15, // 15: xray.app.proxyman.command.HandlerService.RemoveOutbound:input_type -> xray.app.proxyman.command.RemoveOutboundRequest
|
5, // 15: xray.app.proxyman.command.HandlerService.RemoveInbound:output_type -> xray.app.proxyman.command.RemoveInboundResponse
|
||||||
17, // 16: xray.app.proxyman.command.HandlerService.AlterOutbound:input_type -> xray.app.proxyman.command.AlterOutboundRequest
|
7, // 16: xray.app.proxyman.command.HandlerService.AlterInbound:output_type -> xray.app.proxyman.command.AlterInboundResponse
|
||||||
19, // 17: xray.app.proxyman.command.HandlerService.ListOutbounds:input_type -> xray.app.proxyman.command.ListOutboundsRequest
|
9, // 17: xray.app.proxyman.command.HandlerService.GetInboundUsers:output_type -> xray.app.proxyman.command.GetInboundUserResponse
|
||||||
3, // 18: xray.app.proxyman.command.HandlerService.AddInbound:output_type -> xray.app.proxyman.command.AddInboundResponse
|
10, // 18: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:output_type -> xray.app.proxyman.command.GetInboundUsersCountResponse
|
||||||
5, // 19: xray.app.proxyman.command.HandlerService.RemoveInbound:output_type -> xray.app.proxyman.command.RemoveInboundResponse
|
12, // 19: xray.app.proxyman.command.HandlerService.AddOutbound:output_type -> xray.app.proxyman.command.AddOutboundResponse
|
||||||
7, // 20: xray.app.proxyman.command.HandlerService.AlterInbound:output_type -> xray.app.proxyman.command.AlterInboundResponse
|
14, // 20: xray.app.proxyman.command.HandlerService.RemoveOutbound:output_type -> xray.app.proxyman.command.RemoveOutboundResponse
|
||||||
9, // 21: xray.app.proxyman.command.HandlerService.ListInbounds:output_type -> xray.app.proxyman.command.ListInboundsResponse
|
16, // 21: xray.app.proxyman.command.HandlerService.AlterOutbound:output_type -> xray.app.proxyman.command.AlterOutboundResponse
|
||||||
11, // 22: xray.app.proxyman.command.HandlerService.GetInboundUsers:output_type -> xray.app.proxyman.command.GetInboundUserResponse
|
14, // [14:22] is the sub-list for method output_type
|
||||||
12, // 23: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:output_type -> xray.app.proxyman.command.GetInboundUsersCountResponse
|
6, // [6:14] is the sub-list for method input_type
|
||||||
14, // 24: xray.app.proxyman.command.HandlerService.AddOutbound:output_type -> xray.app.proxyman.command.AddOutboundResponse
|
6, // [6:6] is the sub-list for extension type_name
|
||||||
16, // 25: xray.app.proxyman.command.HandlerService.RemoveOutbound:output_type -> xray.app.proxyman.command.RemoveOutboundResponse
|
6, // [6:6] is the sub-list for extension extendee
|
||||||
18, // 26: xray.app.proxyman.command.HandlerService.AlterOutbound:output_type -> xray.app.proxyman.command.AlterOutboundResponse
|
0, // [0:6] is the sub-list for field type_name
|
||||||
20, // 27: xray.app.proxyman.command.HandlerService.ListOutbounds:output_type -> xray.app.proxyman.command.ListOutboundsResponse
|
|
||||||
18, // [18:28] is the sub-list for method output_type
|
|
||||||
8, // [8:18] is the sub-list for method input_type
|
|
||||||
8, // [8:8] is the sub-list for extension type_name
|
|
||||||
8, // [8:8] is the sub-list for extension extendee
|
|
||||||
0, // [0:8] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_proxyman_command_command_proto_init() }
|
func init() { file_app_proxyman_command_command_proto_init() }
|
||||||
@ -1213,7 +1012,7 @@ func file_app_proxyman_command_command_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_proxyman_command_command_proto_rawDesc,
|
RawDescriptor: file_app_proxyman_command_command_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 22,
|
NumMessages: 18,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
@ -37,12 +37,6 @@ message AlterInboundRequest {
|
|||||||
|
|
||||||
message AlterInboundResponse {}
|
message AlterInboundResponse {}
|
||||||
|
|
||||||
message ListInboundsRequest {}
|
|
||||||
|
|
||||||
message ListInboundsResponse {
|
|
||||||
repeated core.InboundHandlerConfig inbounds = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GetInboundUserRequest {
|
message GetInboundUserRequest {
|
||||||
string tag = 1;
|
string tag = 1;
|
||||||
string email = 2;
|
string email = 2;
|
||||||
@ -75,12 +69,6 @@ message AlterOutboundRequest {
|
|||||||
|
|
||||||
message AlterOutboundResponse {}
|
message AlterOutboundResponse {}
|
||||||
|
|
||||||
message ListOutboundsRequest {}
|
|
||||||
|
|
||||||
message ListOutboundsResponse {
|
|
||||||
repeated core.OutboundHandlerConfig outbounds = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
service HandlerService {
|
service HandlerService {
|
||||||
rpc AddInbound(AddInboundRequest) returns (AddInboundResponse) {}
|
rpc AddInbound(AddInboundRequest) returns (AddInboundResponse) {}
|
||||||
|
|
||||||
@ -88,8 +76,6 @@ service HandlerService {
|
|||||||
|
|
||||||
rpc AlterInbound(AlterInboundRequest) returns (AlterInboundResponse) {}
|
rpc AlterInbound(AlterInboundRequest) returns (AlterInboundResponse) {}
|
||||||
|
|
||||||
rpc ListInbounds(ListInboundsRequest) returns (ListInboundsResponse) {}
|
|
||||||
|
|
||||||
rpc GetInboundUsers(GetInboundUserRequest) returns (GetInboundUserResponse) {}
|
rpc GetInboundUsers(GetInboundUserRequest) returns (GetInboundUserResponse) {}
|
||||||
|
|
||||||
rpc GetInboundUsersCount(GetInboundUserRequest) returns (GetInboundUsersCountResponse) {}
|
rpc GetInboundUsersCount(GetInboundUserRequest) returns (GetInboundUsersCountResponse) {}
|
||||||
@ -99,8 +85,6 @@ service HandlerService {
|
|||||||
rpc RemoveOutbound(RemoveOutboundRequest) returns (RemoveOutboundResponse) {}
|
rpc RemoveOutbound(RemoveOutboundRequest) returns (RemoveOutboundResponse) {}
|
||||||
|
|
||||||
rpc AlterOutbound(AlterOutboundRequest) returns (AlterOutboundResponse) {}
|
rpc AlterOutbound(AlterOutboundRequest) returns (AlterOutboundResponse) {}
|
||||||
|
|
||||||
rpc ListOutbounds(ListOutboundsRequest) returns (ListOutboundsResponse) {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {}
|
message Config {}
|
||||||
|
@ -22,13 +22,11 @@ const (
|
|||||||
HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound"
|
HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound"
|
||||||
HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound"
|
HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound"
|
||||||
HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound"
|
HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound"
|
||||||
HandlerService_ListInbounds_FullMethodName = "/xray.app.proxyman.command.HandlerService/ListInbounds"
|
|
||||||
HandlerService_GetInboundUsers_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsers"
|
HandlerService_GetInboundUsers_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsers"
|
||||||
HandlerService_GetInboundUsersCount_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsersCount"
|
HandlerService_GetInboundUsersCount_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsersCount"
|
||||||
HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound"
|
HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound"
|
||||||
HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound"
|
HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound"
|
||||||
HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound"
|
HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound"
|
||||||
HandlerService_ListOutbounds_FullMethodName = "/xray.app.proxyman.command.HandlerService/ListOutbounds"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandlerServiceClient is the client API for HandlerService service.
|
// HandlerServiceClient is the client API for HandlerService service.
|
||||||
@ -38,13 +36,11 @@ type HandlerServiceClient interface {
|
|||||||
AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error)
|
AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error)
|
||||||
RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error)
|
RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error)
|
||||||
AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error)
|
AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error)
|
||||||
ListInbounds(ctx context.Context, in *ListInboundsRequest, opts ...grpc.CallOption) (*ListInboundsResponse, error)
|
|
||||||
GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error)
|
GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error)
|
||||||
GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error)
|
GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error)
|
||||||
AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error)
|
AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error)
|
||||||
RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error)
|
RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error)
|
||||||
AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error)
|
AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error)
|
||||||
ListOutbounds(ctx context.Context, in *ListOutboundsRequest, opts ...grpc.CallOption) (*ListOutboundsResponse, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type handlerServiceClient struct {
|
type handlerServiceClient struct {
|
||||||
@ -85,16 +81,6 @@ func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboun
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *handlerServiceClient) ListInbounds(ctx context.Context, in *ListInboundsRequest, opts ...grpc.CallOption) (*ListInboundsResponse, error) {
|
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
|
||||||
out := new(ListInboundsResponse)
|
|
||||||
err := c.cc.Invoke(ctx, HandlerService_ListInbounds_FullMethodName, in, out, cOpts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *handlerServiceClient) GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error) {
|
func (c *handlerServiceClient) GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error) {
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(GetInboundUserResponse)
|
out := new(GetInboundUserResponse)
|
||||||
@ -145,16 +131,6 @@ func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutbo
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *handlerServiceClient) ListOutbounds(ctx context.Context, in *ListOutboundsRequest, opts ...grpc.CallOption) (*ListOutboundsResponse, error) {
|
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
|
||||||
out := new(ListOutboundsResponse)
|
|
||||||
err := c.cc.Invoke(ctx, HandlerService_ListOutbounds_FullMethodName, in, out, cOpts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandlerServiceServer is the server API for HandlerService service.
|
// HandlerServiceServer is the server API for HandlerService service.
|
||||||
// All implementations must embed UnimplementedHandlerServiceServer
|
// All implementations must embed UnimplementedHandlerServiceServer
|
||||||
// for forward compatibility.
|
// for forward compatibility.
|
||||||
@ -162,13 +138,11 @@ type HandlerServiceServer interface {
|
|||||||
AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error)
|
AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error)
|
||||||
RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error)
|
RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error)
|
||||||
AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error)
|
AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error)
|
||||||
ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error)
|
|
||||||
GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error)
|
GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error)
|
||||||
GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error)
|
GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error)
|
||||||
AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error)
|
AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error)
|
||||||
RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error)
|
RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error)
|
||||||
AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error)
|
AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error)
|
||||||
ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error)
|
|
||||||
mustEmbedUnimplementedHandlerServiceServer()
|
mustEmbedUnimplementedHandlerServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,9 +162,6 @@ func (UnimplementedHandlerServiceServer) RemoveInbound(context.Context, *RemoveI
|
|||||||
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.Errorf(codes.Unimplemented, "method AlterInbound not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error) {
|
|
||||||
return nil, status.Errorf(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.Errorf(codes.Unimplemented, "method GetInboundUsers not implemented")
|
||||||
}
|
}
|
||||||
@ -206,9 +177,6 @@ func (UnimplementedHandlerServiceServer) RemoveOutbound(context.Context, *Remove
|
|||||||
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.Errorf(codes.Unimplemented, "method AlterOutbound not implemented")
|
||||||
}
|
}
|
||||||
func (UnimplementedHandlerServiceServer) ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ListOutbounds not implemented")
|
|
||||||
}
|
|
||||||
func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
||||||
func (UnimplementedHandlerServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedHandlerServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
@ -284,24 +252,6 @@ func _HandlerService_AlterInbound_Handler(srv interface{}, ctx context.Context,
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _HandlerService_ListInbounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(ListInboundsRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(HandlerServiceServer).ListInbounds(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: HandlerService_ListInbounds_FullMethodName,
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(HandlerServiceServer).ListInbounds(ctx, req.(*ListInboundsRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _HandlerService_GetInboundUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _HandlerService_GetInboundUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(GetInboundUserRequest)
|
in := new(GetInboundUserRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@ -392,24 +342,6 @@ func _HandlerService_AlterOutbound_Handler(srv interface{}, ctx context.Context,
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func _HandlerService_ListOutbounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(ListOutboundsRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(HandlerServiceServer).ListOutbounds(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: HandlerService_ListOutbounds_FullMethodName,
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(HandlerServiceServer).ListOutbounds(ctx, req.(*ListOutboundsRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandlerService_ServiceDesc is the grpc.ServiceDesc for HandlerService service.
|
// HandlerService_ServiceDesc is the grpc.ServiceDesc for HandlerService 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)
|
||||||
@ -429,10 +361,6 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "AlterInbound",
|
MethodName: "AlterInbound",
|
||||||
Handler: _HandlerService_AlterInbound_Handler,
|
Handler: _HandlerService_AlterInbound_Handler,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MethodName: "ListInbounds",
|
|
||||||
Handler: _HandlerService_ListInbounds_Handler,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
MethodName: "GetInboundUsers",
|
MethodName: "GetInboundUsers",
|
||||||
Handler: _HandlerService_GetInboundUsers_Handler,
|
Handler: _HandlerService_GetInboundUsers_Handler,
|
||||||
@ -453,10 +381,6 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "AlterOutbound",
|
MethodName: "AlterOutbound",
|
||||||
Handler: _HandlerService_AlterOutbound_Handler,
|
Handler: _HandlerService_AlterOutbound_Handler,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
MethodName: "ListOutbounds",
|
|
||||||
Handler: _HandlerService_ListOutbounds_Handler,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "app/proxyman/command/command.proto",
|
Metadata: "app/proxyman/command/command.proto",
|
||||||
|
@ -9,13 +9,11 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/policy"
|
"github.com/xtls/xray-core/features/policy"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
||||||
@ -44,8 +42,6 @@ func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AlwaysOnInboundHandler struct {
|
type AlwaysOnInboundHandler struct {
|
||||||
proxyConfig interface{}
|
|
||||||
receiverConfig *proxyman.ReceiverConfig
|
|
||||||
proxy proxy.Inbound
|
proxy proxy.Inbound
|
||||||
workers []worker
|
workers []worker
|
||||||
mux *mux.Server
|
mux *mux.Server
|
||||||
@ -63,8 +59,6 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
}
|
}
|
||||||
|
|
||||||
h := &AlwaysOnInboundHandler{
|
h := &AlwaysOnInboundHandler{
|
||||||
receiverConfig: receiverConfig,
|
|
||||||
proxyConfig: proxyConfig,
|
|
||||||
proxy: p,
|
proxy: p,
|
||||||
mux: mux.NewServer(ctx),
|
mux: mux.NewServer(ctx),
|
||||||
tag: tag,
|
tag: tag,
|
||||||
@ -193,16 +187,3 @@ func (h *AlwaysOnInboundHandler) Tag() string {
|
|||||||
func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound {
|
func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound {
|
||||||
return h.proxy
|
return h.proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReceiverSettings implements inbound.Handler.
|
|
||||||
func (h *AlwaysOnInboundHandler) ReceiverSettings() *serial.TypedMessage {
|
|
||||||
return serial.ToTypedMessage(h.receiverConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProxySettings implements inbound.Handler.
|
|
||||||
func (h *AlwaysOnInboundHandler) ProxySettings() *serial.TypedMessage {
|
|
||||||
if v, ok := h.proxyConfig.(proto.Message); ok {
|
|
||||||
return serial.ToTypedMessage(v)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -10,12 +10,10 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DynamicInboundHandler struct {
|
type DynamicInboundHandler struct {
|
||||||
@ -207,16 +205,3 @@ func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port,
|
|||||||
func (h *DynamicInboundHandler) Tag() string {
|
func (h *DynamicInboundHandler) Tag() string {
|
||||||
return h.tag
|
return h.tag
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReceiverSettings implements inbound.Handler.
|
|
||||||
func (h *DynamicInboundHandler) ReceiverSettings() *serial.TypedMessage {
|
|
||||||
return serial.ToTypedMessage(h.receiverConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProxySettings implements inbound.Handler.
|
|
||||||
func (h *DynamicInboundHandler) ProxySettings() *serial.TypedMessage {
|
|
||||||
if v, ok := h.proxyConfig.(proto.Message); ok {
|
|
||||||
return serial.ToTypedMessage(v)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -89,21 +89,6 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
|
|||||||
return common.ErrNoClue
|
return common.ErrNoClue
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListHandlers implements inbound.Manager.
|
|
||||||
func (m *Manager) ListHandlers(ctx context.Context) []inbound.Handler {
|
|
||||||
m.access.RLock()
|
|
||||||
defer m.access.RUnlock()
|
|
||||||
|
|
||||||
var response []inbound.Handler
|
|
||||||
copy(m.untaggedHandler, response)
|
|
||||||
|
|
||||||
for _, v := range m.taggedHandlers {
|
|
||||||
response = append(response, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start implements common.Runnable.
|
// Start implements common.Runnable.
|
||||||
func (m *Manager) Start() error {
|
func (m *Manager) Start() error {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
|
@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
@ -28,7 +27,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
"github.com/xtls/xray-core/transport/pipe"
|
"github.com/xtls/xray-core/transport/pipe"
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
||||||
@ -61,7 +59,6 @@ type Handler struct {
|
|||||||
tag string
|
tag string
|
||||||
senderSettings *proxyman.SenderConfig
|
senderSettings *proxyman.SenderConfig
|
||||||
streamSettings *internet.MemoryStreamConfig
|
streamSettings *internet.MemoryStreamConfig
|
||||||
proxyConfig proto.Message
|
|
||||||
proxy proxy.Outbound
|
proxy proxy.Outbound
|
||||||
outboundManager outbound.Manager
|
outboundManager outbound.Manager
|
||||||
mux *mux.ClientManager
|
mux *mux.ClientManager
|
||||||
@ -104,7 +101,6 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
h.proxyConfig = proxyConfig
|
|
||||||
|
|
||||||
rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
|
rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -245,9 +241,7 @@ func (h *Handler) DestIpAddress() net.IP {
|
|||||||
// Dial implements internet.Dialer.
|
// Dial implements internet.Dialer.
|
||||||
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
||||||
if h.senderSettings != nil {
|
if h.senderSettings != nil {
|
||||||
|
|
||||||
if h.senderSettings.ProxySettings.HasTag() {
|
if h.senderSettings.ProxySettings.HasTag() {
|
||||||
|
|
||||||
tag := h.senderSettings.ProxySettings.Tag
|
tag := h.senderSettings.ProxySettings.Tag
|
||||||
handler := h.outboundManager.GetHandler(tag)
|
handler := h.outboundManager.GetHandler(tag)
|
||||||
if handler != nil {
|
if handler != nil {
|
||||||
@ -276,45 +270,23 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
|||||||
}
|
}
|
||||||
|
|
||||||
if h.senderSettings.Via != nil {
|
if h.senderSettings.Via != nil {
|
||||||
|
|
||||||
outbounds := session.OutboundsFromContext(ctx)
|
outbounds := session.OutboundsFromContext(ctx)
|
||||||
ob := outbounds[len(outbounds)-1]
|
ob := outbounds[len(outbounds)-1]
|
||||||
var domain string
|
if h.senderSettings.ViaCidr == "" {
|
||||||
addr := h.senderSettings.Via.AsAddress()
|
if h.senderSettings.Via.AsAddress().Family().IsDomain() && h.senderSettings.Via.AsAddress().Domain() == "origin" {
|
||||||
domain = h.senderSettings.Via.GetDomain()
|
|
||||||
switch {
|
|
||||||
case h.senderSettings.ViaCidr != "":
|
|
||||||
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
|
|
||||||
|
|
||||||
case domain == "origin":
|
|
||||||
|
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
if inbound.Conn != nil {
|
|
||||||
origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String())
|
origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String())
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ob.Gateway = net.ParseAddress(origin)
|
ob.Gateway = net.ParseAddress(origin)
|
||||||
errors.LogDebug(ctx, "use receive package ip as snedthrough: ", origin)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
ob.Gateway = h.senderSettings.Via.AsAddress()
|
||||||
}
|
}
|
||||||
case domain == "srcip":
|
} else { //Get a random address.
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
ob.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr)
|
||||||
if inbound.Conn != nil {
|
|
||||||
clientaddr, _, err := net.SplitHostPort(inbound.Conn.RemoteAddr().String())
|
|
||||||
if err == nil {
|
|
||||||
ob.Gateway = net.ParseAddress(clientaddr)
|
|
||||||
errors.LogDebug(ctx, "use client src ip as snedthrough: ", clientaddr)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
//case addr.Family().IsDomain():
|
|
||||||
default:
|
|
||||||
ob.Gateway = addr
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
|
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
|
||||||
@ -353,35 +325,23 @@ func (h *Handler) Start() error {
|
|||||||
// Close implements common.Closable.
|
// Close implements common.Closable.
|
||||||
func (h *Handler) Close() error {
|
func (h *Handler) Close() error {
|
||||||
common.Close(h.mux)
|
common.Close(h.mux)
|
||||||
common.Close(h.proxy)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SenderSettings implements outbound.Handler.
|
func ParseRandomIPv6(address net.Address, prefix string) net.Address {
|
||||||
func (h *Handler) SenderSettings() *serial.TypedMessage {
|
_, network, _ := gonet.ParseCIDR(address.IP().String() + "/" + prefix)
|
||||||
return serial.ToTypedMessage(h.senderSettings)
|
|
||||||
}
|
maskSize, totalBits := network.Mask.Size()
|
||||||
|
subnetSize := big.NewInt(1).Lsh(big.NewInt(1), uint(totalBits-maskSize))
|
||||||
// ProxySettings implements outbound.Handler.
|
|
||||||
func (h *Handler) ProxySettings() *serial.TypedMessage {
|
// random
|
||||||
return serial.ToTypedMessage(h.proxyConfig)
|
randomBigInt, _ := rand.Int(rand.Reader, subnetSize)
|
||||||
}
|
|
||||||
|
startIPBigInt := big.NewInt(0).SetBytes(network.IP.To16())
|
||||||
func ParseRandomIP(addr net.Address, prefix string) net.Address {
|
randomIPBigInt := big.NewInt(0).Add(startIPBigInt, randomBigInt)
|
||||||
|
|
||||||
_, ipnet, _ := gonet.ParseCIDR(addr.IP().String() + "/" + prefix)
|
randomIPBytes := randomIPBigInt.Bytes()
|
||||||
|
randomIPBytes = append(make([]byte, 16-len(randomIPBytes)), randomIPBytes...)
|
||||||
ones, bits := ipnet.Mask.Size()
|
|
||||||
subnetSize := new(big.Int).Lsh(big.NewInt(1), uint(bits-ones))
|
return net.ParseAddress(gonet.IP(randomIPBytes).String())
|
||||||
|
|
||||||
rnd, _ := rand.Int(rand.Reader, subnetSize)
|
|
||||||
|
|
||||||
startInt := new(big.Int).SetBytes(ipnet.IP)
|
|
||||||
rndInt := new(big.Int).Add(startInt, rnd)
|
|
||||||
|
|
||||||
rndBytes := rndInt.Bytes()
|
|
||||||
padded := make([]byte, len(ipnet.IP))
|
|
||||||
copy(padded[len(padded)-len(rndBytes):], rndBytes)
|
|
||||||
|
|
||||||
return net.ParseAddress(gonet.IP(padded).String())
|
|
||||||
}
|
}
|
||||||
|
@ -145,21 +145,6 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListHandlers implements outbound.Manager.
|
|
||||||
func (m *Manager) ListHandlers(ctx context.Context) []outbound.Handler {
|
|
||||||
m.access.RLock()
|
|
||||||
defer m.access.RUnlock()
|
|
||||||
|
|
||||||
var response []outbound.Handler
|
|
||||||
copy(m.untaggedHandlers, response)
|
|
||||||
|
|
||||||
for _, v := range m.taggedHandler {
|
|
||||||
response = append(response, v)
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
|
|
||||||
// Select implements outbound.HandlerSelector.
|
// Select implements outbound.HandlerSelector.
|
||||||
func (m *Manager) Select(selectors []string) []string {
|
func (m *Manager) Select(selectors []string) []string {
|
||||||
|
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
@ -112,16 +111,6 @@ func (o *Outbound) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SenderSettings implements outbound.Handler.
|
|
||||||
func (o *Outbound) SenderSettings() *serial.TypedMessage {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProxySettings implements outbound.Handler.
|
|
||||||
func (o *Outbound) ProxySettings() *serial.TypedMessage {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type StaticMuxPicker struct {
|
type StaticMuxPicker struct {
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
workers []*PortalWorker
|
workers []*PortalWorker
|
||||||
|
@ -119,7 +119,7 @@ type MultiGeoIPMatcher struct {
|
|||||||
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
||||||
var matchers []*GeoIPMatcher
|
var matchers []*GeoIPMatcher
|
||||||
for _, geoip := range geoips {
|
for _, geoip := range geoips {
|
||||||
matcher, err := GlobalGeoIPContainer.Add(geoip)
|
matcher, err := globalGeoIPContainer.Add(geoip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -115,30 +115,4 @@ func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var GlobalGeoIPContainer GeoIPMatcherContainer
|
var globalGeoIPContainer GeoIPMatcherContainer
|
||||||
|
|
||||||
func MatchIPs(matchers []*GeoIPMatcher, ips []net.IP, reverse bool) []net.IP {
|
|
||||||
if len(matchers) == 0 {
|
|
||||||
panic("GeoIP matchers should not be empty to avoid ambiguity")
|
|
||||||
}
|
|
||||||
newIPs := make([]net.IP, 0, len(ips))
|
|
||||||
var isFound bool
|
|
||||||
for _, ip := range ips {
|
|
||||||
isFound = false
|
|
||||||
for _, matcher := range matchers {
|
|
||||||
if matcher.Match(ip) {
|
|
||||||
isFound = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isFound && !reverse {
|
|
||||||
newIPs = append(newIPs, ip)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if !isFound && reverse {
|
|
||||||
newIPs = append(newIPs, ip)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newIPs
|
|
||||||
}
|
|
||||||
|
@ -177,7 +177,7 @@ func TestIPOnDemand(t *testing.T) {
|
|||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
}).Return([]net.IP{{192, 168, 0, 1}}, uint32(600), nil).AnyTimes()
|
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
||||||
@ -222,7 +222,7 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
|||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
}).Return([]net.IP{{192, 168, 0, 1}}, uint32(600), nil).AnyTimes()
|
}).Return([]net.IP{{192, 168, 0, 1}}, nil).AnyTimes()
|
||||||
|
|
||||||
r := new(Router)
|
r := new(Router)
|
||||||
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
||||||
|
@ -40,11 +40,11 @@ func (c *OnlineMap) AddIP(ip string) {
|
|||||||
if ip == "127.0.0.1" {
|
if ip == "127.0.0.1" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.access.Lock()
|
|
||||||
if _, ok := list[ip]; !ok {
|
if _, ok := list[ip]; !ok {
|
||||||
|
c.access.Lock()
|
||||||
list[ip] = time.Now()
|
list[ip] = time.Now()
|
||||||
}
|
|
||||||
c.access.Unlock()
|
c.access.Unlock()
|
||||||
|
}
|
||||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
||||||
list = c.RemoveExpiredIPs(list)
|
list = c.RemoveExpiredIPs(list)
|
||||||
c.lastCleanup = time.Now()
|
c.lastCleanup = time.Now()
|
||||||
|
@ -13,19 +13,8 @@ const (
|
|||||||
Size = 8192
|
Size = 8192
|
||||||
)
|
)
|
||||||
|
|
||||||
var zero = [Size * 10]byte{0}
|
|
||||||
|
|
||||||
var pool = bytespool.GetPool(Size)
|
var pool = bytespool.GetPool(Size)
|
||||||
|
|
||||||
// ownership represents the data owner of the buffer.
|
|
||||||
type ownership uint8
|
|
||||||
|
|
||||||
const (
|
|
||||||
managed ownership = iota
|
|
||||||
unmanaged
|
|
||||||
bytespools
|
|
||||||
)
|
|
||||||
|
|
||||||
// Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
|
// Buffer is a recyclable allocation of a byte array. Buffer.Release() recycles
|
||||||
// the buffer into an internal buffer pool, in order to recreate a buffer more
|
// the buffer into an internal buffer pool, in order to recreate a buffer more
|
||||||
// quickly.
|
// quickly.
|
||||||
@ -33,11 +22,11 @@ type Buffer struct {
|
|||||||
v []byte
|
v []byte
|
||||||
start int32
|
start int32
|
||||||
end int32
|
end int32
|
||||||
ownership ownership
|
unmanaged bool
|
||||||
UDP *net.Destination
|
UDP *net.Destination
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a Buffer with 0 length and 8K capacity, managed.
|
// New creates a Buffer with 0 length and 8K capacity.
|
||||||
func New() *Buffer {
|
func New() *Buffer {
|
||||||
buf := pool.Get().([]byte)
|
buf := pool.Get().([]byte)
|
||||||
if cap(buf) >= Size {
|
if cap(buf) >= Size {
|
||||||
@ -51,7 +40,7 @@ func New() *Buffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewExisted creates a standard size Buffer with an existed bytearray, managed.
|
// NewExisted creates a managed, standard size Buffer with an existed bytearray
|
||||||
func NewExisted(b []byte) *Buffer {
|
func NewExisted(b []byte) *Buffer {
|
||||||
if cap(b) < Size {
|
if cap(b) < Size {
|
||||||
panic("Invalid buffer")
|
panic("Invalid buffer")
|
||||||
@ -68,16 +57,16 @@ func NewExisted(b []byte) *Buffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromBytes creates a Buffer with an existed bytearray, unmanaged.
|
// FromBytes creates a Buffer with an existed bytearray
|
||||||
func FromBytes(b []byte) *Buffer {
|
func FromBytes(b []byte) *Buffer {
|
||||||
return &Buffer{
|
return &Buffer{
|
||||||
v: b,
|
v: b,
|
||||||
end: int32(len(b)),
|
end: int32(len(b)),
|
||||||
ownership: unmanaged,
|
unmanaged: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// StackNew creates a new Buffer object on stack, managed.
|
// StackNew creates a new Buffer object on stack.
|
||||||
// This method is for buffers that is released in the same function.
|
// This method is for buffers that is released in the same function.
|
||||||
func StackNew() Buffer {
|
func StackNew() Buffer {
|
||||||
buf := pool.Get().([]byte)
|
buf := pool.Get().([]byte)
|
||||||
@ -92,17 +81,9 @@ func StackNew() Buffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWithSize creates a Buffer with 0 length and capacity with at least the given size, bytespool's.
|
|
||||||
func NewWithSize(size int32) *Buffer {
|
|
||||||
return &Buffer{
|
|
||||||
v: bytespool.Alloc(size),
|
|
||||||
ownership: bytespools,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release recycles the buffer into an internal buffer pool.
|
// Release recycles the buffer into an internal buffer pool.
|
||||||
func (b *Buffer) Release() {
|
func (b *Buffer) Release() {
|
||||||
if b == nil || b.v == nil || b.ownership == unmanaged {
|
if b == nil || b.v == nil || b.unmanaged {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,14 +91,9 @@ func (b *Buffer) Release() {
|
|||||||
b.v = nil
|
b.v = nil
|
||||||
b.Clear()
|
b.Clear()
|
||||||
|
|
||||||
switch b.ownership {
|
|
||||||
case managed:
|
|
||||||
if cap(p) == Size {
|
if cap(p) == Size {
|
||||||
pool.Put(p)
|
pool.Put(p)
|
||||||
}
|
}
|
||||||
case bytespools:
|
|
||||||
bytespool.Free(p)
|
|
||||||
}
|
|
||||||
b.UDP = nil
|
b.UDP = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,7 +128,6 @@ func (b *Buffer) Extend(n int32) []byte {
|
|||||||
}
|
}
|
||||||
ext := b.v[b.end:end]
|
ext := b.v[b.end:end]
|
||||||
b.end = end
|
b.end = end
|
||||||
copy(ext, zero[:])
|
|
||||||
return ext
|
return ext
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,7 +176,6 @@ func (b *Buffer) Check() {
|
|||||||
|
|
||||||
// Resize cuts the buffer at the given position.
|
// Resize cuts the buffer at the given position.
|
||||||
func (b *Buffer) Resize(from, to int32) {
|
func (b *Buffer) Resize(from, to int32) {
|
||||||
oldEnd := b.end
|
|
||||||
if from < 0 {
|
if from < 0 {
|
||||||
from += b.Len()
|
from += b.Len()
|
||||||
}
|
}
|
||||||
@ -214,9 +188,6 @@ func (b *Buffer) Resize(from, to int32) {
|
|||||||
b.end = b.start + to
|
b.end = b.start + to
|
||||||
b.start += from
|
b.start += from
|
||||||
b.Check()
|
b.Check()
|
||||||
if b.end > oldEnd {
|
|
||||||
copy(b.v[oldEnd:b.end], zero[:])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Advance cuts the buffer at the given position.
|
// Advance cuts the buffer at the given position.
|
||||||
@ -244,6 +215,13 @@ func (b *Buffer) Cap() int32 {
|
|||||||
return int32(len(b.v))
|
return int32(len(b.v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewWithSize creates a Buffer with 0 length and capacity with at least the given size.
|
||||||
|
func NewWithSize(size int32) *Buffer {
|
||||||
|
return &Buffer{
|
||||||
|
v: bytespool.Alloc(size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// IsEmpty returns true if the buffer is empty.
|
// IsEmpty returns true if the buffer is empty.
|
||||||
func (b *Buffer) IsEmpty() bool {
|
func (b *Buffer) IsEmpty() bool {
|
||||||
return b.Len() == 0
|
return b.Len() == 0
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package errors
|
package errors
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,12 +36,12 @@ func AllEqual(expected error, actual error) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, err := range errs {
|
for _, err := range errs {
|
||||||
if !errors.Is(err, expected) {
|
if err != expected {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
return errors.Is(errs, expected)
|
return errs == expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package filesystem
|
|||||||
import (
|
import (
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/platform"
|
"github.com/xtls/xray-core/common/platform"
|
||||||
@ -29,13 +28,6 @@ func ReadAsset(file string) ([]byte, error) {
|
|||||||
return ReadFile(platform.GetAssetLocation(file))
|
return ReadFile(platform.GetAssetLocation(file))
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadCert(file string) ([]byte, error) {
|
|
||||||
if filepath.IsAbs(file) {
|
|
||||||
return ReadFile(file)
|
|
||||||
}
|
|
||||||
return ReadFile(platform.GetCertLocation(file))
|
|
||||||
}
|
|
||||||
|
|
||||||
func CopyFile(dst string, src string) error {
|
func CopyFile(dst string, src string) error {
|
||||||
bytes, err := ReadFile(src)
|
bytes, err := ReadFile(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -21,7 +21,7 @@ func GetToolLocation(file string) string {
|
|||||||
return filepath.Join(toolPath, file)
|
return filepath.Join(toolPath, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAssetLocation searches for `file` in the env dir, the executable dir, and certain locations
|
// GetAssetLocation searches for `file` in certain locations
|
||||||
func GetAssetLocation(file string) string {
|
func GetAssetLocation(file string) string {
|
||||||
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
||||||
defPath := filepath.Join(assetPath, file)
|
defPath := filepath.Join(assetPath, file)
|
||||||
@ -42,9 +42,3 @@ func GetAssetLocation(file string) string {
|
|||||||
// asset not found, let the caller throw out the error
|
// asset not found, let the caller throw out the error
|
||||||
return defPath
|
return defPath
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCertLocation searches for `file` in the env dir and the executable dir
|
|
||||||
func GetCertLocation(file string) string {
|
|
||||||
certPath := NewEnvFlag(CertLocation).GetValue(getExecutableDir)
|
|
||||||
return filepath.Join(certPath, file)
|
|
||||||
}
|
|
||||||
|
@ -13,7 +13,6 @@ const (
|
|||||||
ConfdirLocation = "xray.location.confdir"
|
ConfdirLocation = "xray.location.confdir"
|
||||||
ToolLocation = "xray.location.tool"
|
ToolLocation = "xray.location.tool"
|
||||||
AssetLocation = "xray.location.asset"
|
AssetLocation = "xray.location.asset"
|
||||||
CertLocation = "xray.location.cert"
|
|
||||||
|
|
||||||
UseReadV = "xray.buf.readv"
|
UseReadV = "xray.buf.readv"
|
||||||
UseFreedomSplice = "xray.buf.splice"
|
UseFreedomSplice = "xray.buf.splice"
|
||||||
|
@ -19,14 +19,8 @@ func GetToolLocation(file string) string {
|
|||||||
return filepath.Join(toolPath, file+".exe")
|
return filepath.Join(toolPath, file+".exe")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAssetLocation searches for `file` in the env dir and the executable dir
|
// GetAssetLocation searches for `file` in the executable dir
|
||||||
func GetAssetLocation(file string) string {
|
func GetAssetLocation(file string) string {
|
||||||
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
||||||
return filepath.Join(assetPath, file)
|
return filepath.Join(assetPath, file)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCertLocation searches for `file` in the env dir and the executable dir
|
|
||||||
func GetCertLocation(file string) string {
|
|
||||||
certPath := NewEnvFlag(CertLocation).GetValue(getExecutableDir)
|
|
||||||
return filepath.Join(certPath, file)
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1 @@
|
|||||||
package protocol // import "github.com/xtls/xray-core/common/protocol"
|
package protocol // import "github.com/xtls/xray-core/common/protocol"
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ErrProtoNeedMoreData = errors.New("protocol matches, but need more data to complete sniffing")
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package quic
|
package quic
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto"
|
"crypto"
|
||||||
"crypto/aes"
|
"crypto/aes"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
@ -10,8 +11,8 @@ import (
|
|||||||
"github.com/quic-go/quic-go/quicvarint"
|
"github.com/quic-go/quic-go/quicvarint"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
|
"github.com/xtls/xray-core/common/bytespool"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
|
||||||
ptls "github.com/xtls/xray-core/common/protocol/tls"
|
ptls "github.com/xtls/xray-core/common/protocol/tls"
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
)
|
)
|
||||||
@ -46,17 +47,22 @@ var (
|
|||||||
errNotQuicInitial = errors.New("not initial packet")
|
errNotQuicInitial = errors.New("not initial packet")
|
||||||
)
|
)
|
||||||
|
|
||||||
func SniffQUIC(b []byte) (*SniffHeader, error) {
|
func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
|
||||||
if len(b) == 0 {
|
// In extremely rare cases, this sniffer may cause slice error
|
||||||
return nil, common.ErrNoClue
|
// and we set recover() here to prevent crash.
|
||||||
|
// TODO: Thoroughly fix this panic
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
errors.LogError(context.Background(), "Failed to sniff QUIC: ", r)
|
||||||
|
resultReturn = nil
|
||||||
|
errorReturn = common.ErrNoClue
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
// Crypto data separated across packets
|
// Crypto data separated across packets
|
||||||
cryptoLen := int32(0)
|
cryptoLen := 0
|
||||||
cryptoDataBuf := buf.NewWithSize(32767)
|
cryptoData := bytespool.Alloc(int32(len(b)))
|
||||||
defer cryptoDataBuf.Release()
|
defer bytespool.Free(cryptoData)
|
||||||
cache := buf.New()
|
|
||||||
defer cache.Release()
|
|
||||||
|
|
||||||
// Parse QUIC packets
|
// Parse QUIC packets
|
||||||
for len(b) > 0 {
|
for len(b) > 0 {
|
||||||
@ -99,7 +105,6 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
|||||||
return nil, errNotQuic
|
return nil, errNotQuic
|
||||||
}
|
}
|
||||||
|
|
||||||
if isQuicInitial { // Only initial packets have token, see https://datatracker.ietf.org/doc/html/rfc9000#section-17.2.2
|
|
||||||
tokenLen, err := quicvarint.Read(buffer)
|
tokenLen, err := quicvarint.Read(buffer)
|
||||||
if err != nil || tokenLen > uint64(len(b)) {
|
if err != nil || tokenLen > uint64(len(b)) {
|
||||||
return nil, errNotQuic
|
return nil, errNotQuic
|
||||||
@ -108,16 +113,11 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
|||||||
if _, err = buffer.ReadBytes(int32(tokenLen)); err != nil {
|
if _, err = buffer.ReadBytes(int32(tokenLen)); err != nil {
|
||||||
return nil, errNotQuic
|
return nil, errNotQuic
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
packetLen, err := quicvarint.Read(buffer)
|
packetLen, err := quicvarint.Read(buffer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errNotQuic
|
return nil, errNotQuic
|
||||||
}
|
}
|
||||||
// packetLen is impossible to be shorter than this
|
|
||||||
if packetLen < 4 {
|
|
||||||
return nil, errNotQuic
|
|
||||||
}
|
|
||||||
|
|
||||||
hdrLen := len(b) - int(buffer.Len())
|
hdrLen := len(b) - int(buffer.Len())
|
||||||
if len(b) < hdrLen+int(packetLen) {
|
if len(b) < hdrLen+int(packetLen) {
|
||||||
@ -130,6 +130,9 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
origPNBytes := make([]byte, 4)
|
||||||
|
copy(origPNBytes, b[hdrLen:hdrLen+4])
|
||||||
|
|
||||||
var salt []byte
|
var salt []byte
|
||||||
if versionNumber == version1 {
|
if versionNumber == version1 {
|
||||||
salt = quicSalt
|
salt = quicSalt
|
||||||
@ -144,34 +147,44 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.Clear()
|
cache := buf.New()
|
||||||
|
defer cache.Release()
|
||||||
|
|
||||||
mask := cache.Extend(int32(block.BlockSize()))
|
mask := cache.Extend(int32(block.BlockSize()))
|
||||||
block.Encrypt(mask, b[hdrLen+4:hdrLen+4+len(mask)])
|
block.Encrypt(mask, b[hdrLen+4:hdrLen+4+16])
|
||||||
b[0] ^= mask[0] & 0xf
|
b[0] ^= mask[0] & 0xf
|
||||||
packetNumberLength := int(b[0]&0x3 + 1)
|
for i := range b[hdrLen : hdrLen+4] {
|
||||||
for i := range packetNumberLength {
|
|
||||||
b[hdrLen+i] ^= mask[i+1]
|
b[hdrLen+i] ^= mask[i+1]
|
||||||
}
|
}
|
||||||
|
packetNumberLength := b[0]&0x3 + 1
|
||||||
|
if packetNumberLength != 1 {
|
||||||
|
return nil, errNotQuicInitial
|
||||||
|
}
|
||||||
|
var packetNumber uint32
|
||||||
|
{
|
||||||
|
n, err := buffer.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
packetNumber = uint32(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
extHdrLen := hdrLen + int(packetNumberLength)
|
||||||
|
copy(b[extHdrLen:hdrLen+4], origPNBytes[packetNumberLength:])
|
||||||
|
data := b[extHdrLen : int(packetLen)+hdrLen]
|
||||||
|
|
||||||
key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
|
key := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic key", 16)
|
||||||
iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
|
iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
|
||||||
cipher := AEADAESGCMTLS13(key, iv)
|
cipher := AEADAESGCMTLS13(key, iv)
|
||||||
|
|
||||||
nonce := cache.Extend(int32(cipher.NonceSize()))
|
nonce := cache.Extend(int32(cipher.NonceSize()))
|
||||||
_, err = buffer.Read(nonce[len(nonce)-packetNumberLength:])
|
binary.BigEndian.PutUint64(nonce[len(nonce)-8:], uint64(packetNumber))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
extHdrLen := hdrLen + packetNumberLength
|
|
||||||
data := b[extHdrLen : int(packetLen)+hdrLen]
|
|
||||||
decrypted, err := cipher.Open(b[extHdrLen:extHdrLen], nonce, data, b[:extHdrLen])
|
decrypted, err := cipher.Open(b[extHdrLen:extHdrLen], nonce, data, b[:extHdrLen])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
buffer = buf.FromBytes(decrypted)
|
buffer = buf.FromBytes(decrypted)
|
||||||
for !buffer.IsEmpty() {
|
for i := 0; !buffer.IsEmpty(); i++ {
|
||||||
frameType, _ := buffer.ReadByte()
|
frameType := byte(0x0) // Default to PADDING frame
|
||||||
for frameType == 0x0 && !buffer.IsEmpty() {
|
for frameType == 0x0 && !buffer.IsEmpty() {
|
||||||
frameType, _ = buffer.ReadByte()
|
frameType, _ = buffer.ReadByte()
|
||||||
}
|
}
|
||||||
@ -220,15 +233,16 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
|||||||
if err != nil || length > uint64(buffer.Len()) {
|
if err != nil || length > uint64(buffer.Len()) {
|
||||||
return nil, io.ErrUnexpectedEOF
|
return nil, io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
currentCryptoLen := int32(offset + length)
|
if cryptoLen < int(offset+length) {
|
||||||
if cryptoLen < currentCryptoLen {
|
cryptoLen = int(offset + length)
|
||||||
if cryptoDataBuf.Cap() < currentCryptoLen {
|
if len(cryptoData) < cryptoLen {
|
||||||
return nil, io.ErrShortBuffer
|
newCryptoData := bytespool.Alloc(int32(cryptoLen))
|
||||||
|
copy(newCryptoData, cryptoData)
|
||||||
|
bytespool.Free(cryptoData)
|
||||||
|
cryptoData = newCryptoData
|
||||||
}
|
}
|
||||||
cryptoDataBuf.Extend(currentCryptoLen - cryptoLen)
|
|
||||||
cryptoLen = currentCryptoLen
|
|
||||||
}
|
}
|
||||||
if _, err := buffer.Read(cryptoDataBuf.BytesRange(int32(offset), currentCryptoLen)); err != nil { // Field: Crypto Data
|
if _, err := buffer.Read(cryptoData[offset : offset+length]); err != nil { // Field: Crypto Data
|
||||||
return nil, io.ErrUnexpectedEOF
|
return nil, io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
case 0x1c: // CONNECTION_CLOSE frame, only 0x1c is permitted in initial packet
|
case 0x1c: // CONNECTION_CLOSE frame, only 0x1c is permitted in initial packet
|
||||||
@ -253,7 +267,7 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tlsHdr := &ptls.SniffHeader{}
|
tlsHdr := &ptls.SniffHeader{}
|
||||||
err = ptls.ReadClientHello(cryptoDataBuf.BytesRange(0, cryptoLen), tlsHdr)
|
err = ptls.ReadClientHello(cryptoData[:cryptoLen], tlsHdr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// The crypto data may have not been fully recovered in current packets,
|
// The crypto data may have not been fully recovered in current packets,
|
||||||
// So we continue to sniff rest packets.
|
// So we continue to sniff rest packets.
|
||||||
@ -262,8 +276,7 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
|||||||
}
|
}
|
||||||
return &SniffHeader{domain: tlsHdr.Domain()}, nil
|
return &SniffHeader{domain: tlsHdr.Domain()}, nil
|
||||||
}
|
}
|
||||||
// All payload is parsed as valid QUIC packets, but we need more packets for crypto data to read client hello.
|
return nil, common.ErrNoClue
|
||||||
return nil, protocol.ErrProtoNeedMoreData
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hkdfExpandLabel(hash crypto.Hash, secret, context []byte, label string, length int) []byte {
|
func hkdfExpandLabel(hash crypto.Hash, secret, context []byte, label string, length int) []byte {
|
||||||
|
File diff suppressed because one or more lines are too long
2
common/protocol/tls/cert/.gitignore
vendored
Normal file
2
common/protocol/tls/cert/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.crt
|
||||||
|
*.key
|
@ -3,9 +3,9 @@ package tls
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SniffHeader struct {
|
type SniffHeader struct {
|
||||||
@ -59,6 +59,9 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
|
|||||||
}
|
}
|
||||||
data = data[1+compressionMethodsLen:]
|
data = data[1+compressionMethodsLen:]
|
||||||
|
|
||||||
|
if len(data) == 0 {
|
||||||
|
return errNotClientHello
|
||||||
|
}
|
||||||
if len(data) < 2 {
|
if len(data) < 2 {
|
||||||
return errNotClientHello
|
return errNotClientHello
|
||||||
}
|
}
|
||||||
@ -101,21 +104,13 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
|
|||||||
return errNotClientHello
|
return errNotClientHello
|
||||||
}
|
}
|
||||||
if nameType == 0 {
|
if nameType == 0 {
|
||||||
// QUIC separated across packets
|
serverName := string(d[:nameLen])
|
||||||
// May cause the serverName to be incomplete
|
|
||||||
b := byte(0)
|
|
||||||
for _, b = range d[:nameLen] {
|
|
||||||
if b <= ' ' {
|
|
||||||
return protocol.ErrProtoNeedMoreData
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// An SNI value may not include a
|
// An SNI value may not include a
|
||||||
// trailing dot. See
|
// trailing dot. See
|
||||||
// https://tools.ietf.org/html/rfc6066#section-3.
|
// https://tools.ietf.org/html/rfc6066#section-3.
|
||||||
if b == '.' {
|
if strings.HasSuffix(serverName, ".") {
|
||||||
return errNotClientHello
|
return errNotClientHello
|
||||||
}
|
}
|
||||||
serverName := string(d[:nameLen])
|
|
||||||
h.domain = serverName
|
h.domain = serverName
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -67,9 +67,9 @@ func (t *ActivityTimer) SetTimeout(timeout time.Duration) {
|
|||||||
t.checkTask.Close()
|
t.checkTask.Close()
|
||||||
}
|
}
|
||||||
t.checkTask = checkTask
|
t.checkTask = checkTask
|
||||||
|
t.Unlock()
|
||||||
t.Update()
|
t.Update()
|
||||||
common.Must(checkTask.Start())
|
common.Must(checkTask.Start())
|
||||||
t.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeout time.Duration) *ActivityTimer {
|
func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeout time.Duration) *ActivityTimer {
|
||||||
|
@ -18,8 +18,8 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
Version_x byte = 25
|
Version_x byte = 25
|
||||||
Version_y byte = 6
|
Version_y byte = 3
|
||||||
Version_z byte = 8
|
Version_z byte = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -90,11 +90,6 @@ type Instance struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instance state
|
|
||||||
func (server *Instance) IsRunning() bool {
|
|
||||||
return server.running
|
|
||||||
}
|
|
||||||
|
|
||||||
func AddInboundHandler(server *Instance, config *InboundHandlerConfig) error {
|
func AddInboundHandler(server *Instance, config *InboundHandlerConfig) error {
|
||||||
inboundManager := server.GetFeature(inbound.ManagerType()).(inbound.Manager)
|
inboundManager := server.GetFeature(inbound.ManagerType()).(inbound.Manager)
|
||||||
rawHandler, err := CreateObject(server, config)
|
rawHandler, err := CreateObject(server, config)
|
||||||
|
@ -21,7 +21,11 @@ type Client interface {
|
|||||||
features.Feature
|
features.Feature
|
||||||
|
|
||||||
// LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses.
|
// LookupIP returns IP address for the given domain. IPs may contain IPv4 and/or IPv6 addresses.
|
||||||
LookupIP(domain string, option IPOption) ([]net.IP, uint32, error)
|
LookupIP(domain string, option IPOption) ([]net.IP, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type HostsLookup interface {
|
||||||
|
LookupHosts(domain string) *net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientType returns the type of Client interface. Can be used for implementing common.HasType.
|
// ClientType returns the type of Client interface. Can be used for implementing common.HasType.
|
||||||
@ -34,8 +38,6 @@ func ClientType() interface{} {
|
|||||||
// ErrEmptyResponse indicates that DNS query succeeded but no answer was returned.
|
// ErrEmptyResponse indicates that DNS query succeeded but no answer was returned.
|
||||||
var ErrEmptyResponse = errors.New("empty response")
|
var ErrEmptyResponse = errors.New("empty response")
|
||||||
|
|
||||||
const DefaultTTL = 300
|
|
||||||
|
|
||||||
type RCodeError uint16
|
type RCodeError uint16
|
||||||
|
|
||||||
func (e RCodeError) Error() string {
|
func (e RCodeError) Error() string {
|
||||||
|
@ -20,44 +20,41 @@ func (*Client) Start() error { return nil }
|
|||||||
func (*Client) Close() error { return nil }
|
func (*Client) Close() error { return nil }
|
||||||
|
|
||||||
// LookupIP implements Client.
|
// LookupIP implements Client.
|
||||||
func (*Client) LookupIP(host string, option dns.IPOption) ([]net.IP, uint32, error) {
|
func (*Client) LookupIP(host string, option dns.IPOption) ([]net.IP, error) {
|
||||||
ips, err := net.LookupIP(host)
|
ips, err := net.LookupIP(host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, err
|
||||||
}
|
}
|
||||||
parsedIPs := make([]net.IP, 0, len(ips))
|
parsedIPs := make([]net.IP, 0, len(ips))
|
||||||
ipv4 := make([]net.IP, 0, len(ips))
|
ipv4 := make([]net.IP, 0, len(ips))
|
||||||
ipv6 := make([]net.IP, 0, len(ips))
|
ipv6 := make([]net.IP, 0, len(ips))
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
parsed := net.IPAddress(ip)
|
parsed := net.IPAddress(ip)
|
||||||
if parsed == nil {
|
if parsed != nil {
|
||||||
continue
|
parsedIPs = append(parsedIPs, parsed.IP())
|
||||||
}
|
}
|
||||||
parsedIP := parsed.IP()
|
if len(ip) == net.IPv4len {
|
||||||
parsedIPs = append(parsedIPs, parsedIP)
|
ipv4 = append(ipv4, ip)
|
||||||
|
}
|
||||||
if len(parsedIP) == net.IPv4len {
|
if len(ip) == net.IPv6len {
|
||||||
ipv4 = append(ipv4, parsedIP)
|
ipv6 = append(ipv6, ip)
|
||||||
} else {
|
|
||||||
ipv6 = append(ipv6, parsedIP)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case option.IPv4Enable && option.IPv6Enable:
|
case option.IPv4Enable && option.IPv6Enable:
|
||||||
if len(parsedIPs) > 0 {
|
if len(parsedIPs) > 0 {
|
||||||
return parsedIPs, dns.DefaultTTL, nil
|
return parsedIPs, nil
|
||||||
}
|
}
|
||||||
case option.IPv4Enable:
|
case option.IPv4Enable:
|
||||||
if len(ipv4) > 0 {
|
if len(ipv4) > 0 {
|
||||||
return ipv4, dns.DefaultTTL, nil
|
return ipv4, nil
|
||||||
}
|
}
|
||||||
case option.IPv6Enable:
|
case option.IPv6Enable:
|
||||||
if len(ipv6) > 0 {
|
if len(ipv6) > 0 {
|
||||||
return ipv6, dns.DefaultTTL, nil
|
return ipv6, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
return nil, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// New create a new dns.Client that queries localhost for DNS.
|
// New create a new dns.Client that queries localhost for DNS.
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/features"
|
"github.com/xtls/xray-core/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,10 +15,6 @@ type Handler interface {
|
|||||||
common.Runnable
|
common.Runnable
|
||||||
// The tag of this handler.
|
// The tag of this handler.
|
||||||
Tag() string
|
Tag() string
|
||||||
// Returns the active receiver settings.
|
|
||||||
ReceiverSettings() *serial.TypedMessage
|
|
||||||
// Returns the active proxy settings.
|
|
||||||
ProxySettings() *serial.TypedMessage
|
|
||||||
|
|
||||||
// Deprecated: Do not use in new code.
|
// Deprecated: Do not use in new code.
|
||||||
GetRandomInboundProxy() (interface{}, net.Port, int)
|
GetRandomInboundProxy() (interface{}, net.Port, int)
|
||||||
@ -37,9 +32,6 @@ type Manager interface {
|
|||||||
|
|
||||||
// RemoveHandler removes a handler from Manager.
|
// RemoveHandler removes a handler from Manager.
|
||||||
RemoveHandler(ctx context.Context, tag string) error
|
RemoveHandler(ctx context.Context, tag string) error
|
||||||
|
|
||||||
// ListHandlers returns a list of inbound.Handler.
|
|
||||||
ListHandlers(ctx context.Context) []Handler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManagerType returns the type of Manager interface. Can be used for implementing common.HasType.
|
// ManagerType returns the type of Manager interface. Can be used for implementing common.HasType.
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
|
||||||
"github.com/xtls/xray-core/features"
|
"github.com/xtls/xray-core/features"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
)
|
)
|
||||||
@ -16,8 +15,6 @@ type Handler interface {
|
|||||||
common.Runnable
|
common.Runnable
|
||||||
Tag() string
|
Tag() string
|
||||||
Dispatch(ctx context.Context, link *transport.Link)
|
Dispatch(ctx context.Context, link *transport.Link)
|
||||||
SenderSettings() *serial.TypedMessage
|
|
||||||
ProxySettings() *serial.TypedMessage
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type HandlerSelector interface {
|
type HandlerSelector interface {
|
||||||
@ -38,9 +35,6 @@ type Manager interface {
|
|||||||
|
|
||||||
// RemoveHandler removes a handler from outbound.Manager.
|
// RemoveHandler removes a handler from outbound.Manager.
|
||||||
RemoveHandler(ctx context.Context, tag string) error
|
RemoveHandler(ctx context.Context, tag string) error
|
||||||
|
|
||||||
// ListHandlers returns a list of outbound.Handler.
|
|
||||||
ListHandlers(ctx context.Context) []Handler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ManagerType returns the type of Manager interface. Can be used to implement common.HasType.
|
// ManagerType returns the type of Manager interface. Can be used to implement common.HasType.
|
||||||
|
@ -23,7 +23,7 @@ func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if domain := ctx.GetTargetDomain(); len(domain) != 0 {
|
if domain := ctx.GetTargetDomain(); len(domain) != 0 {
|
||||||
ips, _, err := ctx.dnsClient.LookupIP(domain, dns.IPOption{
|
ips, err := ctx.dnsClient.LookupIP(domain, dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
|
42
go.mod
42
go.mod
@ -4,34 +4,34 @@ go 1.24
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0
|
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0
|
||||||
github.com/cloudflare/circl v1.6.1
|
github.com/cloudflare/circl v1.6.0
|
||||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
||||||
github.com/golang/mock v1.7.0-rc.1
|
github.com/golang/mock v1.7.0-rc.1
|
||||||
github.com/google/go-cmp v0.7.0
|
github.com/google/go-cmp v0.7.0
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/miekg/dns v1.1.66
|
github.com/miekg/dns v1.1.63
|
||||||
github.com/pelletier/go-toml v1.9.5
|
github.com/pelletier/go-toml v1.9.5
|
||||||
github.com/pires/go-proxyproto v0.8.1
|
github.com/pires/go-proxyproto v0.8.0
|
||||||
github.com/quic-go/quic-go v0.52.0
|
github.com/quic-go/quic-go v0.50.0
|
||||||
github.com/refraction-networking/utls v1.7.3
|
github.com/refraction-networking/utls v1.6.7
|
||||||
github.com/sagernet/sing v0.5.1
|
github.com/sagernet/sing v0.5.1
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||||
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771
|
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||||
github.com/vishvananda/netlink v1.3.1
|
github.com/vishvananda/netlink v1.3.0
|
||||||
github.com/xtls/reality v0.0.0-20250608132114-50752aec6bfb
|
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/crypto v0.39.0
|
golang.org/x/crypto v0.36.0
|
||||||
golang.org/x/net v0.41.0
|
golang.org/x/net v0.37.0
|
||||||
golang.org/x/sync v0.15.0
|
golang.org/x/sync v0.12.0
|
||||||
golang.org/x/sys v0.33.0
|
golang.org/x/sys v0.31.0
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||||
google.golang.org/grpc v1.73.0
|
google.golang.org/grpc v1.71.0
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.5
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0
|
||||||
h12.io/socks v1.0.3
|
h12.io/socks v1.0.3
|
||||||
lukechampine.com/blake3 v1.4.1
|
lukechampine.com/blake3 v1.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -41,21 +41,21 @@ require (
|
|||||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||||
github.com/google/btree v1.1.2 // indirect
|
github.com/google/btree v1.1.2 // indirect
|
||||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect
|
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect
|
||||||
github.com/juju/ratelimit v1.0.2 // indirect
|
|
||||||
github.com/klauspost/compress v1.17.8 // indirect
|
github.com/klauspost/compress v1.17.8 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
|
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||||
github.com/vishvananda/netns v0.0.5 // indirect
|
github.com/vishvananda/netns v0.0.4 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
golang.org/x/mod v0.25.0 // indirect
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
|
||||||
golang.org/x/text v0.26.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
|
golang.org/x/text v0.23.0 // indirect
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.33.0 // indirect
|
golang.org/x/tools v0.26.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
104
go.sum
104
go.sum
@ -2,8 +2,8 @@ github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJS
|
|||||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
|
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
|
||||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@ -34,14 +34,12 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
|
|||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
|
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
|
||||||
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c=
|
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364/go.mod h1:eDJQioIyy4Yn3MVivT7rv/39gAJTrA7lgmYr8EW950c=
|
||||||
github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI=
|
|
||||||
github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
|
|
||||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||||
github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
|
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||||
github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
|
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||||
@ -50,16 +48,16 @@ github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3v
|
|||||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
|
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
|
||||||
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
||||||
github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0=
|
github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0=
|
||||||
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
|
github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||||
github.com/quic-go/quic-go v0.52.0 h1:/SlHrCRElyaU6MaEPKqKr9z83sBg2v4FLLvWM+Z47pA=
|
github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo=
|
||||||
github.com/quic-go/quic-go v0.52.0/go.mod h1:MFlGGpcpJqRAfmYi6NC2cptDPSxRWTOGNuP4wqrWmzQ=
|
github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
|
||||||
github.com/refraction-networking/utls v1.7.3 h1:L0WRhHY7Oq1T0zkdzVZMR6zWZv+sXbHB9zcuvsAEqCo=
|
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
|
||||||
github.com/refraction-networking/utls v1.7.3/go.mod h1:TUhh27RHMGtQvjQq+RyO11P6ZNQNBb3N0v7wsEjKAIQ=
|
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||||
github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y=
|
github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y=
|
||||||
@ -74,45 +72,47 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
|
|||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
|
||||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
|
||||||
github.com/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
|
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||||
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
|
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||||
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||||
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/xtls/reality v0.0.0-20250608132114-50752aec6bfb h1:X6ziJCMsFF8Ac/0F3W7+UbFdHZTu+r5nZ/smksHVxNQ=
|
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg=
|
||||||
github.com/xtls/reality v0.0.0-20250608132114-50752aec6bfb/go.mod h1:yD47RN65bDLZgyHWMfFDiqlzrq4usDMt/Xzsk6tMbhw=
|
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
|
||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
|
||||||
|
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
|
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||||
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -121,21 +121,21 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||||
golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
|
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||||
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
|
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -143,12 +143,12 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
|
|||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463 h1:e0AIkUUhxyBKh6ssZNrAMeqhA7RKUj42346d1y02i2g=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250324211829-b45e905df463/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
|
||||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@ -158,9 +158,9 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
|||||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 h1:sfK5nHuG7lRFZ2FdTT3RimOqWBg8IrVm+/Vko1FVOsk=
|
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 h1:P+U/06iIKPQ3DLcg+zBfSCia1luZ2msPZrJ8jYDFPs0=
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g=
|
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0/go.mod h1:NQHVAzMwvZ+Qe3ElSiHmq9RUm1MdNHpUZ52fiEqvn+0=
|
||||||
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
|
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
|
||||||
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
|
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
|
||||||
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w=
|
||||||
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
|
lukechampine.com/blake3 v1.4.0/go.mod h1:MQJNQCTnR+kwOP/JEZSxj3MaQjp80FOFSNMMHXcSeX0=
|
||||||
|
@ -8,13 +8,11 @@ import (
|
|||||||
|
|
||||||
type Duration int64
|
type Duration int64
|
||||||
|
|
||||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
|
||||||
func (d *Duration) MarshalJSON() ([]byte, error) {
|
func (d *Duration) MarshalJSON() ([]byte, error) {
|
||||||
dr := time.Duration(*d)
|
dr := time.Duration(*d)
|
||||||
return json.Marshal(dr.String())
|
return json.Marshal(dr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
|
||||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||||
var v interface{}
|
var v interface{}
|
||||||
if err := json.Unmarshal(b, &v); err != nil {
|
if err := json.Unmarshal(b, &v); err != nil {
|
||||||
|
@ -23,7 +23,6 @@ func (v StringList) Len() int {
|
|||||||
return len(v)
|
return len(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
|
||||||
func (v *StringList) UnmarshalJSON(data []byte) error {
|
func (v *StringList) UnmarshalJSON(data []byte) error {
|
||||||
var strarray []string
|
var strarray []string
|
||||||
if err := json.Unmarshal(data, &strarray); err == nil {
|
if err := json.Unmarshal(data, &strarray); err == nil {
|
||||||
@ -44,12 +43,10 @@ type Address struct {
|
|||||||
net.Address
|
net.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
func (v Address) MarshalJSON() ([]byte, error) {
|
||||||
func (v *Address) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(v.Address.String())
|
return json.Marshal(v.Address.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
|
||||||
func (v *Address) UnmarshalJSON(data []byte) error {
|
func (v *Address) UnmarshalJSON(data []byte) error {
|
||||||
var rawStr string
|
var rawStr string
|
||||||
if err := json.Unmarshal(data, &rawStr); err != nil {
|
if err := json.Unmarshal(data, &rawStr); err != nil {
|
||||||
@ -84,7 +81,6 @@ func (v Network) Build() net.Network {
|
|||||||
|
|
||||||
type NetworkList []Network
|
type NetworkList []Network
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
|
||||||
func (v *NetworkList) UnmarshalJSON(data []byte) error {
|
func (v *NetworkList) UnmarshalJSON(data []byte) error {
|
||||||
var strarray []Network
|
var strarray []Network
|
||||||
if err := json.Unmarshal(data, &strarray); err == nil {
|
if err := json.Unmarshal(data, &strarray); err == nil {
|
||||||
@ -173,19 +169,6 @@ func (v *PortRange) Build() *net.PortRange {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
|
||||||
func (v *PortRange) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(v.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (port *PortRange) String() string {
|
|
||||||
if port.From == port.To {
|
|
||||||
return strconv.Itoa(int(port.From))
|
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("%d-%d", port.From, port.To)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (v *PortRange) UnmarshalJSON(data []byte) error {
|
func (v *PortRange) UnmarshalJSON(data []byte) error {
|
||||||
port, err := parseIntPort(data)
|
port, err := parseIntPort(data)
|
||||||
@ -220,21 +203,20 @@ func (list *PortList) Build() *net.PortList {
|
|||||||
return portList
|
return portList
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
func (v PortList) MarshalJSON() ([]byte, error) {
|
||||||
func (v *PortList) MarshalJSON() ([]byte, error) {
|
return json.Marshal(v.String())
|
||||||
portStr := v.String()
|
|
||||||
port, err := strconv.Atoi(portStr)
|
|
||||||
if err == nil {
|
|
||||||
return json.Marshal(port)
|
|
||||||
} else {
|
|
||||||
return json.Marshal(portStr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v PortList) String() string {
|
func (v PortList) String() string {
|
||||||
ports := []string{}
|
ports := []string{}
|
||||||
for _, port := range v.Range {
|
for _, port := range v.Range {
|
||||||
ports = append(ports, port.String())
|
if port.From == port.To {
|
||||||
|
p := strconv.Itoa(int(port.From))
|
||||||
|
ports = append(ports, p)
|
||||||
|
} else {
|
||||||
|
p := fmt.Sprintf("%d-%d", port.From, port.To)
|
||||||
|
ports = append(ports, p)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return strings.Join(ports, ",")
|
return strings.Join(ports, ",")
|
||||||
}
|
}
|
||||||
@ -295,8 +277,7 @@ type Int32Range struct {
|
|||||||
To int32
|
To int32
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
func (v Int32Range) MarshalJSON() ([]byte, error) {
|
||||||
func (v *Int32Range) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(v.String())
|
return json.Marshal(v.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +289,6 @@ func (v Int32Range) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
|
||||||
func (v *Int32Range) UnmarshalJSON(data []byte) error {
|
func (v *Int32Range) UnmarshalJSON(data []byte) error {
|
||||||
defer v.ensureOrder()
|
defer v.ensureOrder()
|
||||||
var str string
|
var str string
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package conf
|
package conf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -21,17 +17,10 @@ type NameServerConfig struct {
|
|||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
SkipFallback bool `json:"skipFallback"`
|
SkipFallback bool `json:"skipFallback"`
|
||||||
Domains []string `json:"domains"`
|
Domains []string `json:"domains"`
|
||||||
ExpectedIPs StringList `json:"expectedIPs"`
|
ExpectIPs StringList `json:"expectIps"`
|
||||||
ExpectIPs StringList `json:"expectIPs"`
|
|
||||||
QueryStrategy string `json:"queryStrategy"`
|
QueryStrategy string `json:"queryStrategy"`
|
||||||
Tag string `json:"tag"`
|
|
||||||
TimeoutMs uint64 `json:"timeoutMs"`
|
|
||||||
DisableCache bool `json:"disableCache"`
|
|
||||||
FinalQuery bool `json:"finalQuery"`
|
|
||||||
UnexpectedIPs StringList `json:"unexpectedIPs"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
|
||||||
func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
||||||
var address Address
|
var address Address
|
||||||
if err := json.Unmarshal(data, &address); err == nil {
|
if err := json.Unmarshal(data, &address); err == nil {
|
||||||
@ -45,14 +34,8 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
|||||||
Port uint16 `json:"port"`
|
Port uint16 `json:"port"`
|
||||||
SkipFallback bool `json:"skipFallback"`
|
SkipFallback bool `json:"skipFallback"`
|
||||||
Domains []string `json:"domains"`
|
Domains []string `json:"domains"`
|
||||||
ExpectedIPs StringList `json:"expectedIPs"`
|
ExpectIPs StringList `json:"expectIps"`
|
||||||
ExpectIPs StringList `json:"expectIPs"`
|
|
||||||
QueryStrategy string `json:"queryStrategy"`
|
QueryStrategy string `json:"queryStrategy"`
|
||||||
Tag string `json:"tag"`
|
|
||||||
TimeoutMs uint64 `json:"timeoutMs"`
|
|
||||||
DisableCache bool `json:"disableCache"`
|
|
||||||
FinalQuery bool `json:"finalQuery"`
|
|
||||||
UnexpectedIPs StringList `json:"unexpectedIPs"`
|
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(data, &advanced); err == nil {
|
if err := json.Unmarshal(data, &advanced); err == nil {
|
||||||
c.Address = advanced.Address
|
c.Address = advanced.Address
|
||||||
@ -60,14 +43,8 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
|||||||
c.Port = advanced.Port
|
c.Port = advanced.Port
|
||||||
c.SkipFallback = advanced.SkipFallback
|
c.SkipFallback = advanced.SkipFallback
|
||||||
c.Domains = advanced.Domains
|
c.Domains = advanced.Domains
|
||||||
c.ExpectedIPs = advanced.ExpectedIPs
|
|
||||||
c.ExpectIPs = advanced.ExpectIPs
|
c.ExpectIPs = advanced.ExpectIPs
|
||||||
c.QueryStrategy = advanced.QueryStrategy
|
c.QueryStrategy = advanced.QueryStrategy
|
||||||
c.Tag = advanced.Tag
|
|
||||||
c.TimeoutMs = advanced.TimeoutMs
|
|
||||||
c.DisableCache = advanced.DisableCache
|
|
||||||
c.FinalQuery = advanced.FinalQuery
|
|
||||||
c.UnexpectedIPs = advanced.UnexpectedIPs
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,38 +92,9 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.ExpectedIPs) == 0 {
|
geoipList, err := ToCidrList(c.ExpectIPs)
|
||||||
c.ExpectedIPs = c.ExpectIPs
|
|
||||||
}
|
|
||||||
|
|
||||||
actPrior := false
|
|
||||||
var newExpectedIPs StringList
|
|
||||||
for _, s := range c.ExpectedIPs {
|
|
||||||
if s == "*" {
|
|
||||||
actPrior = true
|
|
||||||
} else {
|
|
||||||
newExpectedIPs = append(newExpectedIPs, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actUnprior := false
|
|
||||||
var newUnexpectedIPs StringList
|
|
||||||
for _, s := range c.UnexpectedIPs {
|
|
||||||
if s == "*" {
|
|
||||||
actUnprior = true
|
|
||||||
} else {
|
|
||||||
newUnexpectedIPs = append(newUnexpectedIPs, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedGeoipList, err := ToCidrList(newExpectedIPs)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("invalid expected IP rule: ", c.ExpectedIPs).Base(err)
|
return nil, errors.New("invalid IP rule: ", c.ExpectIPs).Base(err)
|
||||||
}
|
|
||||||
|
|
||||||
unexpectedGeoipList, err := ToCidrList(newUnexpectedIPs)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("invalid unexpected IP rule: ", c.UnexpectedIPs).Base(err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var myClientIP []byte
|
var myClientIP []byte
|
||||||
@ -166,16 +114,9 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
|
|||||||
ClientIp: myClientIP,
|
ClientIp: myClientIP,
|
||||||
SkipFallback: c.SkipFallback,
|
SkipFallback: c.SkipFallback,
|
||||||
PrioritizedDomain: domains,
|
PrioritizedDomain: domains,
|
||||||
ExpectedGeoip: expectedGeoipList,
|
Geoip: geoipList,
|
||||||
OriginalRules: originalRules,
|
OriginalRules: originalRules,
|
||||||
QueryStrategy: resolveQueryStrategy(c.QueryStrategy),
|
QueryStrategy: resolveQueryStrategy(c.QueryStrategy),
|
||||||
ActPrior: actPrior,
|
|
||||||
Tag: c.Tag,
|
|
||||||
TimeoutMs: c.TimeoutMs,
|
|
||||||
DisableCache: c.DisableCache,
|
|
||||||
FinalQuery: c.FinalQuery,
|
|
||||||
UnexpectedGeoip: unexpectedGeoipList,
|
|
||||||
ActUnprior: actUnprior,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,7 +137,6 @@ type DNSConfig struct {
|
|||||||
DisableCache bool `json:"disableCache"`
|
DisableCache bool `json:"disableCache"`
|
||||||
DisableFallback bool `json:"disableFallback"`
|
DisableFallback bool `json:"disableFallback"`
|
||||||
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
|
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
|
||||||
UseSystemHosts bool `json:"useSystemHosts"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type HostAddress struct {
|
type HostAddress struct {
|
||||||
@ -204,18 +144,6 @@ type HostAddress struct {
|
|||||||
addrs []*Address
|
addrs []*Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
|
||||||
func (h *HostAddress) MarshalJSON() ([]byte, error) {
|
|
||||||
if (h.addr != nil) != (h.addrs != nil) {
|
|
||||||
if h.addr != nil {
|
|
||||||
return json.Marshal(h.addr)
|
|
||||||
} else if h.addrs != nil {
|
|
||||||
return json.Marshal(h.addrs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, errors.New("unexpected config state")
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (h *HostAddress) UnmarshalJSON(data []byte) error {
|
func (h *HostAddress) UnmarshalJSON(data []byte) error {
|
||||||
addr := new(Address)
|
addr := new(Address)
|
||||||
@ -261,11 +189,6 @@ func getHostMapping(ha *HostAddress) *dns.Config_HostMapping {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
|
||||||
func (m *HostsWrapper) MarshalJSON() ([]byte, error) {
|
|
||||||
return json.Marshal(m.Hosts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (m *HostsWrapper) UnmarshalJSON(data []byte) error {
|
func (m *HostsWrapper) UnmarshalJSON(data []byte) error {
|
||||||
hosts := make(map[string]*HostAddress)
|
hosts := make(map[string]*HostAddress)
|
||||||
@ -418,15 +341,6 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
|
|||||||
}
|
}
|
||||||
config.StaticHosts = append(config.StaticHosts, staticHosts...)
|
config.StaticHosts = append(config.StaticHosts, staticHosts...)
|
||||||
}
|
}
|
||||||
if c.UseSystemHosts {
|
|
||||||
systemHosts, err := readSystemHosts()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to read system hosts").Base(err)
|
|
||||||
}
|
|
||||||
for domain, ips := range systemHosts {
|
|
||||||
config.StaticHosts = append(config.StaticHosts, &dns.Config_HostMapping{Ip: ips, Domain: domain, Type: dns.DomainMatchingType_Full})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
@ -439,57 +353,7 @@ func resolveQueryStrategy(queryStrategy string) dns.QueryStrategy {
|
|||||||
return dns.QueryStrategy_USE_IP4
|
return dns.QueryStrategy_USE_IP4
|
||||||
case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6":
|
case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6":
|
||||||
return dns.QueryStrategy_USE_IP6
|
return dns.QueryStrategy_USE_IP6
|
||||||
case "usesys", "usesystem", "use_sys", "use_system", "use-sys", "use-system":
|
|
||||||
return dns.QueryStrategy_USE_SYS
|
|
||||||
default:
|
default:
|
||||||
return dns.QueryStrategy_USE_IP
|
return dns.QueryStrategy_USE_IP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func readSystemHosts() (map[string][][]byte, error) {
|
|
||||||
var hostsPath string
|
|
||||||
switch runtime.GOOS {
|
|
||||||
case "windows":
|
|
||||||
hostsPath = filepath.Join(os.Getenv("SystemRoot"), "System32", "drivers", "etc", "hosts")
|
|
||||||
default:
|
|
||||||
hostsPath = "/etc/hosts"
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Open(hostsPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
hostsMap := make(map[string][][]byte)
|
|
||||||
scanner := bufio.NewScanner(file)
|
|
||||||
for scanner.Scan() {
|
|
||||||
line := strings.TrimSpace(scanner.Text())
|
|
||||||
if i := strings.IndexByte(line, '#'); i >= 0 {
|
|
||||||
// Discard comments.
|
|
||||||
line = line[0:i]
|
|
||||||
}
|
|
||||||
f := strings.Fields(line)
|
|
||||||
if len(f) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
addr := net.ParseAddress(f[0])
|
|
||||||
if addr.Family().IsDomain() {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ip := addr.IP()
|
|
||||||
for i := 1; i < len(f); i++ {
|
|
||||||
domain := strings.TrimSuffix(f[i], ".")
|
|
||||||
domain = strings.ToLower(domain)
|
|
||||||
if v, ok := hostsMap[domain]; ok {
|
|
||||||
hostsMap[domain] = append(v, ip)
|
|
||||||
} else {
|
|
||||||
hostsMap[domain] = [][]byte{ip}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := scanner.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return hostsMap, nil
|
|
||||||
}
|
|
||||||
|
@ -30,7 +30,7 @@ func (c *DNSOutboundConfig) Build() (proto.Message, error) {
|
|||||||
switch c.NonIPQuery {
|
switch c.NonIPQuery {
|
||||||
case "":
|
case "":
|
||||||
c.NonIPQuery = "drop"
|
c.NonIPQuery = "drop"
|
||||||
case "drop", "skip", "reject":
|
case "drop", "skip":
|
||||||
default:
|
default:
|
||||||
return nil, errors.New(`unknown "nonIPQuery": `, c.NonIPQuery)
|
return nil, errors.New(`unknown "nonIPQuery": `, c.NonIPQuery)
|
||||||
}
|
}
|
||||||
|
@ -20,18 +20,6 @@ type FakeDNSConfig struct {
|
|||||||
pools []*FakeDNSPoolElementConfig
|
pools []*FakeDNSPoolElementConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
|
||||||
func (f *FakeDNSConfig) MarshalJSON() ([]byte, error) {
|
|
||||||
if (f.pool != nil) != (f.pools != nil) {
|
|
||||||
if f.pool != nil {
|
|
||||||
return json.Marshal(f.pool)
|
|
||||||
} else if f.pools != nil {
|
|
||||||
return json.Marshal(f.pools)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, errors.New("unexpected config state")
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||||
func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error {
|
func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error {
|
||||||
var pool FakeDNSPoolElementConfig
|
var pool FakeDNSPoolElementConfig
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/app/observatory"
|
"github.com/xtls/xray-core/app/observatory"
|
||||||
"github.com/xtls/xray-core/app/observatory/burst"
|
"github.com/xtls/xray-core/app/observatory/burst"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
|
"github.com/xtls/xray-core/infra/conf/cfgcommon/duration"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,9 +26,6 @@ type BurstObservatoryConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b BurstObservatoryConfig) Build() (proto.Message, error) {
|
func (b BurstObservatoryConfig) Build() (proto.Message, error) {
|
||||||
if b.HealthCheck == nil {
|
|
||||||
return nil, errors.New("BurstObservatory requires a valid pingConfig")
|
|
||||||
}
|
|
||||||
if result, err := b.HealthCheck.Build(); err == nil {
|
if result, err := b.HealthCheck.Build(); err == nil {
|
||||||
return &burst.Config{SubjectSelector: b.SubjectSelector, PingConfig: result.(*burst.HealthPingConfig)}, nil
|
return &burst.Config{SubjectSelector: b.SubjectSelector, PingConfig: result.(*burst.HealthPingConfig)}, nil
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,7 +2,6 @@ package conf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/observatory/burst"
|
"github.com/xtls/xray-core/app/observatory/burst"
|
||||||
"github.com/xtls/xray-core/app/router"
|
"github.com/xtls/xray-core/app/router"
|
||||||
@ -52,23 +51,15 @@ type healthCheckSettings struct {
|
|||||||
Interval duration.Duration `json:"interval"`
|
Interval duration.Duration `json:"interval"`
|
||||||
SamplingCount int `json:"sampling"`
|
SamplingCount int `json:"sampling"`
|
||||||
Timeout duration.Duration `json:"timeout"`
|
Timeout duration.Duration `json:"timeout"`
|
||||||
HttpMethod string `json:"httpMethod"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h healthCheckSettings) Build() (proto.Message, error) {
|
func (h healthCheckSettings) Build() (proto.Message, error) {
|
||||||
var httpMethod string
|
|
||||||
if h.HttpMethod == "" {
|
|
||||||
httpMethod = "HEAD"
|
|
||||||
} else {
|
|
||||||
httpMethod = strings.TrimSpace(h.HttpMethod)
|
|
||||||
}
|
|
||||||
return &burst.HealthPingConfig{
|
return &burst.HealthPingConfig{
|
||||||
Destination: h.Destination,
|
Destination: h.Destination,
|
||||||
Connectivity: h.Connectivity,
|
Connectivity: h.Connectivity,
|
||||||
Interval: int64(h.Interval),
|
Interval: int64(h.Interval),
|
||||||
Timeout: int64(h.Timeout),
|
Timeout: int64(h.Timeout),
|
||||||
SamplingCount: int32(h.SamplingCount),
|
SamplingCount: int32(h.SamplingCount),
|
||||||
HttpMethod: httpMethod,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
|||||||
|
|
||||||
func readFileOrString(f string, s []string) ([]byte, error) {
|
func readFileOrString(f string, s []string) ([]byte, error) {
|
||||||
if len(f) > 0 {
|
if len(f) > 0 {
|
||||||
return filesystem.ReadCert(f)
|
return filesystem.ReadFile(f)
|
||||||
}
|
}
|
||||||
if len(s) > 0 {
|
if len(s) > 0 {
|
||||||
return []byte(strings.Join(s, "\n")), nil
|
return []byte(strings.Join(s, "\n")), nil
|
||||||
@ -486,12 +486,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
|||||||
return config, nil
|
return config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type LimitFallback struct {
|
|
||||||
AfterBytes uint64
|
|
||||||
BytesPerSec uint64
|
|
||||||
BurstBytesPerSec uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
type REALITYConfig struct {
|
type REALITYConfig struct {
|
||||||
MasterKeyLog string `json:"masterKeyLog"`
|
MasterKeyLog string `json:"masterKeyLog"`
|
||||||
Show bool `json:"show"`
|
Show bool `json:"show"`
|
||||||
@ -506,9 +500,6 @@ type REALITYConfig struct {
|
|||||||
MaxTimeDiff uint64 `json:"maxTimeDiff"`
|
MaxTimeDiff uint64 `json:"maxTimeDiff"`
|
||||||
ShortIds []string `json:"shortIds"`
|
ShortIds []string `json:"shortIds"`
|
||||||
|
|
||||||
LimitFallbackUpload LimitFallback `json:"limitFallbackUpload"`
|
|
||||||
LimitFallbackDownload LimitFallback `json:"limitFallbackDownload"`
|
|
||||||
|
|
||||||
Fingerprint string `json:"fingerprint"`
|
Fingerprint string `json:"fingerprint"`
|
||||||
ServerName string `json:"serverName"`
|
ServerName string `json:"serverName"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
@ -609,15 +600,6 @@ func (c *REALITYConfig) Build() (proto.Message, error) {
|
|||||||
config.Xver = c.Xver
|
config.Xver = c.Xver
|
||||||
config.ServerNames = c.ServerNames
|
config.ServerNames = c.ServerNames
|
||||||
config.MaxTimeDiff = c.MaxTimeDiff
|
config.MaxTimeDiff = c.MaxTimeDiff
|
||||||
|
|
||||||
config.LimitFallbackUpload = new(reality.LimitFallback)
|
|
||||||
config.LimitFallbackUpload.AfterBytes = c.LimitFallbackUpload.AfterBytes
|
|
||||||
config.LimitFallbackUpload.BytesPerSec = c.LimitFallbackUpload.BytesPerSec
|
|
||||||
config.LimitFallbackUpload.BurstBytesPerSec = c.LimitFallbackUpload.BurstBytesPerSec
|
|
||||||
config.LimitFallbackDownload = new(reality.LimitFallback)
|
|
||||||
config.LimitFallbackDownload.AfterBytes = c.LimitFallbackDownload.AfterBytes
|
|
||||||
config.LimitFallbackDownload.BytesPerSec = c.LimitFallbackDownload.BytesPerSec
|
|
||||||
config.LimitFallbackDownload.BurstBytesPerSec = c.LimitFallbackDownload.BurstBytesPerSec
|
|
||||||
} else {
|
} else {
|
||||||
config.Fingerprint = strings.ToLower(c.Fingerprint)
|
config.Fingerprint = strings.ToLower(c.Fingerprint)
|
||||||
if config.Fingerprint == "unsafe" || config.Fingerprint == "hellogolang" {
|
if config.Fingerprint == "unsafe" || config.Fingerprint == "hellogolang" {
|
||||||
@ -709,38 +691,12 @@ func (p TransportProtocol) Build() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type CustomSockoptConfig struct {
|
type CustomSockoptConfig struct {
|
||||||
Syetem string `json:"system"`
|
|
||||||
Network string `json:"network"`
|
|
||||||
Level string `json:"level"`
|
Level string `json:"level"`
|
||||||
Opt string `json:"opt"`
|
Opt string `json:"opt"`
|
||||||
Value string `json:"value"`
|
Value string `json:"value"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HappyEyeballsConfig struct {
|
|
||||||
PrioritizeIPv6 bool `json:"prioritizeIPv6"`
|
|
||||||
TryDelayMs uint64 `json:"tryDelayMs"`
|
|
||||||
Interleave uint32 `json:"interleave"`
|
|
||||||
MaxConcurrentTry uint32 `json:"maxConcurrentTry"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *HappyEyeballsConfig) UnmarshalJSON(data []byte) error {
|
|
||||||
var innerHappyEyeballsConfig = struct {
|
|
||||||
PrioritizeIPv6 bool `json:"prioritizeIPv6"`
|
|
||||||
TryDelayMs uint64 `json:"tryDelayMs"`
|
|
||||||
Interleave uint32 `json:"interleave"`
|
|
||||||
MaxConcurrentTry uint32 `json:"maxConcurrentTry"`
|
|
||||||
}{PrioritizeIPv6: false, Interleave: 1, TryDelayMs: 0, MaxConcurrentTry: 4}
|
|
||||||
if err := json.Unmarshal(data, &innerHappyEyeballsConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
h.PrioritizeIPv6 = innerHappyEyeballsConfig.PrioritizeIPv6
|
|
||||||
h.TryDelayMs = innerHappyEyeballsConfig.TryDelayMs
|
|
||||||
h.Interleave = innerHappyEyeballsConfig.Interleave
|
|
||||||
h.MaxConcurrentTry = innerHappyEyeballsConfig.MaxConcurrentTry
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SocketConfig struct {
|
type SocketConfig struct {
|
||||||
Mark int32 `json:"mark"`
|
Mark int32 `json:"mark"`
|
||||||
TFO interface{} `json:"tcpFastOpen"`
|
TFO interface{} `json:"tcpFastOpen"`
|
||||||
@ -760,7 +716,6 @@ type SocketConfig struct {
|
|||||||
TcpMptcp bool `json:"tcpMptcp"`
|
TcpMptcp bool `json:"tcpMptcp"`
|
||||||
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
|
CustomSockopt []*CustomSockoptConfig `json:"customSockopt"`
|
||||||
AddressPortStrategy string `json:"addressPortStrategy"`
|
AddressPortStrategy string `json:"addressPortStrategy"`
|
||||||
HappyEyeballsSettings *HappyEyeballsConfig `json:"happyEyeballs"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
@ -822,8 +777,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
|
|
||||||
for _, copt := range c.CustomSockopt {
|
for _, copt := range c.CustomSockopt {
|
||||||
customSockopt := &internet.CustomSockopt{
|
customSockopt := &internet.CustomSockopt{
|
||||||
System: copt.Syetem,
|
|
||||||
Network: copt.Network,
|
|
||||||
Level: copt.Level,
|
Level: copt.Level,
|
||||||
Opt: copt.Opt,
|
Opt: copt.Opt,
|
||||||
Value: copt.Value,
|
Value: copt.Value,
|
||||||
@ -852,14 +805,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
return nil, errors.New("unsupported address and port strategy: ", c.AddressPortStrategy)
|
return nil, errors.New("unsupported address and port strategy: ", c.AddressPortStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
var happyEyeballs = &internet.HappyEyeballsConfig{Interleave: 1, PrioritizeIpv6: false, TryDelayMs: 0, MaxConcurrentTry: 4}
|
|
||||||
if c.HappyEyeballsSettings != nil {
|
|
||||||
happyEyeballs.PrioritizeIpv6 = c.HappyEyeballsSettings.PrioritizeIPv6
|
|
||||||
happyEyeballs.Interleave = c.HappyEyeballsSettings.Interleave
|
|
||||||
happyEyeballs.TryDelayMs = c.HappyEyeballsSettings.TryDelayMs
|
|
||||||
happyEyeballs.MaxConcurrentTry = c.HappyEyeballsSettings.MaxConcurrentTry
|
|
||||||
}
|
|
||||||
|
|
||||||
return &internet.SocketConfig{
|
return &internet.SocketConfig{
|
||||||
Mark: c.Mark,
|
Mark: c.Mark,
|
||||||
Tfo: tfo,
|
Tfo: tfo,
|
||||||
@ -879,7 +824,6 @@ func (c *SocketConfig) Build() (*internet.SocketConfig, error) {
|
|||||||
TcpMptcp: c.TcpMptcp,
|
TcpMptcp: c.TcpMptcp,
|
||||||
CustomSockopt: customSockopts,
|
CustomSockopt: customSockopts,
|
||||||
AddressPortStrategy: addressPortStrategy,
|
AddressPortStrategy: addressPortStrategy,
|
||||||
HappyEyeballs: happyEyeballs,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,6 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
Tfo: 256,
|
Tfo: 256,
|
||||||
DomainStrategy: internet.DomainStrategy_USE_IP,
|
DomainStrategy: internet.DomainStrategy_USE_IP,
|
||||||
DialerProxy: "tag",
|
DialerProxy: "tag",
|
||||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 0, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -48,7 +47,6 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: -1,
|
Tfo: -1,
|
||||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 0, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -67,7 +65,6 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: 65535,
|
Tfo: 65535,
|
||||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 0, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -86,7 +83,6 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: -65535,
|
Tfo: -65535,
|
||||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 0, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -105,7 +101,6 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: 0,
|
Tfo: 0,
|
||||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 0, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -124,7 +119,6 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: 0,
|
Tfo: 0,
|
||||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 0, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
@ -141,7 +135,6 @@ func TestSocketConfig(t *testing.T) {
|
|||||||
expectedOutput = &internet.SocketConfig{
|
expectedOutput = &internet.SocketConfig{
|
||||||
Mark: 0,
|
Mark: 0,
|
||||||
Tfo: 0,
|
Tfo: 0,
|
||||||
HappyEyeballs: &internet.HappyEyeballsConfig{Interleave: 1, TryDelayMs: 0, PrioritizeIpv6: false, MaxConcurrentTry: 4},
|
|
||||||
}
|
}
|
||||||
runMultiTestCase(t, []TestCase{
|
runMultiTestCase(t, []TestCase{
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ func (c *WireGuardConfig) Build() (proto.Message, error) {
|
|||||||
var err error
|
var err error
|
||||||
config.SecretKey, err = ParseWireGuardKey(c.SecretKey)
|
config.SecretKey, err = ParseWireGuardKey(c.SecretKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("invalid WireGuard secret key: %w", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Address == nil {
|
if c.Address == nil {
|
||||||
@ -126,10 +126,6 @@ func (c *WireGuardConfig) Build() (proto.Message, error) {
|
|||||||
func ParseWireGuardKey(str string) (string, error) {
|
func ParseWireGuardKey(str string) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if str == "" {
|
|
||||||
return "", errors.New("key must not be empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(str)%2 == 0 {
|
if len(str)%2 == 0 {
|
||||||
_, err = hex.DecodeString(str)
|
_, err = hex.DecodeString(str)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
@ -69,8 +69,10 @@ func (c *SniffingConfig) Build() (*proxyman.SniffingConfig, error) {
|
|||||||
p = append(p, "tls")
|
p = append(p, "tls")
|
||||||
case "quic":
|
case "quic":
|
||||||
p = append(p, "quic")
|
p = append(p, "quic")
|
||||||
case "fakedns", "fakedns+others":
|
case "fakedns":
|
||||||
p = append(p, "fakedns")
|
p = append(p, "fakedns")
|
||||||
|
case "fakedns+others":
|
||||||
|
p = append(p, "fakedns+others")
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("unknown protocol: ", protocol)
|
return nil, errors.New("unknown protocol: ", protocol)
|
||||||
}
|
}
|
||||||
@ -239,14 +241,14 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
|
|||||||
}
|
}
|
||||||
rawConfig, err := inboundConfigLoader.LoadWithID(settings, c.Protocol)
|
rawConfig, err := inboundConfigLoader.LoadWithID(settings, c.Protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to load inbound detour config for protocol ", c.Protocol).Base(err)
|
return nil, errors.New("failed to load inbound detour config.").Base(err)
|
||||||
}
|
}
|
||||||
if dokodemoConfig, ok := rawConfig.(*DokodemoConfig); ok {
|
if dokodemoConfig, ok := rawConfig.(*DokodemoConfig); ok {
|
||||||
receiverSettings.ReceiveOriginalDestination = dokodemoConfig.Redirect
|
receiverSettings.ReceiveOriginalDestination = dokodemoConfig.Redirect
|
||||||
}
|
}
|
||||||
ts, err := rawConfig.(Buildable).Build()
|
ts, err := rawConfig.(Buildable).Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build inbound handler for protocol ", c.Protocol).Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &core.InboundHandlerConfig{
|
return &core.InboundHandlerConfig{
|
||||||
@ -290,8 +292,7 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
|||||||
senderSettings.ViaCidr = strings.Split(*c.SendThrough, "/")[1]
|
senderSettings.ViaCidr = strings.Split(*c.SendThrough, "/")[1]
|
||||||
} else {
|
} else {
|
||||||
if address.Family().IsDomain() {
|
if address.Family().IsDomain() {
|
||||||
domain := address.Address.Domain()
|
if address.Address.Domain() != "origin" {
|
||||||
if domain != "origin" && domain != "srcip" {
|
|
||||||
return nil, errors.New("unable to send through: " + address.String())
|
return nil, errors.New("unable to send through: " + address.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -302,7 +303,7 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
|||||||
if c.StreamSetting != nil {
|
if c.StreamSetting != nil {
|
||||||
ss, err := c.StreamSetting.Build()
|
ss, err := c.StreamSetting.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build stream settings for outbound detour").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
senderSettings.StreamSettings = ss
|
senderSettings.StreamSettings = ss
|
||||||
}
|
}
|
||||||
@ -310,7 +311,7 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
|||||||
if c.ProxySettings != nil {
|
if c.ProxySettings != nil {
|
||||||
ps, err := c.ProxySettings.Build()
|
ps, err := c.ProxySettings.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("invalid outbound detour proxy settings").Base(err)
|
return nil, errors.New("invalid outbound detour proxy settings.").Base(err)
|
||||||
}
|
}
|
||||||
if ps.TransportLayerProxy {
|
if ps.TransportLayerProxy {
|
||||||
if senderSettings.StreamSettings != nil {
|
if senderSettings.StreamSettings != nil {
|
||||||
@ -330,7 +331,7 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
|||||||
if c.MuxSettings != nil {
|
if c.MuxSettings != nil {
|
||||||
ms, err := c.MuxSettings.Build()
|
ms, err := c.MuxSettings.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build Mux config").Base(err)
|
return nil, errors.New("failed to build Mux config.").Base(err)
|
||||||
}
|
}
|
||||||
senderSettings.MultiplexSettings = ms
|
senderSettings.MultiplexSettings = ms
|
||||||
}
|
}
|
||||||
@ -341,11 +342,11 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
|||||||
}
|
}
|
||||||
rawConfig, err := outboundConfigLoader.LoadWithID(settings, c.Protocol)
|
rawConfig, err := outboundConfigLoader.LoadWithID(settings, c.Protocol)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to load outbound detour config for protocol ", c.Protocol).Base(err)
|
return nil, errors.New("failed to parse to outbound detour config.").Base(err)
|
||||||
}
|
}
|
||||||
ts, err := rawConfig.(Buildable).Build()
|
ts, err := rawConfig.(Buildable).Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build outbound handler for protocol ", c.Protocol).Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &core.OutboundHandlerConfig{
|
return &core.OutboundHandlerConfig{
|
||||||
@ -489,7 +490,7 @@ func (c *Config) Override(o *Config, fn string) {
|
|||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
func (c *Config) Build() (*core.Config, error) {
|
func (c *Config) Build() (*core.Config, error) {
|
||||||
if err := PostProcessConfigureFile(c); err != nil {
|
if err := PostProcessConfigureFile(c); err != nil {
|
||||||
return nil, errors.New("failed to post-process configuration file").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &core.Config{
|
config := &core.Config{
|
||||||
@ -503,21 +504,21 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if c.API != nil {
|
if c.API != nil {
|
||||||
apiConf, err := c.API.Build()
|
apiConf, err := c.API.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build API configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(apiConf))
|
config.App = append(config.App, serial.ToTypedMessage(apiConf))
|
||||||
}
|
}
|
||||||
if c.Metrics != nil {
|
if c.Metrics != nil {
|
||||||
metricsConf, err := c.Metrics.Build()
|
metricsConf, err := c.Metrics.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build metrics configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(metricsConf))
|
config.App = append(config.App, serial.ToTypedMessage(metricsConf))
|
||||||
}
|
}
|
||||||
if c.Stats != nil {
|
if c.Stats != nil {
|
||||||
statsConf, err := c.Stats.Build()
|
statsConf, err := c.Stats.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build stats configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(statsConf))
|
config.App = append(config.App, serial.ToTypedMessage(statsConf))
|
||||||
}
|
}
|
||||||
@ -535,7 +536,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if c.RouterConfig != nil {
|
if c.RouterConfig != nil {
|
||||||
routerConfig, err := c.RouterConfig.Build()
|
routerConfig, err := c.RouterConfig.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build routing configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(routerConfig))
|
config.App = append(config.App, serial.ToTypedMessage(routerConfig))
|
||||||
}
|
}
|
||||||
@ -543,7 +544,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if c.DNSConfig != nil {
|
if c.DNSConfig != nil {
|
||||||
dnsApp, err := c.DNSConfig.Build()
|
dnsApp, err := c.DNSConfig.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build DNS configuration").Base(err)
|
return nil, errors.New("failed to parse DNS config").Base(err)
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(dnsApp))
|
config.App = append(config.App, serial.ToTypedMessage(dnsApp))
|
||||||
}
|
}
|
||||||
@ -551,7 +552,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if c.Policy != nil {
|
if c.Policy != nil {
|
||||||
pc, err := c.Policy.Build()
|
pc, err := c.Policy.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build policy configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(pc))
|
config.App = append(config.App, serial.ToTypedMessage(pc))
|
||||||
}
|
}
|
||||||
@ -559,7 +560,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if c.Reverse != nil {
|
if c.Reverse != nil {
|
||||||
r, err := c.Reverse.Build()
|
r, err := c.Reverse.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build reverse configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(r))
|
config.App = append(config.App, serial.ToTypedMessage(r))
|
||||||
}
|
}
|
||||||
@ -567,7 +568,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if c.FakeDNS != nil {
|
if c.FakeDNS != nil {
|
||||||
r, err := c.FakeDNS.Build()
|
r, err := c.FakeDNS.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build fake DNS configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append([]*serial.TypedMessage{serial.ToTypedMessage(r)}, config.App...)
|
config.App = append([]*serial.TypedMessage{serial.ToTypedMessage(r)}, config.App...)
|
||||||
}
|
}
|
||||||
@ -575,7 +576,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if c.Observatory != nil {
|
if c.Observatory != nil {
|
||||||
r, err := c.Observatory.Build()
|
r, err := c.Observatory.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build observatory configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(r))
|
config.App = append(config.App, serial.ToTypedMessage(r))
|
||||||
}
|
}
|
||||||
@ -583,7 +584,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
if c.BurstObservatory != nil {
|
if c.BurstObservatory != nil {
|
||||||
r, err := c.BurstObservatory.Build()
|
r, err := c.BurstObservatory.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build burst observatory configuration").Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.App = append(config.App, serial.ToTypedMessage(r))
|
config.App = append(config.App, serial.ToTypedMessage(r))
|
||||||
}
|
}
|
||||||
@ -601,7 +602,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
for _, rawInboundConfig := range inbounds {
|
for _, rawInboundConfig := range inbounds {
|
||||||
ic, err := rawInboundConfig.Build()
|
ic, err := rawInboundConfig.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build inbound config with tag ", rawInboundConfig.Tag).Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.Inbound = append(config.Inbound, ic)
|
config.Inbound = append(config.Inbound, ic)
|
||||||
}
|
}
|
||||||
@ -615,7 +616,7 @@ func (c *Config) Build() (*core.Config, error) {
|
|||||||
for _, rawOutboundConfig := range outbounds {
|
for _, rawOutboundConfig := range outbounds {
|
||||||
oc, err := rawOutboundConfig.Build()
|
oc, err := rawOutboundConfig.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to build outbound config with tag ", rawOutboundConfig.Tag).Base(err)
|
return nil, err
|
||||||
}
|
}
|
||||||
config.Outbound = append(config.Outbound, oc)
|
config.Outbound = append(config.Outbound, oc)
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,6 @@ var CmdAPI = &base.Command{
|
|||||||
cmdAddOutbounds,
|
cmdAddOutbounds,
|
||||||
cmdRemoveInbounds,
|
cmdRemoveInbounds,
|
||||||
cmdRemoveOutbounds,
|
cmdRemoveOutbounds,
|
||||||
cmdListInbounds,
|
|
||||||
cmdListOutbounds,
|
|
||||||
cmdInboundUser,
|
cmdInboundUser,
|
||||||
cmdInboundUserCount,
|
cmdInboundUserCount,
|
||||||
cmdAddRules,
|
cmdAddRules,
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
handlerService "github.com/xtls/xray-core/app/proxyman/command"
|
|
||||||
"github.com/xtls/xray-core/main/commands/base"
|
|
||||||
)
|
|
||||||
|
|
||||||
var cmdListInbounds = &base.Command{
|
|
||||||
CustomFlags: true,
|
|
||||||
UsageLine: "{{.Exec}} api lsi [--server=127.0.0.1:8080]",
|
|
||||||
Short: "List inbounds",
|
|
||||||
Long: `
|
|
||||||
List inbounds in Xray.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
-s, -server <server:port>
|
|
||||||
The API server address. Default 127.0.0.1:8080
|
|
||||||
|
|
||||||
-t, -timeout <seconds>
|
|
||||||
Timeout in seconds for calling API. Default 3
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
|
|
||||||
`,
|
|
||||||
Run: executeListInbounds,
|
|
||||||
}
|
|
||||||
|
|
||||||
func executeListInbounds(cmd *base.Command, args []string) {
|
|
||||||
setSharedFlags(cmd)
|
|
||||||
cmd.Flag.Parse(args)
|
|
||||||
|
|
||||||
conn, ctx, close := dialAPIServer()
|
|
||||||
defer close()
|
|
||||||
|
|
||||||
client := handlerService.NewHandlerServiceClient(conn)
|
|
||||||
|
|
||||||
resp, err := client.ListInbounds(ctx, &handlerService.ListInboundsRequest{})
|
|
||||||
if err != nil {
|
|
||||||
base.Fatalf("failed to list inbounds: %s", err)
|
|
||||||
}
|
|
||||||
showJSONResponse(resp)
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package api
|
|
||||||
|
|
||||||
import (
|
|
||||||
handlerService "github.com/xtls/xray-core/app/proxyman/command"
|
|
||||||
"github.com/xtls/xray-core/main/commands/base"
|
|
||||||
)
|
|
||||||
|
|
||||||
var cmdListOutbounds = &base.Command{
|
|
||||||
CustomFlags: true,
|
|
||||||
UsageLine: "{{.Exec}} api lso [--server=127.0.0.1:8080]",
|
|
||||||
Short: "List outbounds",
|
|
||||||
Long: `
|
|
||||||
List outbounds in Xray.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
|
|
||||||
-s, -server <server:port>
|
|
||||||
The API server address. Default 127.0.0.1:8080
|
|
||||||
|
|
||||||
-t, -timeout <seconds>
|
|
||||||
Timeout in seconds for calling API. Default 3
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080
|
|
||||||
`,
|
|
||||||
Run: executeListOutbounds,
|
|
||||||
}
|
|
||||||
|
|
||||||
func executeListOutbounds(cmd *base.Command, args []string) {
|
|
||||||
setSharedFlags(cmd)
|
|
||||||
cmd.Flag.Parse(args)
|
|
||||||
|
|
||||||
conn, ctx, close := dialAPIServer()
|
|
||||||
defer close()
|
|
||||||
|
|
||||||
client := handlerService.NewHandlerServiceClient(conn)
|
|
||||||
resp, err := client.ListOutbounds(ctx, &handlerService.ListOutboundsRequest{})
|
|
||||||
if err != nil {
|
|
||||||
base.Fatalf("failed to list outbounds: %s", err)
|
|
||||||
}
|
|
||||||
showJSONResponse(resp)
|
|
||||||
}
|
|
@ -2,7 +2,6 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
go_errors "errors"
|
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -187,9 +186,6 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet.
|
|||||||
if len(h.blockTypes) > 0 {
|
if len(h.blockTypes) > 0 {
|
||||||
for _, blocktype := range h.blockTypes {
|
for _, blocktype := range h.blockTypes {
|
||||||
if blocktype == int32(qType) {
|
if blocktype == int32(qType) {
|
||||||
if h.nonIPQuery == "reject" {
|
|
||||||
go h.rejectNonIPQuery(id, qType, domain, writer)
|
|
||||||
}
|
|
||||||
errors.LogInfo(ctx, "blocked type ", qType, " query for domain ", domain)
|
errors.LogInfo(ctx, "blocked type ", qType, " query for domain ", domain)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -202,11 +198,6 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet.
|
|||||||
b.Release()
|
b.Release()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if h.nonIPQuery == "reject" {
|
|
||||||
go h.rejectNonIPQuery(id, qType, domain, writer)
|
|
||||||
b.Release()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := connWriter.WriteMessage(b); err != nil {
|
if err := connWriter.WriteMessage(b); err != nil {
|
||||||
@ -245,18 +236,17 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
|
|||||||
var ips []net.IP
|
var ips []net.IP
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
var ttl4 uint32
|
var ttl uint32 = 600
|
||||||
var ttl6 uint32
|
|
||||||
|
|
||||||
switch qType {
|
switch qType {
|
||||||
case dnsmessage.TypeA:
|
case dnsmessage.TypeA:
|
||||||
ips, ttl4, err = h.client.LookupIP(domain, dns.IPOption{
|
ips, err = h.client.LookupIP(domain, dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: false,
|
IPv6Enable: false,
|
||||||
FakeEnable: true,
|
FakeEnable: true,
|
||||||
})
|
})
|
||||||
case dnsmessage.TypeAAAA:
|
case dnsmessage.TypeAAAA:
|
||||||
ips, ttl6, err = h.client.LookupIP(domain, dns.IPOption{
|
ips, err = h.client.LookupIP(domain, dns.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: false,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: true,
|
FakeEnable: true,
|
||||||
@ -264,11 +254,15 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rcode := dns.RCodeFromError(err)
|
rcode := dns.RCodeFromError(err)
|
||||||
if rcode == 0 && len(ips) == 0 && !go_errors.Is(err, dns.ErrEmptyResponse) {
|
if rcode == 0 && len(ips) == 0 && !errors.AllEqual(dns.ErrEmptyResponse, errors.Cause(err)) {
|
||||||
errors.LogInfoInner(context.Background(), err, "ip query")
|
errors.LogInfoInner(context.Background(), err, "ip query")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fkr0, ok := h.fdns.(dns.FakeDNSEngineRev0); ok && len(ips) > 0 && fkr0.IsIPInIPPool(net.IPAddress(ips[0])) {
|
||||||
|
ttl = 1
|
||||||
|
}
|
||||||
|
|
||||||
switch qType {
|
switch qType {
|
||||||
case dnsmessage.TypeA:
|
case dnsmessage.TypeA:
|
||||||
for i, ip := range ips {
|
for i, ip := range ips {
|
||||||
@ -299,17 +293,16 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
|
|||||||
}))
|
}))
|
||||||
common.Must(builder.StartAnswers())
|
common.Must(builder.StartAnswers())
|
||||||
|
|
||||||
rHeader4 := dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName(domain), Class: dnsmessage.ClassINET, TTL: ttl4}
|
rHeader := dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName(domain), Class: dnsmessage.ClassINET, TTL: ttl}
|
||||||
rHeader6 := dnsmessage.ResourceHeader{Name: dnsmessage.MustNewName(domain), Class: dnsmessage.ClassINET, TTL: ttl6}
|
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
if len(ip) == net.IPv4len {
|
if len(ip) == net.IPv4len {
|
||||||
var r dnsmessage.AResource
|
var r dnsmessage.AResource
|
||||||
copy(r.A[:], ip)
|
copy(r.A[:], ip)
|
||||||
common.Must(builder.AResource(rHeader4, r))
|
common.Must(builder.AResource(rHeader, r))
|
||||||
} else {
|
} else {
|
||||||
var r dnsmessage.AAAAResource
|
var r dnsmessage.AAAAResource
|
||||||
copy(r.AAAA[:], ip)
|
copy(r.AAAA[:], ip)
|
||||||
common.Must(builder.AAAAResource(rHeader6, r))
|
common.Must(builder.AAAAResource(rHeader, r))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msgBytes, err := builder.Finish()
|
msgBytes, err := builder.Finish()
|
||||||
@ -325,38 +318,6 @@ func (h *Handler) handleIPQuery(id uint16, qType dnsmessage.Type, domain string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) rejectNonIPQuery(id uint16, qType dnsmessage.Type, domain string, writer dns_proto.MessageWriter) {
|
|
||||||
b := buf.New()
|
|
||||||
rawBytes := b.Extend(buf.Size)
|
|
||||||
builder := dnsmessage.NewBuilder(rawBytes[:0], dnsmessage.Header{
|
|
||||||
ID: id,
|
|
||||||
RCode: dnsmessage.RCodeRefused,
|
|
||||||
RecursionAvailable: true,
|
|
||||||
RecursionDesired: true,
|
|
||||||
Response: true,
|
|
||||||
Authoritative: true,
|
|
||||||
})
|
|
||||||
builder.EnableCompression()
|
|
||||||
common.Must(builder.StartQuestions())
|
|
||||||
common.Must(builder.Question(dnsmessage.Question{
|
|
||||||
Name: dnsmessage.MustNewName(domain),
|
|
||||||
Class: dnsmessage.ClassINET,
|
|
||||||
Type: qType,
|
|
||||||
}))
|
|
||||||
|
|
||||||
msgBytes, err := builder.Finish()
|
|
||||||
if err != nil {
|
|
||||||
errors.LogInfoInner(context.Background(), err, "pack reject message")
|
|
||||||
b.Release()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b.Resize(0, int32(len(msgBytes)))
|
|
||||||
|
|
||||||
if err := writer.WriteMessage(b); err != nil {
|
|
||||||
errors.LogInfoInner(context.Background(), err, "write reject answer")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type outboundConn struct {
|
type outboundConn struct {
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
dialer func() (stat.Connection, error)
|
dialer func() (stat.Connection, error)
|
||||||
|
@ -71,13 +71,13 @@ func (h *Handler) policy() policy.Session {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
|
func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
|
||||||
ips, _, err := h.dns.LookupIP(domain, dns.IPOption{
|
ips, err := h.dns.LookupIP(domain, dns.IPOption{
|
||||||
IPv4Enable: (localAddr == nil || localAddr.Family().IsIPv4()) && h.config.preferIP4(),
|
IPv4Enable: (localAddr == nil || localAddr.Family().IsIPv4()) && h.config.preferIP4(),
|
||||||
IPv6Enable: (localAddr == nil || localAddr.Family().IsIPv6()) && h.config.preferIP6(),
|
IPv6Enable: (localAddr == nil || localAddr.Family().IsIPv6()) && h.config.preferIP6(),
|
||||||
})
|
})
|
||||||
{ // Resolve fallback
|
{ // Resolve fallback
|
||||||
if (len(ips) == 0 || err != nil) && h.config.hasFallback() && localAddr == nil {
|
if (len(ips) == 0 || err != nil) && h.config.hasFallback() && localAddr == nil {
|
||||||
ips, _, err = h.dns.LookupIP(domain, dns.IPOption{
|
ips, err = h.dns.LookupIP(domain, dns.IPOption{
|
||||||
IPv4Enable: h.config.fallbackIP4(),
|
IPv4Enable: h.config.fallbackIP4(),
|
||||||
IPv6Enable: h.config.fallbackIP6(),
|
IPv6Enable: h.config.fallbackIP6(),
|
||||||
})
|
})
|
||||||
|
@ -294,7 +294,7 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
|
|||||||
|
|
||||||
responseDone := func() error {
|
responseDone := func() error {
|
||||||
responseReader := bufio.NewReaderSize(&buf.BufferedReader{Reader: link.Reader}, buf.Size)
|
responseReader := bufio.NewReaderSize(&buf.BufferedReader{Reader: link.Reader}, buf.Size)
|
||||||
response, err := readResponseAndHandle100Continue(responseReader, request, writer)
|
response, err := http.ReadResponse(responseReader, request)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
http_proto.RemoveHopByHopHeaders(response.Header)
|
http_proto.RemoveHopByHopHeaders(response.Header)
|
||||||
if response.ContentLength >= 0 {
|
if response.ContentLength >= 0 {
|
||||||
@ -338,38 +338,6 @@ func (s *Server) handlePlainHTTP(ctx context.Context, request *http.Request, wri
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sometimes, server might send 1xx response to client
|
|
||||||
// it should not be processed by http proxy handler, just forward it to client
|
|
||||||
func readResponseAndHandle100Continue(r *bufio.Reader, req *http.Request, writer io.Writer) (*http.Response, error) {
|
|
||||||
// have a little look of response
|
|
||||||
peekBytes, err := r.Peek(56)
|
|
||||||
if err == nil || err == bufio.ErrBufferFull {
|
|
||||||
str := string(peekBytes)
|
|
||||||
ResponseLine := strings.Split(str, "\r\n")[0]
|
|
||||||
_, status, _ := strings.Cut(ResponseLine, " ")
|
|
||||||
// only handle 1xx response
|
|
||||||
if strings.HasPrefix(status, "1") {
|
|
||||||
ResponseHeader1xx := []byte{}
|
|
||||||
// read until \r\n\r\n (end of http response header)
|
|
||||||
for {
|
|
||||||
data, err := r.ReadSlice('\n')
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to read http 1xx response").Base(err)
|
|
||||||
}
|
|
||||||
ResponseHeader1xx = append(ResponseHeader1xx, data...)
|
|
||||||
if bytes.Equal(ResponseHeader1xx[len(ResponseHeader1xx)-4:], []byte{'\r', '\n', '\r', '\n'}) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if len(ResponseHeader1xx) > 1024 {
|
|
||||||
return nil, errors.New("too big http 1xx response")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
writer.Write(ResponseHeader1xx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return http.ReadResponse(r, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
return NewServer(ctx, config.(*ServerConfig))
|
return NewServer(ctx, config.(*ServerConfig))
|
||||||
|
@ -53,7 +53,6 @@ func (v *Validator) Get(hash string) *protocol.MemoryUser {
|
|||||||
|
|
||||||
// Get a trojan user with hashed key, nil if user doesn't exist.
|
// Get a trojan user with hashed key, nil if user doesn't exist.
|
||||||
func (v *Validator) GetByEmail(email string) *protocol.MemoryUser {
|
func (v *Validator) GetByEmail(email string) *protocol.MemoryUser {
|
||||||
email = strings.ToLower(email)
|
|
||||||
u, _ := v.email.Load(email)
|
u, _ := v.email.Load(email)
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return u.(*protocol.MemoryUser)
|
return u.(*protocol.MemoryUser)
|
||||||
|
@ -63,7 +63,6 @@ func (v *MemoryValidator) Get(id uuid.UUID) *protocol.MemoryUser {
|
|||||||
|
|
||||||
// Get a VLESS user with email, nil if user doesn't exist.
|
// Get a VLESS user with email, nil if user doesn't exist.
|
||||||
func (v *MemoryValidator) GetByEmail(email string) *protocol.MemoryUser {
|
func (v *MemoryValidator) GetByEmail(email string) *protocol.MemoryUser {
|
||||||
email = strings.ToLower(email)
|
|
||||||
u, _ := v.email.Load(email)
|
u, _ := v.email.Load(email)
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return u.(*protocol.MemoryUser)
|
return u.(*protocol.MemoryUser)
|
||||||
|
@ -54,7 +54,7 @@ func (n *netBind) ParseEndpoint(s string) (conn.Endpoint, error) {
|
|||||||
|
|
||||||
addr := xnet.ParseAddress(ipStr)
|
addr := xnet.ParseAddress(ipStr)
|
||||||
if addr.Family() == xnet.AddressFamilyDomain {
|
if addr.Family() == xnet.AddressFamilyDomain {
|
||||||
ips, _, err := n.dns.LookupIP(addr.Domain(), n.dnsOption)
|
ips, err := n.dns.LookupIP(addr.Domain(), n.dnsOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if len(ips) == 0 {
|
} else if len(ips) == 0 {
|
||||||
|
@ -77,20 +77,6 @@ func New(ctx context.Context, conf *DeviceConfig) (*Handler, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) Close() (err error) {
|
|
||||||
go func() {
|
|
||||||
h.wgLock.Lock()
|
|
||||||
defer h.wgLock.Unlock()
|
|
||||||
|
|
||||||
if h.net != nil {
|
|
||||||
_ = h.net.Close()
|
|
||||||
h.net = nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) processWireGuard(ctx context.Context, dialer internet.Dialer) (err error) {
|
func (h *Handler) processWireGuard(ctx context.Context, dialer internet.Dialer) (err error) {
|
||||||
h.wgLock.Lock()
|
h.wgLock.Lock()
|
||||||
defer h.wgLock.Unlock()
|
defer h.wgLock.Unlock()
|
||||||
@ -164,13 +150,13 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
// resolve dns
|
// resolve dns
|
||||||
addr := destination.Address
|
addr := destination.Address
|
||||||
if addr.Family().IsDomain() {
|
if addr.Family().IsDomain() {
|
||||||
ips, _, err := h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
ips, err := h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||||
IPv4Enable: h.hasIPv4 && h.conf.preferIP4(),
|
IPv4Enable: h.hasIPv4 && h.conf.preferIP4(),
|
||||||
IPv6Enable: h.hasIPv6 && h.conf.preferIP6(),
|
IPv6Enable: h.hasIPv6 && h.conf.preferIP6(),
|
||||||
})
|
})
|
||||||
{ // Resolve fallback
|
{ // Resolve fallback
|
||||||
if (len(ips) == 0 || err != nil) && h.conf.hasFallback() {
|
if (len(ips) == 0 || err != nil) && h.conf.hasFallback() {
|
||||||
ips, _, err = h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
ips, err = h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||||
IPv4Enable: h.hasIPv4 && h.conf.fallbackIP4(),
|
IPv4Enable: h.hasIPv4 && h.conf.fallbackIP4(),
|
||||||
IPv6Enable: h.hasIPv6 && h.conf.fallbackIP6(),
|
IPv6Enable: h.hasIPv6 && h.conf.fallbackIP6(),
|
||||||
})
|
})
|
||||||
@ -298,13 +284,13 @@ func (h *Handler) createIPCRequest() string {
|
|||||||
addr = net.ParseAddress(dialerIp.String())
|
addr = net.ParseAddress(dialerIp.String())
|
||||||
errors.LogInfo(h.bind.ctx, "createIPCRequest use dialer dest ip: ", addr)
|
errors.LogInfo(h.bind.ctx, "createIPCRequest use dialer dest ip: ", addr)
|
||||||
} else {
|
} else {
|
||||||
ips, _, err := h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
ips, err := h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||||
IPv4Enable: h.hasIPv4 && h.conf.preferIP4(),
|
IPv4Enable: h.hasIPv4 && h.conf.preferIP4(),
|
||||||
IPv6Enable: h.hasIPv6 && h.conf.preferIP6(),
|
IPv6Enable: h.hasIPv6 && h.conf.preferIP6(),
|
||||||
})
|
})
|
||||||
{ // Resolve fallback
|
{ // Resolve fallback
|
||||||
if (len(ips) == 0 || err != nil) && h.conf.hasFallback() {
|
if (len(ips) == 0 || err != nil) && h.conf.hasFallback() {
|
||||||
ips, _, err = h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
ips, err = h.dns.LookupIP(addr.Domain(), dns.IPOption{
|
||||||
IPv4Enable: h.hasIPv4 && h.conf.fallbackIP4(),
|
IPv4Enable: h.hasIPv4 && h.conf.fallbackIP4(),
|
||||||
IPv6Enable: h.hasIPv6 && h.conf.fallbackIP6(),
|
IPv6Enable: h.hasIPv6 && h.conf.fallbackIP6(),
|
||||||
})
|
})
|
||||||
|
@ -10,7 +10,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"golang.zx2c4.com/wireguard/tun"
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
@ -34,7 +33,6 @@ type netTun struct {
|
|||||||
incomingPacket chan *buffer.View
|
incomingPacket chan *buffer.View
|
||||||
mtu int
|
mtu int
|
||||||
hasV4, hasV6 bool
|
hasV4, hasV6 bool
|
||||||
closeOnce sync.Once
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Net netTun
|
type Net netTun
|
||||||
@ -176,15 +174,18 @@ func (tun *netTun) Flush() error {
|
|||||||
|
|
||||||
// Close implements tun.Device
|
// Close implements tun.Device
|
||||||
func (tun *netTun) Close() error {
|
func (tun *netTun) Close() error {
|
||||||
tun.closeOnce.Do(func() {
|
|
||||||
tun.stack.RemoveNIC(1)
|
tun.stack.RemoveNIC(1)
|
||||||
|
|
||||||
|
if tun.events != nil {
|
||||||
close(tun.events)
|
close(tun.events)
|
||||||
|
}
|
||||||
|
|
||||||
tun.ep.Close()
|
tun.ep.Close()
|
||||||
|
|
||||||
|
if tun.incomingPacket != nil {
|
||||||
close(tun.incomingPacket)
|
close(tun.incomingPacket)
|
||||||
})
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,52 +0,0 @@
|
|||||||
package wireguard_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"runtime/debug"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/core"
|
|
||||||
"github.com/xtls/xray-core/proxy/wireguard"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestWireGuardServerInitializationError verifies that an error during TUN initialization
|
|
||||||
// (triggered by an empty SecretKey) in the WireGuard server does not cause a panic and returns an error instead.
|
|
||||||
func TestWireGuardServerInitializationError(t *testing.T) {
|
|
||||||
// Create a minimal core instance with default features
|
|
||||||
config := &core.Config{}
|
|
||||||
instance, err := core.New(config)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Failed to create core instance: %v", err)
|
|
||||||
}
|
|
||||||
// Set the Xray instance in the context
|
|
||||||
ctx := context.WithValue(context.Background(), core.XrayKey(1), instance)
|
|
||||||
|
|
||||||
// Define the server configuration with an empty SecretKey to trigger error
|
|
||||||
conf := &wireguard.DeviceConfig{
|
|
||||||
IsClient: false,
|
|
||||||
Endpoint: []string{"10.0.0.1/32"},
|
|
||||||
Mtu: 1420,
|
|
||||||
SecretKey: "", // Empty SecretKey to trigger error
|
|
||||||
Peers: []*wireguard.PeerConfig{
|
|
||||||
{
|
|
||||||
PublicKey: "some_public_key",
|
|
||||||
AllowedIps: []string{"10.0.0.2/32"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use defer to catch any panic and fail the test explicitly
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
t.Errorf("TUN initialization panicked: %v", r)
|
|
||||||
debug.PrintStack()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Attempt to initialize the WireGuard server
|
|
||||||
_, err = wireguard.NewServer(ctx, conf)
|
|
||||||
|
|
||||||
// Check that an error is returned
|
|
||||||
assert.ErrorContains(t, err, "failed to set private_key: hex string does not fit the slice")
|
|
||||||
}
|
|
@ -50,13 +50,12 @@ func (mr *DNSClientMockRecorder) Close() *gomock.Call {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LookupIP mocks base method
|
// LookupIP mocks base method
|
||||||
func (m *DNSClient) LookupIP(arg0 string, arg1 dns.IPOption) ([]net.IP, uint32, error) {
|
func (m *DNSClient) LookupIP(arg0 string, arg1 dns.IPOption) ([]net.IP, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "LookupIP", arg0, arg1)
|
ret := m.ctrl.Call(m, "LookupIP", arg0, arg1)
|
||||||
ret0, _ := ret[0].([]net.IP)
|
ret0, _ := ret[0].([]net.IP)
|
||||||
ret1, _ := ret[1].(uint32)
|
ret1, _ := ret[1].(error)
|
||||||
ret2, _ := ret[2].(error)
|
return ret0, ret1
|
||||||
return ret0, ret1, ret2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LookupIP indicates an expected call of LookupIP
|
// LookupIP indicates an expected call of LookupIP
|
||||||
|
@ -91,20 +91,6 @@ func (mr *OutboundManagerMockRecorder) GetHandler(arg0 interface{}) *gomock.Call
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHandler", reflect.TypeOf((*OutboundManager)(nil).GetHandler), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHandler", reflect.TypeOf((*OutboundManager)(nil).GetHandler), arg0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListHandlers mocks base method
|
|
||||||
func (m *OutboundManager) ListHandlers(arg0 context.Context) []outbound.Handler {
|
|
||||||
m.ctrl.T.Helper()
|
|
||||||
ret := m.ctrl.Call(m, "ListHandlers", arg0)
|
|
||||||
ret0, _ := ret[0].([]outbound.Handler)
|
|
||||||
return ret0
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListHandlers indicates an expected call of ListHandlers
|
|
||||||
func (mr *OutboundManagerMockRecorder) ListHandlers(arg0 interface{}) *gomock.Call {
|
|
||||||
mr.mock.ctrl.T.Helper()
|
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListHandlers", reflect.TypeOf((*OutboundManager)(nil).ListHandlers), arg0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveHandler mocks base method
|
// RemoveHandler mocks base method
|
||||||
func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error {
|
func (m *OutboundManager) RemoveHandler(arg0 context.Context, arg1 string) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
@ -31,7 +31,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/testing/servers/tcp"
|
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
"google.golang.org/protobuf/testing/protocmp"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCommanderListenConfigurationItem(t *testing.T) {
|
func TestCommanderListenConfigurationItem(t *testing.T) {
|
||||||
@ -203,116 +202,6 @@ func TestCommanderRemoveHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommanderListHandlers(t *testing.T) {
|
|
||||||
tcpServer := tcp.Server{
|
|
||||||
MsgProcessor: xor,
|
|
||||||
}
|
|
||||||
dest, err := tcpServer.Start()
|
|
||||||
common.Must(err)
|
|
||||||
defer tcpServer.Close()
|
|
||||||
|
|
||||||
clientPort := tcp.PickPort()
|
|
||||||
cmdPort := tcp.PickPort()
|
|
||||||
clientConfig := &core.Config{
|
|
||||||
App: []*serial.TypedMessage{
|
|
||||||
serial.ToTypedMessage(&commander.Config{
|
|
||||||
Tag: "api",
|
|
||||||
Service: []*serial.TypedMessage{
|
|
||||||
serial.ToTypedMessage(&command.Config{}),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
serial.ToTypedMessage(&router.Config{
|
|
||||||
Rule: []*router.RoutingRule{
|
|
||||||
{
|
|
||||||
InboundTag: []string{"api"},
|
|
||||||
TargetTag: &router.RoutingRule_Tag{
|
|
||||||
Tag: "api",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
Inbound: []*core.InboundHandlerConfig{
|
|
||||||
{
|
|
||||||
Tag: "d",
|
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
|
||||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(clientPort)}},
|
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
|
||||||
Address: net.NewIPOrDomain(dest.Address),
|
|
||||||
Port: uint32(dest.Port),
|
|
||||||
Networks: []net.Network{net.Network_TCP},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Tag: "api",
|
|
||||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
|
||||||
PortList: &net.PortList{Range: []*net.PortRange{net.SinglePortRange(cmdPort)}},
|
|
||||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
|
||||||
}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
|
||||||
Address: net.NewIPOrDomain(dest.Address),
|
|
||||||
Port: uint32(dest.Port),
|
|
||||||
Networks: []net.Network{net.Network_TCP},
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Outbound: []*core.OutboundHandlerConfig{
|
|
||||||
{
|
|
||||||
Tag: "default-outbound",
|
|
||||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{}),
|
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
servers, err := InitializeServerConfigs(clientConfig)
|
|
||||||
common.Must(err)
|
|
||||||
defer CloseAllServers(servers)
|
|
||||||
|
|
||||||
if err := testTCPConn(clientPort, 1024, time.Second*5)(); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
cmdConn, err := grpc.Dial(fmt.Sprintf("127.0.0.1:%d", cmdPort), grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithBlock())
|
|
||||||
common.Must(err)
|
|
||||||
defer cmdConn.Close()
|
|
||||||
|
|
||||||
hsClient := command.NewHandlerServiceClient(cmdConn)
|
|
||||||
inboundResp, err := hsClient.ListInbounds(context.Background(), &command.ListInboundsRequest{})
|
|
||||||
common.Must(err)
|
|
||||||
if inboundResp == nil {
|
|
||||||
t.Error("unexpected nil response")
|
|
||||||
}
|
|
||||||
|
|
||||||
if diff := cmp.Diff(
|
|
||||||
inboundResp.Inbounds,
|
|
||||||
clientConfig.Inbound,
|
|
||||||
protocmp.Transform(),
|
|
||||||
cmpopts.SortSlices(func(a, b *core.InboundHandlerConfig) bool {
|
|
||||||
return a.Tag < b.Tag
|
|
||||||
})); diff != "" {
|
|
||||||
t.Fatalf("inbound response doesn't match config (-want +got):\n%s", diff)
|
|
||||||
}
|
|
||||||
|
|
||||||
outboundResp, err := hsClient.ListOutbounds(context.Background(), &command.ListOutboundsRequest{})
|
|
||||||
common.Must(err)
|
|
||||||
if outboundResp == nil {
|
|
||||||
t.Error("unexpected nil response")
|
|
||||||
}
|
|
||||||
|
|
||||||
if diff := cmp.Diff(
|
|
||||||
outboundResp.Outbounds,
|
|
||||||
clientConfig.Outbound,
|
|
||||||
protocmp.Transform(),
|
|
||||||
cmpopts.SortSlices(func(a, b *core.InboundHandlerConfig) bool {
|
|
||||||
return a.Tag < b.Tag
|
|
||||||
})); diff != "" {
|
|
||||||
t.Fatalf("outbound response doesn't match config (-want +got):\n%s", diff)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCommanderAddRemoveUser(t *testing.T) {
|
func TestCommanderAddRemoveUser(t *testing.T) {
|
||||||
tcpServer := tcp.Server{
|
tcpServer := tcp.Server{
|
||||||
MsgProcessor: xor,
|
MsgProcessor: xor,
|
||||||
|
@ -417,12 +417,10 @@ type CustomSockopt struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
System string `protobuf:"bytes,1,opt,name=system,proto3" json:"system,omitempty"`
|
Level string `protobuf:"bytes,1,opt,name=level,proto3" json:"level,omitempty"`
|
||||||
Network string `protobuf:"bytes,2,opt,name=network,proto3" json:"network,omitempty"`
|
Opt string `protobuf:"bytes,2,opt,name=opt,proto3" json:"opt,omitempty"`
|
||||||
Level string `protobuf:"bytes,3,opt,name=level,proto3" json:"level,omitempty"`
|
Value string `protobuf:"bytes,3,opt,name=value,proto3" json:"value,omitempty"`
|
||||||
Opt string `protobuf:"bytes,4,opt,name=opt,proto3" json:"opt,omitempty"`
|
Type string `protobuf:"bytes,4,opt,name=type,proto3" json:"type,omitempty"`
|
||||||
Value string `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"`
|
|
||||||
Type string `protobuf:"bytes,6,opt,name=type,proto3" json:"type,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CustomSockopt) Reset() {
|
func (x *CustomSockopt) Reset() {
|
||||||
@ -455,20 +453,6 @@ func (*CustomSockopt) Descriptor() ([]byte, []int) {
|
|||||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{3}
|
return file_transport_internet_config_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CustomSockopt) GetSystem() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.System
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CustomSockopt) GetNetwork() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Network
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CustomSockopt) GetLevel() string {
|
func (x *CustomSockopt) GetLevel() string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Level
|
return x.Level
|
||||||
@ -529,7 +513,6 @@ type SocketConfig struct {
|
|||||||
TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"`
|
TcpMptcp bool `protobuf:"varint,19,opt,name=tcp_mptcp,json=tcpMptcp,proto3" json:"tcp_mptcp,omitempty"`
|
||||||
CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"`
|
CustomSockopt []*CustomSockopt `protobuf:"bytes,20,rep,name=customSockopt,proto3" json:"customSockopt,omitempty"`
|
||||||
AddressPortStrategy AddressPortStrategy `protobuf:"varint,21,opt,name=address_port_strategy,json=addressPortStrategy,proto3,enum=xray.transport.internet.AddressPortStrategy" json:"address_port_strategy,omitempty"`
|
AddressPortStrategy AddressPortStrategy `protobuf:"varint,21,opt,name=address_port_strategy,json=addressPortStrategy,proto3,enum=xray.transport.internet.AddressPortStrategy" json:"address_port_strategy,omitempty"`
|
||||||
HappyEyeballs *HappyEyeballsConfig `protobuf:"bytes,22,opt,name=happy_eyeballs,json=happyEyeballs,proto3" json:"happy_eyeballs,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SocketConfig) Reset() {
|
func (x *SocketConfig) Reset() {
|
||||||
@ -709,82 +692,6 @@ func (x *SocketConfig) GetAddressPortStrategy() AddressPortStrategy {
|
|||||||
return AddressPortStrategy_None
|
return AddressPortStrategy_None
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SocketConfig) GetHappyEyeballs() *HappyEyeballsConfig {
|
|
||||||
if x != nil {
|
|
||||||
return x.HappyEyeballs
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type HappyEyeballsConfig struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
PrioritizeIpv6 bool `protobuf:"varint,1,opt,name=prioritize_ipv6,json=prioritizeIpv6,proto3" json:"prioritize_ipv6,omitempty"`
|
|
||||||
Interleave uint32 `protobuf:"varint,2,opt,name=interleave,proto3" json:"interleave,omitempty"`
|
|
||||||
TryDelayMs uint64 `protobuf:"varint,3,opt,name=try_delayMs,json=tryDelayMs,proto3" json:"try_delayMs,omitempty"`
|
|
||||||
MaxConcurrentTry uint32 `protobuf:"varint,4,opt,name=max_concurrent_try,json=maxConcurrentTry,proto3" json:"max_concurrent_try,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HappyEyeballsConfig) Reset() {
|
|
||||||
*x = HappyEyeballsConfig{}
|
|
||||||
mi := &file_transport_internet_config_proto_msgTypes[5]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HappyEyeballsConfig) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*HappyEyeballsConfig) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *HappyEyeballsConfig) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_transport_internet_config_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 HappyEyeballsConfig.ProtoReflect.Descriptor instead.
|
|
||||||
func (*HappyEyeballsConfig) Descriptor() ([]byte, []int) {
|
|
||||||
return file_transport_internet_config_proto_rawDescGZIP(), []int{5}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HappyEyeballsConfig) GetPrioritizeIpv6() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.PrioritizeIpv6
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HappyEyeballsConfig) GetInterleave() uint32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Interleave
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HappyEyeballsConfig) GetTryDelayMs() uint64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.TryDelayMs
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *HappyEyeballsConfig) GetMaxConcurrentTry() uint32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.MaxConcurrentTry
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
var File_transport_internet_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_transport_internet_config_proto_rawDesc = []byte{
|
var file_transport_internet_config_proto_rawDesc = []byte{
|
||||||
@ -833,124 +740,105 @@ var file_transport_internet_config_proto_rawDesc = []byte{
|
|||||||
0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x30, 0x0a, 0x13,
|
0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x30, 0x0a, 0x13,
|
||||||
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72,
|
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72,
|
||||||
0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
0x6f, 0x78, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x74, 0x72, 0x61, 0x6e, 0x73,
|
||||||
0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x22, 0x93,
|
0x70, 0x6f, 0x72, 0x74, 0x4c, 0x61, 0x79, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x22, 0x61,
|
||||||
0x01, 0x0a, 0x0d, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74,
|
0x0a, 0x0d, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x12,
|
||||||
0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||||
0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77,
|
0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x6f, 0x72, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f,
|
0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0x72, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28,
|
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a,
|
||||||
0x09, 0x52, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x10, 0x0a, 0x03, 0x6f, 0x70, 0x74, 0x18,
|
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70,
|
||||||
0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6f, 0x70, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
|
0x65, 0x22, 0xfd, 0x07, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66,
|
||||||
0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
|
||||||
0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f, 0x18, 0x02, 0x20,
|
||||||
0x74, 0x79, 0x70, 0x65, 0x22, 0xd2, 0x08, 0x0a, 0x0c, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43,
|
0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74, 0x70, 0x72, 0x6f,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x18, 0x01, 0x20,
|
0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x61, 0x72, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x66, 0x6f,
|
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x74, 0x66, 0x6f, 0x12, 0x48, 0x0a, 0x06, 0x74,
|
0x65, 0x74, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x30, 0x2e, 0x78, 0x72,
|
0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x74, 0x70, 0x72, 0x6f,
|
||||||
0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74,
|
0x78, 0x79, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72,
|
||||||
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66,
|
0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72,
|
||||||
0x69, 0x67, 0x2e, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x06, 0x74,
|
0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69,
|
||||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x41, 0x0a, 0x1d, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x41, 0x64,
|
||||||
0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x5f, 0x61,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64, 0x5f, 0x61, 0x64,
|
||||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x62, 0x69, 0x6e,
|
||||||
0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73,
|
0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x69, 0x6e, 0x64,
|
||||||
0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x69, 0x6e, 0x64,
|
0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x62, 0x69, 0x6e,
|
||||||
0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b,
|
0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x5f,
|
||||||
0x62, 0x69, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x62,
|
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x07,
|
||||||
0x69, 0x6e, 0x64, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08,
|
0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78,
|
||||||
0x62, 0x69, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65,
|
0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x50, 0x0a, 0x0f, 0x64, 0x6f, 0x6d,
|
||||||
0x70, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x08, 0x20, 0x01,
|
||||||
0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50,
|
0x28, 0x0e, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x50, 0x0a, 0x0f,
|
0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18,
|
0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d,
|
||||||
0x08, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x21, 0x0a, 0x0c, 0x64,
|
||||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
0x69, 0x61, 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28,
|
||||||
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e,
|
0x09, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x35,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x21,
|
0x0a, 0x17, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x61, 0x6c, 0x69, 0x76, 0x65,
|
||||||
0x0a, 0x0c, 0x64, 0x69, 0x61, 0x6c, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x09,
|
0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x69, 0x61, 0x6c, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x78,
|
0x14, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74,
|
||||||
0x79, 0x12, 0x35, 0x0a, 0x17, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65, 0x70, 0x5f, 0x61, 0x6c,
|
0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2d, 0x0a, 0x13, 0x74, 0x63, 0x70, 0x5f, 0x6b, 0x65, 0x65,
|
||||||
0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01,
|
0x70, 0x5f, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x64, 0x6c, 0x65, 0x18, 0x0b, 0x20, 0x01,
|
||||||
0x28, 0x05, 0x52, 0x14, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65,
|
0x28, 0x05, 0x52, 0x10, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c, 0x69, 0x76, 0x65,
|
||||||
0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x2d, 0x0a, 0x13, 0x74, 0x63, 0x70, 0x5f,
|
0x49, 0x64, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x63, 0x70, 0x5f, 0x63, 0x6f, 0x6e, 0x67,
|
||||||
0x6b, 0x65, 0x65, 0x70, 0x5f, 0x61, 0x6c, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x64, 0x6c, 0x65, 0x18,
|
0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x74, 0x63,
|
||||||
0x0b, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x74, 0x63, 0x70, 0x4b, 0x65, 0x65, 0x70, 0x41, 0x6c,
|
0x70, 0x43, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x69,
|
||||||
0x69, 0x76, 0x65, 0x49, 0x64, 0x6c, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x74, 0x63, 0x70, 0x5f, 0x63,
|
0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||||
0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x36, 0x6f,
|
||||||
0x0d, 0x74, 0x63, 0x70, 0x43, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c,
|
0x6e, 0x6c, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, 0x36, 0x6f, 0x6e, 0x6c,
|
||||||
0x0a, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28,
|
0x79, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x63, 0x70, 0x5f, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x5f,
|
||||||
0x09, 0x52, 0x09, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06,
|
0x63, 0x6c, 0x61, 0x6d, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x63, 0x70,
|
||||||
0x76, 0x36, 0x6f, 0x6e, 0x6c, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x76, 0x36,
|
0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x43, 0x6c, 0x61, 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x74,
|
||||||
0x6f, 0x6e, 0x6c, 0x79, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x63, 0x70, 0x5f, 0x77, 0x69, 0x6e, 0x64,
|
0x63, 0x70, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18,
|
||||||
0x6f, 0x77, 0x5f, 0x63, 0x6c, 0x61, 0x6d, 0x70, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e,
|
0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x63, 0x70, 0x55, 0x73, 0x65, 0x72, 0x54, 0x69,
|
||||||
0x74, 0x63, 0x70, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x43, 0x6c, 0x61, 0x6d, 0x70, 0x12, 0x28,
|
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x61, 0x78,
|
||||||
0x0a, 0x10, 0x74, 0x63, 0x70, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f,
|
0x5f, 0x73, 0x65, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74, 0x63, 0x70, 0x4d,
|
||||||
0x75, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x74, 0x63, 0x70, 0x55, 0x73, 0x65,
|
0x61, 0x78, 0x53, 0x65, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x6e, 0x65, 0x74, 0x72, 0x61,
|
||||||
0x72, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0b, 0x74, 0x63, 0x70, 0x5f,
|
0x74, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x6e, 0x65, 0x74, 0x72,
|
||||||
0x6d, 0x61, 0x78, 0x5f, 0x73, 0x65, 0x67, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x74,
|
0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x70, 0x74, 0x63, 0x70,
|
||||||
0x63, 0x70, 0x4d, 0x61, 0x78, 0x53, 0x65, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x65, 0x6e, 0x65,
|
0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x63, 0x70, 0x4d, 0x70, 0x74, 0x63, 0x70,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x70, 0x65, 0x6e,
|
0x12, 0x4c, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70,
|
||||||
0x65, 0x74, 0x72, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x63, 0x70, 0x5f, 0x6d, 0x70,
|
0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
|
||||||
0x74, 0x63, 0x70, 0x18, 0x13, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x63, 0x70, 0x4d, 0x70,
|
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
||||||
0x74, 0x63, 0x70, 0x12, 0x4c, 0x0a, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63,
|
0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x52,
|
||||||
0x6b, 0x6f, 0x70, 0x74, 0x18, 0x14, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61,
|
0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70, 0x74, 0x12, 0x60,
|
||||||
0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65,
|
0x0a, 0x15, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x73,
|
||||||
0x72, 0x6e, 0x65, 0x74, 0x2e, 0x43, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2c, 0x2e,
|
||||||
0x70, 0x74, 0x52, 0x0d, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x53, 0x6f, 0x63, 0x6b, 0x6f, 0x70,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
|
||||||
0x74, 0x12, 0x60, 0x0a, 0x15, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x6f, 0x72,
|
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50,
|
||||||
0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0e,
|
0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x13, 0x61, 0x64, 0x64,
|
||||||
0x32, 0x2c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
|
0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65,
|
0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07,
|
||||||
0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x13,
|
0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78,
|
||||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74,
|
0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10,
|
||||||
0x65, 0x67, 0x79, 0x12, 0x53, 0x0a, 0x0e, 0x68, 0x61, 0x70, 0x70, 0x79, 0x5f, 0x65, 0x79, 0x65,
|
0x02, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61,
|
||||||
0x62, 0x61, 0x6c, 0x6c, 0x73, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72,
|
0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12,
|
||||||
0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74,
|
0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55,
|
||||||
0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x48, 0x61, 0x70, 0x70, 0x79, 0x45, 0x79, 0x65, 0x62, 0x61,
|
0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f,
|
||||||
0x6c, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x68, 0x61, 0x70, 0x70, 0x79,
|
0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34,
|
||||||
0x45, 0x79, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x73, 0x22, 0x2f, 0x0a, 0x0a, 0x54, 0x50, 0x72, 0x6f,
|
0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10,
|
||||||
0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x66, 0x66, 0x10, 0x00, 0x12,
|
0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12,
|
||||||
0x0a, 0x0a, 0x06, 0x54, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x52,
|
0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d,
|
||||||
0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x22, 0xad, 0x01, 0x0a, 0x13, 0x48, 0x61,
|
0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a,
|
||||||
0x70, 0x70, 0x79, 0x45, 0x79, 0x65, 0x62, 0x61, 0x6c, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a,
|
||||||
0x67, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x5f,
|
0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x0a, 0x2a, 0x97, 0x01,
|
||||||
0x69, 0x70, 0x76, 0x36, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x69, 0x6f,
|
0x0a, 0x13, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72,
|
||||||
0x72, 0x69, 0x74, 0x69, 0x7a, 0x65, 0x49, 0x70, 0x76, 0x36, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x6e,
|
0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12,
|
||||||
0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a,
|
0x0f, 0x0a, 0x0b, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x01,
|
||||||
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x65, 0x61, 0x76, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x72,
|
0x12, 0x12, 0x0a, 0x0e, 0x53, 0x72, 0x76, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e,
|
||||||
0x79, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
|
0x6c, 0x79, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x41,
|
||||||
0x0a, 0x74, 0x72, 0x79, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x6d,
|
0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54,
|
||||||
0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x72,
|
0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e,
|
||||||
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6e, 0x63,
|
0x54, 0x78, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x05,
|
||||||
0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x79, 0x2a, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f,
|
0x12, 0x15, 0x0a, 0x11, 0x54, 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x6e, 0x64, 0x41, 0x64,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x06, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||||
0x41, 0x53, 0x5f, 0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
||||||
0x50, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02,
|
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||||
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a,
|
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63,
|
||||||
0x08, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55,
|
0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e,
|
||||||
0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52,
|
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72,
|
||||||
0x43, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45,
|
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||||
0x5f, 0x49, 0x50, 0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x49, 0x50, 0x36, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49,
|
|
||||||
0x50, 0x34, 0x36, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49,
|
|
||||||
0x50, 0x36, 0x34, 0x10, 0x0a, 0x2a, 0x97, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
|
||||||
0x73, 0x50, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a,
|
|
||||||
0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x72, 0x76, 0x50, 0x6f,
|
|
||||||
0x72, 0x74, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x72, 0x76, 0x41,
|
|
||||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11,
|
|
||||||
0x53, 0x72, 0x76, 0x50, 0x6f, 0x72, 0x74, 0x41, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
|
||||||
0x73, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x78, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x4f, 0x6e,
|
|
||||||
0x6c, 0x79, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x54, 0x78, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65,
|
|
||||||
0x73, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x10, 0x05, 0x12, 0x15, 0x0a, 0x11, 0x54, 0x78, 0x74, 0x50,
|
|
||||||
0x6f, 0x72, 0x74, 0x41, 0x6e, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x10, 0x06, 0x42,
|
|
||||||
0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e,
|
|
||||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x50, 0x01,
|
|
||||||
0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c,
|
|
||||||
0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e,
|
|
||||||
0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0xaa, 0x02,
|
|
||||||
0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e,
|
|
||||||
0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -966,7 +854,7 @@ func file_transport_internet_config_proto_rawDescGZIP() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
|
var file_transport_internet_config_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
|
||||||
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
var file_transport_internet_config_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
var file_transport_internet_config_proto_goTypes = []any{
|
var file_transport_internet_config_proto_goTypes = []any{
|
||||||
(DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy
|
(DomainStrategy)(0), // 0: xray.transport.internet.DomainStrategy
|
||||||
(AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy
|
(AddressPortStrategy)(0), // 1: xray.transport.internet.AddressPortStrategy
|
||||||
@ -976,26 +864,24 @@ var file_transport_internet_config_proto_goTypes = []any{
|
|||||||
(*ProxyConfig)(nil), // 5: xray.transport.internet.ProxyConfig
|
(*ProxyConfig)(nil), // 5: xray.transport.internet.ProxyConfig
|
||||||
(*CustomSockopt)(nil), // 6: xray.transport.internet.CustomSockopt
|
(*CustomSockopt)(nil), // 6: xray.transport.internet.CustomSockopt
|
||||||
(*SocketConfig)(nil), // 7: xray.transport.internet.SocketConfig
|
(*SocketConfig)(nil), // 7: xray.transport.internet.SocketConfig
|
||||||
(*HappyEyeballsConfig)(nil), // 8: xray.transport.internet.HappyEyeballsConfig
|
(*serial.TypedMessage)(nil), // 8: xray.common.serial.TypedMessage
|
||||||
(*serial.TypedMessage)(nil), // 9: xray.common.serial.TypedMessage
|
(*net.IPOrDomain)(nil), // 9: xray.common.net.IPOrDomain
|
||||||
(*net.IPOrDomain)(nil), // 10: xray.common.net.IPOrDomain
|
|
||||||
}
|
}
|
||||||
var file_transport_internet_config_proto_depIdxs = []int32{
|
var file_transport_internet_config_proto_depIdxs = []int32{
|
||||||
9, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
8, // 0: xray.transport.internet.TransportConfig.settings:type_name -> xray.common.serial.TypedMessage
|
||||||
10, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
|
9, // 1: xray.transport.internet.StreamConfig.address:type_name -> xray.common.net.IPOrDomain
|
||||||
3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig
|
3, // 2: xray.transport.internet.StreamConfig.transport_settings:type_name -> xray.transport.internet.TransportConfig
|
||||||
9, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
|
8, // 3: xray.transport.internet.StreamConfig.security_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
7, // 4: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
|
7, // 4: xray.transport.internet.StreamConfig.socket_settings:type_name -> xray.transport.internet.SocketConfig
|
||||||
2, // 5: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
|
2, // 5: xray.transport.internet.SocketConfig.tproxy:type_name -> xray.transport.internet.SocketConfig.TProxyMode
|
||||||
0, // 6: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
0, // 6: xray.transport.internet.SocketConfig.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||||
6, // 7: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
|
6, // 7: xray.transport.internet.SocketConfig.customSockopt:type_name -> xray.transport.internet.CustomSockopt
|
||||||
1, // 8: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy
|
1, // 8: xray.transport.internet.SocketConfig.address_port_strategy:type_name -> xray.transport.internet.AddressPortStrategy
|
||||||
8, // 9: xray.transport.internet.SocketConfig.happy_eyeballs:type_name -> xray.transport.internet.HappyEyeballsConfig
|
9, // [9:9] is the sub-list for method output_type
|
||||||
10, // [10:10] is the sub-list for method output_type
|
9, // [9:9] is the sub-list for method input_type
|
||||||
10, // [10:10] is the sub-list for method input_type
|
9, // [9:9] is the sub-list for extension type_name
|
||||||
10, // [10:10] is the sub-list for extension type_name
|
9, // [9:9] is the sub-list for extension extendee
|
||||||
10, // [10:10] is the sub-list for extension extendee
|
0, // [0:9] is the sub-list for field type_name
|
||||||
0, // [0:10] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_transport_internet_config_proto_init() }
|
func init() { file_transport_internet_config_proto_init() }
|
||||||
@ -1009,7 +895,7 @@ func file_transport_internet_config_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_transport_internet_config_proto_rawDesc,
|
RawDescriptor: file_transport_internet_config_proto_rawDesc,
|
||||||
NumEnums: 3,
|
NumEnums: 3,
|
||||||
NumMessages: 6,
|
NumMessages: 5,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
@ -65,12 +65,10 @@ message ProxyConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message CustomSockopt {
|
message CustomSockopt {
|
||||||
string system = 1;
|
string level = 1;
|
||||||
string network = 2;
|
string opt = 2;
|
||||||
string level = 3;
|
string value = 3;
|
||||||
string opt = 4;
|
string type = 4;
|
||||||
string value = 5;
|
|
||||||
string type = 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SocketConfig is options to be applied on network sockets.
|
// SocketConfig is options to be applied on network sockets.
|
||||||
@ -130,13 +128,4 @@ message SocketConfig {
|
|||||||
repeated CustomSockopt customSockopt = 20;
|
repeated CustomSockopt customSockopt = 20;
|
||||||
|
|
||||||
AddressPortStrategy address_port_strategy = 21;
|
AddressPortStrategy address_port_strategy = 21;
|
||||||
|
|
||||||
HappyEyeballsConfig happy_eyeballs = 22;
|
|
||||||
}
|
|
||||||
|
|
||||||
message HappyEyeballsConfig {
|
|
||||||
bool prioritize_ipv6 = 1;
|
|
||||||
uint32 interleave = 2;
|
|
||||||
uint64 try_delayMs = 3;
|
|
||||||
uint32 max_concurrent_try = 4;
|
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user