Files
v2ray_simple/netLayer/route.go
hahahrfool e664b9740e 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%的提升.
2022-03-16 19:28:26 +08:00

139 lines
3.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package netLayer
import (
"net"
"strings"
"github.com/yl2chen/cidranger"
)
// TargetDescription 可以完整地描述一个网络层/传输层上的一个特定目标,
// 一般来说一个具体的监听配置就会分配一个tag
type TargetDescription struct {
Addr *Addr
Tag string
}
// Set 是 “集合” 的意思, 是一组相同类型的数据放到一起。
// 这里的相同点,就是它们同属于 将发往一个方向, 即同属一个路由策略
// 任意一个参数匹配后都将发往相同的方向由该方向OutTag 指定
// RouteSet 只负责把一些属性相同的 “网络层/传输层 特征” 放到一起
type RouteSet struct {
//网络层
NetRanger cidranger.Ranger //一个范围
IPs map[string]net.IP //一个确定值
Domains, InTags, Countries map[string]bool // Countries 使用 ISO 3166 字符串 作为key
//传输层
NotAllowTCP bool
NotAllowUDP bool
OutTag string
}
func NewRouteSetForMyCountry(iso string) *RouteSet {
if len(iso) != 2 {
return nil
}
rs := &RouteSet{
Countries: make(map[string]bool),
OutTag: "direct",
}
rs.Countries[iso] = true
return rs
}
func NewFullRouteSet() *RouteSet {
return &RouteSet{
NetRanger: cidranger.NewPCTrieRanger(),
IPs: make(map[string]net.IP),
Domains: make(map[string]bool),
InTags: make(map[string]bool),
Countries: make(map[string]bool),
}
}
func (sg *RouteSet) IsIn(td *TargetDescription) bool {
if td.Tag != "" {
if _, found := sg.InTags[td.Tag]; found {
return true
}
}
return sg.IsAddrIn(td.Addr)
}
func (sg *RouteSet) IsAddrIn(a *Addr) bool {
//我们先过滤传输层再过滤网络层因为传输层没那么多判断只有tcp/udp这个判断而已
if a.IsUDP && sg.NotAllowTCP || !a.IsUDP && sg.NotAllowUDP {
return false
} else if sg.NotAllowTCP != sg.NotAllowUDP && sg.NetRanger == nil && sg.IPs == nil && sg.Domains == nil && sg.InTags == nil && sg.Countries == nil {
//如果仅限制了一个传输层协议,且本集合里没有任何其它内容,那就直接通过
return true
}
//开始网络层判断
if a.IP != nil {
if sg.NetRanger != nil {
if has, _ := sg.NetRanger.Contains(a.IP); has {
return true
}
}
if sg.Countries != nil {
if isoStr := GetIP_ISO(a.IP); isoStr != "" {
if _, found := sg.Countries[isoStr]; found {
return true
}
}
}
if sg.IPs != nil {
if _, found := sg.IPs[a.IP.To16().String()]; found {
return true
}
}
}
if a.Name != "" && sg.Domains != nil {
tokens := strings.Split(a.Name, ".")
if len(tokens) > 1 {
suffix := tokens[len(tokens)-1]
for i := len(tokens) - 2; i >= 0; i-- {
suffix = tokens[i] + "." + suffix
if _, found := sg.Domains[suffix]; found {
return true
}
}
}
}
return false
}
//一个完整的 所有RouteSet的列表进行路由时直接遍历即可
// 所谓的路由实际上就是分流。
type RoutePolicy struct {
List []*RouteSet
}
func NewRoutePolicy() *RoutePolicy {
return &RoutePolicy{
List: make([]*RouteSet, 0, 2),
}
}
func (rp *RoutePolicy) AddRouteSet(rs *RouteSet) {
rp.List = append(rp.List, rs)
}
// 返回一个 proxy.Client 的 tag
// 默认情况下始终具有direct这个tag以及 proxy这个tag无需用户额外在配置文件中指定
// 默认如果不匹配任何值的话,就会流向 "proxy" tag也就是客户设置的 remoteClient的值
func (rp *RoutePolicy) GetOutTag(td *TargetDescription) string {
for _, s := range rp.List {
if s.IsIn(td) {
return s.OutTag
}
}
return "proxy"
}