mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-16 05:40:48 +08:00
重构代码, 支持 use as library.
现在根目录作为一个可用的库,而可执行文件的代码放在 cmd/verysimple 文件夹中。 只是粗略地使其能够运行,有待进一步重构完善。 同时更新了 Makefile 和 .github/workflows
This commit is contained in:
6
.github/workflows/build_release.yml
vendored
6
.github/workflows/build_release.yml
vendored
@@ -24,18 +24,18 @@ jobs:
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
make -f Makefile_release PACK=1 BUILD_VERSION=${{ steps.get_version.outputs.VERSION }}
|
||||
cd cmd/verysimple/ && make -f Makefile_release main PACK=1 BUILD_VERSION=${{ steps.get_version.outputs.VERSION }}
|
||||
|
||||
- name: touch xz archive
|
||||
shell: bash
|
||||
run: |
|
||||
touch -mt $(date +%Y01010000) *.tar.xz
|
||||
cd cmd/verysimple/ && touch -mt $(date +%Y01010000) *.tar.xz
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
if: github.event_name == 'release'
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./*.tar.xz
|
||||
file: cmd/verysimple/*.tar.xz
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
||||
|
37
.github/workflows/build_release_extra.yml
vendored
Normal file
37
.github/workflows/build_release_extra.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Build For Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.18
|
||||
|
||||
- name: Get version
|
||||
id: get_version
|
||||
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
make -f Makefile_release extra PACK=1 BUILD_VERSION=${{ steps.get_version.outputs.VERSION }}
|
||||
|
||||
- name: touch xz archive
|
||||
shell: bash
|
||||
run: |
|
||||
touch -mt $(date +%Y01010000) *.tar.xz
|
||||
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./*.tar.xz
|
||||
tag: ${{ github.ref }}
|
||||
file_glob: true
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -4,7 +4,7 @@ client.toml
|
||||
server.toml
|
||||
v2ray_simple
|
||||
v2ray_simple_*
|
||||
verysimple
|
||||
cmd/verysimple/verysimple
|
||||
verysimple_*
|
||||
*.exe
|
||||
*.DS_Store
|
||||
|
109
Makefile
109
Makefile
@@ -1,107 +1,2 @@
|
||||
# 该Makefile 只支持linux中使用. 不过幸亏golang厉害,交叉编译相当简单
|
||||
#
|
||||
# for building with filename "verysimple" and pack into verysimple_xxx.tgz:
|
||||
# make PACK=1
|
||||
#
|
||||
# 简单起见,该makefile只支持64位
|
||||
#
|
||||
# for embedding geoip file:
|
||||
# make tags="embed_geoip" macm1
|
||||
#
|
||||
# 目前发布版直接使用go1.18编译,你如果想编译出相同文件,也要使用go1.18才行
|
||||
|
||||
# 现在该Makefile文件不用来编译发布包,所以这里版本可以随便自己填了,我们也不用每更新一个官方版本就改动一次文件.
|
||||
# 很棒吧.
|
||||
# 现在这个Makefile文件是你自己的了,随便改.
|
||||
# 不过 现在 BUILD_VERSION 默认会获取当前git 的 commit id, 你可以自行改成任何值, 比如注释掉第二行, 用第一行
|
||||
# BUILD_VERSION :=myversion
|
||||
BUILD_VERSION := $(shell git rev-parse --short HEAD)
|
||||
|
||||
prefix :=verysimple
|
||||
|
||||
linuxAmd :=_linux_amd64
|
||||
linuxArm :=_linux_arm64
|
||||
androidArm64 :=_android_arm64
|
||||
macosAmd :=_macos
|
||||
macosArm :=_macm1
|
||||
windows :=_win10
|
||||
|
||||
#这些Fn变量是用于发布包压缩包的名称,不是可执行文件名称,可执行文件统一叫 verysimple
|
||||
|
||||
linuxAmdFn:=${prefix}${linuxAmd}
|
||||
linuxArmFn:=${prefix}${linuxArm}
|
||||
macFn :=${prefix}${macosAmd}
|
||||
macM1Fn :=${prefix}${macosArm}
|
||||
winFn :=${prefix}${windows}
|
||||
androidArm64Fn :=${prefix}${androidArm64}
|
||||
|
||||
|
||||
cmd:=go build -tags $(tags) -trimpath -ldflags "-X 'main.Version=${BUILD_VERSION}' -s -w -buildid=" -o
|
||||
|
||||
|
||||
ifdef PACK
|
||||
define compile
|
||||
CGO_ENABLED=0 GOOS=$(2) GOARCH=$(3) $(cmd) $(1)
|
||||
mv $(1) verysimple$(4)
|
||||
tar -cJf $(1).tar.xz verysimple$(4) examples/
|
||||
rm verysimple$(4)
|
||||
endef
|
||||
|
||||
else
|
||||
|
||||
define compile
|
||||
CGO_ENABLED=0 GOOS=$(2) GOARCH=$(3) $(cmd) $(1)$(4)
|
||||
endef
|
||||
endif
|
||||
|
||||
|
||||
all: linux_amd64 linux_arm64 android_arm64 macos macm1 win10
|
||||
|
||||
getver:
|
||||
@echo $(BUILD_VERSION)
|
||||
|
||||
#注意调用参数时,逗号前后不能留空格
|
||||
|
||||
linux_amd64:
|
||||
$(call compile, $(linuxAmdFn),linux,amd64)
|
||||
|
||||
linux_arm64:
|
||||
$(call compile, $(linuxArmFn),linux,arm64)
|
||||
|
||||
android_arm64:
|
||||
$(call compile, $(androidArm64Fn),android,arm64)
|
||||
|
||||
macos:
|
||||
$(call compile, $(macFn),darwin,amd64)
|
||||
|
||||
#提供macos 的apple silicon版本.
|
||||
macm1:
|
||||
$(call compile, $(macM1Fn),darwin,arm64)
|
||||
|
||||
win10:
|
||||
$(call compile, $(winFn),windows,amd64,.exe)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f verysimple
|
||||
rm -f verysimple.exe
|
||||
|
||||
rm -f $(linuxAmdFn)
|
||||
rm -f $(linuxArmFn)
|
||||
rm -f ${winFn}.exe
|
||||
rm -f $(macFn)
|
||||
rm -f $(macM1Fn)
|
||||
rm -f $(androidArm64Fn)
|
||||
|
||||
rm -f $(linuxAmdFn).tar.xz
|
||||
rm -f $(linuxArmFn).tar.xz
|
||||
rm -f ${winFn}.tar.xz
|
||||
rm -f $(macFn).tar.xz
|
||||
rm -f $(macM1Fn).tar.xz
|
||||
rm -f $(androidArm64Fn).tar.xz
|
||||
|
||||
rmlog:
|
||||
rm -f vs_log
|
||||
rm -f vs_log_client
|
||||
rm -f vs_log_server
|
||||
|
||||
all:
|
||||
cd cmd/verysimple/ && make verysimple_cmd
|
@@ -1,69 +1,2 @@
|
||||
#BUILD_VERSION := vx.x.x-beta.x 这个将在github action里自动通过tag配置, 参见 .github/workflows/build_release.yml
|
||||
|
||||
prefix :=verysimple
|
||||
|
||||
cmd:=go build -tags $(tags) -trimpath -ldflags "-X 'main.Version=${BUILD_VERSION}' -s -w -buildid=" -o
|
||||
|
||||
|
||||
ifdef PACK
|
||||
define compile
|
||||
CGO_ENABLED=0 GOOS=$(2) GOARCH=$(3) GOARM=$(5) $(cmd) $(1)
|
||||
mv $(1) verysimple$(4)
|
||||
tar -cJf $(1).tar.xz verysimple$(4) examples/
|
||||
rm verysimple$(4)
|
||||
endef
|
||||
|
||||
else
|
||||
|
||||
define compile
|
||||
CGO_ENABLED=0 GOOS=$(2) GOARCH=$(3) $(cmd) $(1)$(4)
|
||||
endef
|
||||
endif
|
||||
|
||||
|
||||
all: linux_amd64 linux_arm64 android_arm64 macos macm1 win10 win10_arm
|
||||
|
||||
extra: linux_arm32_v7 linux_mips64 linux_mips win32
|
||||
|
||||
# 注意调用参数时,逗号前后不能留空格
|
||||
# 关于arm版本号 https://github.com/goreleaser/goreleaser/issues/36
|
||||
|
||||
linux_amd64:
|
||||
$(call compile, ${prefix}_linux_amd64,linux,amd64)
|
||||
|
||||
linux_arm64:
|
||||
$(call compile, ${prefix}_linux_arm64,linux,arm64)
|
||||
|
||||
linux_arm32_v7:
|
||||
$(call compile, ${prefix}_linux_arm32_v7a,linux,arm,,7)
|
||||
|
||||
linux_mips64:
|
||||
$(call compile, ${prefix}_linux_mips64,linux,mips64)
|
||||
|
||||
linux_mips:
|
||||
$(call compile, ${prefix}_linux_mips,linux,mips)
|
||||
|
||||
android_arm64:
|
||||
$(call compile, ${prefix}_android_arm64,android,arm64)
|
||||
|
||||
macos:
|
||||
$(call compile, ${prefix}_macOS_intel,darwin,amd64)
|
||||
|
||||
macm1:
|
||||
$(call compile, ${prefix}_macOS_apple,darwin,arm64)
|
||||
|
||||
win32:
|
||||
$(call compile, ${prefix}_win32,windows,386,.exe)
|
||||
|
||||
win10:
|
||||
$(call compile, ${prefix}_win10,windows,amd64,.exe)
|
||||
|
||||
win10_arm:
|
||||
$(call compile, ${prefix}_win10_arm64,windows,arm64,.exe)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f ${prefix}
|
||||
rm -f ${prefix}.exe
|
||||
rm -f ${prefix}_*
|
||||
rm -f *.tar.xz
|
||||
all:
|
||||
cd cmd/verysimple/ && make -f Makefile_release main
|
11
README.md
11
README.md
@@ -483,6 +483,17 @@ https://github.com/e1732a364fed/v2ray_simple/discussions/3
|
||||
|
||||
对于功能的golang test,请使用 `go test ./... -count=1` 命令。如果要详细的打印出test的过程,可以添加 -v 参数
|
||||
|
||||
内网测试命令示例:
|
||||
|
||||
在 cmd/verysimple 文件夹中, 打开两个终端,
|
||||
```
|
||||
./verysimple -c ../../examples/quic.client.toml -ll 0
|
||||
```
|
||||
|
||||
```
|
||||
./verysimple -c ../../examples/quic.server.toml -ll 0
|
||||
```
|
||||
|
||||
## 测速
|
||||
|
||||
测试环境:ubuntu虚拟机, 使用开源测试工具
|
||||
|
108
cmd/verysimple/Makefile
Normal file
108
cmd/verysimple/Makefile
Normal file
@@ -0,0 +1,108 @@
|
||||
# 该Makefile 只支持linux中使用. 不过幸亏golang厉害,交叉编译相当简单
|
||||
#
|
||||
# for building with filename "verysimple" and pack into verysimple_xxx.tgz:
|
||||
# make PACK=1
|
||||
#
|
||||
# 简单起见,该makefile只支持64位
|
||||
#
|
||||
# for embedding geoip file:
|
||||
# make tags="embed_geoip" macm1
|
||||
#
|
||||
# 目前发布版直接使用go1.18编译,你如果想编译出相同文件,也要使用go1.18才行
|
||||
|
||||
# 现在该Makefile文件不用来编译发布包,所以这里版本可以随便自己填了,我们也不用每更新一个官方版本就改动一次文件.
|
||||
# 很棒吧.
|
||||
# 现在这个Makefile文件是你自己的了,随便改.
|
||||
# 不过 现在 BUILD_VERSION 默认会获取当前git 的 commit id, 你可以自行改成任何值, 比如注释掉第二行, 用第一行
|
||||
# BUILD_VERSION :=myversion
|
||||
BUILD_VERSION := $(shell git rev-parse --short HEAD)
|
||||
|
||||
prefix :=verysimple
|
||||
|
||||
linuxAmd :=_linux_amd64
|
||||
linuxArm :=_linux_arm64
|
||||
androidArm64 :=_android_arm64
|
||||
macosAmd :=_macos
|
||||
macosArm :=_macm1
|
||||
windows :=_win10
|
||||
|
||||
#这些Fn变量是用于发布包压缩包的名称,不是可执行文件名称,可执行文件统一叫 verysimple
|
||||
|
||||
linuxAmdFn:=${prefix}${linuxAmd}
|
||||
linuxArmFn:=${prefix}${linuxArm}
|
||||
macFn :=${prefix}${macosAmd}
|
||||
macM1Fn :=${prefix}${macosArm}
|
||||
winFn :=${prefix}${windows}
|
||||
androidArm64Fn :=${prefix}${androidArm64}
|
||||
|
||||
|
||||
cmd:=go build -tags $(tags) -trimpath -ldflags "-X 'main.Version=${BUILD_VERSION}' -s -w -buildid=" -o
|
||||
|
||||
|
||||
ifdef PACK
|
||||
define compile
|
||||
CGO_ENABLED=0 GOOS=$(2) GOARCH=$(3) $(cmd) $(1)
|
||||
mv $(1) verysimple$(4)
|
||||
tar -cJf $(1).tar.xz verysimple$(4) -C ../../ examples/
|
||||
rm verysimple$(4)
|
||||
endef
|
||||
|
||||
else
|
||||
|
||||
define compile
|
||||
CGO_ENABLED=0 GOOS=$(2) GOARCH=$(3) $(cmd) $(1)$(4)
|
||||
endef
|
||||
endif
|
||||
|
||||
|
||||
verysimple_cmd: linux_amd64 linux_arm64 android_arm64 macos macm1 win10
|
||||
@echo "make verysimple cmd"
|
||||
|
||||
getver:
|
||||
@echo $(BUILD_VERSION)
|
||||
|
||||
#注意调用参数时,逗号前后不能留空格
|
||||
|
||||
linux_amd64:
|
||||
$(call compile, $(linuxAmdFn),linux,amd64)
|
||||
|
||||
linux_arm64:
|
||||
$(call compile, $(linuxArmFn),linux,arm64)
|
||||
|
||||
android_arm64:
|
||||
$(call compile, $(androidArm64Fn),android,arm64)
|
||||
|
||||
macos:
|
||||
$(call compile, $(macFn),darwin,amd64)
|
||||
|
||||
#提供macos 的apple silicon版本.
|
||||
macm1:
|
||||
$(call compile, $(macM1Fn),darwin,arm64)
|
||||
|
||||
win10:
|
||||
$(call compile, $(winFn),windows,amd64,.exe)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f verysimple
|
||||
rm -f verysimple.exe
|
||||
|
||||
rm -f $(linuxAmdFn)
|
||||
rm -f $(linuxArmFn)
|
||||
rm -f ${winFn}.exe
|
||||
rm -f $(macFn)
|
||||
rm -f $(macM1Fn)
|
||||
rm -f $(androidArm64Fn)
|
||||
|
||||
rm -f $(linuxAmdFn).tar.xz
|
||||
rm -f $(linuxArmFn).tar.xz
|
||||
rm -f ${winFn}.tar.xz
|
||||
rm -f $(macFn).tar.xz
|
||||
rm -f $(macM1Fn).tar.xz
|
||||
rm -f $(androidArm64Fn).tar.xz
|
||||
|
||||
rmlog:
|
||||
rm -f vs_log
|
||||
rm -f vs_log_client
|
||||
rm -f vs_log_server
|
||||
|
69
cmd/verysimple/Makefile_release
Normal file
69
cmd/verysimple/Makefile_release
Normal file
@@ -0,0 +1,69 @@
|
||||
#BUILD_VERSION := vx.x.x-beta.x 这个将在github action里自动通过tag配置, 参见 .github/workflows/build_release.yml
|
||||
|
||||
prefix :=verysimple
|
||||
|
||||
cmd:=go build -tags $(tags) -trimpath -ldflags "-X 'main.Version=${BUILD_VERSION}' -s -w -buildid=" -o
|
||||
|
||||
|
||||
ifdef PACK
|
||||
define compile
|
||||
CGO_ENABLED=0 GOOS=$(2) GOARCH=$(3) GOARM=$(5) $(cmd) $(1)
|
||||
mv $(1) verysimple$(4)
|
||||
tar -cJf $(1).tar.xz verysimple$(4) -C ../../ examples/
|
||||
rm verysimple$(4)
|
||||
endef
|
||||
|
||||
else
|
||||
|
||||
define compile
|
||||
CGO_ENABLED=0 GOOS=$(2) GOARCH=$(3) $(cmd) $(1)$(4)
|
||||
endef
|
||||
endif
|
||||
|
||||
|
||||
main: linux_amd64 linux_arm64 android_arm64 macos macm1 win10 win10_arm
|
||||
|
||||
extra: linux_arm32_v7 linux_mips64 linux_mips win32
|
||||
|
||||
# 注意调用参数时,逗号前后不能留空格
|
||||
# 关于arm版本号 https://github.com/goreleaser/goreleaser/issues/36
|
||||
|
||||
linux_amd64:
|
||||
$(call compile, ${prefix}_linux_amd64,linux,amd64)
|
||||
|
||||
linux_arm64:
|
||||
$(call compile, ${prefix}_linux_arm64,linux,arm64)
|
||||
|
||||
linux_arm32_v7:
|
||||
$(call compile, ${prefix}_linux_arm32_v7a,linux,arm,,7)
|
||||
|
||||
linux_mips64:
|
||||
$(call compile, ${prefix}_linux_mips64,linux,mips64)
|
||||
|
||||
linux_mips:
|
||||
$(call compile, ${prefix}_linux_mips,linux,mips)
|
||||
|
||||
android_arm64:
|
||||
$(call compile, ${prefix}_android_arm64,android,arm64)
|
||||
|
||||
macos:
|
||||
$(call compile, ${prefix}_macOS_intel,darwin,amd64)
|
||||
|
||||
macm1:
|
||||
$(call compile, ${prefix}_macOS_apple,darwin,arm64)
|
||||
|
||||
win32:
|
||||
$(call compile, ${prefix}_win32,windows,386,.exe)
|
||||
|
||||
win10:
|
||||
$(call compile, ${prefix}_win10,windows,amd64,.exe)
|
||||
|
||||
win10_arm:
|
||||
$(call compile, ${prefix}_win10_arm64,windows,arm64,.exe)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f ${prefix}
|
||||
rm -f ${prefix}.exe
|
||||
rm -f ${prefix}_*
|
||||
rm -f *.tar.xz
|
@@ -8,6 +8,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
vs "github.com/e1732a364fed/v2ray_simple"
|
||||
|
||||
"github.com/asaskevich/govalidator"
|
||||
"github.com/e1732a364fed/v2ray_simple/advLayer/quic"
|
||||
"github.com/e1732a364fed/v2ray_simple/netLayer"
|
||||
@@ -193,8 +195,8 @@ func generateConfigFileInteractively() {
|
||||
"将此次生成的配置投入运行(热加载)",
|
||||
}
|
||||
|
||||
confClient := StandardConf{}
|
||||
confServer := StandardConf{}
|
||||
confClient := vs.StandardConf{}
|
||||
confServer := vs.StandardConf{}
|
||||
|
||||
var clientStr, serverStr string
|
||||
|
||||
@@ -220,7 +222,7 @@ func generateConfigFileInteractively() {
|
||||
Domains: []string{"geosite:cn"},
|
||||
}}
|
||||
|
||||
confClient.App = &AppConf{MyCountryISO_3166: "CN"}
|
||||
confClient.App = &vs.AppConf{MyCountryISO_3166: "CN"}
|
||||
|
||||
clientStr, err = utils.GetPurgedTomlStr(confClient)
|
||||
if err != nil {
|
||||
@@ -247,8 +249,8 @@ func generateConfigFileInteractively() {
|
||||
fmt.Printf("\n")
|
||||
|
||||
case 2: //clear
|
||||
confClient = StandardConf{}
|
||||
confServer = StandardConf{}
|
||||
confClient = vs.StandardConf{}
|
||||
confServer = vs.StandardConf{}
|
||||
clientStr = ""
|
||||
serverStr = ""
|
||||
case 3: //output
|
||||
@@ -632,10 +634,10 @@ func interactively_hotRemoveServerOrClient() {
|
||||
printAllState(os.Stdout)
|
||||
|
||||
var items []string
|
||||
if len(allServers) > 0 {
|
||||
if len(vs.AllServers) > 0 {
|
||||
items = append(items, "listen")
|
||||
}
|
||||
if len(allClients) > 0 {
|
||||
if len(vs.AllClients) > 0 {
|
||||
items = append(items, "dial")
|
||||
}
|
||||
|
||||
@@ -665,7 +667,7 @@ func interactively_hotRemoveServerOrClient() {
|
||||
|
||||
var theInt int64
|
||||
|
||||
if (will_delete_dial && len(allClients) > 1) || (will_delete_listen && len(allServers) > 1) {
|
||||
if (will_delete_dial && len(vs.AllClients) > 1) || (will_delete_listen && len(vs.AllServers) > 1) {
|
||||
|
||||
validateFunc := func(input string) error {
|
||||
theInt, err = strconv.ParseInt(input, 10, 64)
|
||||
@@ -673,11 +675,11 @@ func interactively_hotRemoveServerOrClient() {
|
||||
return errors.New("Invalid number")
|
||||
}
|
||||
|
||||
if will_delete_dial && int(theInt) >= len(allClients) {
|
||||
if will_delete_dial && int(theInt) >= len(vs.AllClients) {
|
||||
return errors.New("must with in len of dial array")
|
||||
}
|
||||
|
||||
if will_delete_listen && int(theInt) >= len(allServers) {
|
||||
if will_delete_listen && int(theInt) >= len(vs.AllServers) {
|
||||
return errors.New("must with in len of listen array")
|
||||
}
|
||||
|
||||
@@ -705,15 +707,15 @@ func interactively_hotRemoveServerOrClient() {
|
||||
will_delete_index = int(theInt)
|
||||
|
||||
if will_delete_dial {
|
||||
allClients[will_delete_index].Stop()
|
||||
allClients = utils.TrimSlice(allClients, will_delete_index)
|
||||
vs.AllClients[will_delete_index].Stop()
|
||||
vs.AllClients = utils.TrimSlice(vs.AllClients, will_delete_index)
|
||||
}
|
||||
if will_delete_listen {
|
||||
listenerArray[will_delete_index].Close()
|
||||
allServers[will_delete_index].Stop()
|
||||
vs.ListenerArray[will_delete_index].Close()
|
||||
vs.AllServers[will_delete_index].Stop()
|
||||
|
||||
allServers = utils.TrimSlice(allServers, will_delete_index)
|
||||
listenerArray = utils.TrimSlice(listenerArray, will_delete_index)
|
||||
vs.AllServers = utils.TrimSlice(vs.AllServers, will_delete_index)
|
||||
vs.ListenerArray = utils.TrimSlice(vs.ListenerArray, will_delete_index)
|
||||
|
||||
}
|
||||
|
||||
@@ -755,7 +757,7 @@ func interactively_hotLoadConfigFile() {
|
||||
|
||||
fmt.Printf("你输入了 %s\n", fpath)
|
||||
|
||||
standardConf, err = LoadTomlConfFile(fpath)
|
||||
standardConf, err = vs.LoadTomlConfFile(fpath)
|
||||
if err != nil {
|
||||
|
||||
log.Printf("can not load standard config file: %s\n", err)
|
@@ -9,6 +9,8 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
vs "github.com/e1732a364fed/v2ray_simple"
|
||||
|
||||
"github.com/e1732a364fed/v2ray_simple/advLayer"
|
||||
"github.com/e1732a364fed/v2ray_simple/netLayer"
|
||||
"github.com/e1732a364fed/v2ray_simple/proxy"
|
||||
@@ -128,16 +130,16 @@ func tryDownloadMMDB() {
|
||||
}
|
||||
|
||||
func printAllState(w io.Writer) {
|
||||
fmt.Fprintln(w, "activeConnectionCount", activeConnectionCount)
|
||||
fmt.Fprintln(w, "allDownloadBytesSinceStart", allDownloadBytesSinceStart)
|
||||
fmt.Fprintln(w, "allUploadBytesSinceStart", allUploadBytesSinceStart)
|
||||
fmt.Fprintln(w, "activeConnectionCount", vs.ActiveConnectionCount)
|
||||
fmt.Fprintln(w, "allDownloadBytesSinceStart", vs.AllDownloadBytesSinceStart)
|
||||
fmt.Fprintln(w, "allUploadBytesSinceStart", vs.AllUploadBytesSinceStart)
|
||||
|
||||
for i, s := range allServers {
|
||||
for i, s := range vs.AllServers {
|
||||
fmt.Fprintln(w, "inServer", i, proxy.GetFullName(s), s.AddrStr())
|
||||
|
||||
}
|
||||
|
||||
for i, c := range allClients {
|
||||
for i, c := range vs.AllClients {
|
||||
fmt.Fprintln(w, "outClient", i, proxy.GetFullName(c), c.AddrStr())
|
||||
}
|
||||
}
|
||||
@@ -148,8 +150,8 @@ func tryDownloadGeositeSourceFromConfiguredProxy() {
|
||||
|
||||
var outClient proxy.Client
|
||||
|
||||
if defaultOutClient != nil {
|
||||
outClient = defaultOutClient
|
||||
if vs.DefaultOutClient != nil {
|
||||
outClient = vs.DefaultOutClient
|
||||
fmt.Println("trying to download geosite through your proxy dial")
|
||||
} else {
|
||||
fmt.Println("trying to download geosite directly")
|
||||
@@ -165,7 +167,7 @@ func tryDownloadGeositeSourceFromConfiguredProxy() {
|
||||
protocol = "http"
|
||||
`
|
||||
|
||||
clientConf, err := LoadTomlConfStr(tempClientConfStr)
|
||||
clientConf, err := vs.LoadTomlConfStr(tempClientConfStr)
|
||||
if err != nil {
|
||||
fmt.Println("can not create LoadTomlConfStr: ", err)
|
||||
|
||||
@@ -180,7 +182,7 @@ protocol = "http"
|
||||
listenAddrStr := netLayer.GetRandLocalPrivateAddr(true, false)
|
||||
clientEndInServer.SetAddrStr(listenAddrStr)
|
||||
|
||||
listener = listenSer(clientEndInServer, outClient, false)
|
||||
listener = vs.ListenSer(clientEndInServer, outClient, false)
|
||||
|
||||
proxyurl = "http://" + listenAddrStr
|
||||
|
||||
@@ -200,10 +202,10 @@ func hotLoadDialConfForRuntime(conf []*proxy.DialConf) {
|
||||
log.Println("can not create outClient: ", err)
|
||||
return
|
||||
}
|
||||
if defaultOutClient == nil {
|
||||
defaultOutClient = outClient
|
||||
if vs.DefaultOutClient == nil {
|
||||
vs.DefaultOutClient = outClient
|
||||
}
|
||||
allClients = append(allClients, outClient)
|
||||
vs.AllClients = append(vs.AllClients, outClient)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -215,8 +217,8 @@ func hotLoadListenConfForRuntime(conf []*proxy.ListenConf) {
|
||||
log.Println("can not create inServer: ", err)
|
||||
return
|
||||
}
|
||||
listenSer(inServer, defaultOutClient, true)
|
||||
allServers = append(allServers, inServer)
|
||||
vs.ListenSer(inServer, vs.DefaultOutClient, true)
|
||||
vs.AllServers = append(vs.AllServers, inServer)
|
||||
|
||||
}
|
||||
|
269
cmd/verysimple/main.go
Normal file
269
cmd/verysimple/main.go
Normal file
@@ -0,0 +1,269 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
vs "github.com/e1732a364fed/v2ray_simple"
|
||||
"github.com/e1732a364fed/v2ray_simple/netLayer"
|
||||
"github.com/e1732a364fed/v2ray_simple/proxy"
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
"github.com/pkg/profile"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
configFileName string
|
||||
standardConf vs.StandardConf
|
||||
|
||||
startPProf bool
|
||||
startMProf bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&configFileName, "c", "client.toml", "config file name")
|
||||
flag.BoolVar(&startPProf, "pp", false, "pprof")
|
||||
flag.BoolVar(&startMProf, "mp", false, "memory pprof")
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
os.Exit(mainFunc())
|
||||
}
|
||||
|
||||
func mainFunc() (result int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if ce := utils.CanLogFatal("Captured panic!"); ce != nil {
|
||||
ce.Write(zap.Any("err:", r))
|
||||
} else {
|
||||
log.Fatalln("panic captured!", r)
|
||||
}
|
||||
|
||||
result = -3
|
||||
}
|
||||
}()
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if cmdPrintVer {
|
||||
printVersion_simple()
|
||||
//根据 cmdPrintVer 的定义, 我们直接退出
|
||||
return
|
||||
} else {
|
||||
printVersion()
|
||||
|
||||
}
|
||||
|
||||
if !utils.IsFlagGiven("lf") {
|
||||
if strings.Contains(configFileName, "server") {
|
||||
utils.LogOutFileName += "_server"
|
||||
} else if strings.Contains(configFileName, "client") {
|
||||
utils.LogOutFileName += "_client"
|
||||
}
|
||||
}
|
||||
|
||||
utils.ShouldLogToFile = true
|
||||
|
||||
utils.InitLog()
|
||||
|
||||
if startPProf {
|
||||
f, _ := os.OpenFile("cpu.pprof", os.O_CREATE|os.O_RDWR, 0644)
|
||||
defer f.Close()
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
|
||||
}
|
||||
if startMProf {
|
||||
//若不使用 NoShutdownHook, 我们ctrl+c退出时不会产生 pprof文件
|
||||
p := profile.Start(profile.MemProfile, profile.MemProfileRate(1), profile.NoShutdownHook)
|
||||
|
||||
defer p.Stop()
|
||||
}
|
||||
|
||||
utils.Info("Program started")
|
||||
defer utils.Info("Program exited")
|
||||
var err error
|
||||
if standardConf, err = vs.LoadConfig(configFileName); err != nil && !isFlexible() {
|
||||
log.Printf("no config exist, and no api server or interactive cli enabled, exiting...")
|
||||
return -1
|
||||
}
|
||||
|
||||
netLayer.Prepare()
|
||||
|
||||
fmt.Printf("Log Level:%d\n", utils.LogLevel)
|
||||
fmt.Printf("UseReadv:%t\n", netLayer.UseReadv)
|
||||
fmt.Printf("tls_lazy_encrypt:%t\n", vs.Tls_lazy_encrypt)
|
||||
|
||||
runPreCommands()
|
||||
|
||||
var defaultInServer proxy.Server
|
||||
|
||||
//load inServers and vs.RoutePolicy
|
||||
switch vs.ConfMode {
|
||||
case vs.SimpleMode:
|
||||
var hase bool
|
||||
var eie utils.ErrInErr
|
||||
defaultInServer, hase, eie = proxy.ServerFromURL(vs.SimpleConf.Server_ThatListenPort_Url)
|
||||
if hase {
|
||||
if ce := utils.CanLogErr("can not create local server"); ce != nil {
|
||||
ce.Write(zap.Error(eie))
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
if !defaultInServer.CantRoute() && vs.SimpleConf.Route != nil {
|
||||
|
||||
netLayer.LoadMaxmindGeoipFile("")
|
||||
|
||||
//极简模式只支持通过 mycountry进行 geoip分流 这一种情况
|
||||
vs.RoutePolicy = netLayer.NewRoutePolicy()
|
||||
if vs.SimpleConf.MyCountryISO_3166 != "" {
|
||||
vs.RoutePolicy.AddRouteSet(netLayer.NewRouteSetForMyCountry(vs.SimpleConf.MyCountryISO_3166))
|
||||
|
||||
}
|
||||
}
|
||||
case vs.StandardMode:
|
||||
|
||||
vs.LoadCommonComponentsFromStandardConf(&standardConf)
|
||||
|
||||
//虽然标准模式支持多个Server,目前先只考虑一个
|
||||
//多个Server存在的话,则必须要用 tag指定路由; 然后,我们需在预先阶段就判断好tag指定的路由
|
||||
|
||||
if len(standardConf.Listen) < 1 {
|
||||
utils.Warn("no listen in config settings")
|
||||
break
|
||||
}
|
||||
|
||||
for _, serverConf := range standardConf.Listen {
|
||||
thisConf := serverConf
|
||||
if thisConf.Protocol == "tproxy" {
|
||||
vs.ListenTproxy(thisConf.GetAddrStrForListenOrDial())
|
||||
continue
|
||||
}
|
||||
|
||||
if thisConf.Uuid == "" && vs.Default_uuid != "" {
|
||||
thisConf.Uuid = vs.Default_uuid
|
||||
}
|
||||
|
||||
thisServer, err := proxy.NewServer(thisConf)
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("can not create local server:"); ce != nil {
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
vs.AllServers = append(vs.AllServers, thisServer)
|
||||
if tag := thisServer.GetTag(); tag != "" {
|
||||
vs.ServersTagMap[tag] = thisServer
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// load outClients
|
||||
switch vs.ConfMode {
|
||||
case vs.SimpleMode:
|
||||
var hase bool
|
||||
var eie utils.ErrInErr
|
||||
vs.DefaultOutClient, hase, eie = proxy.ClientFromURL(vs.SimpleConf.Client_ThatDialRemote_Url)
|
||||
if hase {
|
||||
if ce := utils.CanLogErr("can not create remote client"); ce != nil {
|
||||
ce.Write(zap.Error(eie))
|
||||
}
|
||||
return -1
|
||||
}
|
||||
case vs.StandardMode:
|
||||
|
||||
if len(standardConf.Dial) < 1 {
|
||||
utils.Warn("no dial in config settings")
|
||||
break
|
||||
}
|
||||
|
||||
for _, thisConf := range standardConf.Dial {
|
||||
if thisConf.Uuid == "" && vs.Default_uuid != "" {
|
||||
thisConf.Uuid = vs.Default_uuid
|
||||
}
|
||||
|
||||
thisClient, err := proxy.NewClient(thisConf)
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("can not create remote client: "); ce != nil {
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
vs.AllClients = append(vs.AllClients, thisClient)
|
||||
|
||||
if tag := thisClient.GetTag(); tag != "" {
|
||||
vs.ClientsTagMap[tag] = thisClient
|
||||
}
|
||||
}
|
||||
|
||||
if len(vs.AllClients) > 0 {
|
||||
vs.DefaultOutClient = vs.AllClients[0]
|
||||
|
||||
} else {
|
||||
vs.DefaultOutClient = vs.DirectClient
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
configFileQualifiedToRun := false
|
||||
|
||||
if (defaultInServer != nil || len(vs.AllServers) > 0 || len(vs.TproxyList) > 0) && (vs.DefaultOutClient != nil) {
|
||||
configFileQualifiedToRun = true
|
||||
|
||||
if vs.ConfMode == vs.SimpleMode {
|
||||
vs.ListenSer(defaultInServer, vs.DefaultOutClient, true)
|
||||
} else {
|
||||
for _, inServer := range vs.AllServers {
|
||||
vs.ListenSer(inServer, vs.DefaultOutClient, true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//没配置可用的listen或者dial,而且还无法动态更改配置
|
||||
if !configFileQualifiedToRun && !isFlexible() {
|
||||
utils.Error("No valid proxy settings available, exit now.")
|
||||
return -1
|
||||
}
|
||||
|
||||
if enableApiServer {
|
||||
go checkConfigAndTryRunApiServer()
|
||||
|
||||
}
|
||||
|
||||
if interactive_mode {
|
||||
runCli()
|
||||
}
|
||||
|
||||
{
|
||||
osSignals := make(chan os.Signal, 1)
|
||||
signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM)
|
||||
<-osSignals
|
||||
|
||||
utils.Info("Program got close signal.")
|
||||
|
||||
//在程序ctrl+C关闭时, 会主动Close所有的监听端口. 主要是被报告windows有时退出程序之后, 端口还是处于占用状态.
|
||||
// 用下面代码以试图解决端口占用问题.
|
||||
|
||||
for _, listener := range vs.ListenerArray {
|
||||
if listener != nil {
|
||||
listener.Close()
|
||||
}
|
||||
}
|
||||
|
||||
for _, tm := range vs.TproxyList {
|
||||
tm.Stop()
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package v2ray_simple
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
32
configs.go
32
configs.go
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package v2ray_simple
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -70,7 +70,7 @@ func LoadTomlConfFile(fileNamePath string) (StandardConf, error) {
|
||||
}
|
||||
|
||||
//mainfallback, dnsMachine, routePolicy
|
||||
func loadCommonComponentsFromStandardConf() {
|
||||
func LoadCommonComponentsFromStandardConf(standardConf *StandardConf) {
|
||||
|
||||
if len(standardConf.Fallbacks) != 0 {
|
||||
mainFallback = httpLayer.NewClassicFallbackFromConfList(standardConf.Fallbacks)
|
||||
@@ -98,18 +98,18 @@ func loadCommonComponentsFromStandardConf() {
|
||||
|
||||
netLayer.LoadMaxmindGeoipFile("")
|
||||
|
||||
routePolicy = netLayer.NewRoutePolicy()
|
||||
RoutePolicy = netLayer.NewRoutePolicy()
|
||||
if hasAppLevelMyCountry {
|
||||
routePolicy.AddRouteSet(netLayer.NewRouteSetForMyCountry(standardConf.App.MyCountryISO_3166))
|
||||
RoutePolicy.AddRouteSet(netLayer.NewRouteSetForMyCountry(standardConf.App.MyCountryISO_3166))
|
||||
|
||||
}
|
||||
|
||||
netLayer.LoadRulesForRoutePolicy(standardConf.Route, routePolicy)
|
||||
netLayer.LoadRulesForRoutePolicy(standardConf.Route, RoutePolicy)
|
||||
}
|
||||
}
|
||||
|
||||
// 先检查configFileName是否存在,存在就尝试加载文件到 standardConf 或者 simpleConf,否则尝试 -L参数
|
||||
func loadConfig() (err error) {
|
||||
func LoadConfig(configFileName string) (standardConf StandardConf, err error) {
|
||||
|
||||
fpath := utils.GetFilePath(configFileName)
|
||||
if fpath != "" {
|
||||
@@ -123,11 +123,11 @@ func loadConfig() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
confMode = 1
|
||||
ConfMode = 1
|
||||
|
||||
//loglevel 和 noreadv这种会被 命令行覆盖的配置,需要直接在 loadConfig函数中先处理一遍
|
||||
if appConf := standardConf.App; appConf != nil {
|
||||
default_uuid = appConf.DefaultUUID
|
||||
Default_uuid = appConf.DefaultUUID
|
||||
|
||||
if appConf.LogLevel != nil && !utils.IsFlagGiven("ll") {
|
||||
utils.LogLevel = *appConf.LogLevel
|
||||
@@ -146,19 +146,19 @@ func loadConfig() (err error) {
|
||||
// 默认所有json格式的文件都为 极简模式
|
||||
|
||||
var hasE bool
|
||||
simpleConf, hasE, err = proxy.LoadSimpleConfigFile(fpath)
|
||||
SimpleConf, hasE, err = proxy.LoadSimpleConfigFile(fpath)
|
||||
if hasE {
|
||||
|
||||
log.Printf("can not load simple config file: %s\n", err)
|
||||
return
|
||||
}
|
||||
if simpleConf.Fallbacks != nil {
|
||||
mainFallback = httpLayer.NewClassicFallbackFromConfList(simpleConf.Fallbacks)
|
||||
if SimpleConf.Fallbacks != nil {
|
||||
mainFallback = httpLayer.NewClassicFallbackFromConfList(SimpleConf.Fallbacks)
|
||||
}
|
||||
confMode = 0
|
||||
ConfMode = 0
|
||||
|
||||
if simpleConf.Client_ThatDialRemote_Url == "" {
|
||||
simpleConf.Client_ThatDialRemote_Url = "direct://"
|
||||
if SimpleConf.Client_ThatDialRemote_Url == "" {
|
||||
SimpleConf.Client_ThatDialRemote_Url = "direct://"
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -172,7 +172,7 @@ func loadConfig() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
simpleConf = proxy.SimpleConf{
|
||||
SimpleConf = proxy.SimpleConf{
|
||||
Server_ThatListenPort_Url: listenURL,
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ func loadConfig() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
simpleConf.Client_ThatDialRemote_Url = dialURL
|
||||
SimpleConf.Client_ThatDialRemote_Url = dialURL
|
||||
}
|
||||
|
||||
} else {
|
||||
|
335
main.go
335
main.go
@@ -1,22 +1,17 @@
|
||||
package main
|
||||
package v2ray_simple
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/profile"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/e1732a364fed/v2ray_simple/advLayer/grpc"
|
||||
@@ -38,62 +33,51 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
simpleMode = iota
|
||||
standardMode
|
||||
v2rayCompatibleMode
|
||||
SimpleMode = iota
|
||||
StandardMode
|
||||
V2rayCompatibleMode
|
||||
)
|
||||
|
||||
//统计数据
|
||||
var (
|
||||
activeConnectionCount int32
|
||||
allDownloadBytesSinceStart uint64
|
||||
allUploadBytesSinceStart uint64
|
||||
ActiveConnectionCount int32
|
||||
AllDownloadBytesSinceStart uint64
|
||||
AllUploadBytesSinceStart uint64
|
||||
)
|
||||
|
||||
var (
|
||||
configFileName string
|
||||
|
||||
uniqueTestDomain string //有时需要测试到单一网站的流量,此时为了避免其它干扰,需要在这里声明 一下 该域名,然后程序里会进行过滤
|
||||
|
||||
confMode int = -1 //0: simple json, 1: standard toml, 2: v2ray compatible json
|
||||
simpleConf proxy.SimpleConf
|
||||
standardConf StandardConf
|
||||
directClient, _, _ = proxy.ClientFromURL("direct://")
|
||||
defaultOutClient proxy.Client
|
||||
default_uuid string
|
||||
ConfMode int = -1 //0: simple json, 1: standard toml, 2: v2ray compatible json
|
||||
SimpleConf proxy.SimpleConf
|
||||
DirectClient, _, _ = proxy.ClientFromURL("direct://")
|
||||
DefaultOutClient proxy.Client
|
||||
Default_uuid string
|
||||
|
||||
allServers = make([]proxy.Server, 0, 8)
|
||||
allClients = make([]proxy.Client, 0, 8)
|
||||
listenerArray []net.Listener
|
||||
AllServers = make([]proxy.Server, 0, 8)
|
||||
AllClients = make([]proxy.Client, 0, 8)
|
||||
ListenerArray []net.Listener
|
||||
|
||||
serversTagMap = make(map[string]proxy.Server)
|
||||
clientsTagMap = make(map[string]proxy.Client)
|
||||
ServersTagMap = make(map[string]proxy.Server)
|
||||
ClientsTagMap = make(map[string]proxy.Client)
|
||||
|
||||
listenURL string //用于命令行模式
|
||||
dialURL string //用于命令行模式
|
||||
|
||||
tls_lazy_encrypt bool
|
||||
tls_lazy_secure bool
|
||||
Tls_lazy_encrypt bool
|
||||
Tls_lazy_secure bool
|
||||
|
||||
routePolicy *netLayer.RoutePolicy
|
||||
RoutePolicy *netLayer.RoutePolicy
|
||||
mainFallback *httpLayer.ClassicFallback
|
||||
dnsMachine *netLayer.DNSMachine
|
||||
|
||||
startPProf bool
|
||||
startMProf bool
|
||||
|
||||
tproxyList []tproxy.Machine
|
||||
TproxyList []tproxy.Machine
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
flag.BoolVar(&startPProf, "pp", false, "pprof")
|
||||
flag.BoolVar(&startMProf, "mp", false, "memory pprof")
|
||||
|
||||
flag.BoolVar(&tls_lazy_encrypt, "lazy", false, "tls lazy encrypt (splice)")
|
||||
flag.BoolVar(&tls_lazy_secure, "ls", false, "tls lazy secure, use special techs to ensure the tls lazy encrypt data can't be detected. Only valid at client end.")
|
||||
|
||||
flag.StringVar(&configFileName, "c", "client.toml", "config file name")
|
||||
flag.BoolVar(&Tls_lazy_encrypt, "lazy", false, "tls lazy encrypt (splice)")
|
||||
flag.BoolVar(&Tls_lazy_secure, "ls", false, "tls lazy secure, use special techs to ensure the tls lazy encrypt data can't be detected. Only valid at client end.")
|
||||
|
||||
flag.StringVar(&listenURL, "L", "", "listen URL (i.e. the listen part in config file), only enbled when config file is not provided.")
|
||||
flag.StringVar(&dialURL, "D", "", "dial URL (i.e. the dial part in config file), only enbled when config file is not provided.")
|
||||
@@ -102,244 +86,9 @@ func init() {
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
os.Exit(mainFunc())
|
||||
}
|
||||
|
||||
func mainFunc() (result int) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if ce := utils.CanLogFatal("Captured panic!"); ce != nil {
|
||||
ce.Write(zap.Any("err:", r))
|
||||
} else {
|
||||
log.Fatalln("panic captured!", r)
|
||||
}
|
||||
|
||||
result = -3
|
||||
}
|
||||
}()
|
||||
|
||||
flag.Parse()
|
||||
|
||||
if cmdPrintVer {
|
||||
printVersion_simple()
|
||||
//根据 cmdPrintVer 的定义, 我们直接退出
|
||||
return
|
||||
} else {
|
||||
printVersion()
|
||||
|
||||
}
|
||||
|
||||
if !utils.IsFlagGiven("lf") {
|
||||
if strings.Contains(configFileName, "server") {
|
||||
utils.LogOutFileName += "_server"
|
||||
} else if strings.Contains(configFileName, "client") {
|
||||
utils.LogOutFileName += "_client"
|
||||
}
|
||||
}
|
||||
|
||||
utils.ShouldLogToFile = true
|
||||
|
||||
utils.InitLog()
|
||||
|
||||
if startPProf {
|
||||
f, _ := os.OpenFile("cpu.pprof", os.O_CREATE|os.O_RDWR, 0644)
|
||||
defer f.Close()
|
||||
pprof.StartCPUProfile(f)
|
||||
defer pprof.StopCPUProfile()
|
||||
|
||||
}
|
||||
if startMProf {
|
||||
//若不使用 NoShutdownHook, 我们ctrl+c退出时不会产生 pprof文件
|
||||
p := profile.Start(profile.MemProfile, profile.MemProfileRate(1), profile.NoShutdownHook)
|
||||
|
||||
defer p.Stop()
|
||||
}
|
||||
|
||||
utils.Info("Program started")
|
||||
defer utils.Info("Program exited")
|
||||
|
||||
if err := loadConfig(); err != nil && !isFlexible() {
|
||||
log.Printf("no config exist, and no api server or interactive cli enabled, exiting...")
|
||||
return -1
|
||||
}
|
||||
|
||||
netLayer.Prepare()
|
||||
|
||||
fmt.Printf("Log Level:%d\n", utils.LogLevel)
|
||||
fmt.Printf("UseReadv:%t\n", netLayer.UseReadv)
|
||||
fmt.Printf("tls_lazy_encrypt:%t\n", tls_lazy_encrypt)
|
||||
|
||||
runPreCommands()
|
||||
|
||||
var defaultInServer proxy.Server
|
||||
|
||||
//load inServers and routePolicy
|
||||
switch confMode {
|
||||
case simpleMode:
|
||||
var hase bool
|
||||
var eie utils.ErrInErr
|
||||
defaultInServer, hase, eie = proxy.ServerFromURL(simpleConf.Server_ThatListenPort_Url)
|
||||
if hase {
|
||||
if ce := utils.CanLogErr("can not create local server"); ce != nil {
|
||||
ce.Write(zap.Error(eie))
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
if !defaultInServer.CantRoute() && simpleConf.Route != nil {
|
||||
|
||||
netLayer.LoadMaxmindGeoipFile("")
|
||||
|
||||
//极简模式只支持通过 mycountry进行 geoip分流 这一种情况
|
||||
routePolicy = netLayer.NewRoutePolicy()
|
||||
if simpleConf.MyCountryISO_3166 != "" {
|
||||
routePolicy.AddRouteSet(netLayer.NewRouteSetForMyCountry(simpleConf.MyCountryISO_3166))
|
||||
|
||||
}
|
||||
}
|
||||
case standardMode:
|
||||
|
||||
loadCommonComponentsFromStandardConf()
|
||||
|
||||
//虽然标准模式支持多个Server,目前先只考虑一个
|
||||
//多个Server存在的话,则必须要用 tag指定路由; 然后,我们需在预先阶段就判断好tag指定的路由
|
||||
|
||||
if len(standardConf.Listen) < 1 {
|
||||
utils.Warn("no listen in config settings")
|
||||
break
|
||||
}
|
||||
|
||||
for _, serverConf := range standardConf.Listen {
|
||||
thisConf := serverConf
|
||||
if thisConf.Protocol == "tproxy" {
|
||||
listenTproxy(thisConf.GetAddrStrForListenOrDial())
|
||||
continue
|
||||
}
|
||||
|
||||
if thisConf.Uuid == "" && default_uuid != "" {
|
||||
thisConf.Uuid = default_uuid
|
||||
}
|
||||
|
||||
thisServer, err := proxy.NewServer(thisConf)
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("can not create local server:"); ce != nil {
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
allServers = append(allServers, thisServer)
|
||||
if tag := thisServer.GetTag(); tag != "" {
|
||||
serversTagMap[tag] = thisServer
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// load outClients
|
||||
switch confMode {
|
||||
case simpleMode:
|
||||
var hase bool
|
||||
var eie utils.ErrInErr
|
||||
defaultOutClient, hase, eie = proxy.ClientFromURL(simpleConf.Client_ThatDialRemote_Url)
|
||||
if hase {
|
||||
if ce := utils.CanLogErr("can not create remote client"); ce != nil {
|
||||
ce.Write(zap.Error(eie))
|
||||
}
|
||||
return -1
|
||||
}
|
||||
case standardMode:
|
||||
|
||||
if len(standardConf.Dial) < 1 {
|
||||
utils.Warn("no dial in config settings")
|
||||
break
|
||||
}
|
||||
|
||||
for _, thisConf := range standardConf.Dial {
|
||||
if thisConf.Uuid == "" && default_uuid != "" {
|
||||
thisConf.Uuid = default_uuid
|
||||
}
|
||||
|
||||
thisClient, err := proxy.NewClient(thisConf)
|
||||
if err != nil {
|
||||
if ce := utils.CanLogErr("can not create remote client: "); ce != nil {
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
continue
|
||||
}
|
||||
allClients = append(allClients, thisClient)
|
||||
|
||||
if tag := thisClient.GetTag(); tag != "" {
|
||||
clientsTagMap[tag] = thisClient
|
||||
}
|
||||
}
|
||||
|
||||
if len(allClients) > 0 {
|
||||
defaultOutClient = allClients[0]
|
||||
|
||||
} else {
|
||||
defaultOutClient = directClient
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
configFileQualifiedToRun := false
|
||||
|
||||
if (defaultInServer != nil || len(allServers) > 0 || len(tproxyList) > 0) && (defaultOutClient != nil) {
|
||||
configFileQualifiedToRun = true
|
||||
|
||||
if confMode == simpleMode {
|
||||
listenSer(defaultInServer, defaultOutClient, true)
|
||||
} else {
|
||||
for _, inServer := range allServers {
|
||||
listenSer(inServer, defaultOutClient, true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//没配置可用的listen或者dial,而且还无法动态更改配置
|
||||
if !configFileQualifiedToRun && !isFlexible() {
|
||||
utils.Error("No valid proxy settings available, exit now.")
|
||||
return -1
|
||||
}
|
||||
|
||||
if enableApiServer {
|
||||
go checkConfigAndTryRunApiServer()
|
||||
|
||||
}
|
||||
|
||||
if interactive_mode {
|
||||
runCli()
|
||||
}
|
||||
|
||||
{
|
||||
osSignals := make(chan os.Signal, 1)
|
||||
signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM)
|
||||
<-osSignals
|
||||
|
||||
utils.Info("Program got close signal.")
|
||||
|
||||
//在程序ctrl+C关闭时, 会主动Close所有的监听端口. 主要是被报告windows有时退出程序之后, 端口还是处于占用状态.
|
||||
// 用下面代码以试图解决端口占用问题.
|
||||
|
||||
for _, listener := range listenerArray {
|
||||
if listener != nil {
|
||||
listener.Close()
|
||||
}
|
||||
}
|
||||
|
||||
for _, tm := range tproxyList {
|
||||
tm.Stop()
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//非阻塞. 在main函数中被调用。也可以在 test代码中直接使用 listenSer 函数 来手动开启新的转发流程。
|
||||
//非阻塞. 在main函数中被调用。也可以在 test代码中直接使用 ListenSer 函数 来手动开启新的转发流程。
|
||||
// 若 not_temporary 为true, 则生成的listener将会被添加到 listenerArray 中
|
||||
func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client, not_temporary bool) (thisListener net.Listener) {
|
||||
func ListenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client, not_temporary bool) (thisListener net.Listener) {
|
||||
|
||||
var err error
|
||||
|
||||
@@ -411,7 +160,7 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client, not_
|
||||
}
|
||||
|
||||
if not_temporary {
|
||||
listenerArray = append(listenerArray, thisListener)
|
||||
ListenerArray = append(ListenerArray, thisListener)
|
||||
|
||||
}
|
||||
|
||||
@@ -470,7 +219,7 @@ func handleNewIncomeConnection(inServer proxy.Server, defaultClientForThis proxy
|
||||
forbidDNS_orRoute: forbidDNS_orRoute,
|
||||
}
|
||||
|
||||
iics.isTlsLazyServerEnd = tls_lazy_encrypt && canLazyEncryptServer(inServer)
|
||||
iics.isTlsLazyServerEnd = Tls_lazy_encrypt && canLazyEncryptServer(inServer)
|
||||
|
||||
wrappedConn := thisLocalConnectionInstance
|
||||
|
||||
@@ -980,7 +729,7 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co
|
||||
inServer := iics.inServer
|
||||
|
||||
//尝试分流, 获取到真正要发向 的 outClient
|
||||
if !iics.forbidDNS_orRoute && routePolicy != nil && !(inServer != nil && inServer.CantRoute()) {
|
||||
if !iics.forbidDNS_orRoute && RoutePolicy != nil && !(inServer != nil && inServer.CantRoute()) {
|
||||
|
||||
desc := &netLayer.TargetDescription{
|
||||
Addr: targetAddr,
|
||||
@@ -993,10 +742,10 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co
|
||||
ce.Write(zap.Any("source", desc))
|
||||
}
|
||||
|
||||
outtag := routePolicy.GetOutTag(desc)
|
||||
outtag := RoutePolicy.GetOutTag(desc)
|
||||
|
||||
if outtag == "direct" {
|
||||
client = directClient
|
||||
client = DirectClient
|
||||
iics.routedToDirect = true
|
||||
routed = true
|
||||
|
||||
@@ -1007,7 +756,7 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co
|
||||
}
|
||||
} else {
|
||||
|
||||
if tagC, ok := clientsTagMap[outtag]; ok {
|
||||
if tagC, ok := ClientsTagMap[outtag]; ok {
|
||||
client = tagC
|
||||
routed = true
|
||||
if ce := utils.CanLogInfo("Route"); ce != nil {
|
||||
@@ -1047,7 +796,7 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co
|
||||
iics.inServerTlsRawReadRecorder.StopRecord()
|
||||
}
|
||||
} else {
|
||||
isTlsLazy_clientEnd = tls_lazy_encrypt && canLazyEncryptClient(client)
|
||||
isTlsLazy_clientEnd = Tls_lazy_encrypt && canLazyEncryptClient(client)
|
||||
|
||||
}
|
||||
|
||||
@@ -1062,7 +811,7 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co
|
||||
log.Printf("loading TLS SniffConn %t %t\n", isTlsLazy_clientEnd, iics.isTlsLazyServerEnd)
|
||||
}
|
||||
|
||||
wlc = tlsLayer.NewSniffConn(iics.baseLocalConn, wlc, isTlsLazy_clientEnd, tls_lazy_secure)
|
||||
wlc = tlsLayer.NewSniffConn(iics.baseLocalConn, wlc, isTlsLazy_clientEnd, Tls_lazy_secure)
|
||||
|
||||
}
|
||||
|
||||
@@ -1266,7 +1015,7 @@ func dialClient(targetAddr netLayer.Addr,
|
||||
|
||||
if isTlsLazy_clientEnd {
|
||||
|
||||
if tls_lazy_secure && wlc != nil {
|
||||
if Tls_lazy_secure && wlc != nil {
|
||||
// 如果使用secure办法,则我们每次不能先拨号,而是要detect用户的首包后再拨号
|
||||
// 这种情况只需要客户端操作, 此时我们wrc直接传入原始的 刚拨号好的 tcp连接,即 clientConn
|
||||
|
||||
@@ -1660,7 +1409,7 @@ func dialClient_andRelay(iics incomingInserverConnState, targetAddr netLayer.Add
|
||||
|
||||
if !targetAddr.IsUDP() {
|
||||
|
||||
if tls_lazy_encrypt && !iics.routedToDirect {
|
||||
if Tls_lazy_encrypt && !iics.routedToDirect {
|
||||
|
||||
// 我们加了回落之后,就无法确定 “未使用tls的outClient 一定是在服务端” 了
|
||||
if isTlsLazy_clientEnd {
|
||||
@@ -1693,11 +1442,11 @@ func dialClient_andRelay(iics incomingInserverConnState, targetAddr netLayer.Add
|
||||
utils.PutBytes(iics.theFallbackFirstBuffer.Bytes()) //这个Buf不是从utils.GetBuf创建的,而是从一个 GetBytes的[]byte 包装 的,所以我们要PutBytes,而不是PutBuf
|
||||
}
|
||||
|
||||
atomic.AddInt32(&activeConnectionCount, 1)
|
||||
atomic.AddInt32(&ActiveConnectionCount, 1)
|
||||
|
||||
netLayer.Relay(&realTargetAddr, wrc, wlc, &allDownloadBytesSinceStart, &allUploadBytesSinceStart)
|
||||
netLayer.Relay(&realTargetAddr, wrc, wlc, &AllDownloadBytesSinceStart, &AllUploadBytesSinceStart)
|
||||
|
||||
atomic.AddInt32(&activeConnectionCount, -1)
|
||||
atomic.AddInt32(&ActiveConnectionCount, -1)
|
||||
|
||||
return
|
||||
|
||||
@@ -1710,12 +1459,12 @@ func dialClient_andRelay(iics incomingInserverConnState, targetAddr netLayer.Add
|
||||
|
||||
}
|
||||
|
||||
atomic.AddInt32(&activeConnectionCount, 1)
|
||||
atomic.AddInt32(&ActiveConnectionCount, 1)
|
||||
|
||||
if client.IsUDP_MultiChannel() {
|
||||
utils.Debug("Relaying UDP with MultiChannel")
|
||||
|
||||
netLayer.RelayUDP_separate(udp_wrc, udp_wlc, &targetAddr, &allDownloadBytesSinceStart, &allUploadBytesSinceStart, func(raddr netLayer.Addr) netLayer.MsgConn {
|
||||
netLayer.RelayUDP_separate(udp_wrc, udp_wlc, &targetAddr, &AllDownloadBytesSinceStart, &AllUploadBytesSinceStart, func(raddr netLayer.Addr) netLayer.MsgConn {
|
||||
utils.Debug("Relaying UDP with MultiChannel,dialfunc called")
|
||||
|
||||
_, udp_wrc, _, _, result := dialClient(raddr, client, iics.baseLocalConn, nil, "", false)
|
||||
@@ -1732,11 +1481,11 @@ func dialClient_andRelay(iics incomingInserverConnState, targetAddr netLayer.Add
|
||||
})
|
||||
|
||||
} else {
|
||||
netLayer.RelayUDP(udp_wrc, udp_wlc, &allDownloadBytesSinceStart, &allUploadBytesSinceStart)
|
||||
netLayer.RelayUDP(udp_wrc, udp_wlc, &AllDownloadBytesSinceStart, &AllUploadBytesSinceStart)
|
||||
|
||||
}
|
||||
|
||||
atomic.AddInt32(&activeConnectionCount, -1)
|
||||
atomic.AddInt32(&ActiveConnectionCount, -1)
|
||||
|
||||
return
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package v2ray_simple
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
@@ -115,8 +115,8 @@ protocol = "direct"
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
listenSer(clientEndInServer, clientEndOutClient, false)
|
||||
listenSer(serverEndInServer, serverEndOutClient, false)
|
||||
ListenSer(clientEndInServer, clientEndOutClient, false)
|
||||
ListenSer(serverEndInServer, serverEndOutClient, false)
|
||||
|
||||
proxyurl := "http://127.0.0.1:" + clientListenPort
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package v2ray_simple
|
||||
|
||||
import (
|
||||
"io"
|
||||
@@ -85,7 +85,7 @@ func tryTlsLazyRawCopy(useSecureMethod bool, proxy_client proxy.UserClient, prox
|
||||
|
||||
wrcVless := wrc.(*vless.UserTCPConn)
|
||||
tlsConn := wrcVless.Conn.(*tlsLayer.Conn)
|
||||
rawWRC = tlsConn.GetRaw(tls_lazy_encrypt)
|
||||
rawWRC = tlsConn.GetRaw(Tls_lazy_encrypt)
|
||||
|
||||
} else {
|
||||
rawWRC = wrc.(*net.TCPConn) //因为是direct
|
||||
@@ -97,7 +97,7 @@ func tryTlsLazyRawCopy(useSecureMethod bool, proxy_client proxy.UserClient, prox
|
||||
|
||||
}
|
||||
|
||||
if tls_lazy_encrypt {
|
||||
if Tls_lazy_encrypt {
|
||||
theRecorder.StopRecord()
|
||||
theRecorder.ReleaseBuffers()
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package v2ray_simple
|
||||
|
||||
import (
|
||||
"go.uber.org/zap"
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
func listenTproxy(addr string) {
|
||||
func ListenTproxy(addr string) {
|
||||
utils.Info("Start running Tproxy")
|
||||
|
||||
ad, err := netLayer.NewAddr(addr)
|
||||
@@ -26,7 +26,7 @@ func listenTproxy(addr string) {
|
||||
}
|
||||
udpConn := startLoopUDP(ad)
|
||||
|
||||
tproxyList = append(tproxyList, tproxy.Machine{Addr: ad, Listener: lis, UDPConn: udpConn})
|
||||
TproxyList = append(TproxyList, tproxy.Machine{Addr: ad, Listener: lis, UDPConn: udpConn})
|
||||
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func startLoopTCP(ad netLayer.Addr) (net.Listener, error) {
|
||||
|
||||
passToOutClient(incomingInserverConnState{
|
||||
wrappedConn: tcpconn,
|
||||
defaultClient: defaultOutClient,
|
||||
defaultClient: DefaultOutClient,
|
||||
}, false, tcpconn, nil, targetAddr)
|
||||
})
|
||||
|
||||
@@ -75,7 +75,7 @@ func startLoopUDP(ad netLayer.Addr) *net.UDPConn {
|
||||
}
|
||||
|
||||
go passToOutClient(incomingInserverConnState{
|
||||
defaultClient: defaultOutClient,
|
||||
defaultClient: DefaultOutClient,
|
||||
}, false, nil, msgConn, raddr)
|
||||
}
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package main
|
||||
package v2ray_simple
|
||||
|
||||
import (
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
func listenTproxy(addr string) {
|
||||
func ListenTproxy(addr string) {
|
||||
utils.Warn("Tproxy not possible on non-linux device")
|
||||
}
|
||||
|
10
udp_test.go
10
udp_test.go
@@ -1,4 +1,4 @@
|
||||
package main
|
||||
package v2ray_simple
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -190,10 +190,10 @@ protocol = "direct"
|
||||
t.FailNow()
|
||||
}
|
||||
|
||||
listenSer(clientEndInServer, clientEndOutClient, false)
|
||||
listenSer(clientEndInServer2, clientEndOutClient, false)
|
||||
listenSer(clientEndInServer3, clientEndOutClient, false)
|
||||
listenSer(serverEndInServer, serverEndOutClient, false)
|
||||
ListenSer(clientEndInServer, clientEndOutClient, false)
|
||||
ListenSer(clientEndInServer2, clientEndOutClient, false)
|
||||
ListenSer(clientEndInServer3, clientEndOutClient, false)
|
||||
ListenSer(serverEndInServer, serverEndOutClient, false)
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion(dns.Fqdn("www.qq.com"), dns.TypeA)
|
||||
|
Reference in New Issue
Block a user