mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-08 18:20:47 +08:00
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:
178
proxy/proxy.go
178
proxy/proxy.go
@@ -1,92 +1,99 @@
|
||||
/*
|
||||
package proxy 定义了代理转发所需的必备组件
|
||||
Package proxy 定义了代理转发所需的必备组件
|
||||
|
||||
# 层级讨论
|
||||
目前认为,一个传输过程由四个部分组成,基础连接(udp/tcp),TLS(可选),中间层(ws、grpc、http等,可选),具体协议(socks5,vless,trojan等)
|
||||
Layer Definition 层级讨论
|
||||
|
||||
其中,ws和grpc被认为是 高级应用层,http(伪装)属于低级应用层。
|
||||
目前认为,一个传输过程由四个部分组成,基础连接(udp/tcp),TLS(可选),中间层(ws、grpc、http等,可选),具体协议(socks5,vless,trojan等).
|
||||
|
||||
TLS:Transport 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+tls,https实际上是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)
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user