mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-08-22 09:36:49 +08:00
Compare commits
83 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
404af13b56 | ||
![]() |
c10bd28731 | ||
![]() |
501d5dec60 | ||
![]() |
d04a9d4fc9 | ||
![]() |
ae97821e40 | ||
![]() |
219a7dac20 | ||
![]() |
a1626cbf94 | ||
![]() |
f7dd84d6b9 | ||
![]() |
ea02ae74ed | ||
![]() |
c15974f7ee | ||
![]() |
13f0eccb8f | ||
![]() |
f0cb292dc6 | ||
![]() |
3654c0d710 | ||
![]() |
f8ec93dfdd | ||
![]() |
980236f2b6 | ||
![]() |
be29cc39d7 | ||
![]() |
9c6685d2ee | ||
![]() |
f5a70e4200 | ||
![]() |
75b3ef71a1 | ||
![]() |
df53afceae | ||
![]() |
459504300c | ||
![]() |
075051a693 | ||
![]() |
bbf25b14d9 | ||
![]() |
89074a14b6 | ||
![]() |
73c5650b17 | ||
![]() |
0a3c449cdf | ||
![]() |
ca07a705dc | ||
![]() |
3120ca4121 | ||
![]() |
9b6141b83f | ||
![]() |
416f2df11c | ||
![]() |
29c6318ffe | ||
![]() |
9ee9a0634e | ||
![]() |
544f7661ca | ||
![]() |
121eb7b4fc | ||
![]() |
3168d27b0b | ||
![]() |
b98d060ee0 | ||
![]() |
26d49df22e | ||
![]() |
1d450cfbd2 | ||
![]() |
017f53b5fc | ||
![]() |
0735053348 | ||
![]() |
e41a61c6f7 | ||
![]() |
a9715295b8 | ||
![]() |
f0b0a7cd4b | ||
![]() |
cefae55d7c | ||
![]() |
84eeb56ae4 | ||
![]() |
eba2906d3a | ||
![]() |
cc2849025d | ||
![]() |
c1ad35fba8 | ||
![]() |
447a49d16a | ||
![]() |
51504c624c | ||
![]() |
98a2e2c7a1 | ||
![]() |
a476310aec | ||
![]() |
b8924782a1 | ||
![]() |
45ab4cb5ba | ||
![]() |
8ce2a0e245 | ||
![]() |
61800fcc66 | ||
![]() |
ae0eec41d8 | ||
![]() |
080bd8241c | ||
![]() |
b356b35312 | ||
![]() |
1593677b09 | ||
![]() |
c85a91bc29 | ||
![]() |
dd16dcec03 | ||
![]() |
e9eec57b46 | ||
![]() |
32f0017449 | ||
![]() |
12f5b05aca | ||
![]() |
befa7b8138 | ||
![]() |
0c61752829 | ||
![]() |
cabc4c6013 | ||
![]() |
fbc56b88da | ||
![]() |
fc41874508 | ||
![]() |
03c20bf3b4 | ||
![]() |
2843167761 | ||
![]() |
021868afca | ||
![]() |
548646fb06 | ||
![]() |
e64fb3ca9b | ||
![]() |
09db7e1cca | ||
![]() |
457c1f65e0 | ||
![]() |
592157bb00 | ||
![]() |
8374d59ce6 | ||
![]() |
ec3b2b0907 | ||
![]() |
4b893fdd22 | ||
![]() |
ec2224974d | ||
![]() |
ba57ccdd45 |
87
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
87
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
name: Bug report
|
||||
description: "Submit Xray-core bug"
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Integrity requirements
|
||||
description: |-
|
||||
Please check all of the following options to prove that you have read and understood the requirements, otherwise this issue will be closed.
|
||||
options:
|
||||
- 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
|
||||
- label: I searched issues and did not find any similar issues.
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version
|
||||
description: Version of Xray-core
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Description
|
||||
description: Please provide a detailed description of the error. And the information you think valuable.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Reproduction Method
|
||||
description: |-
|
||||
Based on the configuration you provided below, provide the method to reproduce the bug.
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |-
|
||||
## Configuration and Log Section
|
||||
|
||||
### For config
|
||||
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.
|
||||
|
||||
### For logs
|
||||
Please set the log level to debug first.
|
||||
Restart Xray-core, then operate according to the reproduction method, try to reduce the irrelevant part in the log.
|
||||
Remember to delete parts with personal information (such as UUID and IP).
|
||||
Provide the log of Xray-core, not the log output by the panel or other things.
|
||||
|
||||
### Finally
|
||||
After removing parts that do not affect reproduction, provide the actual running **complete** file, do not only provide inbound or outbound or a few lines of logs based on your own judgment.
|
||||
Put the content between the preset ```<details><pre><code>``` ```</code></pre></details>``` in the text box.
|
||||
If the problem is very clear that only related to one end (such as core startup failure/crash after correctly writing the config according to the documents), N/A can be filled in for unnecessary areas below.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Client config
|
||||
value: |-
|
||||
<details><pre><code>
|
||||
|
||||
</code></pre></details>
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Server config
|
||||
value: |-
|
||||
<details><pre><code>
|
||||
|
||||
</code></pre></details>
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Client log
|
||||
value: |-
|
||||
<details><pre><code>
|
||||
|
||||
</code></pre></details>
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Server log
|
||||
value: |-
|
||||
<details><pre><code>
|
||||
|
||||
</code></pre></details>
|
||||
validations:
|
||||
required: true
|
87
.github/ISSUE_TEMPLATE/bug_report_zh.yml
vendored
Normal file
87
.github/ISSUE_TEMPLATE/bug_report_zh.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
name: bug反馈
|
||||
description: "提交 Xray-core bug"
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: 完整性要求
|
||||
description: |-
|
||||
请勾选以下所有选项以证明您已经阅读并理解了以下要求,否则该 issue 将被关闭。
|
||||
options:
|
||||
- label: 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
|
||||
required: true
|
||||
- label: 我搜索了issues,没有发现已提出的类似问题。
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: 版本
|
||||
description: 使用的Xray-core版本
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 描述
|
||||
description: 请提供错误的详细描述。以及你认为有价值的信息。
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 重现方式
|
||||
description: |-
|
||||
基于你下面提供的配置,提供重现BUG方法。
|
||||
validations:
|
||||
required: true
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |-
|
||||
## 配置与日志部分
|
||||
|
||||
### 对于配置文件
|
||||
请提供可以重现问题的配置文件,包括服务端和客户端。
|
||||
不要直接在这里黏贴一大段导出的 config 文件。去掉无用的出入站、规则、选项,这可以帮助确定问题,如果你真的想得到帮助。
|
||||
|
||||
### 对于日志
|
||||
请先将日志等级设置为 debug.
|
||||
重启 Xray-core ,再按复现方式操作,尽量减少日志中的无关部分。
|
||||
记得删除有关个人信息(如UUID与IP)的部分。
|
||||
提供 Xray-core 的日志,而不是面板或者别的东西输出的日志。
|
||||
|
||||
### 最后
|
||||
在去掉不影响复现的部分后,提供实际运行的**完整**文件,不要出于自己的判断只提供入站出站或者几行日志。
|
||||
把内容放在文本框预置的 ```<details><pre><code>``` 和 ```</code></pre></details>``` 中间。
|
||||
如果问题十分明确只出现在某一端(如按文档正确编写配置后核心启动失败/崩溃),可以在下面不需要的项目填入N/A.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 客户端配置
|
||||
value: |-
|
||||
<details><pre><code>
|
||||
|
||||
</code></pre></details>
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 服务端配置
|
||||
value: |-
|
||||
<details><pre><code>
|
||||
|
||||
</code></pre></details>
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 客户端日志
|
||||
value: |-
|
||||
<details><pre><code>
|
||||
|
||||
</code></pre></details>
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 服务端日志
|
||||
value: |-
|
||||
<details><pre><code>
|
||||
|
||||
</code></pre></details>
|
||||
validations:
|
||||
required: true
|
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
@@ -1,5 +1,11 @@
|
||||
name: Build and Release
|
||||
|
||||
# NOTE: This Github Actions file depends on the Makefile.
|
||||
# Building the correct package requires the correct binaries generated by the Makefile. To
|
||||
# ensure the correct output, the Makefile must accept the appropriate input and compile the
|
||||
# correct file with the correct name. If you need to modify this file, please ensure it won't
|
||||
# disrupt the Makefile.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
@@ -11,14 +17,14 @@ on:
|
||||
- "**/*.go"
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
- ".github/workflows/*.yml"
|
||||
- ".github/workflows/release.yml"
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
paths:
|
||||
- "**/*.go"
|
||||
- "go.mod"
|
||||
- "go.sum"
|
||||
- ".github/workflows/*.yml"
|
||||
- ".github/workflows/release.yml"
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -177,7 +183,7 @@ jobs:
|
||||
run: |
|
||||
mkdir -p build_assets
|
||||
make
|
||||
find . -maxdepth 1 -type f -regex '.*\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \;
|
||||
find . -maxdepth 1 -type f -regex './\(wxray\|xray\|xray_softfloat\)\(\|.exe\)' -exec mv {} ./build_assets/ \;
|
||||
|
||||
- name: Restore Cache
|
||||
uses: actions/cache/restore@v4
|
||||
@@ -192,6 +198,7 @@ jobs:
|
||||
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
|
||||
|
||||
- name: Create ZIP archive
|
||||
if: github.event_name == 'release'
|
||||
shell: bash
|
||||
run: |
|
||||
pushd build_assets || exit 1
|
||||
|
20
Makefile
20
Makefile
@@ -2,6 +2,17 @@ NAME = xray
|
||||
|
||||
VERSION=$(shell git describe --always --dirty)
|
||||
|
||||
# NOTE: This MAKEFILE can be used to build Xray-core locally and in Automatic workflows. It is \
|
||||
provided for convinience in automatic building and functions as a part of it.
|
||||
# NOTE: If you need to modify this file, please be aware that:\
|
||||
- This file is not the main Makefile; it only accepts environment variables and builds the \
|
||||
binary.\
|
||||
- Automatic building expects the correct binaries to be built by this Makefile. If you \
|
||||
intend to propose a change to this Makefile, carefully review the file below and ensure \
|
||||
that the change will not accidently break the automatic building:\
|
||||
.github/workflows/release.yml \
|
||||
Otherwise it is recommended to contact the project maintainers.
|
||||
|
||||
LDFLAGS = -X github.com/xtls/xray-core/core.build=$(VERSION) -s -w -buildid=
|
||||
PARAMS = -trimpath -ldflags "$(LDFLAGS)" -v
|
||||
MAIN = ./main
|
||||
@@ -12,18 +23,15 @@ ADDITION = go build -o w$(NAME).exe -trimpath -ldflags "-H windowsgui $(LDFLAGS)
|
||||
else
|
||||
OUTPUT = $(NAME)
|
||||
endif
|
||||
ifeq ($(shell echo "$(GOARCH)" | grep -Pq "(mips|mipsle)" && echo true),true) #
|
||||
ifeq ($(shell echo "$(GOARCH)" | grep -Eq "(mips|mipsle)" && echo true),true) #
|
||||
ADDITION = GOMIPS=softfloat go build -o $(NAME)_softfloat -trimpath -ldflags "$(LDFLAGS)" -v $(MAIN)
|
||||
endif
|
||||
.PHONY: clean
|
||||
.PHONY: clean build
|
||||
|
||||
build:
|
||||
go build -o $(OUTPUT) $(PARAMS) $(MAIN)
|
||||
$(ADDITION)
|
||||
|
||||
install:
|
||||
go build -o $(PREFIX)/bin/$(OUTPUT) $(PARAMS) $(MAIN)
|
||||
|
||||
clean:
|
||||
go clean -v -i $(PWD)
|
||||
rm -f xray xray.exe wxray.exe xray_softfloat
|
||||
rm -f xray xray.exe wxray.exe xray_softfloat
|
||||
|
@@ -21,11 +21,10 @@
|
||||
## Installation
|
||||
|
||||
- Linux Script
|
||||
- [XTLS/Xray-install](https://github.com/XTLS/Xray-install)
|
||||
- [team-cloudchaser/tempest](https://github.com/team-cloudchaser/tempest) (supports [`systemd`](https://systemd.io) and [OpenRC](https://github.com/OpenRC/openrc); Linux-only)
|
||||
- [XTLS/Xray-install](https://github.com/XTLS/Xray-install) (**Official**)
|
||||
- [tempest](https://github.com/team-cloudchaser/tempest) (supports [`systemd`](https://systemd.io) and [OpenRC](https://github.com/OpenRC/openrc); Linux-only)
|
||||
- Docker
|
||||
- Official: [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core)
|
||||
- [iamybj/docker-xray](https://hub.docker.com/r/iamybj/docker-xray)
|
||||
- [ghcr.io/xtls/xray-core](https://ghcr.io/xtls/xray-core) (**Official**)
|
||||
- [teddysun/xray](https://hub.docker.com/r/teddysun/xray)
|
||||
- Web Panel
|
||||
- [X-UI-English](https://github.com/NidukaAkalanka/x-ui-english), [3X-UI](https://github.com/MHSanaei/3x-ui), [X-UI](https://github.com/alireza0/x-ui), [X-UI](https://github.com/diditra/x-ui)
|
||||
|
@@ -21,12 +21,14 @@ type Commander struct {
|
||||
services []Service
|
||||
ohm outbound.Manager
|
||||
tag string
|
||||
listen string
|
||||
}
|
||||
|
||||
// NewCommander creates a new Commander based on the given config.
|
||||
func NewCommander(ctx context.Context, config *Config) (*Commander, error) {
|
||||
c := &Commander{
|
||||
tag: config.Tag,
|
||||
tag: config.Tag,
|
||||
listen: config.Listen,
|
||||
}
|
||||
|
||||
common.Must(core.RequireFeatures(ctx, func(om outbound.Manager) {
|
||||
@@ -66,16 +68,29 @@ func (c *Commander) Start() error {
|
||||
}
|
||||
c.Unlock()
|
||||
|
||||
var listen = func(listener net.Listener) {
|
||||
if err := c.server.Serve(listener); err != nil {
|
||||
newError("failed to start grpc server").Base(err).AtError().WriteToLog()
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.listen) > 0 {
|
||||
if l, err := net.Listen("tcp", c.listen); err != nil {
|
||||
newError("API server failed to listen on ", c.listen).Base(err).AtError().WriteToLog()
|
||||
return err
|
||||
} else {
|
||||
newError("API server listening on ", l.Addr()).AtInfo().WriteToLog()
|
||||
go listen(l)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
listener := &OutboundListener{
|
||||
buffer: make(chan net.Conn, 4),
|
||||
done: done.New(),
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := c.server.Serve(listener); err != nil {
|
||||
newError("failed to start grpc server").Base(err).AtError().WriteToLog()
|
||||
}
|
||||
}()
|
||||
go listen(listener)
|
||||
|
||||
if err := c.ohm.RemoveHandler(context.Background(), c.tag); err != nil {
|
||||
newError("failed to remove existing handler").WriteToLog()
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/commander/config.proto
|
||||
|
||||
package commander
|
||||
@@ -29,6 +29,8 @@ type Config struct {
|
||||
|
||||
// Tag of the outbound handler that handles grpc connections.
|
||||
Tag string `protobuf:"bytes,1,opt,name=tag,proto3" json:"tag,omitempty"`
|
||||
// Network address of commander grpc service.
|
||||
Listen string `protobuf:"bytes,3,opt,name=listen,proto3" json:"listen,omitempty"`
|
||||
// Services that supported by this server. All services must implement Service
|
||||
// interface.
|
||||
Service []*serial.TypedMessage `protobuf:"bytes,2,rep,name=service,proto3" json:"service,omitempty"`
|
||||
@@ -73,6 +75,13 @@ func (x *Config) GetTag() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetListen() string {
|
||||
if x != nil {
|
||||
return x.Listen
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetService() []*serial.TypedMessage {
|
||||
if x != nil {
|
||||
return x.Service
|
||||
@@ -127,20 +136,21 @@ var file_app_commander_config_proto_rawDesc = []byte{
|
||||
0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72,
|
||||
0x1a, 0x21, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2f,
|
||||
0x74, 0x79, 0x70, 0x65, 0x64, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a,
|
||||
0x6f, 0x74, 0x6f, 0x22, 0x6e, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a,
|
||||
0x03, 0x74, 0x61, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12,
|
||||
0x3a, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
|
||||
0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61,
|
||||
0x67, 0x65, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x52,
|
||||
0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42,
|
||||
0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61,
|
||||
0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61,
|
||||
0x6e, 0x64, 0x65, 0x72, 0xaa, 0x02, 0x12, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e,
|
||||
0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
0x16, 0x0a, 0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x06, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x12, 0x3a, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79,
|
||||
0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x22, 0x12, 0x0a, 0x10, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x58, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x78,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
|
||||
0x72, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||
0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61,
|
||||
0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65, 0x72, 0xaa, 0x02, 0x12, 0x58,
|
||||
0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x65,
|
||||
0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
@@ -12,6 +12,10 @@ import "common/serial/typed_message.proto";
|
||||
message Config {
|
||||
// Tag of the outbound handler that handles grpc connections.
|
||||
string tag = 1;
|
||||
|
||||
// Network address of commander grpc service.
|
||||
string listen = 3;
|
||||
|
||||
// Services that supported by this server. All services must implement Service
|
||||
// interface.
|
||||
repeated xray.common.serial.TypedMessage service = 2;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/dispatcher/config.proto
|
||||
|
||||
package dispatcher
|
||||
|
@@ -4,6 +4,7 @@ package dispatcher
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -186,8 +187,20 @@ func (d *DefaultDispatcher) shouldOverride(ctx context.Context, result SniffResu
|
||||
return false
|
||||
}
|
||||
for _, d := range request.ExcludeForDomain {
|
||||
if strings.ToLower(domain) == d {
|
||||
return false
|
||||
if strings.HasPrefix(d, "regexp:") {
|
||||
pattern := d[7:]
|
||||
re, err := regexp.Compile(pattern)
|
||||
if err != nil {
|
||||
newError("Unable to compile regex").WriteToLog(session.ExportIDToError(ctx))
|
||||
continue
|
||||
}
|
||||
if re.MatchString(domain) {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if strings.ToLower(domain) == d {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
protocolString := result.Protocol()
|
||||
@@ -218,11 +231,12 @@ func (d *DefaultDispatcher) Dispatch(ctx context.Context, destination net.Destin
|
||||
if !destination.IsValid() {
|
||||
panic("Dispatcher: Invalid destination.")
|
||||
}
|
||||
ob := session.OutboundFromContext(ctx)
|
||||
if ob == nil {
|
||||
ob = &session.Outbound{}
|
||||
ctx = session.ContextWithOutbound(ctx, ob)
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
if len(outbounds) == 0 {
|
||||
outbounds = []*session.Outbound{{}}
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
}
|
||||
ob := outbounds[len(outbounds)-1]
|
||||
ob.OriginalTarget = destination
|
||||
ob.Target = destination
|
||||
content := session.ContentFromContext(ctx)
|
||||
@@ -274,11 +288,12 @@ func (d *DefaultDispatcher) DispatchLink(ctx context.Context, destination net.De
|
||||
if !destination.IsValid() {
|
||||
return newError("Dispatcher: Invalid destination.")
|
||||
}
|
||||
ob := session.OutboundFromContext(ctx)
|
||||
if ob == nil {
|
||||
ob = &session.Outbound{}
|
||||
ctx = session.ContextWithOutbound(ctx, ob)
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
if len(outbounds) == 0 {
|
||||
outbounds = []*session.Outbound{{}}
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
}
|
||||
ob := outbounds[len(outbounds)-1]
|
||||
ob.OriginalTarget = destination
|
||||
ob.Target = destination
|
||||
content := session.ContentFromContext(ctx)
|
||||
@@ -368,7 +383,8 @@ func sniffer(ctx context.Context, cReader *cachedReader, metadataOnly bool, netw
|
||||
return contentResult, contentErr
|
||||
}
|
||||
func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.Link, destination net.Destination) {
|
||||
ob := session.OutboundFromContext(ctx)
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds)-1]
|
||||
if hosts, ok := d.dns.(dns.HostsLookup); ok && destination.Address.Family().IsDomain() {
|
||||
proxied := hosts.LookupHosts(ob.Target.String())
|
||||
if proxied != nil {
|
||||
@@ -425,6 +441,7 @@ func (d *DefaultDispatcher) routedDispatch(ctx context.Context, link *transport.
|
||||
return
|
||||
}
|
||||
|
||||
ob.Tag = handler.Tag()
|
||||
if accessMessage := log.AccessMessageFromContext(ctx); accessMessage != nil {
|
||||
if tag := handler.Tag(); tag != "" {
|
||||
if inTag == "" {
|
||||
|
@@ -26,11 +26,12 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
|
||||
return protocolSnifferWithMetadata{}, errNotInit
|
||||
}
|
||||
return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
|
||||
Target := session.OutboundFromContext(ctx).Target
|
||||
if Target.Network == net.Network_TCP || Target.Network == net.Network_UDP {
|
||||
domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(Target.Address)
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if ob.Target.Network == net.Network_TCP || ob.Target.Network == net.Network_UDP {
|
||||
domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(ob.Target.Address)
|
||||
if domainFromFakeDNS != "" {
|
||||
newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", Target.Address.String()).WriteToLog(session.ExportIDToError(ctx))
|
||||
newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", ob.Target.Address.String()).WriteToLog(session.ExportIDToError(ctx))
|
||||
return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil
|
||||
}
|
||||
}
|
||||
@@ -38,7 +39,7 @@ func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error)
|
||||
if ipAddressInRangeValueI := ctx.Value(ipAddressInRange); ipAddressInRangeValueI != nil {
|
||||
ipAddressInRangeValue := ipAddressInRangeValueI.(*ipAddressInRangeOpt)
|
||||
if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok {
|
||||
inPool := fkr0.IsIPInIPPool(Target.Address)
|
||||
inPool := fkr0.IsIPInIPPool(ob.Target.Address)
|
||||
ipAddressInRangeValue.addressInRange = &inPool
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/dns/config.proto
|
||||
|
||||
package dns
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/dns/fakedns/fakedns.proto
|
||||
|
||||
package fakedns
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/log/command/config.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.23.1
|
||||
// - protoc v5.27.0
|
||||
// source: app/log/command/config.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/log/config.proto
|
||||
|
||||
package log
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/metrics/config.proto
|
||||
|
||||
package metrics
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/observatory/burst/config.proto
|
||||
|
||||
package burst
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/observatory/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.23.1
|
||||
// - protoc v5.27.0
|
||||
// source: app/observatory/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/observatory/config.proto
|
||||
|
||||
package observatory
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/policy/config.proto
|
||||
|
||||
package policy
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/proxyman/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.23.1
|
||||
// - protoc v5.27.0
|
||||
// source: app/proxyman/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/proxyman/config.proto
|
||||
|
||||
package proxyman
|
||||
|
@@ -60,7 +60,7 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
||||
sid := session.NewID()
|
||||
ctx = session.ContextWithID(ctx, sid)
|
||||
|
||||
var outbound = &session.Outbound{}
|
||||
outbounds := []*session.Outbound{{}}
|
||||
if w.recvOrigDest {
|
||||
var dest net.Destination
|
||||
switch getTProxyType(w.stream) {
|
||||
@@ -75,10 +75,10 @@ func (w *tcpWorker) callback(conn stat.Connection) {
|
||||
dest = net.DestinationFromAddr(conn.LocalAddr())
|
||||
}
|
||||
if dest.IsValid() {
|
||||
outbound.Target = dest
|
||||
outbounds[0].Target = dest
|
||||
}
|
||||
}
|
||||
ctx = session.ContextWithOutbound(ctx, outbound)
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
|
||||
if w.uplinkCounter != nil || w.downlinkCounter != nil {
|
||||
conn = &stat.CounterConnection{
|
||||
@@ -308,11 +308,11 @@ func (w *udpWorker) callback(b *buf.Buffer, source net.Destination, originalDest
|
||||
sid := session.NewID()
|
||||
ctx = session.ContextWithID(ctx, sid)
|
||||
|
||||
outbounds := []*session.Outbound{{}}
|
||||
if originalDest.IsValid() {
|
||||
ctx = session.ContextWithOutbound(ctx, &session.Outbound{
|
||||
Target: originalDest,
|
||||
})
|
||||
outbounds[0].Target = originalDest
|
||||
}
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
ctx = session.ContextWithInbound(ctx, &session.Inbound{
|
||||
Source: source,
|
||||
Gateway: net.UDPDestination(w.address, w.port),
|
||||
|
@@ -2,12 +2,8 @@ package outbound
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"io"
|
||||
"math/rand"
|
||||
gonet "net"
|
||||
"os"
|
||||
|
||||
"github.com/xtls/xray-core/app/proxyman"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
@@ -25,6 +21,10 @@ import (
|
||||
"github.com/xtls/xray-core/transport/internet/stat"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"github.com/xtls/xray-core/transport/pipe"
|
||||
"io"
|
||||
"math/big"
|
||||
gonet "net"
|
||||
"os"
|
||||
)
|
||||
|
||||
func getStatCounter(v *core.Instance, tag string) (stats.Counter, stats.Counter) {
|
||||
@@ -169,10 +169,11 @@ func (h *Handler) Tag() string {
|
||||
|
||||
// Dispatch implements proxy.Outbound.Dispatch.
|
||||
func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound.Target.Network == net.Network_UDP && outbound.OriginalTarget.Address != nil && outbound.OriginalTarget.Address != outbound.Target.Address {
|
||||
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: outbound.Target.Address, OriginalDest: outbound.OriginalTarget.Address}
|
||||
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: outbound.Target.Address, OriginalDest: outbound.OriginalTarget.Address}
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if ob.Target.Network == net.Network_UDP && ob.OriginalTarget.Address != nil && ob.OriginalTarget.Address != ob.Target.Address {
|
||||
link.Reader = &buf.EndpointOverrideReader{Reader: link.Reader, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
||||
link.Writer = &buf.EndpointOverrideWriter{Writer: link.Writer, Dest: ob.Target.Address, OriginalDest: ob.OriginalTarget.Address}
|
||||
}
|
||||
if h.mux != nil {
|
||||
test := func(err error) {
|
||||
@@ -183,7 +184,7 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
||||
common.Interrupt(link.Writer)
|
||||
}
|
||||
}
|
||||
if outbound.Target.Network == net.Network_UDP && outbound.Target.Port == 443 {
|
||||
if ob.Target.Network == net.Network_UDP && ob.Target.Port == 443 {
|
||||
switch h.udp443 {
|
||||
case "reject":
|
||||
test(newError("XUDP rejected UDP/443 traffic").AtInfo())
|
||||
@@ -192,7 +193,7 @@ func (h *Handler) Dispatch(ctx context.Context, link *transport.Link) {
|
||||
goto out
|
||||
}
|
||||
}
|
||||
if h.xudp != nil && outbound.Target.Network == net.Network_UDP {
|
||||
if h.xudp != nil && ob.Target.Network == net.Network_UDP {
|
||||
if !h.xudp.Enabled {
|
||||
goto out
|
||||
}
|
||||
@@ -243,10 +244,11 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
||||
handler := h.outboundManager.GetHandler(tag)
|
||||
if handler != nil {
|
||||
newError("proxying to ", tag, " for dest ", dest).AtDebug().WriteToLog(session.ExportIDToError(ctx))
|
||||
ctx = session.ContextWithOutbound(ctx, &session.Outbound{
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ctx = session.ContextWithOutbounds(ctx, append(outbounds, &session.Outbound{
|
||||
Target: dest,
|
||||
})
|
||||
|
||||
Tag: tag,
|
||||
})) // add another outbound in session ctx
|
||||
opts := pipe.OptionsFromContext(ctx)
|
||||
uplinkReader, uplinkWriter := pipe.New(opts...)
|
||||
downlinkReader, downlinkWriter := pipe.New(opts...)
|
||||
@@ -266,15 +268,12 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
||||
}
|
||||
|
||||
if h.senderSettings.Via != nil {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil {
|
||||
outbound = new(session.Outbound)
|
||||
ctx = session.ContextWithOutbound(ctx, outbound)
|
||||
}
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if h.senderSettings.ViaCidr == "" {
|
||||
outbound.Gateway = h.senderSettings.Via.AsAddress()
|
||||
ob.Gateway = h.senderSettings.Via.AsAddress()
|
||||
} else { //Get a random address.
|
||||
outbound.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr)
|
||||
ob.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -285,10 +284,9 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti
|
||||
|
||||
conn, err := internet.Dial(ctx, dest, h.streamSettings)
|
||||
conn = h.getStatCouterConnection(conn)
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound != nil {
|
||||
outbound.Conn = conn
|
||||
}
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
ob.Conn = conn
|
||||
return conn, err
|
||||
}
|
||||
|
||||
@@ -319,16 +317,21 @@ func (h *Handler) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return random IPv6 in a CIDR block
|
||||
|
||||
func ParseRandomIPv6(address net.Address, prefix string) net.Address {
|
||||
addr := address.IP().String()
|
||||
_, network, _ := gonet.ParseCIDR(addr + "/" + prefix)
|
||||
_, network, _ := gonet.ParseCIDR(address.IP().String() + "/" + prefix)
|
||||
|
||||
ipv6 := network.IP.To16()
|
||||
prefixLen, _ := network.Mask.Size()
|
||||
for i := prefixLen / 8; i < 16; i++ {
|
||||
ipv6[i] = byte(rand.Intn(256))
|
||||
}
|
||||
maskSize, totalBits := network.Mask.Size()
|
||||
subnetSize := big.NewInt(1).Lsh(big.NewInt(1), uint(totalBits-maskSize))
|
||||
|
||||
return net.ParseAddress(gonet.IP(ipv6).String())
|
||||
// random
|
||||
randomBigInt, _ := rand.Int(rand.Reader, subnetSize)
|
||||
|
||||
startIPBigInt := big.NewInt(0).SetBytes(network.IP.To16())
|
||||
randomIPBigInt := big.NewInt(0).Add(startIPBigInt, randomBigInt)
|
||||
|
||||
randomIPBytes := randomIPBigInt.Bytes()
|
||||
randomIPBytes = append(make([]byte, 16-len(randomIPBytes)), randomIPBytes...)
|
||||
|
||||
return net.ParseAddress(gonet.IP(randomIPBytes).String())
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ import (
|
||||
"github.com/xtls/xray-core/app/stats"
|
||||
"github.com/xtls/xray-core/common/net"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
core "github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/outbound"
|
||||
"github.com/xtls/xray-core/proxy/freedom"
|
||||
@@ -44,6 +45,7 @@ func TestOutboundWithoutStatCounter(t *testing.T) {
|
||||
v, _ := core.New(config)
|
||||
v.AddFeature((outbound.Manager)(new(Manager)))
|
||||
ctx := context.WithValue(context.Background(), xrayKey, v)
|
||||
ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{{}})
|
||||
h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{
|
||||
Tag: "tag",
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
@@ -73,6 +75,7 @@ func TestOutboundWithStatCounter(t *testing.T) {
|
||||
v, _ := core.New(config)
|
||||
v.AddFeature((outbound.Manager)(new(Manager)))
|
||||
ctx := context.WithValue(context.Background(), xrayKey, v)
|
||||
ctx = session.ContextWithOutbounds(ctx, []*session.Outbound{{}})
|
||||
h, _ := NewHandler(ctx, &core.OutboundHandlerConfig{
|
||||
Tag: "tag",
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/reverse/config.proto
|
||||
|
||||
package reverse
|
||||
|
@@ -62,12 +62,13 @@ func (p *Portal) Close() error {
|
||||
}
|
||||
|
||||
func (p *Portal) HandleConnection(ctx context.Context, link *transport.Link) error {
|
||||
outboundMeta := session.OutboundFromContext(ctx)
|
||||
if outboundMeta == nil {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if ob == nil {
|
||||
return newError("outbound metadata not found").AtError()
|
||||
}
|
||||
|
||||
if isDomain(outboundMeta.Target, p.domain) {
|
||||
if isDomain(ob.Target, p.domain) {
|
||||
muxClient, err := mux.NewClientWorker(*link, mux.ClientStrategy{})
|
||||
if err != nil {
|
||||
return newError("failed to create mux client worker").Base(err).AtWarning()
|
||||
@@ -206,9 +207,10 @@ func NewPortalWorker(client *mux.ClientWorker) (*PortalWorker, error) {
|
||||
downlinkReader, downlinkWriter := pipe.New(opt...)
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = session.ContextWithOutbound(ctx, &session.Outbound{
|
||||
outbounds := []*session.Outbound{{
|
||||
Target: net.UDPDestination(net.DomainAddress(internalDomain), 0),
|
||||
})
|
||||
}}
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
f := client.Dispatch(ctx, &transport.Link{
|
||||
Reader: uplinkReader,
|
||||
Writer: downlinkWriter,
|
||||
|
@@ -4,6 +4,9 @@ import (
|
||||
"context"
|
||||
sync "sync"
|
||||
|
||||
"github.com/xtls/xray-core/app/observatory"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/extension"
|
||||
"github.com/xtls/xray-core/features/outbound"
|
||||
)
|
||||
@@ -17,14 +20,58 @@ type BalancingPrincipleTarget interface {
|
||||
}
|
||||
|
||||
type RoundRobinStrategy struct {
|
||||
FallbackTag string
|
||||
|
||||
ctx context.Context
|
||||
observatory extension.Observatory
|
||||
mu sync.Mutex
|
||||
index int
|
||||
}
|
||||
|
||||
func (s *RoundRobinStrategy) InjectContext(ctx context.Context) {
|
||||
s.ctx = ctx
|
||||
}
|
||||
|
||||
func (s *RoundRobinStrategy) GetPrincipleTarget(strings []string) []string {
|
||||
return strings
|
||||
}
|
||||
|
||||
func (s *RoundRobinStrategy) PickOutbound(tags []string) string {
|
||||
if len(s.FallbackTag) > 0 && s.observatory == nil {
|
||||
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
|
||||
s.observatory = observatory
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
if s.observatory != nil {
|
||||
observeReport, err := s.observatory.GetObservation(s.ctx)
|
||||
if err == nil {
|
||||
aliveTags := make([]string, 0)
|
||||
if result, ok := observeReport.(*observatory.ObservationResult); ok {
|
||||
status := result.Status
|
||||
statusMap := make(map[string]*observatory.OutboundStatus)
|
||||
for _, outboundStatus := range status {
|
||||
statusMap[outboundStatus.OutboundTag] = outboundStatus
|
||||
}
|
||||
for _, candidate := range tags {
|
||||
if outboundStatus, found := statusMap[candidate]; found {
|
||||
if outboundStatus.Alive {
|
||||
aliveTags = append(aliveTags, candidate)
|
||||
}
|
||||
} else {
|
||||
// unfound candidate is considered alive
|
||||
aliveTags = append(aliveTags, candidate)
|
||||
}
|
||||
}
|
||||
tags = aliveTags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
n := len(tags)
|
||||
if n == 0 {
|
||||
panic("0 tags")
|
||||
// goes to fallbackTag
|
||||
return ""
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/router/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.23.1
|
||||
// - protoc v5.27.0
|
||||
// source: app/router/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -135,7 +135,7 @@ func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatch
|
||||
case "roundrobin":
|
||||
return &Balancer{
|
||||
selectors: br.OutboundSelector,
|
||||
strategy: &RoundRobinStrategy{},
|
||||
strategy: &RoundRobinStrategy{FallbackTag: br.FallbackTag},
|
||||
fallbackTag: br.FallbackTag,
|
||||
ohm: ohm,
|
||||
}, nil
|
||||
@@ -162,7 +162,7 @@ func (br *BalancingRule) Build(ohm outbound.Manager, dispatcher routing.Dispatch
|
||||
selectors: br.OutboundSelector,
|
||||
ohm: ohm,
|
||||
fallbackTag: br.FallbackTag,
|
||||
strategy: &RandomStrategy{},
|
||||
strategy: &RandomStrategy{FallbackTag: br.FallbackTag},
|
||||
}, nil
|
||||
default:
|
||||
return nil, newError("unrecognized balancer type")
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/router/config.proto
|
||||
|
||||
package router
|
||||
@@ -864,7 +864,7 @@ type StrategyLeastLoadConfig struct {
|
||||
Baselines []int64 `protobuf:"varint,3,rep,packed,name=baselines,proto3" json:"baselines,omitempty"`
|
||||
// expected nodes count to select
|
||||
Expected int32 `protobuf:"varint,4,opt,name=expected,proto3" json:"expected,omitempty"`
|
||||
// max acceptable rtt, filter away high delay nodes. defalut 0
|
||||
// max acceptable rtt, filter away high delay nodes. default 0
|
||||
MaxRTT int64 `protobuf:"varint,5,opt,name=maxRTT,proto3" json:"maxRTT,omitempty"`
|
||||
// acceptable failure rate
|
||||
Tolerance float32 `protobuf:"fixed32,6,opt,name=tolerance,proto3" json:"tolerance,omitempty"`
|
||||
|
@@ -147,7 +147,7 @@ message StrategyLeastLoadConfig {
|
||||
repeated int64 baselines = 3;
|
||||
// expected nodes count to select
|
||||
int32 expected = 4;
|
||||
// max acceptable rtt, filter away high delay nodes. defalut 0
|
||||
// max acceptable rtt, filter away high delay nodes. default 0
|
||||
int64 maxRTT = 5;
|
||||
// acceptable failure rate
|
||||
float tolerance = 6;
|
||||
|
@@ -45,7 +45,9 @@ func TestSimpleRouter(t *testing.T) {
|
||||
HandlerSelector: mockHs,
|
||||
}, nil))
|
||||
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
|
||||
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.DomainAddress("example.com"), 80),
|
||||
}})
|
||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||
common.Must(err)
|
||||
if tag := route.GetOutboundTag(); tag != "test" {
|
||||
@@ -86,7 +88,9 @@ func TestSimpleBalancer(t *testing.T) {
|
||||
HandlerSelector: mockHs,
|
||||
}, nil))
|
||||
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
|
||||
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.DomainAddress("example.com"), 80),
|
||||
}})
|
||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||
common.Must(err)
|
||||
if tag := route.GetOutboundTag(); tag != "test" {
|
||||
@@ -174,7 +178,9 @@ func TestIPOnDemand(t *testing.T) {
|
||||
r := new(Router)
|
||||
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
||||
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
|
||||
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.DomainAddress("example.com"), 80),
|
||||
}})
|
||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||
common.Must(err)
|
||||
if tag := route.GetOutboundTag(); tag != "test" {
|
||||
@@ -213,7 +219,9 @@ func TestIPIfNonMatchDomain(t *testing.T) {
|
||||
r := new(Router)
|
||||
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
||||
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.DomainAddress("example.com"), 80)})
|
||||
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.DomainAddress("example.com"), 80),
|
||||
}})
|
||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||
common.Must(err)
|
||||
if tag := route.GetOutboundTag(); tag != "test" {
|
||||
@@ -247,7 +255,9 @@ func TestIPIfNonMatchIP(t *testing.T) {
|
||||
r := new(Router)
|
||||
common.Must(r.Init(context.TODO(), config, mockDNS, nil, nil))
|
||||
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: net.TCPDestination(net.LocalHostIP, 80)})
|
||||
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.LocalHostIP, 80),
|
||||
}})
|
||||
route, err := r.PickRoute(routing_session.AsRoutingContext(ctx))
|
||||
common.Must(err)
|
||||
if tag := route.GetOutboundTag(); tag != "test" {
|
||||
|
@@ -1,17 +1,63 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/xtls/xray-core/app/observatory"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/dice"
|
||||
"github.com/xtls/xray-core/core"
|
||||
"github.com/xtls/xray-core/features/extension"
|
||||
)
|
||||
|
||||
// RandomStrategy represents a random balancing strategy
|
||||
type RandomStrategy struct{}
|
||||
type RandomStrategy struct{
|
||||
FallbackTag string
|
||||
|
||||
ctx context.Context
|
||||
observatory extension.Observatory
|
||||
}
|
||||
|
||||
func (s *RandomStrategy) InjectContext(ctx context.Context) {
|
||||
s.ctx = ctx
|
||||
}
|
||||
|
||||
func (s *RandomStrategy) GetPrincipleTarget(strings []string) []string {
|
||||
return strings
|
||||
}
|
||||
|
||||
func (s *RandomStrategy) PickOutbound(candidates []string) string {
|
||||
if len(s.FallbackTag) > 0 && s.observatory == nil {
|
||||
common.Must(core.RequireFeatures(s.ctx, func(observatory extension.Observatory) error {
|
||||
s.observatory = observatory
|
||||
return nil
|
||||
}))
|
||||
}
|
||||
if s.observatory != nil {
|
||||
observeReport, err := s.observatory.GetObservation(s.ctx)
|
||||
if err == nil {
|
||||
aliveTags := make([]string, 0)
|
||||
if result, ok := observeReport.(*observatory.ObservationResult); ok {
|
||||
status := result.Status
|
||||
statusMap := make(map[string]*observatory.OutboundStatus)
|
||||
for _, outboundStatus := range status {
|
||||
statusMap[outboundStatus.OutboundTag] = outboundStatus
|
||||
}
|
||||
for _, candidate := range candidates {
|
||||
if outboundStatus, found := statusMap[candidate]; found {
|
||||
if outboundStatus.Alive {
|
||||
aliveTags = append(aliveTags, candidate)
|
||||
}
|
||||
} else {
|
||||
// unfound candidate is considered alive
|
||||
aliveTags = append(aliveTags, candidate)
|
||||
}
|
||||
}
|
||||
candidates = aliveTags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
count := len(candidates)
|
||||
if count == 0 {
|
||||
// goes to fallbackTag
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/stats/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.3.0
|
||||
// - protoc v4.23.1
|
||||
// - protoc v5.27.0
|
||||
// source: app/stats/command/command.proto
|
||||
|
||||
package command
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: app/stats/config.proto
|
||||
|
||||
package stats
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/log/log.proto
|
||||
|
||||
package log
|
||||
|
@@ -148,9 +148,10 @@ func (f *DialingWorkerFactory) Create() (*ClientWorker, error) {
|
||||
}
|
||||
|
||||
go func(p proxy.Outbound, d internet.Dialer, c common.Closable) {
|
||||
ctx := session.ContextWithOutbound(context.Background(), &session.Outbound{
|
||||
outbounds := []*session.Outbound{{
|
||||
Target: net.TCPDestination(muxCoolAddress, muxCoolPort),
|
||||
})
|
||||
}}
|
||||
ctx := session.ContextWithOutbounds(context.Background(), outbounds)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
if err := p.Process(ctx, &transport.Link{Reader: uplinkReader, Writer: downlinkWriter}, d); err != nil {
|
||||
@@ -242,17 +243,18 @@ func writeFirstPayload(reader buf.Reader, writer *Writer) error {
|
||||
}
|
||||
|
||||
func fetchInput(ctx context.Context, s *Session, output buf.Writer) {
|
||||
dest := session.OutboundFromContext(ctx).Target
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
transferType := protocol.TransferTypeStream
|
||||
if dest.Network == net.Network_UDP {
|
||||
if ob.Target.Network == net.Network_UDP {
|
||||
transferType = protocol.TransferTypePacket
|
||||
}
|
||||
s.transferType = transferType
|
||||
writer := NewWriter(s.ID, dest, output, transferType, xudp.GetGlobalID(ctx))
|
||||
writer := NewWriter(s.ID, ob.Target, output, transferType, xudp.GetGlobalID(ctx))
|
||||
defer s.Close(false)
|
||||
defer writer.Close()
|
||||
|
||||
newError("dispatching request to ", dest).WriteToLog(session.ExportIDToError(ctx))
|
||||
newError("dispatching request to ", ob.Target).WriteToLog(session.ExportIDToError(ctx))
|
||||
if err := writeFirstPayload(s.input, writer); err != nil {
|
||||
newError("failed to write first payload").Base(err).WriteToLog(session.ExportIDToError(ctx))
|
||||
writer.hasError = true
|
||||
|
@@ -86,9 +86,9 @@ func TestClientWorkerClose(t *testing.T) {
|
||||
}
|
||||
|
||||
tr1, tw1 := pipe.New(pipe.WithoutSizeLimit())
|
||||
ctx1 := session.ContextWithOutbound(context.Background(), &session.Outbound{
|
||||
ctx1 := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.DomainAddress("www.example.com"), 80),
|
||||
})
|
||||
}})
|
||||
common.Must(manager.Dispatch(ctx1, &transport.Link{
|
||||
Reader: tr1,
|
||||
Writer: tw1,
|
||||
@@ -103,9 +103,9 @@ func TestClientWorkerClose(t *testing.T) {
|
||||
}
|
||||
|
||||
tr2, tw2 := pipe.New(pipe.WithoutSizeLimit())
|
||||
ctx2 := session.ContextWithOutbound(context.Background(), &session.Outbound{
|
||||
ctx2 := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{
|
||||
Target: net.TCPDestination(net.DomainAddress("www.example.com"), 80),
|
||||
})
|
||||
}})
|
||||
common.Must(manager.Dispatch(ctx2, &transport.Link{
|
||||
Reader: tr2,
|
||||
Writer: tw2,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/net/address.proto
|
||||
|
||||
package net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/net/destination.proto
|
||||
|
||||
package net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/net/network.proto
|
||||
|
||||
package net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/net/port.proto
|
||||
|
||||
package net
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/protocol/headers.proto
|
||||
|
||||
package protocol
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/protocol/server_spec.proto
|
||||
|
||||
package protocol
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/protocol/user.proto
|
||||
|
||||
package protocol
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: common/serial/typed_message.proto
|
||||
|
||||
package serial
|
||||
|
@@ -51,13 +51,13 @@ func InboundFromContext(ctx context.Context) *Inbound {
|
||||
return nil
|
||||
}
|
||||
|
||||
func ContextWithOutbound(ctx context.Context, outbound *Outbound) context.Context {
|
||||
return context.WithValue(ctx, outboundSessionKey, outbound)
|
||||
func ContextWithOutbounds(ctx context.Context, outbounds []*Outbound) context.Context {
|
||||
return context.WithValue(ctx, outboundSessionKey, outbounds)
|
||||
}
|
||||
|
||||
func OutboundFromContext(ctx context.Context) *Outbound {
|
||||
if outbound, ok := ctx.Value(outboundSessionKey).(*Outbound); ok {
|
||||
return outbound
|
||||
func OutboundsFromContext(ctx context.Context) []*Outbound {
|
||||
if outbounds, ok := ctx.Value(outboundSessionKey).([]*Outbound); ok {
|
||||
return outbounds
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -44,24 +44,17 @@ type Inbound struct {
|
||||
Tag string
|
||||
// Name of the inbound proxy that handles the connection.
|
||||
Name string
|
||||
// User is the user that authencates for the inbound. May be nil if the protocol allows anounymous traffic.
|
||||
// User is the user that authenticates for the inbound. May be nil if the protocol allows anonymous traffic.
|
||||
User *protocol.MemoryUser
|
||||
// Conn is actually internet.Connection. May be nil.
|
||||
Conn net.Conn
|
||||
// Timer of the inbound buf copier. May be nil.
|
||||
Timer *signal.ActivityTimer
|
||||
// CanSpliceCopy is a property for this connection, set by both inbound and outbound
|
||||
// CanSpliceCopy is a property for this connection
|
||||
// 1 = can, 2 = after processing protocol info should be able to, 3 = cannot
|
||||
CanSpliceCopy int
|
||||
}
|
||||
|
||||
func(i *Inbound) SetCanSpliceCopy(canSpliceCopy int) int {
|
||||
if canSpliceCopy > i.CanSpliceCopy {
|
||||
i.CanSpliceCopy = canSpliceCopy
|
||||
}
|
||||
return i.CanSpliceCopy
|
||||
}
|
||||
|
||||
// Outbound is the metadata of an outbound connection.
|
||||
type Outbound struct {
|
||||
// Target address of the outbound connection.
|
||||
@@ -70,10 +63,15 @@ type Outbound struct {
|
||||
RouteTarget net.Destination
|
||||
// Gateway address
|
||||
Gateway net.Address
|
||||
// Tag of the outbound proxy that handles the connection.
|
||||
Tag string
|
||||
// Name of the outbound proxy that handles the connection.
|
||||
Name string
|
||||
// Conn is actually internet.Connection. May be nil. It is currently nil for outbound with proxySettings
|
||||
Conn net.Conn
|
||||
// CanSpliceCopy is a property for this connection
|
||||
// 1 = can, 2 = after processing protocol info should be able to, 3 = cannot
|
||||
CanSpliceCopy int
|
||||
}
|
||||
|
||||
// SniffingRequest controls the behavior of content sniffing.
|
||||
|
@@ -43,9 +43,14 @@ func NewOutboundDialer(outbound proxy.Outbound, dialer internet.Dialer) *XrayOut
|
||||
}
|
||||
|
||||
func (d *XrayOutboundDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||
ctx = session.ContextWithOutbound(ctx, &session.Outbound{
|
||||
Target: ToDestination(destination, ToNetwork(network)),
|
||||
})
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
if len(outbounds) == 0 {
|
||||
outbounds = []*session.Outbound{{}}
|
||||
ctx = session.ContextWithOutbounds(ctx, outbounds)
|
||||
}
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
ob.Target = ToDestination(destination, ToNetwork(network))
|
||||
|
||||
opts := []pipe.Option{pipe.WithSizeLimit(64 * 1024)}
|
||||
uplinkReader, uplinkWriter := pipe.New(opts...)
|
||||
downlinkReader, downlinkWriter := pipe.New(opts...)
|
||||
|
@@ -24,7 +24,7 @@ type ConfigLoader func(input interface{}) (*Config, error)
|
||||
// ConfigBuilder is a builder to build core.Config from filenames and formats
|
||||
type ConfigBuilder func(files []string, formats []string) (*Config, error)
|
||||
|
||||
// ConfigMerger merge multiple json configs into on config
|
||||
// ConfigsMerger merge multiple json configs into on config
|
||||
type ConfigsMerger func(files []string, formats []string) (string, error)
|
||||
|
||||
var (
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: core/config.proto
|
||||
|
||||
package core
|
||||
|
@@ -21,7 +21,7 @@ import (
|
||||
var (
|
||||
Version_x byte = 1
|
||||
Version_y byte = 8
|
||||
Version_z byte = 10
|
||||
Version_z byte = 15
|
||||
)
|
||||
|
||||
var (
|
||||
|
@@ -124,9 +124,11 @@ func (ctx *Context) GetSkipDNSResolve() bool {
|
||||
|
||||
// AsRoutingContext creates a context from context.context with session info.
|
||||
func AsRoutingContext(ctx context.Context) routing.Context {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
return &Context{
|
||||
Inbound: session.InboundFromContext(ctx),
|
||||
Outbound: session.OutboundFromContext(ctx),
|
||||
Outbound: ob,
|
||||
Content: session.ContentFromContext(ctx),
|
||||
}
|
||||
}
|
||||
|
50
go.mod
50
go.mod
@@ -3,59 +3,59 @@ module github.com/xtls/xray-core
|
||||
go 1.22
|
||||
|
||||
require (
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0
|
||||
github.com/cloudflare/circl v1.3.9
|
||||
github.com/ghodss/yaml v1.0.1-0.20220118164431-d8423dcdf344
|
||||
github.com/golang/mock v1.7.0-rc.1
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/miekg/dns v1.1.58
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/miekg/dns v1.1.61
|
||||
github.com/pelletier/go-toml v1.9.5
|
||||
github.com/pires/go-proxyproto v0.7.0
|
||||
github.com/quic-go/quic-go v0.42.0
|
||||
github.com/refraction-networking/utls v1.6.3
|
||||
github.com/sagernet/sing v0.3.8
|
||||
github.com/quic-go/quic-go v0.45.0
|
||||
github.com/refraction-networking/utls v1.6.6
|
||||
github.com/sagernet/sing v0.4.1
|
||||
github.com/sagernet/sing-shadowsocks v0.2.6
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230316163032-ced5aaba43e3
|
||||
github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19
|
||||
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc
|
||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||
golang.org/x/crypto v0.21.0
|
||||
golang.org/x/net v0.22.0
|
||||
golang.org/x/sync v0.6.0
|
||||
golang.org/x/sys v0.18.0
|
||||
golang.org/x/crypto v0.24.0
|
||||
golang.org/x/net v0.26.0
|
||||
golang.org/x/sync v0.7.0
|
||||
golang.org/x/sys v0.21.0
|
||||
golang.zx2c4.com/wireguard v0.0.0-20231211153847-12269c276173
|
||||
google.golang.org/grpc v1.62.1
|
||||
google.golang.org/protobuf v1.33.0
|
||||
gvisor.dev/gvisor v0.0.0-20231104011432-48a6d7d5bd0b
|
||||
google.golang.org/grpc v1.64.0
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489
|
||||
h12.io/socks v1.0.3
|
||||
lukechampine.com/blake3 v1.2.1
|
||||
lukechampine.com/blake3 v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
|
||||
github.com/francoispqt/gojay v1.2.13 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect
|
||||
github.com/klauspost/compress v1.17.7 // indirect
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.16.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
|
||||
golang.org/x/mod v0.18.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.19.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
109
go.sum
109
go.sum
@@ -8,6 +8,8 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1
|
||||
dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
|
||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0 h1:Wo41lDOevRJSGpevP+8Pk5bANX7fJacO2w04aqLiC5I=
|
||||
github.com/OmarTariq612/goech v0.0.0-20240405204721-8e2e1dafd3a0/go.mod h1:FVGavL/QEBQDcBpr3fAojoK17xX5k9bicBphrOpP7uM=
|
||||
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
@@ -15,8 +17,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cloudflare/circl v1.3.9 h1:QFrlgFYf2Qpi8bSpVPK1HBvWpx16v/1TZivyo7pGuBE=
|
||||
github.com/cloudflare/circl v1.3.9/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@@ -36,8 +38,8 @@ github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
@@ -47,8 +49,6 @@ github.com/golang/mock v1.7.0-rc.1 h1:YojYx61/OLFsiv6Rw1Z96LpldJIy31o+UHmwAUMJ6/
|
||||
github.com/golang/mock v1.7.0-rc.1/go.mod h1:s42URUywIqd+OcERslBJvOjepvNymP31m3q8d/GkuRs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
@@ -59,13 +59,13 @@ github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+u
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba h1:ql1qNgCyOB7iAEk8JTNM+zJrgIbnyCKX/wdlyPufP5g=
|
||||
github.com/google/pprof v0.0.0-20240528025155-186aa0362fba/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/h12w/go-socks5 v0.0.0-20200522160539-76189e178364 h1:5XxdakFhqd9dnXoAZy1Mb2R/DZ6D1e+0bGC/JhucGYI=
|
||||
@@ -74,30 +74,28 @@ github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
|
||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
|
||||
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM=
|
||||
github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
|
||||
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
|
||||
@@ -112,15 +110,15 @@ github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/quic-go/quic-go v0.42.0 h1:uSfdap0eveIl8KXnipv9K7nlwZ5IqLlYOpJ58u5utpM=
|
||||
github.com/quic-go/quic-go v0.42.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
|
||||
github.com/refraction-networking/utls v1.6.3 h1:MFOfRN35sSx6K5AZNIoESsBuBxS2LCgRilRIdHb6fDc=
|
||||
github.com/refraction-networking/utls v1.6.3/go.mod h1:yil9+7qSl+gBwJqztoQseO6Pr3h62pQoY1lXiNR/FPs=
|
||||
github.com/quic-go/quic-go v0.45.0 h1:OHmkQGM37luZITyTSu6ff03HP/2IrwDX1ZFiNEhSFUE=
|
||||
github.com/quic-go/quic-go v0.45.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
|
||||
github.com/refraction-networking/utls v1.6.6 h1:igFsYBUJPYM8Rno9xUuDoM5GQrVEqY4llzEXOkL43Ig=
|
||||
github.com/refraction-networking/utls v1.6.6/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sagernet/sing v0.3.8 h1:gm4JKalPhydMYX2zFOTnnd4TXtM/16WFRqSjMepYQQk=
|
||||
github.com/sagernet/sing v0.3.8/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI=
|
||||
github.com/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk=
|
||||
github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
|
||||
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
|
||||
@@ -165,8 +163,8 @@ github.com/vishvananda/netlink v1.2.1-beta.2.0.20230316163032-ced5aaba43e3/go.mo
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19 h1:capMfFYRgH9BCLd6A3Er/cH3A9Nz3CU2KwxwOQZIePI=
|
||||
github.com/xtls/reality v0.0.0-20231112171332-de1173cf2b19/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
|
||||
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc h1:0Nj8T1n7F7+v4vRVroaJIvY6R0vNABLfPH+lzPHRJvI=
|
||||
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
@@ -179,17 +177,17 @@ golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnf
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
|
||||
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -201,8 +199,8 @@ golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -214,8 +212,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -228,15 +226,15 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220804214406-8e32c043e418/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
@@ -248,8 +246,8 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
|
||||
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
|
||||
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
|
||||
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -269,19 +267,18 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
|
||||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7 h1:em/y72n4XlYRtayY/cVj6pnVzHa//BDA1BdoO+z9mdE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
|
||||
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@@ -292,14 +289,14 @@ gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
|
||||
gvisor.dev/gvisor v0.0.0-20231104011432-48a6d7d5bd0b h1:yqkg3pTifuKukuWanp8spDsL4irJkHF5WI0J47hU87o=
|
||||
gvisor.dev/gvisor v0.0.0-20231104011432-48a6d7d5bd0b/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk=
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489 h1:ze1vwAdliUAr68RQ5NtufWaXaOg8WUO2OACzEV+TNdE=
|
||||
gvisor.dev/gvisor v0.0.0-20231202080848-1f7806d17489/go.mod h1:10sU+Uh5KKNv1+2x2A0Gvzt8FjD3ASIhorV3YsauXhk=
|
||||
h12.io/socks v1.0.3 h1:Ka3qaQewws4j4/eDQnOdpr4wXsC//dXtWvftlIcCQUo=
|
||||
h12.io/socks v1.0.3/go.mod h1:AIhxy1jOId/XCz9BO+EIgNL2rQiPTBNnOfnVnQ+3Eck=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
|
||||
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||
sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
||||
|
@@ -14,6 +14,7 @@ import (
|
||||
|
||||
type APIConfig struct {
|
||||
Tag string `json:"tag"`
|
||||
Listen string `json:"listen"`
|
||||
Services []string `json:"services"`
|
||||
}
|
||||
|
||||
@@ -42,6 +43,7 @@ func (c *APIConfig) Build() (*commander.Config, error) {
|
||||
|
||||
return &commander.Config{
|
||||
Tag: c.Tag,
|
||||
Listen: c.Listen,
|
||||
Service: services,
|
||||
}, nil
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ type strategyLeastLoadConfig struct {
|
||||
Baselines []duration.Duration `json:"baselines,omitempty"`
|
||||
// expected nodes count to select
|
||||
Expected int32 `json:"expected,omitempty"`
|
||||
// max acceptable rtt, filter away high delay nodes. defalut 0
|
||||
// max acceptable rtt, filter away high delay nodes. default 0
|
||||
MaxRTT duration.Duration `json:"maxRTT,omitempty"`
|
||||
// acceptable failure rate
|
||||
Tolerance float64 `json:"tolerance,omitempty"`
|
||||
|
@@ -97,7 +97,8 @@ func TestRouterConfig(t *testing.T) {
|
||||
"balancers": [
|
||||
{
|
||||
"tag": "b1",
|
||||
"selector": ["test"]
|
||||
"selector": ["test"],
|
||||
"fallbackTag": "fall"
|
||||
},
|
||||
{
|
||||
"tag": "b2",
|
||||
@@ -137,6 +138,7 @@ func TestRouterConfig(t *testing.T) {
|
||||
Tag: "b1",
|
||||
OutboundSelector: []string{"test"},
|
||||
Strategy: "random",
|
||||
FallbackTag: "fall",
|
||||
},
|
||||
{
|
||||
Tag: "b2",
|
||||
|
@@ -16,6 +16,7 @@ type TransportConfig struct {
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
HTTPUPGRADEConfig *HttpUpgradeConfig `json:"httpupgradeSettings"`
|
||||
SplitHTTPConfig *SplitHTTPConfig `json:"splithttpSettings"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -113,5 +114,16 @@ func (c *TransportConfig) Build() (*global.Config, error) {
|
||||
})
|
||||
}
|
||||
|
||||
if c.SplitHTTPConfig != nil {
|
||||
shs, err := c.SplitHTTPConfig.Build()
|
||||
if err != nil {
|
||||
return nil, newError("failed to build SplitHTTP config").Base(err)
|
||||
}
|
||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
||||
ProtocolName: "splithttp",
|
||||
Settings: serial.ToTypedMessage(shs),
|
||||
})
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ import (
|
||||
"github.com/xtls/xray-core/transport/internet/kcp"
|
||||
"github.com/xtls/xray-core/transport/internet/quic"
|
||||
"github.com/xtls/xray-core/transport/internet/reality"
|
||||
"github.com/xtls/xray-core/transport/internet/splithttp"
|
||||
"github.com/xtls/xray-core/transport/internet/tcp"
|
||||
"github.com/xtls/xray-core/transport/internet/tls"
|
||||
"github.com/xtls/xray-core/transport/internet/websocket"
|
||||
@@ -208,8 +209,10 @@ func (c *HttpUpgradeConfig) Build() (proto.Message, error) {
|
||||
// Host priority: Host field > headers field > address.
|
||||
if c.Host == "" && c.Headers["host"] != "" {
|
||||
c.Host = c.Headers["host"]
|
||||
delete(c.Headers,"host")
|
||||
} else if c.Host == "" && c.Headers["Host"] != "" {
|
||||
c.Host = c.Headers["Host"]
|
||||
delete(c.Headers,"Host")
|
||||
}
|
||||
config := &httpupgrade.Config{
|
||||
Path: path,
|
||||
@@ -221,6 +224,34 @@ func (c *HttpUpgradeConfig) Build() (proto.Message, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type SplitHTTPConfig struct {
|
||||
Host string `json:"host"`
|
||||
Path string `json:"path"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
MaxConcurrentUploads int32 `json:"maxConcurrentUploads"`
|
||||
MaxUploadSize int32 `json:"maxUploadSize"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
func (c *SplitHTTPConfig) Build() (proto.Message, error) {
|
||||
// If http host is not set in the Host field, but in headers field, we add it to Host Field here.
|
||||
// If we don't do that, http host will be overwritten as address.
|
||||
// Host priority: Host field > headers field > address.
|
||||
if c.Host == "" && c.Headers["host"] != "" {
|
||||
c.Host = c.Headers["host"]
|
||||
} else if c.Host == "" && c.Headers["Host"] != "" {
|
||||
c.Host = c.Headers["Host"]
|
||||
}
|
||||
config := &splithttp.Config{
|
||||
Path: c.Path,
|
||||
Host: c.Host,
|
||||
Header: c.Headers,
|
||||
MaxConcurrentUploads: c.MaxConcurrentUploads,
|
||||
MaxUploadSize: c.MaxUploadSize,
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
type HTTPConfig struct {
|
||||
Host *StringList `json:"host"`
|
||||
Path string `json:"path"`
|
||||
@@ -392,7 +423,6 @@ type TLSConfig struct {
|
||||
MinVersion string `json:"minVersion"`
|
||||
MaxVersion string `json:"maxVersion"`
|
||||
CipherSuites string `json:"cipherSuites"`
|
||||
PreferServerCipherSuites bool `json:"preferServerCipherSuites"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
RejectUnknownSNI bool `json:"rejectUnknownSni"`
|
||||
PinnedPeerCertificateChainSha256 *[]string `json:"pinnedPeerCertificateChainSha256"`
|
||||
@@ -424,7 +454,6 @@ func (c *TLSConfig) Build() (proto.Message, error) {
|
||||
config.MinVersion = c.MinVersion
|
||||
config.MaxVersion = c.MaxVersion
|
||||
config.CipherSuites = c.CipherSuites
|
||||
config.PreferServerCipherSuites = c.PreferServerCipherSuites
|
||||
config.Fingerprint = strings.ToLower(c.Fingerprint)
|
||||
if config.Fingerprint != "" && tls.GetFingerprint(config.Fingerprint) == nil {
|
||||
return nil, newError(`unknown fingerprint: `, config.Fingerprint)
|
||||
@@ -648,6 +677,8 @@ func (p TransportProtocol) Build() (string, error) {
|
||||
return "grpc", nil
|
||||
case "httpupgrade":
|
||||
return "httpupgrade", nil
|
||||
case "splithttp":
|
||||
return "splithttp", nil
|
||||
default:
|
||||
return "", newError("Config: unknown transport protocol: ", p)
|
||||
}
|
||||
@@ -762,6 +793,7 @@ type StreamConfig struct {
|
||||
GRPCConfig *GRPCConfig `json:"grpcSettings"`
|
||||
GUNConfig *GRPCConfig `json:"gunSettings"`
|
||||
HTTPUPGRADESettings *HttpUpgradeConfig `json:"httpupgradeSettings"`
|
||||
SplitHTTPSettings *SplitHTTPConfig `json:"splithttpSettings"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
@@ -892,6 +924,16 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
Settings: serial.ToTypedMessage(hs),
|
||||
})
|
||||
}
|
||||
if c.SplitHTTPSettings != nil {
|
||||
hs, err := c.SplitHTTPSettings.Build()
|
||||
if err != nil {
|
||||
return nil, newError("Failed to build SplitHTTP config.").Base(err)
|
||||
}
|
||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
||||
ProtocolName: "splithttp",
|
||||
Settings: serial.ToTypedMessage(hs),
|
||||
})
|
||||
}
|
||||
if c.SocketSettings != nil {
|
||||
ss, err := c.SocketSettings.Build()
|
||||
if err != nil {
|
||||
|
@@ -22,14 +22,14 @@ func (c *WireGuardPeerConfig) Build() (proto.Message, error) {
|
||||
config := new(wireguard.PeerConfig)
|
||||
|
||||
if c.PublicKey != "" {
|
||||
config.PublicKey, err = parseWireGuardKey(c.PublicKey)
|
||||
config.PublicKey, err = ParseWireGuardKey(c.PublicKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if c.PreSharedKey != "" {
|
||||
config.PreSharedKey, err = parseWireGuardKey(c.PreSharedKey)
|
||||
config.PreSharedKey, err = ParseWireGuardKey(c.PreSharedKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func (c *WireGuardConfig) Build() (proto.Message, error) {
|
||||
config := new(wireguard.DeviceConfig)
|
||||
|
||||
var err error
|
||||
config.SecretKey, err = parseWireGuardKey(c.SecretKey)
|
||||
config.SecretKey, err = ParseWireGuardKey(c.SecretKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func (c *WireGuardConfig) Build() (proto.Message, error) {
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func parseWireGuardKey(str string) (string, error) {
|
||||
func ParseWireGuardKey(str string) (string, error) {
|
||||
var err error
|
||||
|
||||
if len(str)%2 == 0 {
|
||||
|
@@ -557,6 +557,9 @@ func applyTransportConfig(s *StreamConfig, t *TransportConfig) {
|
||||
if s.HTTPUPGRADESettings == nil {
|
||||
s.HTTPUPGRADESettings = t.HTTPUPGRADEConfig
|
||||
}
|
||||
if s.SplitHTTPSettings == nil {
|
||||
s.SplitHTTPSettings = t.SplitHTTPConfig
|
||||
}
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
|
@@ -174,11 +174,14 @@ func main() {
|
||||
suffix = ".exe"
|
||||
}
|
||||
|
||||
targetedVersion, err := getProjectProtocVersion("https://raw.githubusercontent.com/xtls/xray-core/HEAD/core/config.pb.go")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
/*
|
||||
targetedVersion, err := getProjectProtocVersion("https://raw.githubusercontent.com/XTLS/Xray-core/HEAD/core/config.pb.go")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
*/
|
||||
targetedVersion := ""
|
||||
|
||||
protoc, err := whichProtoc(suffix, targetedVersion)
|
||||
if err != nil {
|
||||
|
@@ -23,5 +23,6 @@ var CmdAPI = &base.Command{
|
||||
cmdRemoveOutbounds,
|
||||
cmdAddRules,
|
||||
cmdRemoveRules,
|
||||
cmdSourceIpBlock,
|
||||
},
|
||||
}
|
||||
|
132
main/commands/all/api/source_ip_block.go
Normal file
132
main/commands/all/api/source_ip_block.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
routerService "github.com/xtls/xray-core/app/router/command"
|
||||
cserial "github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/infra/conf/serial"
|
||||
"github.com/xtls/xray-core/main/commands/base"
|
||||
)
|
||||
|
||||
var cmdSourceIpBlock = &base.Command{
|
||||
CustomFlags: true,
|
||||
UsageLine: "{{.Exec}} api sib [--server=127.0.0.1:8080] -outbound=blocked -inbound=socks 1.2.3.4",
|
||||
Short: "Drop connections by source ip",
|
||||
Long: `
|
||||
Drop connections by source ip.
|
||||
Arguments:
|
||||
-s, -server
|
||||
The API server address. Default 127.0.0.1:8080
|
||||
-t, -timeout
|
||||
Timeout seconds to call API. Default 3
|
||||
-outbound
|
||||
route traffic to specific outbound.
|
||||
-inbound
|
||||
target traffig from specific inbound.
|
||||
-ruletag
|
||||
set ruleTag. Default sourceIpBlock
|
||||
-reset
|
||||
remove ruletag and apply new source IPs. Default false
|
||||
|
||||
Example:
|
||||
{{.Exec}} {{.LongName}} --server=127.0.0.1:8080 c1.json c2.json
|
||||
`,
|
||||
Run: executeSourceIpBlock,
|
||||
}
|
||||
|
||||
func executeSourceIpBlock(cmd *base.Command, args []string) {
|
||||
var (
|
||||
inbound string
|
||||
outbound string
|
||||
ruletag string
|
||||
reset bool
|
||||
)
|
||||
setSharedFlags(cmd)
|
||||
cmd.Flag.StringVar(&inbound, "inbound", "", "")
|
||||
cmd.Flag.StringVar(&outbound, "outbound", "", "")
|
||||
cmd.Flag.StringVar(&ruletag, "ruletag", "sourceIpBlock", "")
|
||||
cmd.Flag.BoolVar(&reset, "reset", false, "")
|
||||
|
||||
cmd.Flag.Parse(args)
|
||||
|
||||
unnamedArgs := cmd.Flag.Args()
|
||||
if len(unnamedArgs) == 0 {
|
||||
fmt.Println("reading from stdin:")
|
||||
unnamedArgs = []string{"stdin:"}
|
||||
}
|
||||
conn, ctx, close := dialAPIServer()
|
||||
defer close()
|
||||
|
||||
client := routerService.NewRoutingServiceClient(conn)
|
||||
|
||||
jsonIps, err := json.Marshal(unnamedArgs)
|
||||
if err != nil {
|
||||
fmt.Println("Error marshaling JSON:", err)
|
||||
return
|
||||
}
|
||||
|
||||
jsonInbound, err := json.Marshal([]string{inbound})
|
||||
if inbound == "" {
|
||||
jsonInbound, err = json.Marshal([]string{})
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Println("Error marshaling JSON:", err)
|
||||
return
|
||||
}
|
||||
stringConfig := fmt.Sprintf(`
|
||||
{
|
||||
"routing": {
|
||||
"rules": [
|
||||
{
|
||||
"ruleTag" : "%s",
|
||||
"inboundTag": %s,
|
||||
"outboundTag": "%s",
|
||||
"type": "field",
|
||||
"source": %s
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
`, ruletag, string(jsonInbound), outbound, string(jsonIps))
|
||||
|
||||
conf, err := serial.DecodeJSONConfig(strings.NewReader(stringConfig))
|
||||
if err != nil {
|
||||
base.Fatalf("failed to decode : %s", err)
|
||||
}
|
||||
rc := *conf.RouterConfig
|
||||
|
||||
config, err := rc.Build()
|
||||
if err != nil {
|
||||
base.Fatalf("failed to build conf: %s", err)
|
||||
}
|
||||
tmsg := cserial.ToTypedMessage(config)
|
||||
if tmsg == nil {
|
||||
base.Fatalf("failed to format config to TypedMessage.")
|
||||
}
|
||||
|
||||
if reset {
|
||||
rr := &routerService.RemoveRuleRequest{
|
||||
RuleTag: ruletag,
|
||||
}
|
||||
resp, err := client.RemoveRule(ctx, rr)
|
||||
if err != nil {
|
||||
base.Fatalf("failed to perform RemoveRule: %s", err)
|
||||
}
|
||||
showJSONResponse(resp)
|
||||
|
||||
}
|
||||
ra := &routerService.AddRuleRequest{
|
||||
Config: tmsg,
|
||||
ShouldAppend: true,
|
||||
}
|
||||
resp, err := client.AddRule(ctx, ra)
|
||||
if err != nil {
|
||||
base.Fatalf("failed to perform AddRule: %s", err)
|
||||
}
|
||||
showJSONResponse(resp)
|
||||
|
||||
}
|
69
main/commands/all/tls/ech.go
Normal file
69
main/commands/all/tls/ech.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package tls
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/OmarTariq612/goech"
|
||||
"github.com/cloudflare/circl/hpke"
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/main/commands/base"
|
||||
)
|
||||
|
||||
var cmdECH = &base.Command{
|
||||
UsageLine: `{{.Exec}} tls ech [--serverName (string)] [--json]`,
|
||||
Short: `Generate TLS-ECH certificates`,
|
||||
Long: `
|
||||
Generate TLS-ECH certificates.
|
||||
|
||||
Set serverName to your custom string: {{.Exec}} tls ech --serverName (string)
|
||||
Generate into json format: {{.Exec}} tls ech --json
|
||||
`, // Enable PQ signature schemes: {{.Exec}} tls ech --pq-signature-schemes-enabled
|
||||
}
|
||||
|
||||
func init() {
|
||||
cmdECH.Run = executeECH
|
||||
}
|
||||
|
||||
var input_pqSignatureSchemesEnabled = cmdECH.Flag.Bool("pqSignatureSchemesEnabled", false, "")
|
||||
var input_serverName = cmdECH.Flag.String("serverName", "cloudflare-ech.com", "")
|
||||
var input_json = cmdECH.Flag.Bool("json", false, "True == turn on json output")
|
||||
|
||||
func executeECH(cmd *base.Command, args []string) {
|
||||
var kem hpke.KEM
|
||||
|
||||
if *input_pqSignatureSchemesEnabled {
|
||||
kem = hpke.KEM_X25519_KYBER768_DRAFT00
|
||||
} else {
|
||||
kem = hpke.KEM_X25519_HKDF_SHA256
|
||||
}
|
||||
|
||||
echKeySet, err := goech.GenerateECHKeySet(0, *input_serverName, kem)
|
||||
common.Must(err)
|
||||
|
||||
configBuffer, _ := echKeySet.ECHConfig.MarshalBinary()
|
||||
keyBuffer, _ := echKeySet.MarshalBinary()
|
||||
|
||||
configPEM := string(pem.EncodeToMemory(&pem.Block{Type: "ECH CONFIGS", Bytes: configBuffer}))
|
||||
keyPEM := string(pem.EncodeToMemory(&pem.Block{Type: "ECH KEYS", Bytes: keyBuffer}))
|
||||
if *input_json {
|
||||
jECHConfigs := map[string]interface{}{
|
||||
"configs": strings.Split(strings.TrimSpace(string(configPEM)), "\n"),
|
||||
}
|
||||
jECHKey := map[string]interface{}{
|
||||
"key": strings.Split(strings.TrimSpace(string(keyPEM)), "\n"),
|
||||
}
|
||||
|
||||
for _, i := range []map[string]interface{}{jECHConfigs, jECHKey} {
|
||||
content, err := json.MarshalIndent(i, "", " ")
|
||||
common.Must(err)
|
||||
os.Stdout.Write(content)
|
||||
os.Stdout.WriteString("\n")
|
||||
}
|
||||
} else {
|
||||
os.Stdout.WriteString(configPEM)
|
||||
os.Stdout.WriteString(keyPEM)
|
||||
}
|
||||
}
|
@@ -14,5 +14,6 @@ var CmdTLS = &base.Command{
|
||||
cmdCert,
|
||||
cmdPing,
|
||||
cmdCertChainHash,
|
||||
cmdECH,
|
||||
},
|
||||
}
|
||||
|
@@ -57,6 +57,7 @@ import (
|
||||
_ "github.com/xtls/xray-core/transport/internet/kcp"
|
||||
_ "github.com/xtls/xray-core/transport/internet/quic"
|
||||
_ "github.com/xtls/xray-core/transport/internet/reality"
|
||||
_ "github.com/xtls/xray-core/transport/internet/splithttp"
|
||||
_ "github.com/xtls/xray-core/transport/internet/tcp"
|
||||
_ "github.com/xtls/xray-core/transport/internet/tls"
|
||||
_ "github.com/xtls/xray-core/transport/internet/udp"
|
||||
|
@@ -31,10 +31,9 @@ func New(ctx context.Context, config *Config) (*Handler, error) {
|
||||
|
||||
// Process implements OutboundHandler.Dispatch().
|
||||
func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound != nil {
|
||||
outbound.Name = "blackhole"
|
||||
}
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
ob.Name = "blackhole"
|
||||
|
||||
nBytes := h.response.WriteTo(link.Writer)
|
||||
if nBytes > 0 {
|
||||
|
@@ -7,13 +7,15 @@ import (
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/buf"
|
||||
"github.com/xtls/xray-core/common/serial"
|
||||
"github.com/xtls/xray-core/common/session"
|
||||
"github.com/xtls/xray-core/proxy/blackhole"
|
||||
"github.com/xtls/xray-core/transport"
|
||||
"github.com/xtls/xray-core/transport/pipe"
|
||||
)
|
||||
|
||||
func TestBlackholeHTTPResponse(t *testing.T) {
|
||||
handler, err := blackhole.New(context.Background(), &blackhole.Config{
|
||||
ctx := session.ContextWithOutbounds(context.Background(), []*session.Outbound{{}})
|
||||
handler, err := blackhole.New(ctx, &blackhole.Config{
|
||||
Response: serial.ToTypedMessage(&blackhole.HTTPResponse{}),
|
||||
})
|
||||
common.Must(err)
|
||||
@@ -32,7 +34,7 @@ func TestBlackholeHTTPResponse(t *testing.T) {
|
||||
Reader: reader,
|
||||
Writer: writer,
|
||||
}
|
||||
common.Must(handler.Process(context.Background(), &link, nil))
|
||||
common.Must(handler.Process(ctx, &link, nil))
|
||||
common.Must(rerr)
|
||||
if mb.IsEmpty() {
|
||||
t.Error("expect http response, but nothing")
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/blackhole/config.proto
|
||||
|
||||
package blackhole
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/dns/config.proto
|
||||
|
||||
package dns
|
||||
|
@@ -96,15 +96,16 @@ func parseIPQuery(b []byte) (r bool, domain string, id uint16, qType dnsmessage.
|
||||
|
||||
// Process implements proxy.Outbound.
|
||||
func (h *Handler) Process(ctx context.Context, link *transport.Link, d internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if !ob.Target.IsValid() {
|
||||
return newError("invalid outbound")
|
||||
}
|
||||
outbound.Name = "dns"
|
||||
ob.Name = "dns"
|
||||
|
||||
srcNetwork := outbound.Target.Network
|
||||
srcNetwork := ob.Target.Network
|
||||
|
||||
dest := outbound.Target
|
||||
dest := ob.Target
|
||||
if h.server.Network != net.Network_Unknown {
|
||||
dest.Network = h.server.Network
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/dokodemo/config.proto
|
||||
|
||||
package dokodemo
|
||||
|
@@ -86,10 +86,15 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
|
||||
|
||||
destinationOverridden := false
|
||||
if d.config.FollowRedirect {
|
||||
if outbound := session.OutboundFromContext(ctx); outbound != nil && outbound.Target.IsValid() {
|
||||
dest = outbound.Target
|
||||
destinationOverridden = true
|
||||
} else if handshake, ok := conn.(hasHandshakeAddressContext); ok {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
if len(outbounds) > 0 {
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if ob.Target.IsValid() {
|
||||
dest = ob.Target
|
||||
destinationOverridden = true
|
||||
}
|
||||
}
|
||||
if handshake, ok := conn.(hasHandshakeAddressContext); ok && !destinationOverridden {
|
||||
addr := handshake.HandshakeAddressContext(ctx)
|
||||
if addr != nil {
|
||||
dest.Address = addr
|
||||
@@ -103,7 +108,7 @@ func (d *DokodemoDoor) Process(ctx context.Context, network net.Network, conn st
|
||||
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
inbound.Name = "dokodemo-door"
|
||||
inbound.SetCanSpliceCopy(1)
|
||||
inbound.CanSpliceCopy = 1
|
||||
inbound.User = &protocol.MemoryUser{
|
||||
Level: d.config.UserLevel,
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/freedom/config.proto
|
||||
|
||||
package freedom
|
||||
|
@@ -106,16 +106,16 @@ func isValidAddress(addr *net.IPOrDomain) bool {
|
||||
|
||||
// Process implements proxy.Outbound.
|
||||
func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if !ob.Target.IsValid() {
|
||||
return newError("target not specified.")
|
||||
}
|
||||
outbound.Name = "freedom"
|
||||
ob.Name = "freedom"
|
||||
ob.CanSpliceCopy = 1
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound != nil {
|
||||
inbound.SetCanSpliceCopy(1)
|
||||
}
|
||||
destination := outbound.Target
|
||||
|
||||
destination := ob.Target
|
||||
UDPOverride := net.UDPDestination(nil, 0)
|
||||
if h.config.DestinationOverride != nil {
|
||||
server := h.config.DestinationOverride.Server
|
||||
@@ -219,10 +219,12 @@ func (h *Handler) Process(ctx context.Context, link *transport.Link, dialer inte
|
||||
defer timer.SetTimeout(plcy.Timeouts.UplinkOnly)
|
||||
if destination.Network == net.Network_TCP {
|
||||
var writeConn net.Conn
|
||||
var inTimer *signal.ActivityTimer
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil && useSplice {
|
||||
writeConn = inbound.Conn
|
||||
inTimer = inbound.Timer
|
||||
}
|
||||
return proxy.CopyRawConnIfExist(ctx, conn, writeConn, link.Writer, timer)
|
||||
return proxy.CopyRawConnIfExist(ctx, conn, writeConn, link.Writer, timer, inTimer)
|
||||
}
|
||||
reader := NewPacketReader(conn, UDPOverride)
|
||||
if err := buf.Copy(reader, output, buf.UpdateActivity(timer)); err != nil {
|
||||
@@ -373,6 +375,9 @@ func (f *FragmentWriter) Write(b []byte) (int, error) {
|
||||
return f.writer.Write(b)
|
||||
}
|
||||
recordLen := 5 + ((int(b[3]) << 8) | int(b[4]))
|
||||
if len(b) < recordLen { // maybe already fragmented somehow
|
||||
return f.writer.Write(b)
|
||||
}
|
||||
data := b[5:recordLen]
|
||||
buf := make([]byte, 1024)
|
||||
for from := 0; ; {
|
||||
|
@@ -69,16 +69,14 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
|
||||
// Process implements proxy.Outbound.Process. We first create a socket tunnel via HTTP CONNECT method, then redirect all inbound traffic to that tunnel.
|
||||
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if !ob.Target.IsValid() {
|
||||
return newError("target not specified.")
|
||||
}
|
||||
outbound.Name = "http"
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound != nil {
|
||||
inbound.SetCanSpliceCopy(2)
|
||||
}
|
||||
target := outbound.Target
|
||||
ob.Name = "http"
|
||||
ob.CanSpliceCopy = 2
|
||||
target := ob.Target
|
||||
targetAddr := target.NetAddr()
|
||||
|
||||
if target.Network == net.Network_UDP {
|
||||
@@ -175,9 +173,10 @@ func fillRequestHeader(ctx context.Context, header []*Header) ([]*Header, error)
|
||||
}
|
||||
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
|
||||
if inbound == nil || outbound == nil {
|
||||
if inbound == nil || ob == nil {
|
||||
return nil, newError("missing inbound or outbound metadata from context")
|
||||
}
|
||||
|
||||
@@ -186,7 +185,7 @@ func fillRequestHeader(ctx context.Context, header []*Header) ([]*Header, error)
|
||||
Target net.Destination
|
||||
}{
|
||||
Source: inbound.Source,
|
||||
Target: outbound.Target,
|
||||
Target: ob.Target,
|
||||
}
|
||||
|
||||
filled := make([]*Header, len(header))
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/http/config.proto
|
||||
|
||||
package http
|
||||
|
@@ -85,7 +85,7 @@ type readerOnly struct {
|
||||
func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
inbound.Name = "http"
|
||||
inbound.SetCanSpliceCopy(2)
|
||||
inbound.CanSpliceCopy = 2
|
||||
inbound.User = &protocol.MemoryUser{
|
||||
Level: s.config.UserLevel,
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/loopback/config.proto
|
||||
|
||||
package loopback
|
||||
|
@@ -22,12 +22,13 @@ type Loopback struct {
|
||||
}
|
||||
|
||||
func (l *Loopback) Process(ctx context.Context, link *transport.Link, _ internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if !ob.Target.IsValid() {
|
||||
return newError("target not specified.")
|
||||
}
|
||||
outbound.Name = "loopback"
|
||||
destination := outbound.Target
|
||||
ob.Name = "loopback"
|
||||
destination := ob.Target
|
||||
|
||||
newError("opening connection to ", destination).WriteToLog(session.ExportIDToError(ctx))
|
||||
|
||||
|
108
proxy/proxy.go
108
proxy/proxy.go
@@ -470,49 +470,81 @@ func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
|
||||
// CopyRawConnIfExist use the most efficient copy method.
|
||||
// - If caller don't want to turn on splice, do not pass in both reader conn and writer conn
|
||||
// - writer are from *transport.Link
|
||||
func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net.Conn, writer buf.Writer, timer signal.ActivityUpdater) error {
|
||||
func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net.Conn, writer buf.Writer, timer *signal.ActivityTimer, inTimer *signal.ActivityTimer) error {
|
||||
readerConn, readCounter, _ := UnwrapRawConn(readerConn)
|
||||
writerConn, _, writeCounter := UnwrapRawConn(writerConn)
|
||||
reader := buf.NewReader(readerConn)
|
||||
if inbound := session.InboundFromContext(ctx); inbound != nil {
|
||||
if tc, ok := writerConn.(*net.TCPConn); ok && readerConn != nil && writerConn != nil && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
|
||||
for inbound.CanSpliceCopy != 3 {
|
||||
if inbound.CanSpliceCopy == 1 {
|
||||
newError("CopyRawConn splice").WriteToLog(session.ExportIDToError(ctx))
|
||||
statWriter, _ := writer.(*dispatcher.SizeStatWriter)
|
||||
//runtime.Gosched() // necessary
|
||||
time.Sleep(time.Millisecond) // without this, there will be a rare ssl error for freedom splice
|
||||
w, err := tc.ReadFrom(readerConn)
|
||||
if readCounter != nil {
|
||||
readCounter.Add(w) // outbound stats
|
||||
}
|
||||
if writeCounter != nil {
|
||||
writeCounter.Add(w) // inbound stats
|
||||
}
|
||||
if statWriter != nil {
|
||||
statWriter.Counter.Add(w) // user stats
|
||||
}
|
||||
if err != nil && errors.Cause(err) != io.EOF {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
buffer, err := reader.ReadMultiBuffer()
|
||||
if !buffer.IsEmpty() {
|
||||
if readCounter != nil {
|
||||
readCounter.Add(int64(buffer.Len()))
|
||||
}
|
||||
timer.Update()
|
||||
if werr := writer.WriteMultiBuffer(buffer); werr != nil {
|
||||
return werr
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if runtime.GOOS != "linux" && runtime.GOOS != "android" {
|
||||
return readV(ctx, reader, writer, timer, readCounter)
|
||||
}
|
||||
tc, ok := writerConn.(*net.TCPConn)
|
||||
if !ok || readerConn == nil || writerConn == nil {
|
||||
return readV(ctx, reader, writer, timer, readCounter)
|
||||
}
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound == nil || inbound.CanSpliceCopy == 3 {
|
||||
return readV(ctx, reader, writer, timer, readCounter)
|
||||
}
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
if len(outbounds) == 0 {
|
||||
return readV(ctx, reader, writer, timer, readCounter)
|
||||
}
|
||||
for _, ob := range outbounds {
|
||||
if ob.CanSpliceCopy == 3 {
|
||||
return readV(ctx, reader, writer, timer, readCounter)
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
var splice = inbound.CanSpliceCopy == 1
|
||||
for _, ob := range outbounds {
|
||||
if ob.CanSpliceCopy != 1 {
|
||||
splice = false
|
||||
}
|
||||
}
|
||||
if splice {
|
||||
newError("CopyRawConn splice").WriteToLog(session.ExportIDToError(ctx))
|
||||
statWriter, _ := writer.(*dispatcher.SizeStatWriter)
|
||||
//runtime.Gosched() // necessary
|
||||
time.Sleep(time.Millisecond) // without this, there will be a rare ssl error for freedom splice
|
||||
timer.SetTimeout(8 * time.Hour) // prevent leak, just in case
|
||||
if inTimer != nil {
|
||||
inTimer.SetTimeout(8 * time.Hour)
|
||||
}
|
||||
w, err := tc.ReadFrom(readerConn)
|
||||
if readCounter != nil {
|
||||
readCounter.Add(w) // outbound stats
|
||||
}
|
||||
if writeCounter != nil {
|
||||
writeCounter.Add(w) // inbound stats
|
||||
}
|
||||
if statWriter != nil {
|
||||
statWriter.Counter.Add(w) // user stats
|
||||
}
|
||||
if err != nil && errors.Cause(err) != io.EOF {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
buffer, err := reader.ReadMultiBuffer()
|
||||
if !buffer.IsEmpty() {
|
||||
if readCounter != nil {
|
||||
readCounter.Add(int64(buffer.Len()))
|
||||
}
|
||||
timer.Update()
|
||||
if werr := writer.WriteMultiBuffer(buffer); werr != nil {
|
||||
return werr
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readV(ctx context.Context, reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, readCounter stats.Counter) error {
|
||||
newError("CopyRawConn readv").WriteToLog(session.ExportIDToError(ctx))
|
||||
if err := buf.Copy(reader, writer, buf.UpdateActivity(timer), buf.AddToStatCounter(readCounter)); err != nil {
|
||||
return newError("failed to process response").Base(err)
|
||||
|
@@ -49,16 +49,14 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
|
||||
// Process implements OutboundHandler.Process().
|
||||
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if !ob.Target.IsValid() {
|
||||
return newError("target not specified")
|
||||
}
|
||||
outbound.Name = "shadowsocks"
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound != nil {
|
||||
inbound.SetCanSpliceCopy(3)
|
||||
}
|
||||
destination := outbound.Target
|
||||
ob.Name = "shadowsocks"
|
||||
ob.CanSpliceCopy = 3
|
||||
destination := ob.Target
|
||||
network := destination.Network
|
||||
|
||||
var server *protocol.ServerSpec
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/shadowsocks/config.proto
|
||||
|
||||
package shadowsocks
|
||||
|
@@ -73,7 +73,7 @@ func (s *Server) Network() []net.Network {
|
||||
func (s *Server) Process(ctx context.Context, network net.Network, conn stat.Connection, dispatcher routing.Dispatcher) error {
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
inbound.Name = "shadowsocks"
|
||||
inbound.SetCanSpliceCopy(3)
|
||||
inbound.CanSpliceCopy = 3
|
||||
|
||||
switch network {
|
||||
case net.Network_TCP:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/shadowsocks_2022/config.proto
|
||||
|
||||
package shadowsocks_2022
|
||||
|
@@ -66,7 +66,7 @@ func (i *Inbound) Network() []net.Network {
|
||||
func (i *Inbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
inbound.Name = "shadowsocks-2022"
|
||||
inbound.SetCanSpliceCopy(3)
|
||||
inbound.CanSpliceCopy = 3
|
||||
|
||||
var metadata M.Metadata
|
||||
if inbound.Source.IsValid() {
|
||||
|
@@ -155,7 +155,7 @@ func (i *MultiUserInbound) Network() []net.Network {
|
||||
func (i *MultiUserInbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
inbound.Name = "shadowsocks-2022-multi"
|
||||
inbound.SetCanSpliceCopy(3)
|
||||
inbound.CanSpliceCopy = 3
|
||||
|
||||
var metadata M.Metadata
|
||||
if inbound.Source.IsValid() {
|
||||
|
@@ -87,7 +87,7 @@ func (i *RelayInbound) Network() []net.Network {
|
||||
func (i *RelayInbound) Process(ctx context.Context, network net.Network, connection stat.Connection, dispatcher routing.Dispatcher) error {
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
inbound.Name = "shadowsocks-2022-relay"
|
||||
inbound.SetCanSpliceCopy(3)
|
||||
inbound.CanSpliceCopy = 3
|
||||
|
||||
var metadata M.Metadata
|
||||
if inbound.Source.IsValid() {
|
||||
|
@@ -65,15 +65,16 @@ func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer int
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound != nil {
|
||||
inboundConn = inbound.Conn
|
||||
inbound.SetCanSpliceCopy(3)
|
||||
}
|
||||
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if !ob.Target.IsValid() {
|
||||
return newError("target not specified")
|
||||
}
|
||||
outbound.Name = "shadowsocks-2022"
|
||||
destination := outbound.Target
|
||||
ob.Name = "shadowsocks-2022"
|
||||
ob.CanSpliceCopy = 3
|
||||
destination := ob.Target
|
||||
network := destination.Network
|
||||
|
||||
newError("tunneling request to ", destination, " via ", o.server.NetAddr()).WriteToLog(session.ExportIDToError(ctx))
|
||||
|
@@ -57,17 +57,15 @@ func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
|
||||
// Process implements proxy.Outbound.Process.
|
||||
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
outbounds := session.OutboundsFromContext(ctx)
|
||||
ob := outbounds[len(outbounds) - 1]
|
||||
if !ob.Target.IsValid() {
|
||||
return newError("target not specified.")
|
||||
}
|
||||
outbound.Name = "socks"
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound != nil {
|
||||
inbound.SetCanSpliceCopy(2)
|
||||
}
|
||||
ob.Name = "socks"
|
||||
ob.CanSpliceCopy = 2
|
||||
// Destination of the inner request.
|
||||
destination := outbound.Target
|
||||
destination := ob.Target
|
||||
|
||||
// Outbound server.
|
||||
var server *protocol.ServerSpec
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.33.0
|
||||
// protoc v4.23.1
|
||||
// protoc-gen-go v1.34.1
|
||||
// protoc v5.27.0
|
||||
// source: proxy/socks/config.proto
|
||||
|
||||
package socks
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user