mirror of
				https://github.com/e1732a364fed/v2ray_simple.git
				synced 2025-10-31 03:56:20 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			181 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			181 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package netLayer
 | ||
| 
 | ||
| import (
 | ||
| 	"net/netip"
 | ||
| 	"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[netip.Addr]bool //一个确定值
 | ||
| 	Domains, InTags, Countries map[string]bool     // Countries 使用 ISO 3166 字符串 作为key
 | ||
| 
 | ||
| 	//传输层
 | ||
| 	AllowedTransportLayerProtocols uint16
 | ||
| 
 | ||
| 	OutTag string //目标
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| func NewRouteSetForMyCountry(iso string) *RouteSet {
 | ||
| 	if len(iso) != 2 {
 | ||
| 		return nil
 | ||
| 	}
 | ||
| 	rs := &RouteSet{
 | ||
| 		Countries:                      make(map[string]bool),
 | ||
| 		Domains:                        make(map[string]bool),
 | ||
| 		OutTag:                         "direct",
 | ||
| 		AllowedTransportLayerProtocols: TCP | UDP, //默认即支持tcp和udp
 | ||
| 
 | ||
| 	}
 | ||
| 	rs.Countries[iso] = true
 | ||
| 	rs.Domains[strings.ToLower(iso)] = true //iso字符串的小写正好可以作为顶级域名
 | ||
| 	return rs
 | ||
| }
 | ||
| 
 | ||
| func NewFullRouteSet() *RouteSet {
 | ||
| 	return &RouteSet{
 | ||
| 		NetRanger:                      cidranger.NewPCTrieRanger(),
 | ||
| 		IPs:                            make(map[netip.Addr]bool),
 | ||
| 		Domains:                        make(map[string]bool),
 | ||
| 		InTags:                         make(map[string]bool),
 | ||
| 		Countries:                      make(map[string]bool),
 | ||
| 		AllowedTransportLayerProtocols: TCP | UDP, //默认即支持tcp和udp
 | ||
| 	}
 | ||
| }
 | ||
| 
 | ||
| func (sg *RouteSet) IsIn(td *TargetDescription) bool {
 | ||
| 	if td.Tag != "" && sg.InTags != nil {
 | ||
| 		if _, found := sg.InTags[td.Tag]; found {
 | ||
| 			return true
 | ||
| 		}
 | ||
| 	}
 | ||
| 	return sg.IsAddrIn(td.Addr)
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| func (sg *RouteSet) IsTransportProtocolAllowed(p uint16) bool {
 | ||
| 	return sg.AllowedTransportLayerProtocols&p > 0
 | ||
| }
 | ||
| 
 | ||
| func (sg *RouteSet) IsAddrNetworkAllowed(a Addr) bool {
 | ||
| 
 | ||
| 	if a.Network == "" {
 | ||
| 		return sg.IsTransportProtocolAllowed(TCP)
 | ||
| 	}
 | ||
| 
 | ||
| 	p := StrToTransportProtocol(a.Network)
 | ||
| 
 | ||
| 	return sg.IsTransportProtocolAllowed(p)
 | ||
| }
 | ||
| 
 | ||
| func (sg *RouteSet) IsUDPAllowed() bool {
 | ||
| 	return sg.IsTransportProtocolAllowed(UDP)
 | ||
| }
 | ||
| 
 | ||
| func (sg *RouteSet) IsTCPAllowed() bool {
 | ||
| 	return sg.IsTransportProtocolAllowed(TCP)
 | ||
| }
 | ||
| 
 | ||
| func (sg *RouteSet) IsAddrIn(a Addr) bool {
 | ||
| 	//我们先过滤传输层,再过滤网络层
 | ||
| 
 | ||
| 	if !sg.IsAddrNetworkAllowed(a) {
 | ||
| 		return false
 | ||
| 
 | ||
| 	} else if sg.NetRanger == nil && sg.IPs == nil && sg.Domains == nil && sg.Countries == nil {
 | ||
| 		//如果仅限制了一个传输层协议,且本集合里没有任何其它内容,那就直接通过
 | ||
| 		return true
 | ||
| 	}
 | ||
| 
 | ||
| 	//开始网络层判断
 | ||
| 	if len(a.IP) > 0 {
 | ||
| 		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.GetNetIPAddr()]; found {
 | ||
| 				return true
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	if a.Name != "" {
 | ||
| 		if sg.Domains != nil {
 | ||
| 
 | ||
| 			lastDotIndex := len(a.Name)
 | ||
| 
 | ||
| 			suffix := a.Name
 | ||
| 			for {
 | ||
| 
 | ||
| 				lastDotIndex = strings.LastIndex(a.Name[:lastDotIndex], ".")
 | ||
| 
 | ||
| 				suffix = a.Name[lastDotIndex+1:]
 | ||
| 				if _, found := sg.Domains[suffix]; found {
 | ||
| 					return true
 | ||
| 				}
 | ||
| 				if lastDotIndex == -1 {
 | ||
| 					goto afterName
 | ||
| 				}
 | ||
| 			}
 | ||
| 
 | ||
| 		}
 | ||
| 
 | ||
| 	}
 | ||
| afterName:
 | ||
| 	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"
 | ||
| }
 | 
