mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-25 01:30:30 +08:00
创建新子包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%的提升.
139 lines
3.5 KiB
Go
139 lines
3.5 KiB
Go
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"
|
||
}
|