mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-23 01:56:48 +08:00
Compare commits
1 Commits
5129c1e4ff
...
dialTimeou
Author | SHA1 | Date | |
---|---|---|---|
![]() |
43b57825fa |
72
.github/docker/Dockerfile
vendored
72
.github/docker/Dockerfile
vendored
@@ -1,62 +1,28 @@
|
||||
# syntax=docker/dockerfile:latest
|
||||
FROM --platform=$BUILDPLATFORM golang:latest AS build
|
||||
|
||||
# Build xray-core
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
||||
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
|
||||
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
|
||||
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
|
||||
# chainguard/static contains only tzdata and ca-certificates, can be built with multiarch static binaries.
|
||||
FROM --platform=linux/amd64 chainguard/static:latest
|
||||
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
|
||||
|
||||
# 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
|
||||
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
|
||||
USER root
|
||||
WORKDIR /root
|
||||
VOLUME /etc/xray
|
||||
ARG TZ=Asia/Shanghai
|
||||
ENV TZ=$TZ
|
||||
ENTRYPOINT [ "/usr/bin/xray" ]
|
||||
CMD [ "-confdir", "/etc/xray/" ]
|
||||
|
||||
ENTRYPOINT [ "/usr/local/bin/xray" ]
|
||||
CMD [ "-confdir", "/usr/local/etc/xray/" ]
|
||||
ARG flavor=v2fly
|
||||
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": {}
|
||||
}]
|
||||
}
|
155
.github/workflows/docker.yml
vendored
155
.github/workflows/docker.yml
vendored
@@ -1,133 +1,76 @@
|
||||
name: Build and Push Docker Image
|
||||
name: Build docker image
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
- released
|
||||
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Docker image tag:"
|
||||
required: true
|
||||
latest:
|
||||
description: "Set to latest"
|
||||
type: boolean
|
||||
default: false
|
||||
types: [published]
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
if: (github.event.action != 'published') || (github.event.action == 'published' && github.event.release.prerelease == true)
|
||||
build-image:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Set repository and image name to lowercase
|
||||
env:
|
||||
IMAGE_NAME: "${{ github.repository }}"
|
||||
run: |
|
||||
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||
|
||||
- name: Validate and extract tag
|
||||
run: |
|
||||
SOURCE_TAG="${{ github.event.inputs.tag }}"
|
||||
if [[ -z "$SOURCE_TAG" ]]; then
|
||||
SOURCE_TAG="${{ github.ref_name }}"
|
||||
fi
|
||||
if [[ -z "$SOURCE_TAG" ]]; then
|
||||
SOURCE_TAG="${{ github.event.release.tag_name }}"
|
||||
fi
|
||||
|
||||
if [[ -z "$SOURCE_TAG" ]]; then
|
||||
echo "Error: Could not determine a valid tag source. Input tag and context tag (github.ref_name) are both empty."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$SOURCE_TAG" =~ ^v[0-9]+\.[0-9] ]]; then
|
||||
IMAGE_TAG="${SOURCE_TAG#v}"
|
||||
else
|
||||
IMAGE_TAG="$SOURCE_TAG"
|
||||
fi
|
||||
|
||||
echo "Docker image tag: '$IMAGE_TAG'."
|
||||
echo "IMAGE_TAG=$IMAGE_TAG" >>${GITHUB_ENV}
|
||||
|
||||
LATEST=false
|
||||
if [[ "${{ github.event_name }}" == "release" && "${{ github.event.release.prerelease }}" == "false" ]] || [[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.latest }}" == "true" ]]; then
|
||||
LATEST=true
|
||||
fi
|
||||
|
||||
echo "Latest: '$LATEST'."
|
||||
echo "LATEST=$LATEST" >>${GITHUB_ENV}
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- name: Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
||||
flavor: latest=auto
|
||||
tags: |
|
||||
type=sha
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
- name: Docker metadata Loyalsoldier flavor
|
||||
id: loyalsoldier
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
||||
flavor: |
|
||||
latest=auto
|
||||
suffix=-ls,onlatest=true
|
||||
tags: |
|
||||
type=sha
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Docker image (main architectures)
|
||||
id: build_main_arches
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: .github/docker/Dockerfile
|
||||
platforms: |
|
||||
linux/amd64
|
||||
linux/arm/v7
|
||||
linux/arm64/v8
|
||||
linux/ppc64le
|
||||
linux/s390x
|
||||
linux/arm64
|
||||
linux/loong64
|
||||
linux/riscv64
|
||||
provenance: false
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
|
||||
- name: Build Docker image (additional architectures)
|
||||
id: build_additional_arches
|
||||
file: .github/docker/Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
- name: Build and push Loyalsoldier flavor
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: .github/docker/Dockerfile.usa
|
||||
platforms: |
|
||||
linux/386
|
||||
linux/arm/v6
|
||||
linux/riscv64
|
||||
linux/amd64
|
||||
linux/arm64
|
||||
linux/loong64
|
||||
linux/riscv64
|
||||
provenance: false
|
||||
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||
|
||||
- name: Create manifest list and push
|
||||
run: |
|
||||
echo "Creating multi-arch manifest with tag: '${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}'."
|
||||
docker buildx imagetools create \
|
||||
--tag ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }} \
|
||||
${{ env.FULL_IMAGE_NAME }}@${{ steps.build_main_arches.outputs.digest }} \
|
||||
${{ env.FULL_IMAGE_NAME }}@${{ steps.build_additional_arches.outputs.digest }}
|
||||
|
||||
if [[ "${{ env.LATEST }}" == "true" ]]; then
|
||||
echo "Adding 'latest' tag to manifest: '${{ env.FULL_IMAGE_NAME }}:latest'."
|
||||
docker buildx imagetools create \
|
||||
--tag ${{ env.FULL_IMAGE_NAME }}:latest \
|
||||
${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||
fi
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ env.IMAGE_TAG }}
|
||||
|
||||
if [[ "${{ env.LATEST }}" == "true" ]]; then
|
||||
docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:latest
|
||||
fi
|
||||
file: .github/docker/Dockerfile
|
||||
build-args: flavor=loyalsoldier
|
||||
push: true
|
||||
tags: |
|
||||
${{ steps.loyalsoldier.outputs.tags }}
|
||||
|
33
.github/workflows/release-win7.yml
vendored
33
.github/workflows/release-win7.yml
vendored
@@ -9,38 +9,7 @@ on:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
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:
|
||||
needs: check-assets
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
@@ -82,7 +51,7 @@ jobs:
|
||||
GOSDK=$(go env GOROOT)
|
||||
rm -r $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
|
||||
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]
|
||||
|
||||
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:
|
||||
needs: check-assets
|
||||
permissions:
|
||||
contents: write
|
||||
strategy:
|
||||
@@ -88,11 +42,6 @@ jobs:
|
||||
- goos: android
|
||||
goarch: arm64
|
||||
# END Android ARM 8
|
||||
# BEGIN Android AMD64
|
||||
- goos: android
|
||||
goarch: amd64
|
||||
patch-assetname: android-amd64
|
||||
# END Android AMD64
|
||||
# Windows ARM
|
||||
- goos: windows
|
||||
goarch: arm64
|
||||
@@ -155,19 +104,6 @@ jobs:
|
||||
- name: Checkout codebase
|
||||
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
|
||||
run: |
|
||||
_NAME=${{ matrix.patch-assetname }}
|
||||
|
@@ -9,7 +9,7 @@ on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# Update GeoData on every day (22:30 UTC)
|
||||
- cron: "30 22 * * *"
|
||||
- cron: '30 22 * * *'
|
||||
push:
|
||||
# Prevent triggering update request storm
|
||||
paths:
|
||||
@@ -45,12 +45,12 @@ jobs:
|
||||
INFO=($(echo $i | awk 'BEGIN{FS=" ";OFS=" "} {print $1,$2,$3,$4}'))
|
||||
FILE_NAME="${INFO[3]}.dat"
|
||||
echo -e "Verifying HASH key..."
|
||||
HASH="$(curl -sL -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
|
||||
continue
|
||||
else
|
||||
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..."
|
||||
[ "$(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
|
||||
|
29
.github/workflows/test.yml
vendored
29
.github/workflows/test.yml
vendored
@@ -6,36 +6,7 @@ on:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
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:
|
||||
needs: check-assets
|
||||
permissions:
|
||||
contents: read
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
17
.gitignore
vendored
17
.gitignore
vendored
@@ -14,18 +14,10 @@
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# macOS specific files
|
||||
*.DS_Store
|
||||
|
||||
# IDE specific files
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Archive files
|
||||
.idea
|
||||
*.zip
|
||||
*.tar.gz
|
||||
|
||||
# Binaries
|
||||
xray
|
||||
xray_softfloat
|
||||
mockgen
|
||||
@@ -34,13 +26,8 @@ vprotogen
|
||||
errorgen
|
||||
!common/errors/errorgen/
|
||||
*.dat
|
||||
|
||||
# Build assets
|
||||
.vscode
|
||||
/build_assets
|
||||
|
||||
# Output from dlv test
|
||||
**/debug.*
|
||||
|
||||
# Certificates
|
||||
*.crt
|
||||
*.key
|
||||
|
39
README.md
39
README.md
@@ -6,13 +6,9 @@
|
||||
|
||||
## Donation & NFTs
|
||||
|
||||
### [Collect a Project X NFT to support the development of Project X!](https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1)
|
||||
|
||||
[<img alt="Project X NFT" width="150px" src="https://raw2.seadn.io/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/7fa9ce900fb39b44226348db330e32/8b7fa9ce900fb39b44226348db330e32.svg" />](https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1)
|
||||
|
||||
- **ETH/USDT/USDC: `0xDc3Fe44F0f25D13CACb1C4896CD0D321df3146Ee`**
|
||||
- **REALITY NFT: https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2**
|
||||
- **Related links: https://opensea.io/collection/xtls, [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633), [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113)**
|
||||
- **Project X NFT: [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633)**
|
||||
- **REALITY NFT: [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113)**
|
||||
|
||||
## License
|
||||
|
||||
@@ -42,13 +38,12 @@
|
||||
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
|
||||
- [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:**
|
||||
- [Remnawave](https://github.com/remnawave/panel)
|
||||
- [Marzban](https://github.com/Gozargah/Marzban)
|
||||
- [Xray-UI](https://github.com/qist/xray-ui)
|
||||
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
|
||||
- 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_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)
|
||||
- Magisk
|
||||
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
|
||||
@@ -85,43 +80,31 @@
|
||||
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||
- [Furious](https://github.com/LorenEteval/Furious)
|
||||
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
|
||||
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||
- Android
|
||||
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
||||
- [X-flutter](https://github.com/XTLS/X-flutter)
|
||||
- [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
|
||||
- [SimpleXray](https://github.com/lhear/SimpleXray)
|
||||
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||
- iOS & macOS arm64 & tvOS
|
||||
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215) ([tvOS](https://apps.apple.com/us/app/happ-proxy-utility-for-tv/id6748297274))
|
||||
- iOS & macOS arm64
|
||||
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
||||
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
||||
- [OneXray](https://github.com/OneXray/OneXray)
|
||||
- macOS arm64 & x64
|
||||
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
|
||||
- [V2rayU](https://github.com/yanue/V2rayU)
|
||||
- [V2RayXS](https://github.com/tzmax/V2RayXS)
|
||||
- [Furious](https://github.com/LorenEteval/Furious)
|
||||
- [OneXray](https://github.com/OneXray/OneXray)
|
||||
- [GoXRay](https://github.com/goxray/desktop)
|
||||
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
||||
- Linux
|
||||
- [v2rayA](https://github.com/v2rayA/v2rayA)
|
||||
- [Furious](https://github.com/LorenEteval/Furious)
|
||||
- [GorzRay](https://github.com/ketetefid/GorzRay)
|
||||
- [GoXRay](https://github.com/goxray/desktop)
|
||||
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||
|
||||
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
|
||||
|
||||
- iOS & macOS arm64 & tvOS
|
||||
- iOS & macOS arm64
|
||||
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
||||
- [Loon](https://apps.apple.com/us/app/loon/id1373567447)
|
||||
- Xray Tools
|
||||
- [xray-knife](https://github.com/lilendian0x00/xray-knife)
|
||||
- [xray-checker](https://github.com/kutovoys/xray-checker)
|
||||
- Xray Wrapper
|
||||
- [XTLS/libXray](https://github.com/XTLS/libXray)
|
||||
- [xtls-sdk](https://github.com/remnawave/xtls-sdk)
|
||||
- [xtlsapi](https://github.com/hiddify/xtlsapi)
|
||||
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
|
||||
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
|
||||
@@ -129,17 +112,15 @@
|
||||
- [XrayR](https://github.com/XrayR-project/XrayR)
|
||||
- [XrayR-release](https://github.com/XrayR-project/XrayR-release)
|
||||
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
|
||||
- Cores
|
||||
- [Amnezia VPN](https://github.com/amnezia-vpn)
|
||||
- [mihomo](https://github.com/MetaCubeX/mihomo)
|
||||
- [Clash.Meta](https://github.com/MetaCubeX/Clash.Meta)
|
||||
- [clashN](https://github.com/2dust/clashN)
|
||||
- [Clash Meta for Android](https://github.com/MetaCubeX/ClashMetaForAndroid)
|
||||
- [sing-box](https://github.com/SagerNet/sing-box)
|
||||
|
||||
## Contributing
|
||||
|
||||
[Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)
|
||||
|
||||
[](https://deepwiki.com/XTLS/Xray-core)
|
||||
|
||||
## 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).
|
||||
|
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"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/transport"
|
||||
)
|
||||
@@ -109,13 +108,3 @@ func (co *Outbound) Close() error {
|
||||
co.closed = true
|
||||
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
|
||||
}
|
||||
|
||||
func (r *cachedReader) Cache(b *buf.Buffer, deadline time.Duration) error {
|
||||
mb, err := r.reader.ReadMultiBufferTimeout(deadline)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func (r *cachedReader) Cache(b *buf.Buffer) {
|
||||
mb, _ := r.reader.ReadMultiBufferTimeout(time.Millisecond * 100)
|
||||
r.Lock()
|
||||
if !mb.IsEmpty() {
|
||||
r.cache, _ = buf.MergeMulti(r.cache, mb)
|
||||
}
|
||||
cacheLen := r.cache.Len()
|
||||
if cacheLen <= b.Cap() {
|
||||
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)
|
||||
b.Resize(0, int32(n))
|
||||
r.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *cachedReader) readInternal() buf.MultiBuffer {
|
||||
@@ -96,6 +98,7 @@ type DefaultDispatcher struct {
|
||||
router routing.Router
|
||||
policy policy.Manager
|
||||
stats stats.Manager
|
||||
dns dns.Client
|
||||
fdns dns.FakeDNSEngine
|
||||
}
|
||||
|
||||
@@ -106,7 +109,7 @@ func init() {
|
||||
core.OptionalFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||
d.fdns = fdns
|
||||
})
|
||||
return d.Init(config.(*Config), om, router, pm, sm)
|
||||
return d.Init(config.(*Config), om, router, pm, sm, dc)
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -115,11 +118,12 @@ func init() {
|
||||
}
|
||||
|
||||
// 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.router = router
|
||||
d.policy = pm
|
||||
d.stats = sm
|
||||
d.dns = dns
|
||||
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) {
|
||||
payload := buf.NewWithSize(32767)
|
||||
payload := buf.New()
|
||||
defer payload.Release()
|
||||
|
||||
sniffer := NewSniffer(ctx)
|
||||
@@ -363,36 +367,26 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
|
||||
}
|
||||
|
||||
contentResult, contentErr := func() (SniffResult, error) {
|
||||
cacheDeadline := 200 * time.Millisecond
|
||||
totalAttempt := 0
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
cachingStartingTimeStamp := time.Now()
|
||||
err := cReader.Cache(payload, cacheDeadline)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
totalAttempt++
|
||||
if totalAttempt > 2 {
|
||||
return nil, errSniffingTimeout
|
||||
}
|
||||
cachingTimeElapsed := time.Since(cachingStartingTimeStamp)
|
||||
cacheDeadline -= cachingTimeElapsed
|
||||
|
||||
cReader.Cache(payload)
|
||||
if !payload.IsEmpty() {
|
||||
result, err := sniffer.Sniff(ctx, payload.Bytes(), network)
|
||||
switch err {
|
||||
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:
|
||||
if err != common.ErrNoClue {
|
||||
return result, err
|
||||
}
|
||||
} else {
|
||||
totalAttempt++
|
||||
}
|
||||
if totalAttempt >= 2 || cacheDeadline <= 0 {
|
||||
return nil, errSniffingTimeout
|
||||
if payload.IsFull() {
|
||||
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) {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
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
|
||||
|
||||
|
@@ -6,7 +6,6 @@ import (
|
||||
"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/protocol"
|
||||
"github.com/xtls/xray-core/common/protocol/bittorrent"
|
||||
"github.com/xtls/xray-core/common/protocol/http"
|
||||
"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) {
|
||||
var pendingSniffer []protocolSnifferWithMetadata
|
||||
for _, si := range s.sniffer {
|
||||
protocolSniffer := si.protocolSniffer
|
||||
s := si.protocolSniffer
|
||||
if si.metadataSniffer || si.network != network {
|
||||
continue
|
||||
}
|
||||
result, err := protocolSniffer(c, payload)
|
||||
result, err := s(c, payload)
|
||||
if err == common.ErrNoClue {
|
||||
pendingSniffer = append(pendingSniffer, si)
|
||||
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 {
|
||||
|
@@ -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_IP4 QueryStrategy = 1
|
||||
QueryStrategy_USE_IP6 QueryStrategy = 2
|
||||
QueryStrategy_USE_SYS QueryStrategy = 3
|
||||
)
|
||||
|
||||
// Enum value maps for QueryStrategy.
|
||||
@@ -89,13 +88,11 @@ var (
|
||||
0: "USE_IP",
|
||||
1: "USE_IP4",
|
||||
2: "USE_IP6",
|
||||
3: "USE_SYS",
|
||||
}
|
||||
QueryStrategy_value = map[string]int32{
|
||||
"USE_IP": 0,
|
||||
"USE_IP4": 1,
|
||||
"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"`
|
||||
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"`
|
||||
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"`
|
||||
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() {
|
||||
@@ -205,9 +195,9 @@ func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
|
||||
func (x *NameServer) GetGeoip() []*router.GeoIP {
|
||||
if x != nil {
|
||||
return x.ExpectedGeoip
|
||||
return x.Geoip
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -226,55 +216,6 @@ func (x *NameServer) GetQueryStrategy() QueryStrategy {
|
||||
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 {
|
||||
state protoimpl.MessageState
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
@@ -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,
|
||||
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,
|
||||
0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x65,
|
||||
0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
|
||||
0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69,
|
||||
0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e,
|
||||
0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
|
||||
0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
|
||||
0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65,
|
||||
0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72,
|
||||
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x74,
|
||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x74,
|
||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x09, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f,
|
||||
0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
||||
0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
||||
0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6e,
|
||||
0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66,
|
||||
0x69, 0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x41, 0x0a, 0x10, 0x75, 0x6e, 0x65,
|
||||
0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0d, 0x20,
|
||||
0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65,
|
||||
0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a,
|
||||
0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x1a, 0x5e, 0x0a, 0x0e,
|
||||
0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34,
|
||||
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61,
|
||||
0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04,
|
||||
0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c,
|
||||
0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
||||
0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04,
|
||||
0x73, 0x69, 0x7a, 0x65, 0x22, 0x9c, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12,
|
||||
0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c,
|
||||
0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63,
|
||||
0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69,
|
||||
0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e,
|
||||
0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52,
|
||||
0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22,
|
||||
0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63,
|
||||
0x68, 0x65, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61,
|
||||
0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74,
|
||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c,
|
||||
0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||
0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
||||
0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62,
|
||||
0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63,
|
||||
0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73,
|
||||
0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63,
|
||||
0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16,
|
||||
0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03,
|
||||
0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65,
|
||||
0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
||||
0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08,
|
||||
0x07, 0x10, 0x08, 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74,
|
||||
0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c,
|
||||
0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12,
|
||||
0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x42, 0x0a, 0x0d, 0x51, 0x75,
|
||||
0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55,
|
||||
0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
||||
0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10,
|
||||
0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x53, 0x59, 0x53, 0x10, 0x03, 0x42, 0x46,
|
||||
0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64,
|
||||
0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f,
|
||||
0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41,
|
||||
0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69,
|
||||
0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
||||
0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52,
|
||||
0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
|
||||
0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
|
||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61,
|
||||
0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
|
||||
0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52,
|
||||
0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74,
|
||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72,
|
||||
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79,
|
||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f,
|
||||
0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79,
|
||||
0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61,
|
||||
0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||
0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67,
|
||||
0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65,
|
||||
0x22, 0x9c, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e,
|
||||
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
||||
0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
||||
0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f,
|
||||
0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||
0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61,
|
||||
0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
|
||||
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69,
|
||||
0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08,
|
||||
0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x42,
|
||||
0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||
0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74,
|
||||
0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
|
||||
0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c,
|
||||
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x73,
|
||||
0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a, 0x16,
|
||||
0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49,
|
||||
0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x64, 0x69,
|
||||
0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d,
|
||||
0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70,
|
||||
0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e,
|
||||
0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67,
|
||||
0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f,
|
||||
0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61,
|
||||
0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02,
|
||||
0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f,
|
||||
0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78,
|
||||
0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a,
|
||||
0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e,
|
||||
0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12,
|
||||
0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b,
|
||||
0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52,
|
||||
0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x35, 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, 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 (
|
||||
@@ -697,20 +621,19 @@ var file_app_dns_config_proto_goTypes = []any{
|
||||
var file_app_dns_config_proto_depIdxs = []int32{
|
||||
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
|
||||
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
|
||||
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, // 6: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
|
||||
6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
|
||||
1, // 8: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
||||
0, // 9: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
|
||||
0, // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
|
||||
11, // [11:11] is the sub-list for method output_type
|
||||
11, // [11:11] is the sub-list for method input_type
|
||||
11, // [11:11] is the sub-list for extension type_name
|
||||
11, // [11:11] is the sub-list for extension extendee
|
||||
0, // [0:11] is the sub-list for field type_name
|
||||
2, // 5: 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
|
||||
1, // 7: 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.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
|
||||
10, // [10:10] is the sub-list for method output_type
|
||||
10, // [10:10] is the sub-list for method input_type
|
||||
10, // [10:10] is the sub-list for extension type_name
|
||||
10, // [10:10] is the sub-list for extension extendee
|
||||
0, // [0:10] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_app_dns_config_proto_init() }
|
||||
|
@@ -25,16 +25,9 @@ message NameServer {
|
||||
}
|
||||
|
||||
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;
|
||||
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 {
|
||||
@@ -48,7 +41,6 @@ enum QueryStrategy {
|
||||
USE_IP = 0;
|
||||
USE_IP4 = 1;
|
||||
USE_IP6 = 2;
|
||||
USE_SYS = 3;
|
||||
}
|
||||
|
||||
message Config {
|
||||
|
191
app/dns/dns.go
191
app/dns/dns.go
@@ -3,12 +3,11 @@ package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
go_errors "errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/xtls/xray-core/app/router"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@@ -20,6 +19,8 @@ import (
|
||||
// DNS is a DNS rely server.
|
||||
type DNS struct {
|
||||
sync.Mutex
|
||||
tag string
|
||||
disableCache bool
|
||||
disableFallback bool
|
||||
disableFallbackIfMatch bool
|
||||
ipOption *dns.IPOption
|
||||
@@ -28,7 +29,6 @@ type DNS struct {
|
||||
ctx context.Context
|
||||
domainMatcher strmatcher.IndexMatcher
|
||||
matcherInfos []*DomainMatcherInfo
|
||||
checkSystem bool
|
||||
}
|
||||
|
||||
// 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.
|
||||
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
|
||||
switch len(config.ClientIp) {
|
||||
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))
|
||||
}
|
||||
|
||||
var ipOption dns.IPOption
|
||||
checkSystem := false
|
||||
var ipOption *dns.IPOption
|
||||
switch config.QueryStrategy {
|
||||
case QueryStrategy_USE_IP:
|
||||
ipOption = dns.IPOption{
|
||||
ipOption = &dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}
|
||||
case QueryStrategy_USE_SYS:
|
||||
ipOption = dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}
|
||||
checkSystem = true
|
||||
case QueryStrategy_USE_IP4:
|
||||
ipOption = dns.IPOption{
|
||||
ipOption = &dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
FakeEnable: false,
|
||||
}
|
||||
case QueryStrategy_USE_IP6:
|
||||
ipOption = dns.IPOption{
|
||||
ipOption = &dns.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("unexpected query strategy ", config.QueryStrategy)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
var clients []*Client
|
||||
clients := []*Client{}
|
||||
domainRuleCount := 0
|
||||
|
||||
var defaultTag = config.Tag
|
||||
if len(config.Tag) == 0 {
|
||||
defaultTag = generateRandomTag()
|
||||
}
|
||||
|
||||
for _, ns := range config.NameServer {
|
||||
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 := make([]*DomainMatcherInfo, domainRuleCount+1)
|
||||
domainMatcher := &strmatcher.MatcherGroup{}
|
||||
geoipContainer := router.GeoIPMatcherContainer{}
|
||||
|
||||
for _, ns := range config.NameServer {
|
||||
clientIdx := len(clients)
|
||||
@@ -116,19 +108,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
||||
case net.IPv4len, net.IPv6len:
|
||||
myClientIP = net.IP(ns.ClientIp)
|
||||
}
|
||||
|
||||
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)
|
||||
client, err := NewClient(ctx, ns, myClientIP, geoipContainer, &matcherInfos, updateDomain)
|
||||
if err != nil {
|
||||
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 len(clients) == 0 {
|
||||
clients = append(clients, NewLocalDNSClient(ipOption))
|
||||
clients = append(clients, NewLocalDNSClient())
|
||||
}
|
||||
|
||||
return &DNS{
|
||||
tag: tag,
|
||||
hosts: hosts,
|
||||
ipOption: &ipOption,
|
||||
ipOption: ipOption,
|
||||
clients: clients,
|
||||
ctx: ctx,
|
||||
domainMatcher: domainMatcher,
|
||||
matcherInfos: matcherInfos,
|
||||
disableCache: config.DisableCache,
|
||||
disableFallback: config.DisableFallback,
|
||||
disableFallbackIfMatch: config.DisableFallbackIfMatch,
|
||||
checkSystem: checkSystem,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -171,101 +152,94 @@ func (s *DNS) Close() error {
|
||||
// IsOwnLink implements proxy.dns.ownLinkVerifier
|
||||
func (s *DNS) IsOwnLink(ctx context.Context) bool {
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound == nil {
|
||||
return false
|
||||
}
|
||||
for _, client := range s.clients {
|
||||
if client.tag == inbound.Tag {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
return inbound != nil && inbound.Tag == s.tag
|
||||
}
|
||||
|
||||
// LookupIP implements dns.Client.
|
||||
func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||
// Normalize the FQDN form query
|
||||
domain = strings.TrimSuffix(domain, ".")
|
||||
func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, error) {
|
||||
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.IPv6Enable = option.IPv6Enable && s.ipOption.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
|
||||
switch addrs, err := s.hosts.Lookup(domain, option); {
|
||||
case err != nil:
|
||||
if go_errors.Is(err, dns.ErrEmptyResponse) {
|
||||
return nil, 0, dns.ErrEmptyResponse
|
||||
}
|
||||
return nil, 0, errors.New("returning nil for domain ", domain).Base(err)
|
||||
switch addrs := s.hosts.Lookup(domain, option); {
|
||||
case addrs == nil: // Domain not recorded in static host
|
||||
break
|
||||
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
|
||||
errors.LogInfo(s.ctx, "domain replaced: ", domain, " -> ", addrs[0].Domain())
|
||||
domain = addrs[0].Domain()
|
||||
default: // Successfully found ip records in static host
|
||||
errors.LogInfo(s.ctx, "returning ", len(addrs), " IP(s) for domain ", domain, " -> ", addrs)
|
||||
ips, err := toNetIP(addrs)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return ips, 10, nil // Hosts ttl is 10
|
||||
return toNetIP(addrs)
|
||||
}
|
||||
|
||||
// Name servers lookup
|
||||
var errs []error
|
||||
errs := []error{}
|
||||
ctx := session.ContextWithInbound(s.ctx, &session.Inbound{Tag: s.tag})
|
||||
for _, client := range s.sortClients(domain) {
|
||||
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
||||
errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
|
||||
continue
|
||||
}
|
||||
|
||||
ips, ttl, err := client.QueryIP(s.ctx, domain, option)
|
||||
|
||||
ips, err := client.QueryIP(ctx, domain, option, s.disableCache)
|
||||
if len(ips) > 0 {
|
||||
if ttl == 0 {
|
||||
ttl = 1
|
||||
return ips, nil
|
||||
}
|
||||
return ips, ttl, nil
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
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)
|
||||
|
||||
if client.IsFinalQuery() {
|
||||
break
|
||||
}
|
||||
// 5 for RcodeRefused in miekg/dns, hardcode to reduce binary size
|
||||
if err != context.Canceled && err != context.DeadlineExceeded && err != errExpectedIPNonMatch && err != dns.ErrEmptyResponse && dns.RCodeFromError(err) != 5 {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if len(errs) > 0 {
|
||||
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, errors.New("returning nil for domain ", domain).Base(errors.Combine(errs...))
|
||||
}
|
||||
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 {
|
||||
@@ -276,11 +250,7 @@ func (s *DNS) sortClients(domain string) []*Client {
|
||||
|
||||
// Priority domain matching
|
||||
hasMatch := false
|
||||
MatchSlice := s.domainMatcher.Match(domain)
|
||||
sort.Slice(MatchSlice, func(i, j int) bool {
|
||||
return MatchSlice[i] < MatchSlice[j]
|
||||
})
|
||||
for _, match := range MatchSlice {
|
||||
for _, match := range s.domainMatcher.Match(domain) {
|
||||
info := s.matcherInfos[match]
|
||||
client := s.clients[info.clientIdx]
|
||||
domainRule := client.domains[info.domainRuleIdx]
|
||||
@@ -327,22 +297,3 @@ func init() {
|
||||
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:
|
||||
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:
|
||||
rr, _ := dns.NewRR("hostname. IN A 127.0.0.1")
|
||||
ans.Answer = append(ans.Answer, rr)
|
||||
@@ -120,6 +117,7 @@ func TestUDPServerSubnet(t *testing.T) {
|
||||
Handler: &staticHandler{},
|
||||
UDPSize: 1200,
|
||||
}
|
||||
|
||||
go dnsServer.ListenAndServe()
|
||||
time.Sleep(time.Second)
|
||||
|
||||
@@ -157,7 +155,7 @@ func TestUDPServerSubnet(t *testing.T) {
|
||||
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -218,7 +216,7 @@ func TestUDPServer(t *testing.T) {
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -278,7 +276,7 @@ func TestUDPServer(t *testing.T) {
|
||||
dnsServer.Shutdown()
|
||||
|
||||
{
|
||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -359,7 +357,7 @@ func TestPrioritizedDomain(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
|
||||
{
|
||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -425,7 +423,7 @@ func TestUDPServerIPv6(t *testing.T) {
|
||||
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -494,7 +492,7 @@ func TestStaticHostDomain(t *testing.T) {
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -539,7 +537,7 @@ func TestIPMatch(t *testing.T) {
|
||||
},
|
||||
Port: uint32(port),
|
||||
},
|
||||
ExpectedGeoip: []*router.GeoIP{
|
||||
Geoip: []*router.GeoIP{
|
||||
{
|
||||
CountryCode: "local",
|
||||
Cidr: []*router.CIDR{
|
||||
@@ -563,7 +561,7 @@ func TestIPMatch(t *testing.T) {
|
||||
},
|
||||
Port: uint32(port),
|
||||
},
|
||||
ExpectedGeoip: []*router.GeoIP{
|
||||
Geoip: []*router.GeoIP{
|
||||
{
|
||||
CountryCode: "test",
|
||||
Cidr: []*router.CIDR{
|
||||
@@ -605,7 +603,7 @@ func TestIPMatch(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
|
||||
{
|
||||
ips, _, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -667,7 +665,7 @@ func TestLocalDomain(t *testing.T) {
|
||||
// Equivalent of dotless:localhost
|
||||
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
|
||||
},
|
||||
ExpectedGeoip: []*router.GeoIP{
|
||||
Geoip: []*router.GeoIP{
|
||||
{ // Will match localhost, localhost-a and localhost-b,
|
||||
CountryCode: "local",
|
||||
Cidr: []*router.CIDR{
|
||||
@@ -728,7 +726,7 @@ func TestLocalDomain(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
|
||||
{ // Will match dotless:
|
||||
ips, _, err := client.LookupIP("hostname", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("hostname", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -743,7 +741,7 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match domain:local
|
||||
ips, _, err := client.LookupIP("hostname.local", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("hostname.local", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -758,7 +756,7 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match static ip
|
||||
ips, _, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("hostnamestatic", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -773,7 +771,7 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match domain replacing
|
||||
ips, _, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("hostnamealias", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
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:
|
||||
ips, _, err := client.LookupIP("localhost", feature_dns.IPOption{
|
||||
{ // 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{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
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
|
||||
ips, _, err := client.LookupIP("localhost-a", feature_dns.IPOption{
|
||||
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
||||
ips, err := client.LookupIP("localhost-a", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
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
|
||||
ips, _, err := client.LookupIP("localhost-b", feature_dns.IPOption{
|
||||
{ // Will match dotless:localhost, and expectIPs: 127.0.0.2, 127.0.0.3
|
||||
ips, err := client.LookupIP("localhost-b", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -833,7 +831,7 @@ func TestLocalDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // Will match dotless:
|
||||
ips, _, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("Mijia Cloud", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -897,7 +895,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
Domain: "google.com",
|
||||
},
|
||||
},
|
||||
ExpectedGeoip: []*router.GeoIP{
|
||||
Geoip: []*router.GeoIP{
|
||||
{ // Will only match 8.8.8.8 and 8.8.4.4
|
||||
Cidr: []*router.CIDR{
|
||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
||||
@@ -922,7 +920,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
Domain: "google.com",
|
||||
},
|
||||
},
|
||||
ExpectedGeoip: []*router.GeoIP{
|
||||
Geoip: []*router.GeoIP{
|
||||
{ // Will match 8.8.8.8 and 8.8.8.7, etc
|
||||
Cidr: []*router.CIDR{
|
||||
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
|
||||
@@ -946,7 +944,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
Domain: "api.google.com",
|
||||
},
|
||||
},
|
||||
ExpectedGeoip: []*router.GeoIP{
|
||||
Geoip: []*router.GeoIP{
|
||||
{ // Will only match 8.8.7.7 (api.google.com)
|
||||
Cidr: []*router.CIDR{
|
||||
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
|
||||
@@ -970,7 +968,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
Domain: "v2.api.google.com",
|
||||
},
|
||||
},
|
||||
ExpectedGeoip: []*router.GeoIP{
|
||||
Geoip: []*router.GeoIP{
|
||||
{ // Will only match 8.8.7.8 (v2.api.google.com)
|
||||
Cidr: []*router.CIDR{
|
||||
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
|
||||
@@ -999,7 +997,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
startTime := time.Now()
|
||||
|
||||
{ // 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,
|
||||
IPv6Enable: true,
|
||||
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
|
||||
ips, _, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
||||
ips, err := client.LookupIP("ipv6.google.com", feature_dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
FakeEnable: false,
|
||||
@@ -1029,7 +1027,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // 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,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
@@ -1044,7 +1042,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
||||
}
|
||||
|
||||
{ // 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,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
|
@@ -32,30 +32,29 @@ type record struct {
|
||||
// IPRecord is a cacheable item for a resolved domain
|
||||
type IPRecord struct {
|
||||
ReqID uint16
|
||||
IP []net.IP
|
||||
IP []net.Address
|
||||
Expire time.Time
|
||||
RCode dnsmessage.RCode
|
||||
RawHeader *dnsmessage.Header
|
||||
}
|
||||
|
||||
func (r *IPRecord) getIPs() ([]net.IP, uint32, error) {
|
||||
if r == nil {
|
||||
return nil, 0, errRecordNotFound
|
||||
func (r *IPRecord) getIPs() ([]net.Address, error) {
|
||||
if r == nil || r.Expire.Before(time.Now()) {
|
||||
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 {
|
||||
return nil, ttl, dns_feature.RCodeError(r.RCode)
|
||||
return nil, dns_feature.RCodeError(r.RCode)
|
||||
}
|
||||
if len(r.IP) == 0 {
|
||||
return nil, ttl, dns_feature.ErrEmptyResponse
|
||||
return r.IP, nil
|
||||
}
|
||||
|
||||
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")
|
||||
@@ -68,20 +67,11 @@ type dnsRequest struct {
|
||||
msg *dnsmessage.Message
|
||||
}
|
||||
|
||||
func genEDNS0Options(clientIP net.IP, padding int) *dnsmessage.Resource {
|
||||
if len(clientIP) == 0 && padding == 0 {
|
||||
func genEDNS0Options(clientIP net.IP) *dnsmessage.Resource {
|
||||
if len(clientIP) == 0 {
|
||||
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 family uint16
|
||||
|
||||
@@ -108,19 +98,18 @@ func genEDNS0Options(clientIP net.IP, padding int) *dnsmessage.Resource {
|
||||
b = append(b, ip[:needLength]...)
|
||||
}
|
||||
|
||||
body.Options = append(body.Options,
|
||||
dnsmessage.Option{
|
||||
const EDNS0SUBNET = 0x08
|
||||
|
||||
opt := new(dnsmessage.Resource)
|
||||
common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
|
||||
|
||||
opt.Body = &dnsmessage.OPTResource{
|
||||
Options: []dnsmessage.Option{
|
||||
{
|
||||
Code: EDNS0SUBNET,
|
||||
Data: b,
|
||||
})
|
||||
}
|
||||
|
||||
if padding != 0 {
|
||||
body.Options = append(body.Options,
|
||||
dnsmessage.Option{
|
||||
Code: EDNS0PADDING,
|
||||
Data: make([]byte, padding),
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return opt
|
||||
@@ -192,8 +181,7 @@ func parseResponse(payload []byte) (*IPRecord, error) {
|
||||
ipRecord := &IPRecord{
|
||||
ReqID: h.ID,
|
||||
RCode: h.RCode,
|
||||
Expire: now.Add(time.Second * dns_feature.DefaultTTL),
|
||||
RawHeader: &h,
|
||||
Expire: now.Add(time.Second * 600),
|
||||
}
|
||||
|
||||
L:
|
||||
@@ -208,7 +196,7 @@ L:
|
||||
|
||||
ttl := ah.TTL
|
||||
if ttl == 0 {
|
||||
ttl = 1
|
||||
ttl = 600
|
||||
}
|
||||
expire := now.Add(time.Duration(ttl) * time.Second)
|
||||
if ipRecord.Expire.After(expire) {
|
||||
@@ -222,17 +210,14 @@ L:
|
||||
errors.LogInfoInner(context.Background(), err, "failed to parse A record for domain: ", ah.Name)
|
||||
break L
|
||||
}
|
||||
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:]).IP())
|
||||
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.A[:]))
|
||||
case dnsmessage.TypeAAAA:
|
||||
ans, err := parser.AAAAResource()
|
||||
if err != nil {
|
||||
errors.LogInfoInner(context.Background(), err, "failed to parse AAAA record for domain: ", ah.Name)
|
||||
break L
|
||||
}
|
||||
newIP := net.IPAddress(ans.AAAA[:]).IP()
|
||||
if len(newIP) == net.IPv6len {
|
||||
ipRecord.IP = append(ipRecord.IP, newIP)
|
||||
}
|
||||
ipRecord.IP = append(ipRecord.IP, net.IPAddress(ans.AAAA[:]))
|
||||
default:
|
||||
if err := parser.SkipAnswer(); err != nil {
|
||||
errors.LogInfoInner(context.Background(), err, "failed to skip answer")
|
||||
|
@@ -51,7 +51,7 @@ func Test_parseResponse(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
"empty",
|
||||
&IPRecord{0, []net.IP(nil), time.Time{}, dnsmessage.RCodeSuccess, nil},
|
||||
&IPRecord{0, []net.Address(nil), time.Time{}, dnsmessage.RCodeSuccess},
|
||||
false,
|
||||
},
|
||||
{
|
||||
@@ -63,16 +63,15 @@ func Test_parseResponse(t *testing.T) {
|
||||
"a record",
|
||||
&IPRecord{
|
||||
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{},
|
||||
dnsmessage.RCodeSuccess,
|
||||
nil,
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"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,
|
||||
},
|
||||
}
|
||||
@@ -85,9 +84,8 @@ func Test_parseResponse(t *testing.T) {
|
||||
}
|
||||
|
||||
if got != nil {
|
||||
// reset the time and RawHeader
|
||||
// reset the time
|
||||
got.Expire = time.Time{}
|
||||
got.RawHeader = nil
|
||||
}
|
||||
if 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 {
|
||||
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)
|
||||
}
|
||||
})
|
||||
|
@@ -2,7 +2,6 @@ package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
@@ -33,15 +32,7 @@ func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
|
||||
ips := make([]net.Address, 0, len(mapping.Ip)+1)
|
||||
switch {
|
||||
case len(mapping.ProxiedDomain) > 0:
|
||||
if mapping.ProxiedDomain[0] == '#' {
|
||||
rcode, err := strconv.Atoi(mapping.ProxiedDomain[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ips = append(ips, dns.RCodeError(rcode))
|
||||
} else {
|
||||
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
|
||||
}
|
||||
case len(mapping.Ip) > 0:
|
||||
for _, ip := range mapping.Ip {
|
||||
addr := net.IPAddress(ip)
|
||||
@@ -50,6 +41,8 @@ func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
|
||||
}
|
||||
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
|
||||
@@ -68,51 +61,33 @@ func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func (h *StaticHosts) lookupInternal(domain string) ([]net.Address, error) {
|
||||
ips := make([]net.Address, 0)
|
||||
found := false
|
||||
func (h *StaticHosts) lookupInternal(domain string) []net.Address {
|
||||
var ips []net.Address
|
||||
for _, id := range h.matchers.Match(domain) {
|
||||
for _, v := range h.ips[id] {
|
||||
if err, ok := v.(dns.RCodeError); ok {
|
||||
if uint16(err) == 0 {
|
||||
return nil, dns.ErrEmptyResponse
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
ips = append(ips, h.ips[id]...)
|
||||
found = true
|
||||
}
|
||||
if !found {
|
||||
return nil, nil
|
||||
}
|
||||
return ips, nil
|
||||
return ips
|
||||
}
|
||||
|
||||
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) ([]net.Address, error) {
|
||||
switch addrs, err := h.lookupInternal(domain); {
|
||||
case err != nil:
|
||||
return nil, err
|
||||
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address {
|
||||
switch addrs := h.lookupInternal(domain); {
|
||||
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
||||
return addrs, nil
|
||||
return nil
|
||||
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")
|
||||
if maxDepth > 0 {
|
||||
unwrapped, err := h.lookup(addrs[0].Domain(), option, maxDepth-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
unwrapped := h.lookup(addrs[0].Domain(), option, maxDepth-1)
|
||||
if unwrapped != nil {
|
||||
return unwrapped, nil
|
||||
return unwrapped
|
||||
}
|
||||
}
|
||||
return addrs, nil
|
||||
return addrs
|
||||
default: // IP record found, return a non-nil IP array
|
||||
return filterIP(addrs, option), nil
|
||||
return filterIP(addrs, option)
|
||||
}
|
||||
}
|
||||
|
||||
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
|
||||
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) ([]net.Address, error) {
|
||||
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) []net.Address {
|
||||
return h.lookup(domain, option, 5)
|
||||
}
|
||||
|
@@ -12,11 +12,6 @@ import (
|
||||
|
||||
func TestStaticHosts(t *testing.T) {
|
||||
pb := []*Config_HostMapping{
|
||||
{
|
||||
Type: DomainMatchingType_Subdomain,
|
||||
Domain: "lan",
|
||||
ProxiedDomain: "#3",
|
||||
},
|
||||
{
|
||||
Type: DomainMatchingType_Full,
|
||||
Domain: "example.com",
|
||||
@@ -59,14 +54,7 @@ func TestStaticHosts(t *testing.T) {
|
||||
common.Must(err)
|
||||
|
||||
{
|
||||
_, err := hosts.Lookup("example.com.lan", dns.IPOption{})
|
||||
if dns.RCodeFromError(err) != 3 {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ips, _ := hosts.Lookup("example.com", dns.IPOption{
|
||||
ips := hosts.Lookup("example.com", dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
@@ -79,7 +67,7 @@ func TestStaticHosts(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
domain, _ := hosts.Lookup("proxy.xray.com", dns.IPOption{
|
||||
domain := hosts.Lookup("proxy.xray.com", dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
})
|
||||
@@ -92,7 +80,7 @@ func TestStaticHosts(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
domain, _ := hosts.Lookup("proxy2.xray.com", dns.IPOption{
|
||||
domain := hosts.Lookup("proxy2.xray.com", dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: false,
|
||||
})
|
||||
@@ -105,7 +93,7 @@ func TestStaticHosts(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
ips, _ := hosts.Lookup("www.example.cn", dns.IPOption{
|
||||
ips := hosts.Lookup("www.example.cn", dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
@@ -118,7 +106,7 @@ func TestStaticHosts(t *testing.T) {
|
||||
}
|
||||
|
||||
{
|
||||
ips, _ := hosts.Lookup("baidu.com", dns.IPOption{
|
||||
ips := hosts.Lookup("baidu.com", dns.IPOption{
|
||||
IPv4Enable: false,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
|
@@ -9,7 +9,6 @@ import (
|
||||
"github.com/xtls/xray-core/app/router"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"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/core"
|
||||
"github.com/xtls/xray-core/features/dns"
|
||||
@@ -21,27 +20,22 @@ type Server interface {
|
||||
// Name of the Client.
|
||||
Name() string
|
||||
// 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.
|
||||
type Client struct {
|
||||
server Server
|
||||
clientIP net.IP
|
||||
skipFallback bool
|
||||
domains []string
|
||||
expectedIPs []*router.GeoIPMatcher
|
||||
unexpectedIPs []*router.GeoIPMatcher
|
||||
actPrior bool
|
||||
actUnprior bool
|
||||
tag string
|
||||
timeoutMs time.Duration
|
||||
finalQuery bool
|
||||
ipOption *dns.IPOption
|
||||
checkSystem bool
|
||||
expectIPs []*router.GeoIPMatcher
|
||||
}
|
||||
|
||||
var errExpectedIPNonMatch = errors.New("expectIPs not match")
|
||||
|
||||
// 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() {
|
||||
u, err := url.Parse(address.Domain())
|
||||
if err != nil {
|
||||
@@ -49,29 +43,26 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
||||
}
|
||||
switch {
|
||||
case strings.EqualFold(u.String(), "localhost"):
|
||||
return NewLocalNameServer(), nil
|
||||
return NewLocalNameServer(queryStrategy), nil
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
return NewQUICNameServer(u, disableCache, clientIP)
|
||||
return NewQUICNameServer(u, queryStrategy)
|
||||
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
|
||||
return NewTCPLocalNameServer(u, disableCache, clientIP)
|
||||
return NewTCPLocalNameServer(u, queryStrategy)
|
||||
case strings.EqualFold(u.String(), "fakedns"):
|
||||
var fd dns.FakeDNSEngine
|
||||
err = core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||
core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||
fd = fdns
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewFakeDNSServer(fd), nil
|
||||
}
|
||||
}
|
||||
@@ -79,7 +70,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
||||
dest.Network = net.Network_UDP
|
||||
}
|
||||
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()
|
||||
}
|
||||
@@ -89,9 +80,7 @@ func NewClient(
|
||||
ctx context.Context,
|
||||
ns *NameServer,
|
||||
clientIP net.IP,
|
||||
disableCache bool,
|
||||
tag string,
|
||||
ipOption dns.IPOption,
|
||||
container router.GeoIPMatcherContainer,
|
||||
matcherInfos *[]*DomainMatcherInfo,
|
||||
updateDomainRule func(strmatcher.Matcher, int, []*DomainMatcherInfo) error,
|
||||
) (*Client, error) {
|
||||
@@ -99,7 +88,7 @@ func NewClient(
|
||||
|
||||
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
||||
// 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 {
|
||||
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
||||
}
|
||||
@@ -154,23 +143,13 @@ func NewClient(
|
||||
}
|
||||
|
||||
// Establish expected IPs
|
||||
var expectedMatchers []*router.GeoIPMatcher
|
||||
for _, geoip := range ns.ExpectedGeoip {
|
||||
matcher, err := router.GlobalGeoIPContainer.Add(geoip)
|
||||
var matchers []*router.GeoIPMatcher
|
||||
for _, geoip := range ns.Geoip {
|
||||
matcher, err := container.Add(geoip)
|
||||
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)
|
||||
}
|
||||
|
||||
// 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)
|
||||
matchers = append(matchers, matcher)
|
||||
}
|
||||
|
||||
if len(clientIP) > 0 {
|
||||
@@ -178,29 +157,15 @@ func NewClient(
|
||||
case *net.IPOrDomain_Domain:
|
||||
errors.LogInfo(ctx, "DNS: client ", ns.Address.Address.GetDomain(), " uses clientIP ", clientIP.String())
|
||||
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.clientIP = clientIP
|
||||
client.skipFallback = ns.SkipFallback
|
||||
client.domains = rules
|
||||
client.expectedIPs = expectedMatchers
|
||||
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
|
||||
client.expectIPs = matchers
|
||||
return nil
|
||||
})
|
||||
return client, err
|
||||
@@ -211,79 +176,43 @@ func (c *Client) Name() string {
|
||||
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.
|
||||
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||
if c.checkSystem {
|
||||
supportIPv4, supportIPv6 := checkSystemNetwork()
|
||||
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)
|
||||
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption, disableCache bool) ([]net.IP, error) {
|
||||
ctx, cancel := context.WithTimeout(ctx, 4*time.Second)
|
||||
ips, err := c.server.QueryIP(ctx, domain, c.clientIP, option, disableCache)
|
||||
cancel()
|
||||
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return ips, err
|
||||
}
|
||||
return c.MatchExpectedIPs(domain, ips)
|
||||
}
|
||||
|
||||
if len(ips) == 0 {
|
||||
return nil, 0, dns.ErrEmptyResponse
|
||||
// MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones.
|
||||
func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) ([]net.IP, error) {
|
||||
if len(c.expectIPs) == 0 {
|
||||
return ips, nil
|
||||
}
|
||||
|
||||
if len(c.expectedIPs) > 0 && !c.actPrior {
|
||||
ips = router.MatchIPs(c.expectedIPs, ips, false)
|
||||
errors.LogDebug(context.Background(), "domain ", domain, " expectedIPs ", ips, " matched at server ", c.Name())
|
||||
if len(ips) == 0 {
|
||||
return nil, 0, dns.ErrEmptyResponse
|
||||
newIps := []net.IP{}
|
||||
for _, ip := range ips {
|
||||
for _, matcher := range c.expectIPs {
|
||||
if matcher.Match(ip) {
|
||||
newIps = append(newIps, ip)
|
||||
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
|
||||
}
|
||||
|
||||
if len(c.expectedIPs) > 0 && c.actPrior {
|
||||
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
|
||||
errors.LogDebug(context.Background(), "domain ", domain, " expectIPs ", newIps, " matched at server ", c.Name())
|
||||
return newIps, nil
|
||||
}
|
||||
|
||||
func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) dns.IPOption {
|
||||
switch queryStrategy {
|
||||
case QueryStrategy_USE_IP:
|
||||
return ipOption
|
||||
case QueryStrategy_USE_SYS:
|
||||
return ipOption
|
||||
case QueryStrategy_USE_IP4:
|
||||
return dns.IPOption{
|
||||
IPv4Enable: ipOption.IPv4Enable,
|
||||
|
@@ -4,12 +4,12 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
go_errors "errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
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/protocol/dns"
|
||||
"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"
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
@@ -31,14 +34,18 @@ import (
|
||||
// which is compatible with traditional dns over udp(RFC1035),
|
||||
// thus most of the DOH implementation is copied from udpns.go
|
||||
type DoHNameServer struct {
|
||||
cacheController *CacheController
|
||||
sync.RWMutex
|
||||
ips map[string]*record
|
||||
pub *pubsub.Service
|
||||
cleanup *task.Periodic
|
||||
httpClient *http.Client
|
||||
dohURL string
|
||||
clientIP net.IP
|
||||
name string
|
||||
queryStrategy QueryStrategy
|
||||
}
|
||||
|
||||
// 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"
|
||||
mode := "DOH"
|
||||
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)
|
||||
s := &DoHNameServer{
|
||||
cacheController: NewCacheController(mode+"//"+url.Host, disableCache),
|
||||
ips: make(map[string]*record),
|
||||
pub: pubsub.NewService(),
|
||||
name: mode + "//" + url.Host,
|
||||
dohURL: url.String(),
|
||||
clientIP: clientIP,
|
||||
queryStrategy: queryStrategy,
|
||||
}
|
||||
s.cleanup = &task.Periodic{
|
||||
Interval: time.Minute,
|
||||
Execute: s.Cleanup,
|
||||
}
|
||||
s.httpClient = &http.Client{
|
||||
Transport: &http2.Transport{
|
||||
@@ -114,25 +127,99 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, dis
|
||||
|
||||
// Name implements Server.
|
||||
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 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
||||
errors.LogInfo(ctx, s.Name(), " querying: ", domain)
|
||||
func (s *DoHNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||
errors.LogInfo(ctx, s.name, " querying: ", domain)
|
||||
|
||||
if s.Name()+"." == "DOH//"+domain {
|
||||
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead.")
|
||||
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
|
||||
if s.name+"." == "DOH//"+domain {
|
||||
errors.LogError(ctx, s.name, " tries to resolve itself! Use IP or set \"hosts\" instead.")
|
||||
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
|
||||
// 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))))
|
||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||
|
||||
var deadline time.Time
|
||||
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)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain)
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain)
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
rec, err := parseResponse(resp)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain)
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
s.cacheController.updateIP(r, rec)
|
||||
s.updateIP(r, rec)
|
||||
}(req)
|
||||
}
|
||||
}
|
||||
@@ -215,50 +299,107 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
|
||||
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.
|
||||
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)
|
||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
||||
defer closeSubscribers(sub4, sub6)
|
||||
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||
if !option.IPv4Enable && !option.IPv6Enable {
|
||||
return nil, dns_feature.ErrEmptyResponse
|
||||
}
|
||||
|
||||
if s.cacheController.disableCache {
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
||||
if disableCache {
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||
} else {
|
||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||
if !go_errors.Is(err, errRecordNotFound) {
|
||||
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})
|
||||
return ips, ttl, err
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||
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})
|
||||
return ips, err
|
||||
}
|
||||
}
|
||||
|
||||
noResponseErrCh := make(chan error, 2)
|
||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
||||
start := time.Now()
|
||||
|
||||
// ipv4 and ipv6 belong to different subscription groups
|
||||
var sub4, sub6 *pubsub.Subscriber
|
||||
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 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, 0, ctx.Err()
|
||||
case err := <-noResponseErrCh:
|
||||
return nil, 0, err
|
||||
case <-sub4.Wait():
|
||||
sub4.Close()
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}
|
||||
if sub6 != nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, 0, ctx.Err()
|
||||
case err := <-noResponseErrCh:
|
||||
return nil, 0, err
|
||||
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)
|
||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||
return ips, ttl, err
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
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")
|
||||
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)
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
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")
|
||||
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)
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if len(ips) == 0 {
|
||||
@@ -47,10 +47,10 @@ func TestDOHNameServerWithCache(t *testing.T) {
|
||||
}
|
||||
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, true)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
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")
|
||||
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)
|
||||
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,
|
||||
IPv6Enable: false,
|
||||
})
|
||||
IPv6Enable: true,
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
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")
|
||||
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)
|
||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||
IPv4Enable: false,
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if len(ips) == 0 {
|
||||
|
@@ -20,9 +20,9 @@ func (FakeDNSServer) Name() string {
|
||||
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 {
|
||||
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
|
||||
@@ -34,13 +34,13 @@ func (f *FakeDNSServer) QueryIP(ctx context.Context, domain string, opt dns.IPOp
|
||||
|
||||
netIP, err := toNetIP(ips)
|
||||
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)
|
||||
|
||||
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 (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
@@ -14,13 +15,24 @@ import (
|
||||
// LocalNameServer is an wrapper over local DNS feature.
|
||||
type LocalNameServer struct {
|
||||
client *localdns.Client
|
||||
queryStrategy QueryStrategy
|
||||
}
|
||||
|
||||
const errEmptyResponse = "No address associated with hostname"
|
||||
|
||||
// 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()
|
||||
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 {
|
||||
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.
|
||||
func NewLocalNameServer() *LocalNameServer {
|
||||
func NewLocalNameServer(queryStrategy QueryStrategy) *LocalNameServer {
|
||||
errors.LogInfo(context.Background(), "DNS: created localhost client")
|
||||
return &LocalNameServer{
|
||||
queryStrategy: queryStrategy,
|
||||
client: localdns.New(),
|
||||
}
|
||||
}
|
||||
|
||||
// NewLocalDNSClient creates localdns client object for directly lookup in system DNS.
|
||||
func NewLocalDNSClient(ipOption dns.IPOption) *Client {
|
||||
return &Client{server: NewLocalNameServer(), ipOption: &ipOption}
|
||||
func NewLocalDNSClient() *Client {
|
||||
return &Client{server: NewLocalNameServer(QueryStrategy_USE_IP)}
|
||||
}
|
||||
|
@@ -7,17 +7,18 @@ import (
|
||||
|
||||
. "github.com/xtls/xray-core/app/dns"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/features/dns"
|
||||
)
|
||||
|
||||
func TestLocalNameServer(t *testing.T) {
|
||||
s := NewLocalNameServer()
|
||||
s := NewLocalNameServer(QueryStrategy_USE_IP)
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if len(ips) == 0 {
|
||||
|
@@ -4,20 +4,23 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
go_errors "errors"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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/errors"
|
||||
"github.com/xtls/xray-core/common/log"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol/dns"
|
||||
"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"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
@@ -30,14 +33,17 @@ const handshakeTimeout = time.Second * 8
|
||||
// QUICNameServer implemented DNS over QUIC
|
||||
type QUICNameServer struct {
|
||||
sync.RWMutex
|
||||
cacheController *CacheController
|
||||
ips map[string]*record
|
||||
pub *pubsub.Service
|
||||
cleanup *task.Periodic
|
||||
name string
|
||||
destination *net.Destination
|
||||
connection *quic.Conn
|
||||
clientIP net.IP
|
||||
connection quic.Connection
|
||||
queryStrategy QueryStrategy
|
||||
}
|
||||
|
||||
// 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())
|
||||
|
||||
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)
|
||||
|
||||
s := &QUICNameServer{
|
||||
cacheController: NewCacheController(url.String(), disableCache),
|
||||
ips: make(map[string]*record),
|
||||
pub: pubsub.NewService(),
|
||||
name: url.String(),
|
||||
destination: &dest,
|
||||
clientIP: clientIP,
|
||||
queryStrategy: queryStrategy,
|
||||
}
|
||||
s.cleanup = &task.Periodic{
|
||||
Interval: time.Minute,
|
||||
Execute: s.Cleanup,
|
||||
}
|
||||
|
||||
return s, nil
|
||||
@@ -61,17 +73,94 @@ func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICN
|
||||
|
||||
// Name returns client name
|
||||
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 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
||||
errors.LogInfo(ctx, s.Name(), " querying: ", domain)
|
||||
func (s *QUICNameServer) sendQuery(ctx context.Context, domain string, clientIP net.IP, option dns_feature.IPOption) {
|
||||
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
|
||||
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)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
dnsReqBuf := buf.New()
|
||||
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||
dnsReqBuf.Write(b.Bytes())
|
||||
b.Release()
|
||||
|
||||
conn, err := s.openStream(dnsCtx)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to open quic connection")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to send query")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
@@ -143,84 +219,137 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||
if err != nil && n == 0 {
|
||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
var length int16
|
||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
respBuf.Clear()
|
||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||
if err != nil && n == 0 {
|
||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := parseResponse(respBuf.Bytes())
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to handle response")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
s.cacheController.updateIP(r, rec)
|
||||
s.updateIP(r, rec)
|
||||
}(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
|
||||
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)
|
||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
||||
defer closeSubscribers(sub4, sub6)
|
||||
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||
if !option.IPv4Enable && !option.IPv6Enable {
|
||||
return nil, dns_feature.ErrEmptyResponse
|
||||
}
|
||||
|
||||
if s.cacheController.disableCache {
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
||||
if disableCache {
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||
} else {
|
||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||
if !go_errors.Is(err, errRecordNotFound) {
|
||||
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})
|
||||
return ips, ttl, err
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||
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})
|
||||
return ips, err
|
||||
}
|
||||
}
|
||||
|
||||
noResponseErrCh := make(chan error, 2)
|
||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
||||
start := time.Now()
|
||||
|
||||
// ipv4 and ipv6 belong to different subscription groups
|
||||
var sub4, sub6 *pubsub.Subscriber
|
||||
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 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, 0, ctx.Err()
|
||||
case err := <-noResponseErrCh:
|
||||
return nil, 0, err
|
||||
case <-sub4.Wait():
|
||||
sub4.Close()
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}
|
||||
if sub6 != nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, 0, ctx.Err()
|
||||
case err := <-noResponseErrCh:
|
||||
return nil, 0, err
|
||||
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
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case <-done:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||
return ips, ttl, err
|
||||
|
||||
}
|
||||
|
||||
func isActive(s *quic.Conn) bool {
|
||||
func isActive(s quic.Connection) bool {
|
||||
select {
|
||||
case <-s.Context().Done():
|
||||
return false
|
||||
@@ -229,8 +358,8 @@ func isActive(s *quic.Conn) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *QUICNameServer) getConnection() (*quic.Conn, error) {
|
||||
var conn *quic.Conn
|
||||
func (s *QUICNameServer) getConnection() (quic.Connection, error) {
|
||||
var conn quic.Connection
|
||||
s.RLock()
|
||||
conn = s.connection
|
||||
if conn != nil && isActive(conn) {
|
||||
@@ -263,7 +392,7 @@ func (s *QUICNameServer) getConnection() (*quic.Conn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (s *QUICNameServer) openConnection() (*quic.Conn, error) {
|
||||
func (s *QUICNameServer) openConnection() (quic.Connection, error) {
|
||||
tlsConfig := tls.Config{}
|
||||
quicConfig := &quic.Config{
|
||||
HandshakeIdleTimeout: handshakeTimeout,
|
||||
@@ -283,7 +412,7 @@ func (s *QUICNameServer) openConnection() (*quic.Conn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (s *QUICNameServer) openStream(ctx context.Context) (*quic.Stream, error) {
|
||||
func (s *QUICNameServer) openStream(ctx context.Context) (quic.Stream, error) {
|
||||
conn, err := s.getConnection()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@@ -16,23 +16,24 @@ import (
|
||||
func TestQUICNameServer(t *testing.T) {
|
||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||
common.Must(err)
|
||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
||||
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP)
|
||||
common.Must(err)
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if len(ips) == 0 {
|
||||
t.Error("expect some ips, but got 0")
|
||||
}
|
||||
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, true)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if r := cmp.Diff(ips2, ips); r != "" {
|
||||
@@ -43,13 +44,13 @@ func TestQUICNameServer(t *testing.T) {
|
||||
func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||
common.Must(err)
|
||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
||||
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP4)
|
||||
common.Must(err)
|
||||
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,
|
||||
IPv6Enable: false,
|
||||
})
|
||||
IPv6Enable: true,
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if len(ips) == 0 {
|
||||
@@ -66,13 +67,13 @@ func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
||||
func TestQUICNameServerWithIPv6Override(t *testing.T) {
|
||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||
common.Must(err)
|
||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
||||
s, err := NewQUICNameServer(url, QueryStrategy_USE_IP6)
|
||||
common.Must(err)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
||||
IPv4Enable: false,
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if len(ips) == 0 {
|
||||
|
@@ -4,11 +4,12 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
go_errors "errors"
|
||||
"net/url"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"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/protocol/dns"
|
||||
"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"
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"golang.org/x/net/dns/dnsmessage"
|
||||
)
|
||||
|
||||
// TCPNameServer implemented DNS over TCP (RFC7766).
|
||||
type TCPNameServer struct {
|
||||
cacheController *CacheController
|
||||
sync.RWMutex
|
||||
name string
|
||||
destination *net.Destination
|
||||
ips map[string]*record
|
||||
pub *pubsub.Service
|
||||
cleanup *task.Periodic
|
||||
reqID uint32
|
||||
dial func(context.Context) (net.Conn, error)
|
||||
clientIP net.IP
|
||||
queryStrategy QueryStrategy
|
||||
}
|
||||
|
||||
// NewTCPNameServer creates DNS over TCP server object for remote resolving.
|
||||
func NewTCPNameServer(
|
||||
url *url.URL,
|
||||
dispatcher routing.Dispatcher,
|
||||
disableCache bool,
|
||||
clientIP net.IP,
|
||||
queryStrategy QueryStrategy,
|
||||
) (*TCPNameServer, error) {
|
||||
s, err := baseTCPNameServer(url, "TCP", disableCache, clientIP)
|
||||
s, err := baseTCPNameServer(url, "TCP", queryStrategy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -58,8 +65,8 @@ func NewTCPNameServer(
|
||||
}
|
||||
|
||||
// NewTCPLocalNameServer creates DNS over TCP client object for local resolving
|
||||
func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
|
||||
s, err := baseTCPNameServer(url, "TCPL", disableCache, clientIP)
|
||||
func NewTCPLocalNameServer(url *url.URL, queryStrategy QueryStrategy) (*TCPNameServer, error) {
|
||||
s, err := baseTCPNameServer(url, "TCPL", queryStrategy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -71,7 +78,7 @@ func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*T
|
||||
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)
|
||||
if url.Port() != "" {
|
||||
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)
|
||||
|
||||
s := &TCPNameServer{
|
||||
cacheController: NewCacheController(prefix+"//"+dest.NetAddr(), disableCache),
|
||||
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
|
||||
@@ -92,17 +105,94 @@ func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP
|
||||
|
||||
// Name implements Server.
|
||||
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 {
|
||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||
}
|
||||
|
||||
func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
||||
errors.LogDebug(ctx, s.Name(), " querying DNS for: ", domain)
|
||||
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)
|
||||
|
||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||
|
||||
var deadline time.Time
|
||||
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)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
conn, err := s.dial(dnsCtx)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to dial namesever")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
dnsReqBuf := buf.New()
|
||||
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||
dnsReqBuf.Write(b.Bytes())
|
||||
b.Release()
|
||||
|
||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to send query")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
dnsReqBuf.Release()
|
||||
@@ -170,80 +247,129 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||
if err != nil && n == 0 {
|
||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
var length int16
|
||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
respBuf.Clear()
|
||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||
if err != nil && n == 0 {
|
||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
rec, err := parseResponse(respBuf.Bytes())
|
||||
if err != nil {
|
||||
errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
|
||||
noResponseErrCh <- err
|
||||
return
|
||||
}
|
||||
|
||||
s.cacheController.updateIP(r, rec)
|
||||
s.updateIP(r, rec)
|
||||
}(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.
|
||||
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)
|
||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
||||
defer closeSubscribers(sub4, sub6)
|
||||
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||
if !option.IPv4Enable && !option.IPv6Enable {
|
||||
return nil, dns_feature.ErrEmptyResponse
|
||||
}
|
||||
|
||||
if s.cacheController.disableCache {
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
||||
if disableCache {
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||
} else {
|
||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||
if !go_errors.Is(err, errRecordNotFound) {
|
||||
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})
|
||||
return ips, ttl, err
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||
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})
|
||||
return ips, err
|
||||
}
|
||||
}
|
||||
|
||||
noResponseErrCh := make(chan error, 2)
|
||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
||||
start := time.Now()
|
||||
|
||||
// ipv4 and ipv6 belong to different subscription groups
|
||||
var sub4, sub6 *pubsub.Subscriber
|
||||
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 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, 0, ctx.Err()
|
||||
case err := <-noResponseErrCh:
|
||||
return nil, 0, err
|
||||
case <-sub4.Wait():
|
||||
sub4.Close()
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}
|
||||
if sub6 != nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, 0, ctx.Err()
|
||||
case err := <-noResponseErrCh:
|
||||
return nil, 0, err
|
||||
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)
|
||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||
return ips, ttl, err
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case <-done:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,13 +16,13 @@ import (
|
||||
func TestTCPLocalNameServer(t *testing.T) {
|
||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||
common.Must(err)
|
||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
||||
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP)
|
||||
common.Must(err)
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if len(ips) == 0 {
|
||||
@@ -33,13 +33,13 @@ func TestTCPLocalNameServer(t *testing.T) {
|
||||
func TestTCPLocalNameServerWithCache(t *testing.T) {
|
||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||
common.Must(err)
|
||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
||||
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP)
|
||||
common.Must(err)
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if len(ips) == 0 {
|
||||
@@ -47,10 +47,10 @@ func TestTCPLocalNameServerWithCache(t *testing.T) {
|
||||
}
|
||||
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, true)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
if r := cmp.Diff(ips2, ips); r != "" {
|
||||
@@ -61,13 +61,13 @@ func TestTCPLocalNameServerWithCache(t *testing.T) {
|
||||
func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||
common.Must(err)
|
||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
||||
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP4)
|
||||
common.Must(err)
|
||||
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,
|
||||
IPv6Enable: false,
|
||||
})
|
||||
IPv6Enable: true,
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
|
||||
@@ -85,13 +85,13 @@ func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
||||
func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {
|
||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||
common.Must(err)
|
||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
||||
s, err := NewTCPLocalNameServer(url, QueryStrategy_USE_IP6)
|
||||
common.Must(err)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||
IPv4Enable: false,
|
||||
ips, err := s.QueryIP(ctx, "google.com", net.IP(nil), dns_feature.IPOption{
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
})
|
||||
}, false)
|
||||
cancel()
|
||||
common.Must(err)
|
||||
|
||||
|
@@ -2,7 +2,6 @@ package dns
|
||||
|
||||
import (
|
||||
"context"
|
||||
go_errors "errors"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -14,6 +13,7 @@ import (
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/protocol/dns"
|
||||
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"
|
||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||
"github.com/xtls/xray-core/features/routing"
|
||||
@@ -24,36 +24,35 @@ import (
|
||||
// ClassicNameServer implemented traditional UDP DNS.
|
||||
type ClassicNameServer struct {
|
||||
sync.RWMutex
|
||||
cacheController *CacheController
|
||||
name string
|
||||
address *net.Destination
|
||||
requests map[uint16]*udpDnsRequest
|
||||
ips map[string]*record
|
||||
requests map[uint16]*dnsRequest
|
||||
pub *pubsub.Service
|
||||
udpServer *udp.Dispatcher
|
||||
requestsCleanup *task.Periodic
|
||||
cleanup *task.Periodic
|
||||
reqID uint32
|
||||
clientIP net.IP
|
||||
}
|
||||
|
||||
type udpDnsRequest struct {
|
||||
dnsRequest
|
||||
ctx context.Context
|
||||
queryStrategy QueryStrategy
|
||||
}
|
||||
|
||||
// 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
|
||||
if address.Port == 0 {
|
||||
address.Port = net.Port(53)
|
||||
}
|
||||
|
||||
s := &ClassicNameServer{
|
||||
cacheController: NewCacheController(strings.ToUpper(address.String()), disableCache),
|
||||
address: &address,
|
||||
requests: make(map[uint16]*udpDnsRequest),
|
||||
clientIP: clientIP,
|
||||
ips: make(map[string]*record),
|
||||
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,
|
||||
Execute: s.RequestsCleanup,
|
||||
Execute: s.Cleanup,
|
||||
}
|
||||
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
|
||||
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.
|
||||
func (s *ClassicNameServer) Name() string {
|
||||
return s.cacheController.name
|
||||
return s.name
|
||||
}
|
||||
|
||||
// RequestsCleanup clears expired items from cache
|
||||
func (s *ClassicNameServer) RequestsCleanup() error {
|
||||
// Cleanup clears expired items from cache
|
||||
func (s *ClassicNameServer) Cleanup() error {
|
||||
now := time.Now()
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
if len(s.requests) == 0 {
|
||||
return errors.New(s.Name(), " nothing to do. stopping...")
|
||||
if len(s.ips) == 0 && len(s.requests) == 0 {
|
||||
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 {
|
||||
@@ -82,7 +101,7 @@ func (s *ClassicNameServer) RequestsCleanup() error {
|
||||
}
|
||||
|
||||
if len(s.requests) == 0 {
|
||||
s.requests = make(map[uint16]*udpDnsRequest)
|
||||
s.requests = make(map[uint16]*dnsRequest)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -92,7 +111,7 @@ func (s *ClassicNameServer) RequestsCleanup() error {
|
||||
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
|
||||
ipRec, err := parseResponse(packet.Payload.Bytes())
|
||||
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
|
||||
}
|
||||
|
||||
@@ -105,107 +124,179 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
|
||||
}
|
||||
s.Unlock()
|
||||
if !ok {
|
||||
errors.LogError(ctx, s.Name(), " cannot find the pending request")
|
||||
errors.LogError(ctx, s.name, " cannot find the pending request")
|
||||
return
|
||||
}
|
||||
|
||||
// if truncated, retry with EDNS0 option(udp payload size: 1350)
|
||||
if ipRec.RawHeader.Truncated {
|
||||
// if already has EDNS0 option, no need to retry
|
||||
if len(req.msg.Additionals) == 0 {
|
||||
// copy necessary meta data from original request
|
||||
// and add EDNS0 option
|
||||
opt := new(dnsmessage.Resource)
|
||||
common.Must(opt.Header.SetEDNS0(1350, 0xfe00, true))
|
||||
opt.Body = &dnsmessage.OPTResource{}
|
||||
newMsg := *req.msg
|
||||
newReq := *req
|
||||
newMsg.Additionals = append(newMsg.Additionals, *opt)
|
||||
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
|
||||
var rec record
|
||||
switch req.reqType {
|
||||
case dnsmessage.TypeA:
|
||||
rec.A = ipRec
|
||||
case dnsmessage.TypeAAAA:
|
||||
rec.AAAA = ipRec
|
||||
}
|
||||
|
||||
elapsed := time.Since(req.start)
|
||||
errors.LogInfo(ctx, s.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
|
||||
if len(req.domain) > 0 && (rec.A != nil || rec.AAAA != nil) {
|
||||
s.updateIP(req.domain, &rec)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||
}
|
||||
|
||||
func (s *ClassicNameServer) addPendingRequest(req *udpDnsRequest) {
|
||||
func (s *ClassicNameServer) addPendingRequest(req *dnsRequest) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
|
||||
id := req.msg.ID
|
||||
req.expire = time.Now().Add(time.Second * 8)
|
||||
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) {
|
||||
errors.LogDebug(ctx, s.Name(), " querying DNS for: ", domain)
|
||||
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)
|
||||
|
||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(clientIP))
|
||||
|
||||
for _, req := range reqs {
|
||||
udpReq := &udpDnsRequest{
|
||||
dnsRequest: *req,
|
||||
ctx: ctx,
|
||||
}
|
||||
s.addPendingRequest(udpReq)
|
||||
s.addPendingRequest(req)
|
||||
b, _ := dns.PackMessage(req.msg)
|
||||
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.
|
||||
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)
|
||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
||||
defer closeSubscribers(sub4, sub6)
|
||||
option = ResolveIpOptionOverride(s.queryStrategy, option)
|
||||
if !option.IPv4Enable && !option.IPv6Enable {
|
||||
return nil, dns_feature.ErrEmptyResponse
|
||||
}
|
||||
|
||||
if s.cacheController.disableCache {
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.Name())
|
||||
if disableCache {
|
||||
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", domain, " at ", s.name)
|
||||
} else {
|
||||
ips, ttl, err := s.cacheController.findIPsForDomain(fqdn, option)
|
||||
if !go_errors.Is(err, errRecordNotFound) {
|
||||
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})
|
||||
return ips, ttl, err
|
||||
ips, err := s.findIPsForDomain(fqdn, option)
|
||||
if err == nil || err == dns_feature.ErrEmptyResponse {
|
||||
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})
|
||||
return ips, err
|
||||
}
|
||||
}
|
||||
|
||||
noResponseErrCh := make(chan error, 2)
|
||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
||||
start := time.Now()
|
||||
|
||||
// ipv4 and ipv6 belong to different subscription groups
|
||||
var sub4, sub6 *pubsub.Subscriber
|
||||
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 {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, 0, ctx.Err()
|
||||
case err := <-noResponseErrCh:
|
||||
return nil, 0, err
|
||||
case <-sub4.Wait():
|
||||
sub4.Close()
|
||||
case <-ctx.Done():
|
||||
}
|
||||
}
|
||||
if sub6 != nil {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, 0, ctx.Err()
|
||||
case err := <-noResponseErrCh:
|
||||
return nil, 0, err
|
||||
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)
|
||||
log.Record(&log.DNSLog{Server: s.Name(), Domain: domain, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||
return ips, ttl, err
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
case <-done:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"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/transport"
|
||||
)
|
||||
@@ -109,13 +108,3 @@ func (co *Outbound) Close() error {
|
||||
co.closed = true
|
||||
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"`
|
||||
// ping timeout, int64 values of time.Duration
|
||||
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() {
|
||||
@@ -159,13 +157,6 @@ func (x *HealthPingConfig) GetTimeout() int64 {
|
||||
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_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,
|
||||
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,
|
||||
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,
|
||||
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,
|
||||
@@ -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,
|
||||
0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74,
|
||||
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x4d, 0x65,
|
||||
0x74, 0x68, 0x6f, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x74, 0x74, 0x70,
|
||||
0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
||||
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
|
||||
0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
|
||||
|
@@ -26,7 +26,4 @@ message HealthPingConfig {
|
||||
int32 samplingCount = 4;
|
||||
// ping timeout, int64 values of time.Duration
|
||||
int64 timeout = 5;
|
||||
// http method to make request
|
||||
string httpMethod = 6;
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,6 @@ type HealthPingSettings struct {
|
||||
Interval time.Duration `json:"interval"`
|
||||
SamplingCount int `json:"sampling"`
|
||||
Timeout time.Duration `json:"timeout"`
|
||||
HttpMethod string `json:"httpMethod"`
|
||||
}
|
||||
|
||||
// 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 {
|
||||
settings := &HealthPingSettings{}
|
||||
if config != nil {
|
||||
|
||||
var httpMethod string
|
||||
if config.HttpMethod == "" {
|
||||
httpMethod = "HEAD"
|
||||
} else {
|
||||
httpMethod = strings.TrimSpace(config.HttpMethod)
|
||||
}
|
||||
|
||||
settings = &HealthPingSettings{
|
||||
Connectivity: strings.TrimSpace(config.Connectivity),
|
||||
Destination: strings.TrimSpace(config.Destination),
|
||||
Interval: time.Duration(config.Interval),
|
||||
SamplingCount: int(config.SamplingCount),
|
||||
Timeout: time.Duration(config.Timeout),
|
||||
HttpMethod: httpMethod,
|
||||
}
|
||||
}
|
||||
if settings.Destination == "" {
|
||||
@@ -174,7 +164,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
|
||||
}
|
||||
time.AfterFunc(delay, func() {
|
||||
errors.LogDebug(h.ctx, "checking ", handler)
|
||||
delay, err := client.MeasureDelay(h.Settings.HttpMethod)
|
||||
delay, err := client.MeasureDelay()
|
||||
if err == nil {
|
||||
ch <- &rtt{
|
||||
handler: handler,
|
||||
@@ -261,7 +251,7 @@ func (h *HealthPing) checkConnectivity() bool {
|
||||
h.Settings.Connectivity,
|
||||
h.Settings.Timeout,
|
||||
)
|
||||
if _, err := tester.MeasureDelay(h.Settings.HttpMethod); err != nil {
|
||||
if _, err := tester.MeasureDelay(); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
@@ -2,7 +2,6 @@ package burst
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@@ -52,28 +51,20 @@ func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, handler
|
||||
}
|
||||
|
||||
// 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 {
|
||||
panic("pingClient not initialized")
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(httpMethod, s.destination, nil)
|
||||
req, err := http.NewRequest(http.MethodHead, s.destination, nil)
|
||||
if err != nil {
|
||||
return rttFailed, err
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
resp, err := s.httpClient.Do(req)
|
||||
if err != nil {
|
||||
return rttFailed, err
|
||||
}
|
||||
if httpMethod == http.MethodGet {
|
||||
_, err = io.Copy(io.Discard, resp.Body)
|
||||
if err != nil {
|
||||
return rttFailed, err
|
||||
}
|
||||
}
|
||||
// don't wait for body
|
||||
resp.Body.Close()
|
||||
|
||||
return time.Since(start), nil
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@ package command
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/xtls/xray-core/app/commander"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
@@ -100,28 +99,6 @@ func (s *handlerServer) AlterInbound(ctx context.Context, request *AlterInboundR
|
||||
return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler)
|
||||
}
|
||||
|
||||
func (s *handlerServer) ListInbounds(ctx context.Context, request *ListInboundsRequest) (*ListInboundsResponse, error) {
|
||||
handlers := s.ihm.ListHandlers(ctx)
|
||||
response := &ListInboundsResponse{}
|
||||
if request.GetIsOnlyTags() {
|
||||
for _, handler := range handlers {
|
||||
response.Inbounds = append(response.Inbounds, &core.InboundHandlerConfig{
|
||||
Tag: handler.Tag(),
|
||||
})
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
handler, err := s.ihm.GetHandler(ctx, request.Tag)
|
||||
if err != nil {
|
||||
@@ -187,23 +164,6 @@ func (s *handlerServer) AlterOutbound(ctx context.Context, request *AlterOutboun
|
||||
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() {}
|
||||
|
||||
type service struct {
|
||||
|
@@ -364,96 +364,6 @@ func (*AlterInboundResponse) Descriptor() ([]byte, []int) {
|
||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
type ListInboundsRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
IsOnlyTags bool `protobuf:"varint,1,opt,name=isOnlyTags,proto3" json:"isOnlyTags,omitempty"`
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
func (x *ListInboundsRequest) GetIsOnlyTags() bool {
|
||||
if x != nil {
|
||||
return x.IsOnlyTags
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
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 {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -465,7 +375,7 @@ type GetInboundUserRequest struct {
|
||||
|
||||
func (x *GetInboundUserRequest) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -477,7 +387,7 @@ func (x *GetInboundUserRequest) String() string {
|
||||
func (*GetInboundUserRequest) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -490,7 +400,7 @@ func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use GetInboundUserRequest.ProtoReflect.Descriptor instead.
|
||||
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 {
|
||||
@@ -517,7 +427,7 @@ type GetInboundUserResponse struct {
|
||||
|
||||
func (x *GetInboundUserResponse) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -529,7 +439,7 @@ func (x *GetInboundUserResponse) String() string {
|
||||
func (*GetInboundUserResponse) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -542,7 +452,7 @@ func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use GetInboundUserResponse.ProtoReflect.Descriptor instead.
|
||||
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 {
|
||||
@@ -562,7 +472,7 @@ type GetInboundUsersCountResponse struct {
|
||||
|
||||
func (x *GetInboundUsersCountResponse) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -574,7 +484,7 @@ func (x *GetInboundUsersCountResponse) String() string {
|
||||
func (*GetInboundUsersCountResponse) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -587,7 +497,7 @@ func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use GetInboundUsersCountResponse.ProtoReflect.Descriptor instead.
|
||||
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 {
|
||||
@@ -607,7 +517,7 @@ type AddOutboundRequest struct {
|
||||
|
||||
func (x *AddOutboundRequest) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -619,7 +529,7 @@ func (x *AddOutboundRequest) String() string {
|
||||
func (*AddOutboundRequest) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -632,7 +542,7 @@ func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use AddOutboundRequest.ProtoReflect.Descriptor instead.
|
||||
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 {
|
||||
@@ -650,7 +560,7 @@ type AddOutboundResponse struct {
|
||||
|
||||
func (x *AddOutboundResponse) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -662,7 +572,7 @@ func (x *AddOutboundResponse) String() string {
|
||||
func (*AddOutboundResponse) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -675,7 +585,7 @@ func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use AddOutboundResponse.ProtoReflect.Descriptor instead.
|
||||
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 {
|
||||
@@ -688,7 +598,7 @@ type RemoveOutboundRequest struct {
|
||||
|
||||
func (x *RemoveOutboundRequest) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -700,7 +610,7 @@ func (x *RemoveOutboundRequest) String() string {
|
||||
func (*RemoveOutboundRequest) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -713,7 +623,7 @@ func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use RemoveOutboundRequest.ProtoReflect.Descriptor instead.
|
||||
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 {
|
||||
@@ -731,7 +641,7 @@ type RemoveOutboundResponse struct {
|
||||
|
||||
func (x *RemoveOutboundResponse) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -743,7 +653,7 @@ func (x *RemoveOutboundResponse) String() string {
|
||||
func (*RemoveOutboundResponse) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -756,7 +666,7 @@ func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use RemoveOutboundResponse.ProtoReflect.Descriptor instead.
|
||||
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 {
|
||||
@@ -770,7 +680,7 @@ type AlterOutboundRequest struct {
|
||||
|
||||
func (x *AlterOutboundRequest) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -782,7 +692,7 @@ func (x *AlterOutboundRequest) String() string {
|
||||
func (*AlterOutboundRequest) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -795,7 +705,7 @@ func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use AlterOutboundRequest.ProtoReflect.Descriptor instead.
|
||||
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 {
|
||||
@@ -820,7 +730,7 @@ type AlterOutboundResponse struct {
|
||||
|
||||
func (x *AlterOutboundResponse) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -832,7 +742,7 @@ func (x *AlterOutboundResponse) String() string {
|
||||
func (*AlterOutboundResponse) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -845,88 +755,7 @@ func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use AlterOutboundResponse.ProtoReflect.Descriptor instead.
|
||||
func (*AlterOutboundResponse) Descriptor() ([]byte, []int) {
|
||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{18}
|
||||
}
|
||||
|
||||
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
|
||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{16}
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -937,7 +766,7 @@ type Config struct {
|
||||
|
||||
func (x *Config) Reset() {
|
||||
*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.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -949,7 +778,7 @@ func (x *Config) String() string {
|
||||
func (*Config) ProtoMessage() {}
|
||||
|
||||
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 {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -962,7 +791,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||
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
|
||||
@@ -1002,84 +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,
|
||||
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,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x13,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x54, 0x61, 0x67,
|
||||
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x54,
|
||||
0x61, 0x67, 0x73, 0x22, 0x53, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x69,
|
||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08,
|
||||
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x3f, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49,
|
||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
||||
0x74, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a, 0x16, 0x47, 0x65, 0x74,
|
||||
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05,
|
||||
0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x52, 0x0a, 0x12, 0x41,
|
||||
0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e,
|
||||
0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x22,
|
||||
0x15, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x15, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
||||
0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
|
||||
0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61,
|
||||
0x67, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x14, 0x41,
|
||||
0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x15,
|
||||
0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a,
|
||||
0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73,
|
||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73,
|
||||
0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x1c, 0x47, 0x65, 0x74,
|
||||
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22,
|
||||
0x52, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64,
|
||||
0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x15, 0x52, 0x65,
|
||||
0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79,
|
||||
0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75,
|
||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16,
|
||||
0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x57, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75,
|
||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x3e, 0x0a, 0x09, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f,
|
||||
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22,
|
||||
0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xae, 0x09, 0x0a, 0x0e, 0x48, 0x61,
|
||||
0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x0a,
|
||||
0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, 0x52, 0x65, 0x6d,
|
||||
0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72,
|
||||
0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f,
|
||||
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x68, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
|
||||
0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09,
|
||||
0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74,
|
||||
0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xc5, 0x07, 0x0a,
|
||||
0x0e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
|
||||
0x6b, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||
0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e,
|
||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
||||
0x71, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12,
|
||||
0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
||||
0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
||||
0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
||||
0x64, 0x73, 0x12, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d,
|
||||
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e,
|
||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||
0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
||||
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
|
||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d,
|
||||
0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76,
|
||||
0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x12, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41,
|
||||
0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41,
|
||||
0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x78, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
@@ -1118,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,
|
||||
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74,
|
||||
0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62,
|
||||
0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
||||
0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||
0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f,
|
||||
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2e, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x19,
|
||||
0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||
0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
0x73, 0x65, 0x22, 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x19, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41,
|
||||
0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
||||
0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -1148,7 +946,7 @@ func file_app_proxyman_command_command_proto_rawDescGZIP() []byte {
|
||||
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{
|
||||
(*AddUserOperation)(nil), // 0: xray.app.proxyman.command.AddUserOperation
|
||||
(*RemoveUserOperation)(nil), // 1: xray.app.proxyman.command.RemoveUserOperation
|
||||
@@ -1158,59 +956,49 @@ var file_app_proxyman_command_command_proto_goTypes = []any{
|
||||
(*RemoveInboundResponse)(nil), // 5: xray.app.proxyman.command.RemoveInboundResponse
|
||||
(*AlterInboundRequest)(nil), // 6: xray.app.proxyman.command.AlterInboundRequest
|
||||
(*AlterInboundResponse)(nil), // 7: xray.app.proxyman.command.AlterInboundResponse
|
||||
(*ListInboundsRequest)(nil), // 8: xray.app.proxyman.command.ListInboundsRequest
|
||||
(*ListInboundsResponse)(nil), // 9: xray.app.proxyman.command.ListInboundsResponse
|
||||
(*GetInboundUserRequest)(nil), // 10: xray.app.proxyman.command.GetInboundUserRequest
|
||||
(*GetInboundUserResponse)(nil), // 11: xray.app.proxyman.command.GetInboundUserResponse
|
||||
(*GetInboundUsersCountResponse)(nil), // 12: xray.app.proxyman.command.GetInboundUsersCountResponse
|
||||
(*AddOutboundRequest)(nil), // 13: xray.app.proxyman.command.AddOutboundRequest
|
||||
(*AddOutboundResponse)(nil), // 14: xray.app.proxyman.command.AddOutboundResponse
|
||||
(*RemoveOutboundRequest)(nil), // 15: xray.app.proxyman.command.RemoveOutboundRequest
|
||||
(*RemoveOutboundResponse)(nil), // 16: xray.app.proxyman.command.RemoveOutboundResponse
|
||||
(*AlterOutboundRequest)(nil), // 17: xray.app.proxyman.command.AlterOutboundRequest
|
||||
(*AlterOutboundResponse)(nil), // 18: xray.app.proxyman.command.AlterOutboundResponse
|
||||
(*ListOutboundsRequest)(nil), // 19: xray.app.proxyman.command.ListOutboundsRequest
|
||||
(*ListOutboundsResponse)(nil), // 20: xray.app.proxyman.command.ListOutboundsResponse
|
||||
(*Config)(nil), // 21: xray.app.proxyman.command.Config
|
||||
(*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
|
||||
(*GetInboundUserRequest)(nil), // 8: xray.app.proxyman.command.GetInboundUserRequest
|
||||
(*GetInboundUserResponse)(nil), // 9: xray.app.proxyman.command.GetInboundUserResponse
|
||||
(*GetInboundUsersCountResponse)(nil), // 10: xray.app.proxyman.command.GetInboundUsersCountResponse
|
||||
(*AddOutboundRequest)(nil), // 11: xray.app.proxyman.command.AddOutboundRequest
|
||||
(*AddOutboundResponse)(nil), // 12: xray.app.proxyman.command.AddOutboundResponse
|
||||
(*RemoveOutboundRequest)(nil), // 13: xray.app.proxyman.command.RemoveOutboundRequest
|
||||
(*RemoveOutboundResponse)(nil), // 14: xray.app.proxyman.command.RemoveOutboundResponse
|
||||
(*AlterOutboundRequest)(nil), // 15: xray.app.proxyman.command.AlterOutboundRequest
|
||||
(*AlterOutboundResponse)(nil), // 16: xray.app.proxyman.command.AlterOutboundResponse
|
||||
(*Config)(nil), // 17: xray.app.proxyman.command.Config
|
||||
(*protocol.User)(nil), // 18: xray.common.protocol.User
|
||||
(*core.InboundHandlerConfig)(nil), // 19: xray.core.InboundHandlerConfig
|
||||
(*serial.TypedMessage)(nil), // 20: xray.common.serial.TypedMessage
|
||||
(*core.OutboundHandlerConfig)(nil), // 21: xray.core.OutboundHandlerConfig
|
||||
}
|
||||
var file_app_proxyman_command_command_proto_depIdxs = []int32{
|
||||
22, // 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
|
||||
24, // 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
|
||||
22, // 4: xray.app.proxyman.command.GetInboundUserResponse.users:type_name -> xray.common.protocol.User
|
||||
25, // 5: xray.app.proxyman.command.AddOutboundRequest.outbound:type_name -> xray.core.OutboundHandlerConfig
|
||||
24, // 6: xray.app.proxyman.command.AlterOutboundRequest.operation:type_name -> xray.common.serial.TypedMessage
|
||||
25, // 7: xray.app.proxyman.command.ListOutboundsResponse.outbounds:type_name -> xray.core.OutboundHandlerConfig
|
||||
2, // 8: xray.app.proxyman.command.HandlerService.AddInbound:input_type -> xray.app.proxyman.command.AddInboundRequest
|
||||
4, // 9: xray.app.proxyman.command.HandlerService.RemoveInbound:input_type -> xray.app.proxyman.command.RemoveInboundRequest
|
||||
6, // 10: xray.app.proxyman.command.HandlerService.AlterInbound:input_type -> xray.app.proxyman.command.AlterInboundRequest
|
||||
8, // 11: xray.app.proxyman.command.HandlerService.ListInbounds:input_type -> xray.app.proxyman.command.ListInboundsRequest
|
||||
10, // 12: xray.app.proxyman.command.HandlerService.GetInboundUsers:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
||||
10, // 13: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
||||
13, // 14: xray.app.proxyman.command.HandlerService.AddOutbound:input_type -> xray.app.proxyman.command.AddOutboundRequest
|
||||
15, // 15: xray.app.proxyman.command.HandlerService.RemoveOutbound:input_type -> xray.app.proxyman.command.RemoveOutboundRequest
|
||||
17, // 16: xray.app.proxyman.command.HandlerService.AlterOutbound:input_type -> xray.app.proxyman.command.AlterOutboundRequest
|
||||
19, // 17: xray.app.proxyman.command.HandlerService.ListOutbounds:input_type -> xray.app.proxyman.command.ListOutboundsRequest
|
||||
3, // 18: xray.app.proxyman.command.HandlerService.AddInbound:output_type -> xray.app.proxyman.command.AddInboundResponse
|
||||
5, // 19: xray.app.proxyman.command.HandlerService.RemoveInbound:output_type -> xray.app.proxyman.command.RemoveInboundResponse
|
||||
7, // 20: xray.app.proxyman.command.HandlerService.AlterInbound:output_type -> xray.app.proxyman.command.AlterInboundResponse
|
||||
9, // 21: xray.app.proxyman.command.HandlerService.ListInbounds:output_type -> xray.app.proxyman.command.ListInboundsResponse
|
||||
11, // 22: xray.app.proxyman.command.HandlerService.GetInboundUsers:output_type -> xray.app.proxyman.command.GetInboundUserResponse
|
||||
12, // 23: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:output_type -> xray.app.proxyman.command.GetInboundUsersCountResponse
|
||||
14, // 24: xray.app.proxyman.command.HandlerService.AddOutbound:output_type -> xray.app.proxyman.command.AddOutboundResponse
|
||||
16, // 25: xray.app.proxyman.command.HandlerService.RemoveOutbound:output_type -> xray.app.proxyman.command.RemoveOutboundResponse
|
||||
18, // 26: xray.app.proxyman.command.HandlerService.AlterOutbound:output_type -> xray.app.proxyman.command.AlterOutboundResponse
|
||||
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
|
||||
18, // 0: xray.app.proxyman.command.AddUserOperation.user:type_name -> xray.common.protocol.User
|
||||
19, // 1: xray.app.proxyman.command.AddInboundRequest.inbound:type_name -> xray.core.InboundHandlerConfig
|
||||
20, // 2: xray.app.proxyman.command.AlterInboundRequest.operation:type_name -> xray.common.serial.TypedMessage
|
||||
18, // 3: 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
|
||||
20, // 5: 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
|
||||
4, // 7: xray.app.proxyman.command.HandlerService.RemoveInbound:input_type -> xray.app.proxyman.command.RemoveInboundRequest
|
||||
6, // 8: xray.app.proxyman.command.HandlerService.AlterInbound:input_type -> xray.app.proxyman.command.AlterInboundRequest
|
||||
8, // 9: xray.app.proxyman.command.HandlerService.GetInboundUsers:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
||||
8, // 10: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
||||
11, // 11: xray.app.proxyman.command.HandlerService.AddOutbound:input_type -> xray.app.proxyman.command.AddOutboundRequest
|
||||
13, // 12: xray.app.proxyman.command.HandlerService.RemoveOutbound:input_type -> xray.app.proxyman.command.RemoveOutboundRequest
|
||||
15, // 13: xray.app.proxyman.command.HandlerService.AlterOutbound:input_type -> xray.app.proxyman.command.AlterOutboundRequest
|
||||
3, // 14: xray.app.proxyman.command.HandlerService.AddInbound:output_type -> xray.app.proxyman.command.AddInboundResponse
|
||||
5, // 15: xray.app.proxyman.command.HandlerService.RemoveInbound:output_type -> xray.app.proxyman.command.RemoveInboundResponse
|
||||
7, // 16: xray.app.proxyman.command.HandlerService.AlterInbound:output_type -> xray.app.proxyman.command.AlterInboundResponse
|
||||
9, // 17: xray.app.proxyman.command.HandlerService.GetInboundUsers:output_type -> xray.app.proxyman.command.GetInboundUserResponse
|
||||
10, // 18: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:output_type -> xray.app.proxyman.command.GetInboundUsersCountResponse
|
||||
12, // 19: xray.app.proxyman.command.HandlerService.AddOutbound:output_type -> xray.app.proxyman.command.AddOutboundResponse
|
||||
14, // 20: xray.app.proxyman.command.HandlerService.RemoveOutbound:output_type -> xray.app.proxyman.command.RemoveOutboundResponse
|
||||
16, // 21: xray.app.proxyman.command.HandlerService.AlterOutbound:output_type -> xray.app.proxyman.command.AlterOutboundResponse
|
||||
14, // [14:22] is the sub-list for method output_type
|
||||
6, // [6:14] is the sub-list for method input_type
|
||||
6, // [6:6] is the sub-list for extension type_name
|
||||
6, // [6:6] is the sub-list for extension extendee
|
||||
0, // [0:6] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_app_proxyman_command_command_proto_init() }
|
||||
@@ -1224,7 +1012,7 @@ func file_app_proxyman_command_command_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_app_proxyman_command_command_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 22,
|
||||
NumMessages: 18,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
@@ -37,14 +37,6 @@ message AlterInboundRequest {
|
||||
|
||||
message AlterInboundResponse {}
|
||||
|
||||
message ListInboundsRequest {
|
||||
bool isOnlyTags = 1;
|
||||
}
|
||||
|
||||
message ListInboundsResponse {
|
||||
repeated core.InboundHandlerConfig inbounds = 1;
|
||||
}
|
||||
|
||||
message GetInboundUserRequest {
|
||||
string tag = 1;
|
||||
string email = 2;
|
||||
@@ -77,12 +69,6 @@ message AlterOutboundRequest {
|
||||
|
||||
message AlterOutboundResponse {}
|
||||
|
||||
message ListOutboundsRequest {}
|
||||
|
||||
message ListOutboundsResponse {
|
||||
repeated core.OutboundHandlerConfig outbounds = 1;
|
||||
}
|
||||
|
||||
service HandlerService {
|
||||
rpc AddInbound(AddInboundRequest) returns (AddInboundResponse) {}
|
||||
|
||||
@@ -90,8 +76,6 @@ service HandlerService {
|
||||
|
||||
rpc AlterInbound(AlterInboundRequest) returns (AlterInboundResponse) {}
|
||||
|
||||
rpc ListInbounds(ListInboundsRequest) returns (ListInboundsResponse) {}
|
||||
|
||||
rpc GetInboundUsers(GetInboundUserRequest) returns (GetInboundUserResponse) {}
|
||||
|
||||
rpc GetInboundUsersCount(GetInboundUserRequest) returns (GetInboundUsersCountResponse) {}
|
||||
@@ -101,8 +85,6 @@ service HandlerService {
|
||||
rpc RemoveOutbound(RemoveOutboundRequest) returns (RemoveOutboundResponse) {}
|
||||
|
||||
rpc AlterOutbound(AlterOutboundRequest) returns (AlterOutboundResponse) {}
|
||||
|
||||
rpc ListOutbounds(ListOutboundsRequest) returns (ListOutboundsResponse) {}
|
||||
}
|
||||
|
||||
message Config {}
|
||||
|
@@ -22,13 +22,11 @@ const (
|
||||
HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound"
|
||||
HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound"
|
||||
HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound"
|
||||
HandlerService_ListInbounds_FullMethodName = "/xray.app.proxyman.command.HandlerService/ListInbounds"
|
||||
HandlerService_GetInboundUsers_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsers"
|
||||
HandlerService_GetInboundUsersCount_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsersCount"
|
||||
HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound"
|
||||
HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound"
|
||||
HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound"
|
||||
HandlerService_ListOutbounds_FullMethodName = "/xray.app.proxyman.command.HandlerService/ListOutbounds"
|
||||
)
|
||||
|
||||
// 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)
|
||||
RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, 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)
|
||||
GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error)
|
||||
AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error)
|
||||
RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, 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 {
|
||||
@@ -85,16 +81,6 @@ func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboun
|
||||
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) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetInboundUserResponse)
|
||||
@@ -145,16 +131,6 @@ func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutbo
|
||||
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.
|
||||
// All implementations must embed UnimplementedHandlerServiceServer
|
||||
// for forward compatibility.
|
||||
@@ -162,13 +138,11 @@ type HandlerServiceServer interface {
|
||||
AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error)
|
||||
RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error)
|
||||
AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error)
|
||||
ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error)
|
||||
GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error)
|
||||
GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error)
|
||||
AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error)
|
||||
RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error)
|
||||
AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error)
|
||||
ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error)
|
||||
mustEmbedUnimplementedHandlerServiceServer()
|
||||
}
|
||||
|
||||
@@ -188,9 +162,6 @@ func (UnimplementedHandlerServiceServer) RemoveInbound(context.Context, *RemoveI
|
||||
func (UnimplementedHandlerServiceServer) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) {
|
||||
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) {
|
||||
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) {
|
||||
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) testEmbeddedByValue() {}
|
||||
|
||||
@@ -284,24 +252,6 @@ func _HandlerService_AlterInbound_Handler(srv interface{}, ctx context.Context,
|
||||
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) {
|
||||
in := new(GetInboundUserRequest)
|
||||
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)
|
||||
}
|
||||
|
||||
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.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
@@ -429,10 +361,6 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "AlterInbound",
|
||||
Handler: _HandlerService_AlterInbound_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListInbounds",
|
||||
Handler: _HandlerService_ListInbounds_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetInboundUsers",
|
||||
Handler: _HandlerService_GetInboundUsers_Handler,
|
||||
@@ -453,10 +381,6 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "AlterOutbound",
|
||||
Handler: _HandlerService_AlterOutbound_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListOutbounds",
|
||||
Handler: _HandlerService_ListOutbounds_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "app/proxyman/command/command.proto",
|
||||
|
@@ -9,13 +9,11 @@ import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/mux"
|
||||
"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/features/policy"
|
||||
"github.com/xtls/xray-core/features/stats"
|
||||
"github.com/xtls/xray-core/proxy"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
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 {
|
||||
proxyConfig interface{}
|
||||
receiverConfig *proxyman.ReceiverConfig
|
||||
proxy proxy.Inbound
|
||||
workers []worker
|
||||
mux *mux.Server
|
||||
@@ -63,8 +59,6 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
||||
}
|
||||
|
||||
h := &AlwaysOnInboundHandler{
|
||||
receiverConfig: receiverConfig,
|
||||
proxyConfig: proxyConfig,
|
||||
proxy: p,
|
||||
mux: mux.NewServer(ctx),
|
||||
tag: tag,
|
||||
@@ -193,16 +187,3 @@ func (h *AlwaysOnInboundHandler) Tag() string {
|
||||
func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound {
|
||||
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/mux"
|
||||
"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/core"
|
||||
"github.com/xtls/xray-core/proxy"
|
||||
"github.com/xtls/xray-core/transport/internet"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type DynamicInboundHandler struct {
|
||||
@@ -207,16 +205,3 @@ func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port,
|
||||
func (h *DynamicInboundHandler) Tag() string {
|
||||
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
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ import (
|
||||
// Manager manages all inbound handlers.
|
||||
type Manager struct {
|
||||
access sync.RWMutex
|
||||
untaggedHandlers []inbound.Handler
|
||||
untaggedHandler []inbound.Handler
|
||||
taggedHandlers map[string]inbound.Handler
|
||||
running bool
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (m *Manager) AddHandler(ctx context.Context, handler inbound.Handler) error
|
||||
}
|
||||
m.taggedHandlers[tag] = handler
|
||||
} else {
|
||||
m.untaggedHandlers = append(m.untaggedHandlers, handler)
|
||||
m.untaggedHandler = append(m.untaggedHandler, handler)
|
||||
}
|
||||
|
||||
if m.running {
|
||||
@@ -89,21 +89,6 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
|
||||
return common.ErrNoClue
|
||||
}
|
||||
|
||||
// ListHandlers implements inbound.Manager.
|
||||
func (m *Manager) ListHandlers(ctx context.Context) []inbound.Handler {
|
||||
m.access.RLock()
|
||||
defer m.access.RUnlock()
|
||||
|
||||
response := make([]inbound.Handler, len(m.untaggedHandlers))
|
||||
copy(response, m.untaggedHandlers)
|
||||
|
||||
for _, v := range m.taggedHandlers {
|
||||
response = append(response, v)
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
// Start implements common.Runnable.
|
||||
func (m *Manager) Start() error {
|
||||
m.access.Lock()
|
||||
@@ -117,7 +102,7 @@ func (m *Manager) Start() error {
|
||||
}
|
||||
}
|
||||
|
||||
for _, handler := range m.untaggedHandlers {
|
||||
for _, handler := range m.untaggedHandler {
|
||||
if err := handler.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -138,7 +123,7 @@ func (m *Manager) Close() error {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
for _, handler := range m.untaggedHandlers {
|
||||
for _, handler := range m.untaggedHandler {
|
||||
if err := handler.Close(); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
@@ -91,7 +91,6 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
||||
}
|
||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
||||
Local: net.DestinationFromAddr(conn.LocalAddr()),
|
||||
Gateway: net.TCPDestination(w.address, w.port),
|
||||
Tag: w.tag,
|
||||
Conn: conn,
|
||||
@@ -162,7 +161,6 @@ type udpConn struct {
|
||||
uplink stats.Counter
|
||||
downlink stats.Counter
|
||||
inactive bool
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func (c *udpConn) setInactive() {
|
||||
@@ -205,9 +203,6 @@ func (c *udpConn) Write(buf []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (c *udpConn) Close() error {
|
||||
if c.cancel != nil {
|
||||
c.cancel()
|
||||
}
|
||||
common.Must(c.done.Close())
|
||||
common.Must(common.Close(c.writer))
|
||||
return nil
|
||||
@@ -264,7 +259,6 @@ func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
|
||||
defer w.Unlock()
|
||||
|
||||
if conn, found := w.activeConn[id]; found && !conn.done.Done() {
|
||||
conn.updateActivity()
|
||||
return conn, true
|
||||
}
|
||||
|
||||
@@ -312,8 +306,7 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||
common.Must(w.checker.Start())
|
||||
|
||||
go func() {
|
||||
ctx, cancel := context.WithCancel(w.ctx)
|
||||
conn.cancel = cancel
|
||||
ctx := w.ctx
|
||||
sid := session.NewID()
|
||||
ctx = c.ContextWithID(ctx, sid)
|
||||
|
||||
@@ -322,10 +315,8 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||
outbounds[0].Target = originalDest
|
||||
}
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
|
||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||
Source: source,
|
||||
Local: net.DestinationFromAddr(w.hub.Addr()),
|
||||
Gateway: net.UDPDestination(w.address, w.port),
|
||||
Tag: w.tag,
|
||||
})
|
||||
@@ -475,7 +466,6 @@ func (w *dsWorker) callback(conn stat.Connection) {
|
||||
}
|
||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
||||
Local: net.DestinationFromAddr(conn.LocalAddr()),
|
||||
Gateway: net.UnixDestination(w.address),
|
||||
Tag: w.tag,
|
||||
Conn: conn,
|
||||
|
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/mux"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"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/core"
|
||||
"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/tls"
|
||||
"github.com/xtls/xray-core/transport/pipe"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
||||
@@ -61,7 +59,6 @@ type Handler struct {
|
||||
tag string
|
||||
senderSettings *proxyman.SenderConfig
|
||||
streamSettings *internet.MemoryStreamConfig
|
||||
proxyConfig proto.Message
|
||||
proxy proxy.Outbound
|
||||
outboundManager outbound.Manager
|
||||
mux *mux.ClientManager
|
||||
@@ -104,7 +101,6 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.proxyConfig = proxyConfig
|
||||
|
||||
rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
|
||||
if err != nil {
|
||||
@@ -245,9 +241,7 @@ func (h *Handler) DestIpAddress() net.IP {
|
||||
// Dial implements internet.Dialer.
|
||||
func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connection, error) {
|
||||
if h.senderSettings != nil {
|
||||
|
||||
if h.senderSettings.ProxySettings.HasTag() {
|
||||
|
||||
tag := h.senderSettings.ProxySettings.Tag
|
||||
handler := h.outboundManager.GetHandler(tag)
|
||||
if handler != nil {
|
||||
@@ -276,45 +270,23 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
||||
}
|
||||
|
||||
if h.senderSettings.Via != nil {
|
||||
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds)-1]
|
||||
var domain string
|
||||
addr := h.senderSettings.Via.AsAddress()
|
||||
domain = h.senderSettings.Via.GetDomain()
|
||||
switch {
|
||||
case h.senderSettings.ViaCidr != "":
|
||||
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
|
||||
|
||||
case domain == "origin":
|
||||
|
||||
if h.senderSettings.ViaCidr == "" {
|
||||
if h.senderSettings.Via.AsAddress().Family().IsDomain() && h.senderSettings.Via.AsAddress().Domain() == "origin" {
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||
if inbound.Conn != nil {
|
||||
origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String())
|
||||
if err == nil {
|
||||
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":
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||
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)
|
||||
} else { //Get a random address.
|
||||
ob.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//case addr.Family().IsDomain():
|
||||
default:
|
||||
ob.Gateway = addr
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
|
||||
@@ -353,35 +325,23 @@ func (h *Handler) Start() error {
|
||||
// Close implements common.Closable.
|
||||
func (h *Handler) Close() error {
|
||||
common.Close(h.mux)
|
||||
common.Close(h.proxy)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SenderSettings implements outbound.Handler.
|
||||
func (h *Handler) SenderSettings() *serial.TypedMessage {
|
||||
return serial.ToTypedMessage(h.senderSettings)
|
||||
}
|
||||
|
||||
// ProxySettings implements outbound.Handler.
|
||||
func (h *Handler) ProxySettings() *serial.TypedMessage {
|
||||
return serial.ToTypedMessage(h.proxyConfig)
|
||||
}
|
||||
|
||||
func ParseRandomIP(addr net.Address, prefix string) net.Address {
|
||||
|
||||
_, ipnet, _ := gonet.ParseCIDR(addr.IP().String() + "/" + prefix)
|
||||
|
||||
ones, bits := ipnet.Mask.Size()
|
||||
subnetSize := new(big.Int).Lsh(big.NewInt(1), uint(bits-ones))
|
||||
|
||||
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())
|
||||
func ParseRandomIPv6(address net.Address, prefix string) net.Address {
|
||||
_, network, _ := gonet.ParseCIDR(address.IP().String() + "/" + prefix)
|
||||
|
||||
maskSize, totalBits := network.Mask.Size()
|
||||
subnetSize := big.NewInt(1).Lsh(big.NewInt(1), uint(totalBits-maskSize))
|
||||
|
||||
// random
|
||||
randomBigInt, _ := rand.Int(rand.Reader, subnetSize)
|
||||
|
||||
startIPBigInt := big.NewInt(0).SetBytes(network.IP.To16())
|
||||
randomIPBigInt := big.NewInt(0).Add(startIPBigInt, randomBigInt)
|
||||
|
||||
randomIPBytes := randomIPBigInt.Bytes()
|
||||
randomIPBytes = append(make([]byte, 16-len(randomIPBytes)), randomIPBytes...)
|
||||
|
||||
return net.ParseAddress(gonet.IP(randomIPBytes).String())
|
||||
}
|
||||
|
@@ -145,21 +145,6 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ListHandlers implements outbound.Manager.
|
||||
func (m *Manager) ListHandlers(ctx context.Context) []outbound.Handler {
|
||||
m.access.RLock()
|
||||
defer m.access.RUnlock()
|
||||
|
||||
response := make([]outbound.Handler, len(m.untaggedHandlers))
|
||||
copy(response, m.untaggedHandlers)
|
||||
|
||||
for _, v := range m.taggedHandler {
|
||||
response = append(response, v)
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
// Select implements outbound.HandlerSelector.
|
||||
func (m *Manager) Select(selectors []string) []string {
|
||||
|
||||
|
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
func (c *Control) FillInRandom() {
|
||||
randomLength := dice.Roll(64)
|
||||
randomLength++
|
||||
c.Random = make([]byte, randomLength)
|
||||
io.ReadFull(rand.Reader, c.Random)
|
||||
}
|
||||
|
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/mux"
|
||||
"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/task"
|
||||
"github.com/xtls/xray-core/features/outbound"
|
||||
@@ -112,16 +111,6 @@ func (o *Outbound) Close() error {
|
||||
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 {
|
||||
access sync.Mutex
|
||||
workers []*PortalWorker
|
||||
@@ -170,7 +159,7 @@ func (p *StaticMuxPicker) PickAvailable() (*mux.ClientWorker, error) {
|
||||
if w.draining {
|
||||
continue
|
||||
}
|
||||
if w.IsFull() {
|
||||
if w.client.Closed() {
|
||||
continue
|
||||
}
|
||||
if w.client.ActiveConnections() < minConn {
|
||||
@@ -211,7 +200,6 @@ type PortalWorker struct {
|
||||
writer buf.Writer
|
||||
reader buf.Reader
|
||||
draining bool
|
||||
counter uint32
|
||||
}
|
||||
|
||||
func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
|
||||
@@ -245,7 +233,7 @@ func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
|
||||
}
|
||||
|
||||
func (w *PortalWorker) heartbeat() error {
|
||||
if w.Closed() {
|
||||
if w.client.Closed() {
|
||||
return errors.New("client worker stopped")
|
||||
}
|
||||
|
||||
@@ -261,22 +249,17 @@ func (w *PortalWorker) heartbeat() error {
|
||||
msg.State = Control_DRAIN
|
||||
|
||||
defer func() {
|
||||
w.client.GetTimer().Reset(time.Second * 16)
|
||||
common.Close(w.writer)
|
||||
common.Interrupt(w.reader)
|
||||
w.writer = nil
|
||||
}()
|
||||
}
|
||||
|
||||
w.counter = (w.counter + 1) % 5
|
||||
if w.draining || w.counter == 1 {
|
||||
b, err := proto.Marshal(msg)
|
||||
common.Must(err)
|
||||
mb := buf.MergeBytes(nil, b)
|
||||
return w.writer.WriteMultiBuffer(mb)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *PortalWorker) IsFull() bool {
|
||||
return w.client.IsFull()
|
||||
|
@@ -42,8 +42,6 @@ type RoutingContext struct {
|
||||
Attributes map[string]string `protobuf:"bytes,10,rep,name=Attributes,proto3" json:"Attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
OutboundGroupTags []string `protobuf:"bytes,11,rep,name=OutboundGroupTags,proto3" json:"OutboundGroupTags,omitempty"`
|
||||
OutboundTag string `protobuf:"bytes,12,opt,name=OutboundTag,proto3" json:"OutboundTag,omitempty"`
|
||||
LocalIPs [][]byte `protobuf:"bytes,13,rep,name=LocalIPs,proto3" json:"LocalIPs,omitempty"`
|
||||
LocalPort uint32 `protobuf:"varint,14,opt,name=LocalPort,proto3" json:"LocalPort,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RoutingContext) Reset() {
|
||||
@@ -160,20 +158,6 @@ func (x *RoutingContext) GetOutboundTag() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RoutingContext) GetLocalIPs() [][]byte {
|
||||
if x != nil {
|
||||
return x.LocalIPs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RoutingContext) GetLocalPort() uint32 {
|
||||
if x != nil {
|
||||
return x.LocalPort
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
||||
// opened by xray-core.
|
||||
// * FieldSelectors selects a subset of fields in routing statistics to return.
|
||||
@@ -843,7 +827,7 @@ var file_app_router_command_command_proto_rawDesc = []byte{
|
||||
0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65,
|
||||
0x72, 0x69, 0x61, 0x6c, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd6, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
||||
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9c, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
||||
0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x49,
|
||||
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0a, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x32, 0x0a, 0x07, 0x4e,
|
||||
@@ -873,127 +857,123 @@ var file_app_router_command_command_proto_rawDesc = []byte{
|
||||
0x03, 0x28, 0x09, 0x52, 0x11, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x47, 0x72, 0x6f,
|
||||
0x75, 0x70, 0x54, 0x61, 0x67, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4f, 0x75, 0x74,
|
||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61,
|
||||
0x6c, 0x49, 0x50, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4c, 0x6f, 0x63, 0x61,
|
||||
0x6c, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72,
|
||||
0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f,
|
||||
0x72, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||
0x01, 0x22, 0x46, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f,
|
||||
0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
|
||||
0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
||||
0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x54, 0x65,
|
||||
0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f,
|
||||
0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72,
|
||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
|
||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x46, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63,
|
||||
0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
||||
0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||
0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22,
|
||||
0xb1, 0x01, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43,
|
||||
0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
||||
0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
||||
0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65,
|
||||
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46,
|
||||
0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a,
|
||||
0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73,
|
||||
0x75, 0x6c, 0x74, 0x22, 0x27, 0x0a, 0x13, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65,
|
||||
0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61,
|
||||
0x67, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x26, 0x0a, 0x0c,
|
||||
0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61,
|
||||
0x72, 0x67, 0x65, 0x74, 0x22, 0xa9, 0x01, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
|
||||
0x72, 0x4d, 0x73, 0x67, 0x12, 0x41, 0x0a, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
|
||||
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52,
|
||||
0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12,
|
||||
0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72,
|
||||
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65,
|
||||
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69,
|
||||
0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d,
|
||||
0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x27, 0x0a,
|
||||
0x13, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x26, 0x0a, 0x0c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
|
||||
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xa9,
|
||||
0x01, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x41,
|
||||
0x0a, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||
0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
||||
0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x74,
|
||||
0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72,
|
||||
0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6f,
|
||||
0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63,
|
||||
0x69, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e,
|
||||
0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
||||
0x0f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||
0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49,
|
||||
0x6e, 0x66, 0x6f, 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, 0x5b, 0x0a, 0x17,
|
||||
0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x61, 0x6e, 0x64, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52,
|
||||
0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x1d, 0x4f, 0x76, 0x65,
|
||||
0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72,
|
||||
0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61,
|
||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61,
|
||||
0x72, 0x67, 0x65, 0x74, 0x22, 0x20, 0x0a, 0x1e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6e, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79,
|
||||
0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65,
|
||||
0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64,
|
||||
0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x22, 0x11, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c,
|
||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2d, 0x0a, 0x11, 0x52, 0x65, 0x6d,
|
||||
0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f,
|
||||
0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08,
|
||||
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xbf, 0x05, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
||||
0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7b, 0x0a, 0x15, 0x53,
|
||||
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53,
|
||||
0x74, 0x61, 0x74, 0x73, 0x12, 0x35, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53,
|
||||
0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53,
|
||||
0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54,
|
||||
0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x70, 0x72, 0x69, 0x6e, 0x63,
|
||||
0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65,
|
||||
0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 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, 0x5b, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x42, 0x61,
|
||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x1d, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42,
|
||||
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72,
|
||||
0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x20,
|
||||
0x0a, 0x1e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x6e, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x12, 0x38, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73,
|
||||
0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x22, 0x0a, 0x0c,
|
||||
0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x08, 0x52, 0x0c, 0x73, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x41, 0x70, 0x70, 0x65, 0x6e, 0x64,
|
||||
0x22, 0x11, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x2d, 0x0a, 0x11, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x75, 0x6c, 0x65,
|
||||
0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54,
|
||||
0x61, 0x67, 0x22, 0x14, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66,
|
||||
0x69, 0x67, 0x32, 0xbf, 0x05, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x7b, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
|
||||
0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x35,
|
||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
||||
0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74,
|
||||
0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
||||
0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69,
|
||||
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0f, 0x47,
|
||||
0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f,
|
||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
|
||||
0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
||||
0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00,
|
||||
0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12,
|
||||
0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74,
|
||||
0x65, 0x78, 0x74, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||
0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e,
|
||||
0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49,
|
||||
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x8b, 0x01,
|
||||
0x0a, 0x16, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x36, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||
0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||
0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65,
|
||||
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x07, 0x41,
|
||||
0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61,
|
||||
0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c,
|
||||
0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x00, 0x12, 0x8b, 0x01, 0x0a, 0x16, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65,
|
||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x36,
|
||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
||||
0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64,
|
||||
0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||
0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c,
|
||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x67, 0x0a, 0x0a, 0x52,
|
||||
0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
|
||||
0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x00, 0x12, 0x5e, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x27, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63,
|
||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
||||
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x00, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x61, 0x6e, 0x64, 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, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52,
|
||||
0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x41, 0x64, 0x64, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x00, 0x12, 0x67, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12,
|
||||
0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
||||
0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f,
|
||||
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 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, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
||||
0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -25,8 +25,6 @@ message RoutingContext {
|
||||
map<string, string> Attributes = 10;
|
||||
repeated string OutboundGroupTags = 11;
|
||||
string OutboundTag = 12;
|
||||
repeated bytes LocalIPs = 13;
|
||||
uint32 LocalPort = 14;
|
||||
}
|
||||
|
||||
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
||||
|
@@ -28,14 +28,6 @@ func (c routingContext) GetTargetPort() net.Port {
|
||||
return net.Port(c.RoutingContext.GetTargetPort())
|
||||
}
|
||||
|
||||
func (c routingContext) GetLocalIPs() []net.IP {
|
||||
return mapBytesToIPs(c.RoutingContext.GetLocalIPs())
|
||||
}
|
||||
|
||||
func (c routingContext) GetLocalPort() net.Port {
|
||||
return net.Port(c.RoutingContext.GetLocalPort())
|
||||
}
|
||||
|
||||
func (c routingContext) GetRuleTag() string {
|
||||
return ""
|
||||
}
|
||||
@@ -62,10 +54,8 @@ var fieldMap = map[string]func(*RoutingContext, routing.Route){
|
||||
"network": func(s *RoutingContext, r routing.Route) { s.Network = r.GetNetwork() },
|
||||
"ip_source": func(s *RoutingContext, r routing.Route) { s.SourceIPs = mapIPsToBytes(r.GetSourceIPs()) },
|
||||
"ip_target": func(s *RoutingContext, r routing.Route) { s.TargetIPs = mapIPsToBytes(r.GetTargetIPs()) },
|
||||
"ip_local": func(s *RoutingContext, r routing.Route) { s.LocalIPs = mapIPsToBytes(r.GetLocalIPs()) },
|
||||
"port_source": func(s *RoutingContext, r routing.Route) { s.SourcePort = uint32(r.GetSourcePort()) },
|
||||
"port_target": func(s *RoutingContext, r routing.Route) { s.TargetPort = uint32(r.GetTargetPort()) },
|
||||
"port_local": func(s *RoutingContext, r routing.Route) { s.LocalPort = uint32(r.GetLocalPort()) },
|
||||
"domain": func(s *RoutingContext, r routing.Route) { s.TargetDomain = r.GetTargetDomain() },
|
||||
"protocol": func(s *RoutingContext, r routing.Route) { s.Protocol = r.GetProtocol() },
|
||||
"user": func(s *RoutingContext, r routing.Route) { s.User = r.GetUser() },
|
||||
|
@@ -113,13 +113,13 @@ func (m *DomainMatcher) Apply(ctx routing.Context) bool {
|
||||
|
||||
type MultiGeoIPMatcher struct {
|
||||
matchers []*GeoIPMatcher
|
||||
asType string // local, source, target
|
||||
onSource bool
|
||||
}
|
||||
|
||||
func NewMultiGeoIPMatcher(geoips []*GeoIP, asType string) (*MultiGeoIPMatcher, error) {
|
||||
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
||||
var matchers []*GeoIPMatcher
|
||||
for _, geoip := range geoips {
|
||||
matcher, err := GlobalGeoIPContainer.Add(geoip)
|
||||
matcher, err := globalGeoIPContainer.Add(geoip)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func NewMultiGeoIPMatcher(geoips []*GeoIP, asType string) (*MultiGeoIPMatcher, e
|
||||
|
||||
matcher := &MultiGeoIPMatcher{
|
||||
matchers: matchers,
|
||||
asType: asType,
|
||||
onSource: onSource,
|
||||
}
|
||||
|
||||
return matcher, nil
|
||||
@@ -137,18 +137,11 @@ func NewMultiGeoIPMatcher(geoips []*GeoIP, asType string) (*MultiGeoIPMatcher, e
|
||||
// Apply implements Condition.
|
||||
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
||||
var ips []net.IP
|
||||
|
||||
switch m.asType {
|
||||
case "local":
|
||||
ips = ctx.GetLocalIPs()
|
||||
case "source":
|
||||
if m.onSource {
|
||||
ips = ctx.GetSourceIPs()
|
||||
case "target":
|
||||
} else {
|
||||
ips = ctx.GetTargetIPs()
|
||||
default:
|
||||
panic("unreachable, asType should be local or source or target")
|
||||
}
|
||||
|
||||
for _, ip := range ips {
|
||||
for _, matcher := range m.matchers {
|
||||
if matcher.Match(ip) {
|
||||
@@ -161,30 +154,24 @@ func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
||||
|
||||
type PortMatcher struct {
|
||||
port net.MemoryPortList
|
||||
asType string // local, source, target
|
||||
onSource bool
|
||||
}
|
||||
|
||||
// NewPortMatcher create a new port matcher that can match source or local or destination port
|
||||
func NewPortMatcher(list *net.PortList, asType string) *PortMatcher {
|
||||
// NewPortMatcher create a new port matcher that can match source or destination port
|
||||
func NewPortMatcher(list *net.PortList, onSource bool) *PortMatcher {
|
||||
return &PortMatcher{
|
||||
port: net.PortListFromProto(list),
|
||||
asType: asType,
|
||||
onSource: onSource,
|
||||
}
|
||||
}
|
||||
|
||||
// Apply implements Condition.
|
||||
func (v *PortMatcher) Apply(ctx routing.Context) bool {
|
||||
switch v.asType {
|
||||
case "local":
|
||||
return v.port.Contains(ctx.GetLocalPort())
|
||||
case "source":
|
||||
if v.onSource {
|
||||
return v.port.Contains(ctx.GetSourcePort())
|
||||
case "target":
|
||||
} else {
|
||||
return v.port.Contains(ctx.GetTargetPort())
|
||||
default:
|
||||
panic("unreachable, asType should be local or source or target")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type NetworkMatcher struct {
|
||||
|
@@ -115,30 +115,4 @@ func (c *GeoIPMatcherContainer) Add(geoip *GeoIP) (*GeoIPMatcher, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
var globalGeoIPContainer GeoIPMatcherContainer
|
||||
|
@@ -495,7 +495,7 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
||||
})
|
||||
}
|
||||
|
||||
matcher, err := NewMultiGeoIPMatcher(geoips, "target")
|
||||
matcher, err := NewMultiGeoIPMatcher(geoips, false)
|
||||
common.Must(err)
|
||||
|
||||
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
||||
|
@@ -61,15 +61,11 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
||||
}
|
||||
|
||||
if rr.PortList != nil {
|
||||
conds.Add(NewPortMatcher(rr.PortList, "target"))
|
||||
conds.Add(NewPortMatcher(rr.PortList, false))
|
||||
}
|
||||
|
||||
if rr.SourcePortList != nil {
|
||||
conds.Add(NewPortMatcher(rr.SourcePortList, "source"))
|
||||
}
|
||||
|
||||
if rr.LocalPortList != nil {
|
||||
conds.Add(NewPortMatcher(rr.LocalPortList, "local"))
|
||||
conds.Add(NewPortMatcher(rr.SourcePortList, true))
|
||||
}
|
||||
|
||||
if len(rr.Networks) > 0 {
|
||||
@@ -77,7 +73,7 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
||||
}
|
||||
|
||||
if len(rr.Geoip) > 0 {
|
||||
cond, err := NewMultiGeoIPMatcher(rr.Geoip, "target")
|
||||
cond, err := NewMultiGeoIPMatcher(rr.Geoip, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -85,22 +81,13 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
||||
}
|
||||
|
||||
if len(rr.SourceGeoip) > 0 {
|
||||
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, "source")
|
||||
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conds.Add(cond)
|
||||
}
|
||||
|
||||
if len(rr.LocalGeoip) > 0 {
|
||||
cond, err := NewMultiGeoIPMatcher(rr.LocalGeoip, "local")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
conds.Add(cond)
|
||||
errors.LogWarning(context.Background(), "Due to some limitations, in UDP connections, localIP is always equal to listen interface IP, so \"localIP\" rule condition does not work properly on UDP inbound connections that listen on all interfaces")
|
||||
}
|
||||
|
||||
if len(rr.Protocol) > 0 {
|
||||
conds.Add(NewProtocolMatcher(rr.Protocol))
|
||||
}
|
||||
|
@@ -470,7 +470,7 @@ type RoutingRule struct {
|
||||
// *RoutingRule_Tag
|
||||
// *RoutingRule_BalancingTag
|
||||
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
||||
RuleTag string `protobuf:"bytes,20,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
|
||||
RuleTag string `protobuf:"bytes,18,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
|
||||
// List of domains for target domain matching.
|
||||
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
||||
// List of GeoIPs for target IP address matching. If this entry exists, the
|
||||
@@ -492,8 +492,6 @@ type RoutingRule struct {
|
||||
Protocol []string `protobuf:"bytes,9,rep,name=protocol,proto3" json:"protocol,omitempty"`
|
||||
Attributes map[string]string `protobuf:"bytes,15,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||
DomainMatcher string `protobuf:"bytes,17,opt,name=domain_matcher,json=domainMatcher,proto3" json:"domain_matcher,omitempty"`
|
||||
LocalGeoip []*GeoIP `protobuf:"bytes,18,rep,name=local_geoip,json=localGeoip,proto3" json:"local_geoip,omitempty"`
|
||||
LocalPortList *net.PortList `protobuf:"bytes,19,opt,name=local_port_list,json=localPortList,proto3" json:"local_port_list,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RoutingRule) Reset() {
|
||||
@@ -631,20 +629,6 @@ func (x *RoutingRule) GetDomainMatcher() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RoutingRule) GetLocalGeoip() []*GeoIP {
|
||||
if x != nil {
|
||||
return x.LocalGeoip
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *RoutingRule) GetLocalPortList() *net.PortList {
|
||||
if x != nil {
|
||||
return x.LocalPortList
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isRoutingRule_TargetTag interface {
|
||||
isRoutingRule_TargetTag()
|
||||
}
|
||||
@@ -1085,13 +1069,13 @@ var file_app_router_config_proto_rawDesc = []byte{
|
||||
0x6f, 0x53, 0x69, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x05, 0x65, 0x6e, 0x74,
|
||||
0x72, 0x79, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x53, 0x69,
|
||||
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xca, 0x06, 0x0a, 0x0b, 0x52, 0x6f,
|
||||
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xce, 0x05, 0x0a, 0x0b, 0x52, 0x6f,
|
||||
0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x25, 0x0a,
|
||||
0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x0c,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e,
|
||||
0x67, 0x54, 0x61, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x67,
|
||||
0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x12,
|
||||
0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x12,
|
||||
0x2f, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||
0x17, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||
@@ -1125,75 +1109,67 @@ var file_app_router_config_proto_rawDesc = []byte{
|
||||
0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72,
|
||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||
0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x37, 0x0a,
|
||||
0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x12, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
|
||||
0x6c, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x41, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f,
|
||||
0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
|
||||
0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61,
|
||||
0x6c, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
|
||||
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76,
|
||||
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67,
|
||||
0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75,
|
||||
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18,
|
||||
0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53,
|
||||
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||
0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||
0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f,
|
||||
0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
|
||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72,
|
||||
0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||
0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||
0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x74,
|
||||
0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
|
||||
0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||
0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78,
|
||||
0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x12,
|
||||
0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||
0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x17,
|
||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61,
|
||||
0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73,
|
||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||
0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c,
|
||||
0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
|
||||
0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08,
|
||||
0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
|
||||
0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52,
|
||||
0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54,
|
||||
0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x9b,
|
||||
0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d,
|
||||
0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||
0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61,
|
||||
0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61,
|
||||
0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75,
|
||||
0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69,
|
||||
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e,
|
||||
0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03,
|
||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67,
|
||||
0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52,
|
||||
0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72,
|
||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12,
|
||||
0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70,
|
||||
0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a,
|
||||
0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03, 0x42, 0x4f, 0x0a, 0x13,
|
||||
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||
0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65,
|
||||
0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x0f, 0x58, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x1a, 0x3d, 0x0a,
|
||||
0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
||||
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a,
|
||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42,
|
||||
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b,
|
||||
0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
|
||||
0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
|
||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||
0x65, 0x67, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73,
|
||||
0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65,
|
||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
|
||||
0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61,
|
||||
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72,
|
||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72,
|
||||
0x65, 0x67, 0x65, 0x78, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67,
|
||||
0x65, 0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
||||
0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
|
||||
0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73,
|
||||
0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63,
|
||||
0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72,
|
||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73,
|
||||
0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18,
|
||||
0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73,
|
||||
0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06,
|
||||
0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61,
|
||||
0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63,
|
||||
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e,
|
||||
0x63, 0x65, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a,
|
||||
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
||||
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e,
|
||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30,
|
||||
0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52,
|
||||
0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
||||
0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75,
|
||||
0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||
0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
||||
0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49,
|
||||
0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10,
|
||||
0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02,
|
||||
0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03,
|
||||
0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
||||
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa,
|
||||
0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
||||
0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -1244,18 +1220,16 @@ var file_app_router_config_proto_depIdxs = []int32{
|
||||
4, // 10: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
|
||||
15, // 11: xray.app.router.RoutingRule.source_port_list:type_name -> xray.common.net.PortList
|
||||
14, // 12: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
|
||||
4, // 13: xray.app.router.RoutingRule.local_geoip:type_name -> xray.app.router.GeoIP
|
||||
15, // 14: xray.app.router.RoutingRule.local_port_list:type_name -> xray.common.net.PortList
|
||||
17, // 15: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
|
||||
10, // 16: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
|
||||
1, // 17: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
||||
8, // 18: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
||||
9, // 19: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
||||
20, // [20:20] is the sub-list for method output_type
|
||||
20, // [20:20] is the sub-list for method input_type
|
||||
20, // [20:20] is the sub-list for extension type_name
|
||||
20, // [20:20] is the sub-list for extension extendee
|
||||
0, // [0:20] is the sub-list for field type_name
|
||||
17, // 13: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
|
||||
10, // 14: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
|
||||
1, // 15: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
||||
8, // 16: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
||||
9, // 17: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
||||
18, // [18:18] is the sub-list for method output_type
|
||||
18, // [18:18] is the sub-list for method input_type
|
||||
18, // [18:18] is the sub-list for extension type_name
|
||||
18, // [18:18] is the sub-list for extension extendee
|
||||
0, // [0:18] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_app_router_config_proto_init() }
|
||||
|
@@ -79,7 +79,7 @@ message RoutingRule {
|
||||
// Tag of routing balancer.
|
||||
string balancing_tag = 12;
|
||||
}
|
||||
string rule_tag = 20;
|
||||
string rule_tag = 18;
|
||||
|
||||
// List of domains for target domain matching.
|
||||
repeated Domain domain = 2;
|
||||
@@ -110,9 +110,6 @@ message RoutingRule {
|
||||
map<string, string> attributes = 15;
|
||||
|
||||
string domain_matcher = 17;
|
||||
|
||||
repeated GeoIP local_geoip = 18;
|
||||
xray.common.net.PortList local_port_list = 19;
|
||||
}
|
||||
|
||||
message BalancingRule {
|
||||
|
@@ -177,7 +177,7 @@ func TestIPOnDemand(t *testing.T) {
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
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)
|
||||
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
||||
@@ -222,7 +222,7 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
||||
IPv4Enable: true,
|
||||
IPv6Enable: true,
|
||||
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)
|
||||
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
||||
|
@@ -12,8 +12,6 @@ import (
|
||||
"github.com/xtls/xray-core/core"
|
||||
feature_stats "github.com/xtls/xray-core/features/stats"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// statsServer is an implementation of StatsService.
|
||||
@@ -32,7 +30,7 @@ func NewStatsServer(manager feature_stats.Manager) StatsServiceServer {
|
||||
func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
|
||||
c := s.stats.GetCounter(request.Name)
|
||||
if c == nil {
|
||||
return nil, status.Error(codes.NotFound, request.Name+" not found.")
|
||||
return nil, errors.New(request.Name, " not found.")
|
||||
}
|
||||
var value int64
|
||||
if request.Reset_ {
|
||||
@@ -51,7 +49,7 @@ func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*
|
||||
func (s *statsServer) GetStatsOnline(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
|
||||
c := s.stats.GetOnlineMap(request.Name)
|
||||
if c == nil {
|
||||
return nil, status.Error(codes.NotFound, request.Name+" not found.")
|
||||
return nil, errors.New(request.Name, " not found.")
|
||||
}
|
||||
value := int64(c.Count())
|
||||
return &GetStatsResponse{
|
||||
@@ -66,7 +64,7 @@ func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStat
|
||||
c := s.stats.GetOnlineMap(request.Name)
|
||||
|
||||
if c == nil {
|
||||
return nil, status.Error(codes.NotFound, request.Name+" not found.")
|
||||
return nil, errors.New(request.Name, " not found.")
|
||||
}
|
||||
|
||||
ips := make(map[string]int64)
|
||||
|
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
// OnlineMap is an implementation of stats.OnlineMap.
|
||||
type OnlineMap struct {
|
||||
value int
|
||||
ipList map[string]time.Time
|
||||
access sync.RWMutex
|
||||
lastCleanup time.Time
|
||||
@@ -24,10 +25,7 @@ func NewOnlineMap() *OnlineMap {
|
||||
|
||||
// Count implements stats.OnlineMap.
|
||||
func (c *OnlineMap) Count() int {
|
||||
c.access.RLock()
|
||||
defer c.access.RUnlock()
|
||||
|
||||
return len(c.ipList)
|
||||
return c.value
|
||||
}
|
||||
|
||||
// List implements stats.OnlineMap.
|
||||
@@ -37,18 +35,23 @@ func (c *OnlineMap) List() []string {
|
||||
|
||||
// AddIP implements stats.OnlineMap.
|
||||
func (c *OnlineMap) AddIP(ip string) {
|
||||
list := c.ipList
|
||||
|
||||
if ip == "127.0.0.1" {
|
||||
return
|
||||
}
|
||||
|
||||
if _, ok := list[ip]; !ok {
|
||||
c.access.Lock()
|
||||
c.ipList[ip] = time.Now()
|
||||
list[ip] = time.Now()
|
||||
c.access.Unlock()
|
||||
|
||||
}
|
||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
||||
c.RemoveExpiredIPs()
|
||||
list = c.RemoveExpiredIPs(list)
|
||||
c.lastCleanup = time.Now()
|
||||
}
|
||||
|
||||
c.value = len(list)
|
||||
c.ipList = list
|
||||
}
|
||||
|
||||
func (c *OnlineMap) GetKeys() []string {
|
||||
@@ -62,22 +65,24 @@ func (c *OnlineMap) GetKeys() []string {
|
||||
return keys
|
||||
}
|
||||
|
||||
func (c *OnlineMap) RemoveExpiredIPs() {
|
||||
func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.Time {
|
||||
c.access.Lock()
|
||||
defer c.access.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
for k, t := range c.ipList {
|
||||
for k, t := range list {
|
||||
diff := now.Sub(t)
|
||||
if diff.Seconds() > 20 {
|
||||
delete(c.ipList, k)
|
||||
delete(list, k)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
|
||||
list := c.ipList
|
||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
||||
c.RemoveExpiredIPs()
|
||||
list = c.RemoveExpiredIPs(list)
|
||||
c.lastCleanup = time.Now()
|
||||
}
|
||||
|
||||
|
@@ -1,152 +0,0 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.35.1
|
||||
// protoc v5.28.2
|
||||
// source: app/version/config.proto
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
CoreVersion string `protobuf:"bytes,1,opt,name=core_version,json=coreVersion,proto3" json:"core_version,omitempty"`
|
||||
MinVersion string `protobuf:"bytes,2,opt,name=min_version,json=minVersion,proto3" json:"min_version,omitempty"`
|
||||
MaxVersion string `protobuf:"bytes,3,opt,name=max_version,json=maxVersion,proto3" json:"max_version,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
*x = Config{}
|
||||
mi := &file_app_version_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Config) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Config) ProtoMessage() {}
|
||||
|
||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_app_version_config_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||
func (*Config) Descriptor() ([]byte, []int) {
|
||||
return file_app_version_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Config) GetCoreVersion() string {
|
||||
if x != nil {
|
||||
return x.CoreVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetMinVersion() string {
|
||||
if x != nil {
|
||||
return x.MinVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetMaxVersion() string {
|
||||
if x != nil {
|
||||
return x.MaxVersion
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_app_version_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_app_version_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x18, 0x61, 0x70, 0x70, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x6f,
|
||||
0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x78, 0x72, 0x61, 0x79,
|
||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x6d, 0x0a, 0x06,
|
||||
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x72, 0x65, 0x5f, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f,
|
||||
0x72, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x69, 0x6e,
|
||||
0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
|
||||
0x6d, 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x61,
|
||||
0x78, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0a, 0x6d, 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x52, 0x0a, 0x14, 0x63,
|
||||
0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x76, 0x65, 0x72, 0x73,
|
||||
0x69, 0x6f, 0x6e, 0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65,
|
||||
0x2f, 0x61, 0x70, 0x70, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0xaa, 0x02, 0x10, 0x58,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_app_version_config_proto_rawDescOnce sync.Once
|
||||
file_app_version_config_proto_rawDescData = file_app_version_config_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_app_version_config_proto_rawDescGZIP() []byte {
|
||||
file_app_version_config_proto_rawDescOnce.Do(func() {
|
||||
file_app_version_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_app_version_config_proto_rawDescData)
|
||||
})
|
||||
return file_app_version_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_app_version_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
|
||||
var file_app_version_config_proto_goTypes = []any{
|
||||
(*Config)(nil), // 0: xray.app.version.Config
|
||||
}
|
||||
var file_app_version_config_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
0, // [0:0] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_app_version_config_proto_init() }
|
||||
func file_app_version_config_proto_init() {
|
||||
if File_app_version_config_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_app_version_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 1,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_app_version_config_proto_goTypes,
|
||||
DependencyIndexes: file_app_version_config_proto_depIdxs,
|
||||
MessageInfos: file_app_version_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_app_version_config_proto = out.File
|
||||
file_app_version_config_proto_rawDesc = nil
|
||||
file_app_version_config_proto_goTypes = nil
|
||||
file_app_version_config_proto_depIdxs = nil
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package xray.app.version;
|
||||
option csharp_namespace = "Xray.App.Version";
|
||||
option go_package = "github.com/xtls/xray-core/app/version";
|
||||
option java_package = "com.xray.app.version";
|
||||
option java_multiple_files = true;
|
||||
|
||||
|
||||
message Config {
|
||||
string core_version = 1;
|
||||
string min_version = 2;
|
||||
string max_version = 3;
|
||||
}
|
@@ -1,77 +0,0 @@
|
||||
package version
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Version struct {
|
||||
config *Config
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func New(ctx context.Context, config *Config) (*Version, error) {
|
||||
if config.MinVersion != "" {
|
||||
result, err := compareVersions(config.MinVersion, config.CoreVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result > 0 {
|
||||
return nil, errors.New("this config must be run on version ", config.MinVersion, " or higher")
|
||||
}
|
||||
}
|
||||
if config.MaxVersion != "" {
|
||||
result, err := compareVersions(config.MaxVersion, config.CoreVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result < 0 {
|
||||
return nil, errors.New("this config should be run on version ", config.MaxVersion, " or lower")
|
||||
}
|
||||
}
|
||||
return &Version{config: config, ctx: ctx}, nil
|
||||
}
|
||||
|
||||
func compareVersions(v1, v2 string) (int, error) {
|
||||
// Split version strings into components
|
||||
v1Parts := strings.Split(v1, ".")
|
||||
v2Parts := strings.Split(v2, ".")
|
||||
|
||||
// Pad shorter versions with zeros
|
||||
for len(v1Parts) < len(v2Parts) {
|
||||
v1Parts = append(v1Parts, "0")
|
||||
}
|
||||
for len(v2Parts) < len(v1Parts) {
|
||||
v2Parts = append(v2Parts, "0")
|
||||
}
|
||||
|
||||
// Compare each part
|
||||
for i := 0; i < len(v1Parts); i++ {
|
||||
// Convert parts to integers
|
||||
n1, err := strconv.Atoi(v1Parts[i])
|
||||
if err != nil {
|
||||
return 0, errors.New("invalid version component ", v1Parts[i], " in ", v1)
|
||||
}
|
||||
n2, err := strconv.Atoi(v2Parts[i])
|
||||
if err != nil {
|
||||
return 0, errors.New("invalid version component ", v2Parts[i], " in ", v2)
|
||||
}
|
||||
|
||||
if n1 < n2 {
|
||||
return -1, nil // v1 < v2
|
||||
}
|
||||
if n1 > n2 {
|
||||
return 1, nil // v1 > v2
|
||||
}
|
||||
}
|
||||
return 0, nil // v1 == v2
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return New(ctx, config.(*Config))
|
||||
}))
|
||||
}
|
@@ -13,21 +13,8 @@ const (
|
||||
Size = 8192
|
||||
)
|
||||
|
||||
var ErrBufferFull = errors.New("buffer is full")
|
||||
|
||||
var zero = [Size * 10]byte{0}
|
||||
|
||||
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
|
||||
// the buffer into an internal buffer pool, in order to recreate a buffer more
|
||||
// quickly.
|
||||
@@ -35,11 +22,11 @@ type Buffer struct {
|
||||
v []byte
|
||||
start int32
|
||||
end int32
|
||||
ownership ownership
|
||||
unmanaged bool
|
||||
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 {
|
||||
buf := pool.Get().([]byte)
|
||||
if cap(buf) >= Size {
|
||||
@@ -53,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 {
|
||||
if cap(b) < Size {
|
||||
panic("Invalid buffer")
|
||||
@@ -70,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 {
|
||||
return &Buffer{
|
||||
v: 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.
|
||||
func StackNew() Buffer {
|
||||
buf := pool.Get().([]byte)
|
||||
@@ -94,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.
|
||||
func (b *Buffer) Release() {
|
||||
if b == nil || b.v == nil || b.ownership == unmanaged {
|
||||
if b == nil || b.v == nil || b.unmanaged {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -112,14 +91,9 @@ func (b *Buffer) Release() {
|
||||
b.v = nil
|
||||
b.Clear()
|
||||
|
||||
switch b.ownership {
|
||||
case managed:
|
||||
if cap(p) == Size {
|
||||
pool.Put(p)
|
||||
}
|
||||
case bytespools:
|
||||
bytespool.Free(p)
|
||||
}
|
||||
b.UDP = nil
|
||||
}
|
||||
|
||||
@@ -154,7 +128,6 @@ func (b *Buffer) Extend(n int32) []byte {
|
||||
}
|
||||
ext := b.v[b.end:end]
|
||||
b.end = end
|
||||
copy(ext, zero[:])
|
||||
return ext
|
||||
}
|
||||
|
||||
@@ -203,7 +176,6 @@ func (b *Buffer) Check() {
|
||||
|
||||
// Resize cuts the buffer at the given position.
|
||||
func (b *Buffer) Resize(from, to int32) {
|
||||
oldEnd := b.end
|
||||
if from < 0 {
|
||||
from += b.Len()
|
||||
}
|
||||
@@ -216,9 +188,6 @@ func (b *Buffer) Resize(from, to int32) {
|
||||
b.end = b.start + to
|
||||
b.start += from
|
||||
b.Check()
|
||||
if b.end > oldEnd {
|
||||
copy(b.v[oldEnd:b.end], zero[:])
|
||||
}
|
||||
}
|
||||
|
||||
// Advance cuts the buffer at the given position.
|
||||
@@ -246,6 +215,13 @@ func (b *Buffer) Cap() int32 {
|
||||
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.
|
||||
func (b *Buffer) IsEmpty() bool {
|
||||
return b.Len() == 0
|
||||
@@ -260,16 +236,13 @@ func (b *Buffer) IsFull() bool {
|
||||
func (b *Buffer) Write(data []byte) (int, error) {
|
||||
nBytes := copy(b.v[b.end:], data)
|
||||
b.end += int32(nBytes)
|
||||
if nBytes < len(data) {
|
||||
return nBytes, ErrBufferFull
|
||||
}
|
||||
return nBytes, nil
|
||||
}
|
||||
|
||||
// WriteByte writes a single byte into the buffer.
|
||||
func (b *Buffer) WriteByte(v byte) error {
|
||||
if b.IsFull() {
|
||||
return ErrBufferFull
|
||||
return errors.New("buffer full")
|
||||
}
|
||||
b.v[b.end] = v
|
||||
b.end++
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -37,12 +36,12 @@ func AllEqual(expected error, actual error) bool {
|
||||
return false
|
||||
}
|
||||
for _, err := range errs {
|
||||
if !errors.Is(err, expected) {
|
||||
if err != expected {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return errors.Is(errs, expected)
|
||||
return errs == expected
|
||||
}
|
||||
}
|
||||
|
@@ -173,7 +173,6 @@ type ClientWorker struct {
|
||||
sessionManager *SessionManager
|
||||
link transport.Link
|
||||
done *done.Instance
|
||||
timer *time.Ticker
|
||||
strategy ClientStrategy
|
||||
}
|
||||
|
||||
@@ -188,7 +187,6 @@ func NewClientWorker(stream transport.Link, s ClientStrategy) (*ClientWorker, er
|
||||
sessionManager: NewSessionManager(),
|
||||
link: stream,
|
||||
done: done.New(),
|
||||
timer: time.NewTicker(time.Second * 16),
|
||||
strategy: s,
|
||||
}
|
||||
|
||||
@@ -211,12 +209,9 @@ func (m *ClientWorker) Closed() bool {
|
||||
return m.done.Done()
|
||||
}
|
||||
|
||||
func (m *ClientWorker) GetTimer() *time.Ticker {
|
||||
return m.timer
|
||||
}
|
||||
|
||||
func (m *ClientWorker) monitor() {
|
||||
defer m.timer.Stop()
|
||||
timer := time.NewTicker(time.Second * 16)
|
||||
defer timer.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
@@ -225,7 +220,7 @@ func (m *ClientWorker) monitor() {
|
||||
common.Close(m.link.Writer)
|
||||
common.Interrupt(m.link.Reader)
|
||||
return
|
||||
case <-m.timer.C:
|
||||
case <-timer.C:
|
||||
size := m.sessionManager.Size()
|
||||
if size == 0 && m.sessionManager.CloseIfNoSession() {
|
||||
common.Must(m.done.Close())
|
||||
@@ -281,8 +276,6 @@ func (m *ClientWorker) IsClosing() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsFull returns true if this ClientWorker is unable to accept more connections.
|
||||
// it might be because it is closing, or the number of connections has reached the limit.
|
||||
func (m *ClientWorker) IsFull() bool {
|
||||
if m.IsClosing() || m.Closed() {
|
||||
return true
|
||||
@@ -296,12 +289,12 @@ func (m *ClientWorker) IsFull() bool {
|
||||
}
|
||||
|
||||
func (m *ClientWorker) Dispatch(ctx context.Context, link *transport.Link) bool {
|
||||
if m.IsFull() {
|
||||
if m.IsFull() || m.Closed() {
|
||||
return false
|
||||
}
|
||||
|
||||
sm := m.sessionManager
|
||||
s := sm.Allocate(&m.strategy)
|
||||
s := sm.Allocate()
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
|
@@ -201,12 +201,11 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
|
||||
transferType: protocol.TransferTypePacket,
|
||||
XUDP: x,
|
||||
}
|
||||
go handle(ctx, x.Mux, w.link.Writer)
|
||||
x.Status = Active
|
||||
if !w.sessionManager.Add(x.Mux) {
|
||||
x.Mux.Close(false)
|
||||
return errors.New("failed to add new session")
|
||||
}
|
||||
go handle(ctx, x.Mux, w.link.Writer)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -227,23 +226,18 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
|
||||
if meta.Target.Network == net.Network_UDP {
|
||||
s.transferType = protocol.TransferTypePacket
|
||||
}
|
||||
if !w.sessionManager.Add(s) {
|
||||
s.Close(false)
|
||||
return errors.New("failed to add new session")
|
||||
}
|
||||
w.sessionManager.Add(s)
|
||||
go handle(ctx, s, w.link.Writer)
|
||||
if !meta.Option.Has(OptionData) {
|
||||
return nil
|
||||
}
|
||||
|
||||
rr := s.NewReader(reader, &meta.Target)
|
||||
err = buf.Copy(rr, s.output)
|
||||
|
||||
if err != nil && buf.IsWriteError(err) {
|
||||
s.Close(false)
|
||||
return buf.Copy(rr, buf.Discard)
|
||||
if err := buf.Copy(rr, s.output); err != nil {
|
||||
buf.Copy(rr, buf.Discard)
|
||||
return s.Close(false)
|
||||
}
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.BufferedReader) error {
|
||||
@@ -310,11 +304,10 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
|
||||
}
|
||||
|
||||
func (w *ServerWorker) run(ctx context.Context) {
|
||||
reader := &buf.BufferedReader{Reader: w.link.Reader}
|
||||
input := w.link.Reader
|
||||
reader := &buf.BufferedReader{Reader: input}
|
||||
|
||||
defer w.sessionManager.Close()
|
||||
defer common.Close(w.link.Writer)
|
||||
defer common.Interrupt(w.link.Reader)
|
||||
|
||||
for {
|
||||
select {
|
||||
@@ -325,6 +318,7 @@ func (w *ServerWorker) run(ctx context.Context) {
|
||||
if err != nil {
|
||||
if errors.Cause(err) != io.EOF {
|
||||
errors.LogInfoInner(ctx, err, "unexpected EOF")
|
||||
common.Interrupt(input)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@@ -50,14 +50,11 @@ func (m *SessionManager) Count() int {
|
||||
return int(m.count)
|
||||
}
|
||||
|
||||
func (m *SessionManager) Allocate(Strategy *ClientStrategy) *Session {
|
||||
func (m *SessionManager) Allocate() *Session {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
MaxConcurrency := int(Strategy.MaxConcurrency)
|
||||
MaxConnection := uint16(Strategy.MaxConnection)
|
||||
|
||||
if m.closed || (MaxConcurrency > 0 && len(m.sessions) >= MaxConcurrency) || (MaxConnection > 0 && m.count >= MaxConnection) {
|
||||
if m.closed {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@@ -9,7 +9,7 @@ import (
|
||||
func TestSessionManagerAdd(t *testing.T) {
|
||||
m := NewSessionManager()
|
||||
|
||||
s := m.Allocate(&ClientStrategy{})
|
||||
s := m.Allocate()
|
||||
if s.ID != 1 {
|
||||
t.Error("id: ", s.ID)
|
||||
}
|
||||
@@ -17,7 +17,7 @@ func TestSessionManagerAdd(t *testing.T) {
|
||||
t.Error("size: ", m.Size())
|
||||
}
|
||||
|
||||
s = m.Allocate(&ClientStrategy{})
|
||||
s = m.Allocate()
|
||||
if s.ID != 2 {
|
||||
t.Error("id: ", s.ID)
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func TestSessionManagerAdd(t *testing.T) {
|
||||
|
||||
func TestSessionManagerClose(t *testing.T) {
|
||||
m := NewSessionManager()
|
||||
s := m.Allocate(&ClientStrategy{})
|
||||
s := m.Allocate()
|
||||
|
||||
if m.CloseIfNoSession() {
|
||||
t.Error("able to close")
|
||||
|
@@ -3,7 +3,6 @@ package filesystem
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/platform"
|
||||
@@ -29,13 +28,6 @@ func ReadAsset(file string) ([]byte, error) {
|
||||
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 {
|
||||
bytes, err := ReadFile(src)
|
||||
if err != nil {
|
||||
|
@@ -21,7 +21,7 @@ func GetToolLocation(file string) string {
|
||||
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 {
|
||||
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
||||
defPath := filepath.Join(assetPath, file)
|
||||
@@ -42,9 +42,3 @@ func GetAssetLocation(file string) string {
|
||||
// asset not found, let the caller throw out the error
|
||||
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"
|
||||
ToolLocation = "xray.location.tool"
|
||||
AssetLocation = "xray.location.asset"
|
||||
CertLocation = "xray.location.cert"
|
||||
|
||||
UseReadV = "xray.buf.readv"
|
||||
UseFreedomSplice = "xray.buf.splice"
|
||||
|
@@ -19,14 +19,8 @@ func GetToolLocation(file string) string {
|
||||
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 {
|
||||
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
||||
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"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var ErrProtoNeedMoreData = errors.New("protocol matches, but need more data to complete sniffing")
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package quic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/tls"
|
||||
@@ -10,8 +11,8 @@ import (
|
||||
"github.com/quic-go/quic-go/quicvarint"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"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/protocol"
|
||||
ptls "github.com/xtls/xray-core/common/protocol/tls"
|
||||
"golang.org/x/crypto/hkdf"
|
||||
)
|
||||
@@ -46,17 +47,22 @@ var (
|
||||
errNotQuicInitial = errors.New("not initial packet")
|
||||
)
|
||||
|
||||
func SniffQUIC(b []byte) (*SniffHeader, error) {
|
||||
if len(b) == 0 {
|
||||
return nil, common.ErrNoClue
|
||||
func SniffQUIC(b []byte) (resultReturn *SniffHeader, errorReturn error) {
|
||||
// In extremely rare cases, this sniffer may cause slice error
|
||||
// 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
|
||||
cryptoLen := int32(0)
|
||||
cryptoDataBuf := buf.NewWithSize(32767)
|
||||
defer cryptoDataBuf.Release()
|
||||
cache := buf.New()
|
||||
defer cache.Release()
|
||||
cryptoLen := 0
|
||||
cryptoData := bytespool.Alloc(int32(len(b)))
|
||||
defer bytespool.Free(cryptoData)
|
||||
|
||||
// Parse QUIC packets
|
||||
for len(b) > 0 {
|
||||
@@ -99,7 +105,6 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
||||
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)
|
||||
if err != nil || tokenLen > uint64(len(b)) {
|
||||
return nil, errNotQuic
|
||||
@@ -108,16 +113,11 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
||||
if _, err = buffer.ReadBytes(int32(tokenLen)); err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
}
|
||||
|
||||
packetLen, err := quicvarint.Read(buffer)
|
||||
if err != nil {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
// packetLen is impossible to be shorter than this
|
||||
if packetLen < 4 {
|
||||
return nil, errNotQuic
|
||||
}
|
||||
|
||||
hdrLen := len(b) - int(buffer.Len())
|
||||
if len(b) < hdrLen+int(packetLen) {
|
||||
@@ -130,6 +130,9 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
||||
continue
|
||||
}
|
||||
|
||||
origPNBytes := make([]byte, 4)
|
||||
copy(origPNBytes, b[hdrLen:hdrLen+4])
|
||||
|
||||
var salt []byte
|
||||
if versionNumber == version1 {
|
||||
salt = quicSalt
|
||||
@@ -144,34 +147,44 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cache.Clear()
|
||||
cache := buf.New()
|
||||
defer cache.Release()
|
||||
|
||||
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
|
||||
packetNumberLength := int(b[0]&0x3 + 1)
|
||||
for i := range packetNumberLength {
|
||||
for i := range b[hdrLen : hdrLen+4] {
|
||||
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)
|
||||
iv := hkdfExpandLabel(crypto.SHA256, secret, []byte{}, "quic iv", 12)
|
||||
cipher := AEADAESGCMTLS13(key, iv)
|
||||
|
||||
nonce := cache.Extend(int32(cipher.NonceSize()))
|
||||
_, err = buffer.Read(nonce[len(nonce)-packetNumberLength:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
extHdrLen := hdrLen + packetNumberLength
|
||||
data := b[extHdrLen : int(packetLen)+hdrLen]
|
||||
binary.BigEndian.PutUint64(nonce[len(nonce)-8:], uint64(packetNumber))
|
||||
decrypted, err := cipher.Open(b[extHdrLen:extHdrLen], nonce, data, b[:extHdrLen])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
buffer = buf.FromBytes(decrypted)
|
||||
for !buffer.IsEmpty() {
|
||||
frameType, _ := buffer.ReadByte()
|
||||
for i := 0; !buffer.IsEmpty(); i++ {
|
||||
frameType := byte(0x0) // Default to PADDING frame
|
||||
for frameType == 0x0 && !buffer.IsEmpty() {
|
||||
frameType, _ = buffer.ReadByte()
|
||||
}
|
||||
@@ -220,15 +233,16 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
||||
if err != nil || length > uint64(buffer.Len()) {
|
||||
return nil, io.ErrUnexpectedEOF
|
||||
}
|
||||
currentCryptoLen := int32(offset + length)
|
||||
if cryptoLen < currentCryptoLen {
|
||||
if cryptoDataBuf.Cap() < currentCryptoLen {
|
||||
return nil, io.ErrShortBuffer
|
||||
if cryptoLen < int(offset+length) {
|
||||
cryptoLen = int(offset + length)
|
||||
if len(cryptoData) < cryptoLen {
|
||||
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
|
||||
}
|
||||
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{}
|
||||
err = ptls.ReadClientHello(cryptoDataBuf.BytesRange(0, cryptoLen), tlsHdr)
|
||||
err = ptls.ReadClientHello(cryptoData[:cryptoLen], tlsHdr)
|
||||
if err != nil {
|
||||
// The crypto data may have not been fully recovered in current packets,
|
||||
// So we continue to sniff rest packets.
|
||||
@@ -262,8 +276,7 @@ func SniffQUIC(b []byte) (*SniffHeader, error) {
|
||||
}
|
||||
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, protocol.ErrProtoNeedMoreData
|
||||
return nil, common.ErrNoClue
|
||||
}
|
||||
|
||||
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 (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/protocol"
|
||||
)
|
||||
|
||||
type SniffHeader struct {
|
||||
@@ -59,6 +59,9 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
|
||||
}
|
||||
data = data[1+compressionMethodsLen:]
|
||||
|
||||
if len(data) == 0 {
|
||||
return errNotClientHello
|
||||
}
|
||||
if len(data) < 2 {
|
||||
return errNotClientHello
|
||||
}
|
||||
@@ -101,21 +104,13 @@ func ReadClientHello(data []byte, h *SniffHeader) error {
|
||||
return errNotClientHello
|
||||
}
|
||||
if nameType == 0 {
|
||||
// QUIC separated across packets
|
||||
// May cause the serverName to be incomplete
|
||||
b := byte(0)
|
||||
for _, b = range d[:nameLen] {
|
||||
if b <= ' ' {
|
||||
return protocol.ErrProtoNeedMoreData
|
||||
}
|
||||
}
|
||||
serverName := string(d[:nameLen])
|
||||
// An SNI value may not include a
|
||||
// trailing dot. See
|
||||
// https://tools.ietf.org/html/rfc6066#section-3.
|
||||
if b == '.' {
|
||||
if strings.HasSuffix(serverName, ".") {
|
||||
return errNotClientHello
|
||||
}
|
||||
serverName := string(d[:nameLen])
|
||||
h.domain = serverName
|
||||
return nil
|
||||
}
|
||||
|
@@ -36,8 +36,6 @@ func ExportIDToError(ctx context.Context) errors.ExportOption {
|
||||
type Inbound struct {
|
||||
// Source address of the inbound connection.
|
||||
Source net.Destination
|
||||
// Local address of the inbound connection.
|
||||
Local net.Destination
|
||||
// Gateway address.
|
||||
Gateway net.Destination
|
||||
// Tag of the inbound proxy that handles the connection.
|
||||
|
@@ -67,9 +67,9 @@ func (t *ActivityTimer) SetTimeout(timeout time.Duration) {
|
||||
t.checkTask.Close()
|
||||
}
|
||||
t.checkTask = checkTask
|
||||
t.Unlock()
|
||||
t.Update()
|
||||
common.Must(checkTask.Start())
|
||||
t.Unlock()
|
||||
}
|
||||
|
||||
func CancelAfterInactivity(ctx context.Context, cancel context.CancelFunc, timeout time.Duration) *ActivityTimer {
|
||||
|
@@ -1,112 +0,0 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// TypedSyncMap is a wrapper of sync.Map that provides type-safe for keys and values.
|
||||
// No need to use type assertions every time, so you can have more time to enjoy other things like GochiUsa
|
||||
// If sync.Map methods returned nil, it will return the zero value of the type V.
|
||||
type TypedSyncMap[K, V any] struct {
|
||||
syncMap *sync.Map
|
||||
}
|
||||
|
||||
// NewTypedSyncMap creates a new TypedSyncMap
|
||||
// K is key type, V is value type
|
||||
// It is recommended to use pointer types for V because sync.Map might return nil
|
||||
// If sync.Map methods really returned nil, it will return the zero value of the type V
|
||||
func NewTypedSyncMap[K any, V any]() *TypedSyncMap[K, V] {
|
||||
return &TypedSyncMap[K, V]{
|
||||
syncMap: &sync.Map{},
|
||||
}
|
||||
}
|
||||
|
||||
// Clear deletes all the entries, resulting in an empty Map.
|
||||
func (m *TypedSyncMap[K, V]) Clear() {
|
||||
m.syncMap.Clear()
|
||||
}
|
||||
|
||||
// CompareAndDelete deletes the entry for key if its value is equal to old.
|
||||
// The old value must be of a comparable type.
|
||||
//
|
||||
// If there is no current value for key in the map, CompareAndDelete
|
||||
// returns false (even if the old value is the nil interface value).
|
||||
func (m *TypedSyncMap[K, V]) CompareAndDelete(key K, old V) (deleted bool) {
|
||||
return m.syncMap.CompareAndDelete(key, old)
|
||||
}
|
||||
|
||||
// CompareAndSwap swaps the old and new values for key
|
||||
// if the value stored in the map is equal to old.
|
||||
// The old value must be of a comparable type.
|
||||
func (m *TypedSyncMap[K, V]) CompareAndSwap(key K, old V, new V) (swapped bool) {
|
||||
return m.syncMap.CompareAndSwap(key, old, new)
|
||||
}
|
||||
|
||||
// Delete deletes the value for a key.
|
||||
func (m *TypedSyncMap[K, V]) Delete(key K) {
|
||||
m.syncMap.Delete(key)
|
||||
}
|
||||
|
||||
// Load returns the value stored in the map for a key, or nil if no
|
||||
// value is present.
|
||||
// The ok result indicates whether value was found in the map.
|
||||
func (m *TypedSyncMap[K, V]) Load(key K) (value V, ok bool) {
|
||||
anyValue, ok := m.syncMap.Load(key)
|
||||
// anyValue might be nil
|
||||
if anyValue != nil {
|
||||
value = anyValue.(V)
|
||||
}
|
||||
return value, ok
|
||||
}
|
||||
|
||||
// LoadAndDelete deletes the value for a key, returning the previous value if any.
|
||||
// The loaded result reports whether the key was present.
|
||||
func (m *TypedSyncMap[K, V]) LoadAndDelete(key K) (value V, loaded bool) {
|
||||
anyValue, loaded := m.syncMap.LoadAndDelete(key)
|
||||
if anyValue != nil {
|
||||
value = anyValue.(V)
|
||||
}
|
||||
return value, loaded
|
||||
}
|
||||
|
||||
// LoadOrStore returns the existing value for the key if present.
|
||||
// Otherwise, it stores and returns the given value.
|
||||
// The loaded result is true if the value was loaded, false if stored.
|
||||
func (m *TypedSyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
|
||||
anyActual, loaded := m.syncMap.LoadOrStore(key, value)
|
||||
if anyActual != nil {
|
||||
actual = anyActual.(V)
|
||||
}
|
||||
return actual, loaded
|
||||
}
|
||||
|
||||
// Range calls f sequentially for each key and value present in the map.
|
||||
// If f returns false, range stops the iteration.
|
||||
//
|
||||
// Range does not necessarily correspond to any consistent snapshot of the Map's
|
||||
// contents: no key will be visited more than once, but if the value for any key
|
||||
// is stored or deleted concurrently (including by f), Range may reflect any
|
||||
// mapping for that key from any point during the Range call. Range does not
|
||||
// block other methods on the receiver; even f itself may call any method on m.
|
||||
//
|
||||
// Range may be O(N) with the number of elements in the map even if f returns
|
||||
// false after a constant number of calls.
|
||||
func (m *TypedSyncMap[K, V]) Range(f func(key K, value V) bool) {
|
||||
m.syncMap.Range(func(key, value any) bool {
|
||||
return f(key.(K), value.(V))
|
||||
})
|
||||
}
|
||||
|
||||
// Store sets the value for a key.
|
||||
func (m *TypedSyncMap[K, V]) Store(key K, value V) {
|
||||
m.syncMap.Store(key, value)
|
||||
}
|
||||
|
||||
// Swap swaps the value for a key and returns the previous value if any. The loaded result reports whether the key was present.
|
||||
func (m *TypedSyncMap[K, V]) Swap(key K, value V) (previous V, loaded bool) {
|
||||
anyPrevious, loaded := m.syncMap.Swap(key, value)
|
||||
if anyPrevious != nil {
|
||||
previous = anyPrevious.(V)
|
||||
}
|
||||
return previous, loaded
|
||||
}
|
@@ -18,7 +18,7 @@ import (
|
||||
|
||||
var (
|
||||
Version_x byte = 25
|
||||
Version_y byte = 8
|
||||
Version_y byte = 3
|
||||
Version_z byte = 3
|
||||
)
|
||||
|
||||
|
@@ -90,11 +90,6 @@ type Instance struct {
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// Instance state
|
||||
func (server *Instance) IsRunning() bool {
|
||||
return server.running
|
||||
}
|
||||
|
||||
func AddInboundHandler(server *Instance, config *InboundHandlerConfig) error {
|
||||
inboundManager := server.GetFeature(inbound.ManagerType()).(inbound.Manager)
|
||||
rawHandler, err := CreateObject(server, config)
|
||||
|
@@ -21,7 +21,11 @@ type Client interface {
|
||||
features.Feature
|
||||
|
||||
// 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.
|
||||
@@ -34,32 +38,12 @@ func ClientType() interface{} {
|
||||
// ErrEmptyResponse indicates that DNS query succeeded but no answer was returned.
|
||||
var ErrEmptyResponse = errors.New("empty response")
|
||||
|
||||
const DefaultTTL = 300
|
||||
|
||||
type RCodeError uint16
|
||||
|
||||
func (e RCodeError) Error() string {
|
||||
return serial.Concat("rcode: ", uint16(e))
|
||||
}
|
||||
|
||||
func (RCodeError) IP() net.IP {
|
||||
panic("Calling IP() on a RCodeError.")
|
||||
}
|
||||
|
||||
func (RCodeError) Domain() string {
|
||||
panic("Calling Domain() on a RCodeError.")
|
||||
}
|
||||
|
||||
func (RCodeError) Family() net.AddressFamily {
|
||||
panic("Calling Family() on a RCodeError.")
|
||||
}
|
||||
|
||||
func (e RCodeError) String() string {
|
||||
return e.Error()
|
||||
}
|
||||
|
||||
var _ net.Address = (*RCodeError)(nil)
|
||||
|
||||
func RCodeFromError(err error) uint16 {
|
||||
if err == nil {
|
||||
return 0
|
||||
|
@@ -20,44 +20,41 @@ func (*Client) Start() error { return nil }
|
||||
func (*Client) Close() error { return nil }
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, err
|
||||
}
|
||||
parsedIPs := make([]net.IP, 0, len(ips))
|
||||
ipv4 := make([]net.IP, 0, len(ips))
|
||||
ipv6 := make([]net.IP, 0, len(ips))
|
||||
for _, ip := range ips {
|
||||
parsed := net.IPAddress(ip)
|
||||
if parsed == nil {
|
||||
continue
|
||||
if parsed != nil {
|
||||
parsedIPs = append(parsedIPs, parsed.IP())
|
||||
}
|
||||
parsedIP := parsed.IP()
|
||||
parsedIPs = append(parsedIPs, parsedIP)
|
||||
|
||||
if len(parsedIP) == net.IPv4len {
|
||||
ipv4 = append(ipv4, parsedIP)
|
||||
} else {
|
||||
ipv6 = append(ipv6, parsedIP)
|
||||
if len(ip) == net.IPv4len {
|
||||
ipv4 = append(ipv4, ip)
|
||||
}
|
||||
if len(ip) == net.IPv6len {
|
||||
ipv6 = append(ipv6, ip)
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case option.IPv4Enable && option.IPv6Enable:
|
||||
if len(parsedIPs) > 0 {
|
||||
return parsedIPs, dns.DefaultTTL, nil
|
||||
return parsedIPs, nil
|
||||
}
|
||||
case option.IPv4Enable:
|
||||
if len(ipv4) > 0 {
|
||||
return ipv4, dns.DefaultTTL, nil
|
||||
return ipv4, nil
|
||||
}
|
||||
case option.IPv6Enable:
|
||||
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.
|
||||
|
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/features"
|
||||
)
|
||||
|
||||
@@ -16,10 +15,6 @@ type Handler interface {
|
||||
common.Runnable
|
||||
// The tag of this handler.
|
||||
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.
|
||||
GetRandomInboundProxy() (interface{}, net.Port, int)
|
||||
@@ -37,9 +32,6 @@ type Manager interface {
|
||||
|
||||
// RemoveHandler removes a handler from Manager.
|
||||
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.
|
||||
|
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/features"
|
||||
"github.com/xtls/xray-core/transport"
|
||||
)
|
||||
@@ -16,8 +15,6 @@ type Handler interface {
|
||||
common.Runnable
|
||||
Tag() string
|
||||
Dispatch(ctx context.Context, link *transport.Link)
|
||||
SenderSettings() *serial.TypedMessage
|
||||
ProxySettings() *serial.TypedMessage
|
||||
}
|
||||
|
||||
type HandlerSelector interface {
|
||||
@@ -38,9 +35,6 @@ type Manager interface {
|
||||
|
||||
// RemoveHandler removes a handler from outbound.Manager.
|
||||
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.
|
||||
|
@@ -23,12 +23,6 @@ type Context interface {
|
||||
// GetTargetPort returns the target port of the connection.
|
||||
GetTargetPort() net.Port
|
||||
|
||||
// GetLocalIPs returns the local IPs bound to the connection.
|
||||
GetLocalIPs() []net.IP
|
||||
|
||||
// GetLocalPort returns the local port of the connection.
|
||||
GetLocalPort() net.Port
|
||||
|
||||
// GetTargetDomain returns the target domain of the connection, if exists.
|
||||
GetTargetDomain() string
|
||||
|
||||
|
@@ -23,7 +23,7 @@ func (ctx *ResolvableContext) GetTargetIPs() []net.IP {
|
||||
}
|
||||
|
||||
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,
|
||||
IPv6Enable: true,
|
||||
FakeEnable: false,
|
||||
|
@@ -28,13 +28,12 @@ func (ctx *Context) GetSourceIPs() []net.IP {
|
||||
if ctx.Inbound == nil || !ctx.Inbound.Source.IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if ctx.Inbound.Source.Address.Family().IsIP() {
|
||||
return []net.IP{ctx.Inbound.Source.Address.IP()}
|
||||
dest := ctx.Inbound.Source
|
||||
if dest.Address.Family().IsDomain() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
return []net.IP{dest.Address.IP()}
|
||||
}
|
||||
|
||||
// GetSourcePort implements routing.Context.
|
||||
@@ -66,27 +65,6 @@ func (ctx *Context) GetTargetPort() net.Port {
|
||||
return ctx.Outbound.Target.Port
|
||||
}
|
||||
|
||||
// GetLocalIPs implements routing.Context.
|
||||
func (ctx *Context) GetLocalIPs() []net.IP {
|
||||
if ctx.Inbound == nil || !ctx.Inbound.Local.IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if ctx.Inbound.Local.Address.Family().IsIP() {
|
||||
return []net.IP{ctx.Inbound.Local.Address.IP()}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetLocalPort implements routing.Context.
|
||||
func (ctx *Context) GetLocalPort() net.Port {
|
||||
if ctx.Inbound == nil || !ctx.Inbound.Local.IsValid() {
|
||||
return 0
|
||||
}
|
||||
return ctx.Inbound.Local.Port
|
||||
}
|
||||
|
||||
// GetTargetDomain implements routing.Context.
|
||||
func (ctx *Context) GetTargetDomain() string {
|
||||
if ctx.Outbound == nil || !ctx.Outbound.Target.IsValid() {
|
||||
|
55
go.mod
55
go.mod
@@ -3,56 +3,59 @@ module github.com/xtls/xray-core
|
||||
go 1.24
|
||||
|
||||
require (
|
||||
github.com/cloudflare/circl v1.6.1
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0
|
||||
github.com/cloudflare/circl v1.6.0
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
||||
github.com/golang/mock v1.7.0-rc.1
|
||||
github.com/google/go-cmp v0.7.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/miekg/dns v1.1.68
|
||||
github.com/miekg/dns v1.1.63
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pires/go-proxyproto v0.8.1
|
||||
github.com/quic-go/quic-go v0.54.0
|
||||
github.com/refraction-networking/utls v1.8.0
|
||||
github.com/pires/go-proxyproto v0.8.0
|
||||
github.com/quic-go/quic-go v0.50.0
|
||||
github.com/refraction-networking/utls v1.6.7
|
||||
github.com/sagernet/sing v0.5.1
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||
github.com/vishvananda/netlink v1.3.1
|
||||
github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.41.0
|
||||
golang.org/x/net v0.43.0
|
||||
golang.org/x/sync v0.16.0
|
||||
golang.org/x/sys v0.35.0
|
||||
golang.org/x/crypto v0.35.0
|
||||
golang.org/x/net v0.35.0
|
||||
golang.org/x/sync v0.11.0
|
||||
golang.org/x/sys v0.30.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
google.golang.org/grpc v1.74.2
|
||||
google.golang.org/protobuf v1.36.7
|
||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
||||
google.golang.org/grpc v1.70.0
|
||||
google.golang.org/protobuf v1.36.5
|
||||
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0
|
||||
h12.io/socks v1.0.3
|
||||
lukechampine.com/blake3 v1.4.1
|
||||
lukechampine.com/blake3 v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 // indirect
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/juju/ratelimit v1.0.2 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||
github.com/vishvananda/netns v0.0.5 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
go.uber.org/mock v0.5.0 // indirect
|
||||
golang.org/x/mod v0.26.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/time v0.7.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
147
go.sum
147
go.sum
@@ -1,19 +1,23 @@
|
||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
|
||||
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJSGpevP+8Pk5bANX7fJacO2w04aqLiC5I=
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
|
||||
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E=
|
||||
github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0=
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw=
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344 h1:Arcl6UOIS/kgO2nW3A65HN+7CMjSDP/gofXL4CZt1V4=
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/U=
|
||||
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
@@ -22,43 +26,40 @@ github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g=
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/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/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.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/miekg/dns v1.1.68 h1:jsSRkNozw7G/mnmXULynzMNIsgY2dHC8LO6U6Ij2JEA=
|
||||
github.com/miekg/dns v1.1.68/go.mod h1:fujopn7TB3Pu3JM69XaawiU0wqjpL9/8xGop5UrTPps=
|
||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
|
||||
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
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/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
|
||||
github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0=
|
||||
github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0=
|
||||
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
||||
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
||||
github.com/refraction-networking/utls v1.8.0 h1:L38krhiTAyj9EeiQQa2sg+hYb4qwLCqdMcpZrRfbONE=
|
||||
github.com/refraction-networking/utls v1.8.0/go.mod h1:jkSOEkLqn+S/jtpEHPOsVv/4V4EVnelwbMQl4vCWXAM=
|
||||
github.com/quic-go/quic-go v0.50.0 h1:3H/ld1pa3CYhkcc20TPIyG1bNsdhn9qZBGN3b9/UyUo=
|
||||
github.com/quic-go/quic-go v0.50.0/go.mod h1:Vim6OmUvlYdwBhXP9ZVrtGmCMWa3wEqhq3NgYrI8b4E=
|
||||
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
|
||||
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y=
|
||||
github.com/sagernet/sing v0.5.1/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||
@@ -71,67 +72,68 @@ 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/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/vishvananda/netlink v1.3.1 h1:3AEMt62VKqz90r0tmNhog0r/PpWKmrEShJU0wJW6bV0=
|
||||
github.com/vishvananda/netlink v1.3.1/go.mod h1:ARtKouGSTGchR8aMwmkzC0qiNPrrWO5JS/XMVl45+b4=
|
||||
github.com/vishvananda/netns v0.0.5 h1:DfiHV+j8bA32MFM7bfEunvT8IAqQ/NzSJHtcmW5zdEY=
|
||||
github.com/vishvananda/netns v0.0.5/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7 h1:Ript0vN+nSO33+Vj4n0mgNY5M+oOxFQJdrJ1VnwTBO0=
|
||||
github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7/go.mod h1:XxvnCCgBee4WWE0bc4E+a7wbk8gkJ/rS0vNVNtC5qp0=
|
||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg=
|
||||
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
|
||||
golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
|
||||
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.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg=
|
||||
golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
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.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/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.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0=
|
||||
golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -139,15 +141,14 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
||||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
|
||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
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 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
@@ -155,9 +156,9 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5 h1:sfK5nHuG7lRFZ2FdTT3RimOqWBg8IrVm+/Vko1FVOsk=
|
||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5/go.mod h1:3r5CMtNQMKIvBlrmM9xWUNamjKBYPOWyXOjmg5Kts3g=
|
||||
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0 h1:P+U/06iIKPQ3DLcg+zBfSCia1luZ2msPZrJ8jYDFPs0=
|
||||
gvisor.dev/gvisor v0.0.0-20240320123526-dc6abceb7ff0/go.mod h1:NQHVAzMwvZ+Qe3ElSiHmq9RUm1MdNHpUZ52fiEqvn+0=
|
||||
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
|
||||
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
|
||||
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
|
||||
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=
|
||||
lukechampine.com/blake3 v1.4.0 h1:xDbKOZCVbnZsfzM6mHSYcGRHZ3YrLDzqz8XnV4uaD5w=
|
||||
lukechampine.com/blake3 v1.4.0/go.mod h1:MQJNQCTnR+kwOP/JEZSxj3MaQjp80FOFSNMMHXcSeX0=
|
||||
|
@@ -8,13 +8,11 @@ import (
|
||||
|
||||
type Duration int64
|
||||
|
||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||
func (d *Duration) MarshalJSON() ([]byte, error) {
|
||||
dr := time.Duration(*d)
|
||||
return json.Marshal(dr.String())
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||
func (d *Duration) UnmarshalJSON(b []byte) error {
|
||||
var v interface{}
|
||||
if err := json.Unmarshal(b, &v); err != nil {
|
||||
|
@@ -23,7 +23,6 @@ func (v StringList) Len() int {
|
||||
return len(v)
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||
func (v *StringList) UnmarshalJSON(data []byte) error {
|
||||
var strarray []string
|
||||
if err := json.Unmarshal(data, &strarray); err == nil {
|
||||
@@ -44,12 +43,10 @@ type Address struct {
|
||||
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())
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||
func (v *Address) UnmarshalJSON(data []byte) error {
|
||||
var rawStr string
|
||||
if err := json.Unmarshal(data, &rawStr); err != nil {
|
||||
@@ -84,7 +81,6 @@ func (v Network) Build() net.Network {
|
||||
|
||||
type NetworkList []Network
|
||||
|
||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||
func (v *NetworkList) UnmarshalJSON(data []byte) error {
|
||||
var strarray []Network
|
||||
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
|
||||
func (v *PortRange) UnmarshalJSON(data []byte) error {
|
||||
port, err := parseIntPort(data)
|
||||
@@ -220,21 +203,20 @@ func (list *PortList) Build() *net.PortList {
|
||||
return portList
|
||||
}
|
||||
|
||||
// MarshalJSON implements encoding/json.Marshaler.MarshalJSON
|
||||
func (v *PortList) MarshalJSON() ([]byte, error) {
|
||||
portStr := v.String()
|
||||
port, err := strconv.Atoi(portStr)
|
||||
if err == nil {
|
||||
return json.Marshal(port)
|
||||
} else {
|
||||
return json.Marshal(portStr)
|
||||
}
|
||||
func (v PortList) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.String())
|
||||
}
|
||||
|
||||
func (v PortList) String() string {
|
||||
ports := []string{}
|
||||
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, ",")
|
||||
}
|
||||
@@ -295,8 +277,7 @@ type Int32Range struct {
|
||||
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())
|
||||
}
|
||||
|
||||
@@ -308,7 +289,6 @@ func (v Int32Range) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
|
||||
func (v *Int32Range) UnmarshalJSON(data []byte) error {
|
||||
defer v.ensureOrder()
|
||||
var str string
|
||||
|
@@ -1,11 +1,7 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
@@ -21,17 +17,10 @@ type NameServerConfig struct {
|
||||
Port uint16 `json:"port"`
|
||||
SkipFallback bool `json:"skipFallback"`
|
||||
Domains []string `json:"domains"`
|
||||
ExpectedIPs StringList `json:"expectedIPs"`
|
||||
ExpectIPs StringList `json:"expectIPs"`
|
||||
ExpectIPs StringList `json:"expectIps"`
|
||||
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 {
|
||||
var address Address
|
||||
if err := json.Unmarshal(data, &address); err == nil {
|
||||
@@ -45,14 +34,8 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
||||
Port uint16 `json:"port"`
|
||||
SkipFallback bool `json:"skipFallback"`
|
||||
Domains []string `json:"domains"`
|
||||
ExpectedIPs StringList `json:"expectedIPs"`
|
||||
ExpectIPs StringList `json:"expectIPs"`
|
||||
ExpectIPs StringList `json:"expectIps"`
|
||||
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 {
|
||||
c.Address = advanced.Address
|
||||
@@ -60,14 +43,8 @@ func (c *NameServerConfig) UnmarshalJSON(data []byte) error {
|
||||
c.Port = advanced.Port
|
||||
c.SkipFallback = advanced.SkipFallback
|
||||
c.Domains = advanced.Domains
|
||||
c.ExpectedIPs = advanced.ExpectedIPs
|
||||
c.ExpectIPs = advanced.ExpectIPs
|
||||
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
|
||||
}
|
||||
|
||||
@@ -115,38 +92,9 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
|
||||
})
|
||||
}
|
||||
|
||||
if len(c.ExpectedIPs) == 0 {
|
||||
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)
|
||||
geoipList, err := ToCidrList(c.ExpectIPs)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid expected IP rule: ", c.ExpectedIPs).Base(err)
|
||||
}
|
||||
|
||||
unexpectedGeoipList, err := ToCidrList(newUnexpectedIPs)
|
||||
if err != nil {
|
||||
return nil, errors.New("invalid unexpected IP rule: ", c.UnexpectedIPs).Base(err)
|
||||
return nil, errors.New("invalid IP rule: ", c.ExpectIPs).Base(err)
|
||||
}
|
||||
|
||||
var myClientIP []byte
|
||||
@@ -166,16 +114,9 @@ func (c *NameServerConfig) Build() (*dns.NameServer, error) {
|
||||
ClientIp: myClientIP,
|
||||
SkipFallback: c.SkipFallback,
|
||||
PrioritizedDomain: domains,
|
||||
ExpectedGeoip: expectedGeoipList,
|
||||
Geoip: geoipList,
|
||||
OriginalRules: originalRules,
|
||||
QueryStrategy: resolveQueryStrategy(c.QueryStrategy),
|
||||
ActPrior: actPrior,
|
||||
Tag: c.Tag,
|
||||
TimeoutMs: c.TimeoutMs,
|
||||
DisableCache: c.DisableCache,
|
||||
FinalQuery: c.FinalQuery,
|
||||
UnexpectedGeoip: unexpectedGeoipList,
|
||||
ActUnprior: actUnprior,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -196,7 +137,6 @@ type DNSConfig struct {
|
||||
DisableCache bool `json:"disableCache"`
|
||||
DisableFallback bool `json:"disableFallback"`
|
||||
DisableFallbackIfMatch bool `json:"disableFallbackIfMatch"`
|
||||
UseSystemHosts bool `json:"useSystemHosts"`
|
||||
}
|
||||
|
||||
type HostAddress struct {
|
||||
@@ -204,18 +144,6 @@ type HostAddress struct {
|
||||
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
|
||||
func (h *HostAddress) UnmarshalJSON(data []byte) error {
|
||||
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
|
||||
func (m *HostsWrapper) UnmarshalJSON(data []byte) error {
|
||||
hosts := make(map[string]*HostAddress)
|
||||
@@ -418,15 +341,6 @@ func (c *DNSConfig) Build() (*dns.Config, error) {
|
||||
}
|
||||
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
|
||||
}
|
||||
@@ -439,57 +353,7 @@ func resolveQueryStrategy(queryStrategy string) dns.QueryStrategy {
|
||||
return dns.QueryStrategy_USE_IP4
|
||||
case "useip6", "useipv6", "use_ip6", "use_ipv6", "use_ip_v6", "use-ip6", "use-ipv6", "use-ip-v6":
|
||||
return dns.QueryStrategy_USE_IP6
|
||||
case "usesys", "usesystem", "use_sys", "use_system", "use-sys", "use-system":
|
||||
return dns.QueryStrategy_USE_SYS
|
||||
default:
|
||||
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 {
|
||||
case "":
|
||||
c.NonIPQuery = "drop"
|
||||
case "drop", "skip", "reject":
|
||||
case "drop", "skip":
|
||||
default:
|
||||
return nil, errors.New(`unknown "nonIPQuery": `, c.NonIPQuery)
|
||||
}
|
||||
|
@@ -1,35 +1,26 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"github.com/xtls/xray-core/common/errors"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/proxy/dokodemo"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
type DokodemoConfig struct {
|
||||
Address *Address `json:"address"`
|
||||
Port uint16 `json:"port"`
|
||||
PortMap map[string]string `json:"portMap"`
|
||||
Network *NetworkList `json:"network"`
|
||||
FollowRedirect bool `json:"followRedirect"`
|
||||
Host *Address `json:"address"`
|
||||
PortValue uint16 `json:"port"`
|
||||
NetworkList *NetworkList `json:"network"`
|
||||
Redirect bool `json:"followRedirect"`
|
||||
UserLevel uint32 `json:"userLevel"`
|
||||
}
|
||||
|
||||
func (v *DokodemoConfig) Build() (proto.Message, error) {
|
||||
config := new(dokodemo.Config)
|
||||
if v.Address != nil {
|
||||
config.Address = v.Address.Build()
|
||||
if v.Host != nil {
|
||||
config.Address = v.Host.Build()
|
||||
}
|
||||
config.Port = uint32(v.Port)
|
||||
config.PortMap = v.PortMap
|
||||
for _, v := range config.PortMap {
|
||||
if _, _, err := net.SplitHostPort(v); err != nil {
|
||||
return nil, errors.New("invalid portMap: ", v).Base(err)
|
||||
}
|
||||
}
|
||||
config.Networks = v.Network.Build()
|
||||
config.FollowRedirect = v.FollowRedirect
|
||||
config.Port = uint32(v.PortValue)
|
||||
config.Networks = v.NetworkList.Build()
|
||||
config.FollowRedirect = v.Redirect
|
||||
config.UserLevel = v.UserLevel
|
||||
return config, nil
|
||||
}
|
||||
|
@@ -20,18 +20,6 @@ type FakeDNSConfig struct {
|
||||
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
|
||||
func (f *FakeDNSConfig) UnmarshalJSON(data []byte) error {
|
||||
var pool FakeDNSPoolElementConfig
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user