feat:添加回落和分流功能.

创建新子包netLayer, 将 proxy.Addr改为 netLayer.Addr
修订文档

RoutePolicy等分流机制也放到 netLayer

引入github.com/oschwald/maxminddb-golang 依赖,支持使用 GeoLite2-Country.mmdb 来进行ip分流

另外注意它默认的版本对于 golang.org/x/sys 包的依赖太老了,会导致go1.18中编译不通过,我在
go.mod 文件中新增了下面代码,就能通过编译了

```
require (
	golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect
)
```

verysimple的可执行文件的相同目录下,必须有该mmdb文件才能够开启ip分流功能

新配置方式:配置文件新加一行 "route":{ "mycountry":"CN" }

mycountry指定的国家的ip会被直连发送,其他地址ip会被发送到代理.

新配置方式,回落,直接在 local 项的 url 的 query部分添加 fallback=:80, 或者 fallback=127.0.0.1:80
即可 回落到指定端口.

将tls_test重新挪动到tlsLayer包中

在main.go中添加了 logLevel变量,并且把关于配置文件的部分挪动到 config.go

出了上面的分流和回落以外,还新增支持了 #xxx 的尾缀,用于配置该url的tag. tag在未来会被用于精准分流

Makefile中新增了 PACK 参数用于编译出 打包版的发行包;可选 tag=embed_geoip 参数用于将mmdb.tgz文件内置到可执行程序里

同时,我开始直接使用go1.18编译本项目,期待性能提升,因为这是新发布的版本,看了介绍据说对 mac m1有20%的提升.
This commit is contained in:
hahahrfool
2022-03-16 19:28:26 +08:00
parent 405207bc56
commit e664b9740e
27 changed files with 664 additions and 170 deletions

View File

