mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-12-18 21:24:37 +03:00
Compare commits
232 Commits
v1.250516.
...
optimize-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5f17ab4fc | ||
|
|
a610a4c89a | ||
|
|
b451f8929d | ||
|
|
81f8f398c7 | ||
|
|
aea123842b | ||
|
|
bd7503d506 | ||
|
|
903214a0f0 | ||
|
|
e403abe360 | ||
|
|
c123f163c2 | ||
|
|
93312d29e5 | ||
|
|
36cb0f00bd | ||
|
|
cadcb47074 | ||
|
|
c6afcd5fb6 | ||
|
|
ed5f7e7af5 | ||
|
|
9d3401b6f0 | ||
|
|
d60ef656cc | ||
|
|
a83253f3d7 | ||
|
|
2969a189e6 | ||
|
|
d41840132a | ||
|
|
f14fd1cbee | ||
|
|
cd51f57535 | ||
|
|
4956e65824 | ||
|
|
2185a730d2 | ||
|
|
fcfb0a302a | ||
|
|
b40bf56e4e | ||
|
|
27ad487545 | ||
|
|
e914183996 | ||
|
|
acfda31e59 | ||
|
|
f9dd3aef72 | ||
|
|
b24ef88a80 | ||
|
|
b16a5f03fe | ||
|
|
2f1fabb318 | ||
|
|
1ec2966433 | ||
|
|
8a4b0a9eb0 | ||
|
|
4e8ee302a6 | ||
|
|
18a4104737 | ||
|
|
1a32d18c16 | ||
|
|
412bc17c12 | ||
|
|
9491b67f3c | ||
|
|
cb4f943f50 | ||
|
|
b69a376aa1 | ||
|
|
12f4a014e0 | ||
|
|
9cc7907234 | ||
|
|
21a9658519 | ||
|
|
7f436f5318 | ||
|
|
dcfde8dc92 | ||
|
|
898db92d51 | ||
|
|
8dd0e388a2 | ||
|
|
40f0a541bf | ||
|
|
1762d6c8cc | ||
|
|
195248801d | ||
|
|
4a825c0260 | ||
|
|
514c9e5a22 | ||
|
|
2f366aed2e | ||
|
|
c0c88f3d73 | ||
|
|
d0344bcff8 | ||
|
|
a6ebb3061c | ||
|
|
fe57507fd9 | ||
|
|
83c5370eec | ||
|
|
1a48453bea | ||
|
|
3167e5cec0 | ||
|
|
5148c5786f | ||
|
|
3edfb0e335 | ||
|
|
d3248a4f8e | ||
|
|
30e10be95d | ||
|
|
cced1477a0 | ||
|
|
9f5dcb1591 | ||
|
|
ce5c51d3ba | ||
|
|
11f670c8a6 | ||
|
|
a387ae9590 | ||
|
|
4ae497106d | ||
|
|
1f4fc2e7bb | ||
|
|
ae44b86b0d | ||
|
|
8276a443bc | ||
|
|
1e2f251bb3 | ||
|
|
845010b535 | ||
|
|
a0c63ba1cf | ||
|
|
2b82366148 | ||
|
|
ab1fa13ebe | ||
|
|
4740ba2425 | ||
|
|
4b0ee28f1c | ||
|
|
6ec0291d4e | ||
|
|
118131fcaf | ||
|
|
197b319f9a | ||
|
|
8b579bf3ec | ||
|
|
cbade89ab1 | ||
|
|
d20397c15d | ||
|
|
19f8907296 | ||
|
|
e943de5300 | ||
|
|
4064f8dd80 | ||
|
|
2acd206821 | ||
|
|
4c6fd94d97 | ||
|
|
fd54b10d97 | ||
|
|
6830089d3c | ||
|
|
6768a22f67 | ||
|
|
e8b02cd664 | ||
|
|
fbb0ecfb83 | ||
|
|
a31842feaa | ||
|
|
79325ead2e | ||
|
|
81b7cd718a | ||
|
|
ea1a3ae8f1 | ||
|
|
593ededd3e | ||
|
|
82ea7a3cc5 | ||
|
|
56a45ad578 | ||
|
|
4976085ddb | ||
|
|
fcdd4df446 | ||
|
|
12b077f33b | ||
|
|
702d2c06ca | ||
|
|
7951a5c4bf | ||
|
|
c2141f09e7 | ||
|
|
ef640ed309 | ||
|
|
5fa5f3fbb9 | ||
|
|
2ee372e758 | ||
|
|
11f0513bce | ||
|
|
b65da77267 | ||
|
|
33272a0499 | ||
|
|
87b643a388 | ||
|
|
6d1695a686 | ||
|
|
3a54924045 | ||
|
|
573300bc22 | ||
|
|
7f300dbf0c | ||
|
|
5464862ee6 | ||
|
|
337b4b814e | ||
|
|
105b306d07 | ||
|
|
de23e51077 | ||
|
|
40ce850bd9 | ||
|
|
2485f4831f | ||
|
|
aac0d6a6a5 | ||
|
|
f557bf7da4 | ||
|
|
6fc0a40c2a | ||
|
|
f3cdcad541 | ||
|
|
5a8e9c25a4 | ||
|
|
836b6487e4 | ||
|
|
b1107b9810 | ||
|
|
0cceea75da | ||
|
|
4b21c9aed3 | ||
|
|
cde6e33ec9 | ||
|
|
5dce7e4e25 | ||
|
|
9359844149 | ||
|
|
8222f43eea | ||
|
|
04e6439b51 | ||
|
|
bd86732f68 | ||
|
|
d4f11e6d68 | ||
|
|
00f3147242 | ||
|
|
7cbf5b004c | ||
|
|
87fff12fd9 | ||
|
|
a02723e63f | ||
|
|
146b14ab55 | ||
|
|
b2829219a0 | ||
|
|
116cd70a3a | ||
|
|
c569f478af | ||
|
|
b6b51c51c8 | ||
|
|
fb7a9d8d61 | ||
|
|
3fe02a658a | ||
|
|
5f93ff6c3a | ||
|
|
10376f5b4d | ||
|
|
1ea00fad81 | ||
|
|
cfcf2a63d1 | ||
|
|
66025f2889 | ||
|
|
c9cd26d6d3 | ||
|
|
caee152adf | ||
|
|
eb433d9462 | ||
|
|
87d8b97d9a | ||
|
|
9d15ecf1f9 | ||
|
|
4f45c5faa5 | ||
|
|
26de58933f | ||
|
|
31b508d372 | ||
|
|
955a569181 | ||
|
|
d141d01d0c | ||
|
|
4e826abebf | ||
|
|
4433641e30 | ||
|
|
a196a16c55 | ||
|
|
8c0bf15901 | ||
|
|
dbd9125686 | ||
|
|
923b5d7229 | ||
|
|
f90fae22aa | ||
|
|
b065595f58 | ||
|
|
308f8a7459 | ||
|
|
050f596e8f | ||
|
|
3b47d0846e | ||
|
|
7f23a1cb65 | ||
|
|
446315cf1f | ||
|
|
eed05549fc | ||
|
|
2b4a8d235b | ||
|
|
83686ebfaa | ||
|
|
79c6f99384 | ||
|
|
ca8ef209a7 | ||
|
|
cbcab89c7e | ||
|
|
abd551e9f7 | ||
|
|
10dbeb4335 | ||
|
|
6afd721ced | ||
|
|
5c0bc361d3 | ||
|
|
3a2ac9d0bf | ||
|
|
1785178762 | ||
|
|
1976d02ec9 | ||
|
|
3ba733079e | ||
|
|
6a8a85f83a | ||
|
|
409e4e8f12 | ||
|
|
486d005986 | ||
|
|
cb1afb33e6 | ||
|
|
38ed2cc387 | ||
|
|
b043db8260 | ||
|
|
27742da2c6 | ||
|
|
fbae89d017 | ||
|
|
58c28b4aeb | ||
|
|
ca1c4b63f6 | ||
|
|
18ab291e0c | ||
|
|
e011b746dc | ||
|
|
f4b23c6565 | ||
|
|
7d36cad3e0 | ||
|
|
a576a4b183 | ||
|
|
f38d3f786a | ||
|
|
402067d281 | ||
|
|
97fdcb4228 | ||
|
|
bfbccc2721 | ||
|
|
f67c70c4a2 | ||
|
|
83e5fa4f3c | ||
|
|
4e1a6f0fd1 | ||
|
|
ab0b9a6220 | ||
|
|
b80e319655 | ||
|
|
6232e230d9 | ||
|
|
028e1114e6 | ||
|
|
af7a76da67 | ||
|
|
d44c78b819 | ||
|
|
d0c80fc80d | ||
|
|
1f49bfc6a5 | ||
|
|
dd52732e1f | ||
|
|
4af53ab364 | ||
|
|
462bc3cfba | ||
|
|
84c8e24a6c | ||
|
|
9fe4ee75b7 | ||
|
|
f1116cee60 |
29
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
29
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -7,6 +7,8 @@ body:
|
|||||||
description: |-
|
description: |-
|
||||||
Please check all of the following options to prove that you have read and understood the requirements, otherwise this issue will be closed.
|
Please check all of the following options to prove that you have read and understood the requirements, otherwise this issue will be closed.
|
||||||
options:
|
options:
|
||||||
|
- label: I have read all the comments in the issue template and ensured that this issue meet the requirements.
|
||||||
|
required: true
|
||||||
- label: I confirm that I have read the documentation, understand the meaning of all the configuration items I wrote, and did not pile up seemingly useful options or default values.
|
- label: I confirm that I have read the documentation, understand the meaning of all the configuration items I wrote, and did not pile up seemingly useful options or default values.
|
||||||
required: true
|
required: true
|
||||||
- label: I provided the complete config and logs, rather than just providing the truncated parts based on my own judgment.
|
- label: I provided the complete config and logs, rather than just providing the truncated parts based on my own judgment.
|
||||||
@@ -38,6 +40,8 @@ body:
|
|||||||
### For config
|
### For config
|
||||||
Please provide the configuration files that can reproduce the problem, including the server and client.
|
Please provide the configuration files that can reproduce the problem, including the server and client.
|
||||||
Don't just paste a big exported config file here. Eliminate useless inbound/outbound, rules, options, this can help determine the problem, if you really want to get help.
|
Don't just paste a big exported config file here. Eliminate useless inbound/outbound, rules, options, this can help determine the problem, if you really want to get help.
|
||||||
|
After removing parts that do not affect reproduction, provide the actual running **complete** file.
|
||||||
|
meaning of complete: This config can be directly used to start the core, **not a truncated part of the config**. For fields like keys, use newly generated valid parameters that have not been actually used to fill in.
|
||||||
|
|
||||||
### For logs
|
### For logs
|
||||||
Please set the log level to debug and dnsLog to true first.
|
Please set the log level to debug and dnsLog to true first.
|
||||||
@@ -46,42 +50,29 @@ body:
|
|||||||
Provide the log of Xray-core, not the log output by the panel or other things.
|
Provide the log of Xray-core, not the log output by the panel or other things.
|
||||||
|
|
||||||
### Finally
|
### Finally
|
||||||
After removing parts that do not affect reproduction, provide the actual running **complete** file, do not only provide inbound or outbound or a few lines of logs based on your own judgment.
|
The specific content to be filled in each of the following text boxes needs to be placed between ```<details><pre><code>``` and ```</code></pre></details>```, like this
|
||||||
Put the content between the preset ```<details><pre><code>``` ```</code></pre></details>``` in the text box.
|
```
|
||||||
If the problem is very clear that only related to one end (such as core startup failure/crash after correctly writing the config according to the documents), N/A can be filled in for unnecessary areas below.
|
<details><pre><code>
|
||||||
|
(config)
|
||||||
|
</code></pre></details>
|
||||||
|
```
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Client config
|
label: Client config
|
||||||
value: |-
|
|
||||||
<details><pre><code>
|
|
||||||
|
|
||||||
</code></pre></details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Server config
|
label: Server config
|
||||||
value: |-
|
|
||||||
<details><pre><code>
|
|
||||||
|
|
||||||
</code></pre></details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Client log
|
label: Client log
|
||||||
value: |-
|
|
||||||
<details><pre><code>
|
|
||||||
|
|
||||||
</code></pre></details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: Server log
|
label: Server log
|
||||||
value: |-
|
|
||||||
<details><pre><code>
|
|
||||||
|
|
||||||
</code></pre></details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
29
.github/ISSUE_TEMPLATE/bug_report_zh.yml
vendored
29
.github/ISSUE_TEMPLATE/bug_report_zh.yml
vendored
@@ -7,6 +7,8 @@ body:
|
|||||||
description: |-
|
description: |-
|
||||||
请勾选以下所有选项以证明您已经阅读并理解了以下要求,否则该 issue 将被关闭。
|
请勾选以下所有选项以证明您已经阅读并理解了以下要求,否则该 issue 将被关闭。
|
||||||
options:
|
options:
|
||||||
|
- label: 我读完了 issue 模板中的所有注释,确保填写符合要求。
|
||||||
|
required: true
|
||||||
- label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
|
- label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
|
||||||
required: true
|
required: true
|
||||||
- label: 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。
|
- label: 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。
|
||||||
@@ -38,6 +40,8 @@ body:
|
|||||||
### 对于配置文件
|
### 对于配置文件
|
||||||
请提供可以重现问题的配置文件,包括服务端和客户端。
|
请提供可以重现问题的配置文件,包括服务端和客户端。
|
||||||
不要直接在这里黏贴一大段导出的 config 文件。去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。
|
不要直接在这里黏贴一大段导出的 config 文件。去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。
|
||||||
|
在去掉不影响复现的部分后,提供实际运行的**完整**文件。
|
||||||
|
完整的含义:可以直接使用这个配置启动核心,**不是截取的部分配置**。对于密钥等参数使用重新生成未实际使用的有效参数填充。
|
||||||
|
|
||||||
### 对于日志
|
### 对于日志
|
||||||
请先将日志等级设置为 debug, dnsLog 设置为true.
|
请先将日志等级设置为 debug, dnsLog 设置为true.
|
||||||
@@ -46,42 +50,29 @@ body:
|
|||||||
提供 Xray-core 的日志,而不是面板或者别的东西输出的日志。
|
提供 Xray-core 的日志,而不是面板或者别的东西输出的日志。
|
||||||
|
|
||||||
### 最后
|
### 最后
|
||||||
在去掉不影响复现的部分后,提供实际运行的**完整**文件,不要出于自己的判断只提供入站出站或者几行日志。
|
把下面的每格具体内容需要放在 ```<details><pre><code>``` 和 ```</code></pre></details>``` 中间,如
|
||||||
把内容放在文本框预置的 ```<details><pre><code>``` 和 ```</code></pre></details>``` 中间。
|
```
|
||||||
如果问题十分明确只出现在某一端(如按文档正确编写配置后核心启动失败/崩溃),可以在下面不需要的项目填入N/A.
|
<details><pre><code>
|
||||||
|
(config)
|
||||||
|
</code></pre></details>
|
||||||
|
```
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 客户端配置
|
label: 客户端配置
|
||||||
value: |-
|
|
||||||
<details><pre><code>
|
|
||||||
|
|
||||||
</code></pre></details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 服务端配置
|
label: 服务端配置
|
||||||
value: |-
|
|
||||||
<details><pre><code>
|
|
||||||
|
|
||||||
</code></pre></details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 客户端日志
|
label: 客户端日志
|
||||||
value: |-
|
|
||||||
<details><pre><code>
|
|
||||||
|
|
||||||
</code></pre></details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: 服务端日志
|
label: 服务端日志
|
||||||
value: |-
|
|
||||||
<details><pre><code>
|
|
||||||
|
|
||||||
</code></pre></details>
|
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|||||||
74
.github/docker/Dockerfile
vendored
74
.github/docker/Dockerfile
vendored
@@ -1,28 +1,62 @@
|
|||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:latest
|
||||||
FROM --platform=$BUILDPLATFORM golang:alpine AS build
|
FROM --platform=$BUILDPLATFORM golang:latest AS build
|
||||||
|
|
||||||
|
# Build xray-core
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
COPY . .
|
COPY . .
|
||||||
ARG TARGETOS
|
ARG TARGETOS
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -ldflags "-s -w -buildid=" ./main
|
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="all=-l=4" -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
|
|
||||||
|
|
||||||
# chainguard/static contains only tzdata and ca-certificates, can be built with multiarch static binaries.
|
# Download geodat into a staging directory
|
||||||
FROM --platform=linux/amd64 chainguard/static:latest
|
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geoip.dat /tmp/geodat/geoip.dat
|
||||||
WORKDIR /var/log/xray
|
ADD https://raw.githubusercontent.com/Loyalsoldier/v2ray-rules-dat/release/geosite.dat /tmp/geodat/geosite.dat
|
||||||
COPY .github/docker/files/config.json /etc/xray/config.json
|
|
||||||
COPY --from=build --chmod=755 /src/xray /usr/bin/xray
|
|
||||||
|
|
||||||
USER root
|
RUN mkdir -p /tmp/empty
|
||||||
WORKDIR /root
|
|
||||||
VOLUME /etc/xray
|
# Create config files with empty JSON content
|
||||||
ARG TZ=Asia/Shanghai
|
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
|
||||||
ENV TZ=$TZ
|
ENV TZ=$TZ
|
||||||
ENTRYPOINT [ "/usr/bin/xray" ]
|
|
||||||
CMD [ "-confdir", "/etc/xray/" ]
|
|
||||||
|
|
||||||
ARG flavor=v2fly
|
ENTRYPOINT [ "/usr/local/bin/xray" ]
|
||||||
COPY --from=build --chmod=644 /$flavor /usr/share/xray
|
CMD [ "-confdir", "/usr/local/etc/xray/" ]
|
||||||
|
|||||||
71
.github/docker/Dockerfile.usa
vendored
Normal file
71
.github/docker/Dockerfile.usa
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# 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 -buildvcs=false -gcflags="all=-l=4" -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
18
.github/docker/files/config.json
vendored
@@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"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,76 +1,133 @@
|
|||||||
name: Build docker image
|
name: Build and Push Docker Image
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types:
|
||||||
push:
|
- published
|
||||||
branches:
|
- released
|
||||||
- main
|
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: "Docker image tag:"
|
||||||
|
required: true
|
||||||
|
latest:
|
||||||
|
description: "Set to latest"
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-image:
|
build-and-push:
|
||||||
|
if: (github.event.action != 'published') || (github.event.action == 'published' && github.event.release.prerelease == true)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
|
contents: read
|
||||||
packages: write
|
packages: write
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Set repository and image name to lowercase
|
||||||
- name: Docker metadata
|
env:
|
||||||
id: meta
|
IMAGE_NAME: "${{ github.repository }}"
|
||||||
uses: docker/metadata-action@v5
|
run: |
|
||||||
with:
|
echo "IMAGE_NAME=${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||||
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
echo "FULL_IMAGE_NAME=ghcr.io/${IMAGE_NAME,,}" >>${GITHUB_ENV}
|
||||||
flavor: latest=auto
|
|
||||||
tags: |
|
- name: Validate and extract tag
|
||||||
type=sha
|
run: |
|
||||||
type=ref,event=branch
|
SOURCE_TAG="${{ github.event.inputs.tag }}"
|
||||||
type=ref,event=pr
|
if [[ -z "$SOURCE_TAG" ]]; then
|
||||||
type=semver,pattern={{version}}
|
SOURCE_TAG="${{ github.ref_name }}"
|
||||||
- name: Docker metadata Loyalsoldier flavor
|
fi
|
||||||
id: loyalsoldier
|
if [[ -z "$SOURCE_TAG" ]]; then
|
||||||
uses: docker/metadata-action@v5
|
SOURCE_TAG="${{ github.event.release.tag_name }}"
|
||||||
with:
|
fi
|
||||||
images: ghcr.io/${{ github.repository_owner }}/xray-core
|
|
||||||
flavor: |
|
if [[ -z "$SOURCE_TAG" ]]; then
|
||||||
latest=auto
|
echo "Error: Could not determine a valid tag source. Input tag and context tag (github.ref_name) are both empty."
|
||||||
suffix=-ls,onlatest=true
|
exit 1
|
||||||
tags: |
|
fi
|
||||||
type=sha
|
|
||||||
type=ref,event=branch
|
if [[ "$SOURCE_TAG" =~ ^v[0-9]+\.[0-9] ]]; then
|
||||||
type=ref,event=pr
|
IMAGE_TAG="${SOURCE_TAG#v}"
|
||||||
type=semver,pattern={{version}}
|
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@v6
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
- name: Build Docker image (main architectures)
|
||||||
- name: Build and push
|
id: build_main_arches
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
file: .github/docker/Dockerfile
|
||||||
platforms: |
|
platforms: |
|
||||||
linux/amd64
|
linux/amd64
|
||||||
linux/arm64
|
linux/arm/v7
|
||||||
linux/loong64
|
linux/arm64/v8
|
||||||
linux/riscv64
|
linux/ppc64le
|
||||||
|
linux/s390x
|
||||||
provenance: false
|
provenance: false
|
||||||
file: .github/docker/Dockerfile
|
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||||
push: true
|
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
- name: Build Docker image (additional architectures)
|
||||||
- name: Build and push Loyalsoldier flavor
|
id: build_additional_arches
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
file: .github/docker/Dockerfile.usa
|
||||||
platforms: |
|
platforms: |
|
||||||
linux/amd64
|
linux/386
|
||||||
linux/arm64
|
linux/arm/v6
|
||||||
linux/loong64
|
|
||||||
linux/riscv64
|
linux/riscv64
|
||||||
|
linux/loong64
|
||||||
provenance: false
|
provenance: false
|
||||||
file: .github/docker/Dockerfile
|
outputs: type=image,name=${{ env.FULL_IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
|
||||||
build-args: flavor=loyalsoldier
|
|
||||||
push: true
|
- name: Create manifest list and push
|
||||||
tags: |
|
run: |
|
||||||
${{ steps.loyalsoldier.outputs.tags }}
|
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
|
||||||
|
|||||||
10
.github/workflows/release-win7.yml
vendored
10
.github/workflows/release-win7.yml
vendored
@@ -63,7 +63,7 @@ jobs:
|
|||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Show workflow information
|
- name: Show workflow information
|
||||||
run: |
|
run: |
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -94,11 +94,11 @@ jobs:
|
|||||||
mkdir -p build_assets
|
mkdir -p build_assets
|
||||||
COMMID=$(git describe --always --dirty)
|
COMMID=$(git describe --always --dirty)
|
||||||
echo 'Building Xray for Windows 7...'
|
echo 'Building Xray for Windows 7...'
|
||||||
go build -o build_assets/xray.exe -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
go build -o build_assets/xray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
||||||
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
|
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
|
||||||
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
|
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
|
||||||
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
|
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
|
||||||
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
||||||
|
|
||||||
- name: Restore Geodat Cache
|
- name: Restore Geodat Cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
@@ -132,7 +132,7 @@ jobs:
|
|||||||
mv build_assets Xray-${{ env.ASSET_NAME }}
|
mv build_assets Xray-${{ env.ASSET_NAME }}
|
||||||
|
|
||||||
- name: Upload files to Artifacts
|
- name: Upload files to Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: Xray-${{ env.ASSET_NAME }}
|
name: Xray-${{ env.ASSET_NAME }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
18
.github/workflows/release.yml
vendored
18
.github/workflows/release.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Trigger Asset Update Workflow if Assets Missing
|
- name: Trigger Asset Update Workflow if Assets Missing
|
||||||
if: steps.check-assets.outputs.missing == 'true'
|
if: steps.check-assets.outputs.missing == 'true'
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v8
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
@@ -153,7 +153,7 @@ jobs:
|
|||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Set up NDK
|
- name: Set up NDK
|
||||||
if: matrix.goos == 'android'
|
if: matrix.goos == 'android'
|
||||||
@@ -176,7 +176,7 @@ jobs:
|
|||||||
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
echo "ASSET_NAME=$_NAME" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
@@ -190,17 +190,19 @@ jobs:
|
|||||||
COMMID=$(git describe --always --dirty)
|
COMMID=$(git describe --always --dirty)
|
||||||
if [[ ${GOOS} == 'windows' ]]; then
|
if [[ ${GOOS} == 'windows' ]]; then
|
||||||
echo 'Building Xray for Windows...'
|
echo 'Building Xray for Windows...'
|
||||||
go build -o build_assets/xray.exe -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
go build -o build_assets/xray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
||||||
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
|
echo 'CreateObject("Wscript.Shell").Run "xray.exe -config config.json",0' > build_assets/xray_no_window.vbs
|
||||||
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
|
echo 'Start-Process -FilePath ".\xray.exe" -ArgumentList "-config .\config.json" -WindowStyle Hidden' > build_assets/xray_no_window.ps1
|
||||||
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
|
# The line below is for without running conhost.exe version. Commented for not being used. Provided for reference.
|
||||||
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
# go build -o build_assets/wxray.exe -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-H windowsgui -X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
||||||
else
|
else
|
||||||
echo 'Building Xray...'
|
echo 'Building Xray...'
|
||||||
go build -o build_assets/xray -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
|
||||||
if [[ ${GOARCH} == 'mips' || ${GOARCH} == 'mipsle' ]]; then
|
if [[ ${GOARCH} == 'mips' || ${GOARCH} == 'mipsle' ]]; then
|
||||||
|
go build -o build_assets/xray -trimpath -buildvcs=false -gcflags="-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
||||||
echo 'Building soft-float Xray for MIPS/MIPSLE 32-bit...'
|
echo 'Building soft-float Xray for MIPS/MIPSLE 32-bit...'
|
||||||
GOMIPS=softfloat go build -o build_assets/xray_softfloat -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
GOMIPS=softfloat go build -o build_assets/xray_softfloat -trimpath -buildvcs=false -gcflags="-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
||||||
|
else
|
||||||
|
go build -o build_assets/xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=${COMMID} -s -w -buildid=" -v ./main
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -236,7 +238,7 @@ jobs:
|
|||||||
mv build_assets Xray-${{ env.ASSET_NAME }}
|
mv build_assets Xray-${{ env.ASSET_NAME }}
|
||||||
|
|
||||||
- name: Upload files to Artifacts
|
- name: Upload files to Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: Xray-${{ env.ASSET_NAME }}
|
name: Xray-${{ env.ASSET_NAME }}
|
||||||
path: |
|
path: |
|
||||||
|
|||||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -45,9 +45,9 @@ jobs:
|
|||||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v6
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
|||||||
40
.gitignore
vendored
40
.gitignore
vendored
@@ -11,21 +11,23 @@
|
|||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
|
||||||
# vendor/
|
|
||||||
|
|
||||||
# macOS specific files
|
# macOS specific files
|
||||||
*.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# IDE specific files
|
# IDE/editor specific files
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
# Archive files
|
# Archives and compressed files
|
||||||
*.zip
|
*.zip
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
*.tar
|
||||||
|
*.gz
|
||||||
|
*.bz2
|
||||||
|
|
||||||
# Binaries
|
# Go build binaries
|
||||||
xray
|
xray
|
||||||
xray_softfloat
|
xray_softfloat
|
||||||
mockgen
|
mockgen
|
||||||
@@ -36,11 +38,31 @@ errorgen
|
|||||||
*.dat
|
*.dat
|
||||||
|
|
||||||
# Build assets
|
# Build assets
|
||||||
/build_assets
|
/build_assets/
|
||||||
|
|
||||||
# Output from dlv test
|
# Output from dlv test
|
||||||
**/debug.*
|
**/debug.*
|
||||||
|
|
||||||
# Certificates
|
# Certificates and keys
|
||||||
*.crt
|
*.crt
|
||||||
*.key
|
*.key
|
||||||
|
|
||||||
|
# Dependency directories (uncomment if needed)
|
||||||
|
# vendor/
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Coverage reports
|
||||||
|
coverage.*
|
||||||
|
|
||||||
|
# Node modules (in case of frontend assets)
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# System files
|
||||||
|
Thumbs.db
|
||||||
|
ehthumbs.db
|
||||||
|
|
||||||
|
# Other common ignores
|
||||||
|
*.bak
|
||||||
|
*.tmp
|
||||||
|
|||||||
60
README.md
60
README.md
@@ -4,11 +4,30 @@
|
|||||||
|
|
||||||
[README](https://github.com/XTLS/Xray-core#readme) is open, so feel free to submit your project [here](https://github.com/XTLS/Xray-core/pulls).
|
[README](https://github.com/XTLS/Xray-core#readme) is open, so feel free to submit your project [here](https://github.com/XTLS/Xray-core/pulls).
|
||||||
|
|
||||||
|
## Sponsors
|
||||||
|
|
||||||
|
[](https://docs.rw)
|
||||||
|
|
||||||
|
[](https://happ.su)
|
||||||
|
|
||||||
|
[**Sponsor Xray-core**](https://github.com/XTLS/Xray-core/issues/3668)
|
||||||
|
|
||||||
## Donation & NFTs
|
## 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)
|
||||||
|
|
||||||
|
- **TRX(Tron)/USDT/USDC: `TNrDh5VSfwd4RPrwsohr6poyNTfFefNYan`**
|
||||||
|
- **TON: `UQApeV-u2gm43aC1uP76xAC1m6vCylstaN1gpfBmre_5IyTH`**
|
||||||
|
- **BTC: `1JpqcziZZuqv3QQJhZGNGBVdCBrGgkL6cT`**
|
||||||
|
- **XMR: `4ABHQZ3yJZkBnLoqiKvb3f8eqUnX4iMPb6wdant5ZLGQELctcerceSGEfJnoCk6nnyRZm73wrwSgvZ2WmjYLng6R7sR67nq`**
|
||||||
|
- **SOL/USDT/USDC: `3x5NuXHzB5APG6vRinPZcsUv5ukWUY1tBGRSJiEJWtZa`**
|
||||||
- **ETH/USDT/USDC: `0xDc3Fe44F0f25D13CACb1C4896CD0D321df3146Ee`**
|
- **ETH/USDT/USDC: `0xDc3Fe44F0f25D13CACb1C4896CD0D321df3146Ee`**
|
||||||
- **Project X NFT: [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633)**
|
- **Project X NFT: https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/1**
|
||||||
- **REALITY NFT: [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113)**
|
- **VLESS NFT: https://opensea.io/collection/vless**
|
||||||
|
- **REALITY NFT: https://opensea.io/item/ethereum/0x5ee362866001613093361eb8569d59c4141b76d1/2**
|
||||||
|
- **Related links: [VLESS Post-Quantum Encryption](https://github.com/XTLS/Xray-core/pull/5067), [XHTTP: Beyond REALITY](https://github.com/XTLS/Xray-core/discussions/4113), [Announcement of NFTs by Project X](https://github.com/XTLS/Xray-core/discussions/3633)**
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
@@ -39,12 +58,14 @@
|
|||||||
- [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
|
- [wulabing/xray_docker](https://github.com/wulabing/xray_docker)
|
||||||
- Web Panel - **WARNING: Please DO NOT USE plain HTTP panels like 3X-UI**, as they are believed to be bribed by Iran GFW for supporting plain HTTP by default and refused to change (https://github.com/XTLS/Xray-core/pull/3884#issuecomment-2439595331), which has already put many users' data security in danger in the past few years. **If you are already using 3X-UI, please switch to the following panels, which are verified to support HTTPS and SSH port forwarding only:**
|
- Web Panel - **WARNING: Please DO NOT USE plain HTTP panels like 3X-UI**, as they are believed to be bribed by Iran GFW for supporting plain HTTP by default and refused to change (https://github.com/XTLS/Xray-core/pull/3884#issuecomment-2439595331), which has already put many users' data security in danger in the past few years. **If you are already using 3X-UI, please switch to the following panels, which are verified to support HTTPS and SSH port forwarding only:**
|
||||||
- [Remnawave](https://github.com/remnawave/panel)
|
- [Remnawave](https://github.com/remnawave/panel)
|
||||||
|
- [X-Panel](https://github.com/xeefei/X-Panel)
|
||||||
|
- [PasarGuard](https://github.com/PasarGuard/panel)
|
||||||
- [Marzban](https://github.com/Gozargah/Marzban)
|
- [Marzban](https://github.com/Gozargah/Marzban)
|
||||||
- [Xray-UI](https://github.com/qist/xray-ui)
|
- [Xray-UI](https://github.com/qist/xray-ui)
|
||||||
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
|
- [Hiddify](https://github.com/hiddify/Hiddify-Manager)
|
||||||
- One Click
|
- One Click
|
||||||
- [Xray-REALITY](https://github.com/zxcvos/Xray-script), [xray-reality](https://github.com/sajjaddg/xray-reality), [reality-ezpz](https://github.com/aleskxyz/reality-ezpz)
|
- [Xray-REALITY](https://github.com/zxcvos/Xray-script), [xray-reality](https://github.com/sajjaddg/xray-reality), [reality-ezpz](https://github.com/aleskxyz/reality-ezpz)
|
||||||
- [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool)
|
- [Xray_bash_onekey](https://github.com/hello-yunshu/Xray_bash_onekey), [XTool](https://github.com/LordPenguin666/XTool), [VPainLess](https://github.com/vpainless/vpainless)
|
||||||
- [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
|
- [v2ray-agent](https://github.com/mack-a/v2ray-agent), [Xray_onekey](https://github.com/wulabing/Xray_onekey), [ProxySU](https://github.com/proxysu/ProxySU)
|
||||||
- Magisk
|
- Magisk
|
||||||
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
|
- [Xray4Magisk](https://github.com/Asterisk4Magisk/Xray4Magisk)
|
||||||
@@ -81,26 +102,37 @@
|
|||||||
- [v2rayN](https://github.com/2dust/v2rayN)
|
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
- [Furious](https://github.com/LorenEteval/Furious)
|
- [Furious](https://github.com/LorenEteval/Furious)
|
||||||
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
|
- [Invisible Man - Xray](https://github.com/InvisibleManVPN/InvisibleMan-XRayClient)
|
||||||
|
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||||
- Android
|
- Android
|
||||||
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
- [v2rayNG](https://github.com/2dust/v2rayNG)
|
||||||
- [X-flutter](https://github.com/XTLS/X-flutter)
|
- [X-flutter](https://github.com/XTLS/X-flutter)
|
||||||
- [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
|
- [SaeedDev94/Xray](https://github.com/SaeedDev94/Xray)
|
||||||
- iOS & macOS arm64
|
- [SimpleXray](https://github.com/lhear/SimpleXray)
|
||||||
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
|
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||||
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
- 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))
|
||||||
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
- [Streisand](https://apps.apple.com/app/streisand/id6450534064)
|
||||||
|
- [OneXray](https://github.com/OneXray/OneXray)
|
||||||
- macOS arm64 & x64
|
- macOS arm64 & x64
|
||||||
|
- [Happ](https://apps.apple.com/app/happ-proxy-utility/id6504287215)
|
||||||
- [V2rayU](https://github.com/yanue/V2rayU)
|
- [V2rayU](https://github.com/yanue/V2rayU)
|
||||||
- [V2RayXS](https://github.com/tzmax/V2RayXS)
|
- [V2RayXS](https://github.com/tzmax/V2RayXS)
|
||||||
- [Furious](https://github.com/LorenEteval/Furious)
|
- [Furious](https://github.com/LorenEteval/Furious)
|
||||||
- [FoXray](https://apps.apple.com/app/foxray/id6448898396)
|
- [OneXray](https://github.com/OneXray/OneXray)
|
||||||
|
- [GoXRay](https://github.com/goxray/desktop)
|
||||||
|
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||||
|
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
- Linux
|
- Linux
|
||||||
- [v2rayA](https://github.com/v2rayA/v2rayA)
|
- [v2rayA](https://github.com/v2rayA/v2rayA)
|
||||||
- [Furious](https://github.com/LorenEteval/Furious)
|
- [Furious](https://github.com/LorenEteval/Furious)
|
||||||
|
- [GorzRay](https://github.com/ketetefid/GorzRay)
|
||||||
|
- [GoXRay](https://github.com/goxray/desktop)
|
||||||
|
- [AnyPortal](https://github.com/AnyPortal/AnyPortal)
|
||||||
|
- [v2rayN](https://github.com/2dust/v2rayN)
|
||||||
|
|
||||||
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
|
## Others that support VLESS, XTLS, REALITY, XUDP, PLUX...
|
||||||
|
|
||||||
- iOS & macOS arm64
|
- iOS & macOS arm64 & tvOS
|
||||||
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
- [Shadowrocket](https://apps.apple.com/app/shadowrocket/id932747118)
|
||||||
- [Loon](https://apps.apple.com/us/app/loon/id1373567447)
|
- [Loon](https://apps.apple.com/us/app/loon/id1373567447)
|
||||||
- Xray Tools
|
- Xray Tools
|
||||||
@@ -108,6 +140,7 @@
|
|||||||
- [xray-checker](https://github.com/kutovoys/xray-checker)
|
- [xray-checker](https://github.com/kutovoys/xray-checker)
|
||||||
- Xray Wrapper
|
- Xray Wrapper
|
||||||
- [XTLS/libXray](https://github.com/XTLS/libXray)
|
- [XTLS/libXray](https://github.com/XTLS/libXray)
|
||||||
|
- [xtls-sdk](https://github.com/remnawave/xtls-sdk)
|
||||||
- [xtlsapi](https://github.com/hiddify/xtlsapi)
|
- [xtlsapi](https://github.com/hiddify/xtlsapi)
|
||||||
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
|
- [AndroidLibXrayLite](https://github.com/2dust/AndroidLibXrayLite)
|
||||||
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
|
- [Xray-core-python](https://github.com/LorenEteval/Xray-core-python)
|
||||||
@@ -116,6 +149,7 @@
|
|||||||
- [XrayR-release](https://github.com/XrayR-project/XrayR-release)
|
- [XrayR-release](https://github.com/XrayR-project/XrayR-release)
|
||||||
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
|
- [XrayR-V2Board](https://github.com/missuo/XrayR-V2Board)
|
||||||
- Cores
|
- Cores
|
||||||
|
- [Amnezia VPN](https://github.com/amnezia-vpn)
|
||||||
- [mihomo](https://github.com/MetaCubeX/mihomo)
|
- [mihomo](https://github.com/MetaCubeX/mihomo)
|
||||||
- [sing-box](https://github.com/SagerNet/sing-box)
|
- [sing-box](https://github.com/SagerNet/sing-box)
|
||||||
|
|
||||||
@@ -123,6 +157,8 @@
|
|||||||
|
|
||||||
[Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)
|
[Code of Conduct](https://github.com/XTLS/Xray-core/blob/main/CODE_OF_CONDUCT.md)
|
||||||
|
|
||||||
|
[](https://deepwiki.com/XTLS/Xray-core)
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
- [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases).
|
- [Xray-core v1.0.0](https://github.com/XTLS/Xray-core/releases/tag/v1.0.0) was forked from [v2fly-core 9a03cc5](https://github.com/v2fly/v2ray-core/commit/9a03cc5c98d04cc28320fcee26dbc236b3291256), and we have made & accumulated a huge number of enhancements over time, check [the release notes for each version](https://github.com/XTLS/Xray-core/releases).
|
||||||
@@ -148,7 +184,13 @@ CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-s -w -buildi
|
|||||||
Make sure that you are using the same Go version, and remember to set the git commit id (7 bytes):
|
Make sure that you are using the same Go version, and remember to set the git commit id (7 bytes):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -ldflags="-X github.com/xtls/xray-core/core.build=REPLACE -s -w -buildid=" -v ./main
|
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="all=-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=REPLACE -s -w -buildid=" -v ./main
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are compiling a 32-bit MIPS/MIPSLE target, use this command instead:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
CGO_ENABLED=0 go build -o xray -trimpath -buildvcs=false -gcflags="-l=4" -ldflags="-X github.com/xtls/xray-core/core.build=REPLACE -s -w -buildid=" -v ./main
|
||||||
```
|
```
|
||||||
|
|
||||||
## Stargazers over time
|
## Stargazers over time
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
)
|
)
|
||||||
@@ -108,3 +109,13 @@ func (co *Outbound) Close() error {
|
|||||||
co.closed = true
|
co.closed = true
|
||||||
return co.listener.Close()
|
return co.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SenderSettings implements outbound.Handler.
|
||||||
|
func (co *Outbound) SenderSettings() *serial.TypedMessage {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxySettings implements outbound.Handler.
|
||||||
|
func (co *Outbound) ProxySettings() *serial.TypedMessage {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ var errSniffingTimeout = errors.New("timeout on sniffing")
|
|||||||
|
|
||||||
type cachedReader struct {
|
type cachedReader struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
reader *pipe.Reader
|
reader buf.TimeoutReader // *pipe.Reader or *buf.TimeoutWrapperReader
|
||||||
cache buf.MultiBuffer
|
cache buf.MultiBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,9 @@ func (r *cachedReader) Interrupt() {
|
|||||||
r.cache = buf.ReleaseMulti(r.cache)
|
r.cache = buf.ReleaseMulti(r.cache)
|
||||||
}
|
}
|
||||||
r.Unlock()
|
r.Unlock()
|
||||||
r.reader.Interrupt()
|
if p, ok := r.reader.(*pipe.Reader); ok {
|
||||||
|
p.Interrupt()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultDispatcher is a default implementation of Dispatcher.
|
// DefaultDispatcher is a default implementation of Dispatcher.
|
||||||
@@ -194,6 +196,47 @@ func (d *DefaultDispatcher) getLink(ctx context.Context) (*transport.Link, *tran
|
|||||||
return inboundLink, outboundLink
|
return inboundLink, outboundLink
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DefaultDispatcher) WrapLink(ctx context.Context, link *transport.Link) *transport.Link {
|
||||||
|
sessionInbound := session.InboundFromContext(ctx)
|
||||||
|
var user *protocol.MemoryUser
|
||||||
|
if sessionInbound != nil {
|
||||||
|
user = sessionInbound.User
|
||||||
|
}
|
||||||
|
|
||||||
|
link.Reader = &buf.TimeoutWrapperReader{Reader: link.Reader}
|
||||||
|
|
||||||
|
if user != nil && len(user.Email) > 0 {
|
||||||
|
p := d.policy.ForLevel(user.Level)
|
||||||
|
if p.Stats.UserUplink {
|
||||||
|
name := "user>>>" + user.Email + ">>>traffic>>>uplink"
|
||||||
|
if c, _ := stats.GetOrRegisterCounter(d.stats, name); c != nil {
|
||||||
|
link.Reader.(*buf.TimeoutWrapperReader).Counter = c
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Stats.UserDownlink {
|
||||||
|
name := "user>>>" + user.Email + ">>>traffic>>>downlink"
|
||||||
|
if c, _ := stats.GetOrRegisterCounter(d.stats, name); c != nil {
|
||||||
|
link.Writer = &SizeStatWriter{
|
||||||
|
Counter: c,
|
||||||
|
Writer: link.Writer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if p.Stats.UserOnline {
|
||||||
|
name := "user>>>" + user.Email + ">>>online"
|
||||||
|
if om, _ := stats.GetOrRegisterOnlineMap(d.stats, name); om != nil {
|
||||||
|
sessionInbounds := session.InboundFromContext(ctx)
|
||||||
|
userIP := sessionInbounds.Source.Address.String()
|
||||||
|
om.AddIP(userIP)
|
||||||
|
// log Online user with ips
|
||||||
|
// errors.LogDebug(ctx, "user>>>" + user.Email + ">>>online", om.Count(), om.List())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return link
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
|
func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResult, request session.SniffingRequest, destination net.Destination) bool {
|
||||||
domain := result.Domain()
|
domain := result.Domain()
|
||||||
if domain == "" {
|
if domain == "" {
|
||||||
@@ -314,12 +357,13 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
|
|||||||
content = new(session.Content)
|
content = new(session.Content)
|
||||||
ctx = session.ContextWithContent(ctx, content)
|
ctx = session.ContextWithContent(ctx, content)
|
||||||
}
|
}
|
||||||
|
outbound = d.WrapLink(ctx, outbound)
|
||||||
sniffingRequest := content.SniffingRequest
|
sniffingRequest := content.SniffingRequest
|
||||||
if !sniffingRequest.Enabled {
|
if !sniffingRequest.Enabled {
|
||||||
d.routedDispatch(ctx, outbound, destination)
|
d.routedDispatch(ctx, outbound, destination)
|
||||||
} else {
|
} else {
|
||||||
cReader := &cachedReader{
|
cReader := &cachedReader{
|
||||||
reader: outbound.Reader.(*pipe.Reader),
|
reader: outbound.Reader.(buf.TimeoutReader),
|
||||||
}
|
}
|
||||||
outbound.Reader = cReader
|
outbound.Reader = cReader
|
||||||
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network)
|
result, err := sniffer(ctx, cReader, sniffingRequest.MetadataOnly, destination.Network)
|
||||||
@@ -439,6 +483,9 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
|
|||||||
handler = h
|
handler = h
|
||||||
} else {
|
} else {
|
||||||
errors.LogWarning(ctx, "non existing outTag: ", outTag)
|
errors.LogWarning(ctx, "non existing outTag: ", outTag)
|
||||||
|
common.Close(link.Writer)
|
||||||
|
common.Interrupt(link.Reader)
|
||||||
|
return // DO NOT CHANGE: the traffic shouldn't be processed by default outbound if the specified outbound tag doesn't exist (yet), e.g., VLESS Reverse Proxy
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
errors.LogInfo(ctx, "default route for ", destination)
|
errors.LogInfo(ctx, "default route for ", destination)
|
||||||
|
|||||||
@@ -3,36 +3,55 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
go_errors "errors"
|
go_errors "errors"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
"github.com/xtls/xray-core/common/signal/pubsub"
|
"github.com/xtls/xray-core/common/signal/pubsub"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
"sync"
|
"golang.org/x/sync/singleflight"
|
||||||
"time"
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
minSizeForEmptyRebuild = 512
|
||||||
|
shrinkAbsoluteThreshold = 10240
|
||||||
|
shrinkRatioThreshold = 0.65
|
||||||
|
migrationBatchSize = 4096
|
||||||
)
|
)
|
||||||
|
|
||||||
type CacheController struct {
|
type CacheController struct {
|
||||||
|
name string
|
||||||
|
disableCache bool
|
||||||
|
serveStale bool
|
||||||
|
serveExpiredTTL int32
|
||||||
|
|
||||||
|
ips map[string]*record
|
||||||
|
dirtyips map[string]*record
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
ips map[string]*record
|
pub *pubsub.Service
|
||||||
pub *pubsub.Service
|
cacheCleanup *task.Periodic
|
||||||
cacheCleanup *task.Periodic
|
highWatermark int
|
||||||
name string
|
requestGroup singleflight.Group
|
||||||
disableCache bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCacheController(name string, disableCache bool) *CacheController {
|
func NewCacheController(name string, disableCache bool, serveStale bool, serveExpiredTTL uint32) *CacheController {
|
||||||
c := &CacheController{
|
c := &CacheController{
|
||||||
name: name,
|
name: name,
|
||||||
disableCache: disableCache,
|
disableCache: disableCache,
|
||||||
ips: make(map[string]*record),
|
serveStale: serveStale,
|
||||||
pub: pubsub.NewService(),
|
serveExpiredTTL: -int32(serveExpiredTTL),
|
||||||
|
ips: make(map[string]*record),
|
||||||
|
pub: pubsub.NewService(),
|
||||||
}
|
}
|
||||||
|
|
||||||
c.cacheCleanup = &task.Periodic{
|
c.cacheCleanup = &task.Periodic{
|
||||||
Interval: time.Minute,
|
Interval: 300 * time.Second,
|
||||||
Execute: c.CacheCleanup,
|
Execute: c.CacheCleanup,
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
@@ -40,131 +59,263 @@ func NewCacheController(name string, disableCache bool) *CacheController {
|
|||||||
|
|
||||||
// CacheCleanup clears expired items from cache
|
// CacheCleanup clears expired items from cache
|
||||||
func (c *CacheController) CacheCleanup() error {
|
func (c *CacheController) CacheCleanup() error {
|
||||||
now := time.Now()
|
expiredKeys, err := c.collectExpiredKeys()
|
||||||
c.Lock()
|
if err != nil {
|
||||||
defer c.Unlock()
|
return err
|
||||||
|
|
||||||
if len(c.ips) == 0 {
|
|
||||||
return errors.New("nothing to do. stopping...")
|
|
||||||
}
|
}
|
||||||
|
if len(expiredKeys) == 0 {
|
||||||
for domain, record := range c.ips {
|
return nil
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
c.writeAndShrink(expiredKeys)
|
||||||
if len(c.ips) == 0 {
|
|
||||||
c.ips = make(map[string]*record)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheController) updateIP(req *dnsRequest, ipRec *IPRecord) {
|
func (c *CacheController) collectExpiredKeys() ([]string, error) {
|
||||||
elapsed := time.Since(req.start)
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
|
||||||
c.Lock()
|
if len(c.ips) == 0 {
|
||||||
rec, found := c.ips[req.domain]
|
return nil, errors.New("nothing to do. stopping...")
|
||||||
if !found {
|
|
||||||
rec = &record{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch req.reqType {
|
// skip collection if a migration is in progress
|
||||||
case dnsmessage.TypeA:
|
if c.dirtyips != nil {
|
||||||
rec.A = ipRec
|
return nil, nil
|
||||||
case dnsmessage.TypeAAAA:
|
|
||||||
rec.AAAA = ipRec
|
|
||||||
}
|
}
|
||||||
|
|
||||||
errors.LogInfo(context.Background(), c.name, " got answer: ", req.domain, " ", req.reqType, " -> ", ipRec.IP, " ", elapsed)
|
now := time.Now()
|
||||||
c.ips[req.domain] = rec
|
if c.serveStale && c.serveExpiredTTL != 0 {
|
||||||
|
now = now.Add(time.Duration(c.serveExpiredTTL) * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
switch req.reqType {
|
expiredKeys := make([]string, 0, len(c.ips)/4) // pre-allocate
|
||||||
case dnsmessage.TypeA:
|
|
||||||
c.pub.Publish(req.domain+"4", nil)
|
for domain, rec := range c.ips {
|
||||||
if !c.disableCache {
|
if (rec.A != nil && rec.A.Expire.Before(now)) ||
|
||||||
_, _, err := rec.AAAA.getIPs()
|
(rec.AAAA != nil && rec.AAAA.Expire.Before(now)) {
|
||||||
if !go_errors.Is(err, errRecordNotFound) {
|
expiredKeys = append(expiredKeys, domain)
|
||||||
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()
|
return expiredKeys, nil
|
||||||
common.Must(c.cacheCleanup.Start())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheController) findIPsForDomain(domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
func (c *CacheController) writeAndShrink(expiredKeys []string) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
|
||||||
|
// double check to prevent upper call multiple cleanup tasks
|
||||||
|
if c.dirtyips != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lenBefore := len(c.ips)
|
||||||
|
if lenBefore > c.highWatermark {
|
||||||
|
c.highWatermark = lenBefore
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
if c.serveStale && c.serveExpiredTTL != 0 {
|
||||||
|
now = now.Add(time.Duration(c.serveExpiredTTL) * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, domain := range expiredKeys {
|
||||||
|
rec := c.ips[domain]
|
||||||
|
if rec == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if rec.A != nil && rec.A.Expire.Before(now) {
|
||||||
|
rec.A = nil
|
||||||
|
}
|
||||||
|
if rec.AAAA != nil && rec.AAAA.Expire.Before(now) {
|
||||||
|
rec.AAAA = nil
|
||||||
|
}
|
||||||
|
if rec.A == nil && rec.AAAA == nil {
|
||||||
|
delete(c.ips, domain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lenAfter := len(c.ips)
|
||||||
|
|
||||||
|
if lenAfter == 0 {
|
||||||
|
if c.highWatermark >= minSizeForEmptyRebuild {
|
||||||
|
errors.LogDebug(context.Background(), c.name,
|
||||||
|
" rebuilding empty cache map to reclaim memory.",
|
||||||
|
" size_before_cleanup=", lenBefore,
|
||||||
|
" peak_size_before_rebuild=", c.highWatermark,
|
||||||
|
)
|
||||||
|
|
||||||
|
c.ips = make(map[string]*record)
|
||||||
|
c.highWatermark = 0
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if reductionFromPeak := c.highWatermark - lenAfter; reductionFromPeak > shrinkAbsoluteThreshold &&
|
||||||
|
float64(reductionFromPeak) > float64(c.highWatermark)*shrinkRatioThreshold {
|
||||||
|
errors.LogDebug(context.Background(), c.name,
|
||||||
|
" shrinking cache map to reclaim memory.",
|
||||||
|
" new_size=", lenAfter,
|
||||||
|
" peak_size_before_shrink=", c.highWatermark,
|
||||||
|
" reduction_since_peak=", reductionFromPeak,
|
||||||
|
)
|
||||||
|
|
||||||
|
c.dirtyips = c.ips
|
||||||
|
c.ips = make(map[string]*record, int(float64(lenAfter)*1.1))
|
||||||
|
c.highWatermark = lenAfter
|
||||||
|
go c.migrate()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type migrationEntry struct {
|
||||||
|
key string
|
||||||
|
value *record
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CacheController) migrate() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
errors.LogError(context.Background(), c.name, " panic during cache migration: ", r)
|
||||||
|
c.Lock()
|
||||||
|
c.dirtyips = nil
|
||||||
|
// c.ips = make(map[string]*record)
|
||||||
|
// c.highWatermark = 0
|
||||||
|
c.Unlock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
c.RLock()
|
c.RLock()
|
||||||
record, found := c.ips[domain]
|
dirtyips := c.dirtyips
|
||||||
c.RUnlock()
|
c.RUnlock()
|
||||||
|
|
||||||
if !found {
|
// double check to prevent upper call multiple cleanup tasks
|
||||||
return nil, 0, errRecordNotFound
|
if dirtyips == nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var errs []error
|
errors.LogDebug(context.Background(), c.name, " starting background cache migration for ", len(dirtyips), " items")
|
||||||
var allIPs []net.IP
|
|
||||||
var rTTL uint32 = dns_feature.DefaultTTL
|
|
||||||
|
|
||||||
mergeReq := option.IPv4Enable && option.IPv6Enable
|
batch := make([]migrationEntry, 0, migrationBatchSize)
|
||||||
|
for domain, recD := range dirtyips {
|
||||||
|
batch = append(batch, migrationEntry{domain, recD})
|
||||||
|
|
||||||
if option.IPv4Enable {
|
if len(batch) >= migrationBatchSize {
|
||||||
ips, ttl, err := record.A.getIPs()
|
c.flush(batch)
|
||||||
if !mergeReq || go_errors.Is(err, errRecordNotFound) {
|
batch = batch[:0]
|
||||||
return ips, ttl, err
|
runtime.Gosched()
|
||||||
}
|
}
|
||||||
if ttl < rTTL {
|
}
|
||||||
rTTL = ttl
|
if len(batch) > 0 {
|
||||||
}
|
c.flush(batch)
|
||||||
if len(ips) > 0 {
|
}
|
||||||
allIPs = append(allIPs, ips...)
|
|
||||||
|
c.Lock()
|
||||||
|
c.dirtyips = nil
|
||||||
|
c.Unlock()
|
||||||
|
|
||||||
|
errors.LogDebug(context.Background(), c.name, " cache migration completed")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CacheController) flush(batch []migrationEntry) {
|
||||||
|
c.Lock()
|
||||||
|
defer c.Unlock()
|
||||||
|
|
||||||
|
for _, dirty := range batch {
|
||||||
|
if cur := c.ips[dirty.key]; cur != nil {
|
||||||
|
merge := &record{}
|
||||||
|
if cur.A == nil {
|
||||||
|
merge.A = dirty.value.A
|
||||||
|
} else {
|
||||||
|
merge.A = cur.A
|
||||||
|
}
|
||||||
|
if cur.AAAA == nil {
|
||||||
|
merge.AAAA = dirty.value.AAAA
|
||||||
|
} else {
|
||||||
|
merge.AAAA = cur.AAAA
|
||||||
|
}
|
||||||
|
c.ips[dirty.key] = merge
|
||||||
} else {
|
} else {
|
||||||
errs = append(errs, err)
|
c.ips[dirty.key] = dirty.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CacheController) updateRecord(req *dnsRequest, rep *IPRecord) {
|
||||||
|
rtt := time.Since(req.start)
|
||||||
|
|
||||||
|
switch req.reqType {
|
||||||
|
case dnsmessage.TypeA:
|
||||||
|
c.pub.Publish(req.domain+"4", rep)
|
||||||
|
case dnsmessage.TypeAAAA:
|
||||||
|
c.pub.Publish(req.domain+"6", rep)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.disableCache {
|
||||||
|
errors.LogInfo(context.Background(), c.name, " got answer: ", req.domain, " ", req.reqType, " -> ", rep.IP, ", rtt: ", rtt)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.Lock()
|
||||||
|
lockWait := time.Since(req.start) - rtt
|
||||||
|
|
||||||
|
newRec := &record{}
|
||||||
|
oldRec := c.ips[req.domain]
|
||||||
|
var dirtyRec *record
|
||||||
|
if c.dirtyips != nil {
|
||||||
|
dirtyRec = c.dirtyips[req.domain]
|
||||||
|
}
|
||||||
|
|
||||||
|
var pubRecord *IPRecord
|
||||||
|
var pubSuffix string
|
||||||
|
|
||||||
|
switch req.reqType {
|
||||||
|
case dnsmessage.TypeA:
|
||||||
|
newRec.A = rep
|
||||||
|
if oldRec != nil && oldRec.AAAA != nil {
|
||||||
|
newRec.AAAA = oldRec.AAAA
|
||||||
|
pubRecord = oldRec.AAAA
|
||||||
|
} else if dirtyRec != nil && dirtyRec.AAAA != nil {
|
||||||
|
pubRecord = dirtyRec.AAAA
|
||||||
|
}
|
||||||
|
pubSuffix = "6"
|
||||||
|
case dnsmessage.TypeAAAA:
|
||||||
|
newRec.AAAA = rep
|
||||||
|
if oldRec != nil && oldRec.A != nil {
|
||||||
|
newRec.A = oldRec.A
|
||||||
|
pubRecord = oldRec.A
|
||||||
|
} else if dirtyRec != nil && dirtyRec.A != nil {
|
||||||
|
pubRecord = dirtyRec.A
|
||||||
|
}
|
||||||
|
pubSuffix = "4"
|
||||||
|
}
|
||||||
|
|
||||||
|
c.ips[req.domain] = newRec
|
||||||
|
c.Unlock()
|
||||||
|
|
||||||
|
if pubRecord != nil {
|
||||||
|
_, ttl, err := pubRecord.getIPs()
|
||||||
|
if ttl > 0 && !go_errors.Is(err, errRecordNotFound) {
|
||||||
|
c.pub.Publish(req.domain+pubSuffix, pubRecord)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if option.IPv6Enable {
|
errors.LogInfo(context.Background(), c.name, " got answer: ", req.domain, " ", req.reqType, " -> ", rep.IP, ", rtt: ", rtt, ", lock: ", lockWait)
|
||||||
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 {
|
if !c.serveStale || c.serveExpiredTTL != 0 {
|
||||||
return allIPs, rTTL, nil
|
common.Must(c.cacheCleanup.Start())
|
||||||
}
|
}
|
||||||
if go_errors.Is(errs[0], errs[1]) {
|
}
|
||||||
return nil, rTTL, errs[0]
|
|
||||||
|
func (c *CacheController) findRecords(domain string) *record {
|
||||||
|
c.RLock()
|
||||||
|
defer c.RUnlock()
|
||||||
|
|
||||||
|
rec := c.ips[domain]
|
||||||
|
if rec == nil && c.dirtyips != nil {
|
||||||
|
rec = c.dirtyips[domain]
|
||||||
}
|
}
|
||||||
return nil, rTTL, errors.Combine(errs...)
|
return rec
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CacheController) registerSubscribers(domain string, option dns_feature.IPOption) (sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
|
func (c *CacheController) registerSubscribers(domain string, option dns_feature.IPOption) (sub4 *pubsub.Subscriber, sub6 *pubsub.Subscriber) {
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ const (
|
|||||||
QueryStrategy_USE_IP QueryStrategy = 0
|
QueryStrategy_USE_IP QueryStrategy = 0
|
||||||
QueryStrategy_USE_IP4 QueryStrategy = 1
|
QueryStrategy_USE_IP4 QueryStrategy = 1
|
||||||
QueryStrategy_USE_IP6 QueryStrategy = 2
|
QueryStrategy_USE_IP6 QueryStrategy = 2
|
||||||
|
QueryStrategy_USE_SYS QueryStrategy = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for QueryStrategy.
|
// Enum value maps for QueryStrategy.
|
||||||
@@ -88,11 +89,13 @@ var (
|
|||||||
0: "USE_IP",
|
0: "USE_IP",
|
||||||
1: "USE_IP4",
|
1: "USE_IP4",
|
||||||
2: "USE_IP6",
|
2: "USE_IP6",
|
||||||
|
3: "USE_SYS",
|
||||||
}
|
}
|
||||||
QueryStrategy_value = map[string]int32{
|
QueryStrategy_value = map[string]int32{
|
||||||
"USE_IP": 0,
|
"USE_IP": 0,
|
||||||
"USE_IP4": 1,
|
"USE_IP4": 1,
|
||||||
"USE_IP6": 2,
|
"USE_IP6": 2,
|
||||||
|
"USE_SYS": 3,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -128,16 +131,23 @@ type NameServer struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
Address *net.Endpoint `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||||
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
|
ClientIp []byte `protobuf:"bytes,5,opt,name=client_ip,json=clientIp,proto3" json:"client_ip,omitempty"`
|
||||||
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
|
SkipFallback bool `protobuf:"varint,6,opt,name=skipFallback,proto3" json:"skipFallback,omitempty"`
|
||||||
PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
|
PrioritizedDomain []*NameServer_PriorityDomain `protobuf:"bytes,2,rep,name=prioritized_domain,json=prioritizedDomain,proto3" json:"prioritized_domain,omitempty"`
|
||||||
Geoip []*router.GeoIP `protobuf:"bytes,3,rep,name=geoip,proto3" json:"geoip,omitempty"`
|
ExpectedGeoip []*router.GeoIP `protobuf:"bytes,3,rep,name=expected_geoip,json=expectedGeoip,proto3" json:"expected_geoip,omitempty"`
|
||||||
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
|
OriginalRules []*NameServer_OriginalRule `protobuf:"bytes,4,rep,name=original_rules,json=originalRules,proto3" json:"original_rules,omitempty"`
|
||||||
QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
QueryStrategy QueryStrategy `protobuf:"varint,7,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
||||||
AllowUnexpectedIPs bool `protobuf:"varint,8,opt,name=allowUnexpectedIPs,proto3" json:"allowUnexpectedIPs,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"`
|
Tag string `protobuf:"bytes,9,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
TimeoutMs uint64 `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
|
TimeoutMs uint64 `protobuf:"varint,10,opt,name=timeoutMs,proto3" json:"timeoutMs,omitempty"`
|
||||||
|
DisableCache *bool `protobuf:"varint,11,opt,name=disableCache,proto3,oneof" json:"disableCache,omitempty"`
|
||||||
|
ServeStale *bool `protobuf:"varint,15,opt,name=serveStale,proto3,oneof" json:"serveStale,omitempty"`
|
||||||
|
ServeExpiredTTL *uint32 `protobuf:"varint,16,opt,name=serveExpiredTTL,proto3,oneof" json:"serveExpiredTTL,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"`
|
||||||
|
PolicyID uint32 `protobuf:"varint,17,opt,name=policyID,proto3" json:"policyID,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) Reset() {
|
func (x *NameServer) Reset() {
|
||||||
@@ -198,9 +208,9 @@ func (x *NameServer) GetPrioritizedDomain() []*NameServer_PriorityDomain {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetGeoip() []*router.GeoIP {
|
func (x *NameServer) GetExpectedGeoip() []*router.GeoIP {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Geoip
|
return x.ExpectedGeoip
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -219,9 +229,9 @@ func (x *NameServer) GetQueryStrategy() QueryStrategy {
|
|||||||
return QueryStrategy_USE_IP
|
return QueryStrategy_USE_IP
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *NameServer) GetAllowUnexpectedIPs() bool {
|
func (x *NameServer) GetActPrior() bool {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.AllowUnexpectedIPs
|
return x.ActPrior
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -240,6 +250,55 @@ func (x *NameServer) GetTimeoutMs() uint64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *NameServer) GetDisableCache() bool {
|
||||||
|
if x != nil && x.DisableCache != nil {
|
||||||
|
return *x.DisableCache
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NameServer) GetServeStale() bool {
|
||||||
|
if x != nil && x.ServeStale != nil {
|
||||||
|
return *x.ServeStale
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NameServer) GetServeExpiredTTL() uint32 {
|
||||||
|
if x != nil && x.ServeExpiredTTL != nil {
|
||||||
|
return *x.ServeExpiredTTL
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *NameServer) GetPolicyID() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.PolicyID
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -256,9 +315,12 @@ type Config struct {
|
|||||||
Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"`
|
Tag string `protobuf:"bytes,6,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||||
// DisableCache disables DNS cache
|
// DisableCache disables DNS cache
|
||||||
DisableCache bool `protobuf:"varint,8,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
|
DisableCache bool `protobuf:"varint,8,opt,name=disableCache,proto3" json:"disableCache,omitempty"`
|
||||||
|
ServeStale bool `protobuf:"varint,12,opt,name=serveStale,proto3" json:"serveStale,omitempty"`
|
||||||
|
ServeExpiredTTL uint32 `protobuf:"varint,13,opt,name=serveExpiredTTL,proto3" json:"serveExpiredTTL,omitempty"`
|
||||||
QueryStrategy QueryStrategy `protobuf:"varint,9,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
QueryStrategy QueryStrategy `protobuf:"varint,9,opt,name=query_strategy,json=queryStrategy,proto3,enum=xray.app.dns.QueryStrategy" json:"query_strategy,omitempty"`
|
||||||
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
|
DisableFallback bool `protobuf:"varint,10,opt,name=disableFallback,proto3" json:"disableFallback,omitempty"`
|
||||||
DisableFallbackIfMatch bool `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
|
DisableFallbackIfMatch bool `protobuf:"varint,11,opt,name=disableFallbackIfMatch,proto3" json:"disableFallbackIfMatch,omitempty"`
|
||||||
|
EnableParallelQuery bool `protobuf:"varint,14,opt,name=enableParallelQuery,proto3" json:"enableParallelQuery,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -326,6 +388,20 @@ func (x *Config) GetDisableCache() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetServeStale() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.ServeStale
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetServeExpiredTTL() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.ServeExpiredTTL
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
func (x *Config) GetQueryStrategy() QueryStrategy {
|
func (x *Config) GetQueryStrategy() QueryStrategy {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.QueryStrategy
|
return x.QueryStrategy
|
||||||
@@ -347,6 +423,13 @@ func (x *Config) GetDisableFallbackIfMatch() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Config) GetEnableParallelQuery() bool {
|
||||||
|
if x != nil {
|
||||||
|
return x.EnableParallelQuery
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type NameServer_PriorityDomain struct {
|
type NameServer_PriorityDomain struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -532,7 +615,7 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
|||||||
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
0x2e, 0x64, 0x6e, 0x73, 0x1a, 0x1c, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74,
|
||||||
0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
0x2f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
0x74, 0x6f, 0x1a, 0x17, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2f, 0x63,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x92, 0x05, 0x0a, 0x0a,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdf, 0x07, 0x0a, 0x0a,
|
||||||
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
|
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x33, 0x0a, 0x07, 0x61, 0x64,
|
||||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x45, 0x6e,
|
||||||
@@ -546,81 +629,111 @@ var file_app_dns_config_proto_rawDesc = []byte{
|
|||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d, 0x65,
|
||||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44,
|
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44,
|
||||||
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a,
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x11, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x7a,
|
||||||
0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x2c, 0x0a, 0x05, 0x67, 0x65, 0x6f, 0x69,
|
0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x3d, 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x65,
|
||||||
0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61,
|
0x63, 0x74, 0x65, 0x64, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
|
||||||
0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52,
|
0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||||
0x05, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
|
0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0d, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74,
|
||||||
0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25,
|
0x65, 0x64, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x4c, 0x0a, 0x0e, 0x6f, 0x72, 0x69, 0x67, 0x69,
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61,
|
0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
||||||
0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61,
|
0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e,
|
||||||
0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52,
|
0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e,
|
||||||
0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74,
|
0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78,
|
0x52, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,
|
||||||
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65,
|
||||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f,
|
0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72,
|
||||||
0x77, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x49, 0x50, 0x73, 0x18, 0x08,
|
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x63, 0x74,
|
||||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x55, 0x6e, 0x65, 0x78, 0x70,
|
0x50, 0x72, 0x69, 0x6f, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x63, 0x74,
|
||||||
0x65, 0x63, 0x74, 0x65, 0x64, 0x49, 0x50, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
|
0x50, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x09, 0x20, 0x01,
|
||||||
0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69,
|
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x6f,
|
||||||
0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74,
|
0x75, 0x74, 0x4d, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
||||||
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4d, 0x73, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f,
|
0x6f, 0x75, 0x74, 0x4d, 0x73, 0x12, 0x27, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65,
|
||||||
0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79,
|
0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0c, 0x64,
|
||||||
0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x88, 0x01, 0x01, 0x12, 0x23,
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61,
|
0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x01,
|
||||||
0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
0x28, 0x08, 0x48, 0x01, 0x52, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65,
|
||||||
0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
0x88, 0x01, 0x01, 0x12, 0x2d, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69,
|
||||||
0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67,
|
0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0d, 0x48, 0x02, 0x52, 0x0f,
|
||||||
0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x88,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
0x01, 0x01, 0x12, 0x1e, 0x0a, 0x0a, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79,
|
||||||
0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65,
|
0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x51, 0x75, 0x65,
|
||||||
0x22, 0x9c, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x6e,
|
0x72, 0x79, 0x12, 0x41, 0x0a, 0x10, 0x75, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
|
||||||
0x61, 0x6d, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
|
0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78,
|
||||||
0x32, 0x18, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47,
|
||||||
0x4e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65,
|
0x65, 0x6f, 0x49, 0x50, 0x52, 0x0f, 0x75, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64,
|
||||||
0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
|
0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e, 0x70, 0x72,
|
||||||
0x5f, 0x69, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e,
|
0x69, 0x6f, 0x72, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x63, 0x74, 0x55, 0x6e,
|
||||||
0x74, 0x49, 0x70, 0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f,
|
0x70, 0x72, 0x69, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49,
|
||||||
0x73, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x44, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49,
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
0x44, 0x1a, 0x5e, 0x0a, 0x0e, 0x50, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x44, 0x6f, 0x6d,
|
||||||
0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61,
|
0x61, 0x69, 0x6e, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
|
0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73,
|
||||||
0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69,
|
0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54,
|
||||||
0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08,
|
0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d,
|
||||||
0x52, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x42,
|
0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x6e, 0x1a, 0x36, 0x0a, 0x0c, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x52, 0x75, 0x6c,
|
||||||
0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74,
|
0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20,
|
||||||
0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65,
|
0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x64, 0x69,
|
||||||
0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c,
|
0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x73,
|
||||||
0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x73,
|
0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x73, 0x65,
|
||||||
0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a, 0x16,
|
0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x22, 0x98, 0x05,
|
||||||
0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49,
|
0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x39, 0x0a, 0x0b, 0x6e, 0x61, 0x6d, 0x65,
|
||||||
0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x64, 0x69,
|
0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e,
|
||||||
0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x4e, 0x61, 0x6d,
|
||||||
0x61, 0x74, 0x63, 0x68, 0x1a, 0x92, 0x01, 0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70,
|
0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x52, 0x0a, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x65, 0x72,
|
||||||
0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
|
0x76, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x70,
|
||||||
0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e,
|
0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x70,
|
||||||
0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67,
|
0x12, 0x43, 0x0a, 0x0c, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x73,
|
||||||
0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f,
|
0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61,
|
0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x6f, 0x73,
|
||||||
0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02,
|
0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63,
|
||||||
0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f,
|
0x48, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x06, 0x20, 0x01,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78,
|
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x22, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x61, 0x62,
|
||||||
0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a,
|
0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x64,
|
||||||
0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e,
|
0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x73,
|
||||||
0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12,
|
0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b,
|
0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x53, 0x74, 0x61, 0x6c, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x73,
|
||||||
0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f, 0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52,
|
0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x54, 0x54, 0x4c, 0x18, 0x0d,
|
||||||
0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a, 0x35, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53,
|
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49,
|
0x65, 0x64, 0x54, 0x54, 0x4c, 0x12, 0x42, 0x0a, 0x0e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x73,
|
||||||
0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e,
|
||||||
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x42, 0x46, 0x0a,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x51, 0x75, 0x65,
|
||||||
0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e,
|
0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0d, 0x71, 0x75, 0x65, 0x72,
|
||||||
0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x73,
|
||||||
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61,
|
0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01,
|
||||||
0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70,
|
0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c, 0x62,
|
||||||
0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x61, 0x63, 0x6b, 0x12, 0x36, 0x0a, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61,
|
||||||
|
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x0b, 0x20,
|
||||||
|
0x01, 0x28, 0x08, 0x52, 0x16, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x61, 0x6c, 0x6c,
|
||||||
|
0x62, 0x61, 0x63, 0x6b, 0x49, 0x66, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x30, 0x0a, 0x13, 0x65,
|
||||||
|
0x6e, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x51, 0x75, 0x65,
|
||||||
|
0x72, 0x79, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||||
|
0x50, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x92, 0x01,
|
||||||
|
0x0a, 0x0b, 0x48, 0x6f, 0x73, 0x74, 0x4d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x12, 0x34, 0x0a,
|
||||||
|
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x20, 0x2e, 0x78, 0x72,
|
||||||
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
|
0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
|
||||||
|
0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||||
|
0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x02, 0x69, 0x70, 0x12, 0x25, 0x0a, 0x0e, 0x70,
|
||||||
|
0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x04, 0x20,
|
||||||
|
0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x64, 0x44, 0x6f, 0x6d, 0x61,
|
||||||
|
0x69, 0x6e, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x2a, 0x45, 0x0a, 0x12, 0x44, 0x6f, 0x6d, 0x61,
|
||||||
|
0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x69, 0x6e, 0x67, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08,
|
||||||
|
0x0a, 0x04, 0x46, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x64,
|
||||||
|
0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x77, 0x6f,
|
||||||
|
0x72, 0x64, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x67, 0x65, 0x78, 0x10, 0x03, 0x2a,
|
||||||
|
0x42, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
|
0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07,
|
||||||
|
0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45,
|
||||||
|
0x5f, 0x49, 0x50, 0x36, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x53, 0x59,
|
||||||
|
0x53, 0x10, 0x03, 0x42, 0x46, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
|
0x61, 0x70, 0x70, 0x2e, 0x64, 0x6e, 0x73, 0x50, 0x01, 0x5a, 0x21, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||||
|
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
||||||
|
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x64, 0x6e, 0x73, 0xaa, 0x02, 0x0c, 0x58,
|
||||||
|
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x44, 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||||
|
0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -651,19 +764,20 @@ var file_app_dns_config_proto_goTypes = []any{
|
|||||||
var file_app_dns_config_proto_depIdxs = []int32{
|
var file_app_dns_config_proto_depIdxs = []int32{
|
||||||
7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
|
7, // 0: xray.app.dns.NameServer.address:type_name -> xray.common.net.Endpoint
|
||||||
4, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
|
4, // 1: xray.app.dns.NameServer.prioritized_domain:type_name -> xray.app.dns.NameServer.PriorityDomain
|
||||||
8, // 2: xray.app.dns.NameServer.geoip:type_name -> xray.app.router.GeoIP
|
8, // 2: xray.app.dns.NameServer.expected_geoip:type_name -> xray.app.router.GeoIP
|
||||||
5, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
|
5, // 3: xray.app.dns.NameServer.original_rules:type_name -> xray.app.dns.NameServer.OriginalRule
|
||||||
1, // 4: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
1, // 4: xray.app.dns.NameServer.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
||||||
2, // 5: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
|
8, // 5: xray.app.dns.NameServer.unexpected_geoip:type_name -> xray.app.router.GeoIP
|
||||||
6, // 6: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
|
2, // 6: xray.app.dns.Config.name_server:type_name -> xray.app.dns.NameServer
|
||||||
1, // 7: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
6, // 7: xray.app.dns.Config.static_hosts:type_name -> xray.app.dns.Config.HostMapping
|
||||||
0, // 8: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
|
1, // 8: xray.app.dns.Config.query_strategy:type_name -> xray.app.dns.QueryStrategy
|
||||||
0, // 9: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
|
0, // 9: xray.app.dns.NameServer.PriorityDomain.type:type_name -> xray.app.dns.DomainMatchingType
|
||||||
10, // [10:10] is the sub-list for method output_type
|
0, // 10: xray.app.dns.Config.HostMapping.type:type_name -> xray.app.dns.DomainMatchingType
|
||||||
10, // [10:10] is the sub-list for method input_type
|
11, // [11:11] is the sub-list for method output_type
|
||||||
10, // [10:10] is the sub-list for extension type_name
|
11, // [11:11] is the sub-list for method input_type
|
||||||
10, // [10:10] is the sub-list for extension extendee
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
0, // [0:10] is the sub-list for field type_name
|
11, // [11:11] is the sub-list for extension extendee
|
||||||
|
0, // [0:11] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_dns_config_proto_init() }
|
func init() { file_app_dns_config_proto_init() }
|
||||||
@@ -671,6 +785,7 @@ func file_app_dns_config_proto_init() {
|
|||||||
if File_app_dns_config_proto != nil {
|
if File_app_dns_config_proto != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
file_app_dns_config_proto_msgTypes[0].OneofWrappers = []any{}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
|
|||||||
@@ -25,12 +25,19 @@ message NameServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repeated PriorityDomain prioritized_domain = 2;
|
repeated PriorityDomain prioritized_domain = 2;
|
||||||
repeated xray.app.router.GeoIP geoip = 3;
|
repeated xray.app.router.GeoIP expected_geoip = 3;
|
||||||
repeated OriginalRule original_rules = 4;
|
repeated OriginalRule original_rules = 4;
|
||||||
QueryStrategy query_strategy = 7;
|
QueryStrategy query_strategy = 7;
|
||||||
bool allowUnexpectedIPs = 8;
|
bool actPrior = 8;
|
||||||
string tag = 9;
|
string tag = 9;
|
||||||
uint64 timeoutMs = 10;
|
uint64 timeoutMs = 10;
|
||||||
|
optional bool disableCache = 11;
|
||||||
|
optional bool serveStale = 15;
|
||||||
|
optional uint32 serveExpiredTTL = 16;
|
||||||
|
bool finalQuery = 12;
|
||||||
|
repeated xray.app.router.GeoIP unexpected_geoip = 13;
|
||||||
|
bool actUnprior = 14;
|
||||||
|
uint32 policyID = 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DomainMatchingType {
|
enum DomainMatchingType {
|
||||||
@@ -44,6 +51,7 @@ enum QueryStrategy {
|
|||||||
USE_IP = 0;
|
USE_IP = 0;
|
||||||
USE_IP4 = 1;
|
USE_IP4 = 1;
|
||||||
USE_IP6 = 2;
|
USE_IP6 = 2;
|
||||||
|
USE_SYS = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
@@ -75,9 +83,13 @@ message Config {
|
|||||||
|
|
||||||
// DisableCache disables DNS cache
|
// DisableCache disables DNS cache
|
||||||
bool disableCache = 8;
|
bool disableCache = 8;
|
||||||
|
bool serveStale = 12;
|
||||||
|
uint32 serveExpiredTTL = 13;
|
||||||
|
|
||||||
QueryStrategy query_strategy = 9;
|
QueryStrategy query_strategy = 9;
|
||||||
|
|
||||||
bool disableFallback = 10;
|
bool disableFallback = 10;
|
||||||
bool disableFallbackIfMatch = 11;
|
bool disableFallbackIfMatch = 11;
|
||||||
|
|
||||||
|
bool enableParallelQuery = 14;
|
||||||
}
|
}
|
||||||
|
|||||||
363
app/dns/dns.go
363
app/dns/dns.go
@@ -5,9 +5,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
go_errors "errors"
|
go_errors "errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
@@ -22,12 +25,14 @@ type DNS struct {
|
|||||||
sync.Mutex
|
sync.Mutex
|
||||||
disableFallback bool
|
disableFallback bool
|
||||||
disableFallbackIfMatch bool
|
disableFallbackIfMatch bool
|
||||||
|
enableParallelQuery bool
|
||||||
ipOption *dns.IPOption
|
ipOption *dns.IPOption
|
||||||
hosts *StaticHosts
|
hosts *StaticHosts
|
||||||
clients []*Client
|
clients []*Client
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
domainMatcher strmatcher.IndexMatcher
|
domainMatcher strmatcher.IndexMatcher
|
||||||
matcherInfos []*DomainMatcherInfo
|
matcherInfos []*DomainMatcherInfo
|
||||||
|
checkSystem bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
|
// DomainMatcherInfo contains information attached to index returned by Server.domainMatcher
|
||||||
@@ -47,6 +52,7 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ipOption dns.IPOption
|
var ipOption dns.IPOption
|
||||||
|
checkSystem := false
|
||||||
switch config.QueryStrategy {
|
switch config.QueryStrategy {
|
||||||
case QueryStrategy_USE_IP:
|
case QueryStrategy_USE_IP:
|
||||||
ipOption = dns.IPOption{
|
ipOption = dns.IPOption{
|
||||||
@@ -54,6 +60,13 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
FakeEnable: false,
|
FakeEnable: false,
|
||||||
}
|
}
|
||||||
|
case QueryStrategy_USE_SYS:
|
||||||
|
ipOption = dns.IPOption{
|
||||||
|
IPv4Enable: true,
|
||||||
|
IPv6Enable: true,
|
||||||
|
FakeEnable: false,
|
||||||
|
}
|
||||||
|
checkSystem = true
|
||||||
case QueryStrategy_USE_IP4:
|
case QueryStrategy_USE_IP4:
|
||||||
ipOption = dns.IPOption{
|
ipOption = dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
@@ -109,6 +122,19 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
disableCache := config.DisableCache
|
disableCache := config.DisableCache
|
||||||
|
if ns.DisableCache != nil {
|
||||||
|
disableCache = *ns.DisableCache
|
||||||
|
}
|
||||||
|
|
||||||
|
serveStale := config.ServeStale
|
||||||
|
if ns.ServeStale != nil {
|
||||||
|
serveStale = *ns.ServeStale
|
||||||
|
}
|
||||||
|
|
||||||
|
serveExpiredTTL := config.ServeExpiredTTL
|
||||||
|
if ns.ServeExpiredTTL != nil {
|
||||||
|
serveExpiredTTL = *ns.ServeExpiredTTL
|
||||||
|
}
|
||||||
|
|
||||||
var tag = defaultTag
|
var tag = defaultTag
|
||||||
if len(ns.Tag) > 0 {
|
if len(ns.Tag) > 0 {
|
||||||
@@ -118,7 +144,8 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
if !clientIPOption.IPv4Enable && !clientIPOption.IPv6Enable {
|
if !clientIPOption.IPv4Enable && !clientIPOption.IPv6Enable {
|
||||||
return nil, errors.New("no QueryStrategy available for ", ns.Address)
|
return nil, errors.New("no QueryStrategy available for ", ns.Address)
|
||||||
}
|
}
|
||||||
client, err := NewClient(ctx, ns, myClientIP, disableCache, tag, clientIPOption, &matcherInfos, updateDomain)
|
|
||||||
|
client, err := NewClient(ctx, ns, myClientIP, disableCache, serveStale, serveExpiredTTL, tag, clientIPOption, &matcherInfos, updateDomain)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("failed to create client").Base(err)
|
return nil, errors.New("failed to create client").Base(err)
|
||||||
}
|
}
|
||||||
@@ -139,6 +166,8 @@ func New(ctx context.Context, config *Config) (*DNS, error) {
|
|||||||
matcherInfos: matcherInfos,
|
matcherInfos: matcherInfos,
|
||||||
disableFallback: config.DisableFallback,
|
disableFallback: config.DisableFallback,
|
||||||
disableFallbackIfMatch: config.DisableFallbackIfMatch,
|
disableFallbackIfMatch: config.DisableFallbackIfMatch,
|
||||||
|
enableParallelQuery: config.EnableParallelQuery,
|
||||||
|
checkSystem: checkSystem,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,15 +208,26 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, er
|
|||||||
return nil, 0, errors.New("empty domain name")
|
return nil, 0, errors.New("empty domain name")
|
||||||
}
|
}
|
||||||
|
|
||||||
option.IPv4Enable = option.IPv4Enable && s.ipOption.IPv4Enable
|
if s.checkSystem {
|
||||||
option.IPv6Enable = option.IPv6Enable && s.ipOption.IPv6Enable
|
supportIPv4, supportIPv6 := checkRoutes()
|
||||||
|
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 {
|
if !option.IPv4Enable && !option.IPv6Enable {
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
return nil, 0, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Static host lookup
|
// Static host lookup
|
||||||
switch addrs := s.hosts.Lookup(domain, option); {
|
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)
|
||||||
case addrs == nil: // Domain not recorded in static host
|
case addrs == nil: // Domain not recorded in static host
|
||||||
break
|
break
|
||||||
case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
|
case len(addrs) == 0: // Domain recorded, but no valid IP returned (e.g. IPv4 address with only IPv6 enabled)
|
||||||
@@ -205,42 +245,11 @@ func (s *DNS) LookupIP(domain string, option dns.IPOption) ([]net.IP, uint32, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name servers lookup
|
// Name servers lookup
|
||||||
var errs []error
|
if s.enableParallelQuery {
|
||||||
for _, client := range s.sortClients(domain) {
|
return s.parallelQuery(domain, option)
|
||||||
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
} else {
|
||||||
errors.LogDebug(s.ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
|
return s.serialQuery(domain, option)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
ips, ttl, err := client.QueryIP(s.ctx, domain, option)
|
|
||||||
|
|
||||||
if len(ips) > 0 {
|
|
||||||
if ttl == 0 {
|
|
||||||
ttl = 1
|
|
||||||
}
|
|
||||||
return ips, ttl, 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 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, 0, errors.New("returning nil for domain ", domain).Base(err0)
|
|
||||||
}
|
|
||||||
return nil, 0, errors.New("returning nil for domain ", domain).Base(allErrs)
|
|
||||||
}
|
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DNS) sortClients(domain string) []*Client {
|
func (s *DNS) sortClients(domain string) []*Client {
|
||||||
@@ -267,6 +276,9 @@ func (s *DNS) sortClients(domain string) []*Client {
|
|||||||
clients = append(clients, client)
|
clients = append(clients, client)
|
||||||
clientNames = append(clientNames, client.Name())
|
clientNames = append(clientNames, client.Name())
|
||||||
hasMatch = true
|
hasMatch = true
|
||||||
|
if client.finalQuery {
|
||||||
|
return clients
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !(s.disableFallback || s.disableFallbackIfMatch && hasMatch) {
|
if !(s.disableFallback || s.disableFallbackIfMatch && hasMatch) {
|
||||||
@@ -278,6 +290,9 @@ func (s *DNS) sortClients(domain string) []*Client {
|
|||||||
clientUsed[idx] = true
|
clientUsed[idx] = true
|
||||||
clients = append(clients, client)
|
clients = append(clients, client)
|
||||||
clientNames = append(clientNames, client.Name())
|
clientNames = append(clientNames, client.Name())
|
||||||
|
if client.finalQuery {
|
||||||
|
return clients
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,16 +304,280 @@ func (s *DNS) sortClients(domain string) []*Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(clients) == 0 {
|
if len(clients) == 0 {
|
||||||
clients = append(clients, s.clients[0])
|
if len(s.clients) > 0 {
|
||||||
clientNames = append(clientNames, s.clients[0].Name())
|
clients = append(clients, s.clients[0])
|
||||||
errors.LogDebug(s.ctx, "domain ", domain, " will use the first DNS: ", clientNames)
|
clientNames = append(clientNames, s.clients[0].Name())
|
||||||
|
errors.LogWarning(s.ctx, "domain ", domain, " will use the first DNS: ", clientNames)
|
||||||
|
} else {
|
||||||
|
errors.LogError(s.ctx, "no DNS clients available for domain ", domain, " and no default clients configured")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return clients
|
return clients
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeQueryErrors(domain string, errs []error) error {
|
||||||
|
if len(errs) == 0 {
|
||||||
|
return dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
var noRNF error
|
||||||
|
for _, err := range errs {
|
||||||
|
if go_errors.Is(err, errRecordNotFound) {
|
||||||
|
continue // server no response, ignore
|
||||||
|
} else if noRNF == nil {
|
||||||
|
noRNF = err
|
||||||
|
} else if !go_errors.Is(err, noRNF) {
|
||||||
|
return errors.New("returning nil for domain ", domain).Base(errors.Combine(errs...))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if go_errors.Is(noRNF, dns.ErrEmptyResponse) {
|
||||||
|
return dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
if noRNF == nil {
|
||||||
|
noRNF = errRecordNotFound
|
||||||
|
}
|
||||||
|
return errors.New("returning nil for domain ", domain).Base(noRNF)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DNS) serialQuery(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
|
var errs []error
|
||||||
|
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)
|
||||||
|
|
||||||
|
if len(ips) > 0 {
|
||||||
|
return ips, ttl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
errors.LogInfoInner(s.ctx, err, "failed to lookup ip for domain ", domain, " at server ", client.Name(), " in serial query mode")
|
||||||
|
if err == nil {
|
||||||
|
err = dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
return nil, 0, mergeQueryErrors(domain, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DNS) parallelQuery(domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
|
var errs []error
|
||||||
|
clients := s.sortClients(domain)
|
||||||
|
|
||||||
|
resultsChan := asyncQueryAll(domain, option, clients, s.ctx)
|
||||||
|
|
||||||
|
groups, groupOf := makeGroups( /*s.ctx,*/ clients)
|
||||||
|
results := make([]*queryResult, len(clients))
|
||||||
|
pending := make([]int, len(groups))
|
||||||
|
for gi, g := range groups {
|
||||||
|
pending[gi] = g.end - g.start + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
nextGroup := 0
|
||||||
|
for range clients {
|
||||||
|
result := <-resultsChan
|
||||||
|
results[result.index] = &result
|
||||||
|
|
||||||
|
gi := groupOf[result.index]
|
||||||
|
pending[gi]--
|
||||||
|
|
||||||
|
for nextGroup < len(groups) {
|
||||||
|
g := groups[nextGroup]
|
||||||
|
|
||||||
|
// group race, minimum rtt -> return
|
||||||
|
for j := g.start; j <= g.end; j++ {
|
||||||
|
r := results[j]
|
||||||
|
if r != nil && r.err == nil && len(r.ips) > 0 {
|
||||||
|
return r.ips, r.ttl, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// current group is incomplete and no one success -> continue pending
|
||||||
|
if pending[nextGroup] > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// all failed -> log and continue next group
|
||||||
|
for j := g.start; j <= g.end; j++ {
|
||||||
|
r := results[j]
|
||||||
|
e := r.err
|
||||||
|
if e == nil {
|
||||||
|
e = dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
errors.LogInfoInner(s.ctx, e, "failed to lookup ip for domain ", domain, " at server ", clients[j].Name(), " in parallel query mode")
|
||||||
|
errs = append(errs, e)
|
||||||
|
}
|
||||||
|
nextGroup++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, 0, mergeQueryErrors(domain, errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
type queryResult struct {
|
||||||
|
ips []net.IP
|
||||||
|
ttl uint32
|
||||||
|
err error
|
||||||
|
index int
|
||||||
|
}
|
||||||
|
|
||||||
|
func asyncQueryAll(domain string, option dns.IPOption, clients []*Client, ctx context.Context) chan queryResult {
|
||||||
|
if len(clients) == 0 {
|
||||||
|
ch := make(chan queryResult)
|
||||||
|
close(ch)
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := make(chan queryResult, len(clients))
|
||||||
|
for i, client := range clients {
|
||||||
|
if !option.FakeEnable && strings.EqualFold(client.Name(), "FakeDNS") {
|
||||||
|
errors.LogDebug(ctx, "skip DNS resolution for domain ", domain, " at server ", client.Name())
|
||||||
|
ch <- queryResult{err: dns.ErrEmptyResponse, index: i}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
go func(i int, c *Client) {
|
||||||
|
qctx := ctx
|
||||||
|
if !c.server.IsDisableCache() {
|
||||||
|
nctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), c.timeoutMs*2)
|
||||||
|
qctx = nctx
|
||||||
|
defer cancel()
|
||||||
|
}
|
||||||
|
ips, ttl, err := c.QueryIP(qctx, domain, option)
|
||||||
|
ch <- queryResult{ips: ips, ttl: ttl, err: err, index: i}
|
||||||
|
}(i, client)
|
||||||
|
}
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
type group struct{ start, end int }
|
||||||
|
|
||||||
|
// merge only adjacent and rule-equivalent Client into a single group
|
||||||
|
func makeGroups( /*ctx context.Context,*/ clients []*Client) ([]group, []int) {
|
||||||
|
n := len(clients)
|
||||||
|
if n == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
groups := make([]group, 0, n)
|
||||||
|
groupOf := make([]int, n)
|
||||||
|
|
||||||
|
s, e := 0, 0
|
||||||
|
for i := 1; i < n; i++ {
|
||||||
|
if clients[i-1].policyID == clients[i].policyID {
|
||||||
|
e = i
|
||||||
|
} else {
|
||||||
|
for k := s; k <= e; k++ {
|
||||||
|
groupOf[k] = len(groups)
|
||||||
|
}
|
||||||
|
groups = append(groups, group{start: s, end: e})
|
||||||
|
s, e = i, i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for k := s; k <= e; k++ {
|
||||||
|
groupOf[k] = len(groups)
|
||||||
|
}
|
||||||
|
groups = append(groups, group{start: s, end: e})
|
||||||
|
|
||||||
|
// var b strings.Builder
|
||||||
|
// b.WriteString("dns grouping: total clients=")
|
||||||
|
// b.WriteString(strconv.Itoa(n))
|
||||||
|
// b.WriteString(", groups=")
|
||||||
|
// b.WriteString(strconv.Itoa(len(groups)))
|
||||||
|
|
||||||
|
// for gi, g := range groups {
|
||||||
|
// b.WriteString("\n [")
|
||||||
|
// b.WriteString(strconv.Itoa(g.start))
|
||||||
|
// b.WriteString("..")
|
||||||
|
// b.WriteString(strconv.Itoa(g.end))
|
||||||
|
// b.WriteString("] gid=")
|
||||||
|
// b.WriteString(strconv.Itoa(gi))
|
||||||
|
// b.WriteString(" pid=")
|
||||||
|
// b.WriteString(strconv.FormatUint(uint64(clients[g.start].policyID), 10))
|
||||||
|
// b.WriteString(" members: ")
|
||||||
|
|
||||||
|
// for i := g.start; i <= g.end; i++ {
|
||||||
|
// if i > g.start {
|
||||||
|
// b.WriteString(", ")
|
||||||
|
// }
|
||||||
|
// b.WriteString(strconv.Itoa(i))
|
||||||
|
// b.WriteByte(':')
|
||||||
|
// b.WriteString(clients[i].Name())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// errors.LogDebug(ctx, b.String())
|
||||||
|
|
||||||
|
return groups, groupOf
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
common.Must(common.RegisterConfig((*Config)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||||
return New(ctx, config.(*Config))
|
return New(ctx, config.(*Config))
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func probeRoutes() (ipv4 bool, ipv6 bool) {
|
||||||
|
if conn, err := net.Dial("udp4", "192.33.4.12:53"); err == nil {
|
||||||
|
ipv4 = true
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
if conn, err := net.Dial("udp6", "[2001:500:2::c]:53"); err == nil {
|
||||||
|
ipv6 = true
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var routeCache struct {
|
||||||
|
sync.Once
|
||||||
|
sync.RWMutex
|
||||||
|
expire time.Time
|
||||||
|
ipv4, ipv6 bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkRoutes() (bool, bool) {
|
||||||
|
if !isGUIPlatform {
|
||||||
|
routeCache.Once.Do(func() {
|
||||||
|
routeCache.ipv4, routeCache.ipv6 = probeRoutes()
|
||||||
|
})
|
||||||
|
return routeCache.ipv4, routeCache.ipv6
|
||||||
|
}
|
||||||
|
|
||||||
|
routeCache.RWMutex.RLock()
|
||||||
|
now := time.Now()
|
||||||
|
if routeCache.expire.After(now) {
|
||||||
|
routeCache.RWMutex.RUnlock()
|
||||||
|
return routeCache.ipv4, routeCache.ipv6
|
||||||
|
}
|
||||||
|
routeCache.RWMutex.RUnlock()
|
||||||
|
|
||||||
|
routeCache.RWMutex.Lock()
|
||||||
|
defer routeCache.RWMutex.Unlock()
|
||||||
|
|
||||||
|
now = time.Now()
|
||||||
|
if routeCache.expire.After(now) { // double-check
|
||||||
|
return routeCache.ipv4, routeCache.ipv6
|
||||||
|
}
|
||||||
|
routeCache.ipv4, routeCache.ipv6 = probeRoutes() // ~2ms
|
||||||
|
routeCache.expire = now.Add(100 * time.Millisecond) // ttl
|
||||||
|
return routeCache.ipv4, routeCache.ipv6
|
||||||
|
}
|
||||||
|
|
||||||
|
var isGUIPlatform = detectGUIPlatform()
|
||||||
|
|
||||||
|
func detectGUIPlatform() bool {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "android", "ios", "windows", "darwin":
|
||||||
|
return true
|
||||||
|
case "linux", "freebsd", "openbsd":
|
||||||
|
if t := os.Getenv("XDG_SESSION_TYPE"); t == "wayland" || t == "x11" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if os.Getenv("DISPLAY") != "" || os.Getenv("WAYLAND_DISPLAY") != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -539,7 +539,7 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
Geoip: []*router.GeoIP{
|
ExpectedGeoip: []*router.GeoIP{
|
||||||
{
|
{
|
||||||
CountryCode: "local",
|
CountryCode: "local",
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
@@ -563,7 +563,7 @@ func TestIPMatch(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Port: uint32(port),
|
Port: uint32(port),
|
||||||
},
|
},
|
||||||
Geoip: []*router.GeoIP{
|
ExpectedGeoip: []*router.GeoIP{
|
||||||
{
|
{
|
||||||
CountryCode: "test",
|
CountryCode: "test",
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
@@ -667,7 +667,7 @@ func TestLocalDomain(t *testing.T) {
|
|||||||
// Equivalent of dotless:localhost
|
// Equivalent of dotless:localhost
|
||||||
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
|
{Type: DomainMatchingType_Regex, Domain: "^[^.]*localhost[^.]*$"},
|
||||||
},
|
},
|
||||||
Geoip: []*router.GeoIP{
|
ExpectedGeoip: []*router.GeoIP{
|
||||||
{ // Will match localhost, localhost-a and localhost-b,
|
{ // Will match localhost, localhost-a and localhost-b,
|
||||||
CountryCode: "local",
|
CountryCode: "local",
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
@@ -897,7 +897,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
Domain: "google.com",
|
Domain: "google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Geoip: []*router.GeoIP{
|
ExpectedGeoip: []*router.GeoIP{
|
||||||
{ // Will only match 8.8.8.8 and 8.8.4.4
|
{ // Will only match 8.8.8.8 and 8.8.4.4
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
||||||
@@ -922,7 +922,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
Domain: "google.com",
|
Domain: "google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Geoip: []*router.GeoIP{
|
ExpectedGeoip: []*router.GeoIP{
|
||||||
{ // Will match 8.8.8.8 and 8.8.8.7, etc
|
{ // Will match 8.8.8.8 and 8.8.8.7, etc
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
|
{Ip: []byte{8, 8, 8, 7}, Prefix: 24},
|
||||||
@@ -946,7 +946,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
Domain: "api.google.com",
|
Domain: "api.google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Geoip: []*router.GeoIP{
|
ExpectedGeoip: []*router.GeoIP{
|
||||||
{ // Will only match 8.8.7.7 (api.google.com)
|
{ // Will only match 8.8.7.7 (api.google.com)
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
|
{Ip: []byte{8, 8, 7, 7}, Prefix: 32},
|
||||||
@@ -970,7 +970,7 @@ func TestMultiMatchPrioritizedDomain(t *testing.T) {
|
|||||||
Domain: "v2.api.google.com",
|
Domain: "v2.api.google.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Geoip: []*router.GeoIP{
|
ExpectedGeoip: []*router.GeoIP{
|
||||||
{ // Will only match 8.8.7.8 (v2.api.google.com)
|
{ // Will only match 8.8.7.8 (v2.api.google.com)
|
||||||
Cidr: []*router.CIDR{
|
Cidr: []*router.CIDR{
|
||||||
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
|
{Ip: []byte{8, 8, 7, 8}, Prefix: 32},
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package dns
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -13,10 +14,12 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
dns_feature "github.com/xtls/xray-core/features/dns"
|
dns_feature "github.com/xtls/xray-core/features/dns"
|
||||||
|
|
||||||
"golang.org/x/net/dns/dnsmessage"
|
"golang.org/x/net/dns/dnsmessage"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fqdn normalizes domain make sure it ends with '.'
|
// Fqdn normalizes domain make sure it ends with '.'
|
||||||
|
// case-sensitive
|
||||||
func Fqdn(domain string) string {
|
func Fqdn(domain string) string {
|
||||||
if len(domain) > 0 && strings.HasSuffix(domain, ".") {
|
if len(domain) > 0 && strings.HasSuffix(domain, ".") {
|
||||||
return domain
|
return domain
|
||||||
@@ -38,16 +41,14 @@ type IPRecord struct {
|
|||||||
RawHeader *dnsmessage.Header
|
RawHeader *dnsmessage.Header
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *IPRecord) getIPs() ([]net.IP, uint32, error) {
|
func (r *IPRecord) getIPs() ([]net.IP, int32, error) {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, 0, errRecordNotFound
|
return nil, 0, errRecordNotFound
|
||||||
}
|
}
|
||||||
untilExpire := time.Until(r.Expire)
|
|
||||||
if untilExpire <= 0 {
|
|
||||||
return nil, 0, errRecordNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
ttl := uint32(untilExpire/time.Second) + uint32(1)
|
untilExpire := time.Until(r.Expire).Seconds()
|
||||||
|
ttl := int32(math.Ceil(untilExpire))
|
||||||
|
|
||||||
if r.RCode != dnsmessage.RCodeSuccess {
|
if r.RCode != dnsmessage.RCodeSuccess {
|
||||||
return nil, ttl, dns_feature.RCodeError(r.RCode)
|
return nil, ttl, dns_feature.RCodeError(r.RCode)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,31 +18,31 @@ func Test_parseResponse(t *testing.T) {
|
|||||||
|
|
||||||
ans := new(dns.Msg)
|
ans := new(dns.Msg)
|
||||||
ans.Id = 0
|
ans.Id = 0
|
||||||
p = append(p, common.Must2(ans.Pack()).([]byte))
|
p = append(p, common.Must2(ans.Pack()))
|
||||||
|
|
||||||
p = append(p, []byte{})
|
p = append(p, []byte{})
|
||||||
|
|
||||||
ans = new(dns.Msg)
|
ans = new(dns.Msg)
|
||||||
ans.Id = 1
|
ans.Id = 1
|
||||||
ans.Answer = append(ans.Answer,
|
ans.Answer = append(ans.Answer,
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")),
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")),
|
||||||
common.Must2(dns.NewRR("google.com. IN A 8.8.8.8")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN A 8.8.8.8")),
|
||||||
common.Must2(dns.NewRR("google.com. IN A 8.8.4.4")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN A 8.8.4.4")),
|
||||||
)
|
)
|
||||||
p = append(p, common.Must2(ans.Pack()).([]byte))
|
p = append(p, common.Must2(ans.Pack()))
|
||||||
|
|
||||||
ans = new(dns.Msg)
|
ans = new(dns.Msg)
|
||||||
ans.Id = 2
|
ans.Id = 2
|
||||||
ans.Answer = append(ans.Answer,
|
ans.Answer = append(ans.Answer,
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")),
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")),
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")),
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME test.google.com")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN CNAME test.google.com")),
|
||||||
common.Must2(dns.NewRR("google.com. IN AAAA 2001::123:8888")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN AAAA 2001:4860:4860::8888")),
|
||||||
common.Must2(dns.NewRR("google.com. IN AAAA 2001::123:8844")).(dns.RR),
|
common.Must2(dns.NewRR("google.com. IN AAAA 2001:4860:4860::8844")),
|
||||||
)
|
)
|
||||||
p = append(p, common.Must2(ans.Pack()).([]byte))
|
p = append(p, common.Must2(ans.Pack()))
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -72,7 +72,7 @@ func Test_parseResponse(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"aaaa record",
|
"aaaa record",
|
||||||
&IPRecord{2, []net.IP{net.ParseIP("2001::123:8888"), net.ParseIP("2001::123:8844")}, time.Time{}, dnsmessage.RCodeSuccess, nil},
|
&IPRecord{2, []net.IP{net.ParseIP("2001:4860:4860::8888"), net.ParseIP("2001:4860:4860::8844")}, time.Time{}, dnsmessage.RCodeSuccess, nil},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"math"
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
gonet "net"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -17,7 +16,7 @@ import (
|
|||||||
|
|
||||||
type Holder struct {
|
type Holder struct {
|
||||||
domainToIP cache.Lru
|
domainToIP cache.Lru
|
||||||
ipRange *gonet.IPNet
|
ipRange *net.IPNet
|
||||||
mu *sync.Mutex
|
mu *sync.Mutex
|
||||||
|
|
||||||
config *FakeDnsPool
|
config *FakeDnsPool
|
||||||
@@ -79,10 +78,10 @@ func (fkdns *Holder) initializeFromConfig() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
|
func (fkdns *Holder) initialize(ipPoolCidr string, lruSize int) error {
|
||||||
var ipRange *gonet.IPNet
|
var ipRange *net.IPNet
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if _, ipRange, err = gonet.ParseCIDR(ipPoolCidr); err != nil {
|
if _, ipRange, err = net.ParseCIDR(ipPoolCidr); err != nil {
|
||||||
return errors.New("Unable to parse CIDR for Fake DNS IP assignment").Base(err).AtError()
|
return errors.New("Unable to parse CIDR for Fake DNS IP assignment").Base(err).AtError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package fakedns
|
package fakedns
|
||||||
|
|
||||||
import (
|
import (
|
||||||
gonet "net"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -155,7 +154,7 @@ func TestFakeDNSMulti(t *testing.T) {
|
|||||||
assert.True(t, inPool)
|
assert.True(t, inPool)
|
||||||
})
|
})
|
||||||
t.Run("ipv6", func(t *testing.T) {
|
t.Run("ipv6", func(t *testing.T) {
|
||||||
ip, err := gonet.ResolveIPAddr("ip", "fddd:c5b4:ff5f:f4f0::5")
|
ip, err := net.ResolveIPAddr("ip", "fddd:c5b4:ff5f:f4f0::5")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
inPool := fakeMulti.IsIPInIPPool(net.IPAddress(ip.IP))
|
inPool := fakeMulti.IsIPInIPPool(net.IPAddress(ip.IP))
|
||||||
assert.True(t, inPool)
|
assert.True(t, inPool)
|
||||||
@@ -165,7 +164,7 @@ func TestFakeDNSMulti(t *testing.T) {
|
|||||||
assert.False(t, inPool)
|
assert.False(t, inPool)
|
||||||
})
|
})
|
||||||
t.Run("ipv6_inverse", func(t *testing.T) {
|
t.Run("ipv6_inverse", func(t *testing.T) {
|
||||||
ip, err := gonet.ResolveIPAddr("ip", "fcdd:c5b4:ff5f:f4f0::5")
|
ip, err := net.ResolveIPAddr("ip", "fcdd:c5b4:ff5f:f4f0::5")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
inPool := fakeMulti.IsIPInIPPool(net.IPAddress(ip.IP))
|
inPool := fakeMulti.IsIPInIPPool(net.IPAddress(ip.IP))
|
||||||
assert.False(t, inPool)
|
assert.False(t, inPool)
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/strmatcher"
|
"github.com/xtls/xray-core/common/strmatcher"
|
||||||
@@ -31,7 +33,15 @@ func NewStaticHosts(hosts []*Config_HostMapping) (*StaticHosts, error) {
|
|||||||
ips := make([]net.Address, 0, len(mapping.Ip)+1)
|
ips := make([]net.Address, 0, len(mapping.Ip)+1)
|
||||||
switch {
|
switch {
|
||||||
case len(mapping.ProxiedDomain) > 0:
|
case len(mapping.ProxiedDomain) > 0:
|
||||||
ips = append(ips, net.DomainAddress(mapping.ProxiedDomain))
|
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:
|
case len(mapping.Ip) > 0:
|
||||||
for _, ip := range mapping.Ip {
|
for _, ip := range mapping.Ip {
|
||||||
addr := net.IPAddress(ip)
|
addr := net.IPAddress(ip)
|
||||||
@@ -58,38 +68,51 @@ func filterIP(ips []net.Address, option dns.IPOption) []net.Address {
|
|||||||
return filtered
|
return filtered
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *StaticHosts) lookupInternal(domain string) []net.Address {
|
func (h *StaticHosts) lookupInternal(domain string) ([]net.Address, error) {
|
||||||
ips := make([]net.Address, 0)
|
ips := make([]net.Address, 0)
|
||||||
found := false
|
found := false
|
||||||
for _, id := range h.matchers.Match(domain) {
|
for _, 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]...)
|
ips = append(ips, h.ips[id]...)
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
return ips
|
return ips, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) []net.Address {
|
func (h *StaticHosts) lookup(domain string, option dns.IPOption, maxDepth int) ([]net.Address, error) {
|
||||||
switch addrs := h.lookupInternal(domain); {
|
switch addrs, err := h.lookupInternal(domain); {
|
||||||
|
case err != nil:
|
||||||
|
return nil, err
|
||||||
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
case len(addrs) == 0: // Not recorded in static hosts, return nil
|
||||||
return addrs
|
return addrs, nil
|
||||||
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
|
case len(addrs) == 1 && addrs[0].Family().IsDomain(): // Try to unwrap domain
|
||||||
errors.LogDebug(context.Background(), "found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it")
|
errors.LogDebug(context.Background(), "found replaced domain: ", domain, " -> ", addrs[0].Domain(), ". Try to unwrap it")
|
||||||
if maxDepth > 0 {
|
if maxDepth > 0 {
|
||||||
unwrapped := h.lookup(addrs[0].Domain(), option, maxDepth-1)
|
unwrapped, err := h.lookup(addrs[0].Domain(), option, maxDepth-1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if unwrapped != nil {
|
if unwrapped != nil {
|
||||||
return unwrapped
|
return unwrapped, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return addrs
|
return addrs, nil
|
||||||
default: // IP record found, return a non-nil IP array
|
default: // IP record found, return a non-nil IP array
|
||||||
return filterIP(addrs, option)
|
return filterIP(addrs, option), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
|
// Lookup returns IP addresses or proxied domain for the given domain, if exists in this StaticHosts.
|
||||||
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) []net.Address {
|
func (h *StaticHosts) Lookup(domain string, option dns.IPOption) ([]net.Address, error) {
|
||||||
return h.lookup(domain, option, 5)
|
return h.lookup(domain, option, 5)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,11 @@ import (
|
|||||||
|
|
||||||
func TestStaticHosts(t *testing.T) {
|
func TestStaticHosts(t *testing.T) {
|
||||||
pb := []*Config_HostMapping{
|
pb := []*Config_HostMapping{
|
||||||
|
{
|
||||||
|
Type: DomainMatchingType_Subdomain,
|
||||||
|
Domain: "lan",
|
||||||
|
ProxiedDomain: "#3",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Type: DomainMatchingType_Full,
|
Type: DomainMatchingType_Full,
|
||||||
Domain: "example.com",
|
Domain: "example.com",
|
||||||
@@ -54,7 +59,14 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
{
|
{
|
||||||
ips := hosts.Lookup("example.com", dns.IPOption{
|
_, err := hosts.Lookup("example.com.lan", dns.IPOption{})
|
||||||
|
if dns.RCodeFromError(err) != 3 {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
ips, _ := hosts.Lookup("example.com", dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
})
|
||||||
@@ -67,7 +79,7 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
domain := hosts.Lookup("proxy.xray.com", dns.IPOption{
|
domain, _ := hosts.Lookup("proxy.xray.com", dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: false,
|
IPv6Enable: false,
|
||||||
})
|
})
|
||||||
@@ -80,7 +92,7 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
domain := hosts.Lookup("proxy2.xray.com", dns.IPOption{
|
domain, _ := hosts.Lookup("proxy2.xray.com", dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: false,
|
IPv6Enable: false,
|
||||||
})
|
})
|
||||||
@@ -93,7 +105,7 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ips := hosts.Lookup("www.example.cn", dns.IPOption{
|
ips, _ := hosts.Lookup("www.example.cn", dns.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
})
|
||||||
@@ -106,7 +118,7 @@ func TestStaticHosts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ips := hosts.Lookup("baidu.com", dns.IPOption{
|
ips, _ := hosts.Lookup("baidu.com", dns.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: false,
|
||||||
IPv6Enable: true,
|
IPv6Enable: true,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,24 +20,32 @@ import (
|
|||||||
type Server interface {
|
type Server interface {
|
||||||
// Name of the Client.
|
// Name of the Client.
|
||||||
Name() string
|
Name() string
|
||||||
|
|
||||||
|
IsDisableCache() bool
|
||||||
|
|
||||||
// QueryIP sends IP queries to its configured server.
|
// QueryIP sends IP queries to its configured server.
|
||||||
QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error)
|
QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is the interface for DNS client.
|
// Client is the interface for DNS client.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
server Server
|
server Server
|
||||||
skipFallback bool
|
skipFallback bool
|
||||||
domains []string
|
domains []string
|
||||||
expectedIPs []*router.GeoIPMatcher
|
expectedIPs router.GeoIPMatcher
|
||||||
allowUnexpectedIPs bool
|
unexpectedIPs router.GeoIPMatcher
|
||||||
tag string
|
actPrior bool
|
||||||
timeoutMs time.Duration
|
actUnprior bool
|
||||||
ipOption *dns.IPOption
|
tag string
|
||||||
|
timeoutMs time.Duration
|
||||||
|
finalQuery bool
|
||||||
|
ipOption *dns.IPOption
|
||||||
|
checkSystem bool
|
||||||
|
policyID uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates a name server object according to the network destination url.
|
// NewServer creates a name server object according to the network destination url.
|
||||||
func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, disableCache bool, clientIP net.IP) (Server, error) {
|
func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dispatcher, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (Server, error) {
|
||||||
if address := dest.Address; address.Family().IsDomain() {
|
if address := dest.Address; address.Family().IsDomain() {
|
||||||
u, err := url.Parse(address.Domain())
|
u, err := url.Parse(address.Domain())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -47,19 +55,19 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
|||||||
case strings.EqualFold(u.String(), "localhost"):
|
case strings.EqualFold(u.String(), "localhost"):
|
||||||
return NewLocalNameServer(), nil
|
return NewLocalNameServer(), nil
|
||||||
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
|
case strings.EqualFold(u.Scheme, "https"): // DNS-over-HTTPS Remote mode
|
||||||
return NewDoHNameServer(u, dispatcher, false, disableCache, clientIP), nil
|
return NewDoHNameServer(u, dispatcher, false, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
|
case strings.EqualFold(u.Scheme, "h2c"): // DNS-over-HTTPS h2c Remote mode
|
||||||
return NewDoHNameServer(u, dispatcher, true, disableCache, clientIP), nil
|
return NewDoHNameServer(u, dispatcher, true, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
|
case strings.EqualFold(u.Scheme, "https+local"): // DNS-over-HTTPS Local mode
|
||||||
return NewDoHNameServer(u, nil, false, disableCache, clientIP), nil
|
return NewDoHNameServer(u, nil, false, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
case strings.EqualFold(u.Scheme, "h2c+local"): // DNS-over-HTTPS h2c Local mode
|
case strings.EqualFold(u.Scheme, "h2c+local"): // DNS-over-HTTPS h2c Local mode
|
||||||
return NewDoHNameServer(u, nil, true, disableCache, clientIP), nil
|
return NewDoHNameServer(u, nil, true, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
case strings.EqualFold(u.Scheme, "quic+local"): // DNS-over-QUIC Local mode
|
||||||
return NewQUICNameServer(u, disableCache, clientIP)
|
return NewQUICNameServer(u, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
|
case strings.EqualFold(u.Scheme, "tcp"): // DNS-over-TCP Remote mode
|
||||||
return NewTCPNameServer(u, dispatcher, disableCache, clientIP)
|
return NewTCPNameServer(u, dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
|
case strings.EqualFold(u.Scheme, "tcp+local"): // DNS-over-TCP Local mode
|
||||||
return NewTCPLocalNameServer(u, disableCache, clientIP)
|
return NewTCPLocalNameServer(u, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
case strings.EqualFold(u.String(), "fakedns"):
|
case strings.EqualFold(u.String(), "fakedns"):
|
||||||
var fd dns.FakeDNSEngine
|
var fd dns.FakeDNSEngine
|
||||||
err = core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
err = core.RequireFeatures(ctx, func(fdns dns.FakeDNSEngine) {
|
||||||
@@ -75,7 +83,7 @@ func NewServer(ctx context.Context, dest net.Destination, dispatcher routing.Dis
|
|||||||
dest.Network = net.Network_UDP
|
dest.Network = net.Network_UDP
|
||||||
}
|
}
|
||||||
if dest.Network == net.Network_UDP { // UDP classic DNS mode
|
if dest.Network == net.Network_UDP { // UDP classic DNS mode
|
||||||
return NewClassicNameServer(dest, dispatcher, disableCache, clientIP), nil
|
return NewClassicNameServer(dest, dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP), nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("No available name server could be created from ", dest).AtWarning()
|
return nil, errors.New("No available name server could be created from ", dest).AtWarning()
|
||||||
}
|
}
|
||||||
@@ -85,7 +93,7 @@ func NewClient(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
ns *NameServer,
|
ns *NameServer,
|
||||||
clientIP net.IP,
|
clientIP net.IP,
|
||||||
disableCache bool,
|
disableCache bool, serveStale bool, serveExpiredTTL uint32,
|
||||||
tag string,
|
tag string,
|
||||||
ipOption dns.IPOption,
|
ipOption dns.IPOption,
|
||||||
matcherInfos *[]*DomainMatcherInfo,
|
matcherInfos *[]*DomainMatcherInfo,
|
||||||
@@ -95,7 +103,7 @@ func NewClient(
|
|||||||
|
|
||||||
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
err := core.RequireFeatures(ctx, func(dispatcher routing.Dispatcher) error {
|
||||||
// Create a new server for each client for now
|
// Create a new server for each client for now
|
||||||
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, clientIP)
|
server, err := NewServer(ctx, ns.Address.AsDestination(), dispatcher, disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
return errors.New("failed to create nameserver").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
@@ -150,13 +158,21 @@ func NewClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Establish expected IPs
|
// Establish expected IPs
|
||||||
var matchers []*router.GeoIPMatcher
|
var expectedMatcher router.GeoIPMatcher
|
||||||
for _, geoip := range ns.Geoip {
|
if len(ns.ExpectedGeoip) > 0 {
|
||||||
matcher, err := router.GlobalGeoIPContainer.Add(geoip)
|
expectedMatcher, err = router.BuildOptimizedGeoIPMatcher(ns.ExpectedGeoip...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to create ip matcher").Base(err).AtWarning()
|
return errors.New("failed to create expected ip matcher").Base(err).AtWarning()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Establish unexpected IPs
|
||||||
|
var unexpectedMatcher router.GeoIPMatcher
|
||||||
|
if len(ns.UnexpectedGeoip) > 0 {
|
||||||
|
unexpectedMatcher, err = router.BuildOptimizedGeoIPMatcher(ns.UnexpectedGeoip...)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("failed to create unexpected ip matcher").Base(err).AtWarning()
|
||||||
}
|
}
|
||||||
matchers = append(matchers, matcher)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(clientIP) > 0 {
|
if len(clientIP) > 0 {
|
||||||
@@ -173,14 +189,21 @@ func NewClient(
|
|||||||
timeoutMs = time.Duration(ns.TimeoutMs) * time.Millisecond
|
timeoutMs = time.Duration(ns.TimeoutMs) * time.Millisecond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkSystem := ns.QueryStrategy == QueryStrategy_USE_SYS
|
||||||
|
|
||||||
client.server = server
|
client.server = server
|
||||||
client.skipFallback = ns.SkipFallback
|
client.skipFallback = ns.SkipFallback
|
||||||
client.domains = rules
|
client.domains = rules
|
||||||
client.expectedIPs = matchers
|
client.expectedIPs = expectedMatcher
|
||||||
client.allowUnexpectedIPs = ns.AllowUnexpectedIPs
|
client.unexpectedIPs = unexpectedMatcher
|
||||||
|
client.actPrior = ns.ActPrior
|
||||||
|
client.actUnprior = ns.ActUnprior
|
||||||
client.tag = tag
|
client.tag = tag
|
||||||
client.timeoutMs = timeoutMs
|
client.timeoutMs = timeoutMs
|
||||||
|
client.finalQuery = ns.FinalQuery
|
||||||
client.ipOption = &ipOption
|
client.ipOption = &ipOption
|
||||||
|
client.checkSystem = checkSystem
|
||||||
|
client.policyID = ns.PolicyID
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return client, err
|
return client, err
|
||||||
@@ -193,8 +216,15 @@ func (c *Client) Name() string {
|
|||||||
|
|
||||||
// QueryIP sends DNS query to the name server with the client's IP.
|
// QueryIP sends DNS query to the name server with the client's IP.
|
||||||
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
option.IPv4Enable = option.IPv4Enable && c.ipOption.IPv4Enable
|
if c.checkSystem {
|
||||||
option.IPv6Enable = option.IPv6Enable && c.ipOption.IPv6Enable
|
supportIPv4, supportIPv6 := checkRoutes()
|
||||||
|
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 {
|
if !option.IPv4Enable && !option.IPv6Enable {
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
return nil, 0, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
@@ -212,39 +242,47 @@ func (c *Client) QueryIP(ctx context.Context, domain string, option dns.IPOption
|
|||||||
return nil, 0, dns.ErrEmptyResponse
|
return nil, 0, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.expectedIPs) > 0 {
|
if c.expectedIPs != nil && !c.actPrior {
|
||||||
newIps := c.MatchExpectedIPs(domain, ips)
|
ips, _ = c.expectedIPs.FilterIPs(ips)
|
||||||
if len(newIps) == 0 {
|
errors.LogDebug(context.Background(), "domain ", domain, " expectedIPs ", ips, " matched at server ", c.Name())
|
||||||
if !c.allowUnexpectedIPs {
|
if len(ips) == 0 {
|
||||||
return nil, 0, dns.ErrEmptyResponse
|
return nil, 0, dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
ips = newIps
|
|
||||||
|
if c.unexpectedIPs != nil && !c.actUnprior {
|
||||||
|
_, ips = c.unexpectedIPs.FilterIPs(ips)
|
||||||
|
errors.LogDebug(context.Background(), "domain ", domain, " unexpectedIPs ", ips, " matched at server ", c.Name())
|
||||||
|
if len(ips) == 0 {
|
||||||
|
return nil, 0, dns.ErrEmptyResponse
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.expectedIPs != nil && c.actPrior {
|
||||||
|
ipsNew, _ := c.expectedIPs.FilterIPs(ips)
|
||||||
|
if len(ipsNew) > 0 {
|
||||||
|
ips = ipsNew
|
||||||
|
errors.LogDebug(context.Background(), "domain ", domain, " priorIPs ", ips, " matched at server ", c.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.unexpectedIPs != nil && c.actUnprior {
|
||||||
|
_, ipsNew := c.unexpectedIPs.FilterIPs(ips)
|
||||||
|
if len(ipsNew) > 0 {
|
||||||
|
ips = ipsNew
|
||||||
|
errors.LogDebug(context.Background(), "domain ", domain, " unpriorIPs ", ips, " matched at server ", c.Name())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ips, ttl, nil
|
return ips, ttl, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchExpectedIPs matches queried domain IPs with expected IPs and returns matched ones.
|
|
||||||
func (c *Client) MatchExpectedIPs(domain string, ips []net.IP) []net.IP {
|
|
||||||
var newIps []net.IP
|
|
||||||
for _, ip := range ips {
|
|
||||||
for _, matcher := range c.expectedIPs {
|
|
||||||
if matcher.Match(ip) {
|
|
||||||
newIps = append(newIps, ip)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
errors.LogDebug(context.Background(), "domain ", domain, " expectedIPs ", newIps, " matched at server ", c.Name())
|
|
||||||
return newIps
|
|
||||||
}
|
|
||||||
|
|
||||||
func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) dns.IPOption {
|
func ResolveIpOptionOverride(queryStrategy QueryStrategy, ipOption dns.IPOption) dns.IPOption {
|
||||||
switch queryStrategy {
|
switch queryStrategy {
|
||||||
case QueryStrategy_USE_IP:
|
case QueryStrategy_USE_IP:
|
||||||
return ipOption
|
return ipOption
|
||||||
|
case QueryStrategy_USE_SYS:
|
||||||
|
return ipOption
|
||||||
case QueryStrategy_USE_IP4:
|
case QueryStrategy_USE_IP4:
|
||||||
return dns.IPOption{
|
return dns.IPOption{
|
||||||
IPv4Enable: ipOption.IPv4Enable,
|
IPv4Enable: ipOption.IPv4Enable,
|
||||||
|
|||||||
173
app/dns/nameserver_cached.go
Normal file
173
app/dns/nameserver_cached.go
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
package dns
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
go_errors "errors"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"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/signal/pubsub"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CachedNameserver interface {
|
||||||
|
getCacheController() *CacheController
|
||||||
|
|
||||||
|
sendQuery(ctx context.Context, noResponseErrCh chan<- error, fqdn string, option dns.IPOption)
|
||||||
|
}
|
||||||
|
|
||||||
|
// queryIP is called from dns.Server->queryIPTimeout
|
||||||
|
func queryIP(ctx context.Context, s CachedNameserver, domain string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
|
fqdn := Fqdn(domain)
|
||||||
|
|
||||||
|
cache := s.getCacheController()
|
||||||
|
if !cache.disableCache {
|
||||||
|
if rec := cache.findRecords(fqdn); rec != nil {
|
||||||
|
ips, ttl, err := merge(option, rec.A, rec.AAAA)
|
||||||
|
if !go_errors.Is(err, errRecordNotFound) {
|
||||||
|
if ttl > 0 {
|
||||||
|
errors.LogDebugInner(ctx, err, cache.name, " cache HIT ", fqdn, " -> ", ips)
|
||||||
|
log.Record(&log.DNSLog{Server: cache.name, Domain: fqdn, Result: ips, Status: log.DNSCacheHit, Elapsed: 0, Error: err})
|
||||||
|
return ips, uint32(ttl), err
|
||||||
|
}
|
||||||
|
if cache.serveStale && (cache.serveExpiredTTL == 0 || cache.serveExpiredTTL < ttl) {
|
||||||
|
errors.LogDebugInner(ctx, err, cache.name, " cache OPTIMISTE ", fqdn, " -> ", ips)
|
||||||
|
log.Record(&log.DNSLog{Server: cache.name, Domain: fqdn, Result: ips, Status: log.DNSCacheOptimiste, Elapsed: 0, Error: err})
|
||||||
|
go pull(ctx, s, fqdn, option)
|
||||||
|
return ips, 1, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errors.LogDebug(ctx, "DNS cache is disabled. Querying IP for ", fqdn, " at ", cache.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(ctx, s, fqdn, option)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pull(ctx context.Context, s CachedNameserver, fqdn string, option dns.IPOption) {
|
||||||
|
nctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), 8*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
fetch(nctx, s, fqdn, option)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetch(ctx context.Context, s CachedNameserver, fqdn string, option dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
|
key := fqdn
|
||||||
|
switch {
|
||||||
|
case option.IPv4Enable && option.IPv6Enable:
|
||||||
|
key = key + "46"
|
||||||
|
case option.IPv4Enable:
|
||||||
|
key = key + "4"
|
||||||
|
case option.IPv6Enable:
|
||||||
|
key = key + "6"
|
||||||
|
}
|
||||||
|
|
||||||
|
v, _, _ := s.getCacheController().requestGroup.Do(key, func() (any, error) {
|
||||||
|
return doFetch(ctx, s, fqdn, option), nil
|
||||||
|
})
|
||||||
|
ret := v.(result)
|
||||||
|
|
||||||
|
return ret.ips, ret.ttl, ret.error
|
||||||
|
}
|
||||||
|
|
||||||
|
type result struct {
|
||||||
|
ips []net.IP
|
||||||
|
ttl uint32
|
||||||
|
error
|
||||||
|
}
|
||||||
|
|
||||||
|
func doFetch(ctx context.Context, s CachedNameserver, fqdn string, option dns.IPOption) result {
|
||||||
|
sub4, sub6 := s.getCacheController().registerSubscribers(fqdn, option)
|
||||||
|
defer closeSubscribers(sub4, sub6)
|
||||||
|
|
||||||
|
noResponseErrCh := make(chan error, 2)
|
||||||
|
onEvent := func(sub *pubsub.Subscriber) (*IPRecord, error) {
|
||||||
|
if sub == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return nil, ctx.Err()
|
||||||
|
case err := <-noResponseErrCh:
|
||||||
|
return nil, err
|
||||||
|
case msg := <-sub.Wait():
|
||||||
|
sub.Close()
|
||||||
|
return msg.(*IPRecord), nil // should panic
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
||||||
|
|
||||||
|
rec4, err4 := onEvent(sub4)
|
||||||
|
rec6, err6 := onEvent(sub6)
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
if err4 != nil {
|
||||||
|
errs = append(errs, err4)
|
||||||
|
}
|
||||||
|
if err6 != nil {
|
||||||
|
errs = append(errs, err6)
|
||||||
|
}
|
||||||
|
|
||||||
|
ips, ttl, err := merge(option, rec4, rec6, errs...)
|
||||||
|
var rTTL uint32
|
||||||
|
if ttl > 0 {
|
||||||
|
rTTL = uint32(ttl)
|
||||||
|
} else if ttl == 0 && go_errors.Is(err, errRecordNotFound) {
|
||||||
|
rTTL = 0
|
||||||
|
} else { // edge case: where a fast rep's ttl expires during the rtt of a slower, parallel query
|
||||||
|
rTTL = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Record(&log.DNSLog{Server: s.getCacheController().name, Domain: fqdn, Result: ips, Status: log.DNSQueried, Elapsed: time.Since(start), Error: err})
|
||||||
|
return result{ips, rTTL, err}
|
||||||
|
}
|
||||||
|
|
||||||
|
func merge(option dns.IPOption, rec4 *IPRecord, rec6 *IPRecord, errs ...error) ([]net.IP, int32, error) {
|
||||||
|
var allIPs []net.IP
|
||||||
|
var rTTL int32 = dns.DefaultTTL
|
||||||
|
|
||||||
|
mergeReq := option.IPv4Enable && option.IPv6Enable
|
||||||
|
|
||||||
|
if option.IPv4Enable {
|
||||||
|
ips, ttl, err := rec4.getIPs() // it's safe
|
||||||
|
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 := rec6.getIPs() // it's safe
|
||||||
|
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 len(errs) == 2 && go_errors.Is(errs[0], errs[1]) {
|
||||||
|
return nil, rTTL, errs[0]
|
||||||
|
}
|
||||||
|
return nil, rTTL, errors.Combine(errs...)
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
go_errors "errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -38,7 +37,7 @@ type DoHNameServer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewDoHNameServer creates DOH/DOHL client object for remote/local resolving.
|
// NewDoHNameServer creates DOH/DOHL client object for remote/local resolving.
|
||||||
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, disableCache bool, clientIP net.IP) *DoHNameServer {
|
func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) *DoHNameServer {
|
||||||
url.Scheme = "https"
|
url.Scheme = "https"
|
||||||
mode := "DOH"
|
mode := "DOH"
|
||||||
if dispatcher == nil {
|
if dispatcher == nil {
|
||||||
@@ -46,7 +45,7 @@ func NewDoHNameServer(url *url.URL, dispatcher routing.Dispatcher, h2c bool, dis
|
|||||||
}
|
}
|
||||||
errors.LogInfo(context.Background(), "DNS: created ", mode, " client for ", url.String(), ", with h2c ", h2c)
|
errors.LogInfo(context.Background(), "DNS: created ", mode, " client for ", url.String(), ", with h2c ", h2c)
|
||||||
s := &DoHNameServer{
|
s := &DoHNameServer{
|
||||||
cacheController: NewCacheController(mode+"//"+url.Host, disableCache),
|
cacheController: NewCacheController(mode+"//"+url.Host, disableCache, serveStale, serveExpiredTTL),
|
||||||
dohURL: url.String(),
|
dohURL: url.String(),
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
}
|
}
|
||||||
@@ -117,22 +116,35 @@ func (s *DoHNameServer) Name() string {
|
|||||||
return s.cacheController.name
|
return s.cacheController.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *DoHNameServer) IsDisableCache() bool {
|
||||||
|
return s.cacheController.disableCache
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DoHNameServer) newReqID() uint16 {
|
func (s *DoHNameServer) newReqID() uint16 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
// getCacheController implements CachedNameserver.
|
||||||
errors.LogInfo(ctx, s.Name(), " querying: ", domain)
|
func (s *DoHNameServer) getCacheController() *CacheController {
|
||||||
|
return s.cacheController
|
||||||
|
}
|
||||||
|
|
||||||
if s.Name()+"." == "DOH//"+domain {
|
// sendQuery implements CachedNameserver.
|
||||||
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead.")
|
func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, fqdn string, option dns_feature.IPOption) {
|
||||||
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
|
errors.LogInfo(ctx, s.Name(), " querying: ", fqdn)
|
||||||
|
|
||||||
|
if s.Name()+"." == "DOH//"+fqdn {
|
||||||
|
errors.LogError(ctx, s.Name(), " tries to resolve itself! Use IP or set \"hosts\" instead")
|
||||||
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- errors.New("tries to resolve itself!", s.Name())
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// As we don't want our traffic pattern looks like DoH, we use Random-Length Padding instead of Block-Length Padding recommended in RFC 8467
|
// 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
|
// 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(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, int(crypto.RandBetween(100, 300))))
|
||||||
|
|
||||||
var deadline time.Time
|
var deadline time.Time
|
||||||
if d, ok := ctx.Deadline(); ok {
|
if d, ok := ctx.Deadline(); ok {
|
||||||
@@ -166,23 +178,29 @@ func (s *DoHNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
|
|
||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to pack dns query for ", fqdn)
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
|
resp, err := s.dohHTTPSContext(dnsCtx, b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to retrieve response for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to retrieve response for ", fqdn)
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
rec, err := parseResponse(resp)
|
rec, err := parseResponse(resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", domain)
|
errors.LogErrorInner(ctx, err, "failed to handle DOH response for ", fqdn)
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.cacheController.updateIP(r, rec)
|
s.cacheController.updateRecord(r, rec)
|
||||||
}(req)
|
}(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,49 +234,6 @@ func (s *DoHNameServer) dohHTTPSContext(ctx context.Context, b []byte) ([]byte,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) { // nolint: dupl
|
func (s *DoHNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
||||||
fqdn := Fqdn(domain)
|
return queryIP(ctx, s, domain, option)
|
||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
|
||||||
defer closeSubscribers(sub4, sub6)
|
|
||||||
|
|
||||||
if s.cacheController.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
if sub4 != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub4.Wait():
|
|
||||||
sub4.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sub6 != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub6.Wait():
|
|
||||||
sub6.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func TestDOHNameServer(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, nil, false, false, false, 0, net.IP(nil))
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
@@ -34,7 +34,7 @@ func TestDOHNameServerWithCache(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, nil, false, false, false, 0, net.IP(nil))
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
@@ -62,7 +62,7 @@ func TestDOHNameServerWithIPv4Override(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, nil, false, false, false, 0, net.IP(nil))
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: true,
|
IPv4Enable: true,
|
||||||
@@ -85,7 +85,7 @@ func TestDOHNameServerWithIPv6Override(t *testing.T) {
|
|||||||
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
url, err := url.Parse("https+local://1.1.1.1/dns-query")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
s := NewDoHNameServer(url, nil, false, false, net.IP(nil))
|
s := NewDoHNameServer(url, nil, false, false, false, 0, net.IP(nil))
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
IPv4Enable: false,
|
IPv4Enable: false,
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ func (FakeDNSServer) Name() string {
|
|||||||
return "FakeDNS"
|
return "FakeDNS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *FakeDNSServer) IsDisableCache() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
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, opt dns.IPOption) ([]net.IP, uint32, error) {
|
||||||
if f.fakeDNSEngine == nil {
|
if f.fakeDNSEngine == nil {
|
||||||
return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError()
|
return nil, 0, errors.New("Unable to locate a fake DNS Engine").AtError()
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ func (s *LocalNameServer) Name() string {
|
|||||||
return "localhost"
|
return "localhost"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *LocalNameServer) IsDisableCache() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
|
// NewLocalNameServer creates localdns server object for directly lookup in system DNS.
|
||||||
func NewLocalNameServer() *LocalNameServer {
|
func NewLocalNameServer() *LocalNameServer {
|
||||||
errors.LogInfo(context.Background(), "DNS: created localhost client")
|
errors.LogInfo(context.Background(), "DNS: created localhost client")
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
go_errors "errors"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -32,14 +31,12 @@ type QUICNameServer struct {
|
|||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
cacheController *CacheController
|
cacheController *CacheController
|
||||||
destination *net.Destination
|
destination *net.Destination
|
||||||
connection quic.Connection
|
connection *quic.Conn
|
||||||
clientIP net.IP
|
clientIP net.IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
// NewQUICNameServer creates DNS-over-QUIC client object for local resolving
|
||||||
func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICNameServer, error) {
|
func NewQUICNameServer(url *url.URL, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (*QUICNameServer, error) {
|
||||||
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
port := net.Port(853)
|
port := net.Port(853)
|
||||||
if url.Port() != "" {
|
if url.Port() != "" {
|
||||||
@@ -51,27 +48,37 @@ func NewQUICNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*QUICN
|
|||||||
dest := net.UDPDestination(net.ParseAddress(url.Hostname()), port)
|
dest := net.UDPDestination(net.ParseAddress(url.Hostname()), port)
|
||||||
|
|
||||||
s := &QUICNameServer{
|
s := &QUICNameServer{
|
||||||
cacheController: NewCacheController(url.String(), disableCache),
|
cacheController: NewCacheController(url.String(), disableCache, serveStale, serveExpiredTTL),
|
||||||
destination: &dest,
|
destination: &dest,
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogInfo(context.Background(), "DNS: created Local DNS-over-QUIC client for ", url.String())
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns client name
|
// Name implements Server.
|
||||||
func (s *QUICNameServer) Name() string {
|
func (s *QUICNameServer) Name() string {
|
||||||
return s.cacheController.name
|
return s.cacheController.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *QUICNameServer) IsDisableCache() bool {
|
||||||
|
return s.cacheController.disableCache
|
||||||
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) newReqID() uint16 {
|
func (s *QUICNameServer) newReqID() uint16 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
// getCacheController implements CachedNameServer.
|
||||||
errors.LogInfo(ctx, s.Name(), " querying: ", domain)
|
func (s *QUICNameServer) getCacheController() *CacheController { return s.cacheController }
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
// sendQuery implements CachedNameServer.
|
||||||
|
func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, fqdn string, option dns_feature.IPOption) {
|
||||||
|
errors.LogInfo(ctx, s.Name(), " querying: ", fqdn)
|
||||||
|
|
||||||
|
reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
||||||
|
|
||||||
var deadline time.Time
|
var deadline time.Time
|
||||||
if d, ok := ctx.Deadline(); ok {
|
if d, ok := ctx.Deadline(); ok {
|
||||||
@@ -103,7 +110,9 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,13 +120,17 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "binary write failed")
|
errors.LogErrorInner(ctx, err, "binary write failed")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = dnsReqBuf.Write(b.Bytes())
|
_, err = dnsReqBuf.Write(b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "buffer write failed")
|
errors.LogErrorInner(ctx, err, "buffer write failed")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.Release()
|
b.Release()
|
||||||
@@ -125,14 +138,18 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
conn, err := s.openStream(dnsCtx)
|
conn, err := s.openStream(dnsCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to open quic connection")
|
errors.LogErrorInner(ctx, err, "failed to open quic connection")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to send query")
|
errors.LogErrorInner(ctx, err, "failed to send query")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,84 +160,49 @@ func (s *QUICNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- e
|
|||||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var length int16
|
var length uint16
|
||||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
respBuf.Clear()
|
respBuf.Clear()
|
||||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rec, err := parseResponse(respBuf.Bytes())
|
rec, err := parseResponse(respBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to handle response")
|
errors.LogErrorInner(ctx, err, "failed to handle response")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.cacheController.updateIP(r, rec)
|
s.cacheController.updateRecord(r, rec)
|
||||||
}(req)
|
}(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryIP is called from dns.Server->queryIPTimeout
|
// QueryIP implements Server.
|
||||||
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, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
||||||
fqdn := Fqdn(domain)
|
return queryIP(ctx, s, domain, option)
|
||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
|
||||||
defer closeSubscribers(sub4, sub6)
|
|
||||||
|
|
||||||
if s.cacheController.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
if sub4 != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub4.Wait():
|
|
||||||
sub4.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sub6 != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub6.Wait():
|
|
||||||
sub6.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.Connection) bool {
|
func isActive(s *quic.Conn) bool {
|
||||||
select {
|
select {
|
||||||
case <-s.Context().Done():
|
case <-s.Context().Done():
|
||||||
return false
|
return false
|
||||||
@@ -229,8 +211,8 @@ func isActive(s quic.Connection) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) getConnection() (quic.Connection, error) {
|
func (s *QUICNameServer) getConnection() (*quic.Conn, error) {
|
||||||
var conn quic.Connection
|
var conn *quic.Conn
|
||||||
s.RLock()
|
s.RLock()
|
||||||
conn = s.connection
|
conn = s.connection
|
||||||
if conn != nil && isActive(conn) {
|
if conn != nil && isActive(conn) {
|
||||||
@@ -263,7 +245,7 @@ func (s *QUICNameServer) getConnection() (quic.Connection, error) {
|
|||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *QUICNameServer) openConnection() (quic.Connection, error) {
|
func (s *QUICNameServer) openConnection() (*quic.Conn, error) {
|
||||||
tlsConfig := tls.Config{}
|
tlsConfig := tls.Config{}
|
||||||
quicConfig := &quic.Config{
|
quicConfig := &quic.Config{
|
||||||
HandshakeIdleTimeout: handshakeTimeout,
|
HandshakeIdleTimeout: handshakeTimeout,
|
||||||
@@ -283,7 +265,7 @@ func (s *QUICNameServer) openConnection() (quic.Connection, error) {
|
|||||||
return conn, nil
|
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()
|
conn, err := s.getConnection()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
func TestQUICNameServer(t *testing.T) {
|
func TestQUICNameServer(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
||||||
@@ -43,7 +43,7 @@ func TestQUICNameServer(t *testing.T) {
|
|||||||
func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
||||||
@@ -66,7 +66,7 @@ func TestQUICNameServerWithIPv4Override(t *testing.T) {
|
|||||||
func TestQUICNameServerWithIPv6Override(t *testing.T) {
|
func TestQUICNameServerWithIPv6Override(t *testing.T) {
|
||||||
url, err := url.Parse("quic://dns.adguard-dns.com")
|
url, err := url.Parse("quic://dns.adguard-dns.com")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewQUICNameServer(url, false, net.IP(nil))
|
s, err := NewQUICNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns.IPOption{
|
||||||
|
|||||||
@@ -4,14 +4,12 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
go_errors "errors"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/log"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
"github.com/xtls/xray-core/common/protocol/dns"
|
"github.com/xtls/xray-core/common/protocol/dns"
|
||||||
@@ -34,10 +32,10 @@ type TCPNameServer struct {
|
|||||||
func NewTCPNameServer(
|
func NewTCPNameServer(
|
||||||
url *url.URL,
|
url *url.URL,
|
||||||
dispatcher routing.Dispatcher,
|
dispatcher routing.Dispatcher,
|
||||||
disableCache bool,
|
disableCache bool, serveStale bool, serveExpiredTTL uint32,
|
||||||
clientIP net.IP,
|
clientIP net.IP,
|
||||||
) (*TCPNameServer, error) {
|
) (*TCPNameServer, error) {
|
||||||
s, err := baseTCPNameServer(url, "TCP", disableCache, clientIP)
|
s, err := baseTCPNameServer(url, "TCP", disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -54,12 +52,13 @@ func NewTCPNameServer(
|
|||||||
), nil
|
), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogInfo(context.Background(), "DNS: created TCP client initialized for ", url.String())
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTCPLocalNameServer creates DNS over TCP client object for local resolving
|
// NewTCPLocalNameServer creates DNS over TCP client object for local resolving
|
||||||
func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
|
func NewTCPLocalNameServer(url *url.URL, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (*TCPNameServer, error) {
|
||||||
s, err := baseTCPNameServer(url, "TCPL", disableCache, clientIP)
|
s, err := baseTCPNameServer(url, "TCPL", disableCache, serveStale, serveExpiredTTL, clientIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -68,10 +67,11 @@ func NewTCPLocalNameServer(url *url.URL, disableCache bool, clientIP net.IP) (*T
|
|||||||
return internet.DialSystem(ctx, *s.destination, nil)
|
return internet.DialSystem(ctx, *s.destination, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
errors.LogInfo(context.Background(), "DNS: created Local TCP client initialized for ", url.String())
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP net.IP) (*TCPNameServer, error) {
|
func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) (*TCPNameServer, error) {
|
||||||
port := net.Port(53)
|
port := net.Port(53)
|
||||||
if url.Port() != "" {
|
if url.Port() != "" {
|
||||||
var err error
|
var err error
|
||||||
@@ -82,7 +82,7 @@ func baseTCPNameServer(url *url.URL, prefix string, disableCache bool, clientIP
|
|||||||
dest := net.TCPDestination(net.ParseAddress(url.Hostname()), port)
|
dest := net.TCPDestination(net.ParseAddress(url.Hostname()), port)
|
||||||
|
|
||||||
s := &TCPNameServer{
|
s := &TCPNameServer{
|
||||||
cacheController: NewCacheController(prefix+"//"+dest.NetAddr(), disableCache),
|
cacheController: NewCacheController(prefix+"//"+dest.NetAddr(), disableCache, serveStale, serveExpiredTTL),
|
||||||
destination: &dest,
|
destination: &dest,
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
}
|
}
|
||||||
@@ -95,14 +95,25 @@ func (s *TCPNameServer) Name() string {
|
|||||||
return s.cacheController.name
|
return s.cacheController.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *TCPNameServer) IsDisableCache() bool {
|
||||||
|
return s.cacheController.disableCache
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TCPNameServer) newReqID() uint16 {
|
func (s *TCPNameServer) newReqID() uint16 {
|
||||||
return uint16(atomic.AddUint32(&s.reqID, 1))
|
return uint16(atomic.AddUint32(&s.reqID, 1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, domain string, option dns_feature.IPOption) {
|
// getCacheController implements CachedNameserver.
|
||||||
errors.LogDebug(ctx, s.Name(), " querying DNS for: ", domain)
|
func (s *TCPNameServer) getCacheController() *CacheController {
|
||||||
|
return s.cacheController
|
||||||
|
}
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
// sendQuery implements CachedNameserver.
|
||||||
|
func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- error, fqdn string, option dns_feature.IPOption) {
|
||||||
|
errors.LogInfo(ctx, s.Name(), " querying DNS for: ", fqdn)
|
||||||
|
|
||||||
|
reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
||||||
|
|
||||||
var deadline time.Time
|
var deadline time.Time
|
||||||
if d, ok := ctx.Deadline(); ok {
|
if d, ok := ctx.Deadline(); ok {
|
||||||
@@ -131,14 +142,18 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
b, err := dns.PackMessage(r.msg)
|
b, err := dns.PackMessage(r.msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
errors.LogErrorInner(ctx, err, "failed to pack dns query")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := s.dial(dnsCtx)
|
conn, err := s.dial(dnsCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to dial namesever")
|
errors.LogErrorInner(ctx, err, "failed to dial namesever")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
@@ -146,13 +161,17 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
err = binary.Write(dnsReqBuf, binary.BigEndian, uint16(b.Len()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "binary write failed")
|
errors.LogErrorInner(ctx, err, "binary write failed")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = dnsReqBuf.Write(b.Bytes())
|
_, err = dnsReqBuf.Write(b.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "buffer write failed")
|
errors.LogErrorInner(ctx, err, "buffer write failed")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b.Release()
|
b.Release()
|
||||||
@@ -160,7 +179,9 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
_, err = conn.Write(dnsReqBuf.Bytes())
|
_, err = conn.Write(dnsReqBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to send query")
|
errors.LogErrorInner(ctx, err, "failed to send query")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dnsReqBuf.Release()
|
dnsReqBuf.Release()
|
||||||
@@ -170,80 +191,45 @@ func (s *TCPNameServer) sendQuery(ctx context.Context, noResponseErrCh chan<- er
|
|||||||
n, err := respBuf.ReadFullFrom(conn, 2)
|
n, err := respBuf.ReadFullFrom(conn, 2)
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var length int16
|
var length uint16
|
||||||
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
err = binary.Read(bytes.NewReader(respBuf.Bytes()), binary.BigEndian, &length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
errors.LogErrorInner(ctx, err, "failed to parse response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
respBuf.Clear()
|
respBuf.Clear()
|
||||||
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
n, err = respBuf.ReadFullFrom(conn, int32(length))
|
||||||
if err != nil && n == 0 {
|
if err != nil && n == 0 {
|
||||||
errors.LogErrorInner(ctx, err, "failed to read response length")
|
errors.LogErrorInner(ctx, err, "failed to read response length")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rec, err := parseResponse(respBuf.Bytes())
|
rec, err := parseResponse(respBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
|
errors.LogErrorInner(ctx, err, "failed to parse DNS over TCP response")
|
||||||
noResponseErrCh <- err
|
if noResponseErrCh != nil {
|
||||||
|
noResponseErrCh <- err
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cacheController.updateIP(r, rec)
|
s.cacheController.updateRecord(r, rec)
|
||||||
}(req)
|
}(req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
func (s *TCPNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
||||||
fqdn := Fqdn(domain)
|
return queryIP(ctx, s, domain, option)
|
||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
|
||||||
defer closeSubscribers(sub4, sub6)
|
|
||||||
|
|
||||||
if s.cacheController.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
if sub4 != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub4.Wait():
|
|
||||||
sub4.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sub6 != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub6.Wait():
|
|
||||||
sub6.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
func TestTCPLocalNameServer(t *testing.T) {
|
func TestTCPLocalNameServer(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
@@ -33,7 +33,7 @@ func TestTCPLocalNameServer(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithCache(t *testing.T) {
|
func TestTCPLocalNameServerWithCache(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
@@ -61,7 +61,7 @@ func TestTCPLocalNameServerWithCache(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
@@ -85,7 +85,7 @@ func TestTCPLocalNameServerWithIPv4Override(t *testing.T) {
|
|||||||
func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {
|
func TestTCPLocalNameServerWithIPv6Override(t *testing.T) {
|
||||||
url, err := url.Parse("tcp+local://8.8.8.8")
|
url, err := url.Parse("tcp+local://8.8.8.8")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
s, err := NewTCPLocalNameServer(url, false, net.IP(nil))
|
s, err := NewTCPLocalNameServer(url, false, false, 0, net.IP(nil))
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
|
||||||
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
ips, _, err := s.QueryIP(ctx, "google.com", dns_feature.IPOption{
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package dns
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
go_errors "errors"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -10,7 +9,6 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/log"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol/dns"
|
"github.com/xtls/xray-core/common/protocol/dns"
|
||||||
udp_proto "github.com/xtls/xray-core/common/protocol/udp"
|
udp_proto "github.com/xtls/xray-core/common/protocol/udp"
|
||||||
@@ -39,14 +37,14 @@ type udpDnsRequest struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewClassicNameServer creates udp server object for remote resolving.
|
// NewClassicNameServer creates udp server object for remote resolving.
|
||||||
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, disableCache bool, clientIP net.IP) *ClassicNameServer {
|
func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher, disableCache bool, serveStale bool, serveExpiredTTL uint32, clientIP net.IP) *ClassicNameServer {
|
||||||
// default to 53 if unspecific
|
// default to 53 if unspecific
|
||||||
if address.Port == 0 {
|
if address.Port == 0 {
|
||||||
address.Port = net.Port(53)
|
address.Port = net.Port(53)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &ClassicNameServer{
|
s := &ClassicNameServer{
|
||||||
cacheController: NewCacheController(strings.ToUpper(address.String()), disableCache),
|
cacheController: NewCacheController(strings.ToUpper(address.String()), disableCache, serveStale, serveExpiredTTL),
|
||||||
address: &address,
|
address: &address,
|
||||||
requests: make(map[uint16]*udpDnsRequest),
|
requests: make(map[uint16]*udpDnsRequest),
|
||||||
clientIP: clientIP,
|
clientIP: clientIP,
|
||||||
@@ -56,6 +54,7 @@ func NewClassicNameServer(address net.Destination, dispatcher routing.Dispatcher
|
|||||||
Execute: s.RequestsCleanup,
|
Execute: s.RequestsCleanup,
|
||||||
}
|
}
|
||||||
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
|
s.udpServer = udp.NewDispatcher(dispatcher, s.HandleResponse)
|
||||||
|
|
||||||
errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
|
errors.LogInfo(context.Background(), "DNS: created UDP client initialized for ", address.NetAddr())
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@@ -65,6 +64,11 @@ func (s *ClassicNameServer) Name() string {
|
|||||||
return s.cacheController.name
|
return s.cacheController.name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsDisableCache implements Server.
|
||||||
|
func (s *ClassicNameServer) IsDisableCache() bool {
|
||||||
|
return s.cacheController.disableCache
|
||||||
|
}
|
||||||
|
|
||||||
// RequestsCleanup clears expired items from cache
|
// RequestsCleanup clears expired items from cache
|
||||||
func (s *ClassicNameServer) RequestsCleanup() error {
|
func (s *ClassicNameServer) RequestsCleanup() error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -90,9 +94,11 @@ func (s *ClassicNameServer) RequestsCleanup() error {
|
|||||||
|
|
||||||
// HandleResponse handles udp response packet from remote DNS server.
|
// HandleResponse handles udp response packet from remote DNS server.
|
||||||
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
|
func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_proto.Packet) {
|
||||||
ipRec, err := parseResponse(packet.Payload.Bytes())
|
payload := packet.Payload
|
||||||
|
ipRec, err := parseResponse(payload.Bytes())
|
||||||
|
payload.Release()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogError(ctx, s.Name(), " fail to parse responded DNS udp")
|
errors.LogErrorInner(ctx, err, s.Name(), " fail to parse responded DNS udp")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +111,7 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
|
|||||||
}
|
}
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
if !ok {
|
if !ok {
|
||||||
errors.LogError(ctx, s.Name(), " cannot find the pending request")
|
errors.LogErrorInner(ctx, err, s.Name(), " cannot find the pending request")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,12 +131,14 @@ func (s *ClassicNameServer) HandleResponse(ctx context.Context, packet *udp_prot
|
|||||||
newReq.msg = &newMsg
|
newReq.msg = &newMsg
|
||||||
s.addPendingRequest(&newReq)
|
s.addPendingRequest(&newReq)
|
||||||
b, _ := dns.PackMessage(newReq.msg)
|
b, _ := dns.PackMessage(newReq.msg)
|
||||||
|
copyDest := net.UDPDestination(s.address.Address, s.address.Port)
|
||||||
|
b.UDP = ©Dest
|
||||||
s.udpServer.Dispatch(toDnsContext(newReq.ctx, s.address.String()), *s.address, b)
|
s.udpServer.Dispatch(toDnsContext(newReq.ctx, s.address.String()), *s.address, b)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.cacheController.updateIP(&req.dnsRequest, ipRec)
|
s.cacheController.updateRecord(&req.dnsRequest, ipRec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClassicNameServer) newReqID() uint16 {
|
func (s *ClassicNameServer) newReqID() uint16 {
|
||||||
@@ -146,10 +154,16 @@ func (s *ClassicNameServer) addPendingRequest(req *udpDnsRequest) {
|
|||||||
common.Must(s.requestsCleanup.Start())
|
common.Must(s.requestsCleanup.Start())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, domain string, option dns_feature.IPOption) {
|
// getCacheController implements CachedNameserver.
|
||||||
errors.LogDebug(ctx, s.Name(), " querying DNS for: ", domain)
|
func (s *ClassicNameServer) getCacheController() *CacheController {
|
||||||
|
return s.cacheController
|
||||||
|
}
|
||||||
|
|
||||||
reqs := buildReqMsgs(domain, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
// sendQuery implements CachedNameserver.
|
||||||
|
func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, fqdn string, option dns_feature.IPOption) {
|
||||||
|
errors.LogInfo(ctx, s.Name(), " querying DNS for: ", fqdn)
|
||||||
|
|
||||||
|
reqs := buildReqMsgs(fqdn, option, s.newReqID, genEDNS0Options(s.clientIP, 0))
|
||||||
|
|
||||||
for _, req := range reqs {
|
for _, req := range reqs {
|
||||||
udpReq := &udpDnsRequest{
|
udpReq := &udpDnsRequest{
|
||||||
@@ -158,54 +172,13 @@ func (s *ClassicNameServer) sendQuery(ctx context.Context, _ chan<- error, domai
|
|||||||
}
|
}
|
||||||
s.addPendingRequest(udpReq)
|
s.addPendingRequest(udpReq)
|
||||||
b, _ := dns.PackMessage(req.msg)
|
b, _ := dns.PackMessage(req.msg)
|
||||||
|
copyDest := net.UDPDestination(s.address.Address, s.address.Port)
|
||||||
|
b.UDP = ©Dest
|
||||||
s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
|
s.udpServer.Dispatch(toDnsContext(ctx, s.address.String()), *s.address, b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryIP implements Server.
|
// QueryIP implements Server.
|
||||||
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
func (s *ClassicNameServer) QueryIP(ctx context.Context, domain string, option dns_feature.IPOption) ([]net.IP, uint32, error) {
|
||||||
fqdn := Fqdn(domain)
|
return queryIP(ctx, s, domain, option)
|
||||||
sub4, sub6 := s.cacheController.registerSubscribers(fqdn, option)
|
|
||||||
defer closeSubscribers(sub4, sub6)
|
|
||||||
|
|
||||||
if s.cacheController.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
noResponseErrCh := make(chan error, 2)
|
|
||||||
s.sendQuery(ctx, noResponseErrCh, fqdn, option)
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
if sub4 != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub4.Wait():
|
|
||||||
sub4.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if sub6 != nil {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return nil, 0, ctx.Err()
|
|
||||||
case err := <-noResponseErrCh:
|
|
||||||
return nil, 0, err
|
|
||||||
case <-sub6.Wait():
|
|
||||||
sub6.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/common/signal/done"
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
)
|
)
|
||||||
@@ -108,3 +109,13 @@ func (co *Outbound) Close() error {
|
|||||||
co.closed = true
|
co.closed = true
|
||||||
return co.listener.Close()
|
return co.listener.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SenderSettings implements outbound.Handler.
|
||||||
|
func (co *Outbound) SenderSettings() *serial.TypedMessage {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxySettings implements outbound.Handler.
|
||||||
|
func (co *Outbound) ProxySettings() *serial.TypedMessage {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ type HealthPingConfig struct {
|
|||||||
SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"`
|
SamplingCount int32 `protobuf:"varint,4,opt,name=samplingCount,proto3" json:"samplingCount,omitempty"`
|
||||||
// ping timeout, int64 values of time.Duration
|
// ping timeout, int64 values of time.Duration
|
||||||
Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
Timeout int64 `protobuf:"varint,5,opt,name=timeout,proto3" json:"timeout,omitempty"`
|
||||||
|
// http method to make request
|
||||||
|
HttpMethod string `protobuf:"bytes,6,opt,name=httpMethod,proto3" json:"httpMethod,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *HealthPingConfig) Reset() {
|
func (x *HealthPingConfig) Reset() {
|
||||||
@@ -157,6 +159,13 @@ func (x *HealthPingConfig) GetTimeout() int64 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *HealthPingConfig) GetHttpMethod() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.HttpMethod
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
var File_app_observatory_burst_config_proto protoreflect.FileDescriptor
|
var File_app_observatory_burst_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_observatory_burst_config_proto_rawDesc = []byte{
|
var file_app_observatory_burst_config_proto_rawDesc = []byte{
|
||||||
@@ -173,7 +182,7 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{
|
|||||||
0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72,
|
0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x62, 0x75, 0x72,
|
||||||
0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
0x73, 0x74, 0x2e, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
||||||
0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
|
0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22,
|
||||||
0xb4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
0xd4, 0x01, 0x0a, 0x10, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x50, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
0x6e, 0x66, 0x69, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
||||||
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69,
|
0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69,
|
||||||
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
|
||||||
@@ -184,7 +193,9 @@ var file_app_observatory_burst_config_proto_rawDesc = []byte{
|
|||||||
0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73,
|
0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x73,
|
||||||
0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07,
|
0x61, 0x6d, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07,
|
||||||
0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74,
|
0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x74,
|
||||||
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70, 0x4d, 0x65,
|
||||||
|
0x74, 0x68, 0x6f, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x74, 0x74, 0x70,
|
||||||
|
0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x42, 0x70, 0x0a, 0x1e, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x6f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x6f,
|
||||||
0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68,
|
0x72, 0x79, 0x2e, 0x62, 0x75, 0x72, 0x73, 0x74, 0x50, 0x01, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68,
|
||||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
|
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79,
|
||||||
|
|||||||
@@ -26,4 +26,7 @@ message HealthPingConfig {
|
|||||||
int32 samplingCount = 4;
|
int32 samplingCount = 4;
|
||||||
// ping timeout, int64 values of time.Duration
|
// ping timeout, int64 values of time.Duration
|
||||||
int64 timeout = 5;
|
int64 timeout = 5;
|
||||||
|
// http method to make request
|
||||||
|
string httpMethod = 6;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type HealthPingSettings struct {
|
|||||||
Interval time.Duration `json:"interval"`
|
Interval time.Duration `json:"interval"`
|
||||||
SamplingCount int `json:"sampling"`
|
SamplingCount int `json:"sampling"`
|
||||||
Timeout time.Duration `json:"timeout"`
|
Timeout time.Duration `json:"timeout"`
|
||||||
|
HttpMethod string `json:"httpMethod"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// HealthPing is the health checker for balancers
|
// HealthPing is the health checker for balancers
|
||||||
@@ -37,12 +38,21 @@ type HealthPing struct {
|
|||||||
func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *HealthPingConfig) *HealthPing {
|
func NewHealthPing(ctx context.Context, dispatcher routing.Dispatcher, config *HealthPingConfig) *HealthPing {
|
||||||
settings := &HealthPingSettings{}
|
settings := &HealthPingSettings{}
|
||||||
if config != nil {
|
if config != nil {
|
||||||
|
|
||||||
|
var httpMethod string
|
||||||
|
if config.HttpMethod == "" {
|
||||||
|
httpMethod = "HEAD"
|
||||||
|
} else {
|
||||||
|
httpMethod = strings.TrimSpace(config.HttpMethod)
|
||||||
|
}
|
||||||
|
|
||||||
settings = &HealthPingSettings{
|
settings = &HealthPingSettings{
|
||||||
Connectivity: strings.TrimSpace(config.Connectivity),
|
Connectivity: strings.TrimSpace(config.Connectivity),
|
||||||
Destination: strings.TrimSpace(config.Destination),
|
Destination: strings.TrimSpace(config.Destination),
|
||||||
Interval: time.Duration(config.Interval),
|
Interval: time.Duration(config.Interval),
|
||||||
SamplingCount: int(config.SamplingCount),
|
SamplingCount: int(config.SamplingCount),
|
||||||
Timeout: time.Duration(config.Timeout),
|
Timeout: time.Duration(config.Timeout),
|
||||||
|
HttpMethod: httpMethod,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if settings.Destination == "" {
|
if settings.Destination == "" {
|
||||||
@@ -164,7 +174,7 @@ func (h *HealthPing) doCheck(tags []string, duration time.Duration, rounds int)
|
|||||||
}
|
}
|
||||||
time.AfterFunc(delay, func() {
|
time.AfterFunc(delay, func() {
|
||||||
errors.LogDebug(h.ctx, "checking ", handler)
|
errors.LogDebug(h.ctx, "checking ", handler)
|
||||||
delay, err := client.MeasureDelay()
|
delay, err := client.MeasureDelay(h.Settings.HttpMethod)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
ch <- &rtt{
|
ch <- &rtt{
|
||||||
handler: handler,
|
handler: handler,
|
||||||
@@ -251,7 +261,7 @@ func (h *HealthPing) checkConnectivity() bool {
|
|||||||
h.Settings.Connectivity,
|
h.Settings.Connectivity,
|
||||||
h.Settings.Timeout,
|
h.Settings.Timeout,
|
||||||
)
|
)
|
||||||
if _, err := tester.MeasureDelay(); err != nil {
|
if _, err := tester.MeasureDelay(h.Settings.HttpMethod); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package burst
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -51,20 +52,28 @@ func newHTTPClient(ctxv context.Context, dispatcher routing.Dispatcher, handler
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MeasureDelay returns the delay time of the request to dest
|
// MeasureDelay returns the delay time of the request to dest
|
||||||
func (s *pingClient) MeasureDelay() (time.Duration, error) {
|
func (s *pingClient) MeasureDelay(httpMethod string) (time.Duration, error) {
|
||||||
if s.httpClient == nil {
|
if s.httpClient == nil {
|
||||||
panic("pingClient not initialized")
|
panic("pingClient not initialized")
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest(http.MethodHead, s.destination, nil)
|
|
||||||
|
req, err := http.NewRequest(httpMethod, s.destination, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rttFailed, err
|
return rttFailed, err
|
||||||
}
|
}
|
||||||
|
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
resp, err := s.httpClient.Do(req)
|
resp, err := s.httpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return rttFailed, err
|
return rttFailed, err
|
||||||
}
|
}
|
||||||
// don't wait for body
|
if httpMethod == http.MethodGet {
|
||||||
|
_, err = io.Copy(io.Discard, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return rttFailed, err
|
||||||
|
}
|
||||||
|
}
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
|
|
||||||
return time.Since(start), nil
|
return time.Since(start), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package command
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/app/commander"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
@@ -99,6 +100,28 @@ func (s *handlerServer) AlterInbound(ctx context.Context, request *AlterInboundR
|
|||||||
return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler)
|
return &AlterInboundResponse{}, operation.ApplyInbound(ctx, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *handlerServer) ListInbounds(ctx context.Context, request *ListInboundsRequest) (*ListInboundsResponse, error) {
|
||||||
|
handlers := s.ihm.ListHandlers(ctx)
|
||||||
|
response := &ListInboundsResponse{}
|
||||||
|
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) {
|
func (s *handlerServer) GetInboundUsers(ctx context.Context, request *GetInboundUserRequest) (*GetInboundUserResponse, error) {
|
||||||
handler, err := s.ihm.GetHandler(ctx, request.Tag)
|
handler, err := s.ihm.GetHandler(ctx, request.Tag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -164,6 +187,23 @@ func (s *handlerServer) AlterOutbound(ctx context.Context, request *AlterOutboun
|
|||||||
return &AlterOutboundResponse{}, operation.ApplyOutbound(ctx, handler)
|
return &AlterOutboundResponse{}, operation.ApplyOutbound(ctx, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *handlerServer) ListOutbounds(ctx context.Context, request *ListOutboundsRequest) (*ListOutboundsResponse, error) {
|
||||||
|
handlers := s.ohm.ListHandlers(ctx)
|
||||||
|
response := &ListOutboundsResponse{}
|
||||||
|
for _, handler := range handlers {
|
||||||
|
// Ignore gRPC outbound
|
||||||
|
if _, ok := handler.(*commander.Outbound); ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
response.Outbounds = append(response.Outbounds, &core.OutboundHandlerConfig{
|
||||||
|
Tag: handler.Tag(),
|
||||||
|
SenderSettings: handler.SenderSettings(),
|
||||||
|
ProxySettings: handler.ProxySettings(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *handlerServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
func (s *handlerServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
|
|||||||
@@ -364,6 +364,96 @@ func (*AlterInboundResponse) Descriptor() ([]byte, []int) {
|
|||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{7}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{7}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ListInboundsRequest struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
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 {
|
type GetInboundUserRequest struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -375,7 +465,7 @@ type GetInboundUserRequest struct {
|
|||||||
|
|
||||||
func (x *GetInboundUserRequest) Reset() {
|
func (x *GetInboundUserRequest) Reset() {
|
||||||
*x = GetInboundUserRequest{}
|
*x = GetInboundUserRequest{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[8]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[10]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -387,7 +477,7 @@ func (x *GetInboundUserRequest) String() string {
|
|||||||
func (*GetInboundUserRequest) ProtoMessage() {}
|
func (*GetInboundUserRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message {
|
func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[8]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[10]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -400,7 +490,7 @@ func (x *GetInboundUserRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetInboundUserRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetInboundUserRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*GetInboundUserRequest) Descriptor() ([]byte, []int) {
|
func (*GetInboundUserRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{8}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{10}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUserRequest) GetTag() string {
|
func (x *GetInboundUserRequest) GetTag() string {
|
||||||
@@ -427,7 +517,7 @@ type GetInboundUserResponse struct {
|
|||||||
|
|
||||||
func (x *GetInboundUserResponse) Reset() {
|
func (x *GetInboundUserResponse) Reset() {
|
||||||
*x = GetInboundUserResponse{}
|
*x = GetInboundUserResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[9]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[11]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -439,7 +529,7 @@ func (x *GetInboundUserResponse) String() string {
|
|||||||
func (*GetInboundUserResponse) ProtoMessage() {}
|
func (*GetInboundUserResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message {
|
func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[9]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[11]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -452,7 +542,7 @@ func (x *GetInboundUserResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetInboundUserResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetInboundUserResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*GetInboundUserResponse) Descriptor() ([]byte, []int) {
|
func (*GetInboundUserResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{9}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{11}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUserResponse) GetUsers() []*protocol.User {
|
func (x *GetInboundUserResponse) GetUsers() []*protocol.User {
|
||||||
@@ -472,7 +562,7 @@ type GetInboundUsersCountResponse struct {
|
|||||||
|
|
||||||
func (x *GetInboundUsersCountResponse) Reset() {
|
func (x *GetInboundUsersCountResponse) Reset() {
|
||||||
*x = GetInboundUsersCountResponse{}
|
*x = GetInboundUsersCountResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[10]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[12]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -484,7 +574,7 @@ func (x *GetInboundUsersCountResponse) String() string {
|
|||||||
func (*GetInboundUsersCountResponse) ProtoMessage() {}
|
func (*GetInboundUsersCountResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Message {
|
func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[10]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[12]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -497,7 +587,7 @@ func (x *GetInboundUsersCountResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use GetInboundUsersCountResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use GetInboundUsersCountResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*GetInboundUsersCountResponse) Descriptor() ([]byte, []int) {
|
func (*GetInboundUsersCountResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{10}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{12}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *GetInboundUsersCountResponse) GetCount() int64 {
|
func (x *GetInboundUsersCountResponse) GetCount() int64 {
|
||||||
@@ -517,7 +607,7 @@ type AddOutboundRequest struct {
|
|||||||
|
|
||||||
func (x *AddOutboundRequest) Reset() {
|
func (x *AddOutboundRequest) Reset() {
|
||||||
*x = AddOutboundRequest{}
|
*x = AddOutboundRequest{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[11]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[13]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -529,7 +619,7 @@ func (x *AddOutboundRequest) String() string {
|
|||||||
func (*AddOutboundRequest) ProtoMessage() {}
|
func (*AddOutboundRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message {
|
func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[11]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[13]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -542,7 +632,7 @@ func (x *AddOutboundRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AddOutboundRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AddOutboundRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*AddOutboundRequest) Descriptor() ([]byte, []int) {
|
func (*AddOutboundRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{11}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{13}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AddOutboundRequest) GetOutbound() *core.OutboundHandlerConfig {
|
func (x *AddOutboundRequest) GetOutbound() *core.OutboundHandlerConfig {
|
||||||
@@ -560,7 +650,7 @@ type AddOutboundResponse struct {
|
|||||||
|
|
||||||
func (x *AddOutboundResponse) Reset() {
|
func (x *AddOutboundResponse) Reset() {
|
||||||
*x = AddOutboundResponse{}
|
*x = AddOutboundResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[12]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[14]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -572,7 +662,7 @@ func (x *AddOutboundResponse) String() string {
|
|||||||
func (*AddOutboundResponse) ProtoMessage() {}
|
func (*AddOutboundResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message {
|
func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[12]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[14]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -585,7 +675,7 @@ func (x *AddOutboundResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AddOutboundResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AddOutboundResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*AddOutboundResponse) Descriptor() ([]byte, []int) {
|
func (*AddOutboundResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{12}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{14}
|
||||||
}
|
}
|
||||||
|
|
||||||
type RemoveOutboundRequest struct {
|
type RemoveOutboundRequest struct {
|
||||||
@@ -598,7 +688,7 @@ type RemoveOutboundRequest struct {
|
|||||||
|
|
||||||
func (x *RemoveOutboundRequest) Reset() {
|
func (x *RemoveOutboundRequest) Reset() {
|
||||||
*x = RemoveOutboundRequest{}
|
*x = RemoveOutboundRequest{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[13]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[15]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -610,7 +700,7 @@ func (x *RemoveOutboundRequest) String() string {
|
|||||||
func (*RemoveOutboundRequest) ProtoMessage() {}
|
func (*RemoveOutboundRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message {
|
func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[13]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[15]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -623,7 +713,7 @@ func (x *RemoveOutboundRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use RemoveOutboundRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RemoveOutboundRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*RemoveOutboundRequest) Descriptor() ([]byte, []int) {
|
func (*RemoveOutboundRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{13}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{15}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RemoveOutboundRequest) GetTag() string {
|
func (x *RemoveOutboundRequest) GetTag() string {
|
||||||
@@ -641,7 +731,7 @@ type RemoveOutboundResponse struct {
|
|||||||
|
|
||||||
func (x *RemoveOutboundResponse) Reset() {
|
func (x *RemoveOutboundResponse) Reset() {
|
||||||
*x = RemoveOutboundResponse{}
|
*x = RemoveOutboundResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[14]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[16]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -653,7 +743,7 @@ func (x *RemoveOutboundResponse) String() string {
|
|||||||
func (*RemoveOutboundResponse) ProtoMessage() {}
|
func (*RemoveOutboundResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message {
|
func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[14]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[16]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -666,7 +756,7 @@ func (x *RemoveOutboundResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use RemoveOutboundResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use RemoveOutboundResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*RemoveOutboundResponse) Descriptor() ([]byte, []int) {
|
func (*RemoveOutboundResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{14}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{16}
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlterOutboundRequest struct {
|
type AlterOutboundRequest struct {
|
||||||
@@ -680,7 +770,7 @@ type AlterOutboundRequest struct {
|
|||||||
|
|
||||||
func (x *AlterOutboundRequest) Reset() {
|
func (x *AlterOutboundRequest) Reset() {
|
||||||
*x = AlterOutboundRequest{}
|
*x = AlterOutboundRequest{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[15]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[17]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -692,7 +782,7 @@ func (x *AlterOutboundRequest) String() string {
|
|||||||
func (*AlterOutboundRequest) ProtoMessage() {}
|
func (*AlterOutboundRequest) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message {
|
func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[15]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[17]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -705,7 +795,7 @@ func (x *AlterOutboundRequest) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AlterOutboundRequest.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AlterOutboundRequest.ProtoReflect.Descriptor instead.
|
||||||
func (*AlterOutboundRequest) Descriptor() ([]byte, []int) {
|
func (*AlterOutboundRequest) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{15}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{17}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *AlterOutboundRequest) GetTag() string {
|
func (x *AlterOutboundRequest) GetTag() string {
|
||||||
@@ -730,7 +820,7 @@ type AlterOutboundResponse struct {
|
|||||||
|
|
||||||
func (x *AlterOutboundResponse) Reset() {
|
func (x *AlterOutboundResponse) Reset() {
|
||||||
*x = AlterOutboundResponse{}
|
*x = AlterOutboundResponse{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[16]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[18]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -742,7 +832,7 @@ func (x *AlterOutboundResponse) String() string {
|
|||||||
func (*AlterOutboundResponse) ProtoMessage() {}
|
func (*AlterOutboundResponse) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message {
|
func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[16]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[18]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -755,7 +845,88 @@ func (x *AlterOutboundResponse) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use AlterOutboundResponse.ProtoReflect.Descriptor instead.
|
// Deprecated: Use AlterOutboundResponse.ProtoReflect.Descriptor instead.
|
||||||
func (*AlterOutboundResponse) Descriptor() ([]byte, []int) {
|
func (*AlterOutboundResponse) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{16}
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
@@ -766,7 +937,7 @@ type Config struct {
|
|||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
*x = Config{}
|
*x = Config{}
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[17]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[21]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -778,7 +949,7 @@ func (x *Config) String() string {
|
|||||||
func (*Config) ProtoMessage() {}
|
func (*Config) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_command_command_proto_msgTypes[17]
|
mi := &file_app_proxyman_command_command_proto_msgTypes[21]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -791,7 +962,7 @@ func (x *Config) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||||
func (*Config) Descriptor() ([]byte, []int) {
|
func (*Config) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{17}
|
return file_app_proxyman_command_command_proto_rawDescGZIP(), []int{21}
|
||||||
}
|
}
|
||||||
|
|
||||||
var File_app_proxyman_command_command_proto protoreflect.FileDescriptor
|
var File_app_proxyman_command_command_proto protoreflect.FileDescriptor
|
||||||
@@ -831,61 +1002,84 @@ var file_app_proxyman_command_command_proto_rawDesc = []byte{
|
|||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70,
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70,
|
||||||
0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61,
|
0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62,
|
0x74, 0x69, 0x6f, 0x6e, 0x22, 0x16, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62,
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x0a, 0x15,
|
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x35, 0x0a, 0x13,
|
||||||
0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65,
|
0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01,
|
0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x54, 0x61, 0x67,
|
||||||
0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c,
|
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x4f, 0x6e, 0x6c, 0x79, 0x54,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a,
|
0x61, 0x67, 0x73, 0x22, 0x53, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75,
|
||||||
0x16, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52,
|
0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3b, 0x0a, 0x08, 0x69,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73,
|
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e,
|
||||||
0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
||||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73,
|
0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08,
|
||||||
0x65, 0x72, 0x52, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x1c, 0x47, 0x65, 0x74,
|
0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22, 0x3f, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x49,
|
||||||
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e,
|
0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75,
|
0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
|
||||||
0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22,
|
0x74, 0x61, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01,
|
||||||
0x52, 0x0a, 0x12, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65,
|
0x28, 0x09, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x4a, 0x0a, 0x16, 0x47, 0x65, 0x74,
|
||||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e,
|
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
0x6e, 0x73, 0x65, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x73, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||||
0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64,
|
0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||||
0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f,
|
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x52, 0x05,
|
||||||
0x75, 0x6e, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x41, 0x64, 0x64, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
0x75, 0x73, 0x65, 0x72, 0x73, 0x22, 0x34, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f,
|
||||||
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x0a, 0x15, 0x52, 0x65,
|
0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73,
|
||||||
0x6d, 0x6f, 0x76, 0x65, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75,
|
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,
|
||||||
0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x18, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4f,
|
0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
|
||||||
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x68, 0x0a, 0x14, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01,
|
0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x3e, 0x0a, 0x09, 0x6f, 0x70, 0x65,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x4f, 0x75,
|
||||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78,
|
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
|
0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52,
|
||||||
0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x09,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x57, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75,
|
||||||
0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x41, 0x6c, 0x74,
|
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||||
0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x3e, 0x0a, 0x09, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||||
0x73, 0x65, 0x22, 0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xc5, 0x07, 0x0a,
|
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f,
|
||||||
0x0e, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
|
0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f,
|
||||||
0x6b, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e,
|
0x6e, 0x66, 0x69, 0x67, 0x52, 0x09, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x22,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
0x08, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x32, 0xae, 0x09, 0x0a, 0x0e, 0x48, 0x61,
|
||||||
0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62,
|
0x6e, 0x64, 0x6c, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x6b, 0x0a, 0x0a,
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x72,
|
0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63,
|
||||||
|
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
||||||
|
0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
|
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
|
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x64, 0x64, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52,
|
||||||
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, 0x52, 0x65, 0x6d,
|
||||||
|
0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61,
|
||||||
|
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63,
|
||||||
|
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62,
|
||||||
|
0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e,
|
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,
|
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e,
|
||||||
0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d,
|
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
||||||
0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x2f, 0x2e,
|
0x71, 0x0a, 0x0c, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x12,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||||
0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
||||||
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30,
|
0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
|
||||||
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d,
|
0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||||
0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76,
|
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74, 0x65,
|
||||||
0x65, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
0x72, 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,
|
0x22, 0x00, 0x12, 0x71, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e,
|
||||||
0x6e, 0x64, 0x12, 0x2e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
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, 0x41,
|
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c,
|
||||||
0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
|
0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||||
0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
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,
|
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4c,
|
||||||
0x6c, 0x74, 0x65, 0x72, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
0x69, 0x73, 0x74, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||||
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x78, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f,
|
0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x78, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x62, 0x6f,
|
||||||
0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x75, 0x6e, 0x64, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
@@ -924,14 +1118,22 @@ var file_app_proxyman_command_command_proto_rawDesc = []byte{
|
|||||||
0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74,
|
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x41, 0x6c, 0x74,
|
||||||
0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
0x65, 0x72, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||||
0x73, 0x65, 0x22, 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62,
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f,
|
0x6f, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
||||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
|
||||||
0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f,
|
0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x52,
|
||||||
0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f,
|
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x19, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41,
|
0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||||
0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
0x6e, 0x64, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x73,
|
||||||
0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x6d, 0x0a, 0x1d, 0x63, 0x6f,
|
||||||
|
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||||
|
0x6d, 0x61, 0x6e, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2e, 0x67,
|
||||||
|
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78,
|
||||||
|
0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f,
|
||||||
|
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x19,
|
||||||
|
0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||||
|
0x6e, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
|
0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -946,7 +1148,7 @@ func file_app_proxyman_command_command_proto_rawDescGZIP() []byte {
|
|||||||
return file_app_proxyman_command_command_proto_rawDescData
|
return file_app_proxyman_command_command_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_app_proxyman_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
|
var file_app_proxyman_command_command_proto_msgTypes = make([]protoimpl.MessageInfo, 22)
|
||||||
var file_app_proxyman_command_command_proto_goTypes = []any{
|
var file_app_proxyman_command_command_proto_goTypes = []any{
|
||||||
(*AddUserOperation)(nil), // 0: xray.app.proxyman.command.AddUserOperation
|
(*AddUserOperation)(nil), // 0: xray.app.proxyman.command.AddUserOperation
|
||||||
(*RemoveUserOperation)(nil), // 1: xray.app.proxyman.command.RemoveUserOperation
|
(*RemoveUserOperation)(nil), // 1: xray.app.proxyman.command.RemoveUserOperation
|
||||||
@@ -956,49 +1158,59 @@ var file_app_proxyman_command_command_proto_goTypes = []any{
|
|||||||
(*RemoveInboundResponse)(nil), // 5: xray.app.proxyman.command.RemoveInboundResponse
|
(*RemoveInboundResponse)(nil), // 5: xray.app.proxyman.command.RemoveInboundResponse
|
||||||
(*AlterInboundRequest)(nil), // 6: xray.app.proxyman.command.AlterInboundRequest
|
(*AlterInboundRequest)(nil), // 6: xray.app.proxyman.command.AlterInboundRequest
|
||||||
(*AlterInboundResponse)(nil), // 7: xray.app.proxyman.command.AlterInboundResponse
|
(*AlterInboundResponse)(nil), // 7: xray.app.proxyman.command.AlterInboundResponse
|
||||||
(*GetInboundUserRequest)(nil), // 8: xray.app.proxyman.command.GetInboundUserRequest
|
(*ListInboundsRequest)(nil), // 8: xray.app.proxyman.command.ListInboundsRequest
|
||||||
(*GetInboundUserResponse)(nil), // 9: xray.app.proxyman.command.GetInboundUserResponse
|
(*ListInboundsResponse)(nil), // 9: xray.app.proxyman.command.ListInboundsResponse
|
||||||
(*GetInboundUsersCountResponse)(nil), // 10: xray.app.proxyman.command.GetInboundUsersCountResponse
|
(*GetInboundUserRequest)(nil), // 10: xray.app.proxyman.command.GetInboundUserRequest
|
||||||
(*AddOutboundRequest)(nil), // 11: xray.app.proxyman.command.AddOutboundRequest
|
(*GetInboundUserResponse)(nil), // 11: xray.app.proxyman.command.GetInboundUserResponse
|
||||||
(*AddOutboundResponse)(nil), // 12: xray.app.proxyman.command.AddOutboundResponse
|
(*GetInboundUsersCountResponse)(nil), // 12: xray.app.proxyman.command.GetInboundUsersCountResponse
|
||||||
(*RemoveOutboundRequest)(nil), // 13: xray.app.proxyman.command.RemoveOutboundRequest
|
(*AddOutboundRequest)(nil), // 13: xray.app.proxyman.command.AddOutboundRequest
|
||||||
(*RemoveOutboundResponse)(nil), // 14: xray.app.proxyman.command.RemoveOutboundResponse
|
(*AddOutboundResponse)(nil), // 14: xray.app.proxyman.command.AddOutboundResponse
|
||||||
(*AlterOutboundRequest)(nil), // 15: xray.app.proxyman.command.AlterOutboundRequest
|
(*RemoveOutboundRequest)(nil), // 15: xray.app.proxyman.command.RemoveOutboundRequest
|
||||||
(*AlterOutboundResponse)(nil), // 16: xray.app.proxyman.command.AlterOutboundResponse
|
(*RemoveOutboundResponse)(nil), // 16: xray.app.proxyman.command.RemoveOutboundResponse
|
||||||
(*Config)(nil), // 17: xray.app.proxyman.command.Config
|
(*AlterOutboundRequest)(nil), // 17: xray.app.proxyman.command.AlterOutboundRequest
|
||||||
(*protocol.User)(nil), // 18: xray.common.protocol.User
|
(*AlterOutboundResponse)(nil), // 18: xray.app.proxyman.command.AlterOutboundResponse
|
||||||
(*core.InboundHandlerConfig)(nil), // 19: xray.core.InboundHandlerConfig
|
(*ListOutboundsRequest)(nil), // 19: xray.app.proxyman.command.ListOutboundsRequest
|
||||||
(*serial.TypedMessage)(nil), // 20: xray.common.serial.TypedMessage
|
(*ListOutboundsResponse)(nil), // 20: xray.app.proxyman.command.ListOutboundsResponse
|
||||||
(*core.OutboundHandlerConfig)(nil), // 21: xray.core.OutboundHandlerConfig
|
(*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
|
||||||
}
|
}
|
||||||
var file_app_proxyman_command_command_proto_depIdxs = []int32{
|
var file_app_proxyman_command_command_proto_depIdxs = []int32{
|
||||||
18, // 0: xray.app.proxyman.command.AddUserOperation.user:type_name -> xray.common.protocol.User
|
22, // 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
|
23, // 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
|
24, // 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
|
23, // 3: xray.app.proxyman.command.ListInboundsResponse.inbounds:type_name -> xray.core.InboundHandlerConfig
|
||||||
21, // 4: xray.app.proxyman.command.AddOutboundRequest.outbound:type_name -> xray.core.OutboundHandlerConfig
|
22, // 4: xray.app.proxyman.command.GetInboundUserResponse.users:type_name -> xray.common.protocol.User
|
||||||
20, // 5: xray.app.proxyman.command.AlterOutboundRequest.operation:type_name -> xray.common.serial.TypedMessage
|
25, // 5: xray.app.proxyman.command.AddOutboundRequest.outbound:type_name -> xray.core.OutboundHandlerConfig
|
||||||
2, // 6: xray.app.proxyman.command.HandlerService.AddInbound:input_type -> xray.app.proxyman.command.AddInboundRequest
|
24, // 6: xray.app.proxyman.command.AlterOutboundRequest.operation:type_name -> xray.common.serial.TypedMessage
|
||||||
4, // 7: xray.app.proxyman.command.HandlerService.RemoveInbound:input_type -> xray.app.proxyman.command.RemoveInboundRequest
|
25, // 7: xray.app.proxyman.command.ListOutboundsResponse.outbounds:type_name -> xray.core.OutboundHandlerConfig
|
||||||
6, // 8: xray.app.proxyman.command.HandlerService.AlterInbound:input_type -> xray.app.proxyman.command.AlterInboundRequest
|
2, // 8: xray.app.proxyman.command.HandlerService.AddInbound:input_type -> xray.app.proxyman.command.AddInboundRequest
|
||||||
8, // 9: xray.app.proxyman.command.HandlerService.GetInboundUsers:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
4, // 9: xray.app.proxyman.command.HandlerService.RemoveInbound:input_type -> xray.app.proxyman.command.RemoveInboundRequest
|
||||||
8, // 10: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
6, // 10: xray.app.proxyman.command.HandlerService.AlterInbound:input_type -> xray.app.proxyman.command.AlterInboundRequest
|
||||||
11, // 11: xray.app.proxyman.command.HandlerService.AddOutbound:input_type -> xray.app.proxyman.command.AddOutboundRequest
|
8, // 11: xray.app.proxyman.command.HandlerService.ListInbounds:input_type -> xray.app.proxyman.command.ListInboundsRequest
|
||||||
13, // 12: xray.app.proxyman.command.HandlerService.RemoveOutbound:input_type -> xray.app.proxyman.command.RemoveOutboundRequest
|
10, // 12: xray.app.proxyman.command.HandlerService.GetInboundUsers:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
||||||
15, // 13: xray.app.proxyman.command.HandlerService.AlterOutbound:input_type -> xray.app.proxyman.command.AlterOutboundRequest
|
10, // 13: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:input_type -> xray.app.proxyman.command.GetInboundUserRequest
|
||||||
3, // 14: xray.app.proxyman.command.HandlerService.AddInbound:output_type -> xray.app.proxyman.command.AddInboundResponse
|
13, // 14: xray.app.proxyman.command.HandlerService.AddOutbound:input_type -> xray.app.proxyman.command.AddOutboundRequest
|
||||||
5, // 15: xray.app.proxyman.command.HandlerService.RemoveInbound:output_type -> xray.app.proxyman.command.RemoveInboundResponse
|
15, // 15: xray.app.proxyman.command.HandlerService.RemoveOutbound:input_type -> xray.app.proxyman.command.RemoveOutboundRequest
|
||||||
7, // 16: xray.app.proxyman.command.HandlerService.AlterInbound:output_type -> xray.app.proxyman.command.AlterInboundResponse
|
17, // 16: xray.app.proxyman.command.HandlerService.AlterOutbound:input_type -> xray.app.proxyman.command.AlterOutboundRequest
|
||||||
9, // 17: xray.app.proxyman.command.HandlerService.GetInboundUsers:output_type -> xray.app.proxyman.command.GetInboundUserResponse
|
19, // 17: xray.app.proxyman.command.HandlerService.ListOutbounds:input_type -> xray.app.proxyman.command.ListOutboundsRequest
|
||||||
10, // 18: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:output_type -> xray.app.proxyman.command.GetInboundUsersCountResponse
|
3, // 18: xray.app.proxyman.command.HandlerService.AddInbound:output_type -> xray.app.proxyman.command.AddInboundResponse
|
||||||
12, // 19: xray.app.proxyman.command.HandlerService.AddOutbound:output_type -> xray.app.proxyman.command.AddOutboundResponse
|
5, // 19: xray.app.proxyman.command.HandlerService.RemoveInbound:output_type -> xray.app.proxyman.command.RemoveInboundResponse
|
||||||
14, // 20: xray.app.proxyman.command.HandlerService.RemoveOutbound:output_type -> xray.app.proxyman.command.RemoveOutboundResponse
|
7, // 20: xray.app.proxyman.command.HandlerService.AlterInbound:output_type -> xray.app.proxyman.command.AlterInboundResponse
|
||||||
16, // 21: xray.app.proxyman.command.HandlerService.AlterOutbound:output_type -> xray.app.proxyman.command.AlterOutboundResponse
|
9, // 21: xray.app.proxyman.command.HandlerService.ListInbounds:output_type -> xray.app.proxyman.command.ListInboundsResponse
|
||||||
14, // [14:22] is the sub-list for method output_type
|
11, // 22: xray.app.proxyman.command.HandlerService.GetInboundUsers:output_type -> xray.app.proxyman.command.GetInboundUserResponse
|
||||||
6, // [6:14] is the sub-list for method input_type
|
12, // 23: xray.app.proxyman.command.HandlerService.GetInboundUsersCount:output_type -> xray.app.proxyman.command.GetInboundUsersCountResponse
|
||||||
6, // [6:6] is the sub-list for extension type_name
|
14, // 24: xray.app.proxyman.command.HandlerService.AddOutbound:output_type -> xray.app.proxyman.command.AddOutboundResponse
|
||||||
6, // [6:6] is the sub-list for extension extendee
|
16, // 25: xray.app.proxyman.command.HandlerService.RemoveOutbound:output_type -> xray.app.proxyman.command.RemoveOutboundResponse
|
||||||
0, // [0:6] is the sub-list for field type_name
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_proxyman_command_command_proto_init() }
|
func init() { file_app_proxyman_command_command_proto_init() }
|
||||||
@@ -1012,7 +1224,7 @@ func file_app_proxyman_command_command_proto_init() {
|
|||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_proxyman_command_command_proto_rawDesc,
|
RawDescriptor: file_app_proxyman_command_command_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 18,
|
NumMessages: 22,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 1,
|
NumServices: 1,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -37,6 +37,14 @@ message AlterInboundRequest {
|
|||||||
|
|
||||||
message AlterInboundResponse {}
|
message AlterInboundResponse {}
|
||||||
|
|
||||||
|
message ListInboundsRequest {
|
||||||
|
bool isOnlyTags = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ListInboundsResponse {
|
||||||
|
repeated core.InboundHandlerConfig inbounds = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message GetInboundUserRequest {
|
message GetInboundUserRequest {
|
||||||
string tag = 1;
|
string tag = 1;
|
||||||
string email = 2;
|
string email = 2;
|
||||||
@@ -69,6 +77,12 @@ message AlterOutboundRequest {
|
|||||||
|
|
||||||
message AlterOutboundResponse {}
|
message AlterOutboundResponse {}
|
||||||
|
|
||||||
|
message ListOutboundsRequest {}
|
||||||
|
|
||||||
|
message ListOutboundsResponse {
|
||||||
|
repeated core.OutboundHandlerConfig outbounds = 1;
|
||||||
|
}
|
||||||
|
|
||||||
service HandlerService {
|
service HandlerService {
|
||||||
rpc AddInbound(AddInboundRequest) returns (AddInboundResponse) {}
|
rpc AddInbound(AddInboundRequest) returns (AddInboundResponse) {}
|
||||||
|
|
||||||
@@ -76,6 +90,8 @@ service HandlerService {
|
|||||||
|
|
||||||
rpc AlterInbound(AlterInboundRequest) returns (AlterInboundResponse) {}
|
rpc AlterInbound(AlterInboundRequest) returns (AlterInboundResponse) {}
|
||||||
|
|
||||||
|
rpc ListInbounds(ListInboundsRequest) returns (ListInboundsResponse) {}
|
||||||
|
|
||||||
rpc GetInboundUsers(GetInboundUserRequest) returns (GetInboundUserResponse) {}
|
rpc GetInboundUsers(GetInboundUserRequest) returns (GetInboundUserResponse) {}
|
||||||
|
|
||||||
rpc GetInboundUsersCount(GetInboundUserRequest) returns (GetInboundUsersCountResponse) {}
|
rpc GetInboundUsersCount(GetInboundUserRequest) returns (GetInboundUsersCountResponse) {}
|
||||||
@@ -85,6 +101,8 @@ service HandlerService {
|
|||||||
rpc RemoveOutbound(RemoveOutboundRequest) returns (RemoveOutboundResponse) {}
|
rpc RemoveOutbound(RemoveOutboundRequest) returns (RemoveOutboundResponse) {}
|
||||||
|
|
||||||
rpc AlterOutbound(AlterOutboundRequest) returns (AlterOutboundResponse) {}
|
rpc AlterOutbound(AlterOutboundRequest) returns (AlterOutboundResponse) {}
|
||||||
|
|
||||||
|
rpc ListOutbounds(ListOutboundsRequest) returns (ListOutboundsResponse) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
message Config {}
|
message Config {}
|
||||||
|
|||||||
@@ -22,11 +22,13 @@ const (
|
|||||||
HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound"
|
HandlerService_AddInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddInbound"
|
||||||
HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound"
|
HandlerService_RemoveInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveInbound"
|
||||||
HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound"
|
HandlerService_AlterInbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterInbound"
|
||||||
|
HandlerService_ListInbounds_FullMethodName = "/xray.app.proxyman.command.HandlerService/ListInbounds"
|
||||||
HandlerService_GetInboundUsers_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsers"
|
HandlerService_GetInboundUsers_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsers"
|
||||||
HandlerService_GetInboundUsersCount_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsersCount"
|
HandlerService_GetInboundUsersCount_FullMethodName = "/xray.app.proxyman.command.HandlerService/GetInboundUsersCount"
|
||||||
HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound"
|
HandlerService_AddOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AddOutbound"
|
||||||
HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound"
|
HandlerService_RemoveOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/RemoveOutbound"
|
||||||
HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound"
|
HandlerService_AlterOutbound_FullMethodName = "/xray.app.proxyman.command.HandlerService/AlterOutbound"
|
||||||
|
HandlerService_ListOutbounds_FullMethodName = "/xray.app.proxyman.command.HandlerService/ListOutbounds"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HandlerServiceClient is the client API for HandlerService service.
|
// HandlerServiceClient is the client API for HandlerService service.
|
||||||
@@ -36,11 +38,13 @@ type HandlerServiceClient interface {
|
|||||||
AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error)
|
AddInbound(ctx context.Context, in *AddInboundRequest, opts ...grpc.CallOption) (*AddInboundResponse, error)
|
||||||
RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error)
|
RemoveInbound(ctx context.Context, in *RemoveInboundRequest, opts ...grpc.CallOption) (*RemoveInboundResponse, error)
|
||||||
AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error)
|
AlterInbound(ctx context.Context, in *AlterInboundRequest, opts ...grpc.CallOption) (*AlterInboundResponse, error)
|
||||||
|
ListInbounds(ctx context.Context, in *ListInboundsRequest, opts ...grpc.CallOption) (*ListInboundsResponse, error)
|
||||||
GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error)
|
GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error)
|
||||||
GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error)
|
GetInboundUsersCount(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUsersCountResponse, error)
|
||||||
AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error)
|
AddOutbound(ctx context.Context, in *AddOutboundRequest, opts ...grpc.CallOption) (*AddOutboundResponse, error)
|
||||||
RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error)
|
RemoveOutbound(ctx context.Context, in *RemoveOutboundRequest, opts ...grpc.CallOption) (*RemoveOutboundResponse, error)
|
||||||
AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error)
|
AlterOutbound(ctx context.Context, in *AlterOutboundRequest, opts ...grpc.CallOption) (*AlterOutboundResponse, error)
|
||||||
|
ListOutbounds(ctx context.Context, in *ListOutboundsRequest, opts ...grpc.CallOption) (*ListOutboundsResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type handlerServiceClient struct {
|
type handlerServiceClient struct {
|
||||||
@@ -81,6 +85,16 @@ func (c *handlerServiceClient) AlterInbound(ctx context.Context, in *AlterInboun
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *handlerServiceClient) ListInbounds(ctx context.Context, in *ListInboundsRequest, opts ...grpc.CallOption) (*ListInboundsResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListInboundsResponse)
|
||||||
|
err := c.cc.Invoke(ctx, HandlerService_ListInbounds_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *handlerServiceClient) GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error) {
|
func (c *handlerServiceClient) GetInboundUsers(ctx context.Context, in *GetInboundUserRequest, opts ...grpc.CallOption) (*GetInboundUserResponse, error) {
|
||||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
out := new(GetInboundUserResponse)
|
out := new(GetInboundUserResponse)
|
||||||
@@ -131,6 +145,16 @@ func (c *handlerServiceClient) AlterOutbound(ctx context.Context, in *AlterOutbo
|
|||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *handlerServiceClient) ListOutbounds(ctx context.Context, in *ListOutboundsRequest, opts ...grpc.CallOption) (*ListOutboundsResponse, error) {
|
||||||
|
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||||
|
out := new(ListOutboundsResponse)
|
||||||
|
err := c.cc.Invoke(ctx, HandlerService_ListOutbounds_FullMethodName, in, out, cOpts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// HandlerServiceServer is the server API for HandlerService service.
|
// HandlerServiceServer is the server API for HandlerService service.
|
||||||
// All implementations must embed UnimplementedHandlerServiceServer
|
// All implementations must embed UnimplementedHandlerServiceServer
|
||||||
// for forward compatibility.
|
// for forward compatibility.
|
||||||
@@ -138,11 +162,13 @@ type HandlerServiceServer interface {
|
|||||||
AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error)
|
AddInbound(context.Context, *AddInboundRequest) (*AddInboundResponse, error)
|
||||||
RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error)
|
RemoveInbound(context.Context, *RemoveInboundRequest) (*RemoveInboundResponse, error)
|
||||||
AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error)
|
AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error)
|
||||||
|
ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error)
|
||||||
GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error)
|
GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error)
|
||||||
GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error)
|
GetInboundUsersCount(context.Context, *GetInboundUserRequest) (*GetInboundUsersCountResponse, error)
|
||||||
AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error)
|
AddOutbound(context.Context, *AddOutboundRequest) (*AddOutboundResponse, error)
|
||||||
RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error)
|
RemoveOutbound(context.Context, *RemoveOutboundRequest) (*RemoveOutboundResponse, error)
|
||||||
AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error)
|
AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error)
|
||||||
|
ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error)
|
||||||
mustEmbedUnimplementedHandlerServiceServer()
|
mustEmbedUnimplementedHandlerServiceServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,6 +188,9 @@ func (UnimplementedHandlerServiceServer) RemoveInbound(context.Context, *RemoveI
|
|||||||
func (UnimplementedHandlerServiceServer) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) {
|
func (UnimplementedHandlerServiceServer) AlterInbound(context.Context, *AlterInboundRequest) (*AlterInboundResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method AlterInbound not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method AlterInbound not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedHandlerServiceServer) ListInbounds(context.Context, *ListInboundsRequest) (*ListInboundsResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListInbounds not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedHandlerServiceServer) GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error) {
|
func (UnimplementedHandlerServiceServer) GetInboundUsers(context.Context, *GetInboundUserRequest) (*GetInboundUserResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method GetInboundUsers not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method GetInboundUsers not implemented")
|
||||||
}
|
}
|
||||||
@@ -177,6 +206,9 @@ func (UnimplementedHandlerServiceServer) RemoveOutbound(context.Context, *Remove
|
|||||||
func (UnimplementedHandlerServiceServer) AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error) {
|
func (UnimplementedHandlerServiceServer) AlterOutbound(context.Context, *AlterOutboundRequest) (*AlterOutboundResponse, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method AlterOutbound not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method AlterOutbound not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedHandlerServiceServer) ListOutbounds(context.Context, *ListOutboundsRequest) (*ListOutboundsResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ListOutbounds not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
func (UnimplementedHandlerServiceServer) mustEmbedUnimplementedHandlerServiceServer() {}
|
||||||
func (UnimplementedHandlerServiceServer) testEmbeddedByValue() {}
|
func (UnimplementedHandlerServiceServer) testEmbeddedByValue() {}
|
||||||
|
|
||||||
@@ -252,6 +284,24 @@ func _HandlerService_AlterInbound_Handler(srv interface{}, ctx context.Context,
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _HandlerService_ListInbounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListInboundsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(HandlerServiceServer).ListInbounds(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: HandlerService_ListInbounds_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HandlerServiceServer).ListInbounds(ctx, req.(*ListInboundsRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
func _HandlerService_GetInboundUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _HandlerService_GetInboundUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(GetInboundUserRequest)
|
in := new(GetInboundUserRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@@ -342,6 +392,24 @@ func _HandlerService_AlterOutbound_Handler(srv interface{}, ctx context.Context,
|
|||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _HandlerService_ListOutbounds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(ListOutboundsRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(HandlerServiceServer).ListOutbounds(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: HandlerService_ListOutbounds_FullMethodName,
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(HandlerServiceServer).ListOutbounds(ctx, req.(*ListOutboundsRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// HandlerService_ServiceDesc is the grpc.ServiceDesc for HandlerService service.
|
// HandlerService_ServiceDesc is the grpc.ServiceDesc for HandlerService service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
@@ -361,6 +429,10 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "AlterInbound",
|
MethodName: "AlterInbound",
|
||||||
Handler: _HandlerService_AlterInbound_Handler,
|
Handler: _HandlerService_AlterInbound_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListInbounds",
|
||||||
|
Handler: _HandlerService_ListInbounds_Handler,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
MethodName: "GetInboundUsers",
|
MethodName: "GetInboundUsers",
|
||||||
Handler: _HandlerService_GetInboundUsers_Handler,
|
Handler: _HandlerService_GetInboundUsers_Handler,
|
||||||
@@ -381,6 +453,10 @@ var HandlerService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
MethodName: "AlterOutbound",
|
MethodName: "AlterOutbound",
|
||||||
Handler: _HandlerService_AlterOutbound_Handler,
|
Handler: _HandlerService_AlterOutbound_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ListOutbounds",
|
||||||
|
Handler: _HandlerService_ListOutbounds_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{},
|
Streams: []grpc.StreamDesc{},
|
||||||
Metadata: "app/proxyman/command/command.proto",
|
Metadata: "app/proxyman/command/command.proto",
|
||||||
|
|||||||
@@ -1,23 +1 @@
|
|||||||
package proxyman
|
package proxyman
|
||||||
|
|
||||||
func (s *AllocationStrategy) GetConcurrencyValue() uint32 {
|
|
||||||
if s == nil || s.Concurrency == nil {
|
|
||||||
return 3
|
|
||||||
}
|
|
||||||
return s.Concurrency.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AllocationStrategy) GetRefreshValue() uint32 {
|
|
||||||
if s == nil || s.Refresh == nil {
|
|
||||||
return 5
|
|
||||||
}
|
|
||||||
return s.Refresh.Value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ReceiverConfig) GetEffectiveSniffingSettings() *SniffingConfig {
|
|
||||||
if c.SniffingSettings != nil {
|
|
||||||
return c.SniffingSettings
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -23,58 +23,6 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
type AllocationStrategy_Type int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Always allocate all connection handlers.
|
|
||||||
AllocationStrategy_Always AllocationStrategy_Type = 0
|
|
||||||
// Randomly allocate specific range of handlers.
|
|
||||||
AllocationStrategy_Random AllocationStrategy_Type = 1
|
|
||||||
// External. Not supported yet.
|
|
||||||
AllocationStrategy_External AllocationStrategy_Type = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for AllocationStrategy_Type.
|
|
||||||
var (
|
|
||||||
AllocationStrategy_Type_name = map[int32]string{
|
|
||||||
0: "Always",
|
|
||||||
1: "Random",
|
|
||||||
2: "External",
|
|
||||||
}
|
|
||||||
AllocationStrategy_Type_value = map[string]int32{
|
|
||||||
"Always": 0,
|
|
||||||
"Random": 1,
|
|
||||||
"External": 2,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x AllocationStrategy_Type) Enum() *AllocationStrategy_Type {
|
|
||||||
p := new(AllocationStrategy_Type)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x AllocationStrategy_Type) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (AllocationStrategy_Type) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_app_proxyman_config_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (AllocationStrategy_Type) Type() protoreflect.EnumType {
|
|
||||||
return &file_app_proxyman_config_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x AllocationStrategy_Type) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use AllocationStrategy_Type.Descriptor instead.
|
|
||||||
func (AllocationStrategy_Type) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type InboundConfig struct {
|
type InboundConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -111,71 +59,6 @@ func (*InboundConfig) Descriptor() ([]byte, []int) {
|
|||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{0}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
type AllocationStrategy struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Type AllocationStrategy_Type `protobuf:"varint,1,opt,name=type,proto3,enum=xray.app.proxyman.AllocationStrategy_Type" json:"type,omitempty"`
|
|
||||||
// Number of handlers (ports) running in parallel.
|
|
||||||
// Default value is 3 if unset.
|
|
||||||
Concurrency *AllocationStrategy_AllocationStrategyConcurrency `protobuf:"bytes,2,opt,name=concurrency,proto3" json:"concurrency,omitempty"`
|
|
||||||
// Number of minutes before a handler is regenerated.
|
|
||||||
// Default value is 5 if unset.
|
|
||||||
Refresh *AllocationStrategy_AllocationStrategyRefresh `protobuf:"bytes,3,opt,name=refresh,proto3" json:"refresh,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) Reset() {
|
|
||||||
*x = AllocationStrategy{}
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[1]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*AllocationStrategy) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[1]
|
|
||||||
if x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use AllocationStrategy.ProtoReflect.Descriptor instead.
|
|
||||||
func (*AllocationStrategy) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) GetType() AllocationStrategy_Type {
|
|
||||||
if x != nil {
|
|
||||||
return x.Type
|
|
||||||
}
|
|
||||||
return AllocationStrategy_Always
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) GetConcurrency() *AllocationStrategy_AllocationStrategyConcurrency {
|
|
||||||
if x != nil {
|
|
||||||
return x.Concurrency
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy) GetRefresh() *AllocationStrategy_AllocationStrategyRefresh {
|
|
||||||
if x != nil {
|
|
||||||
return x.Refresh
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SniffingConfig struct {
|
type SniffingConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -196,7 +79,7 @@ type SniffingConfig struct {
|
|||||||
|
|
||||||
func (x *SniffingConfig) Reset() {
|
func (x *SniffingConfig) Reset() {
|
||||||
*x = SniffingConfig{}
|
*x = SniffingConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[2]
|
mi := &file_app_proxyman_config_proto_msgTypes[1]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -208,7 +91,7 @@ func (x *SniffingConfig) String() string {
|
|||||||
func (*SniffingConfig) ProtoMessage() {}
|
func (*SniffingConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *SniffingConfig) ProtoReflect() protoreflect.Message {
|
func (x *SniffingConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[2]
|
mi := &file_app_proxyman_config_proto_msgTypes[1]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -221,7 +104,7 @@ func (x *SniffingConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use SniffingConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use SniffingConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*SniffingConfig) Descriptor() ([]byte, []int) {
|
func (*SniffingConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{2}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SniffingConfig) GetEnabled() bool {
|
func (x *SniffingConfig) GetEnabled() bool {
|
||||||
@@ -268,15 +151,14 @@ type ReceiverConfig struct {
|
|||||||
PortList *net.PortList `protobuf:"bytes,1,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
PortList *net.PortList `protobuf:"bytes,1,opt,name=port_list,json=portList,proto3" json:"port_list,omitempty"`
|
||||||
// Listen specifies the IP address that the Receiver should listen on.
|
// Listen specifies the IP address that the Receiver should listen on.
|
||||||
Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
Listen *net.IPOrDomain `protobuf:"bytes,2,opt,name=listen,proto3" json:"listen,omitempty"`
|
||||||
AllocationStrategy *AllocationStrategy `protobuf:"bytes,3,opt,name=allocation_strategy,json=allocationStrategy,proto3" json:"allocation_strategy,omitempty"`
|
StreamSettings *internet.StreamConfig `protobuf:"bytes,3,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
||||||
StreamSettings *internet.StreamConfig `protobuf:"bytes,4,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
ReceiveOriginalDestination bool `protobuf:"varint,4,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"`
|
||||||
ReceiveOriginalDestination bool `protobuf:"varint,5,opt,name=receive_original_destination,json=receiveOriginalDestination,proto3" json:"receive_original_destination,omitempty"`
|
SniffingSettings *SniffingConfig `protobuf:"bytes,6,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
|
||||||
SniffingSettings *SniffingConfig `protobuf:"bytes,7,opt,name=sniffing_settings,json=sniffingSettings,proto3" json:"sniffing_settings,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReceiverConfig) Reset() {
|
func (x *ReceiverConfig) Reset() {
|
||||||
*x = ReceiverConfig{}
|
*x = ReceiverConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[3]
|
mi := &file_app_proxyman_config_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -288,7 +170,7 @@ func (x *ReceiverConfig) String() string {
|
|||||||
func (*ReceiverConfig) ProtoMessage() {}
|
func (*ReceiverConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *ReceiverConfig) ProtoReflect() protoreflect.Message {
|
func (x *ReceiverConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[3]
|
mi := &file_app_proxyman_config_proto_msgTypes[2]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -301,7 +183,7 @@ func (x *ReceiverConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use ReceiverConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use ReceiverConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*ReceiverConfig) Descriptor() ([]byte, []int) {
|
func (*ReceiverConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{3}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReceiverConfig) GetPortList() *net.PortList {
|
func (x *ReceiverConfig) GetPortList() *net.PortList {
|
||||||
@@ -318,13 +200,6 @@ func (x *ReceiverConfig) GetListen() *net.IPOrDomain {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *ReceiverConfig) GetAllocationStrategy() *AllocationStrategy {
|
|
||||||
if x != nil {
|
|
||||||
return x.AllocationStrategy
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ReceiverConfig) GetStreamSettings() *internet.StreamConfig {
|
func (x *ReceiverConfig) GetStreamSettings() *internet.StreamConfig {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.StreamSettings
|
return x.StreamSettings
|
||||||
@@ -358,7 +233,7 @@ type InboundHandlerConfig struct {
|
|||||||
|
|
||||||
func (x *InboundHandlerConfig) Reset() {
|
func (x *InboundHandlerConfig) Reset() {
|
||||||
*x = InboundHandlerConfig{}
|
*x = InboundHandlerConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[4]
|
mi := &file_app_proxyman_config_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -370,7 +245,7 @@ func (x *InboundHandlerConfig) String() string {
|
|||||||
func (*InboundHandlerConfig) ProtoMessage() {}
|
func (*InboundHandlerConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message {
|
func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[4]
|
mi := &file_app_proxyman_config_proto_msgTypes[3]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -383,7 +258,7 @@ func (x *InboundHandlerConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use InboundHandlerConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use InboundHandlerConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*InboundHandlerConfig) Descriptor() ([]byte, []int) {
|
func (*InboundHandlerConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{4}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *InboundHandlerConfig) GetTag() string {
|
func (x *InboundHandlerConfig) GetTag() string {
|
||||||
@@ -415,7 +290,7 @@ type OutboundConfig struct {
|
|||||||
|
|
||||||
func (x *OutboundConfig) Reset() {
|
func (x *OutboundConfig) Reset() {
|
||||||
*x = OutboundConfig{}
|
*x = OutboundConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[5]
|
mi := &file_app_proxyman_config_proto_msgTypes[4]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -427,7 +302,7 @@ func (x *OutboundConfig) String() string {
|
|||||||
func (*OutboundConfig) ProtoMessage() {}
|
func (*OutboundConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *OutboundConfig) ProtoReflect() protoreflect.Message {
|
func (x *OutboundConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[5]
|
mi := &file_app_proxyman_config_proto_msgTypes[4]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -440,7 +315,7 @@ func (x *OutboundConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use OutboundConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use OutboundConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*OutboundConfig) Descriptor() ([]byte, []int) {
|
func (*OutboundConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{5}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{4}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SenderConfig struct {
|
type SenderConfig struct {
|
||||||
@@ -449,16 +324,17 @@ type SenderConfig struct {
|
|||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// Send traffic through the given IP. Only IP is allowed.
|
// Send traffic through the given IP. Only IP is allowed.
|
||||||
Via *net.IPOrDomain `protobuf:"bytes,1,opt,name=via,proto3" json:"via,omitempty"`
|
Via *net.IPOrDomain `protobuf:"bytes,1,opt,name=via,proto3" json:"via,omitempty"`
|
||||||
StreamSettings *internet.StreamConfig `protobuf:"bytes,2,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
StreamSettings *internet.StreamConfig `protobuf:"bytes,2,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"`
|
||||||
ProxySettings *internet.ProxyConfig `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings,proto3" json:"proxy_settings,omitempty"`
|
ProxySettings *internet.ProxyConfig `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings,proto3" json:"proxy_settings,omitempty"`
|
||||||
MultiplexSettings *MultiplexingConfig `protobuf:"bytes,4,opt,name=multiplex_settings,json=multiplexSettings,proto3" json:"multiplex_settings,omitempty"`
|
MultiplexSettings *MultiplexingConfig `protobuf:"bytes,4,opt,name=multiplex_settings,json=multiplexSettings,proto3" json:"multiplex_settings,omitempty"`
|
||||||
ViaCidr string `protobuf:"bytes,5,opt,name=via_cidr,json=viaCidr,proto3" json:"via_cidr,omitempty"`
|
ViaCidr string `protobuf:"bytes,5,opt,name=via_cidr,json=viaCidr,proto3" json:"via_cidr,omitempty"`
|
||||||
|
TargetStrategy internet.DomainStrategy `protobuf:"varint,6,opt,name=target_strategy,json=targetStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"target_strategy,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SenderConfig) Reset() {
|
func (x *SenderConfig) Reset() {
|
||||||
*x = SenderConfig{}
|
*x = SenderConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[6]
|
mi := &file_app_proxyman_config_proto_msgTypes[5]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -470,7 +346,7 @@ func (x *SenderConfig) String() string {
|
|||||||
func (*SenderConfig) ProtoMessage() {}
|
func (*SenderConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *SenderConfig) ProtoReflect() protoreflect.Message {
|
func (x *SenderConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[6]
|
mi := &file_app_proxyman_config_proto_msgTypes[5]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -483,7 +359,7 @@ func (x *SenderConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use SenderConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use SenderConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*SenderConfig) Descriptor() ([]byte, []int) {
|
func (*SenderConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{6}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{5}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SenderConfig) GetVia() *net.IPOrDomain {
|
func (x *SenderConfig) GetVia() *net.IPOrDomain {
|
||||||
@@ -521,6 +397,13 @@ func (x *SenderConfig) GetViaCidr() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *SenderConfig) GetTargetStrategy() internet.DomainStrategy {
|
||||||
|
if x != nil {
|
||||||
|
return x.TargetStrategy
|
||||||
|
}
|
||||||
|
return internet.DomainStrategy(0)
|
||||||
|
}
|
||||||
|
|
||||||
type MultiplexingConfig struct {
|
type MultiplexingConfig struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -538,7 +421,7 @@ type MultiplexingConfig struct {
|
|||||||
|
|
||||||
func (x *MultiplexingConfig) Reset() {
|
func (x *MultiplexingConfig) Reset() {
|
||||||
*x = MultiplexingConfig{}
|
*x = MultiplexingConfig{}
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[7]
|
mi := &file_app_proxyman_config_proto_msgTypes[6]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
ms.StoreMessageInfo(mi)
|
ms.StoreMessageInfo(mi)
|
||||||
}
|
}
|
||||||
@@ -550,7 +433,7 @@ func (x *MultiplexingConfig) String() string {
|
|||||||
func (*MultiplexingConfig) ProtoMessage() {}
|
func (*MultiplexingConfig) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message {
|
func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[7]
|
mi := &file_app_proxyman_config_proto_msgTypes[6]
|
||||||
if x != nil {
|
if x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
if ms.LoadMessageInfo() == nil {
|
if ms.LoadMessageInfo() == nil {
|
||||||
@@ -563,7 +446,7 @@ func (x *MultiplexingConfig) ProtoReflect() protoreflect.Message {
|
|||||||
|
|
||||||
// Deprecated: Use MultiplexingConfig.ProtoReflect.Descriptor instead.
|
// Deprecated: Use MultiplexingConfig.ProtoReflect.Descriptor instead.
|
||||||
func (*MultiplexingConfig) Descriptor() ([]byte, []int) {
|
func (*MultiplexingConfig) Descriptor() ([]byte, []int) {
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{7}
|
return file_app_proxyman_config_proto_rawDescGZIP(), []int{6}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *MultiplexingConfig) GetEnabled() bool {
|
func (x *MultiplexingConfig) GetEnabled() bool {
|
||||||
@@ -594,96 +477,6 @@ func (x *MultiplexingConfig) GetXudpProxyUDP443() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type AllocationStrategy_AllocationStrategyConcurrency struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyConcurrency) Reset() {
|
|
||||||
*x = AllocationStrategy_AllocationStrategyConcurrency{}
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[8]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyConcurrency) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*AllocationStrategy_AllocationStrategyConcurrency) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyConcurrency) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_config_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 AllocationStrategy_AllocationStrategyConcurrency.ProtoReflect.Descriptor instead.
|
|
||||||
func (*AllocationStrategy_AllocationStrategyConcurrency) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyConcurrency) GetValue() uint32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Value
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type AllocationStrategy_AllocationStrategyRefresh struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyRefresh) Reset() {
|
|
||||||
*x = AllocationStrategy_AllocationStrategyRefresh{}
|
|
||||||
mi := &file_app_proxyman_config_proto_msgTypes[9]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyRefresh) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*AllocationStrategy_AllocationStrategyRefresh) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyRefresh) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_app_proxyman_config_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 AllocationStrategy_AllocationStrategyRefresh.ProtoReflect.Descriptor instead.
|
|
||||||
func (*AllocationStrategy_AllocationStrategyRefresh) Descriptor() ([]byte, []int) {
|
|
||||||
return file_app_proxyman_config_proto_rawDescGZIP(), []int{1, 1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *AllocationStrategy_AllocationStrategyRefresh) GetValue() uint32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Value
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_app_proxyman_config_proto protoreflect.FileDescriptor
|
var File_app_proxyman_config_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_app_proxyman_config_proto_rawDesc = []byte{
|
var file_app_proxyman_config_proto_rawDesc = []byte{
|
||||||
@@ -698,125 +491,98 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
|||||||
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f,
|
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,
|
0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72,
|
||||||
0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f,
|
0x6f, 0x74, 0x6f, 0x22, 0x0f, 0x0a, 0x0d, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x22, 0xae, 0x03, 0x0a, 0x12, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74,
|
0x6e, 0x66, 0x69, 0x67, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e,
|
||||||
0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x3e, 0x0a, 0x04, 0x74,
|
0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||||
0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c,
|
0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||||
0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x65, 0x0a, 0x0b, 0x63,
|
0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72,
|
||||||
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x5f,
|
||||||
0x32, 0x43, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f,
|
||||||
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53,
|
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x12,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c, 0x79,
|
||||||
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
|
||||||
0x72, 0x65, 0x6e, 0x63, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f, 0x6e,
|
||||||
0x63, 0x79, 0x12, 0x59, 0x0a, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x18, 0x03, 0x20,
|
0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x4f,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
|
0x6e, 0x6c, 0x79, 0x22, 0xe5, 0x02, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72,
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c,
|
||||||
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63,
|
0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66,
|
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74,
|
||||||
0x72, 0x65, 0x73, 0x68, 0x52, 0x07, 0x72, 0x65, 0x66, 0x72, 0x65, 0x73, 0x68, 0x1a, 0x35, 0x0a,
|
0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x33,
|
||||||
0x1d, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
|
0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
|
||||||
0x65, 0x67, 0x79, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x14,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
|
||||||
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76,
|
0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69, 0x73,
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x1a, 0x31, 0x0a, 0x19, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
0x74, 0x65, 0x6e, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65,
|
||||||
0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x65, 0x66, 0x72, 0x65, 0x73,
|
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78,
|
||||||
0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d,
|
0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e,
|
||||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x2c, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12,
|
0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e,
|
||||||
0x0a, 0x0a, 0x06, 0x41, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x52,
|
0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x61, 0x6e, 0x64, 0x6f, 0x6d, 0x10, 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x78, 0x74, 0x65, 0x72,
|
0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f,
|
||||||
0x6e, 0x61, 0x6c, 0x10, 0x02, 0x22, 0xcc, 0x01, 0x0a, 0x0e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69,
|
0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
||||||
0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62,
|
0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69,
|
||||||
0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e,
|
||||||
0x65, 0x64, 0x12, 0x31, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f,
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e,
|
||||||
0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09,
|
0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x52, 0x13, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65,
|
0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73,
|
0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e,
|
||||||
0x5f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74,
|
||||||
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64,
|
0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0xc0, 0x01, 0x0a, 0x14,
|
||||||
0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6f, 0x6e, 0x6c,
|
0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f,
|
||||||
0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
|
0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x61, 0x4f, 0x6e, 0x6c, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x5f, 0x6f,
|
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76,
|
||||||
0x6e, 0x6c, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||||
0x4f, 0x6e, 0x6c, 0x79, 0x22, 0xbd, 0x03, 0x0a, 0x0e, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65,
|
0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e,
|
||||||
0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x5f,
|
0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73,
|
||||||
0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61,
|
0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74,
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72,
|
0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73,
|
||||||
0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x12,
|
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e,
|
||||||
0x33, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69,
|
||||||
0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
|
0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52,
|
||||||
0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x6c, 0x69,
|
0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10,
|
||||||
0x73, 0x74, 0x65, 0x6e, 0x12, 0x56, 0x0a, 0x13, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69,
|
0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28,
|
0x22, 0x9d, 0x03, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69,
|
||||||
0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f,
|
0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
|
||||||
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74,
|
||||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61,
|
0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4e, 0x0a, 0x0f,
|
0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18,
|
0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61,
|
0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e,
|
0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74,
|
0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
0x72, 0x65, 0x61, 0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x40, 0x0a, 0x1c,
|
0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||||
0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x5f, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
|
0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x5f, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
|
0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||||
0x28, 0x08, 0x52, 0x1a, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x4f, 0x72, 0x69, 0x67, 0x69,
|
0x65, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d,
|
||||||
0x6e, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e,
|
0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a,
|
||||||
0x0a, 0x11, 0x73, 0x6e, 0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x53, 0x6e,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75,
|
||||||
0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x10, 0x73, 0x6e,
|
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
||||||
0x69, 0x66, 0x66, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x4a, 0x04,
|
0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69,
|
||||||
0x08, 0x06, 0x10, 0x07, 0x22, 0xc0, 0x01, 0x0a, 0x14, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
0x6e, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x76, 0x69, 0x61, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18,
|
||||||
0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a,
|
0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x12, 0x50,
|
||||||
0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12,
|
0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x4d, 0x0a, 0x11, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x74, 0x74,
|
0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74,
|
||||||
0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61,
|
0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
|
||||||
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e,
|
0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x72, 0x65,
|
0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
||||||
0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47,
|
0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e,
|
||||||
0x0a, 0x0e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c,
|
||||||
0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f,
|
0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65,
|
0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79,
|
||||||
0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65,
|
||||||
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75,
|
||||||
0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xcb, 0x02, 0x0a, 0x0c, 0x53, 0x65,
|
0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75,
|
||||||
0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69,
|
0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a,
|
||||||
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33,
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f,
|
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78,
|
||||||
0x6d, 0x61, 0x69, 0x6e, 0x52, 0x03, 0x76, 0x69, 0x61, 0x12, 0x4e, 0x0a, 0x0f, 0x73, 0x74, 0x72,
|
0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||||
0x65, 0x61, 0x6d, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x02, 0x20, 0x01,
|
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e,
|
||||||
0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70,
|
0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78,
|
||||||
0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x53, 0x74, 0x72,
|
0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70,
|
||||||
0x65, 0x61, 0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0e, 0x73, 0x74, 0x72, 0x65, 0x61,
|
0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61,
|
||||||
0x6d, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x4b, 0x0a, 0x0e, 0x70, 0x72, 0x6f,
|
0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06,
|
||||||
0x78, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
|
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f,
|
|
||||||
0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x72, 0x6f, 0x78,
|
|
||||||
0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65,
|
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x12, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70,
|
|
||||||
0x6c, 0x65, 0x78, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01,
|
|
||||||
0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72,
|
|
||||||
0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78,
|
|
||||||
0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69,
|
|
||||||
0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08,
|
|
||||||
0x76, 0x69, 0x61, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
|
||||||
0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74,
|
|
||||||
0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18,
|
|
||||||
0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
|
|
||||||
0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63,
|
|
||||||
0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63,
|
|
||||||
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75,
|
|
||||||
0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20,
|
|
||||||
0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72,
|
|
||||||
0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78,
|
|
||||||
0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78,
|
|
||||||
0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x42, 0x55,
|
|
||||||
0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
|
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75,
|
|
||||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
|
||||||
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
|
||||||
0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f,
|
|
||||||
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -831,46 +597,39 @@ func file_app_proxyman_config_proto_rawDescGZIP() []byte {
|
|||||||
return file_app_proxyman_config_proto_rawDescData
|
return file_app_proxyman_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_app_proxyman_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||||
var file_app_proxyman_config_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
|
||||||
var file_app_proxyman_config_proto_goTypes = []any{
|
var file_app_proxyman_config_proto_goTypes = []any{
|
||||||
(AllocationStrategy_Type)(0), // 0: xray.app.proxyman.AllocationStrategy.Type
|
(*InboundConfig)(nil), // 0: xray.app.proxyman.InboundConfig
|
||||||
(*InboundConfig)(nil), // 1: xray.app.proxyman.InboundConfig
|
(*SniffingConfig)(nil), // 1: xray.app.proxyman.SniffingConfig
|
||||||
(*AllocationStrategy)(nil), // 2: xray.app.proxyman.AllocationStrategy
|
(*ReceiverConfig)(nil), // 2: xray.app.proxyman.ReceiverConfig
|
||||||
(*SniffingConfig)(nil), // 3: xray.app.proxyman.SniffingConfig
|
(*InboundHandlerConfig)(nil), // 3: xray.app.proxyman.InboundHandlerConfig
|
||||||
(*ReceiverConfig)(nil), // 4: xray.app.proxyman.ReceiverConfig
|
(*OutboundConfig)(nil), // 4: xray.app.proxyman.OutboundConfig
|
||||||
(*InboundHandlerConfig)(nil), // 5: xray.app.proxyman.InboundHandlerConfig
|
(*SenderConfig)(nil), // 5: xray.app.proxyman.SenderConfig
|
||||||
(*OutboundConfig)(nil), // 6: xray.app.proxyman.OutboundConfig
|
(*MultiplexingConfig)(nil), // 6: xray.app.proxyman.MultiplexingConfig
|
||||||
(*SenderConfig)(nil), // 7: xray.app.proxyman.SenderConfig
|
(*net.PortList)(nil), // 7: xray.common.net.PortList
|
||||||
(*MultiplexingConfig)(nil), // 8: xray.app.proxyman.MultiplexingConfig
|
(*net.IPOrDomain)(nil), // 8: xray.common.net.IPOrDomain
|
||||||
(*AllocationStrategy_AllocationStrategyConcurrency)(nil), // 9: xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
(*internet.StreamConfig)(nil), // 9: xray.transport.internet.StreamConfig
|
||||||
(*AllocationStrategy_AllocationStrategyRefresh)(nil), // 10: xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
(*serial.TypedMessage)(nil), // 10: xray.common.serial.TypedMessage
|
||||||
(*net.PortList)(nil), // 11: xray.common.net.PortList
|
(*internet.ProxyConfig)(nil), // 11: xray.transport.internet.ProxyConfig
|
||||||
(*net.IPOrDomain)(nil), // 12: xray.common.net.IPOrDomain
|
(internet.DomainStrategy)(0), // 12: xray.transport.internet.DomainStrategy
|
||||||
(*internet.StreamConfig)(nil), // 13: xray.transport.internet.StreamConfig
|
|
||||||
(*serial.TypedMessage)(nil), // 14: xray.common.serial.TypedMessage
|
|
||||||
(*internet.ProxyConfig)(nil), // 15: xray.transport.internet.ProxyConfig
|
|
||||||
}
|
}
|
||||||
var file_app_proxyman_config_proto_depIdxs = []int32{
|
var file_app_proxyman_config_proto_depIdxs = []int32{
|
||||||
0, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
7, // 0: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
||||||
9, // 1: xray.app.proxyman.AllocationStrategy.concurrency:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyConcurrency
|
8, // 1: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
||||||
10, // 2: xray.app.proxyman.AllocationStrategy.refresh:type_name -> xray.app.proxyman.AllocationStrategy.AllocationStrategyRefresh
|
9, // 2: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
11, // 3: xray.app.proxyman.ReceiverConfig.port_list:type_name -> xray.common.net.PortList
|
1, // 3: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
||||||
12, // 4: xray.app.proxyman.ReceiverConfig.listen:type_name -> xray.common.net.IPOrDomain
|
10, // 4: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
2, // 5: xray.app.proxyman.ReceiverConfig.allocation_strategy:type_name -> xray.app.proxyman.AllocationStrategy
|
10, // 5: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
13, // 6: xray.app.proxyman.ReceiverConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
8, // 6: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
||||||
3, // 7: xray.app.proxyman.ReceiverConfig.sniffing_settings:type_name -> xray.app.proxyman.SniffingConfig
|
9, // 7: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
14, // 8: xray.app.proxyman.InboundHandlerConfig.receiver_settings:type_name -> xray.common.serial.TypedMessage
|
11, // 8: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
||||||
14, // 9: xray.app.proxyman.InboundHandlerConfig.proxy_settings:type_name -> xray.common.serial.TypedMessage
|
6, // 9: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
||||||
12, // 10: xray.app.proxyman.SenderConfig.via:type_name -> xray.common.net.IPOrDomain
|
12, // 10: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy
|
||||||
13, // 11: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
11, // [11:11] is the sub-list for method output_type
|
||||||
15, // 12: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
11, // [11:11] is the sub-list for method input_type
|
||||||
8, // 13: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
11, // [11:11] is the sub-list for extension type_name
|
||||||
14, // [14:14] is the sub-list for method output_type
|
11, // [11:11] is the sub-list for extension extendee
|
||||||
14, // [14:14] is the sub-list for method input_type
|
0, // [0:11] is the sub-list for field type_name
|
||||||
14, // [14:14] is the sub-list for extension type_name
|
|
||||||
14, // [14:14] is the sub-list for extension extendee
|
|
||||||
0, // [0:14] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_proxyman_config_proto_init() }
|
func init() { file_app_proxyman_config_proto_init() }
|
||||||
@@ -883,14 +642,13 @@ func file_app_proxyman_config_proto_init() {
|
|||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_app_proxyman_config_proto_rawDesc,
|
RawDescriptor: file_app_proxyman_config_proto_rawDesc,
|
||||||
NumEnums: 1,
|
NumEnums: 0,
|
||||||
NumMessages: 10,
|
NumMessages: 7,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
GoTypes: file_app_proxyman_config_proto_goTypes,
|
GoTypes: file_app_proxyman_config_proto_goTypes,
|
||||||
DependencyIndexes: file_app_proxyman_config_proto_depIdxs,
|
DependencyIndexes: file_app_proxyman_config_proto_depIdxs,
|
||||||
EnumInfos: file_app_proxyman_config_proto_enumTypes,
|
|
||||||
MessageInfos: file_app_proxyman_config_proto_msgTypes,
|
MessageInfos: file_app_proxyman_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_app_proxyman_config_proto = out.File
|
File_app_proxyman_config_proto = out.File
|
||||||
|
|||||||
@@ -13,33 +13,6 @@ import "common/serial/typed_message.proto";
|
|||||||
|
|
||||||
message InboundConfig {}
|
message InboundConfig {}
|
||||||
|
|
||||||
message AllocationStrategy {
|
|
||||||
enum Type {
|
|
||||||
// Always allocate all connection handlers.
|
|
||||||
Always = 0;
|
|
||||||
|
|
||||||
// Randomly allocate specific range of handlers.
|
|
||||||
Random = 1;
|
|
||||||
|
|
||||||
// External. Not supported yet.
|
|
||||||
External = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
Type type = 1;
|
|
||||||
|
|
||||||
message AllocationStrategyConcurrency { uint32 value = 1; }
|
|
||||||
|
|
||||||
// Number of handlers (ports) running in parallel.
|
|
||||||
// Default value is 3 if unset.
|
|
||||||
AllocationStrategyConcurrency concurrency = 2;
|
|
||||||
|
|
||||||
message AllocationStrategyRefresh { uint32 value = 1; }
|
|
||||||
|
|
||||||
// Number of minutes before a handler is regenerated.
|
|
||||||
// Default value is 5 if unset.
|
|
||||||
AllocationStrategyRefresh refresh = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SniffingConfig {
|
message SniffingConfig {
|
||||||
// Whether or not to enable content sniffing on an inbound connection.
|
// Whether or not to enable content sniffing on an inbound connection.
|
||||||
bool enabled = 1;
|
bool enabled = 1;
|
||||||
@@ -62,11 +35,10 @@ message ReceiverConfig {
|
|||||||
xray.common.net.PortList port_list = 1;
|
xray.common.net.PortList port_list = 1;
|
||||||
// Listen specifies the IP address that the Receiver should listen on.
|
// Listen specifies the IP address that the Receiver should listen on.
|
||||||
xray.common.net.IPOrDomain listen = 2;
|
xray.common.net.IPOrDomain listen = 2;
|
||||||
AllocationStrategy allocation_strategy = 3;
|
xray.transport.internet.StreamConfig stream_settings = 3;
|
||||||
xray.transport.internet.StreamConfig stream_settings = 4;
|
bool receive_original_destination = 4;
|
||||||
bool receive_original_destination = 5;
|
reserved 5;
|
||||||
reserved 6;
|
SniffingConfig sniffing_settings = 6;
|
||||||
SniffingConfig sniffing_settings = 7;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message InboundHandlerConfig {
|
message InboundHandlerConfig {
|
||||||
@@ -84,6 +56,7 @@ message SenderConfig {
|
|||||||
xray.transport.internet.ProxyConfig proxy_settings = 3;
|
xray.transport.internet.ProxyConfig proxy_settings = 3;
|
||||||
MultiplexingConfig multiplex_settings = 4;
|
MultiplexingConfig multiplex_settings = 4;
|
||||||
string via_cidr = 5;
|
string via_cidr = 5;
|
||||||
|
xray.transport.internet.DomainStrategy target_strategy = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
message MultiplexingConfig {
|
message MultiplexingConfig {
|
||||||
|
|||||||
@@ -5,15 +5,16 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/dice"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/policy"
|
"github.com/xtls/xray-core/features/policy"
|
||||||
"github.com/xtls/xray-core/features/stats"
|
"github.com/xtls/xray-core/features/stats"
|
||||||
"github.com/xtls/xray-core/proxy"
|
"github.com/xtls/xray-core/proxy"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
"github.com/xtls/xray-core/transport/internet"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
||||||
@@ -42,10 +43,12 @@ func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AlwaysOnInboundHandler struct {
|
type AlwaysOnInboundHandler struct {
|
||||||
proxy proxy.Inbound
|
proxyConfig interface{}
|
||||||
workers []worker
|
receiverConfig *proxyman.ReceiverConfig
|
||||||
mux *mux.Server
|
proxy proxy.Inbound
|
||||||
tag string
|
workers []worker
|
||||||
|
mux *mux.Server
|
||||||
|
tag string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) {
|
func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*AlwaysOnInboundHandler, error) {
|
||||||
@@ -59,9 +62,11 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
}
|
}
|
||||||
|
|
||||||
h := &AlwaysOnInboundHandler{
|
h := &AlwaysOnInboundHandler{
|
||||||
proxy: p,
|
receiverConfig: receiverConfig,
|
||||||
mux: mux.NewServer(ctx),
|
proxyConfig: proxyConfig,
|
||||||
tag: tag,
|
proxy: p,
|
||||||
|
mux: mux.NewServer(ctx),
|
||||||
|
tag: tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag)
|
uplinkCounter, downlinkCounter := getStatCounter(core.MustFromContext(ctx), tag)
|
||||||
@@ -97,7 +102,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
stream: mss,
|
stream: mss,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.SniffingSettings,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -119,7 +124,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
recvOrigDest: receiverConfig.ReceiveOriginalDestination,
|
||||||
tag: tag,
|
tag: tag,
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.SniffingSettings,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
@@ -134,7 +139,7 @@ func NewAlwaysOnInboundHandler(ctx context.Context, tag string, receiverConfig *
|
|||||||
address: address,
|
address: address,
|
||||||
port: net.Port(port),
|
port: net.Port(port),
|
||||||
dispatcher: h.mux,
|
dispatcher: h.mux,
|
||||||
sniffingConfig: receiverConfig.GetEffectiveSniffingSettings(),
|
sniffingConfig: receiverConfig.SniffingSettings,
|
||||||
uplinkCounter: uplinkCounter,
|
uplinkCounter: uplinkCounter,
|
||||||
downlinkCounter: downlinkCounter,
|
downlinkCounter: downlinkCounter,
|
||||||
stream: mss,
|
stream: mss,
|
||||||
@@ -172,14 +177,6 @@ func (h *AlwaysOnInboundHandler) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *AlwaysOnInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
|
|
||||||
if len(h.workers) == 0 {
|
|
||||||
return nil, 0, 0
|
|
||||||
}
|
|
||||||
w := h.workers[dice.Roll(len(h.workers))]
|
|
||||||
return w.Proxy(), w.Port(), 9999
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *AlwaysOnInboundHandler) Tag() string {
|
func (h *AlwaysOnInboundHandler) Tag() string {
|
||||||
return h.tag
|
return h.tag
|
||||||
}
|
}
|
||||||
@@ -187,3 +184,16 @@ func (h *AlwaysOnInboundHandler) Tag() string {
|
|||||||
func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound {
|
func (h *AlwaysOnInboundHandler) GetInbound() proxy.Inbound {
|
||||||
return h.proxy
|
return h.proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReceiverSettings implements inbound.Handler.
|
||||||
|
func (h *AlwaysOnInboundHandler) ReceiverSettings() *serial.TypedMessage {
|
||||||
|
return serial.ToTypedMessage(h.receiverConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxySettings implements inbound.Handler.
|
||||||
|
func (h *AlwaysOnInboundHandler) ProxySettings() *serial.TypedMessage {
|
||||||
|
if v, ok := h.proxyConfig.(proto.Message); ok {
|
||||||
|
return serial.ToTypedMessage(v)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,207 +0,0 @@
|
|||||||
package inbound
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
|
||||||
"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/task"
|
|
||||||
"github.com/xtls/xray-core/core"
|
|
||||||
"github.com/xtls/xray-core/proxy"
|
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DynamicInboundHandler struct {
|
|
||||||
tag string
|
|
||||||
v *core.Instance
|
|
||||||
proxyConfig interface{}
|
|
||||||
receiverConfig *proxyman.ReceiverConfig
|
|
||||||
streamSettings *internet.MemoryStreamConfig
|
|
||||||
portMutex sync.Mutex
|
|
||||||
portsInUse map[net.Port]struct{}
|
|
||||||
workerMutex sync.RWMutex
|
|
||||||
worker []worker
|
|
||||||
lastRefresh time.Time
|
|
||||||
mux *mux.Server
|
|
||||||
task *task.Periodic
|
|
||||||
|
|
||||||
ctx context.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDynamicInboundHandler(ctx context.Context, tag string, receiverConfig *proxyman.ReceiverConfig, proxyConfig interface{}) (*DynamicInboundHandler, error) {
|
|
||||||
v := core.MustFromContext(ctx)
|
|
||||||
h := &DynamicInboundHandler{
|
|
||||||
tag: tag,
|
|
||||||
proxyConfig: proxyConfig,
|
|
||||||
receiverConfig: receiverConfig,
|
|
||||||
portsInUse: make(map[net.Port]struct{}),
|
|
||||||
mux: mux.NewServer(ctx),
|
|
||||||
v: v,
|
|
||||||
ctx: ctx,
|
|
||||||
}
|
|
||||||
|
|
||||||
mss, err := internet.ToMemoryStreamConfig(receiverConfig.StreamSettings)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to parse stream settings").Base(err).AtWarning()
|
|
||||||
}
|
|
||||||
if receiverConfig.ReceiveOriginalDestination {
|
|
||||||
if mss.SocketSettings == nil {
|
|
||||||
mss.SocketSettings = &internet.SocketConfig{}
|
|
||||||
}
|
|
||||||
if mss.SocketSettings.Tproxy == internet.SocketConfig_Off {
|
|
||||||
mss.SocketSettings.Tproxy = internet.SocketConfig_Redirect
|
|
||||||
}
|
|
||||||
mss.SocketSettings.ReceiveOriginalDestAddress = true
|
|
||||||
}
|
|
||||||
|
|
||||||
h.streamSettings = mss
|
|
||||||
|
|
||||||
h.task = &task.Periodic{
|
|
||||||
Interval: time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()),
|
|
||||||
Execute: h.refresh,
|
|
||||||
}
|
|
||||||
|
|
||||||
return h, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) allocatePort() net.Port {
|
|
||||||
allPorts := []int32{}
|
|
||||||
for _, pr := range h.receiverConfig.PortList.Range {
|
|
||||||
for i := pr.From; i <= pr.To; i++ {
|
|
||||||
allPorts = append(allPorts, int32(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
h.portMutex.Lock()
|
|
||||||
defer h.portMutex.Unlock()
|
|
||||||
|
|
||||||
for {
|
|
||||||
r := dice.Roll(len(allPorts))
|
|
||||||
port := net.Port(allPorts[r])
|
|
||||||
_, used := h.portsInUse[port]
|
|
||||||
if !used {
|
|
||||||
h.portsInUse[port] = struct{}{}
|
|
||||||
return port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) closeWorkers(workers []worker) {
|
|
||||||
ports2Del := make([]net.Port, len(workers))
|
|
||||||
for idx, worker := range workers {
|
|
||||||
ports2Del[idx] = worker.Port()
|
|
||||||
if err := worker.Close(); err != nil {
|
|
||||||
errors.LogInfoInner(h.ctx, err, "failed to close worker")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h.portMutex.Lock()
|
|
||||||
for _, port := range ports2Del {
|
|
||||||
delete(h.portsInUse, port)
|
|
||||||
}
|
|
||||||
h.portMutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) refresh() error {
|
|
||||||
h.lastRefresh = time.Now()
|
|
||||||
|
|
||||||
timeout := time.Minute * time.Duration(h.receiverConfig.AllocationStrategy.GetRefreshValue()) * 2
|
|
||||||
concurrency := h.receiverConfig.AllocationStrategy.GetConcurrencyValue()
|
|
||||||
workers := make([]worker, 0, concurrency)
|
|
||||||
|
|
||||||
address := h.receiverConfig.Listen.AsAddress()
|
|
||||||
if address == nil {
|
|
||||||
address = net.AnyIP
|
|
||||||
}
|
|
||||||
|
|
||||||
uplinkCounter, downlinkCounter := getStatCounter(h.v, h.tag)
|
|
||||||
|
|
||||||
for i := uint32(0); i < concurrency; i++ {
|
|
||||||
port := h.allocatePort()
|
|
||||||
rawProxy, err := core.CreateObject(h.v, h.proxyConfig)
|
|
||||||
if err != nil {
|
|
||||||
errors.LogWarningInner(h.ctx, err, "failed to create proxy instance")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
p := rawProxy.(proxy.Inbound)
|
|
||||||
nl := p.Network()
|
|
||||||
if net.HasNetwork(nl, net.Network_TCP) {
|
|
||||||
worker := &tcpWorker{
|
|
||||||
tag: h.tag,
|
|
||||||
address: address,
|
|
||||||
port: port,
|
|
||||||
proxy: p,
|
|
||||||
stream: h.streamSettings,
|
|
||||||
recvOrigDest: h.receiverConfig.ReceiveOriginalDestination,
|
|
||||||
dispatcher: h.mux,
|
|
||||||
sniffingConfig: h.receiverConfig.GetEffectiveSniffingSettings(),
|
|
||||||
uplinkCounter: uplinkCounter,
|
|
||||||
downlinkCounter: downlinkCounter,
|
|
||||||
ctx: h.ctx,
|
|
||||||
}
|
|
||||||
if err := worker.Start(); err != nil {
|
|
||||||
errors.LogWarningInner(h.ctx, err, "failed to create TCP worker")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
workers = append(workers, worker)
|
|
||||||
}
|
|
||||||
|
|
||||||
if net.HasNetwork(nl, net.Network_UDP) {
|
|
||||||
worker := &udpWorker{
|
|
||||||
tag: h.tag,
|
|
||||||
proxy: p,
|
|
||||||
address: address,
|
|
||||||
port: port,
|
|
||||||
dispatcher: h.mux,
|
|
||||||
sniffingConfig: h.receiverConfig.GetEffectiveSniffingSettings(),
|
|
||||||
uplinkCounter: uplinkCounter,
|
|
||||||
downlinkCounter: downlinkCounter,
|
|
||||||
stream: h.streamSettings,
|
|
||||||
ctx: h.ctx,
|
|
||||||
}
|
|
||||||
if err := worker.Start(); err != nil {
|
|
||||||
errors.LogWarningInner(h.ctx, err, "failed to create UDP worker")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
workers = append(workers, worker)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
h.workerMutex.Lock()
|
|
||||||
h.worker = workers
|
|
||||||
h.workerMutex.Unlock()
|
|
||||||
|
|
||||||
time.AfterFunc(timeout, func() {
|
|
||||||
h.closeWorkers(workers)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) Start() error {
|
|
||||||
return h.task.Start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) Close() error {
|
|
||||||
return h.task.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) GetRandomInboundProxy() (interface{}, net.Port, int) {
|
|
||||||
h.workerMutex.RLock()
|
|
||||||
defer h.workerMutex.RUnlock()
|
|
||||||
|
|
||||||
if len(h.worker) == 0 {
|
|
||||||
return nil, 0, 0
|
|
||||||
}
|
|
||||||
w := h.worker[dice.Roll(len(h.worker))]
|
|
||||||
expire := h.receiverConfig.AllocationStrategy.GetRefreshValue() - uint32(time.Since(h.lastRefresh)/time.Minute)
|
|
||||||
return w.Proxy(), w.Port(), int(expire)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *DynamicInboundHandler) Tag() string {
|
|
||||||
return h.tag
|
|
||||||
}
|
|
||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
// Manager manages all inbound handlers.
|
// Manager manages all inbound handlers.
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
access sync.RWMutex
|
access sync.RWMutex
|
||||||
untaggedHandler []inbound.Handler
|
untaggedHandlers []inbound.Handler
|
||||||
taggedHandlers map[string]inbound.Handler
|
taggedHandlers map[string]inbound.Handler
|
||||||
running bool
|
running bool
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ func (m *Manager) AddHandler(ctx context.Context, handler inbound.Handler) error
|
|||||||
}
|
}
|
||||||
m.taggedHandlers[tag] = handler
|
m.taggedHandlers[tag] = handler
|
||||||
} else {
|
} else {
|
||||||
m.untaggedHandler = append(m.untaggedHandler, handler)
|
m.untaggedHandlers = append(m.untaggedHandlers, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.running {
|
if m.running {
|
||||||
@@ -89,6 +89,21 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
|
|||||||
return common.ErrNoClue
|
return common.ErrNoClue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListHandlers implements inbound.Manager.
|
||||||
|
func (m *Manager) ListHandlers(ctx context.Context) []inbound.Handler {
|
||||||
|
m.access.RLock()
|
||||||
|
defer m.access.RUnlock()
|
||||||
|
|
||||||
|
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.
|
// Start implements common.Runnable.
|
||||||
func (m *Manager) Start() error {
|
func (m *Manager) Start() error {
|
||||||
m.access.Lock()
|
m.access.Lock()
|
||||||
@@ -102,7 +117,7 @@ func (m *Manager) Start() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, handler := range m.untaggedHandler {
|
for _, handler := range m.untaggedHandlers {
|
||||||
if err := handler.Start(); err != nil {
|
if err := handler.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -123,7 +138,7 @@ func (m *Manager) Close() error {
|
|||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, handler := range m.untaggedHandler {
|
for _, handler := range m.untaggedHandlers {
|
||||||
if err := handler.Close(); err != nil {
|
if err := handler.Close(); err != nil {
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
@@ -163,15 +178,7 @@ func NewHandler(ctx context.Context, config *core.InboundHandlerConfig) (inbound
|
|||||||
ctx = session.ContextWithAllowedNetwork(ctx, net.Network_UDP)
|
ctx = session.ContextWithAllowedNetwork(ctx, net.Network_UDP)
|
||||||
}
|
}
|
||||||
|
|
||||||
allocStrategy := receiverSettings.AllocationStrategy
|
return NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings)
|
||||||
if allocStrategy == nil || allocStrategy.Type == proxyman.AllocationStrategy_Always {
|
|
||||||
return NewAlwaysOnInboundHandler(ctx, tag, receiverSettings, proxySettings)
|
|
||||||
}
|
|
||||||
|
|
||||||
if allocStrategy.Type == proxyman.AllocationStrategy_Random {
|
|
||||||
return NewDynamicInboundHandler(ctx, tag, receiverSettings, proxySettings)
|
|
||||||
}
|
|
||||||
return nil, errors.New("unknown allocation strategy: ", receiverSettings.AllocationStrategy.Type).AtError()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@@ -76,7 +76,25 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
|||||||
case internet.SocketConfig_TProxy:
|
case internet.SocketConfig_TProxy:
|
||||||
dest = net.DestinationFromAddr(conn.LocalAddr())
|
dest = net.DestinationFromAddr(conn.LocalAddr())
|
||||||
}
|
}
|
||||||
|
|
||||||
if dest.IsValid() {
|
if dest.IsValid() {
|
||||||
|
// Check if try to connect to this inbound itself (can cause loopback)
|
||||||
|
var isLoopBack bool
|
||||||
|
if w.address == net.AnyIP || w.address == net.AnyIPv6 {
|
||||||
|
if dest.Port.Value() == w.port.Value() && IsLocal(dest.Address.IP()) {
|
||||||
|
isLoopBack = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if w.hub.Addr().String() == dest.NetAddr() {
|
||||||
|
isLoopBack = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if isLoopBack {
|
||||||
|
cancel()
|
||||||
|
conn.Close()
|
||||||
|
errors.LogError(ctx, errors.New("loopback connection detected"))
|
||||||
|
return
|
||||||
|
}
|
||||||
outbounds[0].Target = dest
|
outbounds[0].Target = dest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,6 +109,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
|||||||
}
|
}
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
||||||
|
Local: net.DestinationFromAddr(conn.LocalAddr()),
|
||||||
Gateway: net.TCPDestination(w.address, w.port),
|
Gateway: net.TCPDestination(w.address, w.port),
|
||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
@@ -161,6 +180,7 @@ type udpConn struct {
|
|||||||
uplink stats.Counter
|
uplink stats.Counter
|
||||||
downlink stats.Counter
|
downlink stats.Counter
|
||||||
inactive bool
|
inactive bool
|
||||||
|
cancel context.CancelFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConn) setInactive() {
|
func (c *udpConn) setInactive() {
|
||||||
@@ -203,6 +223,9 @@ func (c *udpConn) Write(buf []byte) (int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *udpConn) Close() error {
|
func (c *udpConn) Close() error {
|
||||||
|
if c.cancel != nil {
|
||||||
|
c.cancel()
|
||||||
|
}
|
||||||
common.Must(c.done.Close())
|
common.Must(c.done.Close())
|
||||||
common.Must(common.Close(c.writer))
|
common.Must(common.Close(c.writer))
|
||||||
return nil
|
return nil
|
||||||
@@ -259,6 +282,7 @@ func (w *udpWorker) getConnection(id connID) (*udpConn, bool) {
|
|||||||
defer w.Unlock()
|
defer w.Unlock()
|
||||||
|
|
||||||
if conn, found := w.activeConn[id]; found && !conn.done.Done() {
|
if conn, found := w.activeConn[id]; found && !conn.done.Done() {
|
||||||
|
conn.updateActivity()
|
||||||
return conn, true
|
return conn, true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +330,8 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
|||||||
common.Must(w.checker.Start())
|
common.Must(w.checker.Start())
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
ctx := w.ctx
|
ctx, cancel := context.WithCancel(w.ctx)
|
||||||
|
conn.cancel = cancel
|
||||||
sid := session.NewID()
|
sid := session.NewID()
|
||||||
ctx = c.ContextWithID(ctx, sid)
|
ctx = c.ContextWithID(ctx, sid)
|
||||||
|
|
||||||
@@ -315,8 +340,18 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
|||||||
outbounds[0].Target = originalDest
|
outbounds[0].Target = originalDest
|
||||||
}
|
}
|
||||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||||
|
local := net.DestinationFromAddr(w.hub.Addr())
|
||||||
|
if local.Address == net.AnyIP || local.Address == net.AnyIPv6 {
|
||||||
|
if source.Address.Family().IsIPv4() {
|
||||||
|
local.Address = net.AnyIP
|
||||||
|
} else if source.Address.Family().IsIPv6() {
|
||||||
|
local.Address = net.AnyIPv6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
Source: source,
|
Source: source,
|
||||||
|
Local: local, // Due to some limitations, in UDP connections, localIP is always equal to listen interface IP
|
||||||
Gateway: net.UDPDestination(w.address, w.port),
|
Gateway: net.UDPDestination(w.address, w.port),
|
||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
})
|
})
|
||||||
@@ -466,6 +501,7 @@ func (w *dsWorker) callback(conn stat.Connection) {
|
|||||||
}
|
}
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
Source: net.DestinationFromAddr(conn.RemoteAddr()),
|
||||||
|
Local: net.DestinationFromAddr(conn.LocalAddr()),
|
||||||
Gateway: net.UnixDestination(w.address),
|
Gateway: net.UnixDestination(w.address),
|
||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
Conn: conn,
|
Conn: conn,
|
||||||
@@ -526,3 +562,18 @@ func (w *dsWorker) Close() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsLocal(ip net.IP) bool {
|
||||||
|
addrs, err := net.InterfaceAddrs()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok {
|
||||||
|
if ipnet.IP.Equal(ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,9 +6,10 @@ import (
|
|||||||
goerrors "errors"
|
goerrors "errors"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
gonet "net"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/xtls/xray-core/common/dice"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/app/proxyman"
|
"github.com/xtls/xray-core/app/proxyman"
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
@@ -16,6 +17,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/net/cnc"
|
"github.com/xtls/xray-core/common/net/cnc"
|
||||||
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
@@ -27,6 +29,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/transport/internet/stat"
|
"github.com/xtls/xray-core/transport/internet/stat"
|
||||||
"github.com/xtls/xray-core/transport/internet/tls"
|
"github.com/xtls/xray-core/transport/internet/tls"
|
||||||
"github.com/xtls/xray-core/transport/pipe"
|
"github.com/xtls/xray-core/transport/pipe"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
||||||
@@ -59,6 +62,7 @@ type Handler struct {
|
|||||||
tag string
|
tag string
|
||||||
senderSettings *proxyman.SenderConfig
|
senderSettings *proxyman.SenderConfig
|
||||||
streamSettings *internet.MemoryStreamConfig
|
streamSettings *internet.MemoryStreamConfig
|
||||||
|
proxyConfig proto.Message
|
||||||
proxy proxy.Outbound
|
proxy proxy.Outbound
|
||||||
outboundManager outbound.Manager
|
outboundManager outbound.Manager
|
||||||
mux *mux.ClientManager
|
mux *mux.ClientManager
|
||||||
@@ -101,6 +105,9 @@ func NewHandler(ctx context.Context, config *core.OutboundHandlerConfig) (outbou
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
h.proxyConfig = proxyConfig
|
||||||
|
|
||||||
|
ctx = session.ContextWithFullHandler(ctx, h)
|
||||||
|
|
||||||
rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
|
rawProxyHandler, err := common.CreateObject(ctx, proxyConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -173,6 +180,29 @@ func (h *Handler) Tag() string {
|
|||||||
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
||||||
outbounds := session.OutboundsFromContext(ctx)
|
outbounds := session.OutboundsFromContext(ctx)
|
||||||
ob := outbounds[len(outbounds)-1]
|
ob := outbounds[len(outbounds)-1]
|
||||||
|
content := session.ContentFromContext(ctx)
|
||||||
|
if h.senderSettings != nil && h.senderSettings.TargetStrategy.HasStrategy() && ob.Target.Address.Family().IsDomain() && (content == nil || !content.SkipDNSResolve) {
|
||||||
|
strategy := h.senderSettings.TargetStrategy
|
||||||
|
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil {
|
||||||
|
strategy = strategy.GetDynamicStrategy(ob.OriginalTarget.Address.Family())
|
||||||
|
}
|
||||||
|
ips, err := internet.LookupForIP(ob.Target.Address.Domain(), strategy, nil)
|
||||||
|
if err != nil {
|
||||||
|
errors.LogInfoInner(ctx, err, "failed to resolve ip for target ", ob.Target.Address.Domain())
|
||||||
|
if h.senderSettings.TargetStrategy.ForceIP() {
|
||||||
|
err := errors.New("failed to resolve ip for target ", ob.Target.Address.Domain()).Base(err)
|
||||||
|
session.SubmitOutboundErrorToOriginator(ctx, err)
|
||||||
|
common.Interrupt(link.Writer)
|
||||||
|
common.Interrupt(link.Reader)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
unchangedDomain := ob.Target.Address.Domain()
|
||||||
|
ob.Target.Address = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||||
|
errors.LogInfo(ctx, "target: ", unchangedDomain, " resolved to: ", ob.Target.Address.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil && ob.OriginalTarget.Address != ob.Target.Address {
|
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil && ob.OriginalTarget.Address != ob.Target.Address {
|
||||||
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
||||||
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
||||||
@@ -184,6 +214,7 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
|||||||
session.SubmitOutboundErrorToOriginator(ctx, err)
|
session.SubmitOutboundErrorToOriginator(ctx, err)
|
||||||
errors.LogInfo(ctx, err.Error())
|
errors.LogInfo(ctx, err.Error())
|
||||||
common.Interrupt(link.Writer)
|
common.Interrupt(link.Writer)
|
||||||
|
common.Interrupt(link.Reader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 {
|
if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 {
|
||||||
@@ -209,8 +240,10 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
|||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
err := h.proxy.Process(ctx, link, h)
|
err := h.proxy.Process(ctx, link, h)
|
||||||
|
var errC error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if goerrors.Is(err, io.EOF) || goerrors.Is(err, io.ErrClosedPipe) || goerrors.Is(err, context.Canceled) {
|
errC = errors.Cause(err)
|
||||||
|
if goerrors.Is(errC, io.EOF) || goerrors.Is(errC, io.ErrClosedPipe) || goerrors.Is(errC, context.Canceled) {
|
||||||
err = nil
|
err = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,19 +254,15 @@ out:
|
|||||||
errors.LogInfo(ctx, err.Error())
|
errors.LogInfo(ctx, err.Error())
|
||||||
common.Interrupt(link.Writer)
|
common.Interrupt(link.Writer)
|
||||||
} else {
|
} else {
|
||||||
common.Close(link.Writer)
|
if errC != nil && goerrors.Is(errC, io.ErrClosedPipe) {
|
||||||
|
common.Interrupt(link.Writer)
|
||||||
|
} else {
|
||||||
|
common.Close(link.Writer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
common.Interrupt(link.Reader)
|
common.Interrupt(link.Reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Address implements internet.Dialer.
|
|
||||||
func (h *Handler) Address() net.Address {
|
|
||||||
if h.senderSettings == nil || h.senderSettings.Via == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return h.senderSettings.Via.AsAddress()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Handler) DestIpAddress() net.IP {
|
func (h *Handler) DestIpAddress() net.IP {
|
||||||
return internet.DestIpAddress()
|
return internet.DestIpAddress()
|
||||||
}
|
}
|
||||||
@@ -268,45 +297,16 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
|||||||
return h.getStatCouterConnection(conn), nil
|
return h.getStatCouterConnection(conn), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
errors.LogWarning(ctx, "failed to get outbound handler with tag: ", tag)
|
errors.LogError(ctx, "failed to get outbound handler with tag: ", tag)
|
||||||
|
return nil, errors.New("failed to get outbound handler with tag: " + tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
if h.senderSettings.Via != nil {
|
if h.senderSettings.Via != nil {
|
||||||
|
|
||||||
outbounds := session.OutboundsFromContext(ctx)
|
outbounds := session.OutboundsFromContext(ctx)
|
||||||
ob := outbounds[len(outbounds)-1]
|
ob := outbounds[len(outbounds)-1]
|
||||||
addr := h.senderSettings.Via.AsAddress()
|
h.SetOutboundGateway(ctx, ob)
|
||||||
var domain string
|
|
||||||
if addr.Family().IsDomain() {
|
|
||||||
domain = addr.Domain()
|
|
||||||
}
|
|
||||||
switch {
|
|
||||||
case h.senderSettings.ViaCidr != "":
|
|
||||||
ob.Gateway = ParseRandomIP(addr, h.senderSettings.ViaCidr)
|
|
||||||
|
|
||||||
case domain == "origin":
|
|
||||||
|
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
|
||||||
origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String())
|
|
||||||
if err == nil {
|
|
||||||
ob.Gateway = net.ParseAddress(origin)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
case domain == "srcip":
|
|
||||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
|
||||||
srcip, _, err := net.SplitHostPort(inbound.Conn.RemoteAddr().String())
|
|
||||||
if err == nil {
|
|
||||||
ob.Gateway = net.ParseAddress(srcip)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//case addr.Family().IsDomain():
|
|
||||||
default:
|
|
||||||
ob.Gateway = addr
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
|
if conn, err := h.getUoTConnection(ctx, dest); err != os.ErrInvalid {
|
||||||
@@ -316,11 +316,47 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
|||||||
conn, err := internet.Dial(ctx, dest, h.streamSettings)
|
conn, err := internet.Dial(ctx, dest, h.streamSettings)
|
||||||
conn = h.getStatCouterConnection(conn)
|
conn = h.getStatCouterConnection(conn)
|
||||||
outbounds := session.OutboundsFromContext(ctx)
|
outbounds := session.OutboundsFromContext(ctx)
|
||||||
ob := outbounds[len(outbounds)-1]
|
if outbounds != nil {
|
||||||
ob.Conn = conn
|
ob := outbounds[len(outbounds)-1]
|
||||||
|
ob.Conn = conn
|
||||||
|
} else {
|
||||||
|
// for Vision's pre-connect
|
||||||
|
}
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handler) SetOutboundGateway(ctx context.Context, ob *session.Outbound) {
|
||||||
|
if ob.Gateway == nil && h.senderSettings != nil && h.senderSettings.Via != nil && !h.senderSettings.ProxySettings.HasTag() && (h.streamSettings.SocketSettings == nil || len(h.streamSettings.SocketSettings.DialerProxy) == 0) {
|
||||||
|
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 inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
|
if inbound.Local.IsValid() && inbound.Local.Address.Family().IsIP() {
|
||||||
|
ob.Gateway = inbound.Local.Address
|
||||||
|
errors.LogDebug(ctx, "use inbound local ip as sendthrough: ", inbound.Local.Address.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case domain == "srcip":
|
||||||
|
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
|
if inbound.Source.IsValid() && inbound.Source.Address.Family().IsIP() {
|
||||||
|
ob.Gateway = inbound.Source.Address
|
||||||
|
errors.LogDebug(ctx, "use inbound source ip as sendthrough: ", inbound.Source.Address.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//case addr.Family().IsDomain():
|
||||||
|
default:
|
||||||
|
ob.Gateway = addr
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) getStatCouterConnection(conn stat.Connection) stat.Connection {
|
func (h *Handler) getStatCouterConnection(conn stat.Connection) stat.Connection {
|
||||||
if h.uplinkCounter != nil || h.downlinkCounter != nil {
|
if h.uplinkCounter != nil || h.downlinkCounter != nil {
|
||||||
return &stat.CounterConnection{
|
return &stat.CounterConnection{
|
||||||
@@ -349,9 +385,19 @@ func (h *Handler) Close() error {
|
|||||||
return nil
|
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 {
|
func ParseRandomIP(addr net.Address, prefix string) net.Address {
|
||||||
|
|
||||||
_, ipnet, _ := gonet.ParseCIDR(addr.IP().String() + "/" + prefix)
|
_, ipnet, _ := net.ParseCIDR(addr.IP().String() + "/" + prefix)
|
||||||
|
|
||||||
ones, bits := ipnet.Mask.Size()
|
ones, bits := ipnet.Mask.Size()
|
||||||
subnetSize := new(big.Int).Lsh(big.NewInt(1), uint(bits-ones))
|
subnetSize := new(big.Int).Lsh(big.NewInt(1), uint(bits-ones))
|
||||||
@@ -365,5 +411,5 @@ func ParseRandomIP(addr net.Address, prefix string) net.Address {
|
|||||||
padded := make([]byte, len(ipnet.IP))
|
padded := make([]byte, len(ipnet.IP))
|
||||||
copy(padded[len(padded)-len(rndBytes):], rndBytes)
|
copy(padded[len(padded)-len(rndBytes):], rndBytes)
|
||||||
|
|
||||||
return net.ParseAddress(gonet.IP(padded).String())
|
return net.ParseAddress(net.IP(padded).String())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,6 +145,21 @@ func (m *Manager) RemoveHandler(ctx context.Context, tag string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListHandlers implements outbound.Manager.
|
||||||
|
func (m *Manager) ListHandlers(ctx context.Context) []outbound.Handler {
|
||||||
|
m.access.RLock()
|
||||||
|
defer m.access.RUnlock()
|
||||||
|
|
||||||
|
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.
|
// Select implements outbound.HandlerSelector.
|
||||||
func (m *Manager) Select(selectors []string) []string {
|
func (m *Manager) Select(selectors []string) []string {
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/signal"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
@@ -52,6 +53,11 @@ func (b *Bridge) cleanup() {
|
|||||||
if w.IsActive() {
|
if w.IsActive() {
|
||||||
activeWorkers = append(activeWorkers, w)
|
activeWorkers = append(activeWorkers, w)
|
||||||
}
|
}
|
||||||
|
if w.Closed() {
|
||||||
|
if w.Timer != nil {
|
||||||
|
w.Timer.SetTimeout(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(activeWorkers) != len(b.workers) {
|
if len(activeWorkers) != len(b.workers) {
|
||||||
@@ -93,10 +99,11 @@ func (b *Bridge) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BridgeWorker struct {
|
type BridgeWorker struct {
|
||||||
tag string
|
Tag string
|
||||||
worker *mux.ServerWorker
|
Worker *mux.ServerWorker
|
||||||
dispatcher routing.Dispatcher
|
Dispatcher routing.Dispatcher
|
||||||
state Control_State
|
State Control_State
|
||||||
|
Timer *signal.ActivityTimer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBridgeWorker(domain string, tag string, d routing.Dispatcher) (*BridgeWorker, error) {
|
func NewBridgeWorker(domain string, tag string, d routing.Dispatcher) (*BridgeWorker, error) {
|
||||||
@@ -114,16 +121,20 @@ func NewBridgeWorker(domain string, tag string, d routing.Dispatcher) (*BridgeWo
|
|||||||
}
|
}
|
||||||
|
|
||||||
w := &BridgeWorker{
|
w := &BridgeWorker{
|
||||||
dispatcher: d,
|
Dispatcher: d,
|
||||||
tag: tag,
|
Tag: tag,
|
||||||
}
|
}
|
||||||
|
|
||||||
worker, err := mux.NewServerWorker(context.Background(), w, link)
|
worker, err := mux.NewServerWorker(context.Background(), w, link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
w.worker = worker
|
w.Worker = worker
|
||||||
|
|
||||||
|
terminate := func() {
|
||||||
|
worker.Close()
|
||||||
|
}
|
||||||
|
w.Timer = signal.CancelAfterInactivity(ctx, terminate, 60*time.Second)
|
||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,48 +151,65 @@ func (w *BridgeWorker) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *BridgeWorker) IsActive() bool {
|
func (w *BridgeWorker) IsActive() bool {
|
||||||
return w.state == Control_ACTIVE && !w.worker.Closed()
|
return w.State == Control_ACTIVE && !w.Worker.Closed()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *BridgeWorker) Closed() bool {
|
||||||
|
return w.Worker.Closed()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *BridgeWorker) Connections() uint32 {
|
func (w *BridgeWorker) Connections() uint32 {
|
||||||
return w.worker.ActiveConnections()
|
return w.Worker.ActiveConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
|
func (w *BridgeWorker) handleInternalConn(link *transport.Link) {
|
||||||
go func() {
|
reader := link.Reader
|
||||||
reader := link.Reader
|
for {
|
||||||
for {
|
mb, err := reader.ReadMultiBuffer()
|
||||||
mb, err := reader.ReadMultiBuffer()
|
if err != nil {
|
||||||
if err != nil {
|
if w.Timer != nil {
|
||||||
break
|
if w.Closed() {
|
||||||
|
w.Timer.SetTimeout(0)
|
||||||
|
} else {
|
||||||
|
w.Timer.SetTimeout(24 * time.Hour)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, b := range mb {
|
return
|
||||||
var ctl Control
|
}
|
||||||
if err := proto.Unmarshal(b.Bytes(), &ctl); err != nil {
|
if w.Timer != nil {
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to parse proto message")
|
w.Timer.Update()
|
||||||
break
|
}
|
||||||
}
|
for _, b := range mb {
|
||||||
if ctl.State != w.state {
|
var ctl Control
|
||||||
w.state = ctl.State
|
if err := proto.Unmarshal(b.Bytes(), &ctl); err != nil {
|
||||||
|
errors.LogInfoInner(context.Background(), err, "failed to parse proto message")
|
||||||
|
if w.Timer != nil {
|
||||||
|
w.Timer.SetTimeout(0)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ctl.State != w.State {
|
||||||
|
w.State = ctl.State
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error) {
|
func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*transport.Link, error) {
|
||||||
if !isInternalDomain(dest) {
|
if !isInternalDomain(dest) {
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
if session.InboundFromContext(ctx) == nil {
|
||||||
Tag: w.tag,
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
})
|
Tag: w.Tag,
|
||||||
return w.dispatcher.Dispatch(ctx, dest)
|
})
|
||||||
|
}
|
||||||
|
return w.Dispatcher.Dispatch(ctx, dest)
|
||||||
}
|
}
|
||||||
|
|
||||||
opt := []pipe.Option{pipe.WithSizeLimit(16 * 1024)}
|
opt := []pipe.Option{pipe.WithSizeLimit(16 * 1024)}
|
||||||
uplinkReader, uplinkWriter := pipe.New(opt...)
|
uplinkReader, uplinkWriter := pipe.New(opt...)
|
||||||
downlinkReader, downlinkWriter := pipe.New(opt...)
|
downlinkReader, downlinkWriter := pipe.New(opt...)
|
||||||
|
|
||||||
w.handleInternalConn(&transport.Link{
|
go w.handleInternalConn(&transport.Link{
|
||||||
Reader: downlinkReader,
|
Reader: downlinkReader,
|
||||||
Writer: uplinkWriter,
|
Writer: uplinkWriter,
|
||||||
})
|
})
|
||||||
@@ -194,12 +222,17 @@ func (w *BridgeWorker) Dispatch(ctx context.Context, dest net.Destination) (*tra
|
|||||||
|
|
||||||
func (w *BridgeWorker) DispatchLink(ctx context.Context, dest net.Destination, link *transport.Link) error {
|
func (w *BridgeWorker) DispatchLink(ctx context.Context, dest net.Destination, link *transport.Link) error {
|
||||||
if !isInternalDomain(dest) {
|
if !isInternalDomain(dest) {
|
||||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
if session.InboundFromContext(ctx) == nil {
|
||||||
Tag: w.tag,
|
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||||
})
|
Tag: w.Tag,
|
||||||
return w.dispatcher.DispatchLink(ctx, dest, link)
|
})
|
||||||
|
}
|
||||||
|
return w.Dispatcher.DispatchLink(ctx, dest, link)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d, ok := w.Dispatcher.(routing.WrapLinkDispatcher); ok {
|
||||||
|
link = d.WrapLink(ctx, link)
|
||||||
|
}
|
||||||
w.handleInternalConn(link)
|
w.handleInternalConn(link)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
func (c *Control) FillInRandom() {
|
func (c *Control) FillInRandom() {
|
||||||
randomLength := dice.Roll(64)
|
randomLength := dice.Roll(64)
|
||||||
|
randomLength++
|
||||||
c.Random = make([]byte, randomLength)
|
c.Random = make([]byte, randomLength)
|
||||||
io.ReadFull(rand.Reader, c.Random)
|
io.ReadFull(rand.Reader, c.Random)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/mux"
|
"github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
|
"github.com/xtls/xray-core/common/serial"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/signal"
|
||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
"github.com/xtls/xray-core/features/outbound"
|
"github.com/xtls/xray-core/features/outbound"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
@@ -81,9 +83,21 @@ func (p *Portal) HandleConnection(ctx context.Context, link *transport.Link) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.picker.AddWorker(worker)
|
p.picker.AddWorker(worker)
|
||||||
|
|
||||||
|
if _, ok := link.Reader.(*pipe.Reader); !ok {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-muxClient.WaitClosed():
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil && ob.OriginalTarget.Address != ob.Target.Address {
|
||||||
|
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
||||||
|
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
||||||
|
}
|
||||||
|
|
||||||
return p.client.Dispatch(ctx, link)
|
return p.client.Dispatch(ctx, link)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +114,7 @@ func (o *Outbound) Dispatch(ctx context.Context, link *transport.Link) {
|
|||||||
if err := o.portal.HandleConnection(ctx, link); err != nil {
|
if err := o.portal.HandleConnection(ctx, link); err != nil {
|
||||||
errors.LogInfoInner(ctx, err, "failed to process reverse connection")
|
errors.LogInfoInner(ctx, err, "failed to process reverse connection")
|
||||||
common.Interrupt(link.Writer)
|
common.Interrupt(link.Writer)
|
||||||
|
common.Interrupt(link.Reader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +126,16 @@ func (o *Outbound) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SenderSettings implements outbound.Handler.
|
||||||
|
func (o *Outbound) SenderSettings() *serial.TypedMessage {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxySettings implements outbound.Handler.
|
||||||
|
func (o *Outbound) ProxySettings() *serial.TypedMessage {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type StaticMuxPicker struct {
|
type StaticMuxPicker struct {
|
||||||
access sync.Mutex
|
access sync.Mutex
|
||||||
workers []*PortalWorker
|
workers []*PortalWorker
|
||||||
@@ -135,6 +160,8 @@ func (p *StaticMuxPicker) cleanup() error {
|
|||||||
for _, w := range p.workers {
|
for _, w := range p.workers {
|
||||||
if !w.Closed() {
|
if !w.Closed() {
|
||||||
activeWorkers = append(activeWorkers, w)
|
activeWorkers = append(activeWorkers, w)
|
||||||
|
} else {
|
||||||
|
w.timer.SetTimeout(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +186,7 @@ func (p *StaticMuxPicker) PickAvailable() (*mux.ClientWorker, error) {
|
|||||||
if w.draining {
|
if w.draining {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if w.client.Closed() {
|
if w.IsFull() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if w.client.ActiveConnections() < minConn {
|
if w.client.ActiveConnections() < minConn {
|
||||||
@@ -200,6 +227,8 @@ type PortalWorker struct {
|
|||||||
writer buf.Writer
|
writer buf.Writer
|
||||||
reader buf.Reader
|
reader buf.Reader
|
||||||
draining bool
|
draining bool
|
||||||
|
counter uint32
|
||||||
|
timer *signal.ActivityTimer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
|
func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
|
||||||
@@ -219,10 +248,14 @@ func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
|
|||||||
if !f {
|
if !f {
|
||||||
return nil, errors.New("unable to dispatch control connection")
|
return nil, errors.New("unable to dispatch control connection")
|
||||||
}
|
}
|
||||||
|
terminate := func() {
|
||||||
|
client.Close()
|
||||||
|
}
|
||||||
w := &PortalWorker{
|
w := &PortalWorker{
|
||||||
client: client,
|
client: client,
|
||||||
reader: downlinkReader,
|
reader: downlinkReader,
|
||||||
writer: uplinkWriter,
|
writer: uplinkWriter,
|
||||||
|
timer: signal.CancelAfterInactivity(ctx, terminate, 24*time.Hour), // // prevent leak
|
||||||
}
|
}
|
||||||
w.control = &task.Periodic{
|
w.control = &task.Periodic{
|
||||||
Execute: w.heartbeat,
|
Execute: w.heartbeat,
|
||||||
@@ -233,7 +266,7 @@ func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *PortalWorker) heartbeat() error {
|
func (w *PortalWorker) heartbeat() error {
|
||||||
if w.client.Closed() {
|
if w.Closed() {
|
||||||
return errors.New("client worker stopped")
|
return errors.New("client worker stopped")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,10 +288,15 @@ func (w *PortalWorker) heartbeat() error {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := proto.Marshal(msg)
|
w.counter = (w.counter + 1) % 5
|
||||||
common.Must(err)
|
if w.draining || w.counter == 1 {
|
||||||
mb := buf.MergeBytes(nil, b)
|
b, err := proto.Marshal(msg)
|
||||||
return w.writer.WriteMultiBuffer(mb)
|
common.Must(err)
|
||||||
|
mb := buf.MergeBytes(nil, b)
|
||||||
|
w.timer.Update()
|
||||||
|
return w.writer.WriteMultiBuffer(mb)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *PortalWorker) IsFull() bool {
|
func (w *PortalWorker) IsFull() bool {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
internalDomain = "reverse.internal.v2fly.org" // make reverse proxy compatible with v2fly
|
internalDomain = "reverse"
|
||||||
)
|
)
|
||||||
|
|
||||||
func isDomain(dest net.Destination, domain string) bool {
|
func isDomain(dest net.Destination, domain string) bool {
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ 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"`
|
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"`
|
OutboundGroupTags []string `protobuf:"bytes,11,rep,name=OutboundGroupTags,proto3" json:"OutboundGroupTags,omitempty"`
|
||||||
OutboundTag string `protobuf:"bytes,12,opt,name=OutboundTag,proto3" json:"OutboundTag,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"`
|
||||||
|
VlessRoute uint32 `protobuf:"varint,15,opt,name=VlessRoute,proto3" json:"VlessRoute,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingContext) Reset() {
|
func (x *RoutingContext) Reset() {
|
||||||
@@ -158,6 +161,27 @@ func (x *RoutingContext) GetOutboundTag() string {
|
|||||||
return ""
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RoutingContext) GetVlessRoute() uint32 {
|
||||||
|
if x != nil {
|
||||||
|
return x.VlessRoute
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
||||||
// opened by xray-core.
|
// opened by xray-core.
|
||||||
// * FieldSelectors selects a subset of fields in routing statistics to return.
|
// * FieldSelectors selects a subset of fields in routing statistics to return.
|
||||||
@@ -827,7 +851,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,
|
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,
|
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,
|
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, 0x9c, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf6, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
||||||
0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x49,
|
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,
|
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,
|
0x0a, 0x49, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x32, 0x0a, 0x07, 0x4e,
|
||||||
@@ -857,123 +881,129 @@ 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,
|
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,
|
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,
|
0x6e, 0x64, 0x54, 0x61, 0x67, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x4f, 0x75, 0x74,
|
||||||
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72,
|
0x62, 0x6f, 0x75, 0x6e, 0x64, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61,
|
||||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
|
0x6c, 0x49, 0x50, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4c, 0x6f, 0x63, 0x61,
|
||||||
0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a,
|
0x6c, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72,
|
||||||
0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61,
|
0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f,
|
||||||
0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x46, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63,
|
0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
||||||
0x72, 0x69, 0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73,
|
0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
0x74, 0x65, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||||
0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52,
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22,
|
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0xb1, 0x01, 0x0a, 0x10, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||||
0x75, 0x65, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43,
|
0x01, 0x22, 0x46, 0x0a, 0x1c, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x6f,
|
||||||
0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78,
|
0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63,
|
0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74,
|
||||||
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
0x6f, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64,
|
||||||
0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f,
|
0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x22, 0xb1, 0x01, 0x0a, 0x10, 0x54, 0x65,
|
||||||
0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65,
|
0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x4f,
|
||||||
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46,
|
0x0a, 0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
|
||||||
0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
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,
|
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,
|
0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52,
|
||||||
0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63,
|
0x0e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12,
|
||||||
0x69, 0x70, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28,
|
0x26, 0x0a, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72,
|
||||||
0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x53, 0x65,
|
||||||
0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e,
|
0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x24, 0x0a, 0x0d, 0x50, 0x75, 0x62, 0x6c, 0x69,
|
||||||
0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d,
|
||||||
0x0f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x27, 0x0a,
|
||||||
0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49,
|
0x13, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||||
0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61,
|
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x03, 0x28,
|
||||||
0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x5b, 0x0a, 0x17,
|
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x26, 0x0a, 0x0c, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
|
||||||
0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52,
|
0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0xa9,
|
||||||
0x63, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
0x01, 0x0a, 0x0b, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x12, 0x41,
|
||||||
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
0x0a, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x61, 0x6e, 0x64, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x4d, 0x73, 0x67, 0x52,
|
0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||||
0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x22, 0x59, 0x0a, 0x1d, 0x4f, 0x76, 0x65,
|
0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||||
0x72, 0x72, 0x69, 0x64, 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72,
|
0x69, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64,
|
||||||
0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x62, 0x61,
|
0x65, 0x12, 0x57, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x74,
|
||||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x61, 0x72, 0x67, 0x65, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x78, 0x72,
|
||||||
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,
|
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,
|
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x6c, 0x65, 0x54,
|
||||||
0x74, 0x65, 0x78, 0x74, 0x22, 0x00, 0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74,
|
0x61, 0x72, 0x67, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x70, 0x72, 0x69, 0x6e, 0x63,
|
||||||
0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x29, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x69, 0x70, 0x6c, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x22, 0x2a, 0x0a, 0x16, 0x47, 0x65,
|
||||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e,
|
0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71,
|
||||||
0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22, 0x5b, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c,
|
||||||
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,
|
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,
|
0x65, 0x12, 0x40, 0x0a, 0x08, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x18, 0x01, 0x20,
|
||||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x36,
|
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, 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,
|
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69,
|
||||||
0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52,
|
0x62, 0x65, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65,
|
||||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 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, 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,
|
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,
|
0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x22, 0x00,
|
||||||
0x00, 0x12, 0x67, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65, 0x12,
|
0x30, 0x01, 0x12, 0x61, 0x0a, 0x09, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12,
|
||||||
0x2a, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
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, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
|
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f,
|
||||||
0x52, 0x75, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x78, 0x72,
|
0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f,
|
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d,
|
||||||
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x75, 0x6c, 0x65,
|
0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74,
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x67, 0x0a, 0x1b, 0x63, 0x6f,
|
0x65, 0x78, 0x74, 0x22, 0x00, 0x12, 0x76, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61,
|
||||||
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74,
|
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49, 0x6e,
|
||||||
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x78, 0x72, 0x61, 0x79,
|
||||||
0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0xaa, 0x02, 0x17, 0x58, 0x72, 0x61, 0x79,
|
0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||||
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
0x61, 0x6e, 0x64, 0x2e, 0x47, 0x65, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x49,
|
||||||
0x61, 0x6e, 0x64, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
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,
|
||||||
|
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, 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 (
|
var (
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ message RoutingContext {
|
|||||||
map<string, string> Attributes = 10;
|
map<string, string> Attributes = 10;
|
||||||
repeated string OutboundGroupTags = 11;
|
repeated string OutboundGroupTags = 11;
|
||||||
string OutboundTag = 12;
|
string OutboundTag = 12;
|
||||||
|
repeated bytes LocalIPs = 13;
|
||||||
|
uint32 LocalPort = 14;
|
||||||
|
uint32 VlessRoute = 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
||||||
|
|||||||
@@ -28,6 +28,18 @@ func (c routingContext) GetTargetPort() net.Port {
|
|||||||
return net.Port(c.RoutingContext.GetTargetPort())
|
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) GetVlessRoute() net.Port {
|
||||||
|
return net.Port(c.RoutingContext.GetVlessRoute())
|
||||||
|
}
|
||||||
|
|
||||||
func (c routingContext) GetRuleTag() string {
|
func (c routingContext) GetRuleTag() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -54,8 +66,10 @@ var fieldMap = map[string]func(*RoutingContext, routing.Route){
|
|||||||
"network": func(s *RoutingContext, r routing.Route) { s.Network = r.GetNetwork() },
|
"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_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_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_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_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() },
|
"domain": func(s *RoutingContext, r routing.Route) { s.TargetDomain = r.GetTargetDomain() },
|
||||||
"protocol": func(s *RoutingContext, r routing.Route) { s.Protocol = r.GetProtocol() },
|
"protocol": func(s *RoutingContext, r routing.Route) { s.Protocol = r.GetProtocol() },
|
||||||
"user": func(s *RoutingContext, r routing.Route) { s.User = r.GetUser() },
|
"user": func(s *RoutingContext, r routing.Route) { s.User = r.GetUser() },
|
||||||
|
|||||||
@@ -47,20 +47,6 @@ var matcherTypeMap = map[Domain_Type]strmatcher.Type{
|
|||||||
Domain_Full: strmatcher.Full,
|
Domain_Full: strmatcher.Full,
|
||||||
}
|
}
|
||||||
|
|
||||||
func domainToMatcher(domain *Domain) (strmatcher.Matcher, error) {
|
|
||||||
matcherType, f := matcherTypeMap[domain.Type]
|
|
||||||
if !f {
|
|
||||||
return nil, errors.New("unsupported domain type", domain.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
matcher, err := matcherType.New(domain.Value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to create domain matcher").Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return matcher, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type DomainMatcher struct {
|
type DomainMatcher struct {
|
||||||
matchers strmatcher.IndexMatcher
|
matchers strmatcher.IndexMatcher
|
||||||
}
|
}
|
||||||
@@ -83,21 +69,6 @@ func NewMphMatcherGroup(domains []*Domain) (*DomainMatcher, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDomainMatcher(domains []*Domain) (*DomainMatcher, error) {
|
|
||||||
g := new(strmatcher.MatcherGroup)
|
|
||||||
for _, d := range domains {
|
|
||||||
m, err := domainToMatcher(d)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
g.Add(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &DomainMatcher{
|
|
||||||
matchers: g,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *DomainMatcher) ApplyDomain(domain string) bool {
|
func (m *DomainMatcher) ApplyDomain(domain string) bool {
|
||||||
return len(m.matchers.Match(strings.ToLower(domain))) > 0
|
return len(m.matchers.Match(strings.ToLower(domain))) > 0
|
||||||
}
|
}
|
||||||
@@ -111,66 +82,72 @@ func (m *DomainMatcher) Apply(ctx routing.Context) bool {
|
|||||||
return m.ApplyDomain(domain)
|
return m.ApplyDomain(domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
type MultiGeoIPMatcher struct {
|
type MatcherAsType byte
|
||||||
matchers []*GeoIPMatcher
|
|
||||||
onSource bool
|
const (
|
||||||
|
MatcherAsType_Local MatcherAsType = iota
|
||||||
|
MatcherAsType_Source
|
||||||
|
MatcherAsType_Target
|
||||||
|
MatcherAsType_VlessRoute // for port
|
||||||
|
)
|
||||||
|
|
||||||
|
type IPMatcher struct {
|
||||||
|
matcher GeoIPMatcher
|
||||||
|
asType MatcherAsType
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMultiGeoIPMatcher(geoips []*GeoIP, onSource bool) (*MultiGeoIPMatcher, error) {
|
func NewIPMatcher(geoips []*GeoIP, asType MatcherAsType) (*IPMatcher, error) {
|
||||||
var matchers []*GeoIPMatcher
|
matcher, err := BuildOptimizedGeoIPMatcher(geoips...)
|
||||||
for _, geoip := range geoips {
|
if err != nil {
|
||||||
matcher, err := GlobalGeoIPContainer.Add(geoip)
|
return nil, err
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
matchers = append(matchers, matcher)
|
|
||||||
}
|
}
|
||||||
|
return &IPMatcher{matcher: matcher, asType: asType}, nil
|
||||||
matcher := &MultiGeoIPMatcher{
|
|
||||||
matchers: matchers,
|
|
||||||
onSource: onSource,
|
|
||||||
}
|
|
||||||
|
|
||||||
return matcher, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply implements Condition.
|
// Apply implements Condition.
|
||||||
func (m *MultiGeoIPMatcher) Apply(ctx routing.Context) bool {
|
func (m *IPMatcher) Apply(ctx routing.Context) bool {
|
||||||
var ips []net.IP
|
var ips []net.IP
|
||||||
if m.onSource {
|
|
||||||
|
switch m.asType {
|
||||||
|
case MatcherAsType_Local:
|
||||||
|
ips = ctx.GetLocalIPs()
|
||||||
|
case MatcherAsType_Source:
|
||||||
ips = ctx.GetSourceIPs()
|
ips = ctx.GetSourceIPs()
|
||||||
} else {
|
case MatcherAsType_Target:
|
||||||
ips = ctx.GetTargetIPs()
|
ips = ctx.GetTargetIPs()
|
||||||
|
default:
|
||||||
|
panic("unk asType")
|
||||||
}
|
}
|
||||||
for _, ip := range ips {
|
|
||||||
for _, matcher := range m.matchers {
|
return m.matcher.AnyMatch(ips)
|
||||||
if matcher.Match(ip) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type PortMatcher struct {
|
type PortMatcher struct {
|
||||||
port net.MemoryPortList
|
port net.MemoryPortList
|
||||||
onSource bool
|
asType MatcherAsType
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPortMatcher create a new port matcher that can match source or destination port
|
// NewPortMatcher create a new port matcher that can match source or local or destination port
|
||||||
func NewPortMatcher(list *net.PortList, onSource bool) *PortMatcher {
|
func NewPortMatcher(list *net.PortList, asType MatcherAsType) *PortMatcher {
|
||||||
return &PortMatcher{
|
return &PortMatcher{
|
||||||
port: net.PortListFromProto(list),
|
port: net.PortListFromProto(list),
|
||||||
onSource: onSource,
|
asType: asType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply implements Condition.
|
// Apply implements Condition.
|
||||||
func (v *PortMatcher) Apply(ctx routing.Context) bool {
|
func (v *PortMatcher) Apply(ctx routing.Context) bool {
|
||||||
if v.onSource {
|
switch v.asType {
|
||||||
|
case MatcherAsType_Local:
|
||||||
|
return v.port.Contains(ctx.GetLocalPort())
|
||||||
|
case MatcherAsType_Source:
|
||||||
return v.port.Contains(ctx.GetSourcePort())
|
return v.port.Contains(ctx.GetSourcePort())
|
||||||
} else {
|
case MatcherAsType_Target:
|
||||||
return v.port.Contains(ctx.GetTargetPort())
|
return v.port.Contains(ctx.GetTargetPort())
|
||||||
|
case MatcherAsType_VlessRoute:
|
||||||
|
return v.port.Contains(ctx.GetVlessRoute())
|
||||||
|
default:
|
||||||
|
panic("unk asType")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -35,33 +35,6 @@ func getAssetPath(file string) (string, error) {
|
|||||||
return path, nil
|
return path, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGeoIPMatcherContainer(t *testing.T) {
|
|
||||||
container := &router.GeoIPMatcherContainer{}
|
|
||||||
|
|
||||||
m1, err := container.Add(&router.GeoIP{
|
|
||||||
CountryCode: "CN",
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
m2, err := container.Add(&router.GeoIP{
|
|
||||||
CountryCode: "US",
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
m3, err := container.Add(&router.GeoIP{
|
|
||||||
CountryCode: "CN",
|
|
||||||
})
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
if m1 != m3 {
|
|
||||||
t.Error("expect same matcher for same geoip, but not")
|
|
||||||
}
|
|
||||||
|
|
||||||
if m1 == m2 {
|
|
||||||
t.Error("expect different matcher for different geoip, but actually same")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGeoIPMatcher(t *testing.T) {
|
func TestGeoIPMatcher(t *testing.T) {
|
||||||
cidrList := []*router.CIDR{
|
cidrList := []*router.CIDR{
|
||||||
{Ip: []byte{0, 0, 0, 0}, Prefix: 8},
|
{Ip: []byte{0, 0, 0, 0}, Prefix: 8},
|
||||||
@@ -80,8 +53,10 @@ func TestGeoIPMatcher(t *testing.T) {
|
|||||||
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher := &router.GeoIPMatcher{}
|
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
||||||
common.Must(matcher.Init(cidrList))
|
Cidr: cidrList,
|
||||||
|
})
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Input string
|
Input string
|
||||||
@@ -140,8 +115,10 @@ func TestGeoIPMatcherRegression(t *testing.T) {
|
|||||||
{Ip: []byte{98, 108, 20, 0}, Prefix: 23},
|
{Ip: []byte{98, 108, 20, 0}, Prefix: 23},
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher := &router.GeoIPMatcher{}
|
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
||||||
common.Must(matcher.Init(cidrList))
|
Cidr: cidrList,
|
||||||
|
})
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Input string
|
Input string
|
||||||
@@ -171,9 +148,11 @@ func TestGeoIPReverseMatcher(t *testing.T) {
|
|||||||
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
{Ip: []byte{8, 8, 8, 8}, Prefix: 32},
|
||||||
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
{Ip: []byte{91, 108, 4, 0}, Prefix: 16},
|
||||||
}
|
}
|
||||||
matcher := &router.GeoIPMatcher{}
|
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
||||||
matcher.SetReverseMatch(true) // Reverse match
|
Cidr: cidrList,
|
||||||
common.Must(matcher.Init(cidrList))
|
})
|
||||||
|
common.Must(err)
|
||||||
|
matcher.SetReverse(true) // Reverse match
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
Input string
|
Input string
|
||||||
@@ -206,8 +185,10 @@ func TestGeoIPMatcher4CN(t *testing.T) {
|
|||||||
ips, err := loadGeoIP("CN")
|
ips, err := loadGeoIP("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher := &router.GeoIPMatcher{}
|
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
||||||
common.Must(matcher.Init(ips))
|
Cidr: ips,
|
||||||
|
})
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
if matcher.Match([]byte{8, 8, 8, 8}) {
|
if matcher.Match([]byte{8, 8, 8, 8}) {
|
||||||
t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does")
|
t.Error("expect CN geoip doesn't contain 8.8.8.8, but actually does")
|
||||||
@@ -218,8 +199,10 @@ func TestGeoIPMatcher6US(t *testing.T) {
|
|||||||
ips, err := loadGeoIP("US")
|
ips, err := loadGeoIP("US")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher := &router.GeoIPMatcher{}
|
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
||||||
common.Must(matcher.Init(ips))
|
Cidr: ips,
|
||||||
|
})
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
|
if !matcher.Match(net.ParseAddress("2001:4860:4860::8888").IP()) {
|
||||||
t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
|
t.Error("expect US geoip contain 2001:4860:4860::8888, but actually not")
|
||||||
@@ -254,8 +237,10 @@ func BenchmarkGeoIPMatcher4CN(b *testing.B) {
|
|||||||
ips, err := loadGeoIP("CN")
|
ips, err := loadGeoIP("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher := &router.GeoIPMatcher{}
|
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
||||||
common.Must(matcher.Init(ips))
|
Cidr: ips,
|
||||||
|
})
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
@@ -268,8 +253,10 @@ func BenchmarkGeoIPMatcher6US(b *testing.B) {
|
|||||||
ips, err := loadGeoIP("US")
|
ips, err := loadGeoIP("US")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher := &router.GeoIPMatcher{}
|
matcher, err := router.BuildOptimizedGeoIPMatcher(&router.GeoIP{
|
||||||
common.Must(matcher.Init(ips))
|
Cidr: ips,
|
||||||
|
})
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
|
||||||
|
|||||||
@@ -328,9 +328,6 @@ func TestChinaSites(t *testing.T) {
|
|||||||
domains, err := loadGeoSite("CN")
|
domains, err := loadGeoSite("CN")
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
matcher, err := NewDomainMatcher(domains)
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
acMatcher, err := NewMphMatcherGroup(domains)
|
acMatcher, err := NewMphMatcherGroup(domains)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
@@ -362,12 +359,9 @@ func TestChinaSites(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
r1 := matcher.ApplyDomain(testCase.Domain)
|
r := acMatcher.ApplyDomain(testCase.Domain)
|
||||||
r2 := acMatcher.ApplyDomain(testCase.Domain)
|
if r != testCase.Output {
|
||||||
if r1 != testCase.Output {
|
t.Error("ACDomainMatcher expected output ", testCase.Output, " for domain ", testCase.Domain, " but got ", r)
|
||||||
t.Error("DomainMatcher expected output ", testCase.Output, " for domain ", testCase.Domain, " but got ", r1)
|
|
||||||
} else if r2 != testCase.Output {
|
|
||||||
t.Error("ACDomainMatcher expected output ", testCase.Output, " for domain ", testCase.Domain, " but got ", r2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -414,48 +408,6 @@ func BenchmarkMphDomainMatcher(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkDomainMatcher(b *testing.B) {
|
|
||||||
domains, err := loadGeoSite("CN")
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
matcher, err := NewDomainMatcher(domains)
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
type TestCase struct {
|
|
||||||
Domain string
|
|
||||||
Output bool
|
|
||||||
}
|
|
||||||
testCases := []TestCase{
|
|
||||||
{
|
|
||||||
Domain: "163.com",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Domain: "163.com",
|
|
||||||
Output: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Domain: "164.com",
|
|
||||||
Output: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Domain: "164.com",
|
|
||||||
Output: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < 1024; i++ {
|
|
||||||
testCases = append(testCases, TestCase{Domain: strconv.Itoa(i) + ".not-exists.com", Output: false})
|
|
||||||
}
|
|
||||||
|
|
||||||
b.ResetTimer()
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
_ = matcher.ApplyDomain(testCase.Domain)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
||||||
var geoips []*GeoIP
|
var geoips []*GeoIP
|
||||||
|
|
||||||
@@ -495,7 +447,7 @@ func BenchmarkMultiGeoIPMatcher(b *testing.B) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher, err := NewMultiGeoIPMatcher(geoips, false)
|
matcher, err := NewIPMatcher(geoips, MatcherAsType_Target)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
ctx := withOutbound(&session.Outbound{Target: net.TCPDestination(net.ParseAddress("8.8.8.8"), 80)})
|
||||||
|
|||||||
@@ -32,66 +32,38 @@ func (r *Rule) Apply(ctx routing.Context) bool {
|
|||||||
func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
||||||
conds := NewConditionChan()
|
conds := NewConditionChan()
|
||||||
|
|
||||||
if len(rr.Domain) > 0 {
|
|
||||||
switch rr.DomainMatcher {
|
|
||||||
case "linear":
|
|
||||||
matcher, err := NewDomainMatcher(rr.Domain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to build domain condition").Base(err)
|
|
||||||
}
|
|
||||||
conds.Add(matcher)
|
|
||||||
case "mph", "hybrid":
|
|
||||||
fallthrough
|
|
||||||
default:
|
|
||||||
matcher, err := NewMphMatcherGroup(rr.Domain)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("failed to build domain condition with MphDomainMatcher").Base(err)
|
|
||||||
}
|
|
||||||
errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)")
|
|
||||||
conds.Add(matcher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rr.UserEmail) > 0 {
|
|
||||||
conds.Add(NewUserMatcher(rr.UserEmail))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rr.InboundTag) > 0 {
|
if len(rr.InboundTag) > 0 {
|
||||||
conds.Add(NewInboundTagMatcher(rr.InboundTag))
|
conds.Add(NewInboundTagMatcher(rr.InboundTag))
|
||||||
}
|
}
|
||||||
|
|
||||||
if rr.PortList != nil {
|
|
||||||
conds.Add(NewPortMatcher(rr.PortList, false))
|
|
||||||
}
|
|
||||||
|
|
||||||
if rr.SourcePortList != nil {
|
|
||||||
conds.Add(NewPortMatcher(rr.SourcePortList, true))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rr.Networks) > 0 {
|
if len(rr.Networks) > 0 {
|
||||||
conds.Add(NewNetworkMatcher(rr.Networks))
|
conds.Add(NewNetworkMatcher(rr.Networks))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.Geoip) > 0 {
|
|
||||||
cond, err := NewMultiGeoIPMatcher(rr.Geoip, false)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
conds.Add(cond)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rr.SourceGeoip) > 0 {
|
|
||||||
cond, err := NewMultiGeoIPMatcher(rr.SourceGeoip, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
conds.Add(cond)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rr.Protocol) > 0 {
|
if len(rr.Protocol) > 0 {
|
||||||
conds.Add(NewProtocolMatcher(rr.Protocol))
|
conds.Add(NewProtocolMatcher(rr.Protocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rr.PortList != nil {
|
||||||
|
conds.Add(NewPortMatcher(rr.PortList, MatcherAsType_Target))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.SourcePortList != nil {
|
||||||
|
conds.Add(NewPortMatcher(rr.SourcePortList, MatcherAsType_Source))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.LocalPortList != nil {
|
||||||
|
conds.Add(NewPortMatcher(rr.LocalPortList, MatcherAsType_Local))
|
||||||
|
}
|
||||||
|
|
||||||
|
if rr.VlessRouteList != nil {
|
||||||
|
conds.Add(NewPortMatcher(rr.VlessRouteList, MatcherAsType_VlessRoute))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rr.UserEmail) > 0 {
|
||||||
|
conds.Add(NewUserMatcher(rr.UserEmail))
|
||||||
|
}
|
||||||
|
|
||||||
if len(rr.Attributes) > 0 {
|
if len(rr.Attributes) > 0 {
|
||||||
configuredKeys := make(map[string]*regexp.Regexp)
|
configuredKeys := make(map[string]*regexp.Regexp)
|
||||||
for key, value := range rr.Attributes {
|
for key, value := range rr.Attributes {
|
||||||
@@ -100,6 +72,40 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
conds.Add(&AttributeMatcher{configuredKeys})
|
conds.Add(&AttributeMatcher{configuredKeys})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(rr.Geoip) > 0 {
|
||||||
|
cond, err := NewIPMatcher(rr.Geoip, MatcherAsType_Target)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conds.Add(cond)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rr.SourceGeoip) > 0 {
|
||||||
|
cond, err := NewIPMatcher(rr.SourceGeoip, MatcherAsType_Source)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conds.Add(cond)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(rr.LocalGeoip) > 0 {
|
||||||
|
cond, err := NewIPMatcher(rr.LocalGeoip, MatcherAsType_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.Domain) > 0 {
|
||||||
|
matcher, err := NewMphMatcherGroup(rr.Domain)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to build domain condition with MphDomainMatcher").Base(err)
|
||||||
|
}
|
||||||
|
errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)")
|
||||||
|
conds.Add(matcher)
|
||||||
|
}
|
||||||
|
|
||||||
if conds.Len() == 0 {
|
if conds.Len() == 0 {
|
||||||
return nil, errors.New("this rule has no effective fields").AtWarning()
|
return nil, errors.New("this rule has no effective fields").AtWarning()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,8 +84,6 @@ type Config_DomainStrategy int32
|
|||||||
const (
|
const (
|
||||||
// Use domain as is.
|
// Use domain as is.
|
||||||
Config_AsIs Config_DomainStrategy = 0
|
Config_AsIs Config_DomainStrategy = 0
|
||||||
// Always resolve IP for domains.
|
|
||||||
Config_UseIp Config_DomainStrategy = 1
|
|
||||||
// Resolve to IP if the domain doesn't match any rules.
|
// Resolve to IP if the domain doesn't match any rules.
|
||||||
Config_IpIfNonMatch Config_DomainStrategy = 2
|
Config_IpIfNonMatch Config_DomainStrategy = 2
|
||||||
// Resolve to IP if any rule requires IP matching.
|
// Resolve to IP if any rule requires IP matching.
|
||||||
@@ -96,13 +94,11 @@ const (
|
|||||||
var (
|
var (
|
||||||
Config_DomainStrategy_name = map[int32]string{
|
Config_DomainStrategy_name = map[int32]string{
|
||||||
0: "AsIs",
|
0: "AsIs",
|
||||||
1: "UseIp",
|
|
||||||
2: "IpIfNonMatch",
|
2: "IpIfNonMatch",
|
||||||
3: "IpOnDemand",
|
3: "IpOnDemand",
|
||||||
}
|
}
|
||||||
Config_DomainStrategy_value = map[string]int32{
|
Config_DomainStrategy_value = map[string]int32{
|
||||||
"AsIs": 0,
|
"AsIs": 0,
|
||||||
"UseIp": 1,
|
|
||||||
"IpIfNonMatch": 2,
|
"IpIfNonMatch": 2,
|
||||||
"IpOnDemand": 3,
|
"IpOnDemand": 3,
|
||||||
}
|
}
|
||||||
@@ -470,7 +466,7 @@ type RoutingRule struct {
|
|||||||
// *RoutingRule_Tag
|
// *RoutingRule_Tag
|
||||||
// *RoutingRule_BalancingTag
|
// *RoutingRule_BalancingTag
|
||||||
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
TargetTag isRoutingRule_TargetTag `protobuf_oneof:"target_tag"`
|
||||||
RuleTag string `protobuf:"bytes,18,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
|
RuleTag string `protobuf:"bytes,19,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
|
||||||
// List of domains for target domain matching.
|
// List of domains for target domain matching.
|
||||||
Domain []*Domain `protobuf:"bytes,2,rep,name=domain,proto3" json:"domain,omitempty"`
|
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
|
// List of GeoIPs for target IP address matching. If this entry exists, the
|
||||||
@@ -491,7 +487,9 @@ type RoutingRule struct {
|
|||||||
InboundTag []string `protobuf:"bytes,8,rep,name=inbound_tag,json=inboundTag,proto3" json:"inbound_tag,omitempty"`
|
InboundTag []string `protobuf:"bytes,8,rep,name=inbound_tag,json=inboundTag,proto3" json:"inbound_tag,omitempty"`
|
||||||
Protocol []string `protobuf:"bytes,9,rep,name=protocol,proto3" json:"protocol,omitempty"`
|
Protocol []string `protobuf:"bytes,9,rep,name=protocol,proto3" json:"protocol,omitempty"`
|
||||||
Attributes 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"`
|
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,17,rep,name=local_geoip,json=localGeoip,proto3" json:"local_geoip,omitempty"`
|
||||||
|
LocalPortList *net.PortList `protobuf:"bytes,18,opt,name=local_port_list,json=localPortList,proto3" json:"local_port_list,omitempty"`
|
||||||
|
VlessRouteList *net.PortList `protobuf:"bytes,20,opt,name=vless_route_list,json=vlessRouteList,proto3" json:"vless_route_list,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) Reset() {
|
func (x *RoutingRule) Reset() {
|
||||||
@@ -622,11 +620,25 @@ func (x *RoutingRule) GetAttributes() map[string]string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) GetDomainMatcher() string {
|
func (x *RoutingRule) GetLocalGeoip() []*GeoIP {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.DomainMatcher
|
return x.LocalGeoip
|
||||||
}
|
}
|
||||||
return ""
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RoutingRule) GetLocalPortList() *net.PortList {
|
||||||
|
if x != nil {
|
||||||
|
return x.LocalPortList
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *RoutingRule) GetVlessRouteList() *net.PortList {
|
||||||
|
if x != nil {
|
||||||
|
return x.VlessRouteList
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type isRoutingRule_TargetTag interface {
|
type isRoutingRule_TargetTag interface {
|
||||||
@@ -1069,13 +1081,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,
|
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,
|
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,
|
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, 0xce, 0x05, 0x0a, 0x0b, 0x52, 0x6f,
|
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xe8, 0x06, 0x0a, 0x0b, 0x52, 0x6f,
|
||||||
0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x03, 0x74, 0x61, 0x67,
|
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,
|
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,
|
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,
|
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,
|
0x67, 0x54, 0x61, 0x67, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x61, 0x67,
|
||||||
0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x12,
|
0x18, 0x13, 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,
|
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,
|
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,
|
0x72, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
@@ -1107,69 +1119,78 @@ var file_app_router_config_proto_rawDesc = []byte{
|
|||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52,
|
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, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69,
|
0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x2e, 0x41, 0x74, 0x74, 0x72, 0x69,
|
||||||
0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72,
|
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,
|
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f,
|
||||||
0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x1a, 0x3d, 0x0a,
|
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65,
|
||||||
0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
|
0x6f, 0x49, 0x50, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12,
|
||||||
0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
|
0x41, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69,
|
||||||
0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x73, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a,
|
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c,
|
||||||
0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42,
|
0x69, 0x73, 0x74, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69,
|
||||||
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03,
|
0x73, 0x74, 0x12, 0x43, 0x0a, 0x10, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x72, 0x6f, 0x75, 0x74,
|
||||||
0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b,
|
0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78,
|
||||||
0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63,
|
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50,
|
||||||
0x74, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f,
|
0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f,
|
||||||
0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73,
|
0x75, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
|
0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74,
|
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
|
||||||
0x65, 0x67, 0x79, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01,
|
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
|
||||||
0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
|
||||||
0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73,
|
0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
|
||||||
0x73, 0x61, 0x67, 0x65, 0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65,
|
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
|
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62,
|
||||||
0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61,
|
0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20,
|
||||||
0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72,
|
0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c,
|
||||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72,
|
0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x65, 0x67, 0x65, 0x78, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67,
|
0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x65, 0x78, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01,
|
0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x73, 0x65,
|
||||||
0x28, 0x09, 0x52, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c,
|
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78,
|
||||||
0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22,
|
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
|
||||||
0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73,
|
0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10,
|
||||||
0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63,
|
0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
||||||
0x6f, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61,
|
0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67,
|
||||||
0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72,
|
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
||||||
0x61, 0x74, 0x65, 0x67, 0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73,
|
0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57,
|
||||||
0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18,
|
0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x18,
|
||||||
0x03, 0x20, 0x03, 0x28, 0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73,
|
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x12, 0x14, 0x0a,
|
||||||
0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01,
|
0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61,
|
||||||
0x28, 0x05, 0x52, 0x08, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06,
|
0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
|
||||||
0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61,
|
0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74,
|
||||||
0x78, 0x52, 0x54, 0x54, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63,
|
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43,
|
||||||
0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e,
|
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02,
|
||||||
0x63, 0x65, 0x22, 0x9b, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a,
|
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||||
0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79,
|
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09,
|
||||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e,
|
0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52,
|
||||||
0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e,
|
0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78,
|
||||||
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30,
|
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78,
|
||||||
0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78,
|
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52,
|
0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c,
|
||||||
0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||||
0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75,
|
0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x90, 0x02, 0x0a,
|
||||||
0x6c, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
|
||||||
0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63,
|
0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
||||||
0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49,
|
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
0x73, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10,
|
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
||||||
0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02,
|
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03,
|
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67,
|
||||||
0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61,
|
||||||
0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75,
|
0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03,
|
||||||
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||||
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa,
|
0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75,
|
||||||
0x02, 0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c,
|
||||||
0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x65, 0x22, 0x3c, 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, 0x10, 0x0a,
|
||||||
|
0x0c, 0x49, 0x70, 0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x12,
|
||||||
|
0x0e, 0x0a, 0x0a, 0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03, 0x42,
|
||||||
|
0x4f, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||||
|
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||||
|
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63,
|
||||||
|
0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02,
|
||||||
|
0x0f, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72,
|
||||||
|
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -1220,16 +1241,19 @@ var file_app_router_config_proto_depIdxs = []int32{
|
|||||||
4, // 10: xray.app.router.RoutingRule.source_geoip:type_name -> xray.app.router.GeoIP
|
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
|
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
|
14, // 12: xray.app.router.RoutingRule.attributes:type_name -> xray.app.router.RoutingRule.AttributesEntry
|
||||||
17, // 13: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
|
4, // 13: xray.app.router.RoutingRule.local_geoip:type_name -> xray.app.router.GeoIP
|
||||||
10, // 14: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
|
15, // 14: xray.app.router.RoutingRule.local_port_list:type_name -> xray.common.net.PortList
|
||||||
1, // 15: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
15, // 15: xray.app.router.RoutingRule.vless_route_list:type_name -> xray.common.net.PortList
|
||||||
8, // 16: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
17, // 16: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
9, // 17: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
10, // 17: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
|
||||||
18, // [18:18] is the sub-list for method output_type
|
1, // 18: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
||||||
18, // [18:18] is the sub-list for method input_type
|
8, // 19: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
||||||
18, // [18:18] is the sub-list for extension type_name
|
9, // 20: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
||||||
18, // [18:18] is the sub-list for extension extendee
|
21, // [21:21] is the sub-list for method output_type
|
||||||
0, // [0:18] is the sub-list for field type_name
|
21, // [21:21] is the sub-list for method input_type
|
||||||
|
21, // [21:21] is the sub-list for extension type_name
|
||||||
|
21, // [21:21] is the sub-list for extension extendee
|
||||||
|
0, // [0:21] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_router_config_proto_init() }
|
func init() { file_app_router_config_proto_init() }
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ message RoutingRule {
|
|||||||
// Tag of routing balancer.
|
// Tag of routing balancer.
|
||||||
string balancing_tag = 12;
|
string balancing_tag = 12;
|
||||||
}
|
}
|
||||||
string rule_tag = 18;
|
string rule_tag = 19;
|
||||||
|
|
||||||
// List of domains for target domain matching.
|
// List of domains for target domain matching.
|
||||||
repeated Domain domain = 2;
|
repeated Domain domain = 2;
|
||||||
@@ -109,7 +109,10 @@ message RoutingRule {
|
|||||||
|
|
||||||
map<string, string> attributes = 15;
|
map<string, string> attributes = 15;
|
||||||
|
|
||||||
string domain_matcher = 17;
|
repeated GeoIP local_geoip = 17;
|
||||||
|
xray.common.net.PortList local_port_list = 18;
|
||||||
|
|
||||||
|
xray.common.net.PortList vless_route_list = 20;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BalancingRule {
|
message BalancingRule {
|
||||||
@@ -144,8 +147,8 @@ message Config {
|
|||||||
// Use domain as is.
|
// Use domain as is.
|
||||||
AsIs = 0;
|
AsIs = 0;
|
||||||
|
|
||||||
// Always resolve IP for domains.
|
// [Deprecated] Always resolve IP for domains.
|
||||||
UseIp = 1;
|
// UseIp = 1;
|
||||||
|
|
||||||
// Resolve to IP if the domain doesn't match any rules.
|
// Resolve to IP if the domain doesn't match any rules.
|
||||||
IpIfNonMatch = 2;
|
IpIfNonMatch = 2;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import (
|
|||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
feature_stats "github.com/xtls/xray-core/features/stats"
|
feature_stats "github.com/xtls/xray-core/features/stats"
|
||||||
grpc "google.golang.org/grpc"
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
)
|
)
|
||||||
|
|
||||||
// statsServer is an implementation of StatsService.
|
// statsServer is an implementation of StatsService.
|
||||||
@@ -30,7 +32,7 @@ func NewStatsServer(manager feature_stats.Manager) StatsServiceServer {
|
|||||||
func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
|
func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
|
||||||
c := s.stats.GetCounter(request.Name)
|
c := s.stats.GetCounter(request.Name)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, errors.New(request.Name, " not found.")
|
return nil, status.Error(codes.NotFound, request.Name+" not found.")
|
||||||
}
|
}
|
||||||
var value int64
|
var value int64
|
||||||
if request.Reset_ {
|
if request.Reset_ {
|
||||||
@@ -49,7 +51,7 @@ func (s *statsServer) GetStats(ctx context.Context, request *GetStatsRequest) (*
|
|||||||
func (s *statsServer) GetStatsOnline(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
|
func (s *statsServer) GetStatsOnline(ctx context.Context, request *GetStatsRequest) (*GetStatsResponse, error) {
|
||||||
c := s.stats.GetOnlineMap(request.Name)
|
c := s.stats.GetOnlineMap(request.Name)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, errors.New(request.Name, " not found.")
|
return nil, status.Error(codes.NotFound, request.Name+" not found.")
|
||||||
}
|
}
|
||||||
value := int64(c.Count())
|
value := int64(c.Count())
|
||||||
return &GetStatsResponse{
|
return &GetStatsResponse{
|
||||||
@@ -64,7 +66,7 @@ func (s *statsServer) GetStatsOnlineIpList(ctx context.Context, request *GetStat
|
|||||||
c := s.stats.GetOnlineMap(request.Name)
|
c := s.stats.GetOnlineMap(request.Name)
|
||||||
|
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, errors.New(request.Name, " not found.")
|
return nil, status.Error(codes.NotFound, request.Name+" not found.")
|
||||||
}
|
}
|
||||||
|
|
||||||
ips := make(map[string]int64)
|
ips := make(map[string]int64)
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
// OnlineMap is an implementation of stats.OnlineMap.
|
// OnlineMap is an implementation of stats.OnlineMap.
|
||||||
type OnlineMap struct {
|
type OnlineMap struct {
|
||||||
value int
|
|
||||||
ipList map[string]time.Time
|
ipList map[string]time.Time
|
||||||
access sync.RWMutex
|
access sync.RWMutex
|
||||||
lastCleanup time.Time
|
lastCleanup time.Time
|
||||||
@@ -25,7 +24,10 @@ func NewOnlineMap() *OnlineMap {
|
|||||||
|
|
||||||
// Count implements stats.OnlineMap.
|
// Count implements stats.OnlineMap.
|
||||||
func (c *OnlineMap) Count() int {
|
func (c *OnlineMap) Count() int {
|
||||||
return c.value
|
c.access.RLock()
|
||||||
|
defer c.access.RUnlock()
|
||||||
|
|
||||||
|
return len(c.ipList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List implements stats.OnlineMap.
|
// List implements stats.OnlineMap.
|
||||||
@@ -35,23 +37,18 @@ func (c *OnlineMap) List() []string {
|
|||||||
|
|
||||||
// AddIP implements stats.OnlineMap.
|
// AddIP implements stats.OnlineMap.
|
||||||
func (c *OnlineMap) AddIP(ip string) {
|
func (c *OnlineMap) AddIP(ip string) {
|
||||||
list := c.ipList
|
|
||||||
|
|
||||||
if ip == "127.0.0.1" {
|
if ip == "127.0.0.1" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.access.Lock()
|
c.access.Lock()
|
||||||
if _, ok := list[ip]; !ok {
|
c.ipList[ip] = time.Now()
|
||||||
list[ip] = time.Now()
|
|
||||||
}
|
|
||||||
c.access.Unlock()
|
c.access.Unlock()
|
||||||
|
|
||||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
||||||
list = c.RemoveExpiredIPs(list)
|
c.RemoveExpiredIPs()
|
||||||
c.lastCleanup = time.Now()
|
c.lastCleanup = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
c.value = len(list)
|
|
||||||
c.ipList = list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OnlineMap) GetKeys() []string {
|
func (c *OnlineMap) GetKeys() []string {
|
||||||
@@ -65,24 +62,22 @@ func (c *OnlineMap) GetKeys() []string {
|
|||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OnlineMap) RemoveExpiredIPs(list map[string]time.Time) map[string]time.Time {
|
func (c *OnlineMap) RemoveExpiredIPs() {
|
||||||
c.access.Lock()
|
c.access.Lock()
|
||||||
defer c.access.Unlock()
|
defer c.access.Unlock()
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
for k, t := range list {
|
for k, t := range c.ipList {
|
||||||
diff := now.Sub(t)
|
diff := now.Sub(t)
|
||||||
if diff.Seconds() > 20 {
|
if diff.Seconds() > 20 {
|
||||||
delete(list, k)
|
delete(c.ipList, k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
|
func (c *OnlineMap) IpTimeMap() map[string]time.Time {
|
||||||
list := c.ipList
|
|
||||||
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
if time.Since(c.lastCleanup) > c.cleanupPeriod {
|
||||||
list = c.RemoveExpiredIPs(list)
|
c.RemoveExpiredIPs()
|
||||||
c.lastCleanup = time.Now()
|
c.lastCleanup = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
152
app/version/config.pb.go
Normal file
152
app/version/config.pb.go
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
// 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
|
||||||
|
}
|
||||||
14
app/version/config.proto
Normal file
14
app/version/config.proto
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
77
app/version/version.go
Normal file
77
app/version/version.go
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
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,7 +13,7 @@ const (
|
|||||||
Size = 8192
|
Size = 8192
|
||||||
)
|
)
|
||||||
|
|
||||||
var zero = [Size * 10]byte{0}
|
var ErrBufferFull = errors.New("buffer is full")
|
||||||
|
|
||||||
var pool = bytespool.GetPool(Size)
|
var pool = bytespool.GetPool(Size)
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ func (b *Buffer) Bytes() []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extend increases the buffer size by n bytes, and returns the extended part.
|
// Extend increases the buffer size by n bytes, and returns the extended part.
|
||||||
// It panics if result size is larger than buf.Size.
|
// It panics if result size is larger than size of this buffer.
|
||||||
func (b *Buffer) Extend(n int32) []byte {
|
func (b *Buffer) Extend(n int32) []byte {
|
||||||
end := b.end + n
|
end := b.end + n
|
||||||
if end > int32(len(b.v)) {
|
if end > int32(len(b.v)) {
|
||||||
@@ -152,7 +152,7 @@ func (b *Buffer) Extend(n int32) []byte {
|
|||||||
}
|
}
|
||||||
ext := b.v[b.end:end]
|
ext := b.v[b.end:end]
|
||||||
b.end = end
|
b.end = end
|
||||||
copy(ext, zero[:])
|
clear(ext)
|
||||||
return ext
|
return ext
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,7 +215,7 @@ func (b *Buffer) Resize(from, to int32) {
|
|||||||
b.start += from
|
b.start += from
|
||||||
b.Check()
|
b.Check()
|
||||||
if b.end > oldEnd {
|
if b.end > oldEnd {
|
||||||
copy(b.v[oldEnd:b.end], zero[:])
|
clear(b.v[oldEnd:b.end])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,6 +244,14 @@ func (b *Buffer) Cap() int32 {
|
|||||||
return int32(len(b.v))
|
return int32(len(b.v))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Available returns the available capacity of the buffer content.
|
||||||
|
func (b *Buffer) Available() int32 {
|
||||||
|
if b == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return int32(len(b.v)) - b.end
|
||||||
|
}
|
||||||
|
|
||||||
// IsEmpty returns true if the buffer is empty.
|
// IsEmpty returns true if the buffer is empty.
|
||||||
func (b *Buffer) IsEmpty() bool {
|
func (b *Buffer) IsEmpty() bool {
|
||||||
return b.Len() == 0
|
return b.Len() == 0
|
||||||
@@ -258,13 +266,16 @@ func (b *Buffer) IsFull() bool {
|
|||||||
func (b *Buffer) Write(data []byte) (int, error) {
|
func (b *Buffer) Write(data []byte) (int, error) {
|
||||||
nBytes := copy(b.v[b.end:], data)
|
nBytes := copy(b.v[b.end:], data)
|
||||||
b.end += int32(nBytes)
|
b.end += int32(nBytes)
|
||||||
|
if nBytes < len(data) {
|
||||||
|
return nBytes, ErrBufferFull
|
||||||
|
}
|
||||||
return nBytes, nil
|
return nBytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteByte writes a single byte into the buffer.
|
// WriteByte writes a single byte into the buffer.
|
||||||
func (b *Buffer) WriteByte(v byte) error {
|
func (b *Buffer) WriteByte(v byte) error {
|
||||||
if b.IsFull() {
|
if b.IsFull() {
|
||||||
return errors.New("buffer full")
|
return ErrBufferFull
|
||||||
}
|
}
|
||||||
b.v[b.end] = v
|
b.v[b.end] = v
|
||||||
b.end++
|
b.end++
|
||||||
|
|||||||
@@ -24,9 +24,59 @@ var ErrReadTimeout = errors.New("IO timeout")
|
|||||||
|
|
||||||
// TimeoutReader is a reader that returns error if Read() operation takes longer than the given timeout.
|
// TimeoutReader is a reader that returns error if Read() operation takes longer than the given timeout.
|
||||||
type TimeoutReader interface {
|
type TimeoutReader interface {
|
||||||
|
Reader
|
||||||
ReadMultiBufferTimeout(time.Duration) (MultiBuffer, error)
|
ReadMultiBufferTimeout(time.Duration) (MultiBuffer, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TimeoutWrapperReader struct {
|
||||||
|
Reader
|
||||||
|
stats.Counter
|
||||||
|
mb MultiBuffer
|
||||||
|
err error
|
||||||
|
done chan struct{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *TimeoutWrapperReader) ReadMultiBuffer() (MultiBuffer, error) {
|
||||||
|
if r.done != nil {
|
||||||
|
<-r.done
|
||||||
|
r.done = nil
|
||||||
|
if r.Counter != nil {
|
||||||
|
r.Counter.Add(int64(r.mb.Len()))
|
||||||
|
}
|
||||||
|
return r.mb, r.err
|
||||||
|
}
|
||||||
|
r.mb, r.err = r.Reader.ReadMultiBuffer()
|
||||||
|
if r.Counter != nil {
|
||||||
|
r.Counter.Add(int64(r.mb.Len()))
|
||||||
|
}
|
||||||
|
return r.mb, r.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *TimeoutWrapperReader) ReadMultiBufferTimeout(duration time.Duration) (MultiBuffer, error) {
|
||||||
|
if r.done == nil {
|
||||||
|
r.done = make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
r.mb, r.err = r.Reader.ReadMultiBuffer()
|
||||||
|
close(r.done)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
timeout := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
time.Sleep(duration)
|
||||||
|
close(timeout)
|
||||||
|
}()
|
||||||
|
select {
|
||||||
|
case <-r.done:
|
||||||
|
r.done = nil
|
||||||
|
if r.Counter != nil {
|
||||||
|
r.Counter.Add(int64(r.mb.Len()))
|
||||||
|
}
|
||||||
|
return r.mb, r.err
|
||||||
|
case <-timeout:
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Writer extends io.Writer with MultiBuffer.
|
// Writer extends io.Writer with MultiBuffer.
|
||||||
type Writer interface {
|
type Writer interface {
|
||||||
// WriteMultiBuffer writes a MultiBuffer into underlying writer.
|
// WriteMultiBuffer writes a MultiBuffer into underlying writer.
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ func Compact(mb MultiBuffer) MultiBuffer {
|
|||||||
|
|
||||||
for i := 1; i < len(mb); i++ {
|
for i := 1; i < len(mb); i++ {
|
||||||
curr := mb[i]
|
curr := mb[i]
|
||||||
if last.Len()+curr.Len() > Size {
|
if curr.Len() > last.Available() {
|
||||||
mb2 = append(mb2, last)
|
mb2 = append(mb2, last)
|
||||||
last = curr
|
last = curr
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -175,6 +175,29 @@ func TestCompact(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCompactWithConsumed(t *testing.T) {
|
||||||
|
// make a consumed buffer (a.Start != 0)
|
||||||
|
a := New()
|
||||||
|
for range 8192 {
|
||||||
|
common.Must2(a.WriteString("a"))
|
||||||
|
}
|
||||||
|
a.Read(make([]byte, 2))
|
||||||
|
|
||||||
|
b := New()
|
||||||
|
for range 2 {
|
||||||
|
common.Must2(b.WriteString("b"))
|
||||||
|
}
|
||||||
|
|
||||||
|
mb := MultiBuffer{a, b}
|
||||||
|
cmb := Compact(mb)
|
||||||
|
mbc := &MultiBufferContainer{mb}
|
||||||
|
mbc.Read(make([]byte, 8190))
|
||||||
|
|
||||||
|
if w := cmb.String(); w != "bb" {
|
||||||
|
t.Error("unexpected Compact result ", w)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkSplitBytes(b *testing.B) {
|
func BenchmarkSplitBytes(b *testing.B) {
|
||||||
var mb MultiBuffer
|
var mb MultiBuffer
|
||||||
raw := make([]byte, Size)
|
raw := make([]byte, Size)
|
||||||
|
|||||||
@@ -75,9 +75,10 @@ func (w *BufferToBytesWriter) ReadFrom(reader io.Reader) (int64, error) {
|
|||||||
// BufferedWriter is a Writer with internal buffer.
|
// BufferedWriter is a Writer with internal buffer.
|
||||||
type BufferedWriter struct {
|
type BufferedWriter struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
writer Writer
|
writer Writer
|
||||||
buffer *Buffer
|
buffer *Buffer
|
||||||
buffered bool
|
buffered bool
|
||||||
|
flushNext bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBufferedWriter creates a new BufferedWriter.
|
// NewBufferedWriter creates a new BufferedWriter.
|
||||||
@@ -161,6 +162,12 @@ func (w *BufferedWriter) WriteMultiBuffer(b MultiBuffer) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if w.flushNext {
|
||||||
|
w.buffered = false
|
||||||
|
w.flushNext = false
|
||||||
|
return w.flushInternal()
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,6 +208,13 @@ func (w *BufferedWriter) SetBuffered(f bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetFlushNext will wait the next WriteMultiBuffer to flush and set buffered = false
|
||||||
|
func (w *BufferedWriter) SetFlushNext() {
|
||||||
|
w.Lock()
|
||||||
|
defer w.Unlock()
|
||||||
|
w.flushNext = true
|
||||||
|
}
|
||||||
|
|
||||||
// ReadFrom implements io.ReaderFrom.
|
// ReadFrom implements io.ReaderFrom.
|
||||||
func (w *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) {
|
func (w *BufferedWriter) ReadFrom(reader io.Reader) (int64, error) {
|
||||||
if err := w.SetBuffered(false); err != nil {
|
if err := w.SetBuffered(false); err != nil {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"go/build"
|
"go/build"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
@@ -23,7 +24,9 @@ func Must(err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Must2 panics if the second parameter is not nil, otherwise returns the first parameter.
|
// Must2 panics if the second parameter is not nil, otherwise returns the first parameter.
|
||||||
func Must2(v interface{}, err error) interface{} {
|
// This is useful when function returned "sth, err" and avoid many "if err != nil"
|
||||||
|
// Internal usage only, if user input can cause err, it must be handled
|
||||||
|
func Must2[T any](v T, err error) T {
|
||||||
Must(err)
|
Must(err)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
@@ -151,3 +154,14 @@ func GetModuleName(pathToProjectRoot string) (string, error) {
|
|||||||
}
|
}
|
||||||
return moduleName, fmt.Errorf("no `go.mod` file in every parent directory of `%s`", pathToProjectRoot)
|
return moduleName, fmt.Errorf("no `go.mod` file in every parent directory of `%s`", pathToProjectRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloseIfExists call obj.Close() if obj is not nil.
|
||||||
|
func CloseIfExists(obj any) error {
|
||||||
|
if obj != nil {
|
||||||
|
v := reflect.ValueOf(obj)
|
||||||
|
if !v.IsNil() {
|
||||||
|
return Close(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -32,9 +32,7 @@ func NewAesCTRStream(key []byte, iv []byte) cipher.Stream {
|
|||||||
|
|
||||||
// NewAesGcm creates a AEAD cipher based on AES-GCM.
|
// NewAesGcm creates a AEAD cipher based on AES-GCM.
|
||||||
func NewAesGcm(key []byte) cipher.AEAD {
|
func NewAesGcm(key []byte) cipher.AEAD {
|
||||||
block, err := aes.NewCipher(key)
|
block := common.Must2(aes.NewCipher(key))
|
||||||
common.Must(err)
|
aead := common.Must2(cipher.NewGCM(block))
|
||||||
aead, err := cipher.NewGCM(block)
|
|
||||||
common.Must(err)
|
|
||||||
return aead
|
return aead
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ package crypto_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/aes"
|
|
||||||
"crypto/cipher"
|
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -18,11 +16,8 @@ import (
|
|||||||
func TestAuthenticationReaderWriter(t *testing.T) {
|
func TestAuthenticationReaderWriter(t *testing.T) {
|
||||||
key := make([]byte, 16)
|
key := make([]byte, 16)
|
||||||
rand.Read(key)
|
rand.Read(key)
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
aead, err := cipher.NewGCM(block)
|
aead := NewAesGcm(key)
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
const payloadSize = 1024 * 80
|
const payloadSize = 1024 * 80
|
||||||
rawPayload := make([]byte, payloadSize)
|
rawPayload := make([]byte, payloadSize)
|
||||||
@@ -71,7 +66,7 @@ func TestAuthenticationReaderWriter(t *testing.T) {
|
|||||||
t.Error(r)
|
t.Error(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = reader.ReadMultiBuffer()
|
_, err := reader.ReadMultiBuffer()
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
t.Error("error: ", err)
|
t.Error("error: ", err)
|
||||||
}
|
}
|
||||||
@@ -80,11 +75,8 @@ func TestAuthenticationReaderWriter(t *testing.T) {
|
|||||||
func TestAuthenticationReaderWriterPacket(t *testing.T) {
|
func TestAuthenticationReaderWriterPacket(t *testing.T) {
|
||||||
key := make([]byte, 16)
|
key := make([]byte, 16)
|
||||||
common.Must2(rand.Read(key))
|
common.Must2(rand.Read(key))
|
||||||
block, err := aes.NewCipher(key)
|
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
aead, err := cipher.NewGCM(block)
|
aead := NewAesGcm(key)
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
cache := buf.New()
|
cache := buf.New()
|
||||||
iv := make([]byte, 12)
|
iv := make([]byte, 12)
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ func RandBetween(from int64, to int64) int64 {
|
|||||||
if from == to {
|
if from == to {
|
||||||
return from
|
return from
|
||||||
}
|
}
|
||||||
|
if from > to {
|
||||||
|
from, to = to, from
|
||||||
|
}
|
||||||
bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from))
|
bigInt, _ := rand.Int(rand.Reader, big.NewInt(to-from))
|
||||||
return from + bigInt.Int64()
|
return from + bigInt.Int64()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ func (l *DNSLog) String() string {
|
|||||||
type dnsStatus string
|
type dnsStatus string
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DNSQueried = dnsStatus("got answer:")
|
DNSQueried = dnsStatus("got answer:")
|
||||||
DNSCacheHit = dnsStatus("cache HIT:")
|
DNSCacheHit = dnsStatus("cache HIT:")
|
||||||
|
DNSCacheOptimiste = dnsStatus("cache OPTIMISTE:")
|
||||||
)
|
)
|
||||||
|
|
||||||
func joinNetIP(ips []net.IP) string {
|
func joinNetIP(ips []net.IP) string {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package mux
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
goerrors "errors"
|
||||||
"io"
|
"io"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -154,8 +155,11 @@ func (f *DialingWorkerFactory) Create() (*ClientWorker, error) {
|
|||||||
ctx := session.ContextWithOutbounds(context.Background(), outbounds)
|
ctx := session.ContextWithOutbounds(context.Background(), outbounds)
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
|
||||||
if err := p.Process(ctx, &transport.Link{Reader: uplinkReader, Writer: downlinkWriter}, d); err != nil {
|
if errP := p.Process(ctx, &transport.Link{Reader: uplinkReader, Writer: downlinkWriter}, d); errP != nil {
|
||||||
errors.LogInfoInner(ctx, err, "failed to handler mux client connection")
|
errC := errors.Cause(errP)
|
||||||
|
if !(goerrors.Is(errC, io.EOF) || goerrors.Is(errC, io.ErrClosedPipe) || goerrors.Is(errC, context.Canceled)) {
|
||||||
|
errors.LogInfoInner(ctx, errP, "failed to handler mux client connection")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
common.Must(c.Close())
|
common.Must(c.Close())
|
||||||
cancel()
|
cancel()
|
||||||
@@ -173,6 +177,7 @@ type ClientWorker struct {
|
|||||||
sessionManager *SessionManager
|
sessionManager *SessionManager
|
||||||
link transport.Link
|
link transport.Link
|
||||||
done *done.Instance
|
done *done.Instance
|
||||||
|
timer *time.Ticker
|
||||||
strategy ClientStrategy
|
strategy ClientStrategy
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,6 +192,7 @@ func NewClientWorker(stream transport.Link, s ClientStrategy) (*ClientWorker, er
|
|||||||
sessionManager: NewSessionManager(),
|
sessionManager: NewSessionManager(),
|
||||||
link: stream,
|
link: stream,
|
||||||
done: done.New(),
|
done: done.New(),
|
||||||
|
timer: time.NewTicker(time.Second * 16),
|
||||||
strategy: s,
|
strategy: s,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,20 +215,28 @@ func (m *ClientWorker) Closed() bool {
|
|||||||
return m.done.Done()
|
return m.done.Done()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *ClientWorker) WaitClosed() <-chan struct{} {
|
||||||
|
return m.done.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ClientWorker) Close() error {
|
||||||
|
return m.done.Close()
|
||||||
|
}
|
||||||
|
|
||||||
func (m *ClientWorker) monitor() {
|
func (m *ClientWorker) monitor() {
|
||||||
timer := time.NewTicker(time.Second * 16)
|
defer m.timer.Stop()
|
||||||
defer timer.Stop()
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
checkSize := m.sessionManager.Size()
|
||||||
|
checkCount := m.sessionManager.Count()
|
||||||
select {
|
select {
|
||||||
case <-m.done.Wait():
|
case <-m.done.Wait():
|
||||||
m.sessionManager.Close()
|
m.sessionManager.Close()
|
||||||
common.Close(m.link.Writer)
|
common.Interrupt(m.link.Writer)
|
||||||
common.Interrupt(m.link.Reader)
|
common.Interrupt(m.link.Reader)
|
||||||
return
|
return
|
||||||
case <-timer.C:
|
case <-m.timer.C:
|
||||||
size := m.sessionManager.Size()
|
if m.sessionManager.CloseIfNoSessionAndIdle(checkSize, checkCount) {
|
||||||
if size == 0 && m.sessionManager.CloseIfNoSession() {
|
|
||||||
common.Must(m.done.Close())
|
common.Must(m.done.Close())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -250,7 +264,11 @@ func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
|
|||||||
transferType = protocol.TransferTypePacket
|
transferType = protocol.TransferTypePacket
|
||||||
}
|
}
|
||||||
s.transferType = transferType
|
s.transferType = transferType
|
||||||
writer := NewWriter(s.ID, ob.Target, output, transferType, xudp.GetGlobalID(ctx))
|
var inbound *session.Inbound
|
||||||
|
if session.IsReverseMuxFromContext(ctx) {
|
||||||
|
inbound = session.InboundFromContext(ctx)
|
||||||
|
}
|
||||||
|
writer := NewWriter(s.ID, ob.Target, output, transferType, xudp.GetGlobalID(ctx), inbound)
|
||||||
defer s.Close(false)
|
defer s.Close(false)
|
||||||
defer writer.Close()
|
defer writer.Close()
|
||||||
|
|
||||||
@@ -276,6 +294,8 @@ func (m *ClientWorker) IsClosing() bool {
|
|||||||
return false
|
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 {
|
func (m *ClientWorker) IsFull() bool {
|
||||||
if m.IsClosing() || m.Closed() {
|
if m.IsClosing() || m.Closed() {
|
||||||
return true
|
return true
|
||||||
@@ -289,18 +309,24 @@ func (m *ClientWorker) IsFull() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *ClientWorker) Dispatch(ctx context.Context, link *transport.Link) bool {
|
func (m *ClientWorker) Dispatch(ctx context.Context, link *transport.Link) bool {
|
||||||
if m.IsFull() || m.Closed() {
|
if m.IsFull() {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
sm := m.sessionManager
|
sm := m.sessionManager
|
||||||
s := sm.Allocate()
|
s := sm.Allocate(&m.strategy)
|
||||||
if s == nil {
|
if s == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
s.input = link.Reader
|
s.input = link.Reader
|
||||||
s.output = link.Writer
|
s.output = link.Writer
|
||||||
go fetchInput(ctx, s, m.link.Writer)
|
go fetchInput(ctx, s, m.link.Writer)
|
||||||
|
if _, ok := link.Reader.(*pipe.Reader); !ok {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-s.done.Wait():
|
||||||
|
}
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,7 +388,7 @@ func (m *ClientWorker) fetchOutput() {
|
|||||||
|
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
for {
|
for {
|
||||||
err := meta.Unmarshal(reader)
|
err := meta.Unmarshal(reader, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) != io.EOF {
|
if errors.Cause(err) != io.EOF {
|
||||||
errors.LogInfoInner(context.Background(), err, "failed to read metadata")
|
errors.LogInfoInner(context.Background(), err, "failed to read metadata")
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SessionStatus byte
|
type SessionStatus byte
|
||||||
@@ -60,6 +61,7 @@ type FrameMetadata struct {
|
|||||||
Option bitmask.Byte
|
Option bitmask.Byte
|
||||||
SessionStatus SessionStatus
|
SessionStatus SessionStatus
|
||||||
GlobalID [8]byte
|
GlobalID [8]byte
|
||||||
|
Inbound *session.Inbound
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
||||||
@@ -79,11 +81,23 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
|||||||
case net.Network_UDP:
|
case net.Network_UDP:
|
||||||
common.Must(b.WriteByte(byte(TargetNetworkUDP)))
|
common.Must(b.WriteByte(byte(TargetNetworkUDP)))
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
|
if err := addrParser.WriteAddressPort(b, f.Target.Address, f.Target.Port); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if b.UDP != nil { // make sure it's user's proxy request
|
if f.Inbound != nil {
|
||||||
|
if f.Inbound.Source.Network == net.Network_TCP || f.Inbound.Source.Network == net.Network_UDP {
|
||||||
|
common.Must(b.WriteByte(byte(f.Inbound.Source.Network - 1)))
|
||||||
|
if err := addrParser.WriteAddressPort(b, f.Inbound.Source.Address, f.Inbound.Source.Port); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if f.Inbound.Local.Network == net.Network_TCP || f.Inbound.Local.Network == net.Network_UDP {
|
||||||
|
common.Must(b.WriteByte(byte(f.Inbound.Local.Network - 1)))
|
||||||
|
if err := addrParser.WriteAddressPort(b, f.Inbound.Local.Address, f.Inbound.Local.Port); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if b.UDP != nil { // make sure it's user's proxy request
|
||||||
b.Write(f.GlobalID[:]) // no need to check whether it's empty
|
b.Write(f.GlobalID[:]) // no need to check whether it's empty
|
||||||
}
|
}
|
||||||
} else if b.UDP != nil {
|
} else if b.UDP != nil {
|
||||||
@@ -97,7 +111,7 @@ func (f FrameMetadata) WriteTo(b *buf.Buffer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal reads FrameMetadata from the given reader.
|
// Unmarshal reads FrameMetadata from the given reader.
|
||||||
func (f *FrameMetadata) Unmarshal(reader io.Reader) error {
|
func (f *FrameMetadata) Unmarshal(reader io.Reader, readSourceAndLocal bool) error {
|
||||||
metaLen, err := serial.ReadUint16(reader)
|
metaLen, err := serial.ReadUint16(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -112,12 +126,12 @@ func (f *FrameMetadata) Unmarshal(reader io.Reader) error {
|
|||||||
if _, err := b.ReadFullFrom(reader, int32(metaLen)); err != nil {
|
if _, err := b.ReadFullFrom(reader, int32(metaLen)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return f.UnmarshalFromBuffer(b)
|
return f.UnmarshalFromBuffer(b, readSourceAndLocal)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalFromBuffer reads a FrameMetadata from the given buffer.
|
// UnmarshalFromBuffer reads a FrameMetadata from the given buffer.
|
||||||
// Visible for testing only.
|
// Visible for testing only.
|
||||||
func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
|
func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer, readSourceAndLocal bool) error {
|
||||||
if b.Len() < 4 {
|
if b.Len() < 4 {
|
||||||
return errors.New("insufficient buffer: ", b.Len())
|
return errors.New("insufficient buffer: ", b.Len())
|
||||||
}
|
}
|
||||||
@@ -150,6 +164,54 @@ func (f *FrameMetadata) UnmarshalFromBuffer(b *buf.Buffer) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.SessionStatus == SessionStatusNew && readSourceAndLocal {
|
||||||
|
f.Inbound = &session.Inbound{}
|
||||||
|
|
||||||
|
if b.Len() == 0 {
|
||||||
|
return nil // for heartbeat, etc.
|
||||||
|
}
|
||||||
|
network := TargetNetwork(b.Byte(0))
|
||||||
|
if network == 0 {
|
||||||
|
return nil // may be padding
|
||||||
|
}
|
||||||
|
b.Advance(1)
|
||||||
|
addr, port, err := addrParser.ReadAddressPort(nil, b)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("reading source: failed to parse address and port").Base(err)
|
||||||
|
}
|
||||||
|
switch network {
|
||||||
|
case TargetNetworkTCP:
|
||||||
|
f.Inbound.Source = net.TCPDestination(addr, port)
|
||||||
|
case TargetNetworkUDP:
|
||||||
|
f.Inbound.Source = net.UDPDestination(addr, port)
|
||||||
|
default:
|
||||||
|
return errors.New("reading source: unknown network type: ", network)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.Len() == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
network = TargetNetwork(b.Byte(0))
|
||||||
|
if network == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
b.Advance(1)
|
||||||
|
addr, port, err = addrParser.ReadAddressPort(nil, b)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("reading local: failed to parse address and port").Base(err)
|
||||||
|
}
|
||||||
|
switch network {
|
||||||
|
case TargetNetworkTCP:
|
||||||
|
f.Inbound.Local = net.TCPDestination(addr, port)
|
||||||
|
case TargetNetworkUDP:
|
||||||
|
f.Inbound.Local = net.UDPDestination(addr, port)
|
||||||
|
default:
|
||||||
|
return errors.New("reading local: unknown network type: ", network)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Application data is essential, to test whether the pipe is closed.
|
// Application data is essential, to test whether the pipe is closed.
|
||||||
if f.SessionStatus == SessionStatusNew && f.Option.Has(OptionData) &&
|
if f.SessionStatus == SessionStatusNew && f.Option.Has(OptionData) &&
|
||||||
f.Target.Network == net.Network_UDP && b.Len() >= 8 {
|
f.Target.Network == net.Network_UDP && b.Len() >= 8 {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
. "github.com/xtls/xray-core/common/mux"
|
. "github.com/xtls/xray-core/common/mux"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
"github.com/xtls/xray-core/transport/pipe"
|
"github.com/xtls/xray-core/transport/pipe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,13 +33,13 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
pReader, pWriter := pipe.New(pipe.WithSizeLimit(1024))
|
pReader, pWriter := pipe.New(pipe.WithSizeLimit(1024))
|
||||||
|
|
||||||
dest := net.TCPDestination(net.DomainAddress("example.com"), 80)
|
dest := net.TCPDestination(net.DomainAddress("example.com"), 80)
|
||||||
writer := NewWriter(1, dest, pWriter, protocol.TransferTypeStream, [8]byte{})
|
writer := NewWriter(1, dest, pWriter, protocol.TransferTypeStream, [8]byte{}, &session.Inbound{})
|
||||||
|
|
||||||
dest2 := net.TCPDestination(net.LocalHostIP, 443)
|
dest2 := net.TCPDestination(net.LocalHostIP, 443)
|
||||||
writer2 := NewWriter(2, dest2, pWriter, protocol.TransferTypeStream, [8]byte{})
|
writer2 := NewWriter(2, dest2, pWriter, protocol.TransferTypeStream, [8]byte{}, &session.Inbound{})
|
||||||
|
|
||||||
dest3 := net.TCPDestination(net.LocalHostIPv6, 18374)
|
dest3 := net.TCPDestination(net.LocalHostIPv6, 18374)
|
||||||
writer3 := NewWriter(3, dest3, pWriter, protocol.TransferTypeStream, [8]byte{})
|
writer3 := NewWriter(3, dest3, pWriter, protocol.TransferTypeStream, [8]byte{}, &session.Inbound{})
|
||||||
|
|
||||||
writePayload := func(writer *Writer, payload ...byte) error {
|
writePayload := func(writer *Writer, payload ...byte) error {
|
||||||
b := buf.New()
|
b := buf.New()
|
||||||
@@ -62,7 +63,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 1,
|
SessionID: 1,
|
||||||
SessionStatus: SessionStatusNew,
|
SessionStatus: SessionStatusNew,
|
||||||
@@ -81,7 +82,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionStatus: SessionStatusNew,
|
SessionStatus: SessionStatusNew,
|
||||||
SessionID: 2,
|
SessionID: 2,
|
||||||
@@ -94,7 +95,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 1,
|
SessionID: 1,
|
||||||
SessionStatus: SessionStatusKeep,
|
SessionStatus: SessionStatusKeep,
|
||||||
@@ -112,7 +113,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 3,
|
SessionID: 3,
|
||||||
SessionStatus: SessionStatusNew,
|
SessionStatus: SessionStatusNew,
|
||||||
@@ -131,7 +132,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 1,
|
SessionID: 1,
|
||||||
SessionStatus: SessionStatusEnd,
|
SessionStatus: SessionStatusEnd,
|
||||||
@@ -143,7 +144,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 3,
|
SessionID: 3,
|
||||||
SessionStatus: SessionStatusEnd,
|
SessionStatus: SessionStatusEnd,
|
||||||
@@ -155,7 +156,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 2,
|
SessionID: 2,
|
||||||
SessionStatus: SessionStatusKeep,
|
SessionStatus: SessionStatusKeep,
|
||||||
@@ -173,7 +174,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
common.Must(meta.Unmarshal(bytesReader))
|
common.Must(meta.Unmarshal(bytesReader, false))
|
||||||
if r := cmp.Diff(meta, FrameMetadata{
|
if r := cmp.Diff(meta, FrameMetadata{
|
||||||
SessionID: 2,
|
SessionID: 2,
|
||||||
SessionStatus: SessionStatusEnd,
|
SessionStatus: SessionStatusEnd,
|
||||||
@@ -187,7 +188,7 @@ func TestReaderWriter(t *testing.T) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
err := meta.Unmarshal(bytesReader)
|
err := meta.Unmarshal(bytesReader, false)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("nil error")
|
t.Error("nil error")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package mux
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
@@ -11,6 +12,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/session"
|
"github.com/xtls/xray-core/common/session"
|
||||||
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
"github.com/xtls/xray-core/features/routing"
|
"github.com/xtls/xray-core/features/routing"
|
||||||
"github.com/xtls/xray-core/transport"
|
"github.com/xtls/xray-core/transport"
|
||||||
@@ -61,8 +63,18 @@ func (s *Server) DispatchLink(ctx context.Context, dest net.Destination, link *t
|
|||||||
if dest.Address != muxCoolAddress {
|
if dest.Address != muxCoolAddress {
|
||||||
return s.dispatcher.DispatchLink(ctx, dest, link)
|
return s.dispatcher.DispatchLink(ctx, dest, link)
|
||||||
}
|
}
|
||||||
_, err := NewServerWorker(ctx, s.dispatcher, link)
|
if d, ok := s.dispatcher.(routing.WrapLinkDispatcher); ok {
|
||||||
return err
|
link = d.WrapLink(ctx, link)
|
||||||
|
}
|
||||||
|
worker, err := NewServerWorker(ctx, s.dispatcher, link)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
case <-worker.done.Wait():
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start implements common.Runnable.
|
// Start implements common.Runnable.
|
||||||
@@ -79,6 +91,8 @@ type ServerWorker struct {
|
|||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
link *transport.Link
|
link *transport.Link
|
||||||
sessionManager *SessionManager
|
sessionManager *SessionManager
|
||||||
|
done *done.Instance
|
||||||
|
timer *time.Ticker
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerWorker(ctx context.Context, d routing.Dispatcher, link *transport.Link) (*ServerWorker, error) {
|
func NewServerWorker(ctx context.Context, d routing.Dispatcher, link *transport.Link) (*ServerWorker, error) {
|
||||||
@@ -86,8 +100,14 @@ func NewServerWorker(ctx context.Context, d routing.Dispatcher, link *transport.
|
|||||||
dispatcher: d,
|
dispatcher: d,
|
||||||
link: link,
|
link: link,
|
||||||
sessionManager: NewSessionManager(),
|
sessionManager: NewSessionManager(),
|
||||||
|
done: done.New(),
|
||||||
|
timer: time.NewTicker(60 * time.Second),
|
||||||
|
}
|
||||||
|
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
|
inbound.CanSpliceCopy = 3
|
||||||
}
|
}
|
||||||
go worker.run(ctx)
|
go worker.run(ctx)
|
||||||
|
go worker.monitor()
|
||||||
return worker, nil
|
return worker, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,12 +122,40 @@ func handle(ctx context.Context, s *Session, output buf.Writer) {
|
|||||||
s.Close(false)
|
s.Close(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *ServerWorker) monitor() {
|
||||||
|
defer w.timer.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
checkSize := w.sessionManager.Size()
|
||||||
|
checkCount := w.sessionManager.Count()
|
||||||
|
select {
|
||||||
|
case <-w.done.Wait():
|
||||||
|
w.sessionManager.Close()
|
||||||
|
common.Interrupt(w.link.Writer)
|
||||||
|
common.Interrupt(w.link.Reader)
|
||||||
|
return
|
||||||
|
case <-w.timer.C:
|
||||||
|
if w.sessionManager.CloseIfNoSessionAndIdle(checkSize, checkCount) {
|
||||||
|
common.Must(w.done.Close())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (w *ServerWorker) ActiveConnections() uint32 {
|
func (w *ServerWorker) ActiveConnections() uint32 {
|
||||||
return uint32(w.sessionManager.Size())
|
return uint32(w.sessionManager.Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *ServerWorker) Closed() bool {
|
func (w *ServerWorker) Closed() bool {
|
||||||
return w.sessionManager.Closed()
|
return w.done.Done()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ServerWorker) WaitClosed() <-chan struct{} {
|
||||||
|
return w.done.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *ServerWorker) Close() error {
|
||||||
|
return w.done.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.BufferedReader) error {
|
func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.BufferedReader) error {
|
||||||
@@ -118,9 +166,15 @@ func (w *ServerWorker) handleStatusKeepAlive(meta *FrameMetadata, reader *buf.Bu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error {
|
func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata, reader *buf.BufferedReader) error {
|
||||||
// deep-clone outbounds because it is going to be mutated concurrently
|
ctx = session.SubContextFromMuxInbound(ctx)
|
||||||
// (Target and OriginalTarget)
|
if meta.Inbound != nil && meta.Inbound.Source.IsValid() && meta.Inbound.Local.IsValid() {
|
||||||
ctx = session.ContextCloneOutboundsAndContent(ctx)
|
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
|
newInbound := *inbound
|
||||||
|
newInbound.Source = meta.Inbound.Source
|
||||||
|
newInbound.Local = meta.Inbound.Local
|
||||||
|
ctx = session.ContextWithInbound(ctx, &newInbound)
|
||||||
|
}
|
||||||
|
}
|
||||||
errors.LogInfo(ctx, "received request for ", meta.Target)
|
errors.LogInfo(ctx, "received request for ", meta.Target)
|
||||||
{
|
{
|
||||||
msg := &log.AccessMessage{
|
msg := &log.AccessMessage{
|
||||||
@@ -201,11 +255,12 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
|
|||||||
transferType: protocol.TransferTypePacket,
|
transferType: protocol.TransferTypePacket,
|
||||||
XUDP: x,
|
XUDP: x,
|
||||||
}
|
}
|
||||||
go handle(ctx, x.Mux, w.link.Writer)
|
|
||||||
x.Status = Active
|
x.Status = Active
|
||||||
if !w.sessionManager.Add(x.Mux) {
|
if !w.sessionManager.Add(x.Mux) {
|
||||||
x.Mux.Close(false)
|
x.Mux.Close(false)
|
||||||
|
return errors.New("failed to add new session")
|
||||||
}
|
}
|
||||||
|
go handle(ctx, x.Mux, w.link.Writer)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,18 +281,23 @@ func (w *ServerWorker) handleStatusNew(ctx context.Context, meta *FrameMetadata,
|
|||||||
if meta.Target.Network == net.Network_UDP {
|
if meta.Target.Network == net.Network_UDP {
|
||||||
s.transferType = protocol.TransferTypePacket
|
s.transferType = protocol.TransferTypePacket
|
||||||
}
|
}
|
||||||
w.sessionManager.Add(s)
|
if !w.sessionManager.Add(s) {
|
||||||
|
s.Close(false)
|
||||||
|
return errors.New("failed to add new session")
|
||||||
|
}
|
||||||
go handle(ctx, s, w.link.Writer)
|
go handle(ctx, s, w.link.Writer)
|
||||||
if !meta.Option.Has(OptionData) {
|
if !meta.Option.Has(OptionData) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rr := s.NewReader(reader, &meta.Target)
|
rr := s.NewReader(reader, &meta.Target)
|
||||||
if err := buf.Copy(rr, s.output); err != nil {
|
err = buf.Copy(rr, s.output)
|
||||||
buf.Copy(rr, buf.Discard)
|
|
||||||
return s.Close(false)
|
if err != nil && buf.IsWriteError(err) {
|
||||||
|
s.Close(false)
|
||||||
|
return buf.Copy(rr, buf.Discard)
|
||||||
}
|
}
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.BufferedReader) error {
|
func (w *ServerWorker) handleStatusKeep(meta *FrameMetadata, reader *buf.BufferedReader) error {
|
||||||
@@ -278,7 +338,7 @@ func (w *ServerWorker) handleStatusEnd(meta *FrameMetadata, reader *buf.Buffered
|
|||||||
|
|
||||||
func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error {
|
func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedReader) error {
|
||||||
var meta FrameMetadata
|
var meta FrameMetadata
|
||||||
err := meta.Unmarshal(reader)
|
err := meta.Unmarshal(reader, session.IsReverseMuxFromContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("failed to read metadata").Base(err)
|
return errors.New("failed to read metadata").Base(err)
|
||||||
}
|
}
|
||||||
@@ -289,7 +349,7 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
|
|||||||
case SessionStatusEnd:
|
case SessionStatusEnd:
|
||||||
err = w.handleStatusEnd(&meta, reader)
|
err = w.handleStatusEnd(&meta, reader)
|
||||||
case SessionStatusNew:
|
case SessionStatusNew:
|
||||||
err = w.handleStatusNew(ctx, &meta, reader)
|
err = w.handleStatusNew(session.ContextWithIsReverseMux(ctx, false), &meta, reader)
|
||||||
case SessionStatusKeep:
|
case SessionStatusKeep:
|
||||||
err = w.handleStatusKeep(&meta, reader)
|
err = w.handleStatusKeep(&meta, reader)
|
||||||
default:
|
default:
|
||||||
@@ -304,10 +364,11 @@ func (w *ServerWorker) handleFrame(ctx context.Context, reader *buf.BufferedRead
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *ServerWorker) run(ctx context.Context) {
|
func (w *ServerWorker) run(ctx context.Context) {
|
||||||
input := w.link.Reader
|
defer func() {
|
||||||
reader := &buf.BufferedReader{Reader: input}
|
common.Must(w.done.Close())
|
||||||
|
}()
|
||||||
|
|
||||||
defer w.sessionManager.Close()
|
reader := &buf.BufferedReader{Reader: w.link.Reader}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@@ -318,7 +379,6 @@ func (w *ServerWorker) run(ctx context.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) != io.EOF {
|
if errors.Cause(err) != io.EOF {
|
||||||
errors.LogInfoInner(ctx, err, "unexpected EOF")
|
errors.LogInfoInner(ctx, err, "unexpected EOF")
|
||||||
common.Interrupt(input)
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
|
"github.com/xtls/xray-core/common/signal/done"
|
||||||
"github.com/xtls/xray-core/transport/pipe"
|
"github.com/xtls/xray-core/transport/pipe"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -50,11 +51,14 @@ func (m *SessionManager) Count() int {
|
|||||||
return int(m.count)
|
return int(m.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SessionManager) Allocate() *Session {
|
func (m *SessionManager) Allocate(Strategy *ClientStrategy) *Session {
|
||||||
m.Lock()
|
m.Lock()
|
||||||
defer m.Unlock()
|
defer m.Unlock()
|
||||||
|
|
||||||
if m.closed {
|
MaxConcurrency := int(Strategy.MaxConcurrency)
|
||||||
|
MaxConnection := uint16(Strategy.MaxConnection)
|
||||||
|
|
||||||
|
if m.closed || (MaxConcurrency > 0 && len(m.sessions) >= MaxConcurrency) || (MaxConnection > 0 && m.count >= MaxConnection) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,6 +66,7 @@ func (m *SessionManager) Allocate() *Session {
|
|||||||
s := &Session{
|
s := &Session{
|
||||||
ID: m.count,
|
ID: m.count,
|
||||||
parent: m,
|
parent: m,
|
||||||
|
done: done.New(),
|
||||||
}
|
}
|
||||||
m.sessions[s.ID] = s
|
m.sessions[s.ID] = s
|
||||||
return s
|
return s
|
||||||
@@ -112,7 +117,7 @@ func (m *SessionManager) Get(id uint16) (*Session, bool) {
|
|||||||
return s, found
|
return s, found
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *SessionManager) CloseIfNoSession() bool {
|
func (m *SessionManager) CloseIfNoSessionAndIdle(checkSize int, checkCount int) bool {
|
||||||
m.Lock()
|
m.Lock()
|
||||||
defer m.Unlock()
|
defer m.Unlock()
|
||||||
|
|
||||||
@@ -120,11 +125,13 @@ func (m *SessionManager) CloseIfNoSession() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.sessions) != 0 {
|
if len(m.sessions) != 0 || checkSize != 0 || checkCount != int(m.count) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
m.closed = true
|
m.closed = true
|
||||||
|
|
||||||
|
m.sessions = nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +161,7 @@ type Session struct {
|
|||||||
ID uint16
|
ID uint16
|
||||||
transferType protocol.TransferType
|
transferType protocol.TransferType
|
||||||
closed bool
|
closed bool
|
||||||
|
done *done.Instance
|
||||||
XUDP *XUDP
|
XUDP *XUDP
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,6 +176,9 @@ func (s *Session) Close(locked bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
s.closed = true
|
s.closed = true
|
||||||
|
if s.done != nil {
|
||||||
|
s.done.Close()
|
||||||
|
}
|
||||||
if s.XUDP == nil {
|
if s.XUDP == nil {
|
||||||
common.Interrupt(s.input)
|
common.Interrupt(s.input)
|
||||||
common.Close(s.output)
|
common.Close(s.output)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
func TestSessionManagerAdd(t *testing.T) {
|
func TestSessionManagerAdd(t *testing.T) {
|
||||||
m := NewSessionManager()
|
m := NewSessionManager()
|
||||||
|
|
||||||
s := m.Allocate()
|
s := m.Allocate(&ClientStrategy{})
|
||||||
if s.ID != 1 {
|
if s.ID != 1 {
|
||||||
t.Error("id: ", s.ID)
|
t.Error("id: ", s.ID)
|
||||||
}
|
}
|
||||||
@@ -17,7 +17,7 @@ func TestSessionManagerAdd(t *testing.T) {
|
|||||||
t.Error("size: ", m.Size())
|
t.Error("size: ", m.Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
s = m.Allocate()
|
s = m.Allocate(&ClientStrategy{})
|
||||||
if s.ID != 2 {
|
if s.ID != 2 {
|
||||||
t.Error("id: ", s.ID)
|
t.Error("id: ", s.ID)
|
||||||
}
|
}
|
||||||
@@ -39,13 +39,13 @@ func TestSessionManagerAdd(t *testing.T) {
|
|||||||
|
|
||||||
func TestSessionManagerClose(t *testing.T) {
|
func TestSessionManagerClose(t *testing.T) {
|
||||||
m := NewSessionManager()
|
m := NewSessionManager()
|
||||||
s := m.Allocate()
|
s := m.Allocate(&ClientStrategy{})
|
||||||
|
|
||||||
if m.CloseIfNoSession() {
|
if m.CloseIfNoSessionAndIdle(m.Size(), m.Count()) {
|
||||||
t.Error("able to close")
|
t.Error("able to close")
|
||||||
}
|
}
|
||||||
m.Remove(false, s.ID)
|
m.Remove(false, s.ID)
|
||||||
if !m.CloseIfNoSession() {
|
if !m.CloseIfNoSessionAndIdle(m.Size(), m.Count()) {
|
||||||
t.Error("not able to close")
|
t.Error("not able to close")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/common/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
|
"github.com/xtls/xray-core/common/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Writer struct {
|
type Writer struct {
|
||||||
@@ -16,9 +17,10 @@ type Writer struct {
|
|||||||
hasError bool
|
hasError bool
|
||||||
transferType protocol.TransferType
|
transferType protocol.TransferType
|
||||||
globalID [8]byte
|
globalID [8]byte
|
||||||
|
inbound *session.Inbound
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWriter(id uint16, dest net.Destination, writer buf.Writer, transferType protocol.TransferType, globalID [8]byte) *Writer {
|
func NewWriter(id uint16, dest net.Destination, writer buf.Writer, transferType protocol.TransferType, globalID [8]byte, inbound *session.Inbound) *Writer {
|
||||||
return &Writer{
|
return &Writer{
|
||||||
id: id,
|
id: id,
|
||||||
dest: dest,
|
dest: dest,
|
||||||
@@ -26,6 +28,7 @@ func NewWriter(id uint16, dest net.Destination, writer buf.Writer, transferType
|
|||||||
followup: false,
|
followup: false,
|
||||||
transferType: transferType,
|
transferType: transferType,
|
||||||
globalID: globalID,
|
globalID: globalID,
|
||||||
|
inbound: inbound,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +46,7 @@ func (w *Writer) getNextFrameMeta() FrameMetadata {
|
|||||||
SessionID: w.id,
|
SessionID: w.id,
|
||||||
Target: w.dest,
|
Target: w.dest,
|
||||||
GlobalID: w.globalID,
|
GlobalID: w.globalID,
|
||||||
|
Inbound: w.inbound,
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.followup {
|
if w.followup {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ var (
|
|||||||
|
|
||||||
type ListenConfig = net.ListenConfig
|
type ListenConfig = net.ListenConfig
|
||||||
|
|
||||||
|
type KeepAliveConfig = net.KeepAliveConfig
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Listen = net.Listen
|
Listen = net.Listen
|
||||||
ListenTCP = net.ListenTCP
|
ListenTCP = net.ListenTCP
|
||||||
@@ -26,6 +28,12 @@ var FileConn = net.FileConn
|
|||||||
// ParseIP is an alias of net.ParseIP
|
// ParseIP is an alias of net.ParseIP
|
||||||
var ParseIP = net.ParseIP
|
var ParseIP = net.ParseIP
|
||||||
|
|
||||||
|
var ParseCIDR = net.ParseCIDR
|
||||||
|
|
||||||
|
var ResolveIPAddr = net.ResolveIPAddr
|
||||||
|
|
||||||
|
var InterfaceByName = net.InterfaceByName
|
||||||
|
|
||||||
var SplitHostPort = net.SplitHostPort
|
var SplitHostPort = net.SplitHostPort
|
||||||
|
|
||||||
var CIDRMask = net.CIDRMask
|
var CIDRMask = net.CIDRMask
|
||||||
@@ -51,6 +59,8 @@ type (
|
|||||||
UnixConn = net.UnixConn
|
UnixConn = net.UnixConn
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type IPAddr = net.IPAddr
|
||||||
|
|
||||||
// IP is an alias for net.IP.
|
// IP is an alias for net.IP.
|
||||||
type (
|
type (
|
||||||
IP = net.IP
|
IP = net.IP
|
||||||
@@ -82,3 +92,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Resolver = net.Resolver
|
type Resolver = net.Resolver
|
||||||
|
|
||||||
|
var DefaultResolver = net.DefaultResolver
|
||||||
|
|
||||||
|
var JoinHostPort = net.JoinHostPort
|
||||||
|
|
||||||
|
var InterfaceAddrs = net.InterfaceAddrs
|
||||||
|
|
||||||
|
var Interfaces = net.Interfaces
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
//go:build !windows
|
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
package ctlcmd
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
func getSysProcAttr() *syscall.SysProcAttr {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
//go:build windows
|
|
||||||
// +build windows
|
|
||||||
|
|
||||||
package ctlcmd
|
|
||||||
|
|
||||||
import "syscall"
|
|
||||||
|
|
||||||
func getSysProcAttr() *syscall.SysProcAttr {
|
|
||||||
return &syscall.SysProcAttr{
|
|
||||||
HideWindow: true,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
package ctlcmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/buf"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/platform"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
|
|
||||||
xctl := platform.GetToolLocation("xctl")
|
|
||||||
if _, err := os.Stat(xctl); err != nil {
|
|
||||||
return nil, errors.New("xctl doesn't exist").Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var errBuffer buf.MultiBufferContainer
|
|
||||||
var outBuffer buf.MultiBufferContainer
|
|
||||||
|
|
||||||
cmd := exec.Command(xctl, args...)
|
|
||||||
cmd.Stderr = &errBuffer
|
|
||||||
cmd.Stdout = &outBuffer
|
|
||||||
cmd.SysProcAttr = getSysProcAttr()
|
|
||||||
if input != nil {
|
|
||||||
cmd.Stdin = input
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
|
||||||
return nil, errors.New("failed to start xctl").Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cmd.Wait(); err != nil {
|
|
||||||
msg := "failed to execute xctl"
|
|
||||||
if errBuffer.Len() > 0 {
|
|
||||||
msg += ": \n" + strings.TrimSpace(errBuffer.MultiBuffer.String())
|
|
||||||
}
|
|
||||||
return nil, errors.New(msg).Base(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// log stderr, info message
|
|
||||||
if !errBuffer.IsEmpty() {
|
|
||||||
errors.LogInfo(context.Background(), "<xctl message> \n", strings.TrimSpace(errBuffer.MultiBuffer.String()))
|
|
||||||
}
|
|
||||||
|
|
||||||
return outBuffer.MultiBuffer, nil
|
|
||||||
}
|
|
||||||
@@ -8,19 +8,10 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ExpandEnv(s string) string {
|
|
||||||
return os.ExpandEnv(s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LineSeparator() string {
|
func LineSeparator() string {
|
||||||
return "\n"
|
return "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetToolLocation(file string) string {
|
|
||||||
toolPath := NewEnvFlag(ToolLocation).GetValue(getExecutableDir)
|
|
||||||
return filepath.Join(toolPath, file)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAssetLocation searches for `file` in the env dir, the executable dir, and certain locations
|
// GetAssetLocation searches for `file` in the env dir, the executable dir, and certain locations
|
||||||
func GetAssetLocation(file string) string {
|
func GetAssetLocation(file string) string {
|
||||||
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
||||||
|
|||||||
@@ -8,10 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PluginLocation = "xray.location.plugin"
|
|
||||||
ConfigLocation = "xray.location.config"
|
ConfigLocation = "xray.location.config"
|
||||||
ConfdirLocation = "xray.location.confdir"
|
ConfdirLocation = "xray.location.confdir"
|
||||||
ToolLocation = "xray.location.tool"
|
|
||||||
AssetLocation = "xray.location.asset"
|
AssetLocation = "xray.location.asset"
|
||||||
CertLocation = "xray.location.cert"
|
CertLocation = "xray.location.cert"
|
||||||
|
|
||||||
@@ -79,17 +77,6 @@ func getExecutableDir() string {
|
|||||||
return filepath.Dir(exec)
|
return filepath.Dir(exec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getExecutableSubDir(dir string) func() string {
|
|
||||||
return func() string {
|
|
||||||
return filepath.Join(getExecutableDir(), dir)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetPluginDirectory() string {
|
|
||||||
pluginDir := NewEnvFlag(PluginLocation).GetValue(getExecutableSubDir("plugins"))
|
|
||||||
return pluginDir
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetConfigurationPath() string {
|
func GetConfigurationPath() string {
|
||||||
configPath := NewEnvFlag(ConfigLocation).GetValue(getExecutableDir)
|
configPath := NewEnvFlag(ConfigLocation).GetValue(getExecutableDir)
|
||||||
return filepath.Join(configPath, "config.json")
|
return filepath.Join(configPath, "config.json")
|
||||||
|
|||||||
@@ -5,20 +5,10 @@ package platform
|
|||||||
|
|
||||||
import "path/filepath"
|
import "path/filepath"
|
||||||
|
|
||||||
func ExpandEnv(s string) string {
|
|
||||||
// TODO
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func LineSeparator() string {
|
func LineSeparator() string {
|
||||||
return "\r\n"
|
return "\r\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetToolLocation(file string) string {
|
|
||||||
toolPath := NewEnvFlag(ToolLocation).GetValue(getExecutableDir)
|
|
||||||
return filepath.Join(toolPath, file+".exe")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAssetLocation searches for `file` in the env dir and the executable dir
|
// GetAssetLocation searches for `file` in the env dir and the executable dir
|
||||||
func GetAssetLocation(file string) string {
|
func GetAssetLocation(file string) string {
|
||||||
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
assetPath := NewEnvFlag(AssetLocation).GetValue(getExecutableDir)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common/bitmask"
|
"github.com/xtls/xray-core/common/bitmask"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"github.com/xtls/xray-core/common/uuid"
|
|
||||||
"golang.org/x/sys/cpu"
|
"golang.org/x/sys/cpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,11 +15,12 @@ const (
|
|||||||
RequestCommandTCP = RequestCommand(0x01)
|
RequestCommandTCP = RequestCommand(0x01)
|
||||||
RequestCommandUDP = RequestCommand(0x02)
|
RequestCommandUDP = RequestCommand(0x02)
|
||||||
RequestCommandMux = RequestCommand(0x03)
|
RequestCommandMux = RequestCommand(0x03)
|
||||||
|
RequestCommandRvs = RequestCommand(0x04)
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c RequestCommand) TransferType() TransferType {
|
func (c RequestCommand) TransferType() TransferType {
|
||||||
switch c {
|
switch c {
|
||||||
case RequestCommandTCP, RequestCommandMux:
|
case RequestCommandTCP, RequestCommandMux, RequestCommandRvs:
|
||||||
return TransferTypeStream
|
return TransferTypeStream
|
||||||
case RequestCommandUDP:
|
case RequestCommandUDP:
|
||||||
return TransferTypePacket
|
return TransferTypePacket
|
||||||
@@ -70,29 +70,19 @@ type ResponseHeader struct {
|
|||||||
Command ResponseCommand
|
Command ResponseCommand
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandSwitchAccount struct {
|
|
||||||
Host net.Address
|
|
||||||
Port net.Port
|
|
||||||
ID uuid.UUID
|
|
||||||
Level uint32
|
|
||||||
ValidMin byte
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ
|
// Keep in sync with crypto/tls/cipher_suites.go.
|
||||||
hasGCMAsmARM64 = cpu.ARM64.HasAES && cpu.ARM64.HasPMULL
|
hasGCMAsmAMD64 = cpu.X86.HasAES && cpu.X86.HasPCLMULQDQ && cpu.X86.HasSSE41 && cpu.X86.HasSSSE3
|
||||||
// Keep in sync with crypto/aes/cipher_s390x.go.
|
hasGCMAsmARM64 = (cpu.ARM64.HasAES && cpu.ARM64.HasPMULL) || (runtime.GOOS == "darwin" && runtime.GOARCH == "arm64")
|
||||||
hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCBC && cpu.S390X.HasAESCTR &&
|
hasGCMAsmS390X = cpu.S390X.HasAES && cpu.S390X.HasAESCTR && cpu.S390X.HasGHASH
|
||||||
(cpu.S390X.HasGHASH || cpu.S390X.HasAESGCM)
|
hasGCMAsmPPC64 = runtime.GOARCH == "ppc64" || runtime.GOARCH == "ppc64le"
|
||||||
|
|
||||||
hasAESGCMHardwareSupport = runtime.GOARCH == "amd64" && hasGCMAsmAMD64 ||
|
HasAESGCMHardwareSupport = hasGCMAsmAMD64 || hasGCMAsmARM64 || hasGCMAsmS390X || hasGCMAsmPPC64
|
||||||
runtime.GOARCH == "arm64" && hasGCMAsmARM64 ||
|
|
||||||
runtime.GOARCH == "s390x" && hasGCMAsmS390X
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (sc *SecurityConfig) GetSecurityType() SecurityType {
|
func (sc *SecurityConfig) GetSecurityType() SecurityType {
|
||||||
if sc == nil || sc.Type == SecurityType_AUTO {
|
if sc == nil || sc.Type == SecurityType_AUTO {
|
||||||
if hasAESGCMHardwareSupport {
|
if HasAESGCMHardwareSupport {
|
||||||
return SecurityType_AES128_GCM
|
return SecurityType_AES128_GCM
|
||||||
}
|
}
|
||||||
return SecurityType_CHACHA20_POLY1305
|
return SecurityType_CHACHA20_POLY1305
|
||||||
|
|||||||
@@ -1,89 +0,0 @@
|
|||||||
package protocol
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ServerList struct {
|
|
||||||
sync.RWMutex
|
|
||||||
servers []*ServerSpec
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewServerList() *ServerList {
|
|
||||||
return &ServerList{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sl *ServerList) AddServer(server *ServerSpec) {
|
|
||||||
sl.Lock()
|
|
||||||
defer sl.Unlock()
|
|
||||||
|
|
||||||
sl.servers = append(sl.servers, server)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sl *ServerList) Size() uint32 {
|
|
||||||
sl.RLock()
|
|
||||||
defer sl.RUnlock()
|
|
||||||
|
|
||||||
return uint32(len(sl.servers))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sl *ServerList) GetServer(idx uint32) *ServerSpec {
|
|
||||||
sl.Lock()
|
|
||||||
defer sl.Unlock()
|
|
||||||
|
|
||||||
for {
|
|
||||||
if idx >= uint32(len(sl.servers)) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
server := sl.servers[idx]
|
|
||||||
if !server.IsValid() {
|
|
||||||
sl.removeServer(idx)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return server
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (sl *ServerList) removeServer(idx uint32) {
|
|
||||||
n := len(sl.servers)
|
|
||||||
sl.servers[idx] = sl.servers[n-1]
|
|
||||||
sl.servers = sl.servers[:n-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerPicker interface {
|
|
||||||
PickServer() *ServerSpec
|
|
||||||
}
|
|
||||||
|
|
||||||
type RoundRobinServerPicker struct {
|
|
||||||
sync.Mutex
|
|
||||||
serverlist *ServerList
|
|
||||||
nextIndex uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRoundRobinServerPicker(serverlist *ServerList) *RoundRobinServerPicker {
|
|
||||||
return &RoundRobinServerPicker{
|
|
||||||
serverlist: serverlist,
|
|
||||||
nextIndex: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *RoundRobinServerPicker) PickServer() *ServerSpec {
|
|
||||||
p.Lock()
|
|
||||||
defer p.Unlock()
|
|
||||||
|
|
||||||
next := p.nextIndex
|
|
||||||
server := p.serverlist.GetServer(next)
|
|
||||||
if server == nil {
|
|
||||||
next = 0
|
|
||||||
server = p.serverlist.GetServer(0)
|
|
||||||
}
|
|
||||||
next++
|
|
||||||
if next >= p.serverlist.Size() {
|
|
||||||
next = 0
|
|
||||||
}
|
|
||||||
p.nextIndex = next
|
|
||||||
|
|
||||||
return server
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
package protocol_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
|
||||||
. "github.com/xtls/xray-core/common/protocol"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestServerList(t *testing.T) {
|
|
||||||
list := NewServerList()
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(1)), AlwaysValid()))
|
|
||||||
if list.Size() != 1 {
|
|
||||||
t.Error("list size: ", list.Size())
|
|
||||||
}
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
|
|
||||||
if list.Size() != 2 {
|
|
||||||
t.Error("list.size: ", list.Size())
|
|
||||||
}
|
|
||||||
|
|
||||||
server := list.GetServer(1)
|
|
||||||
if server.Destination().Port != 2 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
server = list.GetServer(1)
|
|
||||||
if server != nil {
|
|
||||||
t.Error("server: ", server)
|
|
||||||
}
|
|
||||||
|
|
||||||
server = list.GetServer(0)
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestServerPicker(t *testing.T) {
|
|
||||||
list := NewServerList()
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(1)), AlwaysValid()))
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(2)), BeforeTime(time.Now().Add(time.Second))))
|
|
||||||
list.AddServer(NewServerSpec(net.TCPDestination(net.LocalHostIP, net.Port(3)), BeforeTime(time.Now().Add(time.Second))))
|
|
||||||
|
|
||||||
picker := NewRoundRobinServerPicker(list)
|
|
||||||
server := picker.PickServer()
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 2 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 3 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
server = picker.PickServer()
|
|
||||||
if server.Destination().Port != 1 {
|
|
||||||
t.Error("server: ", server.Destination())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,122 +1,30 @@
|
|||||||
package protocol
|
package protocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/dice"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValidationStrategy interface {
|
|
||||||
IsValid() bool
|
|
||||||
Invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
type alwaysValidStrategy struct{}
|
|
||||||
|
|
||||||
func AlwaysValid() ValidationStrategy {
|
|
||||||
return alwaysValidStrategy{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (alwaysValidStrategy) IsValid() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (alwaysValidStrategy) Invalidate() {}
|
|
||||||
|
|
||||||
type timeoutValidStrategy struct {
|
|
||||||
until time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
func BeforeTime(t time.Time) ValidationStrategy {
|
|
||||||
return &timeoutValidStrategy{
|
|
||||||
until: t,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *timeoutValidStrategy) IsValid() bool {
|
|
||||||
return s.until.After(time.Now())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *timeoutValidStrategy) Invalidate() {
|
|
||||||
s.until = time.Time{}
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerSpec struct {
|
type ServerSpec struct {
|
||||||
sync.RWMutex
|
Destination net.Destination
|
||||||
dest net.Destination
|
User *MemoryUser
|
||||||
users []*MemoryUser
|
|
||||||
valid ValidationStrategy
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerSpec(dest net.Destination, valid ValidationStrategy, users ...*MemoryUser) *ServerSpec {
|
func NewServerSpec(dest net.Destination, user *MemoryUser) *ServerSpec {
|
||||||
return &ServerSpec{
|
return &ServerSpec{
|
||||||
dest: dest,
|
Destination: dest,
|
||||||
users: users,
|
User: user,
|
||||||
valid: valid,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerSpecFromPB(spec *ServerEndpoint) (*ServerSpec, error) {
|
func NewServerSpecFromPB(spec *ServerEndpoint) (*ServerSpec, error) {
|
||||||
dest := net.TCPDestination(spec.Address.AsAddress(), net.Port(spec.Port))
|
dest := net.TCPDestination(spec.Address.AsAddress(), net.Port(spec.Port))
|
||||||
mUsers := make([]*MemoryUser, len(spec.User))
|
var dUser *MemoryUser
|
||||||
for idx, u := range spec.User {
|
if spec.User != nil {
|
||||||
mUser, err := u.ToMemoryUser()
|
user, err := spec.User.ToMemoryUser()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
mUsers[idx] = mUser
|
dUser = user
|
||||||
}
|
}
|
||||||
return NewServerSpec(dest, AlwaysValid(), mUsers...), nil
|
return NewServerSpec(dest, dUser), nil
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) Destination() net.Destination {
|
|
||||||
return s.dest
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) HasUser(user *MemoryUser) bool {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
for _, u := range s.users {
|
|
||||||
if u.Account.Equals(user.Account) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) AddUser(user *MemoryUser) {
|
|
||||||
if s.HasUser(user) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Lock()
|
|
||||||
defer s.Unlock()
|
|
||||||
|
|
||||||
s.users = append(s.users, user)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) PickUser() *MemoryUser {
|
|
||||||
s.RLock()
|
|
||||||
defer s.RUnlock()
|
|
||||||
|
|
||||||
userCount := len(s.users)
|
|
||||||
switch userCount {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case 1:
|
|
||||||
return s.users[0]
|
|
||||||
default:
|
|
||||||
return s.users[dice.Roll(userCount)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) IsValid() bool {
|
|
||||||
return s.valid.IsValid()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ServerSpec) Invalidate() {
|
|
||||||
s.valid.Invalidate()
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user