mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-23 01:56:48 +08:00
Compare commits
1 Commits
main
...
5129c1e4ff
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5129c1e4ff |
29
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
29
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -7,8 +7,6 @@ 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.
|
||||||
@@ -40,8 +38,6 @@ 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.
|
||||||
@@ -50,29 +46,42 @@ 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
|
||||||
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
|
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.
|
||||||
```
|
Put the content between the preset ```<details><pre><code>``` ```</code></pre></details>``` in the text box.
|
||||||
<details><pre><code>
|
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.
|
||||||
(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,8 +7,6 @@ body:
|
|||||||
description: |-
|
description: |-
|
||||||
请勾选以下所有选项以证明您已经阅读并理解了以下要求,否则该 issue 将被关闭。
|
请勾选以下所有选项以证明您已经阅读并理解了以下要求,否则该 issue 将被关闭。
|
||||||
options:
|
options:
|
||||||
- label: 我读完了 issue 模板中的所有注释,确保填写符合要求。
|
|
||||||
required: true
|
|
||||||
- label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
|
- label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
|
||||||
required: true
|
required: true
|
||||||
- label: 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。
|
- label: 我提供了完整的配置文件和日志,而不是出于自己的判断只给出截取的部分。
|
||||||
@@ -40,8 +38,6 @@ body:
|
|||||||
### 对于配置文件
|
### 对于配置文件
|
||||||
请提供可以重现问题的配置文件,包括服务端和客户端。
|
请提供可以重现问题的配置文件,包括服务端和客户端。
|
||||||
不要直接在这里黏贴一大段导出的 config 文件。去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。
|
不要直接在这里黏贴一大段导出的 config 文件。去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。
|
||||||
在去掉不影响复现的部分后,提供实际运行的**完整**文件。
|
|
||||||
完整的含义:可以直接使用这个配置启动核心,**不是截取的部分配置**。对于密钥等参数使用重新生成未实际使用的有效参数填充。
|
|
||||||
|
|
||||||
### 对于日志
|
### 对于日志
|
||||||
请先将日志等级设置为 debug, dnsLog 设置为true.
|
请先将日志等级设置为 debug, dnsLog 设置为true.
|
||||||
@@ -50,29 +46,42 @@ body:
|
|||||||
提供 Xray-core 的日志,而不是面板或者别的东西输出的日志。
|
提供 Xray-core 的日志,而不是面板或者别的东西输出的日志。
|
||||||
|
|
||||||
### 最后
|
### 最后
|
||||||
把下面的每格具体内容需要放在 ```<details><pre><code>``` 和 ```</code></pre></details>``` 中间,如
|
在去掉不影响复现的部分后,提供实际运行的**完整**文件,不要出于自己的判断只提供入站出站或者几行日志。
|
||||||
```
|
把内容放在文本框预置的 ```<details><pre><code>``` 和 ```</code></pre></details>``` 中间。
|
||||||
<details><pre><code>
|
如果问题十分明确只出现在某一端(如按文档正确编写配置后核心启动失败/崩溃),可以在下面不需要的项目填入N/A.
|
||||||
(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
|
||||||
|
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -65,7 +65,7 @@ jobs:
|
|||||||
echo "LATEST=$LATEST" >>${GITHUB_ENV}
|
echo "LATEST=$LATEST" >>${GITHUB_ENV}
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3
|
uses: docker/setup-qemu-action@v3
|
||||||
|
6
.github/workflows/release-win7.yml
vendored
6
.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@v5
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Show workflow information
|
- name: Show workflow information
|
||||||
run: |
|
run: |
|
||||||
@@ -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 -gcflags="all=-l=4" -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 -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 -gcflags="all=-l=4" -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 -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
|
||||||
|
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
@@ -153,7 +153,7 @@ jobs:
|
|||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up NDK
|
- name: Set up NDK
|
||||||
if: matrix.goos == 'android'
|
if: matrix.goos == 'android'
|
||||||
@@ -190,19 +190,17 @@ 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 -gcflags="all=-l=4" -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 -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 -gcflags="all=-l=4" -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 -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 -gcflags="-l=4" -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 -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
|
||||||
|
|
||||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -45,7 +45,7 @@ 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@v5
|
uses: actions/checkout@v4
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
|
42
.gitignore
vendored
42
.gitignore
vendored
@@ -11,23 +11,21 @@
|
|||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
# macOS specific files
|
# Dependency directories (remove the comment below to include it)
|
||||||
.DS_Store
|
# vendor/
|
||||||
|
|
||||||
# IDE/editor specific files
|
# macOS specific files
|
||||||
|
*.DS_Store
|
||||||
|
|
||||||
|
# IDE specific files
|
||||||
.idea/
|
.idea/
|
||||||
.vscode/
|
.vscode/
|
||||||
*.swp
|
|
||||||
*.swo
|
|
||||||
|
|
||||||
# Archives and compressed files
|
# Archive files
|
||||||
*.zip
|
*.zip
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
*.tar
|
|
||||||
*.gz
|
|
||||||
*.bz2
|
|
||||||
|
|
||||||
# Go build binaries
|
# Binaries
|
||||||
xray
|
xray
|
||||||
xray_softfloat
|
xray_softfloat
|
||||||
mockgen
|
mockgen
|
||||||
@@ -38,31 +36,11 @@ errorgen
|
|||||||
*.dat
|
*.dat
|
||||||
|
|
||||||
# Build assets
|
# Build assets
|
||||||
/build_assets/
|
/build_assets
|
||||||
|
|
||||||
# Output from dlv test
|
# Output from dlv test
|
||||||
**/debug.*
|
**/debug.*
|
||||||
|
|
||||||
# Certificates and keys
|
# Certificates
|
||||||
*.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
|
|
||||||
|
@@ -165,13 +165,7 @@ 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 -gcflags="all=-l=4" -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 -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
|
||||||
|
@@ -42,15 +42,12 @@ func (r *IPRecord) getIPs() ([]net.IP, uint32, error) {
|
|||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, 0, errRecordNotFound
|
return nil, 0, errRecordNotFound
|
||||||
}
|
}
|
||||||
untilExpire := time.Until(r.Expire).Seconds()
|
untilExpire := time.Until(r.Expire)
|
||||||
if untilExpire <= 0 {
|
if untilExpire <= 0 {
|
||||||
return nil, 0, errRecordNotFound
|
return nil, 0, errRecordNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
ttl := uint32(untilExpire) + 1
|
ttl := uint32(untilExpire/time.Second) + uint32(1)
|
||||||
if ttl == 1 {
|
|
||||||
r.Expire = time.Now().Add(time.Second) // To ensure that two consecutive requests get the same result
|
|
||||||
}
|
|
||||||
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()))
|
p = append(p, common.Must2(ans.Pack()).([]byte))
|
||||||
|
|
||||||
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")),
|
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")),
|
common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")).(dns.RR),
|
||||||
common.Must2(dns.NewRR("google.com. IN A 8.8.8.8")),
|
common.Must2(dns.NewRR("google.com. IN A 8.8.8.8")).(dns.RR),
|
||||||
common.Must2(dns.NewRR("google.com. IN A 8.8.4.4")),
|
common.Must2(dns.NewRR("google.com. IN A 8.8.4.4")).(dns.RR),
|
||||||
)
|
)
|
||||||
p = append(p, common.Must2(ans.Pack()))
|
p = append(p, common.Must2(ans.Pack()).([]byte))
|
||||||
|
|
||||||
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")),
|
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")),
|
common.Must2(dns.NewRR("google.com. IN CNAME fake.google.com")).(dns.RR),
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")),
|
common.Must2(dns.NewRR("google.com. IN CNAME m.test.google.com")).(dns.RR),
|
||||||
common.Must2(dns.NewRR("google.com. IN CNAME test.google.com")),
|
common.Must2(dns.NewRR("google.com. IN CNAME test.google.com")).(dns.RR),
|
||||||
common.Must2(dns.NewRR("google.com. IN AAAA 2001::123:8888")),
|
common.Must2(dns.NewRR("google.com. IN AAAA 2001::123:8888")).(dns.RR),
|
||||||
common.Must2(dns.NewRR("google.com. IN AAAA 2001::123:8844")),
|
common.Must2(dns.NewRR("google.com. IN AAAA 2001::123:8844")).(dns.RR),
|
||||||
)
|
)
|
||||||
p = append(p, common.Must2(ans.Pack()))
|
p = append(p, common.Must2(ans.Pack()).([]byte))
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
|
@@ -449,12 +449,11 @@ 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() {
|
||||||
@@ -522,13 +521,6 @@ 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
|
||||||
@@ -787,7 +779,7 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
|||||||
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65,
|
0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65,
|
||||||
0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53,
|
0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53,
|
||||||
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f,
|
||||||
0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x9d, 0x03, 0x0a, 0x0c, 0x53, 0x65,
|
0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xcb, 0x02, 0x0a, 0x0c, 0x53, 0x65,
|
||||||
0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69,
|
0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69,
|
||||||
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f,
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f,
|
||||||
@@ -808,28 +800,23 @@ var file_app_proxyman_config_proto_rawDesc = []byte{
|
|||||||
0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69,
|
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,
|
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, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
||||||
0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x12, 0x50, 0x0a, 0x0f, 0x74, 0x61, 0x72, 0x67, 0x65,
|
0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74,
|
||||||
0x74, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e,
|
0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18,
|
||||||
0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
|
0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
|
||||||
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63,
|
||||||
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x74, 0x61, 0x72, 0x67, 0x65,
|
0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63,
|
||||||
0x74, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75,
|
0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75,
|
||||||
0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
|
0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20,
|
||||||
0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72,
|
||||||
0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f,
|
0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78,
|
||||||
0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52,
|
0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78,
|
||||||
0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f,
|
0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x42, 0x55,
|
||||||
0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18,
|
0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70,
|
||||||
0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75,
|
0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75,
|
||||||
0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72,
|
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d,
|
||||||
0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61,
|
||||||
0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33,
|
0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f,
|
||||||
0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70,
|
0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
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 (
|
||||||
@@ -863,7 +850,6 @@ var file_app_proxyman_config_proto_goTypes = []any{
|
|||||||
(*internet.StreamConfig)(nil), // 13: xray.transport.internet.StreamConfig
|
(*internet.StreamConfig)(nil), // 13: xray.transport.internet.StreamConfig
|
||||||
(*serial.TypedMessage)(nil), // 14: xray.common.serial.TypedMessage
|
(*serial.TypedMessage)(nil), // 14: xray.common.serial.TypedMessage
|
||||||
(*internet.ProxyConfig)(nil), // 15: xray.transport.internet.ProxyConfig
|
(*internet.ProxyConfig)(nil), // 15: xray.transport.internet.ProxyConfig
|
||||||
(internet.DomainStrategy)(0), // 16: xray.transport.internet.DomainStrategy
|
|
||||||
}
|
}
|
||||||
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
|
0, // 0: xray.app.proxyman.AllocationStrategy.type:type_name -> xray.app.proxyman.AllocationStrategy.Type
|
||||||
@@ -880,12 +866,11 @@ var file_app_proxyman_config_proto_depIdxs = []int32{
|
|||||||
13, // 11: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
13, // 11: xray.app.proxyman.SenderConfig.stream_settings:type_name -> xray.transport.internet.StreamConfig
|
||||||
15, // 12: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
15, // 12: xray.app.proxyman.SenderConfig.proxy_settings:type_name -> xray.transport.internet.ProxyConfig
|
||||||
8, // 13: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
8, // 13: xray.app.proxyman.SenderConfig.multiplex_settings:type_name -> xray.app.proxyman.MultiplexingConfig
|
||||||
16, // 14: xray.app.proxyman.SenderConfig.target_strategy:type_name -> xray.transport.internet.DomainStrategy
|
14, // [14:14] is the sub-list for method output_type
|
||||||
15, // [15:15] is the sub-list for method output_type
|
14, // [14:14] is the sub-list for method input_type
|
||||||
15, // [15:15] is the sub-list for method input_type
|
14, // [14:14] is the sub-list for extension type_name
|
||||||
15, // [15:15] is the sub-list for extension type_name
|
14, // [14:14] is the sub-list for extension extendee
|
||||||
15, // [15:15] is the sub-list for extension extendee
|
0, // [0:14] is the sub-list for field type_name
|
||||||
0, // [0:15] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_app_proxyman_config_proto_init() }
|
func init() { file_app_proxyman_config_proto_init() }
|
||||||
|
@@ -84,7 +84,6 @@ 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 {
|
||||||
|
@@ -322,18 +322,10 @@ 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
|
Local: net.DestinationFromAddr(w.hub.Addr()),
|
||||||
Gateway: net.UDPDestination(w.address, w.port),
|
Gateway: net.UDPDestination(w.address, w.port),
|
||||||
Tag: w.tag,
|
Tag: w.tag,
|
||||||
})
|
})
|
||||||
|
@@ -9,8 +9,6 @@ import (
|
|||||||
gonet "net"
|
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"
|
||||||
@@ -179,29 +177,6 @@ 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}
|
||||||
@@ -213,7 +188,6 @@ 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 {
|
||||||
@@ -256,6 +230,14 @@ out:
|
|||||||
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()
|
||||||
}
|
}
|
||||||
@@ -290,16 +272,49 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
|||||||
return h.getStatCouterConnection(conn), nil
|
return h.getStatCouterConnection(conn), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
errors.LogError(ctx, "failed to get outbound handler with tag: ", tag)
|
errors.LogWarning(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]
|
||||||
h.SetOutboundGateway(ctx, ob)
|
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.Conn != nil {
|
||||||
|
origin, _, err := net.SplitHostPort(inbound.Conn.LocalAddr().String())
|
||||||
|
if err == nil {
|
||||||
|
ob.Gateway = net.ParseAddress(origin)
|
||||||
|
errors.LogDebug(ctx, "use receive package ip as snedthrough: ", origin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case domain == "srcip":
|
||||||
|
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||||
|
if inbound.Conn != nil {
|
||||||
|
clientaddr, _, err := net.SplitHostPort(inbound.Conn.RemoteAddr().String())
|
||||||
|
if err == nil {
|
||||||
|
ob.Gateway = net.ParseAddress(clientaddr)
|
||||||
|
errors.LogDebug(ctx, "use client src ip as snedthrough: ", clientaddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//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 {
|
||||||
@@ -314,38 +329,6 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
|||||||
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{
|
||||||
|
@@ -44,7 +44,6 @@ type RoutingContext struct {
|
|||||||
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"`
|
LocalIPs [][]byte `protobuf:"bytes,13,rep,name=LocalIPs,proto3" json:"LocalIPs,omitempty"`
|
||||||
LocalPort uint32 `protobuf:"varint,14,opt,name=LocalPort,proto3" json:"LocalPort,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() {
|
||||||
@@ -175,13 +174,6 @@ func (x *RoutingContext) GetLocalPort() uint32 {
|
|||||||
return 0
|
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.
|
||||||
@@ -851,7 +843,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, 0xf6, 0x04, 0x0a, 0x0e, 0x52, 0x6f, 0x75,
|
0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd6, 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,
|
||||||
@@ -885,9 +877,7 @@ var file_app_router_command_command_proto_rawDesc = []byte{
|
|||||||
0x6c, 0x49, 0x50, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4c, 0x6f, 0x63, 0x61,
|
0x6c, 0x49, 0x50, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x08, 0x4c, 0x6f, 0x63, 0x61,
|
||||||
0x6c, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72,
|
0x6c, 0x49, 0x50, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72,
|
||||||
0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f,
|
0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f,
|
||||||
0x72, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75, 0x74, 0x65,
|
0x72, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
||||||
0x18, 0x0f, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x56, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f, 0x75,
|
|
||||||
0x74, 0x65, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73,
|
|
||||||
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
|
||||||
|
@@ -27,7 +27,6 @@ message RoutingContext {
|
|||||||
string OutboundTag = 12;
|
string OutboundTag = 12;
|
||||||
repeated bytes LocalIPs = 13;
|
repeated bytes LocalIPs = 13;
|
||||||
uint32 LocalPort = 14;
|
uint32 LocalPort = 14;
|
||||||
uint32 VlessRoute = 15;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
// SubscribeRoutingStatsRequest subscribes to routing statistics channel if
|
||||||
|
@@ -36,10 +36,6 @@ func (c routingContext) GetLocalPort() net.Port {
|
|||||||
return net.Port(c.RoutingContext.GetLocalPort())
|
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 ""
|
||||||
}
|
}
|
||||||
|
@@ -83,6 +83,21 @@ 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
|
||||||
}
|
}
|
||||||
@@ -166,8 +181,6 @@ func (v *PortMatcher) Apply(ctx routing.Context) bool {
|
|||||||
return v.port.Contains(ctx.GetSourcePort())
|
return v.port.Contains(ctx.GetSourcePort())
|
||||||
case "target":
|
case "target":
|
||||||
return v.port.Contains(ctx.GetTargetPort())
|
return v.port.Contains(ctx.GetTargetPort())
|
||||||
case "vlessRoute":
|
|
||||||
return v.port.Contains(ctx.GetVlessRoute())
|
|
||||||
default:
|
default:
|
||||||
panic("unreachable, asType should be local or source or target")
|
panic("unreachable, asType should be local or source or target")
|
||||||
}
|
}
|
||||||
|
@@ -328,6 +328,9 @@ 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)
|
||||||
|
|
||||||
@@ -359,9 +362,12 @@ func TestChinaSites(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
r := acMatcher.ApplyDomain(testCase.Domain)
|
r1 := matcher.ApplyDomain(testCase.Domain)
|
||||||
if r != testCase.Output {
|
r2 := acMatcher.ApplyDomain(testCase.Domain)
|
||||||
t.Error("ACDomainMatcher expected output ", testCase.Output, " for domain ", testCase.Domain, " but got ", r)
|
if r1 != testCase.Output {
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -408,6 +414,48 @@ 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
|
||||||
|
|
||||||
|
@@ -33,22 +33,29 @@ func (rr *RoutingRule) BuildCondition() (Condition, error) {
|
|||||||
conds := NewConditionChan()
|
conds := NewConditionChan()
|
||||||
|
|
||||||
if len(rr.Domain) > 0 {
|
if len(rr.Domain) > 0 {
|
||||||
matcher, err := NewMphMatcherGroup(rr.Domain)
|
switch rr.DomainMatcher {
|
||||||
if err != nil {
|
case "linear":
|
||||||
return nil, errors.New("failed to build domain condition with MphDomainMatcher").Base(err)
|
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)
|
||||||
}
|
}
|
||||||
errors.LogDebug(context.Background(), "MphDomainMatcher is enabled for ", len(rr.Domain), " domain rule(s)")
|
|
||||||
conds.Add(matcher)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rr.UserEmail) > 0 {
|
if len(rr.UserEmail) > 0 {
|
||||||
conds.Add(NewUserMatcher(rr.UserEmail))
|
conds.Add(NewUserMatcher(rr.UserEmail))
|
||||||
}
|
}
|
||||||
|
|
||||||
if rr.VlessRouteList != nil {
|
|
||||||
conds.Add(NewPortMatcher(rr.VlessRouteList, "vlessRoute"))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rr.InboundTag) > 0 {
|
if len(rr.InboundTag) > 0 {
|
||||||
conds.Add(NewInboundTagMatcher(rr.InboundTag))
|
conds.Add(NewInboundTagMatcher(rr.InboundTag))
|
||||||
}
|
}
|
||||||
|
@@ -470,7 +470,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,19,opt,name=rule_tag,json=ruleTag,proto3" json:"rule_tag,omitempty"`
|
RuleTag string `protobuf:"bytes,20,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,9 +491,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"`
|
||||||
LocalGeoip []*GeoIP `protobuf:"bytes,17,rep,name=local_geoip,json=localGeoip,proto3" json:"local_geoip,omitempty"`
|
DomainMatcher string `protobuf:"bytes,17,opt,name=domain_matcher,json=domainMatcher,proto3" json:"domain_matcher,omitempty"`
|
||||||
LocalPortList *net.PortList `protobuf:"bytes,18,opt,name=local_port_list,json=localPortList,proto3" json:"local_port_list,omitempty"`
|
LocalGeoip []*GeoIP `protobuf:"bytes,18,rep,name=local_geoip,json=localGeoip,proto3" json:"local_geoip,omitempty"`
|
||||||
VlessRouteList *net.PortList `protobuf:"bytes,20,opt,name=vless_route_list,json=vlessRouteList,proto3" json:"vless_route_list,omitempty"`
|
LocalPortList *net.PortList `protobuf:"bytes,19,opt,name=local_port_list,json=localPortList,proto3" json:"local_port_list,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) Reset() {
|
func (x *RoutingRule) Reset() {
|
||||||
@@ -624,6 +624,13 @@ func (x *RoutingRule) GetAttributes() map[string]string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *RoutingRule) GetDomainMatcher() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.DomainMatcher
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) GetLocalGeoip() []*GeoIP {
|
func (x *RoutingRule) GetLocalGeoip() []*GeoIP {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.LocalGeoip
|
return x.LocalGeoip
|
||||||
@@ -638,13 +645,6 @@ func (x *RoutingRule) GetLocalPortList() *net.PortList {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *RoutingRule) GetVlessRouteList() *net.PortList {
|
|
||||||
if x != nil {
|
|
||||||
return x.VlessRouteList
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type isRoutingRule_TargetTag interface {
|
type isRoutingRule_TargetTag interface {
|
||||||
isRoutingRule_TargetTag()
|
isRoutingRule_TargetTag()
|
||||||
}
|
}
|
||||||
@@ -1085,13 +1085,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, 0xe8, 0x06, 0x0a, 0x0b, 0x52, 0x6f,
|
0x74, 0x65, 0x52, 0x05, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0xca, 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, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, 0x75, 0x6c, 0x65, 0x54, 0x61, 0x67, 0x12,
|
0x18, 0x14, 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,
|
||||||
@@ -1123,79 +1123,77 @@ 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, 0x37, 0x0a, 0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f,
|
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
||||||
0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x11, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72,
|
0x5f, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d,
|
||||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65,
|
0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x37, 0x0a,
|
||||||
0x6f, 0x49, 0x50, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12,
|
0x0b, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x67, 0x65, 0x6f, 0x69, 0x70, 0x18, 0x12, 0x20, 0x03,
|
||||||
0x41, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69,
|
0x28, 0x0b, 0x32, 0x16, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||||
0x73, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
0x75, 0x74, 0x65, 0x72, 0x2e, 0x47, 0x65, 0x6f, 0x49, 0x50, 0x52, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c,
|
0x6c, 0x47, 0x65, 0x6f, 0x69, 0x70, 0x12, 0x41, 0x0a, 0x0f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f,
|
||||||
0x69, 0x73, 0x74, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69,
|
0x70, 0x6f, 0x72, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||||
0x73, 0x74, 0x12, 0x43, 0x0a, 0x10, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x5f, 0x72, 0x6f, 0x75, 0x74,
|
0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65,
|
||||||
0x65, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78,
|
0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0d, 0x6c, 0x6f, 0x63, 0x61,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x50,
|
0x6c, 0x50, 0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74,
|
||||||
0x6f, 0x72, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x0e, 0x76, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x6f,
|
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03,
|
||||||
0x75, 0x74, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x3d, 0x0a, 0x0f, 0x41, 0x74, 0x74, 0x72, 0x69,
|
0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14,
|
||||||
0x62, 0x75, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
|
0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76,
|
||||||
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
|
0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67,
|
||||||
0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
|
0x65, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e,
|
||||||
0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
|
0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18,
|
||||||
0x5f, 0x74, 0x61, 0x67, 0x22, 0xdc, 0x01, 0x0a, 0x0d, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69,
|
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75,
|
||||||
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20,
|
0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6f, 0x75, 0x74, 0x62,
|
0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53,
|
||||||
0x6f, 0x75, 0x6e, 0x64, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x02, 0x20,
|
0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||||
0x03, 0x28, 0x09, 0x52, 0x10, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x53, 0x65, 0x6c,
|
0x65, 0x67, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74,
|
||||||
0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
0x65, 0x67, 0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f,
|
||||||
0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20,
|
||||||
0x79, 0x12, 0x4d, 0x0a, 0x11, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x5f, 0x73, 0x65,
|
0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72,
|
||||||
0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78,
|
0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||||
0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61,
|
0x52, 0x10, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e,
|
||||||
0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x10,
|
0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x74,
|
||||||
0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73,
|
0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61,
|
||||||
0x12, 0x21, 0x0a, 0x0c, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x61, 0x67,
|
0x63, 0x6b, 0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x66, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b,
|
0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78,
|
||||||
0x54, 0x61, 0x67, 0x22, 0x54, 0x0a, 0x0e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57,
|
0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x12,
|
||||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x18,
|
0x14, 0x0a, 0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x67, 0x65, 0x78, 0x70, 0x12, 0x14, 0x0a,
|
0x6d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03,
|
||||||
0x05, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6d, 0x61,
|
0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x17,
|
||||||
0x74, 0x63, 0x68, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01,
|
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61,
|
||||||
0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0xc0, 0x01, 0x0a, 0x17, 0x53, 0x74,
|
0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73,
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x4c, 0x65, 0x61, 0x73, 0x74, 0x4c, 0x6f, 0x61, 0x64, 0x43,
|
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
||||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x35, 0x0a, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x18, 0x02,
|
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67,
|
||||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
0x79, 0x57, 0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c,
|
||||||
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x57,
|
0x0a, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28,
|
||||||
0x65, 0x69, 0x67, 0x68, 0x74, 0x52, 0x05, 0x63, 0x6f, 0x73, 0x74, 0x73, 0x12, 0x1c, 0x0a, 0x09,
|
0x03, 0x52, 0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08,
|
||||||
0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x03, 0x52,
|
0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
|
||||||
0x09, 0x62, 0x61, 0x73, 0x65, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78,
|
0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52,
|
||||||
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x65, 0x78,
|
0x54, 0x54, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54,
|
||||||
0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54,
|
0x12, 0x1c, 0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20,
|
||||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x6d, 0x61, 0x78, 0x52, 0x54, 0x54, 0x12, 0x1c,
|
0x01, 0x28, 0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x9b,
|
||||||
0x0a, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28,
|
0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d,
|
||||||
0x02, 0x52, 0x09, 0x74, 0x6f, 0x6c, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x9b, 0x02, 0x0a,
|
0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01,
|
||||||
0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4f, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69,
|
0x28, 0x0e, 0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
||||||
0x6e, 0x5f, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
|
0x75, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61,
|
||||||
0x32, 0x26, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74,
|
0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61,
|
||||||
0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75,
|
||||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e,
|
0x6c, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||||
0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x30, 0x0a, 0x04, 0x72, 0x75, 0x6c, 0x65,
|
0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69,
|
||||||
0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70,
|
0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e,
|
||||||
0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x67,
|
0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03,
|
||||||
0x52, 0x75, 0x6c, 0x65, 0x52, 0x04, 0x72, 0x75, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x0e, 0x62, 0x61,
|
0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||||
0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x03,
|
0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67,
|
||||||
0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f,
|
0x52, 0x75, 0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52,
|
||||||
0x75, 0x74, 0x65, 0x72, 0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75,
|
0x75, 0x6c, 0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72,
|
||||||
0x6c, 0x65, 0x52, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c,
|
0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12,
|
||||||
0x65, 0x22, 0x47, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74, 0x72, 0x61, 0x74,
|
0x09, 0x0a, 0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70,
|
||||||
0x65, 0x67, 0x79, 0x12, 0x08, 0x0a, 0x04, 0x41, 0x73, 0x49, 0x73, 0x10, 0x00, 0x12, 0x09, 0x0a,
|
0x49, 0x66, 0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a,
|
||||||
0x05, 0x55, 0x73, 0x65, 0x49, 0x70, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x70, 0x49, 0x66,
|
0x49, 0x70, 0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03, 0x42, 0x4f, 0x0a, 0x13,
|
||||||
0x4e, 0x6f, 0x6e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x70,
|
0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75,
|
||||||
0x4f, 0x6e, 0x44, 0x65, 0x6d, 0x61, 0x6e, 0x64, 0x10, 0x03, 0x42, 0x4f, 0x0a, 0x13, 0x63, 0x6f,
|
0x74, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||||
0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x72, 0x6f, 0x75, 0x74, 0x65,
|
0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65,
|
||||||
0x72, 0x50, 0x01, 0x5a, 0x24, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
0x2f, 0x61, 0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x0f, 0x58, 0x72,
|
||||||
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61,
|
0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70,
|
||||||
0x70, 0x70, 0x2f, 0x72, 0x6f, 0x75, 0x74, 0x65, 0x72, 0xaa, 0x02, 0x0f, 0x58, 0x72, 0x61, 0x79,
|
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x2e, 0x41, 0x70, 0x70, 0x2e, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -1248,17 +1246,16 @@ var file_app_router_config_proto_depIdxs = []int32{
|
|||||||
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
|
||||||
4, // 13: xray.app.router.RoutingRule.local_geoip:type_name -> xray.app.router.GeoIP
|
4, // 13: xray.app.router.RoutingRule.local_geoip:type_name -> xray.app.router.GeoIP
|
||||||
15, // 14: xray.app.router.RoutingRule.local_port_list:type_name -> xray.common.net.PortList
|
15, // 14: xray.app.router.RoutingRule.local_port_list:type_name -> xray.common.net.PortList
|
||||||
15, // 15: xray.app.router.RoutingRule.vless_route_list:type_name -> xray.common.net.PortList
|
17, // 15: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
|
||||||
17, // 16: xray.app.router.BalancingRule.strategy_settings:type_name -> xray.common.serial.TypedMessage
|
10, // 16: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
|
||||||
10, // 17: xray.app.router.StrategyLeastLoadConfig.costs:type_name -> xray.app.router.StrategyWeight
|
1, // 17: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
||||||
1, // 18: xray.app.router.Config.domain_strategy:type_name -> xray.app.router.Config.DomainStrategy
|
8, // 18: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
||||||
8, // 19: xray.app.router.Config.rule:type_name -> xray.app.router.RoutingRule
|
9, // 19: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
||||||
9, // 20: xray.app.router.Config.balancing_rule:type_name -> xray.app.router.BalancingRule
|
20, // [20:20] is the sub-list for method output_type
|
||||||
21, // [21:21] is the sub-list for method output_type
|
20, // [20:20] is the sub-list for method input_type
|
||||||
21, // [21:21] is the sub-list for method input_type
|
20, // [20:20] is the sub-list for extension type_name
|
||||||
21, // [21:21] is the sub-list for extension type_name
|
20, // [20:20] is the sub-list for extension extendee
|
||||||
21, // [21:21] is the sub-list for extension extendee
|
0, // [0:20] is the sub-list for field type_name
|
||||||
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 = 19;
|
string rule_tag = 20;
|
||||||
|
|
||||||
// List of domains for target domain matching.
|
// List of domains for target domain matching.
|
||||||
repeated Domain domain = 2;
|
repeated Domain domain = 2;
|
||||||
@@ -109,10 +109,10 @@ message RoutingRule {
|
|||||||
|
|
||||||
map<string, string> attributes = 15;
|
map<string, string> attributes = 15;
|
||||||
|
|
||||||
repeated GeoIP local_geoip = 17;
|
string domain_matcher = 17;
|
||||||
xray.common.net.PortList local_port_list = 18;
|
|
||||||
|
|
||||||
xray.common.net.PortList vless_route_list = 20;
|
repeated GeoIP local_geoip = 18;
|
||||||
|
xray.common.net.PortList local_port_list = 19;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BalancingRule {
|
message BalancingRule {
|
||||||
|
@@ -246,14 +246,6 @@ 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
|
||||||
|
@@ -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 curr.Len() > last.Available() {
|
if last.Len()+curr.Len() > Size {
|
||||||
mb2 = append(mb2, last)
|
mb2 = append(mb2, last)
|
||||||
last = curr
|
last = curr
|
||||||
} else {
|
} else {
|
||||||
|
@@ -175,29 +175,6 @@ 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)
|
||||||
|
@@ -23,9 +23,7 @@ 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.
|
||||||
// This is useful when function returned "sth, err" and avoid many "if err != nil"
|
func Must2(v interface{}, err error) interface{} {
|
||||||
// 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
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,9 @@ 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 := common.Must2(aes.NewCipher(key))
|
block, err := aes.NewCipher(key)
|
||||||
aead := common.Must2(cipher.NewGCM(block))
|
common.Must(err)
|
||||||
|
aead, err := cipher.NewGCM(block)
|
||||||
|
common.Must(err)
|
||||||
return aead
|
return aead
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,8 @@ package crypto_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -16,8 +18,11 @@ 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 := NewAesGcm(key)
|
aead, err := cipher.NewGCM(block)
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
const payloadSize = 1024 * 80
|
const payloadSize = 1024 * 80
|
||||||
rawPayload := make([]byte, payloadSize)
|
rawPayload := make([]byte, payloadSize)
|
||||||
@@ -66,7 +71,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)
|
||||||
}
|
}
|
||||||
@@ -75,8 +80,11 @@ 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 := NewAesGcm(key)
|
aead, err := cipher.NewGCM(block)
|
||||||
|
common.Must(err)
|
||||||
|
|
||||||
cache := buf.New()
|
cache := buf.New()
|
||||||
iv := make([]byte, 12)
|
iv := make([]byte, 12)
|
||||||
|
@@ -118,7 +118,9 @@ 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 {
|
||||||
ctx = session.SubContextFromMuxInbound(ctx)
|
// deep-clone outbounds because it is going to be mutated concurrently
|
||||||
|
// (Target and OriginalTarget)
|
||||||
|
ctx = session.ContextCloneOutboundsAndContent(ctx)
|
||||||
errors.LogInfo(ctx, "received request for ", meta.Target)
|
errors.LogInfo(ctx, "received request for ", meta.Target)
|
||||||
{
|
{
|
||||||
msg := &log.AccessMessage{
|
msg := &log.AccessMessage{
|
||||||
|
@@ -184,7 +184,8 @@ func getConfig() string {
|
|||||||
"inboundTag": [
|
"inboundTag": [
|
||||||
"api-in"
|
"api-in"
|
||||||
],
|
],
|
||||||
"outboundTag": "api"
|
"outboundTag": "api",
|
||||||
|
"type": "field"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"domainStrategy": "AsIs"
|
"domainStrategy": "AsIs"
|
||||||
|
@@ -16,15 +16,15 @@ const (
|
|||||||
inboundSessionKey ctx.SessionKey = 1
|
inboundSessionKey ctx.SessionKey = 1
|
||||||
outboundSessionKey ctx.SessionKey = 2
|
outboundSessionKey ctx.SessionKey = 2
|
||||||
contentSessionKey ctx.SessionKey = 3
|
contentSessionKey ctx.SessionKey = 3
|
||||||
muxPreferredSessionKey ctx.SessionKey = 4 // unused
|
muxPreferredSessionKey ctx.SessionKey = 4
|
||||||
sockoptSessionKey ctx.SessionKey = 5 // used by dokodemo to only receive sockopt.Mark
|
sockoptSessionKey ctx.SessionKey = 5
|
||||||
trackedConnectionErrorKey ctx.SessionKey = 6 // used by observer to get outbound error
|
trackedConnectionErrorKey ctx.SessionKey = 6
|
||||||
dispatcherKey ctx.SessionKey = 7 // used by ss2022 inbounds to get dispatcher
|
dispatcherKey ctx.SessionKey = 7
|
||||||
timeoutOnlyKey ctx.SessionKey = 8 // mux context's child contexts to only cancel when its own traffic times out
|
timeoutOnlyKey ctx.SessionKey = 8
|
||||||
allowedNetworkKey ctx.SessionKey = 9 // muxcool server control incoming request tcp/udp
|
allowedNetworkKey ctx.SessionKey = 9
|
||||||
handlerSessionKey ctx.SessionKey = 10 // unused
|
handlerSessionKey ctx.SessionKey = 10
|
||||||
mitmAlpn11Key ctx.SessionKey = 11 // used by TLS dialer
|
mitmAlpn11Key ctx.SessionKey = 11
|
||||||
mitmServerNameKey ctx.SessionKey = 12 // used by TLS dialer
|
mitmServerNameKey ctx.SessionKey = 12
|
||||||
)
|
)
|
||||||
|
|
||||||
func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
|
func ContextWithInbound(ctx context.Context, inbound *Inbound) context.Context {
|
||||||
@@ -42,8 +42,18 @@ func ContextWithOutbounds(ctx context.Context, outbounds []*Outbound) context.Co
|
|||||||
return context.WithValue(ctx, outboundSessionKey, outbounds)
|
return context.WithValue(ctx, outboundSessionKey, outbounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SubContextFromMuxInbound(ctx context.Context) context.Context {
|
func ContextCloneOutboundsAndContent(ctx context.Context) context.Context {
|
||||||
newOutbounds := []*Outbound{{}}
|
outbounds := OutboundsFromContext(ctx)
|
||||||
|
newOutbounds := make([]*Outbound, len(outbounds))
|
||||||
|
for i, ob := range outbounds {
|
||||||
|
if ob == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy outbound by value
|
||||||
|
v := *ob
|
||||||
|
newOutbounds[i] = &v
|
||||||
|
}
|
||||||
|
|
||||||
content := ContentFromContext(ctx)
|
content := ContentFromContext(ctx)
|
||||||
newContent := Content{}
|
newContent := Content{}
|
||||||
|
@@ -46,11 +46,9 @@ type Inbound struct {
|
|||||||
Name string
|
Name string
|
||||||
// User is the user that authenticates for the inbound. May be nil if the protocol allows anonymous traffic.
|
// User is the user that authenticates for the inbound. May be nil if the protocol allows anonymous traffic.
|
||||||
User *protocol.MemoryUser
|
User *protocol.MemoryUser
|
||||||
// VlessRoute is the user-sent VLESS UUID's 7th<<8 | 8th bytes.
|
// Conn is actually internet.Connection. May be nil.
|
||||||
VlessRoute net.Port
|
|
||||||
// Used by splice copy. Conn is actually internet.Connection. May be nil.
|
|
||||||
Conn net.Conn
|
Conn net.Conn
|
||||||
// Used by splice copy. Timer of the inbound buf copier. May be nil.
|
// Timer of the inbound buf copier. May be nil.
|
||||||
Timer *signal.ActivityTimer
|
Timer *signal.ActivityTimer
|
||||||
// CanSpliceCopy is a property for this connection
|
// CanSpliceCopy is a property for this connection
|
||||||
// 1 = can, 2 = after processing protocol info should be able to, 3 = cannot
|
// 1 = can, 2 = after processing protocol info should be able to, 3 = cannot
|
||||||
@@ -69,33 +67,31 @@ type Outbound struct {
|
|||||||
Tag string
|
Tag string
|
||||||
// Name of the outbound proxy that handles the connection.
|
// Name of the outbound proxy that handles the connection.
|
||||||
Name string
|
Name string
|
||||||
// Unused. Conn is actually internet.Connection. May be nil. It is currently nil for outbound with proxySettings
|
// Conn is actually internet.Connection. May be nil. It is currently nil for outbound with proxySettings
|
||||||
Conn net.Conn
|
Conn net.Conn
|
||||||
// CanSpliceCopy is a property for this connection
|
// CanSpliceCopy is a property for this connection
|
||||||
// 1 = can, 2 = after processing protocol info should be able to, 3 = cannot
|
// 1 = can, 2 = after processing protocol info should be able to, 3 = cannot
|
||||||
CanSpliceCopy int
|
CanSpliceCopy int
|
||||||
}
|
}
|
||||||
|
|
||||||
// SniffingRequest controls the behavior of content sniffing. They are from inbound config. Read-only
|
// SniffingRequest controls the behavior of content sniffing.
|
||||||
type SniffingRequest struct {
|
type SniffingRequest struct {
|
||||||
ExcludeForDomain []string
|
ExcludeForDomain []string // read-only once set
|
||||||
OverrideDestinationForProtocol []string
|
OverrideDestinationForProtocol []string // read-only once set
|
||||||
Enabled bool
|
Enabled bool
|
||||||
MetadataOnly bool
|
MetadataOnly bool
|
||||||
RouteOnly bool
|
RouteOnly bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content is the metadata of the connection content. Mainly used for routing.
|
// Content is the metadata of the connection content.
|
||||||
type Content struct {
|
type Content struct {
|
||||||
// Protocol of current content.
|
// Protocol of current content.
|
||||||
Protocol string
|
Protocol string
|
||||||
|
|
||||||
SniffingRequest SniffingRequest
|
SniffingRequest SniffingRequest
|
||||||
|
|
||||||
// HTTP traffic sniffed headers
|
|
||||||
Attributes map[string]string
|
Attributes map[string]string
|
||||||
|
|
||||||
// SkipDNSResolve is set from DNS module. the DOH remote server maybe a domain name, this prevents cycle resolving dead loop
|
|
||||||
SkipDNSResolve bool
|
SkipDNSResolve bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,9 +41,6 @@ type Context interface {
|
|||||||
// GetUser returns the user email from the connection content, if exists.
|
// GetUser returns the user email from the connection content, if exists.
|
||||||
GetUser() string
|
GetUser() string
|
||||||
|
|
||||||
// GetVlessRoute returns the user-sent VLESS UUID's 7th<<8 | 8th bytes, if exists.
|
|
||||||
GetVlessRoute() net.Port
|
|
||||||
|
|
||||||
// GetAttributes returns extra attributes from the conneciont content.
|
// GetAttributes returns extra attributes from the conneciont content.
|
||||||
GetAttributes() map[string]string
|
GetAttributes() map[string]string
|
||||||
|
|
||||||
|
@@ -128,14 +128,6 @@ func (ctx *Context) GetUser() string {
|
|||||||
return ctx.Inbound.User.Email
|
return ctx.Inbound.User.Email
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVlessRoute implements routing.Context.
|
|
||||||
func (ctx *Context) GetVlessRoute() net.Port {
|
|
||||||
if ctx.Inbound == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return ctx.Inbound.VlessRoute
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetAttributes implements routing.Context.
|
// GetAttributes implements routing.Context.
|
||||||
func (ctx *Context) GetAttributes() map[string]string {
|
func (ctx *Context) GetAttributes() map[string]string {
|
||||||
if ctx.Content == nil {
|
if ctx.Content == nil {
|
||||||
|
8
go.mod
8
go.mod
@@ -1,6 +1,6 @@
|
|||||||
module github.com/xtls/xray-core
|
module github.com/xtls/xray-core
|
||||||
|
|
||||||
go 1.25
|
go 1.24
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/cloudflare/circl v1.6.1
|
github.com/cloudflare/circl v1.6.1
|
||||||
@@ -26,8 +26,8 @@ require (
|
|||||||
golang.org/x/sync v0.16.0
|
golang.org/x/sync v0.16.0
|
||||||
golang.org/x/sys v0.35.0
|
golang.org/x/sys v0.35.0
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||||
google.golang.org/grpc v1.75.0
|
google.golang.org/grpc v1.74.2
|
||||||
google.golang.org/protobuf v1.36.8
|
google.golang.org/protobuf v1.36.7
|
||||||
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
gvisor.dev/gvisor v0.0.0-20250428193742-2d800c3129d5
|
||||||
h12.io/socks v1.0.3
|
h12.io/socks v1.0.3
|
||||||
lukechampine.com/blake3 v1.4.1
|
lukechampine.com/blake3 v1.4.1
|
||||||
@@ -52,7 +52,7 @@ require (
|
|||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.35.0 // indirect
|
golang.org/x/tools v0.35.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
34
go.sum
34
go.sum
@@ -80,16 +80,16 @@ github.com/xtls/reality v0.0.0-20250725142056-5b52a03d4fb7/go.mod h1:XxvnCCgBee4
|
|||||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ=
|
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||||
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I=
|
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||||
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE=
|
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||||
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E=
|
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI=
|
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||||
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg=
|
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps=
|
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
|
||||||
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4=
|
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
@@ -139,14 +139,12 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu
|
|||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173 h1:/jFs0duh4rdb8uIfPMv78iAJGcPKDeqAFnaLBropIC4=
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173/go.mod h1:tkCQ4FQXmpAgYVh++1cq16/dH4QJtmvpRv19DWGAHSA=
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY=
|
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||||
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
|
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
||||||
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
|
||||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
@@ -28,7 +28,9 @@ func (c *DNSOutboundConfig) Build() (proto.Message, error) {
|
|||||||
config.Server.Address = c.Address.Build()
|
config.Server.Address = c.Address.Build()
|
||||||
}
|
}
|
||||||
switch c.NonIPQuery {
|
switch c.NonIPQuery {
|
||||||
case "", "reject", "drop", "skip":
|
case "":
|
||||||
|
c.NonIPQuery = "drop"
|
||||||
|
case "drop", "skip", "reject":
|
||||||
default:
|
default:
|
||||||
return nil, errors.New(`unknown "nonIPQuery": `, c.NonIPQuery)
|
return nil, errors.New(`unknown "nonIPQuery": `, c.NonIPQuery)
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@ func TestDnsProxyConfig(t *testing.T) {
|
|||||||
Address: net.NewIPOrDomain(net.IPAddress([]byte{8, 8, 8, 8})),
|
Address: net.NewIPOrDomain(net.IPAddress([]byte{8, 8, 8, 8})),
|
||||||
Port: 53,
|
Port: 53,
|
||||||
},
|
},
|
||||||
|
Non_IPQuery: "drop",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@@ -11,11 +11,9 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
"github.com/xtls/xray-core/proxy/freedom"
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type FreedomConfig struct {
|
type FreedomConfig struct {
|
||||||
TargetStrategy string `json:"targetStrategy"`
|
|
||||||
DomainStrategy string `json:"domainStrategy"`
|
DomainStrategy string `json:"domainStrategy"`
|
||||||
Redirect string `json:"redirect"`
|
Redirect string `json:"redirect"`
|
||||||
UserLevel uint32 `json:"userLevel"`
|
UserLevel uint32 `json:"userLevel"`
|
||||||
@@ -42,35 +40,31 @@ type Noise struct {
|
|||||||
// Build implements Buildable
|
// Build implements Buildable
|
||||||
func (c *FreedomConfig) Build() (proto.Message, error) {
|
func (c *FreedomConfig) Build() (proto.Message, error) {
|
||||||
config := new(freedom.Config)
|
config := new(freedom.Config)
|
||||||
targetStrategy := c.TargetStrategy
|
switch strings.ToLower(c.DomainStrategy) {
|
||||||
if targetStrategy == "" {
|
|
||||||
targetStrategy = c.DomainStrategy
|
|
||||||
}
|
|
||||||
switch strings.ToLower(targetStrategy) {
|
|
||||||
case "asis", "":
|
case "asis", "":
|
||||||
config.DomainStrategy = internet.DomainStrategy_AS_IS
|
config.DomainStrategy = freedom.Config_AS_IS
|
||||||
case "useip":
|
case "useip":
|
||||||
config.DomainStrategy = internet.DomainStrategy_USE_IP
|
config.DomainStrategy = freedom.Config_USE_IP
|
||||||
case "useipv4":
|
case "useipv4":
|
||||||
config.DomainStrategy = internet.DomainStrategy_USE_IP4
|
config.DomainStrategy = freedom.Config_USE_IP4
|
||||||
case "useipv6":
|
case "useipv6":
|
||||||
config.DomainStrategy = internet.DomainStrategy_USE_IP6
|
config.DomainStrategy = freedom.Config_USE_IP6
|
||||||
case "useipv4v6":
|
case "useipv4v6":
|
||||||
config.DomainStrategy = internet.DomainStrategy_USE_IP46
|
config.DomainStrategy = freedom.Config_USE_IP46
|
||||||
case "useipv6v4":
|
case "useipv6v4":
|
||||||
config.DomainStrategy = internet.DomainStrategy_USE_IP64
|
config.DomainStrategy = freedom.Config_USE_IP64
|
||||||
case "forceip":
|
case "forceip":
|
||||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP
|
config.DomainStrategy = freedom.Config_FORCE_IP
|
||||||
case "forceipv4":
|
case "forceipv4":
|
||||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP4
|
config.DomainStrategy = freedom.Config_FORCE_IP4
|
||||||
case "forceipv6":
|
case "forceipv6":
|
||||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP6
|
config.DomainStrategy = freedom.Config_FORCE_IP6
|
||||||
case "forceipv4v6":
|
case "forceipv4v6":
|
||||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP46
|
config.DomainStrategy = freedom.Config_FORCE_IP46
|
||||||
case "forceipv6v4":
|
case "forceipv6v4":
|
||||||
config.DomainStrategy = internet.DomainStrategy_FORCE_IP64
|
config.DomainStrategy = freedom.Config_FORCE_IP64
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("unsupported domain strategy: ", targetStrategy)
|
return nil, errors.New("unsupported domain strategy: ", c.DomainStrategy)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.Fragment != nil {
|
if c.Fragment != nil {
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/protocol"
|
"github.com/xtls/xray-core/common/protocol"
|
||||||
. "github.com/xtls/xray-core/infra/conf"
|
. "github.com/xtls/xray-core/infra/conf"
|
||||||
"github.com/xtls/xray-core/proxy/freedom"
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFreedomConfig(t *testing.T) {
|
func TestFreedomConfig(t *testing.T) {
|
||||||
@@ -24,7 +23,7 @@ func TestFreedomConfig(t *testing.T) {
|
|||||||
}`,
|
}`,
|
||||||
Parser: loadJSON(creator),
|
Parser: loadJSON(creator),
|
||||||
Output: &freedom.Config{
|
Output: &freedom.Config{
|
||||||
DomainStrategy: internet.DomainStrategy_AS_IS,
|
DomainStrategy: freedom.Config_AS_IS,
|
||||||
DestinationOverride: &freedom.DestinationOverride{
|
DestinationOverride: &freedom.DestinationOverride{
|
||||||
Server: &protocol.ServerEndpoint{
|
Server: &protocol.ServerEndpoint{
|
||||||
Address: &net.IPOrDomain{
|
Address: &net.IPOrDomain{
|
||||||
|
@@ -74,6 +74,8 @@ type RouterConfig struct {
|
|||||||
RuleList []json.RawMessage `json:"rules"`
|
RuleList []json.RawMessage `json:"rules"`
|
||||||
DomainStrategy *string `json:"domainStrategy"`
|
DomainStrategy *string `json:"domainStrategy"`
|
||||||
Balancers []*BalancingRule `json:"balancers"`
|
Balancers []*BalancingRule `json:"balancers"`
|
||||||
|
|
||||||
|
DomainMatcher string `json:"domainMatcher"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RouterConfig) getDomainStrategy() router.Config_DomainStrategy {
|
func (c *RouterConfig) getDomainStrategy() router.Config_DomainStrategy {
|
||||||
@@ -109,6 +111,10 @@ func (c *RouterConfig) Build() (*router.Config, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rule.DomainMatcher == "" {
|
||||||
|
rule.DomainMatcher = c.DomainMatcher
|
||||||
|
}
|
||||||
|
|
||||||
config.Rule = append(config.Rule, rule)
|
config.Rule = append(config.Rule, rule)
|
||||||
}
|
}
|
||||||
for _, rawBalancer := range c.Balancers {
|
for _, rawBalancer := range c.Balancers {
|
||||||
@@ -123,8 +129,11 @@ func (c *RouterConfig) Build() (*router.Config, error) {
|
|||||||
|
|
||||||
type RouterRule struct {
|
type RouterRule struct {
|
||||||
RuleTag string `json:"ruleTag"`
|
RuleTag string `json:"ruleTag"`
|
||||||
|
Type string `json:"type"`
|
||||||
OutboundTag string `json:"outboundTag"`
|
OutboundTag string `json:"outboundTag"`
|
||||||
BalancerTag string `json:"balancerTag"`
|
BalancerTag string `json:"balancerTag"`
|
||||||
|
|
||||||
|
DomainMatcher string `json:"domainMatcher"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseIP(s string) (*router.CIDR, error) {
|
func ParseIP(s string) (*router.CIDR, error) {
|
||||||
@@ -531,7 +540,6 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
Source *StringList `json:"source"`
|
Source *StringList `json:"source"`
|
||||||
SourcePort *PortList `json:"sourcePort"`
|
SourcePort *PortList `json:"sourcePort"`
|
||||||
User *StringList `json:"user"`
|
User *StringList `json:"user"`
|
||||||
VlessRoute *PortList `json:"vlessRoute"`
|
|
||||||
InboundTag *StringList `json:"inboundTag"`
|
InboundTag *StringList `json:"inboundTag"`
|
||||||
Protocols *StringList `json:"protocol"`
|
Protocols *StringList `json:"protocol"`
|
||||||
Attributes map[string]string `json:"attrs"`
|
Attributes map[string]string `json:"attrs"`
|
||||||
@@ -559,6 +567,10 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
return nil, errors.New("neither outboundTag nor balancerTag is specified in routing rule")
|
return nil, errors.New("neither outboundTag nor balancerTag is specified in routing rule")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rawFieldRule.DomainMatcher != "" {
|
||||||
|
rule.DomainMatcher = rawFieldRule.DomainMatcher
|
||||||
|
}
|
||||||
|
|
||||||
if rawFieldRule.Domain != nil {
|
if rawFieldRule.Domain != nil {
|
||||||
for _, domain := range *rawFieldRule.Domain {
|
for _, domain := range *rawFieldRule.Domain {
|
||||||
rules, err := parseDomainRule(domain)
|
rules, err := parseDomainRule(domain)
|
||||||
@@ -629,10 +641,6 @@ func parseFieldRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rawFieldRule.VlessRoute != nil {
|
|
||||||
rule.VlessRouteList = rawFieldRule.VlessRoute.Build()
|
|
||||||
}
|
|
||||||
|
|
||||||
if rawFieldRule.InboundTag != nil {
|
if rawFieldRule.InboundTag != nil {
|
||||||
for _, s := range *rawFieldRule.InboundTag {
|
for _, s := range *rawFieldRule.InboundTag {
|
||||||
rule.InboundTag = append(rule.InboundTag, s)
|
rule.InboundTag = append(rule.InboundTag, s)
|
||||||
@@ -658,10 +666,12 @@ func ParseRule(msg json.RawMessage) (*router.RoutingRule, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("invalid router rule").Base(err)
|
return nil, errors.New("invalid router rule").Base(err)
|
||||||
}
|
}
|
||||||
|
if rawRule.Type == "" || strings.EqualFold(rawRule.Type, "field") {
|
||||||
fieldrule, err := parseFieldRule(msg)
|
fieldrule, err := parseFieldRule(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("invalid field rule").Base(err)
|
return nil, errors.New("invalid field rule").Base(err)
|
||||||
|
}
|
||||||
|
return fieldrule, nil
|
||||||
}
|
}
|
||||||
return fieldrule, nil
|
return nil, errors.New("unknown router rule type: ", rawRule.Type)
|
||||||
}
|
}
|
||||||
|
@@ -91,6 +91,7 @@ func TestRouterConfig(t *testing.T) {
|
|||||||
"domainStrategy": "AsIs",
|
"domainStrategy": "AsIs",
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
|
"type": "field",
|
||||||
"domain": [
|
"domain": [
|
||||||
"baidu.com",
|
"baidu.com",
|
||||||
"qq.com"
|
"qq.com"
|
||||||
@@ -98,15 +99,18 @@ func TestRouterConfig(t *testing.T) {
|
|||||||
"outboundTag": "direct"
|
"outboundTag": "direct"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"type": "field",
|
||||||
"ip": [
|
"ip": [
|
||||||
"10.0.0.0/8",
|
"10.0.0.0/8",
|
||||||
"::1/128"
|
"::1/128"
|
||||||
],
|
],
|
||||||
"outboundTag": "test"
|
"outboundTag": "test"
|
||||||
},{
|
},{
|
||||||
|
"type": "field",
|
||||||
"port": "53, 443, 1000-2000",
|
"port": "53, 443, 1000-2000",
|
||||||
"outboundTag": "test"
|
"outboundTag": "test"
|
||||||
},{
|
},{
|
||||||
|
"type": "field",
|
||||||
"port": 123,
|
"port": 123,
|
||||||
"outboundTag": "test"
|
"outboundTag": "test"
|
||||||
}
|
}
|
||||||
@@ -245,6 +249,7 @@ func TestRouterConfig(t *testing.T) {
|
|||||||
"domainStrategy": "IPIfNonMatch",
|
"domainStrategy": "IPIfNonMatch",
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
|
"type": "field",
|
||||||
"domain": [
|
"domain": [
|
||||||
"baidu.com",
|
"baidu.com",
|
||||||
"qq.com"
|
"qq.com"
|
||||||
@@ -252,6 +257,7 @@ func TestRouterConfig(t *testing.T) {
|
|||||||
"outboundTag": "direct"
|
"outboundTag": "direct"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"type": "field",
|
||||||
"ip": [
|
"ip": [
|
||||||
"10.0.0.0/8",
|
"10.0.0.0/8",
|
||||||
"::1/128"
|
"::1/128"
|
||||||
|
@@ -32,20 +32,12 @@ type VLessInboundConfig struct {
|
|||||||
Clients []json.RawMessage `json:"clients"`
|
Clients []json.RawMessage `json:"clients"`
|
||||||
Decryption string `json:"decryption"`
|
Decryption string `json:"decryption"`
|
||||||
Fallbacks []*VLessInboundFallback `json:"fallbacks"`
|
Fallbacks []*VLessInboundFallback `json:"fallbacks"`
|
||||||
Flow string `json:"flow"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build implements Buildable
|
// Build implements Buildable
|
||||||
func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
||||||
config := new(inbound.Config)
|
config := new(inbound.Config)
|
||||||
config.Clients = make([]*protocol.User, len(c.Clients))
|
config.Clients = make([]*protocol.User, len(c.Clients))
|
||||||
switch c.Flow {
|
|
||||||
case vless.None:
|
|
||||||
c.Flow = ""
|
|
||||||
case "", vless.XRV:
|
|
||||||
default:
|
|
||||||
return nil, errors.New(`VLESS "settings.flow" doesn't support "` + c.Flow + `" in this version`)
|
|
||||||
}
|
|
||||||
for idx, rawUser := range c.Clients {
|
for idx, rawUser := range c.Clients {
|
||||||
user := new(protocol.User)
|
user := new(protocol.User)
|
||||||
if err := json.Unmarshal(rawUser, user); err != nil {
|
if err := json.Unmarshal(rawUser, user); err != nil {
|
||||||
@@ -63,11 +55,7 @@ func (c *VLessInboundConfig) Build() (proto.Message, error) {
|
|||||||
account.Id = u.String()
|
account.Id = u.String()
|
||||||
|
|
||||||
switch account.Flow {
|
switch account.Flow {
|
||||||
case "":
|
case "", vless.XRV:
|
||||||
account.Flow = c.Flow
|
|
||||||
case vless.None:
|
|
||||||
account.Flow = ""
|
|
||||||
case vless.XRV:
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.New(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`)
|
return nil, errors.New(`VLESS clients: "flow" doesn't support "` + account.Flow + `" in this version`)
|
||||||
}
|
}
|
||||||
|
@@ -260,14 +260,13 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type OutboundDetourConfig struct {
|
type OutboundDetourConfig struct {
|
||||||
Protocol string `json:"protocol"`
|
Protocol string `json:"protocol"`
|
||||||
SendThrough *string `json:"sendThrough"`
|
SendThrough *string `json:"sendThrough"`
|
||||||
Tag string `json:"tag"`
|
Tag string `json:"tag"`
|
||||||
Settings *json.RawMessage `json:"settings"`
|
Settings *json.RawMessage `json:"settings"`
|
||||||
StreamSetting *StreamConfig `json:"streamSettings"`
|
StreamSetting *StreamConfig `json:"streamSettings"`
|
||||||
ProxySettings *ProxyConfig `json:"proxySettings"`
|
ProxySettings *ProxyConfig `json:"proxySettings"`
|
||||||
MuxSettings *MuxConfig `json:"mux"`
|
MuxSettings *MuxConfig `json:"mux"`
|
||||||
TargetStrategy string `json:"targetStrategy"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *OutboundDetourConfig) checkChainProxyConfig() error {
|
func (c *OutboundDetourConfig) checkChainProxyConfig() error {
|
||||||
@@ -283,32 +282,6 @@ func (c *OutboundDetourConfig) checkChainProxyConfig() error {
|
|||||||
// Build implements Buildable.
|
// Build implements Buildable.
|
||||||
func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) {
|
||||||
senderSettings := &proxyman.SenderConfig{}
|
senderSettings := &proxyman.SenderConfig{}
|
||||||
switch strings.ToLower(c.TargetStrategy) {
|
|
||||||
case "asis", "":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_AS_IS
|
|
||||||
case "useip":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_USE_IP
|
|
||||||
case "useipv4":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_USE_IP4
|
|
||||||
case "useipv6":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_USE_IP6
|
|
||||||
case "useipv4v6":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_USE_IP46
|
|
||||||
case "useipv6v4":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_USE_IP64
|
|
||||||
case "forceip":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_FORCE_IP
|
|
||||||
case "forceipv4":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_FORCE_IP4
|
|
||||||
case "forceipv6":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_FORCE_IP6
|
|
||||||
case "forceipv4v6":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_FORCE_IP46
|
|
||||||
case "forceipv6v4":
|
|
||||||
senderSettings.TargetStrategy = internet.DomainStrategy_FORCE_IP64
|
|
||||||
default:
|
|
||||||
return nil, errors.New("unsupported target domain strategy: ", c.TargetStrategy)
|
|
||||||
}
|
|
||||||
if err := c.checkChainProxyConfig(); err != nil {
|
if err := c.checkChainProxyConfig(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@@ -77,6 +77,7 @@ func TestXrayConfig(t *testing.T) {
|
|||||||
"ip": [
|
"ip": [
|
||||||
"10.0.0.0/8"
|
"10.0.0.0/8"
|
||||||
],
|
],
|
||||||
|
"type": "field",
|
||||||
"outboundTag": "blocked"
|
"outboundTag": "blocked"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@@ -93,6 +93,7 @@ func executeSourceIpBlock(cmd *base.Command, args []string) {
|
|||||||
"ruleTag" : "%s",
|
"ruleTag" : "%s",
|
||||||
"inboundTag": %s,
|
"inboundTag": %s,
|
||||||
"outboundTag": "%s",
|
"outboundTag": "%s",
|
||||||
|
"type": "field",
|
||||||
"source": %s
|
"source": %s
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@@ -6,7 +6,9 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/main/commands/base"
|
"github.com/xtls/xray-core/main/commands/base"
|
||||||
. "github.com/xtls/xray-core/transport/internet/tls"
|
. "github.com/xtls/xray-core/transport/internet/tls"
|
||||||
@@ -137,15 +139,14 @@ func printCertificates(certs []*x509.Certificate) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func printTLSConnDetail(tlsConn *gotls.Conn) {
|
func printTLSConnDetail(tlsConn *gotls.Conn) {
|
||||||
connectionState := tlsConn.ConnectionState()
|
|
||||||
var tlsVersion string
|
var tlsVersion string
|
||||||
if connectionState.Version == gotls.VersionTLS13 {
|
if tlsConn.ConnectionState().Version == gotls.VersionTLS13 {
|
||||||
tlsVersion = "TLS 1.3"
|
tlsVersion = "TLS 1.3"
|
||||||
} else if connectionState.Version == gotls.VersionTLS12 {
|
} else if tlsConn.ConnectionState().Version == gotls.VersionTLS12 {
|
||||||
tlsVersion = "TLS 1.2"
|
tlsVersion = "TLS 1.2"
|
||||||
}
|
}
|
||||||
fmt.Println("TLS Version: ", tlsVersion)
|
fmt.Println("TLS Version: ", tlsVersion)
|
||||||
curveID := connectionState.CurveID
|
curveID := *(*gotls.CurveID)(unsafe.Pointer(reflect.ValueOf(tlsConn).Elem().FieldByName("curveID").UnsafeAddr()))
|
||||||
if curveID != 0 {
|
if curveID != 0 {
|
||||||
PostQuantum := (curveID == gotls.X25519MLKEM768)
|
PostQuantum := (curveID == gotls.X25519MLKEM768)
|
||||||
fmt.Println("TLS Post-Quantum key exchange: ", PostQuantum, "("+curveID.String()+")")
|
fmt.Println("TLS Post-Quantum key exchange: ", PostQuantum, "("+curveID.String()+")")
|
||||||
|
@@ -65,9 +65,6 @@ func (h *Handler) Init(config *Config, dnsClient dns.Client, policyManager polic
|
|||||||
h.server = config.Server.AsDestination()
|
h.server = config.Server.AsDestination()
|
||||||
}
|
}
|
||||||
h.nonIPQuery = config.Non_IPQuery
|
h.nonIPQuery = config.Non_IPQuery
|
||||||
if h.nonIPQuery == "" {
|
|
||||||
h.nonIPQuery = "reject"
|
|
||||||
}
|
|
||||||
h.blockTypes = config.BlockTypes
|
h.blockTypes = config.BlockTypes
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -91,7 +91,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if dest.Port == 0 {
|
if dest.Port == 0 {
|
||||||
dest.Port = net.Port(common.Must2(strconv.Atoi(port)))
|
dest.Port = net.Port(common.Must2(strconv.Atoi(port)).(int))
|
||||||
}
|
}
|
||||||
if d.portMap != nil && d.portMap[port] != "" {
|
if d.portMap != nil && d.portMap[port] != "" {
|
||||||
h, p, _ := net.SplitHostPort(d.portMap[port])
|
h, p, _ := net.SplitHostPort(d.portMap[port])
|
||||||
@@ -99,7 +99,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
|
|||||||
dest.Address = net.ParseAddress(h)
|
dest.Address = net.ParseAddress(h)
|
||||||
}
|
}
|
||||||
if len(p) > 0 {
|
if len(p) > 0 {
|
||||||
dest.Port = net.Port(common.Must2(strconv.Atoi(p)))
|
dest.Port = net.Port(common.Must2(strconv.Atoi(p)).(int))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1 +1,44 @@
|
|||||||
package freedom
|
package freedom
|
||||||
|
|
||||||
|
var strategy = [][]byte{
|
||||||
|
// name strategy, prefer, fallback
|
||||||
|
{0, 0, 0}, // AsIs none, /, /
|
||||||
|
{1, 0, 0}, // UseIP use, both, none
|
||||||
|
{1, 4, 0}, // UseIPv4 use, 4, none
|
||||||
|
{1, 6, 0}, // UseIPv6 use, 6, none
|
||||||
|
{1, 4, 6}, // UseIPv4v6 use, 4, 6
|
||||||
|
{1, 6, 4}, // UseIPv6v4 use, 6, 4
|
||||||
|
{2, 0, 0}, // ForceIP force, both, none
|
||||||
|
{2, 4, 0}, // ForceIPv4 force, 4, none
|
||||||
|
{2, 6, 0}, // ForceIPv6 force, 6, none
|
||||||
|
{2, 4, 6}, // ForceIPv4v6 force, 4, 6
|
||||||
|
{2, 6, 4}, // ForceIPv6v4 force, 6, 4
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) hasStrategy() bool {
|
||||||
|
return strategy[c.DomainStrategy][0] != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) forceIP() bool {
|
||||||
|
return strategy[c.DomainStrategy][0] == 2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) preferIP4() bool {
|
||||||
|
return strategy[c.DomainStrategy][1] == 4 || strategy[c.DomainStrategy][1] == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) preferIP6() bool {
|
||||||
|
return strategy[c.DomainStrategy][1] == 6 || strategy[c.DomainStrategy][1] == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) hasFallback() bool {
|
||||||
|
return strategy[c.DomainStrategy][2] != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) fallbackIP4() bool {
|
||||||
|
return strategy[c.DomainStrategy][2] == 4
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) fallbackIP6() bool {
|
||||||
|
return strategy[c.DomainStrategy][2] == 6
|
||||||
|
}
|
||||||
|
@@ -8,7 +8,6 @@ package freedom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
protocol "github.com/xtls/xray-core/common/protocol"
|
protocol "github.com/xtls/xray-core/common/protocol"
|
||||||
internet "github.com/xtls/xray-core/transport/internet"
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
@@ -22,6 +21,79 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Config_DomainStrategy int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
Config_AS_IS Config_DomainStrategy = 0
|
||||||
|
Config_USE_IP Config_DomainStrategy = 1
|
||||||
|
Config_USE_IP4 Config_DomainStrategy = 2
|
||||||
|
Config_USE_IP6 Config_DomainStrategy = 3
|
||||||
|
Config_USE_IP46 Config_DomainStrategy = 4
|
||||||
|
Config_USE_IP64 Config_DomainStrategy = 5
|
||||||
|
Config_FORCE_IP Config_DomainStrategy = 6
|
||||||
|
Config_FORCE_IP4 Config_DomainStrategy = 7
|
||||||
|
Config_FORCE_IP6 Config_DomainStrategy = 8
|
||||||
|
Config_FORCE_IP46 Config_DomainStrategy = 9
|
||||||
|
Config_FORCE_IP64 Config_DomainStrategy = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
// Enum value maps for Config_DomainStrategy.
|
||||||
|
var (
|
||||||
|
Config_DomainStrategy_name = map[int32]string{
|
||||||
|
0: "AS_IS",
|
||||||
|
1: "USE_IP",
|
||||||
|
2: "USE_IP4",
|
||||||
|
3: "USE_IP6",
|
||||||
|
4: "USE_IP46",
|
||||||
|
5: "USE_IP64",
|
||||||
|
6: "FORCE_IP",
|
||||||
|
7: "FORCE_IP4",
|
||||||
|
8: "FORCE_IP6",
|
||||||
|
9: "FORCE_IP46",
|
||||||
|
10: "FORCE_IP64",
|
||||||
|
}
|
||||||
|
Config_DomainStrategy_value = map[string]int32{
|
||||||
|
"AS_IS": 0,
|
||||||
|
"USE_IP": 1,
|
||||||
|
"USE_IP4": 2,
|
||||||
|
"USE_IP6": 3,
|
||||||
|
"USE_IP46": 4,
|
||||||
|
"USE_IP64": 5,
|
||||||
|
"FORCE_IP": 6,
|
||||||
|
"FORCE_IP4": 7,
|
||||||
|
"FORCE_IP6": 8,
|
||||||
|
"FORCE_IP46": 9,
|
||||||
|
"FORCE_IP64": 10,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (x Config_DomainStrategy) Enum() *Config_DomainStrategy {
|
||||||
|
p := new(Config_DomainStrategy)
|
||||||
|
*p = x
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Config_DomainStrategy) String() string {
|
||||||
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Config_DomainStrategy) Descriptor() protoreflect.EnumDescriptor {
|
||||||
|
return file_proxy_freedom_config_proto_enumTypes[0].Descriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (Config_DomainStrategy) Type() protoreflect.EnumType {
|
||||||
|
return &file_proxy_freedom_config_proto_enumTypes[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x Config_DomainStrategy) Number() protoreflect.EnumNumber {
|
||||||
|
return protoreflect.EnumNumber(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deprecated: Use Config_DomainStrategy.Descriptor instead.
|
||||||
|
func (Config_DomainStrategy) EnumDescriptor() ([]byte, []int) {
|
||||||
|
return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3, 0}
|
||||||
|
}
|
||||||
|
|
||||||
type DestinationOverride struct {
|
type DestinationOverride struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@@ -258,12 +330,12 @@ type Config struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
DomainStrategy internet.DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.transport.internet.DomainStrategy" json:"domain_strategy,omitempty"`
|
DomainStrategy Config_DomainStrategy `protobuf:"varint,1,opt,name=domain_strategy,json=domainStrategy,proto3,enum=xray.proxy.freedom.Config_DomainStrategy" json:"domain_strategy,omitempty"`
|
||||||
DestinationOverride *DestinationOverride `protobuf:"bytes,3,opt,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
DestinationOverride *DestinationOverride `protobuf:"bytes,3,opt,name=destination_override,json=destinationOverride,proto3" json:"destination_override,omitempty"`
|
||||||
UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"`
|
UserLevel uint32 `protobuf:"varint,4,opt,name=user_level,json=userLevel,proto3" json:"user_level,omitempty"`
|
||||||
Fragment *Fragment `protobuf:"bytes,5,opt,name=fragment,proto3" json:"fragment,omitempty"`
|
Fragment *Fragment `protobuf:"bytes,5,opt,name=fragment,proto3" json:"fragment,omitempty"`
|
||||||
ProxyProtocol uint32 `protobuf:"varint,6,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"`
|
ProxyProtocol uint32 `protobuf:"varint,6,opt,name=proxy_protocol,json=proxyProtocol,proto3" json:"proxy_protocol,omitempty"`
|
||||||
Noises []*Noise `protobuf:"bytes,7,rep,name=noises,proto3" json:"noises,omitempty"`
|
Noises []*Noise `protobuf:"bytes,7,rep,name=noises,proto3" json:"noises,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) Reset() {
|
func (x *Config) Reset() {
|
||||||
@@ -296,11 +368,11 @@ func (*Config) Descriptor() ([]byte, []int) {
|
|||||||
return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3}
|
return file_proxy_freedom_config_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetDomainStrategy() internet.DomainStrategy {
|
func (x *Config) GetDomainStrategy() Config_DomainStrategy {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.DomainStrategy
|
return x.DomainStrategy
|
||||||
}
|
}
|
||||||
return internet.DomainStrategy(0)
|
return Config_AS_IS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Config) GetDestinationOverride() *DestinationOverride {
|
func (x *Config) GetDestinationOverride() *DestinationOverride {
|
||||||
@@ -346,72 +418,81 @@ var file_proxy_freedom_config_proto_rawDesc = []byte{
|
|||||||
0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d,
|
0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d,
|
||||||
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||||
0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72,
|
0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72,
|
||||||
0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69,
|
0x6f, 0x74, 0x6f, 0x22, 0x53, 0x0a, 0x13, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69,
|
||||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70,
|
0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x73, 0x65,
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x22, 0x53, 0x0a, 0x13, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74,
|
0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72, 0x61,
|
||||||
0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x73,
|
0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
|
||||||
0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x78, 0x72,
|
0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
|
||||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x02, 0x0a, 0x08, 0x46, 0x72, 0x61,
|
||||||
0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
|
0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73,
|
||||||
0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x22, 0x98, 0x02, 0x0a, 0x08, 0x46, 0x72,
|
0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61, 0x63,
|
||||||
0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
|
0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63, 0x6b,
|
||||||
0x73, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x70, 0x61,
|
0x65, 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70, 0x61,
|
||||||
0x63, 0x6b, 0x65, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x63,
|
0x63, 0x6b, 0x65, 0x74, 0x73, 0x54, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74,
|
||||||
0x6b, 0x65, 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x70,
|
0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e,
|
||||||
0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x54, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67,
|
0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68,
|
||||||
0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65,
|
0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67,
|
||||||
0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74,
|
0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61,
|
||||||
0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e,
|
0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e, 0x74,
|
||||||
0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76,
|
0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74, 0x65,
|
||||||
0x61, 0x6c, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x69, 0x6e,
|
0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b,
|
||||||
0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x69, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x74,
|
0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x12, 0x22, 0x0a, 0x0d, 0x6d,
|
||||||
0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52,
|
0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x07, 0x20, 0x01,
|
||||||
0x0b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x61, 0x78, 0x12, 0x22, 0x0a, 0x0d,
|
0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x69, 0x6e, 0x12,
|
||||||
0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x07, 0x20,
|
0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x61, 0x78,
|
||||||
0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x69, 0x6e,
|
0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69, 0x74,
|
||||||
0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x5f, 0x6d, 0x61,
|
0x4d, 0x61, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x05, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d, 0x0a,
|
||||||
0x78, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d, 0x61, 0x78, 0x53, 0x70, 0x6c, 0x69,
|
0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x74, 0x4d, 0x61, 0x78, 0x22, 0xb2, 0x01, 0x0a, 0x05, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x12, 0x1d,
|
0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a, 0x0a,
|
||||||
0x0a, 0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01,
|
0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
|
||||||
0x28, 0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x69, 0x6e, 0x12, 0x1d, 0x0a,
|
0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x64,
|
||||||
0x0a, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
|
0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
|
||||||
0x04, 0x52, 0x09, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x4d, 0x61, 0x78, 0x12, 0x1b, 0x0a, 0x09,
|
0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x61,
|
||||||
0x64, 0x65, 0x6c, 0x61, 0x79, 0x5f, 0x6d, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52,
|
0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65, 0x6c,
|
||||||
0x08, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x4d, 0x69, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x65, 0x6c,
|
0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x18,
|
||||||
0x61, 0x79, 0x5f, 0x6d, 0x61, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x65,
|
0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19, 0x0a,
|
||||||
0x6c, 0x61, 0x79, 0x4d, 0x61, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
|
0x08, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x12, 0x19,
|
0x07, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x22, 0x97, 0x04, 0x0a, 0x06, 0x43, 0x6f, 0x6e,
|
||||||
0x0a, 0x08, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x5f, 0x74, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
|
0x66, 0x69, 0x67, 0x12, 0x52, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73, 0x74,
|
||||||
0x52, 0x07, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x54, 0x6f, 0x22, 0xe9, 0x02, 0x0a, 0x06, 0x43, 0x6f,
|
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x78,
|
||||||
0x6e, 0x66, 0x69, 0x67, 0x12, 0x50, 0x0a, 0x0f, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x5f, 0x73,
|
0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f,
|
||||||
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e,
|
0x6d, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
||||||
0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53,
|
||||||
0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x44, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
|
0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69,
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x52, 0x0e, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x53, 0x74,
|
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18,
|
||||||
0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x5a, 0x0a, 0x14, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e,
|
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x03,
|
0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13,
|
||||||
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e,
|
0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72,
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x52, 0x13, 0x64,
|
0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65,
|
||||||
0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69,
|
0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76,
|
||||||
0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c,
|
0x65, 0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05,
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x65, 0x76, 0x65,
|
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78,
|
||||||
0x6c, 0x12, 0x38, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20,
|
0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65,
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
0x6e, 0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e,
|
||||||
0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x46, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e,
|
0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06,
|
||||||
0x74, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x70,
|
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x06, 0x20,
|
0x63, 0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20,
|
||||||
0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
|
0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||||
0x6f, 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x18, 0x07, 0x20, 0x03,
|
0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06,
|
||||||
0x28, 0x0b, 0x32, 0x19, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e,
|
0x6e, 0x6f, 0x69, 0x73, 0x65, 0x73, 0x22, 0xa9, 0x01, 0x0a, 0x0e, 0x44, 0x6f, 0x6d, 0x61, 0x69,
|
||||||
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x2e, 0x4e, 0x6f, 0x69, 0x73, 0x65, 0x52, 0x06, 0x6e,
|
0x6e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x53, 0x5f,
|
||||||
0x6f, 0x69, 0x73, 0x65, 0x73, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61,
|
0x49, 0x53, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x10, 0x01,
|
||||||
0x79, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50,
|
0x12, 0x0b, 0x0a, 0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x10, 0x02, 0x12, 0x0b, 0x0a,
|
||||||
0x01, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74,
|
0x07, 0x55, 0x53, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53,
|
||||||
0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f,
|
0x45, 0x5f, 0x49, 0x50, 0x34, 0x36, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x55, 0x53, 0x45, 0x5f,
|
||||||
0x78, 0x79, 0x2f, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61,
|
0x49, 0x50, 0x36, 0x34, 0x10, 0x05, 0x12, 0x0c, 0x0a, 0x08, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f,
|
||||||
0x79, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62,
|
0x49, 0x50, 0x10, 0x06, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50,
|
||||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x34, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36,
|
||||||
|
0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x34, 0x36,
|
||||||
|
0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x49, 0x50, 0x36, 0x34,
|
||||||
|
0x10, 0x0a, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x70,
|
||||||
|
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x50, 0x01, 0x5a, 0x27,
|
||||||
|
0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f,
|
||||||
|
0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f,
|
||||||
|
0x66, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x50,
|
||||||
|
0x72, 0x6f, 0x78, 0x79, 0x2e, 0x46, 0x72, 0x65, 0x65, 0x64, 0x6f, 0x6d, 0x62, 0x06, 0x70, 0x72,
|
||||||
|
0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -426,21 +507,22 @@ func file_proxy_freedom_config_proto_rawDescGZIP() []byte {
|
|||||||
return file_proxy_freedom_config_proto_rawDescData
|
return file_proxy_freedom_config_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var file_proxy_freedom_config_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
var file_proxy_freedom_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
var file_proxy_freedom_config_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||||
var file_proxy_freedom_config_proto_goTypes = []any{
|
var file_proxy_freedom_config_proto_goTypes = []any{
|
||||||
(*DestinationOverride)(nil), // 0: xray.proxy.freedom.DestinationOverride
|
(Config_DomainStrategy)(0), // 0: xray.proxy.freedom.Config.DomainStrategy
|
||||||
(*Fragment)(nil), // 1: xray.proxy.freedom.Fragment
|
(*DestinationOverride)(nil), // 1: xray.proxy.freedom.DestinationOverride
|
||||||
(*Noise)(nil), // 2: xray.proxy.freedom.Noise
|
(*Fragment)(nil), // 2: xray.proxy.freedom.Fragment
|
||||||
(*Config)(nil), // 3: xray.proxy.freedom.Config
|
(*Noise)(nil), // 3: xray.proxy.freedom.Noise
|
||||||
(*protocol.ServerEndpoint)(nil), // 4: xray.common.protocol.ServerEndpoint
|
(*Config)(nil), // 4: xray.proxy.freedom.Config
|
||||||
(internet.DomainStrategy)(0), // 5: xray.transport.internet.DomainStrategy
|
(*protocol.ServerEndpoint)(nil), // 5: xray.common.protocol.ServerEndpoint
|
||||||
}
|
}
|
||||||
var file_proxy_freedom_config_proto_depIdxs = []int32{
|
var file_proxy_freedom_config_proto_depIdxs = []int32{
|
||||||
4, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
|
5, // 0: xray.proxy.freedom.DestinationOverride.server:type_name -> xray.common.protocol.ServerEndpoint
|
||||||
5, // 1: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.transport.internet.DomainStrategy
|
0, // 1: xray.proxy.freedom.Config.domain_strategy:type_name -> xray.proxy.freedom.Config.DomainStrategy
|
||||||
0, // 2: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
1, // 2: xray.proxy.freedom.Config.destination_override:type_name -> xray.proxy.freedom.DestinationOverride
|
||||||
1, // 3: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
2, // 3: xray.proxy.freedom.Config.fragment:type_name -> xray.proxy.freedom.Fragment
|
||||||
2, // 4: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
3, // 4: xray.proxy.freedom.Config.noises:type_name -> xray.proxy.freedom.Noise
|
||||||
5, // [5:5] is the sub-list for method output_type
|
5, // [5:5] is the sub-list for method output_type
|
||||||
5, // [5:5] is the sub-list for method input_type
|
5, // [5:5] is the sub-list for method input_type
|
||||||
5, // [5:5] is the sub-list for extension type_name
|
5, // [5:5] is the sub-list for extension type_name
|
||||||
@@ -458,13 +540,14 @@ func file_proxy_freedom_config_proto_init() {
|
|||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_proxy_freedom_config_proto_rawDesc,
|
RawDescriptor: file_proxy_freedom_config_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 1,
|
||||||
NumMessages: 4,
|
NumMessages: 4,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
GoTypes: file_proxy_freedom_config_proto_goTypes,
|
GoTypes: file_proxy_freedom_config_proto_goTypes,
|
||||||
DependencyIndexes: file_proxy_freedom_config_proto_depIdxs,
|
DependencyIndexes: file_proxy_freedom_config_proto_depIdxs,
|
||||||
|
EnumInfos: file_proxy_freedom_config_proto_enumTypes,
|
||||||
MessageInfos: file_proxy_freedom_config_proto_msgTypes,
|
MessageInfos: file_proxy_freedom_config_proto_msgTypes,
|
||||||
}.Build()
|
}.Build()
|
||||||
File_proxy_freedom_config_proto = out.File
|
File_proxy_freedom_config_proto = out.File
|
||||||
|
@@ -7,7 +7,6 @@ option java_package = "com.xray.proxy.freedom";
|
|||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
|
|
||||||
import "common/protocol/server_spec.proto";
|
import "common/protocol/server_spec.proto";
|
||||||
import "transport/internet/config.proto";
|
|
||||||
|
|
||||||
message DestinationOverride {
|
message DestinationOverride {
|
||||||
xray.common.protocol.ServerEndpoint server = 1;
|
xray.common.protocol.ServerEndpoint server = 1;
|
||||||
@@ -33,7 +32,20 @@ message Noise {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message Config {
|
message Config {
|
||||||
xray.transport.internet.DomainStrategy domain_strategy = 1;
|
enum DomainStrategy {
|
||||||
|
AS_IS = 0;
|
||||||
|
USE_IP = 1;
|
||||||
|
USE_IP4 = 2;
|
||||||
|
USE_IP6 = 3;
|
||||||
|
USE_IP46 = 4;
|
||||||
|
USE_IP64 = 5;
|
||||||
|
FORCE_IP = 6;
|
||||||
|
FORCE_IP4 = 7;
|
||||||
|
FORCE_IP6 = 8;
|
||||||
|
FORCE_IP46 = 9;
|
||||||
|
FORCE_IP64 = 10;
|
||||||
|
}
|
||||||
|
DomainStrategy domain_strategy = 1;
|
||||||
DestinationOverride destination_override = 3;
|
DestinationOverride destination_override = 3;
|
||||||
uint32 user_level = 4;
|
uint32 user_level = 4;
|
||||||
Fragment fragment = 5;
|
Fragment fragment = 5;
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"github.com/xtls/xray-core/common/task"
|
"github.com/xtls/xray-core/common/task"
|
||||||
"github.com/xtls/xray-core/common/utils"
|
"github.com/xtls/xray-core/common/utils"
|
||||||
"github.com/xtls/xray-core/core"
|
"github.com/xtls/xray-core/core"
|
||||||
|
"github.com/xtls/xray-core/features/dns"
|
||||||
"github.com/xtls/xray-core/features/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"
|
||||||
@@ -34,8 +35,8 @@ var useSplice bool
|
|||||||
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) {
|
||||||
h := new(Handler)
|
h := new(Handler)
|
||||||
if err := core.RequireFeatures(ctx, func(pm policy.Manager) error {
|
if err := core.RequireFeatures(ctx, func(pm policy.Manager, d dns.Client) error {
|
||||||
return h.Init(config.(*Config), pm)
|
return h.Init(config.(*Config), pm, d)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -52,13 +53,16 @@ func init() {
|
|||||||
// Handler handles Freedom connections.
|
// Handler handles Freedom connections.
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
policyManager policy.Manager
|
policyManager policy.Manager
|
||||||
|
dns dns.Client
|
||||||
config *Config
|
config *Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes the Handler with necessary parameters.
|
// Init initializes the Handler with necessary parameters.
|
||||||
func (h *Handler) Init(config *Config, pm policy.Manager) error {
|
func (h *Handler) Init(config *Config, pm policy.Manager, d dns.Client) error {
|
||||||
h.config = config
|
h.config = config
|
||||||
h.policyManager = pm
|
h.policyManager = pm
|
||||||
|
h.dns = d
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +71,28 @@ func (h *Handler) policy() policy.Session {
|
|||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Handler) resolveIP(ctx context.Context, domain string, localAddr net.Address) net.Address {
|
||||||
|
ips, _, err := h.dns.LookupIP(domain, dns.IPOption{
|
||||||
|
IPv4Enable: (localAddr == nil || localAddr.Family().IsIPv4()) && h.config.preferIP4(),
|
||||||
|
IPv6Enable: (localAddr == nil || localAddr.Family().IsIPv6()) && h.config.preferIP6(),
|
||||||
|
})
|
||||||
|
{ // Resolve fallback
|
||||||
|
if (len(ips) == 0 || err != nil) && h.config.hasFallback() && localAddr == nil {
|
||||||
|
ips, _, err = h.dns.LookupIP(domain, dns.IPOption{
|
||||||
|
IPv4Enable: h.config.fallbackIP4(),
|
||||||
|
IPv6Enable: h.config.fallbackIP6(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", domain)
|
||||||
|
}
|
||||||
|
if len(ips) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return net.IPAddress(ips[dice.Roll(len(ips))])
|
||||||
|
}
|
||||||
|
|
||||||
func isValidAddress(addr *net.IPOrDomain) bool {
|
func isValidAddress(addr *net.IPOrDomain) bool {
|
||||||
if addr == nil {
|
if addr == nil {
|
||||||
return false
|
return false
|
||||||
@@ -88,12 +114,6 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
inbound := session.InboundFromContext(ctx)
|
inbound := session.InboundFromContext(ctx)
|
||||||
|
|
||||||
destination := ob.Target
|
destination := ob.Target
|
||||||
origTargetAddr := ob.OriginalTarget.Address
|
|
||||||
if origTargetAddr == nil {
|
|
||||||
origTargetAddr = ob.Target.Address
|
|
||||||
}
|
|
||||||
dialer.SetOutboundGateway(ctx, ob)
|
|
||||||
outGateway := ob.Gateway
|
|
||||||
UDPOverride := net.UDPDestination(nil, 0)
|
UDPOverride := net.UDPDestination(nil, 0)
|
||||||
if h.config.DestinationOverride != nil {
|
if h.config.DestinationOverride != nil {
|
||||||
server := h.config.DestinationOverride.Server
|
server := h.config.DestinationOverride.Server
|
||||||
@@ -113,24 +133,17 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
var conn stat.Connection
|
var conn stat.Connection
|
||||||
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||||
dialDest := destination
|
dialDest := destination
|
||||||
if h.config.DomainStrategy.HasStrategy() && dialDest.Address.Family().IsDomain() {
|
if h.config.hasStrategy() && dialDest.Address.Family().IsDomain() {
|
||||||
strategy := h.config.DomainStrategy
|
ip := h.resolveIP(ctx, dialDest.Address.Domain(), dialer.Address())
|
||||||
if destination.Network == net.Network_UDP && origTargetAddr != nil && outGateway == nil {
|
if ip != nil {
|
||||||
strategy = strategy.GetDynamicStrategy(origTargetAddr.Family())
|
|
||||||
}
|
|
||||||
ips, err := internet.LookupForIP(dialDest.Address.Domain(), strategy, outGateway)
|
|
||||||
if err != nil {
|
|
||||||
errors.LogInfoInner(ctx, err, "failed to get IP address for domain ", dialDest.Address.Domain())
|
|
||||||
if h.config.DomainStrategy.ForceIP() {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dialDest = net.Destination{
|
dialDest = net.Destination{
|
||||||
Network: dialDest.Network,
|
Network: dialDest.Network,
|
||||||
Address: net.IPAddress(ips[dice.Roll(len(ips))]),
|
Address: ip,
|
||||||
Port: dialDest.Port,
|
Port: dialDest.Port,
|
||||||
}
|
}
|
||||||
errors.LogInfo(ctx, "dialing to ", dialDest)
|
errors.LogInfo(ctx, "dialing to ", dialDest)
|
||||||
|
} else if h.config.forceIP() {
|
||||||
|
return dns.ErrEmptyResponse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,7 +203,7 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
|||||||
writer = buf.NewWriter(conn)
|
writer = buf.NewWriter(conn)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writer = NewPacketWriter(conn, h, UDPOverride, destination)
|
writer = NewPacketWriter(conn, h, ctx, UDPOverride, destination)
|
||||||
if h.config.Noises != nil {
|
if h.config.Noises != nil {
|
||||||
errors.LogDebug(ctx, "NOISE", h.config.Noises)
|
errors.LogDebug(ctx, "NOISE", h.config.Noises)
|
||||||
writer = &NoisePacketWriter{
|
writer = &NoisePacketWriter{
|
||||||
@@ -326,7 +339,7 @@ func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DialDest means the dial target used in the dialer when creating conn
|
// DialDest means the dial target used in the dialer when creating conn
|
||||||
func NewPacketWriter(conn net.Conn, h *Handler, UDPOverride net.Destination, DialDest net.Destination) buf.Writer {
|
func NewPacketWriter(conn net.Conn, h *Handler, ctx context.Context, UDPOverride net.Destination, DialDest net.Destination) buf.Writer {
|
||||||
iConn := conn
|
iConn := conn
|
||||||
statConn, ok := iConn.(*stat.CounterConnection)
|
statConn, ok := iConn.(*stat.CounterConnection)
|
||||||
if ok {
|
if ok {
|
||||||
@@ -347,9 +360,9 @@ func NewPacketWriter(conn net.Conn, h *Handler, UDPOverride net.Destination, Dia
|
|||||||
PacketConnWrapper: c,
|
PacketConnWrapper: c,
|
||||||
Counter: counter,
|
Counter: counter,
|
||||||
Handler: h,
|
Handler: h,
|
||||||
|
Context: ctx,
|
||||||
UDPOverride: UDPOverride,
|
UDPOverride: UDPOverride,
|
||||||
ResolvedUDPAddr: resolvedUDPAddr,
|
resolvedUDPAddr: resolvedUDPAddr,
|
||||||
LocalAddr: net.DestinationFromAddr(conn.LocalAddr()).Address,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -360,14 +373,14 @@ type PacketWriter struct {
|
|||||||
*internet.PacketConnWrapper
|
*internet.PacketConnWrapper
|
||||||
stats.Counter
|
stats.Counter
|
||||||
*Handler
|
*Handler
|
||||||
|
context.Context
|
||||||
UDPOverride net.Destination
|
UDPOverride net.Destination
|
||||||
|
|
||||||
// Dest of udp packets might be a domain, we will resolve them to IP
|
// Dest of udp packets might be a domain, we will resolve them to IP
|
||||||
// But resolver will return a random one if the domain has many IPs
|
// But resolver will return a random one if the domain has many IPs
|
||||||
// Resulting in these packets being sent to many different IPs randomly
|
// Resulting in these packets being sent to many different IPs randomly
|
||||||
// So, cache and keep the resolve result
|
// So, cache and keep the resolve result
|
||||||
ResolvedUDPAddr *utils.TypedSyncMap[string, net.Address]
|
resolvedUDPAddr *utils.TypedSyncMap[string, net.Address]
|
||||||
LocalAddr net.Address
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||||
@@ -387,22 +400,20 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
b.UDP.Port = w.UDPOverride.Port
|
b.UDP.Port = w.UDPOverride.Port
|
||||||
}
|
}
|
||||||
if b.UDP.Address.Family().IsDomain() {
|
if b.UDP.Address.Family().IsDomain() {
|
||||||
if ip, ok := w.ResolvedUDPAddr.Load(b.UDP.Address.Domain()); ok {
|
if ip, ok := w.resolvedUDPAddr.Load(b.UDP.Address.Domain()); ok {
|
||||||
b.UDP.Address = ip
|
b.UDP.Address = ip
|
||||||
} else {
|
} else {
|
||||||
ShouldUseSystemResolver := true
|
ShouldUseSystemResolver := true
|
||||||
if w.Handler.config.DomainStrategy.HasStrategy() {
|
if w.Handler.config.hasStrategy() {
|
||||||
ips, err := internet.LookupForIP(b.UDP.Address.Domain(), w.Handler.config.DomainStrategy, w.LocalAddr)
|
ip = w.Handler.resolveIP(w.Context, b.UDP.Address.Domain(), nil)
|
||||||
if err != nil {
|
if ip != nil {
|
||||||
// drop packet if resolve failed when forceIP
|
|
||||||
if w.Handler.config.DomainStrategy.ForceIP() {
|
|
||||||
b.Release()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ip = net.IPAddress(ips[dice.Roll(len(ips))])
|
|
||||||
ShouldUseSystemResolver = false
|
ShouldUseSystemResolver = false
|
||||||
}
|
}
|
||||||
|
// drop packet if resolve failed when forceIP
|
||||||
|
if ip == nil && w.Handler.config.forceIP() {
|
||||||
|
b.Release()
|
||||||
|
continue
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if ShouldUseSystemResolver {
|
if ShouldUseSystemResolver {
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp", b.UDP.NetAddr())
|
udpAddr, err := net.ResolveUDPAddr("udp", b.UDP.NetAddr())
|
||||||
@@ -414,7 +425,7 @@ func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ip != nil {
|
if ip != nil {
|
||||||
b.UDP.Address, _ = w.ResolvedUDPAddr.LoadOrStore(b.UDP.Address.Domain(), ip)
|
b.UDP.Address, _ = w.resolvedUDPAddr.LoadOrStore(b.UDP.Address.Domain(), ip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -485,10 +496,7 @@ func (w *NoisePacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
|
w.Writer.WriteMultiBuffer(buf.MultiBuffer{buf.FromBytes(noise)})
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.DelayMin != 0 || n.DelayMax != 0 {
|
if n.DelayMin != 0 || n.DelayMax != 0 {
|
||||||
time.Sleep(time.Duration(crypto.RandBetween(int64(n.DelayMin), int64(n.DelayMax))) * time.Millisecond)
|
time.Sleep(time.Duration(crypto.RandBetween(int64(n.DelayMin), int64(n.DelayMax))) * time.Millisecond)
|
||||||
|
@@ -2,6 +2,7 @@ package shadowsocks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
@@ -57,7 +58,11 @@ func (a *MemoryAccount) CheckIV(iv []byte) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createAesGcm(key []byte) cipher.AEAD {
|
func createAesGcm(key []byte) cipher.AEAD {
|
||||||
return crypto.NewAesGcm(key)
|
block, err := aes.NewCipher(key)
|
||||||
|
common.Must(err)
|
||||||
|
gcm, err := cipher.NewGCM(block)
|
||||||
|
common.Must(err)
|
||||||
|
return gcm
|
||||||
}
|
}
|
||||||
|
|
||||||
func createChaCha20Poly1305(key []byte) cipher.AEAD {
|
func createChaCha20Poly1305(key []byte) cipher.AEAD {
|
||||||
|
@@ -62,7 +62,7 @@ func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
|
// DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream.
|
||||||
func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator vless.Validator) ([]byte, *protocol.RequestHeader, *Addons, bool, error) {
|
func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator vless.Validator) (*protocol.RequestHeader, *Addons, bool, error) {
|
||||||
buffer := buf.StackNew()
|
buffer := buf.StackNew()
|
||||||
defer buffer.Release()
|
defer buffer.Release()
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
|
|||||||
request.Version = first.Byte(0)
|
request.Version = first.Byte(0)
|
||||||
} else {
|
} else {
|
||||||
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
|
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
|
||||||
return nil, nil, nil, false, errors.New("failed to read request version").Base(err)
|
return nil, nil, false, errors.New("failed to read request version").Base(err)
|
||||||
}
|
}
|
||||||
request.Version = buffer.Byte(0)
|
request.Version = buffer.Byte(0)
|
||||||
}
|
}
|
||||||
@@ -87,13 +87,13 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
|
|||||||
} else {
|
} else {
|
||||||
buffer.Clear()
|
buffer.Clear()
|
||||||
if _, err := buffer.ReadFullFrom(reader, 16); err != nil {
|
if _, err := buffer.ReadFullFrom(reader, 16); err != nil {
|
||||||
return nil, nil, nil, false, errors.New("failed to read request user id").Base(err)
|
return nil, nil, false, errors.New("failed to read request user id").Base(err)
|
||||||
}
|
}
|
||||||
copy(id[:], buffer.Bytes())
|
copy(id[:], buffer.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
if request.User = validator.Get(id); request.User == nil {
|
if request.User = validator.Get(id); request.User == nil {
|
||||||
return nil, nil, nil, isfb, errors.New("invalid request user id")
|
return nil, nil, isfb, errors.New("invalid request user id")
|
||||||
}
|
}
|
||||||
|
|
||||||
if isfb {
|
if isfb {
|
||||||
@@ -102,12 +102,12 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
|
|||||||
|
|
||||||
requestAddons, err := DecodeHeaderAddons(&buffer, reader)
|
requestAddons, err := DecodeHeaderAddons(&buffer, reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, false, errors.New("failed to decode request header addons").Base(err)
|
return nil, nil, false, errors.New("failed to decode request header addons").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.Clear()
|
buffer.Clear()
|
||||||
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
|
if _, err := buffer.ReadFullFrom(reader, 1); err != nil {
|
||||||
return nil, nil, nil, false, errors.New("failed to read request command").Base(err)
|
return nil, nil, false, errors.New("failed to read request command").Base(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
request.Command = protocol.RequestCommand(buffer.Byte(0))
|
request.Command = protocol.RequestCommand(buffer.Byte(0))
|
||||||
@@ -122,11 +122,11 @@ func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if request.Address == nil {
|
if request.Address == nil {
|
||||||
return nil, nil, nil, false, errors.New("invalid request address")
|
return nil, nil, false, errors.New("invalid request address")
|
||||||
}
|
}
|
||||||
return id[:], request, requestAddons, false, nil
|
return request, requestAddons, false, nil
|
||||||
default:
|
default:
|
||||||
return nil, nil, nil, isfb, errors.New("invalid request version")
|
return nil, nil, isfb, errors.New("invalid request version")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -45,7 +45,7 @@ func TestRequestSerialization(t *testing.T) {
|
|||||||
Validator := new(vless.MemoryValidator)
|
Validator := new(vless.MemoryValidator)
|
||||||
Validator.Add(user)
|
Validator.Add(user)
|
||||||
|
|
||||||
_, actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {
|
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {
|
||||||
@@ -86,7 +86,7 @@ func TestInvalidRequest(t *testing.T) {
|
|||||||
Validator := new(vless.MemoryValidator)
|
Validator := new(vless.MemoryValidator)
|
||||||
Validator.Add(user)
|
Validator.Add(user)
|
||||||
|
|
||||||
_, _, _, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
_, _, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("nil error")
|
t.Error("nil error")
|
||||||
}
|
}
|
||||||
@@ -117,7 +117,7 @@ func TestMuxRequest(t *testing.T) {
|
|||||||
Validator := new(vless.MemoryValidator)
|
Validator := new(vless.MemoryValidator)
|
||||||
Validator.Add(user)
|
Validator.Add(user)
|
||||||
|
|
||||||
_, actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
actualRequest, actualAddons, _, err := DecodeRequestHeader(false, nil, &buffer, Validator)
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {
|
if r := cmp.Diff(actualRequest, expectedRequest, cmp.AllowUnexported(protocol.ID{})); r != "" {
|
||||||
|
@@ -217,7 +217,6 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
Buffer: buf.MultiBuffer{first},
|
Buffer: buf.MultiBuffer{first},
|
||||||
}
|
}
|
||||||
|
|
||||||
var userSentID []byte // not MemoryAccount.ID
|
|
||||||
var request *protocol.RequestHeader
|
var request *protocol.RequestHeader
|
||||||
var requestAddons *encoding.Addons
|
var requestAddons *encoding.Addons
|
||||||
var err error
|
var err error
|
||||||
@@ -228,7 +227,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
if isfb && firstLen < 18 {
|
if isfb && firstLen < 18 {
|
||||||
err = errors.New("fallback directly")
|
err = errors.New("fallback directly")
|
||||||
} else {
|
} else {
|
||||||
userSentID, request, requestAddons, isfb, err = encoding.DecodeRequestHeader(isfb, first, reader, h.validator)
|
request, requestAddons, isfb, err = encoding.DecodeRequestHeader(isfb, first, reader, h.validator)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -456,7 +455,6 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
}
|
}
|
||||||
inbound.Name = "vless"
|
inbound.Name = "vless"
|
||||||
inbound.User = request.User
|
inbound.User = request.User
|
||||||
inbound.VlessRoute = net.PortFromBytes(userSentID[6:8])
|
|
||||||
|
|
||||||
account := request.User.Account.(*vless.MemoryAccount)
|
account := request.User.Account.(*vless.MemoryAccount)
|
||||||
|
|
||||||
@@ -532,7 +530,7 @@ func (h *Handler) Process(ctx context.Context, network net.Network, connection s
|
|||||||
|
|
||||||
serverReader := link.Reader // .(*pipe.Reader)
|
serverReader := link.Reader // .(*pipe.Reader)
|
||||||
serverWriter := link.Writer // .(*pipe.Writer)
|
serverWriter := link.Writer // .(*pipe.Writer)
|
||||||
trafficState := proxy.NewTrafficState(userSentID)
|
trafficState := proxy.NewTrafficState(account.ID.Bytes())
|
||||||
postRequest := func() error {
|
postRequest := func() error {
|
||||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||||
|
|
||||||
|
@@ -18,12 +18,6 @@ type Validator interface {
|
|||||||
GetCount() int64
|
GetCount() int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProcessUUID(id [16]byte) [16]byte {
|
|
||||||
id[6] = 0
|
|
||||||
id[7] = 0
|
|
||||||
return id
|
|
||||||
}
|
|
||||||
|
|
||||||
// MemoryValidator stores valid VLESS users.
|
// MemoryValidator stores valid VLESS users.
|
||||||
type MemoryValidator struct {
|
type MemoryValidator struct {
|
||||||
// Considering email's usage here, map + sync.Mutex/RWMutex may have better performance.
|
// Considering email's usage here, map + sync.Mutex/RWMutex may have better performance.
|
||||||
@@ -39,7 +33,7 @@ func (v *MemoryValidator) Add(u *protocol.MemoryUser) error {
|
|||||||
return errors.New("User ", u.Email, " already exists.")
|
return errors.New("User ", u.Email, " already exists.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
v.users.Store(ProcessUUID(u.Account.(*MemoryAccount).ID.UUID()), u)
|
v.users.Store(u.Account.(*MemoryAccount).ID.UUID(), u)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,13 +48,13 @@ func (v *MemoryValidator) Del(e string) error {
|
|||||||
return errors.New("User ", e, " not found.")
|
return errors.New("User ", e, " not found.")
|
||||||
}
|
}
|
||||||
v.email.Delete(le)
|
v.email.Delete(le)
|
||||||
v.users.Delete(ProcessUUID(u.(*protocol.MemoryUser).Account.(*MemoryAccount).ID.UUID()))
|
v.users.Delete(u.(*protocol.MemoryUser).Account.(*MemoryAccount).ID.UUID())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a VLESS user with UUID, nil if user doesn't exist.
|
// Get a VLESS user with UUID, nil if user doesn't exist.
|
||||||
func (v *MemoryValidator) Get(id uuid.UUID) *protocol.MemoryUser {
|
func (v *MemoryValidator) Get(id uuid.UUID) *protocol.MemoryUser {
|
||||||
u, _ := v.users.Load(ProcessUUID(id))
|
u, _ := v.users.Load(id)
|
||||||
if u != nil {
|
if u != nil {
|
||||||
return u.(*protocol.MemoryUser)
|
return u.(*protocol.MemoryUser)
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,5 @@
|
|||||||
package vless
|
package vless
|
||||||
|
|
||||||
const (
|
const (
|
||||||
None = "none"
|
XRV = "xtls-rprx-vision"
|
||||||
XRV = "xtls-rprx-vision"
|
|
||||||
)
|
)
|
||||||
|
@@ -2,13 +2,14 @@ package aead
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/crypto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
||||||
@@ -33,7 +34,15 @@ func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
|||||||
|
|
||||||
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||||
|
|
||||||
payloadHeaderAEAD := crypto.NewAesGcm(payloadHeaderLengthAEADKey)
|
payloadHeaderLengthAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderLengthAEADAESBlock)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
|
payloadHeaderLengthAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderLengthAEADNonce, aeadPayloadLengthSerializedByte, generatedAuthID[:])
|
||||||
}
|
}
|
||||||
@@ -45,7 +54,15 @@ func SealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
|||||||
|
|
||||||
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
payloadHeaderAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadAEADIV, string(generatedAuthID[:]), string(connectionNonce))[:12]
|
||||||
|
|
||||||
payloadHeaderAEAD := crypto.NewAesGcm(payloadHeaderAEADKey)
|
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
|
payloadHeaderAEADEncrypted = payloadHeaderAEAD.Seal(nil, payloadHeaderAEADNonce, data, generatedAuthID[:])
|
||||||
}
|
}
|
||||||
@@ -87,7 +104,15 @@ func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte,
|
|||||||
|
|
||||||
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
|
payloadHeaderLengthAEADNonce := KDF(key[:], KDFSaltConstVMessHeaderPayloadLengthAEADIV, string(authid[:]), string(nonce[:]))[:12]
|
||||||
|
|
||||||
payloadHeaderLengthAEAD := crypto.NewAesGcm(payloadHeaderLengthAEADKey)
|
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderLengthAEADKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadHeaderLengthAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:])
|
decryptedAEADHeaderLengthPayload, erropenAEAD := payloadHeaderLengthAEAD.Open(nil, payloadHeaderLengthAEADNonce, payloadHeaderLengthAEADEncrypted[:], authid[:])
|
||||||
|
|
||||||
@@ -120,7 +145,15 @@ func OpenVMessAEADHeader(key [16]byte, authid [16]byte, data io.Reader) ([]byte,
|
|||||||
return nil, false, bytesRead, err
|
return nil, false, bytesRead, err
|
||||||
}
|
}
|
||||||
|
|
||||||
payloadHeaderAEAD := crypto.NewAesGcm(payloadHeaderAEADKey)
|
payloadHeaderAEADAESBlock, err := aes.NewCipher(payloadHeaderAEADKey)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
payloadHeaderAEAD, err := cipher.NewGCM(payloadHeaderAEADAESBlock)
|
||||||
|
if err != nil {
|
||||||
|
panic(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])
|
decryptedAEADHeaderPayload, erropenAEAD := payloadHeaderAEAD.Open(nil, payloadHeaderAEADNonce, payloadHeaderAEADEncrypted, authid[:])
|
||||||
|
|
||||||
|
@@ -3,6 +3,8 @@ package encoding
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
@@ -180,7 +182,8 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
|
|||||||
aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(c.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderLenKey)
|
aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(c.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderLenKey)
|
||||||
aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(c.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderLenIV)[:12]
|
aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(c.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderLenIV)[:12]
|
||||||
|
|
||||||
aeadResponseHeaderLengthEncryptionAEAD := crypto.NewAesGcm(aeadResponseHeaderLengthEncryptionKey)
|
aeadResponseHeaderLengthEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderLengthEncryptionKey)).(cipher.Block)
|
||||||
|
aeadResponseHeaderLengthEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderLengthEncryptionKeyAESBlock)).(cipher.AEAD)
|
||||||
|
|
||||||
var aeadEncryptedResponseHeaderLength [18]byte
|
var aeadEncryptedResponseHeaderLength [18]byte
|
||||||
var decryptedResponseHeaderLength int
|
var decryptedResponseHeaderLength int
|
||||||
@@ -202,7 +205,8 @@ func (c *ClientSession) DecodeResponseHeader(reader io.Reader) (*protocol.Respon
|
|||||||
aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(c.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadKey)
|
aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(c.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadKey)
|
||||||
aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(c.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadIV)[:12]
|
aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(c.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadIV)[:12]
|
||||||
|
|
||||||
aeadResponseHeaderPayloadEncryptionAEAD := crypto.NewAesGcm(aeadResponseHeaderPayloadEncryptionKey)
|
aeadResponseHeaderPayloadEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderPayloadEncryptionKey)).(cipher.Block)
|
||||||
|
aeadResponseHeaderPayloadEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderPayloadEncryptionKeyAESBlock)).(cipher.AEAD)
|
||||||
|
|
||||||
encryptedResponseHeaderBuffer := make([]byte, decryptedResponseHeaderLength+16)
|
encryptedResponseHeaderBuffer := make([]byte, decryptedResponseHeaderLength+16)
|
||||||
|
|
||||||
|
@@ -2,6 +2,8 @@ package encoding
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"hash/fnv"
|
"hash/fnv"
|
||||||
@@ -348,7 +350,8 @@ func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, wr
|
|||||||
aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderLenKey)
|
aeadResponseHeaderLengthEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderLenKey)
|
||||||
aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderLenIV)[:12]
|
aeadResponseHeaderLengthEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderLenIV)[:12]
|
||||||
|
|
||||||
aeadResponseHeaderLengthEncryptionAEAD := crypto.NewAesGcm(aeadResponseHeaderLengthEncryptionKey)
|
aeadResponseHeaderLengthEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderLengthEncryptionKey)).(cipher.Block)
|
||||||
|
aeadResponseHeaderLengthEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderLengthEncryptionKeyAESBlock)).(cipher.AEAD)
|
||||||
|
|
||||||
aeadResponseHeaderLengthEncryptionBuffer := bytes.NewBuffer(nil)
|
aeadResponseHeaderLengthEncryptionBuffer := bytes.NewBuffer(nil)
|
||||||
|
|
||||||
@@ -362,7 +365,8 @@ func (s *ServerSession) EncodeResponseHeader(header *protocol.ResponseHeader, wr
|
|||||||
aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadKey)
|
aeadResponseHeaderPayloadEncryptionKey := vmessaead.KDF16(s.responseBodyKey[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadKey)
|
||||||
aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadIV)[:12]
|
aeadResponseHeaderPayloadEncryptionIV := vmessaead.KDF(s.responseBodyIV[:], vmessaead.KDFSaltConstAEADRespHeaderPayloadIV)[:12]
|
||||||
|
|
||||||
aeadResponseHeaderPayloadEncryptionAEAD := crypto.NewAesGcm(aeadResponseHeaderPayloadEncryptionKey)
|
aeadResponseHeaderPayloadEncryptionKeyAESBlock := common.Must2(aes.NewCipher(aeadResponseHeaderPayloadEncryptionKey)).(cipher.Block)
|
||||||
|
aeadResponseHeaderPayloadEncryptionAEAD := common.Must2(cipher.NewGCM(aeadResponseHeaderPayloadEncryptionKeyAESBlock)).(cipher.AEAD)
|
||||||
|
|
||||||
aeadEncryptedHeaderPayload := aeadResponseHeaderPayloadEncryptionAEAD.Seal(nil, aeadResponseHeaderPayloadEncryptionIV, aeadEncryptedHeaderBuffer.Bytes(), nil)
|
aeadEncryptedHeaderPayload := aeadResponseHeaderPayloadEncryptionAEAD.Seal(nil, aeadResponseHeaderPayloadEncryptionIV, aeadEncryptedHeaderBuffer.Bytes(), nil)
|
||||||
common.Must2(io.Copy(writer, bytes.NewReader(aeadEncryptedHeaderPayload)))
|
common.Must2(io.Copy(writer, bytes.NewReader(aeadEncryptedHeaderPayload)))
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
|
|
||||||
"github.com/xtls/xray-core/common"
|
"github.com/xtls/xray-core/common"
|
||||||
"github.com/xtls/xray-core/common/buf"
|
"github.com/xtls/xray-core/common/buf"
|
||||||
c "github.com/xtls/xray-core/common/ctx"
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
"github.com/xtls/xray-core/common/log"
|
"github.com/xtls/xray-core/common/log"
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
@@ -34,6 +33,7 @@ type routingInfo struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
dispatcher routing.Dispatcher
|
dispatcher routing.Dispatcher
|
||||||
inboundTag *session.Inbound
|
inboundTag *session.Inbound
|
||||||
|
outboundTag *session.Outbound
|
||||||
contentTag *session.Content
|
contentTag *session.Content
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,11 +78,18 @@ func (*Server) Network() []net.Network {
|
|||||||
|
|
||||||
// Process implements proxy.Inbound.
|
// Process implements proxy.Inbound.
|
||||||
func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
||||||
|
inbound := session.InboundFromContext(ctx)
|
||||||
|
inbound.Name = "wireguard"
|
||||||
|
inbound.CanSpliceCopy = 3
|
||||||
|
outbounds := session.OutboundsFromContext(ctx)
|
||||||
|
ob := outbounds[len(outbounds)-1]
|
||||||
|
|
||||||
s.info = routingInfo{
|
s.info = routingInfo{
|
||||||
ctx: ctx,
|
ctx: core.ToBackgroundDetachedContext(ctx),
|
||||||
dispatcher: dispatcher,
|
dispatcher: dispatcher,
|
||||||
inboundTag: session.InboundFromContext(ctx),
|
inboundTag: session.InboundFromContext(ctx),
|
||||||
contentTag: session.ContentFromContext(ctx),
|
outboundTag: ob,
|
||||||
|
contentTag: session.ContentFromContext(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
ep, err := s.bindServer.ParseEndpoint(conn.RemoteAddr().String())
|
ep, err := s.bindServer.ParseEndpoint(conn.RemoteAddr().String())
|
||||||
@@ -127,25 +134,6 @@ func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) {
|
|||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
ctx, cancel := context.WithCancel(core.ToBackgroundDetachedContext(s.info.ctx))
|
ctx, cancel := context.WithCancel(core.ToBackgroundDetachedContext(s.info.ctx))
|
||||||
sid := session.NewID()
|
|
||||||
ctx = c.ContextWithID(ctx, sid)
|
|
||||||
inbound := session.Inbound{} // since promiscuousModeHandler mixed-up context, we shallow copy inbound (tag) and content (configs)
|
|
||||||
if s.info.inboundTag != nil {
|
|
||||||
inbound = *s.info.inboundTag
|
|
||||||
}
|
|
||||||
inbound.Name = "wireguard"
|
|
||||||
inbound.CanSpliceCopy = 3
|
|
||||||
|
|
||||||
// overwrite the source to use the tun address for each sub context.
|
|
||||||
// Since gvisor.ForwarderRequest doesn't provide any info to associate the sub-context with the Parent context
|
|
||||||
// Currently we have no way to link to the original source address
|
|
||||||
inbound.Source = net.DestinationFromAddr(conn.RemoteAddr())
|
|
||||||
ctx = session.ContextWithInbound(ctx, &inbound)
|
|
||||||
if s.info.contentTag != nil {
|
|
||||||
ctx = session.ContextWithContent(ctx, s.info.contentTag)
|
|
||||||
}
|
|
||||||
ctx = session.SubContextFromMuxInbound(ctx)
|
|
||||||
|
|
||||||
plcy := s.policyManager.ForLevel(0)
|
plcy := s.policyManager.ForLevel(0)
|
||||||
timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle)
|
timer := signal.CancelAfterInactivity(ctx, cancel, plcy.Timeouts.ConnectionIdle)
|
||||||
|
|
||||||
@@ -156,9 +144,25 @@ func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) {
|
|||||||
Reason: "",
|
Reason: "",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if s.info.inboundTag != nil {
|
||||||
|
ctx = session.ContextWithInbound(ctx, s.info.inboundTag)
|
||||||
|
}
|
||||||
|
|
||||||
|
// what's this?
|
||||||
|
// Session information should not be shared between different connections
|
||||||
|
// why reuse them in server level? This will cause incorrect destoverride and unexpected routing behavior.
|
||||||
|
// Disable it temporarily. Maybe s.info should be removed.
|
||||||
|
|
||||||
|
// if s.info.outboundTag != nil {
|
||||||
|
// ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{s.info.outboundTag})
|
||||||
|
// }
|
||||||
|
// if s.info.contentTag != nil {
|
||||||
|
// ctx = session.ContextWithContent(ctx, s.info.contentTag)
|
||||||
|
// }
|
||||||
|
|
||||||
link, err := s.info.dispatcher.Dispatch(ctx, dest)
|
link, err := s.info.dispatcher.Dispatch(ctx, dest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "dispatch connection")
|
errors.LogErrorInner(s.info.ctx, err, "dispatch connection")
|
||||||
}
|
}
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
@@ -184,7 +188,7 @@ func (s *Server) forwardConnection(dest net.Destination, conn net.Conn) {
|
|||||||
if err := task.Run(ctx, requestDonePost, responseDone); err != nil {
|
if err := task.Run(ctx, requestDonePost, responseDone); err != nil {
|
||||||
common.Interrupt(link.Reader)
|
common.Interrupt(link.Reader)
|
||||||
common.Interrupt(link.Writer)
|
common.Interrupt(link.Writer)
|
||||||
errors.LogDebugInner(ctx, err, "connection ends")
|
errors.LogDebugInner(s.info.ctx, err, "connection ends")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,6 @@ import (
|
|||||||
"github.com/xtls/xray-core/proxy/freedom"
|
"github.com/xtls/xray-core/proxy/freedom"
|
||||||
"github.com/xtls/xray-core/proxy/socks"
|
"github.com/xtls/xray-core/proxy/socks"
|
||||||
"github.com/xtls/xray-core/testing/servers/tcp"
|
"github.com/xtls/xray-core/testing/servers/tcp"
|
||||||
"github.com/xtls/xray-core/transport/internet"
|
|
||||||
xproxy "golang.org/x/net/proxy"
|
xproxy "golang.org/x/net/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -84,7 +83,7 @@ func TestResolveIP(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Tag: "direct",
|
Tag: "direct",
|
||||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
ProxySettings: serial.ToTypedMessage(&freedom.Config{
|
||||||
DomainStrategy: internet.DomainStrategy_USE_IP,
|
DomainStrategy: freedom.Config_USE_IP,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@@ -2,7 +2,6 @@ package internet
|
|||||||
|
|
||||||
import (
|
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/serial"
|
"github.com/xtls/xray-core/common/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -101,52 +100,30 @@ func (m SocketConfig_TProxyMode) IsEnabled() bool {
|
|||||||
return m != SocketConfig_Off
|
return m != SocketConfig_Off
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s DomainStrategy) HasStrategy() bool {
|
func (s DomainStrategy) hasStrategy() bool {
|
||||||
return strategy[s][0] != 0
|
return strategy[s][0] != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s DomainStrategy) ForceIP() bool {
|
func (s DomainStrategy) forceIP() bool {
|
||||||
return strategy[s][0] == 2
|
return strategy[s][0] == 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s DomainStrategy) PreferIP4() bool {
|
func (s DomainStrategy) preferIP4() bool {
|
||||||
return strategy[s][1] == 4 || strategy[s][1] == 0
|
return strategy[s][1] == 4 || strategy[s][1] == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s DomainStrategy) PreferIP6() bool {
|
func (s DomainStrategy) preferIP6() bool {
|
||||||
return strategy[s][1] == 6 || strategy[s][1] == 0
|
return strategy[s][1] == 6 || strategy[s][1] == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s DomainStrategy) HasFallback() bool {
|
func (s DomainStrategy) hasFallback() bool {
|
||||||
return strategy[s][2] != 0
|
return strategy[s][2] != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s DomainStrategy) FallbackIP4() bool {
|
func (s DomainStrategy) fallbackIP4() bool {
|
||||||
return strategy[s][2] == 4
|
return strategy[s][2] == 4
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s DomainStrategy) FallbackIP6() bool {
|
func (s DomainStrategy) fallbackIP6() bool {
|
||||||
return strategy[s][2] == 6
|
return strategy[s][2] == 6
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s DomainStrategy) GetDynamicStrategy(addrFamily net.AddressFamily) DomainStrategy {
|
|
||||||
if addrFamily.IsDomain(){
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
switch s {
|
|
||||||
case DomainStrategy_USE_IP:
|
|
||||||
if addrFamily.IsIPv4() {
|
|
||||||
return DomainStrategy_USE_IP46
|
|
||||||
} else if addrFamily.IsIPv6() {
|
|
||||||
return DomainStrategy_USE_IP64
|
|
||||||
}
|
|
||||||
case DomainStrategy_FORCE_IP:
|
|
||||||
if addrFamily.IsIPv4() {
|
|
||||||
return DomainStrategy_FORCE_IP46
|
|
||||||
} else if addrFamily.IsIPv6() {
|
|
||||||
return DomainStrategy_FORCE_IP64
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
@@ -24,11 +24,11 @@ type Dialer interface {
|
|||||||
// Dial dials a system connection to the given destination.
|
// Dial dials a system connection to the given destination.
|
||||||
Dial(ctx context.Context, destination net.Destination) (stat.Connection, error)
|
Dial(ctx context.Context, destination net.Destination) (stat.Connection, error)
|
||||||
|
|
||||||
|
// Address returns the address used by this Dialer. Maybe nil if not known.
|
||||||
|
Address() net.Address
|
||||||
|
|
||||||
// DestIpAddress returns the ip of proxy server. It is useful in case of Android client, which prepare an IP before proxy connection is established
|
// DestIpAddress returns the ip of proxy server. It is useful in case of Android client, which prepare an IP before proxy connection is established
|
||||||
DestIpAddress() net.IP
|
DestIpAddress() net.IP
|
||||||
|
|
||||||
// SetOutboundGateway set outbound gateway
|
|
||||||
SetOutboundGateway(ctx context.Context, ob *session.Outbound)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dialFunc is an interface to dial network connection to a specific destination.
|
// dialFunc is an interface to dial network connection to a specific destination.
|
||||||
@@ -85,20 +85,20 @@ var (
|
|||||||
obm outbound.Manager
|
obm outbound.Manager
|
||||||
)
|
)
|
||||||
|
|
||||||
func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]net.IP, error) {
|
func lookupIP(domain string, strategy DomainStrategy, localAddr net.Address) ([]net.IP, error) {
|
||||||
if dnsClient == nil {
|
if dnsClient == nil {
|
||||||
return nil, errors.New("DNS client not initialized").AtError()
|
return nil, errors.New("DNS client not initialized").AtError()
|
||||||
}
|
}
|
||||||
|
|
||||||
ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{
|
ips, _, err := dnsClient.LookupIP(domain, dns.IPOption{
|
||||||
IPv4Enable: (localAddr == nil && strategy.PreferIP4()) || (localAddr != nil && localAddr.Family().IsIPv4() && (strategy.PreferIP4() || strategy.FallbackIP4())),
|
IPv4Enable: (localAddr == nil || localAddr.Family().IsIPv4()) && strategy.preferIP4(),
|
||||||
IPv6Enable: (localAddr == nil && strategy.PreferIP6()) || (localAddr != nil && localAddr.Family().IsIPv6() && (strategy.PreferIP6() || strategy.FallbackIP6())),
|
IPv6Enable: (localAddr == nil || localAddr.Family().IsIPv6()) && strategy.preferIP6(),
|
||||||
})
|
})
|
||||||
{ // Resolve fallback
|
{ // Resolve fallback
|
||||||
if (len(ips) == 0 || err != nil) && strategy.HasFallback() && localAddr == nil {
|
if (len(ips) == 0 || err != nil) && strategy.hasFallback() && localAddr == nil {
|
||||||
ips, _, err = dnsClient.LookupIP(domain, dns.IPOption{
|
ips, _, err = dnsClient.LookupIP(domain, dns.IPOption{
|
||||||
IPv4Enable: strategy.FallbackIP4(),
|
IPv4Enable: strategy.fallbackIP4(),
|
||||||
IPv6Enable: strategy.FallbackIP6(),
|
IPv6Enable: strategy.fallbackIP6(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,6 +109,13 @@ func LookupForIP(domain string, strategy DomainStrategy, localAddr net.Address)
|
|||||||
return ips, err
|
return ips, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func canLookupIP(dst net.Destination, sockopt *SocketConfig) bool {
|
||||||
|
if dst.Address.Family().IsIP() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return sockopt.DomainStrategy.hasStrategy()
|
||||||
|
}
|
||||||
|
|
||||||
func redirect(ctx context.Context, dst net.Destination, obt string, h outbound.Handler) net.Conn {
|
func redirect(ctx context.Context, dst net.Destination, obt string, h outbound.Handler) net.Conn {
|
||||||
errors.LogInfo(ctx, "redirecting request "+dst.String()+" to "+obt)
|
errors.LogInfo(ctx, "redirecting request "+dst.String()+" to "+obt)
|
||||||
outbounds := session.OutboundsFromContext(ctx)
|
outbounds := session.OutboundsFromContext(ctx)
|
||||||
@@ -228,18 +235,9 @@ func checkAddressPortStrategy(ctx context.Context, dest net.Destination, sockopt
|
|||||||
func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
|
func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig) (net.Conn, error) {
|
||||||
var src net.Address
|
var src net.Address
|
||||||
outbounds := session.OutboundsFromContext(ctx)
|
outbounds := session.OutboundsFromContext(ctx)
|
||||||
var outboundName string
|
|
||||||
var origTargetAddr net.Address
|
|
||||||
if len(outbounds) > 0 {
|
if len(outbounds) > 0 {
|
||||||
ob := outbounds[len(outbounds)-1]
|
ob := outbounds[len(outbounds)-1]
|
||||||
if sockopt == nil || len(sockopt.DialerProxy) == 0 {
|
src = ob.Gateway
|
||||||
src = ob.Gateway
|
|
||||||
}
|
|
||||||
outboundName = ob.Name
|
|
||||||
origTargetAddr = ob.OriginalTarget.Address
|
|
||||||
if origTargetAddr == nil {
|
|
||||||
origTargetAddr = ob.Target.Address
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if sockopt == nil {
|
if sockopt == nil {
|
||||||
return effectiveSystemDialer.Dial(ctx, src, dest, sockopt)
|
return effectiveSystemDialer.Dial(ctx, src, dest, sockopt)
|
||||||
@@ -250,22 +248,18 @@ func DialSystem(ctx context.Context, dest net.Destination, sockopt *SocketConfig
|
|||||||
dest = *newDest
|
dest = *newDest
|
||||||
}
|
}
|
||||||
|
|
||||||
if sockopt.DomainStrategy.HasStrategy() && dest.Address.Family().IsDomain() {
|
if canLookupIP(dest, sockopt) {
|
||||||
finalStrategy := sockopt.DomainStrategy
|
ips, err := lookupIP(dest.Address.String(), sockopt.DomainStrategy, src)
|
||||||
if outboundName == "freedom" && dest.Network == net.Network_UDP && origTargetAddr != nil && src == nil {
|
|
||||||
finalStrategy = finalStrategy.GetDynamicStrategy(origTargetAddr.Family())
|
|
||||||
}
|
|
||||||
ips, err := LookupForIP(dest.Address.Domain(), finalStrategy, src)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors.LogErrorInner(ctx, err, "failed to resolve ip")
|
errors.LogErrorInner(ctx, err, "failed to resolve ip")
|
||||||
if sockopt.DomainStrategy.ForceIP() {
|
if sockopt.DomainStrategy.forceIP() {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
} else if sockopt.HappyEyeballs == nil || sockopt.HappyEyeballs.TryDelayMs == 0 || sockopt.HappyEyeballs.MaxConcurrentTry == 0 || len(ips) < 2 || len(sockopt.DialerProxy) > 0 || dest.Network != net.Network_TCP {
|
} else if sockopt.HappyEyeballs == nil || sockopt.HappyEyeballs.TryDelayMs == 0 || sockopt.HappyEyeballs.MaxConcurrentTry == 0 || len(ips) < 2 || len(sockopt.DialerProxy) > 0 || dest.Network != net.Network_TCP {
|
||||||
dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])
|
dest.Address = net.IPAddress(ips[dice.Roll(len(ips))])
|
||||||
errors.LogInfo(ctx, "replace destination with "+dest.String())
|
errors.LogInfo(ctx, "replace destination with "+dest.String())
|
||||||
} else {
|
} else {
|
||||||
return TcpRaceDial(ctx, src, ips, dest.Port, sockopt, dest.Address.String())
|
return TcpRaceDial(ctx, src, ips, dest.Port, sockopt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,6 @@ package internet
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/xtls/xray-core/common/errors"
|
|
||||||
"github.com/xtls/xray-core/common/net"
|
"github.com/xtls/xray-core/common/net"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -13,7 +12,7 @@ type result struct {
|
|||||||
index int
|
index int
|
||||||
}
|
}
|
||||||
|
|
||||||
func TcpRaceDial(ctx context.Context, src net.Address, ips []net.IP, port net.Port, sockopt *SocketConfig, domain string) (net.Conn, error) {
|
func TcpRaceDial(ctx context.Context, src net.Address, ips []net.IP, port net.Port, sockopt *SocketConfig) (net.Conn, error) {
|
||||||
if len(ips) < 2 {
|
if len(ips) < 2 {
|
||||||
panic("at least 2 ips is required to race dial")
|
panic("at least 2 ips is required to race dial")
|
||||||
}
|
}
|
||||||
@@ -31,7 +30,6 @@ func TcpRaceDial(ctx context.Context, src net.Address, ips []net.IP, port net.Po
|
|||||||
activeNum := uint32(0)
|
activeNum := uint32(0)
|
||||||
timer := time.NewTimer(0)
|
timer := time.NewTimer(0)
|
||||||
var winConn net.Conn
|
var winConn net.Conn
|
||||||
errors.LogDebug(ctx, "happy eyeballs racing dial for ", domain, " with IPs ", ips)
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case r := <-resultCh:
|
case r := <-resultCh:
|
||||||
@@ -56,7 +54,6 @@ func TcpRaceDial(ctx context.Context, src net.Address, ips []net.IP, port net.Po
|
|||||||
timer.Stop()
|
timer.Stop()
|
||||||
if winConn == nil {
|
if winConn == nil {
|
||||||
winConn = r.conn
|
winConn = r.conn
|
||||||
errors.LogDebug(ctx, "happy eyeballs established connection for ", domain, " with IP ", ips[r.index])
|
|
||||||
} else {
|
} else {
|
||||||
r.conn.Close()
|
r.conn.Close()
|
||||||
}
|
}
|
||||||
@@ -72,7 +69,6 @@ func TcpRaceDial(ctx context.Context, src net.Address, ips []net.IP, port net.Po
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if activeNum == 0 {
|
if activeNum == 0 {
|
||||||
errors.LogDebugInner(ctx, r.err, "happy eyeballs no connection established for ", domain)
|
|
||||||
return nil, r.err
|
return nil, r.err
|
||||||
}
|
}
|
||||||
timer.Stop()
|
timer.Stop()
|
||||||
|
@@ -1,13 +1,15 @@
|
|||||||
package kcp
|
package kcp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/aes"
|
||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/crypto"
|
"github.com/xtls/xray-core/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewAEADAESGCMBasedOnSeed(seed string) cipher.AEAD {
|
func NewAEADAESGCMBasedOnSeed(seed string) cipher.AEAD {
|
||||||
hashedSeed := sha256.Sum256([]byte(seed))
|
hashedSeed := sha256.Sum256([]byte(seed))
|
||||||
return crypto.NewAesGcm(hashedSeed[:])
|
aesBlock := common.Must2(aes.NewCipher(hashedSeed[:16])).(cipher.Block)
|
||||||
|
return common.Must2(cipher.NewGCM(aesBlock)).(cipher.AEAD)
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,8 @@ package reality
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
"crypto/ecdh"
|
"crypto/ecdh"
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
"crypto/hmac"
|
"crypto/hmac"
|
||||||
@@ -167,7 +169,8 @@ func UClient(c net.Conn, config *Config, ctx context.Context, dest net.Destinati
|
|||||||
if _, err := hkdf.New(sha256.New, uConn.AuthKey, hello.Random[:20], []byte("REALITY")).Read(uConn.AuthKey); err != nil {
|
if _, err := hkdf.New(sha256.New, uConn.AuthKey, hello.Random[:20], []byte("REALITY")).Read(uConn.AuthKey); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
aead := crypto.NewAesGcm(uConn.AuthKey)
|
block, _ := aes.NewCipher(uConn.AuthKey)
|
||||||
|
aead, _ := cipher.NewGCM(block)
|
||||||
if config.Show {
|
if config.Show {
|
||||||
fmt.Printf("REALITY localAddr: %v\tuConn.AuthKey[:16]: %v\tAEAD: %T\n", localAddr, uConn.AuthKey[:16], aead)
|
fmt.Printf("REALITY localAddr: %v\tuConn.AuthKey[:16]: %v\tAEAD: %T\n", localAddr, uConn.AuthKey[:16], aead)
|
||||||
}
|
}
|
||||||
|
@@ -297,7 +297,7 @@ func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.Me
|
|||||||
if transportConfiguration.DownloadSettings != nil {
|
if transportConfiguration.DownloadSettings != nil {
|
||||||
globalDialerAccess.Lock()
|
globalDialerAccess.Lock()
|
||||||
if streamSettings.DownloadSettings == nil {
|
if streamSettings.DownloadSettings == nil {
|
||||||
streamSettings.DownloadSettings = common.Must2(internet.ToMemoryStreamConfig(transportConfiguration.DownloadSettings))
|
streamSettings.DownloadSettings = common.Must2(internet.ToMemoryStreamConfig(transportConfiguration.DownloadSettings)).(*internet.MemoryStreamConfig)
|
||||||
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.Penetrate {
|
if streamSettings.SocketSettings != nil && streamSettings.SocketSettings.Penetrate {
|
||||||
streamSettings.DownloadSettings.SocketSettings = streamSettings.SocketSettings
|
streamSettings.DownloadSettings.SocketSettings = streamSettings.SocketSettings
|
||||||
}
|
}
|
||||||
@@ -490,15 +490,16 @@ func (w uploadWriter) Write(b []byte) (int, error) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
buffer := buf.MultiBufferContainer{}
|
buffer := buf.MultiBufferContainer{}
|
||||||
common.Must2(buffer.Write(b))
|
n, err := buffer.Write(b)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
var writed int
|
|
||||||
for _, buff := range buffer.MultiBuffer {
|
for _, buff := range buffer.MultiBuffer {
|
||||||
err := w.WriteMultiBuffer(buf.MultiBuffer{buff})
|
err := w.WriteMultiBuffer(buf.MultiBuffer{buff})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return writed, err
|
return 0, err
|
||||||
}
|
}
|
||||||
writed += int(buff.Len())
|
|
||||||
}
|
}
|
||||||
return writed, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
package splithttp_test
|
package splithttp_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -422,12 +421,18 @@ func Test_maxUpload(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
uploadReceived := make([]byte, 10001)
|
var uploadSize int
|
||||||
listen, err := ListenXH(context.Background(), net.LocalHostIP, listenPort, streamSettings, func(conn stat.Connection) {
|
listen, err := ListenXH(context.Background(), net.LocalHostIP, listenPort, streamSettings, func(conn stat.Connection) {
|
||||||
go func(c stat.Connection) {
|
go func(c stat.Connection) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
var b [10240]byte
|
||||||
c.SetReadDeadline(time.Now().Add(2 * time.Second))
|
c.SetReadDeadline(time.Now().Add(2 * time.Second))
|
||||||
io.ReadFull(c, uploadReceived)
|
n, err := c.Read(b[:])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadSize = n
|
||||||
|
|
||||||
common.Must2(c.Write([]byte("Response")))
|
common.Must2(c.Write([]byte("Response")))
|
||||||
}(conn)
|
}(conn)
|
||||||
@@ -436,12 +441,10 @@ func Test_maxUpload(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
conn, err := Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), listenPort), streamSettings)
|
conn, err := Dial(ctx, net.TCPDestination(net.DomainAddress("localhost"), listenPort), streamSettings)
|
||||||
common.Must(err)
|
|
||||||
|
|
||||||
// send a slightly too large upload
|
// send a slightly too large upload
|
||||||
upload := make([]byte, 10001)
|
var upload [10001]byte
|
||||||
rand.Read(upload)
|
_, err = conn.Write(upload[:])
|
||||||
_, err = conn.Write(upload)
|
|
||||||
common.Must(err)
|
common.Must(err)
|
||||||
|
|
||||||
var b [10240]byte
|
var b [10240]byte
|
||||||
@@ -452,8 +455,8 @@ func Test_maxUpload(t *testing.T) {
|
|||||||
}
|
}
|
||||||
common.Must(conn.Close())
|
common.Must(conn.Close())
|
||||||
|
|
||||||
if !bytes.Equal(upload, uploadReceived) {
|
if uploadSize > 10000 || uploadSize == 0 {
|
||||||
t.Error("incorrect upload", upload, uploadReceived)
|
t.Error("incorrect upload size: ", uploadSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
common.Must(listen.Close())
|
common.Must(listen.Close())
|
||||||
|
Reference in New Issue
Block a user