@@ -1,92 +1,99 @@
/*
package proxy 定义了代理转发所需的必备组件
Package proxy 定义了代理转发所需的必备组件
# 层级讨论
目前认为一个传输过程由四个部分组成基础连接udp/tcpTLS可选中间层ws、grpc、http等可选具体协议socks5vlesstrojan等
Layer Definition 层级讨论
其中,wsgrpc被认为是 高级应用层http伪装属于低级应用层。
目前认为一个传输过程由四个部分组成基础连接udp/tcpTLS可选中间层wsgrpc、http等可选具体协议socks5vlesstrojan等.
TLSTransport Layer Security 顾名思义TLS作用于传输层第四层但是我们tcp也是第四层所以在本项目中认为不需要“会话层”单独加一个专用于tls的层比较稳妥
其中ws和grpc被认为是 高级应用层http伪装属于低级应用层.
正常OSI是7层我们在这里规定一个 第八层和第九层,第八层就是 vless协议所在位置第九层就是我们实际传输的承载数据
TLS - Transport Layer Security 顾名思义TLS作用于传输层第四层但是我们tcp也是第四层所以在本项目中认为不需要“会话层”单独加一个专用于tls的层比较稳妥.
正常OSI是7层我们在这里规定一个 第八层和第九层,第八层就是 vless协议所在位置第九层就是我们实际传输的承载数据.
## 新的VSI 模型
New Model - VSI 新的VSI 模型
那么我们提出一个 verysimple Interconnection Model 简称vsi模型。1到4层与OSI相同物理、链路、网络、传输)
那么我们提出一个 verysimple Interconnection Model 简称vsi模型。1到4层与OSI相同物理、链路、网络、传输).
把第五层替换成“加密层”把TLS放进去把第六层改为低级应用层http属于这一层
把第五层替换成“加密层”把TLS放进去把第六层改为低级应用层http属于这一层.
第七层 改为高级应用层ws/grpc 属于这一层, 简称高级层;第八层定为 代理层vless/trojan 在这层
第七层 改为高级应用层ws/grpc 属于这一层, 简称高级层;第八层定为 代理层vless/trojan 在这层.
第九层为 承载数据层,承载的为 另一大串 第四层的数据
第九层为 承载数据层,承载的为 另一大串 第四层的数据.
那么我们verysimple实际上就是 基于 “层” 的架构,或称 可分层结构
那么我们verysimple实际上就是 基于 “层” 的架构,或称 可分层结构.
```
9 tcp data
--------------------
8 vless/trojan/socks5
--------------------
7 ws/grpc
--------------------
6 http
--------------------
5 tls
--------------------
4 tcp
--------------------
```
基本上5-8层都是可控的
9 tcp data
--------------------
8 vless/trojan/socks5
--------------------
7 ws/grpc
--------------------
6 http
--------------------
5 tls
--------------------
4 tcp
--------------------
对应的理想配置文件应该如下
```json
{
"layer5_settings": { //或者叫 tls_settings
"tls":{"insecure": true},
"utls":{}
},
"layer6_settings": { //或者叫 http_settings
"headers":{}
},
"layer7_settings": { //或者叫 advancedLayer_settings
"ws":{}
},
"layer8_settings": { //或者叫 proxy_settings
"vless":{}
"trojan":{}
},
}
```
基本上5-8层都是可控的.
对应的理想配置文件应该如下.
{
"layer5_settings": { //或者叫 tls_settings
"tls":{"insecure": true},
"utls":{}
},
"layer6_settings": { //或者叫 http_settings
"headers":{}
},
"layer7_settings": { //或者叫 advancedLayer_settings
"ws":{}
},
"layer8_settings": { //或者叫 proxy_settings
"vless":{}
"trojan":{}
},
}
我们项目的文件夹proxy文件夹代表第8层tlsLayer文件夹代表第5层; 未来还计划在根目录下添加http文件夹第六层
ws和grpc文件夹第七层
ws和grpc文件夹第七层.
同级的ws和grpc是独占的可以都放到一个layer里然后比如第八层配置了一个vless一个trojan那么排列组合就是4种vless+ws, vless+ grpc, trojan+ws, trojan+grpc
同级的ws和grpc是独占的可以都放到一个layer里然后比如第八层配置了一个vless一个trojan那么排列组合就是4种vless+ws, vless+ grpc, trojan+ws, trojan+grpc.
这就大大减轻了各种”一键脚本“的 使用需求,咱们只要选择自己喜欢的各个层,程序自动就为我们生成所有配置;
这就大大减轻了各种”一键脚本“的 使用需求,咱们只要选择自己喜欢的各个层,程序自动就为我们生成所有配置.
运行时如果所有配置都要有那么就需要多种端口共用端口的话可以用nginx
运行时如果所有配置都要有那么就需要多种端口共用端口的话可以用nginx.
也可以程序指定一种 特定的情况比如开始运行程序时冒出交互界面自己按项选择好后就自动运行然后自动生成客户端分享url
也可以程序指定一种 特定的情况比如开始运行程序时冒出交互界面自己按项选择好后就自动运行然后自动生成客户端分享url.
可以在脑海里想象 “穿鞋带” 的画面,有很多洞可以经过,都穿好了,鞋带就系好了。或者手机手势解锁的情况
可以在脑海里想象 “穿鞋带” 的画面,有很多洞可以经过,都穿好了,鞋带就系好了。或者手机手势解锁的情况.
这种好处是每次运行都可以采用不同的配置不同的uuid手机一扫码就能连上
这种好处是每次运行都可以采用不同的配置不同的uuid手机一扫码就能连上.
# proxy 文件夹内容
Contents of proxy package - proxy包内容
接口 ProxyCommon 和 结构 ProxyCommonStruct 给 这个架构定义了标准
接口 ProxyCommon 和 结构 ProxyCommonStruct 给 这个架构定义了标准.
而 Client 和 Server 接口 是 具体利用该架构的 客户端 和 服务端都位于VSI中的第八层
而 Client 和 Server 接口 是 具体利用该架构的 客户端 和 服务端都位于VSI中的第八层.
使用 RegisterClient 和 RegisterServer 来注册新的实现
使用 RegisterClient 和 RegisterServer 来注册新的实现.
还定义了关于udp 转发到机制,该部分直接参考 各个UDP开头的 部分即可
还定义了关于udp 转发到机制,该部分直接参考 各个UDP开头的 部分即可.
Server and Client
我们服务端和 客户端的程序都是有至少一个入口和一个出口的。入口我们叫做localServer出口我们叫做remoteClient.
在localServer中我们负责监听未知连接在remoteClient中我们负责拨号特定目标服务器.
这里的local和remote指的是 数据传输的目的地。
*/
package proxy
@@ -102,10 +109,12 @@ import (
"github.com/hahahrfool/v2ray_simple/tlsLayer"
)
// 给一个节点 提供 VSI中 第 5-7层 的支持
// 给一个节点 提供 VSI中 第 5-7层 的支持, server和 client通用. 个别方法只能用于某一端
type ProxyCommon interface {
AddrStr() string //地址在server就是监听地址在client就是拨号地址
SetAddrStr(string)
CantRoute() bool //for localServer,
GetTag() string
SetUseTLS()
IsUseTLS() bool
@@ -117,8 +126,12 @@ type ProxyCommon interface {
GetTLS_Server() *tlsLayer.Server
GetTLS_Client() *tlsLayer.Client
setCantRoute(bool)
setTag(string)
}
//给 ProxyCommon 的tls做一些配置上的准备从url读取配置
func PrepareTLS_forProxyCommon(u *url.URL, isclient bool, com ProxyCommon) error {
insecureStr := u.Query().Get("insecure")
insecure := false
@@ -149,9 +162,28 @@ func PrepareTLS_forProxyCommon(u *url.URL, isclient bool, com ProxyCommon) error
type ProxyCommonStruct struct {
Addr string
TLS bool
Tag string //可用于路由, 见 netLayer.route.go
tls_s *tlsLayer.Server
tls_c *tlsLayer.Client
cantRoute bool //for localServer, 若为true则 localServer 读得的数据 不会经过分流一定会通过用户指定的remoteclient发出
}
func (pcs *ProxyCommonStruct) CantRoute() bool {
return pcs.cantRoute
}
func (pcs *ProxyCommonStruct) GetTag() string {
return pcs.Tag
}
func (pcs *ProxyCommonStruct) setTag(tag string) {
pcs.Tag = tag
}
func (pcs *ProxyCommonStruct) setCantRoute(cr bool) {
pcs.cantRoute = cr
}
func (pcs *ProxyCommonStruct) HasAdvancedApplicationLayer() bool {
@@ -228,7 +260,7 @@ func ClientFromURL(s string) (Client, error) {
return creatorFunc(u)
} else {
//尝试判断是否套tls
//尝试判断是否套tls, 比如vlesss实际上是vless+tlshttps实际上是http+tls
realScheme := strings.TrimSuffix(schemeName, "s")
creatorFunc, ok = clientMap[realScheme]
@@ -291,6 +323,8 @@ func PrintAllClientNames() {
// ServerFromURL calls the registered creator to create proxy servers
// dialer is the default upstream dialer so cannot be nil, we can use Default when calling this function
// 所有的server都可有 "norule"参数标明无需路由或者此server不可使用路由在监听多个ip时是有用的;
// 路由配置可以在json的其他配置里面设置如 mycountry项
func ServerFromURL(s string) (Server, error) {
u, err := url.Parse(s)
if err != nil {
@@ -300,22 +334,40 @@ func ServerFromURL(s string) (Server, error) {
schemeName := strings.ToLower(u.Scheme)
creatorFunc, ok := serverMap[schemeName]
if ok {
return creatorFunc(u)
ser, err := creatorFunc(u)
if err != nil {
return nil, err
}
configCommonForServer(ser, u)
return ser, nil
} else {
realScheme := strings.TrimSuffix(schemeName, "s")
creatorFunc, ok = serverMap[realScheme]
if ok {
server, err := creatorFunc(u)
if err != nil {
return server, err
return nil, err
}
configCommonForServer(server, u)
server.SetUseTLS()
PrepareTLS_forProxyCommon(u, false, server)
return server, err
return server, nil
}
}
return nil, common.NewDataErr("unknown server scheme '", nil, u.Scheme)
}
func configCommonForServer(ser ProxyCommon, u *url.URL) {
nr := false
q := u.Query()
if q.Get("norule") != "" {
nr = true
}
ser.setCantRoute(nr)
ser.setTag(u.Fragment)
}