mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-10-22 08:19:28 +08:00
修订代码,示例;添加geosite分流,域名现已支持full,sub,regex,geosite,match
This commit is contained in:
44
configs.go
44
configs.go
@@ -21,6 +21,33 @@ func init() {
|
||||
flag.IntVar(&jsonMode, "jm", 0, "json mode, 0:verysimple mode; 1: v2ray mode(not implemented yet)")
|
||||
}
|
||||
|
||||
//mainfallback, dnsConf, routePolicy
|
||||
func loadCommonComponentsFromStandardConf() {
|
||||
|
||||
if len(standardConf.Fallbacks) != 0 {
|
||||
mainFallback = httpLayer.NewClassicFallbackFromConfList(standardConf.Fallbacks)
|
||||
}
|
||||
|
||||
if dnsConf := standardConf.DnsConf; dnsConf != nil {
|
||||
dnsMachine = proxy.LoadDnsMachine(dnsConf)
|
||||
}
|
||||
|
||||
hasAppLevelMyCountry := (standardConf.App != nil && standardConf.App.MyCountryISO_3166 != "")
|
||||
|
||||
if standardConf.Route != nil || hasAppLevelMyCountry {
|
||||
|
||||
netLayer.LoadMaxmindGeoipFile("")
|
||||
|
||||
routePolicy = netLayer.NewRoutePolicy()
|
||||
if hasAppLevelMyCountry {
|
||||
routePolicy.AddRouteSet(netLayer.NewRouteSetForMyCountry(standardConf.App.MyCountryISO_3166))
|
||||
|
||||
}
|
||||
|
||||
proxy.LoadRulesForRoutePolicy(standardConf.Route, routePolicy)
|
||||
}
|
||||
}
|
||||
|
||||
// set conf variable, or exit the program; 还会设置mainFallback
|
||||
// 先检查configFileName是否存在,存在就尝试加载文件,否则尝试 -L参数
|
||||
func loadConfig() (err error) {
|
||||
@@ -37,26 +64,21 @@ func loadConfig() (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
if len(standardConf.Fallbacks) != 0 {
|
||||
mainFallback = httpLayer.NewClassicFallbackFromConfList(standardConf.Fallbacks)
|
||||
|
||||
}
|
||||
confMode = 1
|
||||
|
||||
//loglevel 和 noreadv这种会被 命令行覆盖的配置,需要直接在 loadConfig函数中先处理一遍
|
||||
if appConf := standardConf.App; appConf != nil {
|
||||
if appConf.LogLevel != nil {
|
||||
default_uuid = appConf.DefaultUUID
|
||||
|
||||
if appConf.LogLevel != nil && !utils.IsFlagPassed("ll") {
|
||||
utils.LogLevel = *appConf.LogLevel
|
||||
|
||||
}
|
||||
default_uuid = appConf.DefaultUUID
|
||||
if appConf.NoReadV {
|
||||
if appConf.NoReadV && !utils.IsFlagPassed("readv") {
|
||||
netLayer.UseReadv = false
|
||||
}
|
||||
}
|
||||
if dnsConf := standardConf.DnsConf; dnsConf != nil {
|
||||
|
||||
dnsMachine = proxy.LoadDnsMachine(dnsConf)
|
||||
|
||||
}
|
||||
return
|
||||
} else {
|
||||
//默认认为所有其他后缀的都是json格式,因为有时我会用 server.json.vless 这种写法
|
||||
|
@@ -85,7 +85,7 @@ path = "ohmygod_verysimple_is_very_simple"
|
||||
[[route]]
|
||||
dialTag = "my_vless1"
|
||||
|
||||
# 这个route中,我们只给了tag, 没给其它限定条件,这个是无效的,永远匹配不到。
|
||||
# 上面这个route中,我们只给了tag, 没给其它限定条件,这个是无效的,永远匹配不到。
|
||||
|
||||
|
||||
[[route]]
|
||||
@@ -98,9 +98,9 @@ country = ["US"]
|
||||
|
||||
|
||||
# 比如这个就是 将CN国家的ip 导向自己的grpc节点
|
||||
[[route]]
|
||||
dialTag = "my_grpc"
|
||||
country = ["CN"]
|
||||
#[[route]]
|
||||
#dialTag = "my_grpc"
|
||||
#country = ["CN"]
|
||||
|
||||
|
||||
# 比如这个就是 将CN国家的ip进行直连
|
||||
@@ -108,20 +108,31 @@ country = ["CN"]
|
||||
#dialTag = "direct"
|
||||
#country = ["CN"]
|
||||
|
||||
# 本示例为了测试节点可用性, 默认将直连的路由注释掉了, 如果你在CN国家并想直连CN的ip, 请取消注释上面三行. 并移除其它路由CN的route项
|
||||
|
||||
|
||||
# 下面这种dialTag传入列表的用法非常简洁, 可以达到负载均衡的效果,
|
||||
# 每次路由US国家的流量都会随机从列表中选一项
|
||||
#[[route]]
|
||||
#dialTag = ["my_vps1","myvps2"]
|
||||
#country = ["US"]
|
||||
|
||||
# 本示例为了测试节点可用性, 默认将直连的路由注释掉了, 如果你在CN国家并想直连CN的ip, 请取消注释上面三行. 并移除其它路由CN的route项
|
||||
|
||||
|
||||
# 如果所有route均不匹配,则数据会流向 "proxy" 这个tag 的 dial,如果 没有任何dial具有 "proxy" 这个标签名,则流向第一个dial
|
||||
|
||||
# 如果匹配了app.mycountry, 则数据会直接被直连.
|
||||
# 其它分流匹配示例:
|
||||
# ip = ["0.0.0.0/8","10.0.0.0/8","fe80::/10","10.0.0.1"]
|
||||
# domain = ["www.google.com","www.twitter.com"]
|
||||
|
||||
# 域名匹配完全兼容 v2ray,请参考 https://www.v2fly.org/config/routing.html#ruleobject
|
||||
# domain = ["domain:www.google.com","full:www.twitter.com", "geosite:cn"]
|
||||
|
||||
# 比如这个就是 将CN国家的域名 导向自己的grpc节点
|
||||
[[route]]
|
||||
dialTag = "my_grpc"
|
||||
domain = ["geosite:cn"]
|
||||
|
||||
# network = ["tcp","udp"]
|
||||
# inTag = ["tag1","tag2"]
|
||||
# country = ["CN"]
|
||||
|
69
main.go
69
main.go
@@ -86,16 +86,6 @@ func init() {
|
||||
|
||||
}
|
||||
|
||||
func isFlagPassed(name string) bool {
|
||||
found := false
|
||||
flag.Visit(func(f *flag.Flag) {
|
||||
if f.Name == name {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
flag.Parse()
|
||||
@@ -123,12 +113,6 @@ func main() {
|
||||
defer p.Stop()
|
||||
}
|
||||
|
||||
ll_beforeLoadConfigFile := utils.LogLevel
|
||||
usereadv_beforeLoadConfigFile := netLayer.UseReadv
|
||||
|
||||
cmdLL_given := isFlagPassed("ll")
|
||||
cmdUseReadv_given := isFlagPassed("readv")
|
||||
|
||||
if err := loadConfig(); err != nil && !isFlexible() {
|
||||
log.Printf("no config exist, and no api server or interactive cli enabled, exiting...")
|
||||
os.Exit(-1)
|
||||
@@ -136,20 +120,6 @@ func main() {
|
||||
|
||||
netLayer.Prepare()
|
||||
|
||||
//有点尴尬, 读取配置文件必须要用命令行参数,而配置文件里的部分配置又会覆盖部分命令行参数
|
||||
|
||||
if cmdLL_given && utils.LogLevel != ll_beforeLoadConfigFile {
|
||||
//配置文件配置了日志等级, 但是因为 命令行给出的值优先, 所以要设回
|
||||
|
||||
utils.LogLevel = ll_beforeLoadConfigFile
|
||||
}
|
||||
|
||||
if cmdUseReadv_given && netLayer.UseReadv != usereadv_beforeLoadConfigFile {
|
||||
//配置文件配置了readv, 但是因为 命令行给出的值优先, 所以要设回
|
||||
|
||||
netLayer.UseReadv = usereadv_beforeLoadConfigFile
|
||||
}
|
||||
|
||||
//Printf不会发生 escapes to heap 现象,所以我们统一用 Printf
|
||||
fmt.Printf("Log Level:%d\n", utils.LogLevel)
|
||||
fmt.Printf("UseReadv:%t\n", netLayer.UseReadv)
|
||||
@@ -183,13 +153,14 @@ func main() {
|
||||
}
|
||||
}
|
||||
case standardMode:
|
||||
|
||||
loadCommonComponentsFromStandardConf()
|
||||
|
||||
//虽然标准模式支持多个Server,目前先只考虑一个
|
||||
//多个Server存在的话,则必须要用 tag指定路由; 然后,我们需在预先阶段就判断好tag指定的路由
|
||||
|
||||
if len(standardConf.Listen) < 1 {
|
||||
if ce := utils.CanLogWarn("no listen in config settings"); ce != nil {
|
||||
ce.Write()
|
||||
}
|
||||
utils.Warn("no listen in config settings")
|
||||
break
|
||||
}
|
||||
|
||||
@@ -211,21 +182,6 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
hasMyCountry := (standardConf.App != nil && standardConf.App.MyCountryISO_3166 != "")
|
||||
|
||||
if standardConf.Route != nil || hasMyCountry {
|
||||
|
||||
netLayer.LoadMaxmindGeoipFile("")
|
||||
|
||||
routePolicy = netLayer.NewRoutePolicy()
|
||||
if hasMyCountry {
|
||||
routePolicy.AddRouteSet(netLayer.NewRouteSetForMyCountry(standardConf.App.MyCountryISO_3166))
|
||||
|
||||
}
|
||||
|
||||
proxy.LoadRulesForRoutePolicy(standardConf.Route, routePolicy)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var defaultOutClient proxy.Client
|
||||
@@ -241,9 +197,7 @@ func main() {
|
||||
case standardMode:
|
||||
|
||||
if len(standardConf.Dial) < 1 {
|
||||
if ce := utils.CanLogWarn("no dial in config settings"); ce != nil {
|
||||
ce.Write()
|
||||
}
|
||||
utils.Warn("no dial in config settings")
|
||||
break
|
||||
}
|
||||
|
||||
@@ -331,15 +285,13 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client) {
|
||||
|
||||
handleFunc := inServer.HandleInitialLayersFunc()
|
||||
if handleFunc == nil {
|
||||
utils.ZapLogger.Fatal("inServer.IsHandleInitialLayers but inServer.HandleInitialLayersFunc() returns nil")
|
||||
utils.Fatal("inServer.IsHandleInitialLayers but inServer.HandleInitialLayersFunc() returns nil")
|
||||
}
|
||||
|
||||
//baseConn可以为nil,quic就是如此
|
||||
newConnChan, baseConn := handleFunc()
|
||||
if newConnChan == nil {
|
||||
if ce := utils.CanLogErr("StarthandleInitialLayers can't extablish baseConn"); ce != nil {
|
||||
ce.Write()
|
||||
}
|
||||
utils.Error("StarthandleInitialLayers can't extablish baseConn")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -347,10 +299,7 @@ func listenSer(inServer proxy.Server, defaultOutClientForThis proxy.Client) {
|
||||
for {
|
||||
newConn, ok := <-newConnChan
|
||||
if !ok {
|
||||
if ce := utils.CanLogErr("read from SuperProxy not ok"); ce != nil {
|
||||
ce.Write()
|
||||
|
||||
}
|
||||
utils.Error("read from SuperProxy not ok")
|
||||
|
||||
quic.CloseSession(baseConn)
|
||||
|
||||
@@ -1150,7 +1099,7 @@ func dialClient(iics incomingInserverConnState, targetAddr netLayer.Addr, client
|
||||
|
||||
} else {
|
||||
//虽然拨号失败,但是不能认为我们一定有错误, 因为很可能申请的ip本身就是不可达的, 所以不是error等级而是warn等级
|
||||
if ce := utils.CanLogWarn("failed in dial"); ce != nil {
|
||||
if ce := utils.CanLogWarn("failed dialing"); ce != nil {
|
||||
ce.Write(
|
||||
zap.String("target", realTargetAddr.String()),
|
||||
zap.Error(err),
|
||||
|
@@ -383,6 +383,9 @@ func UDPAddr_v4_to_Bytes(addr *net.UDPAddr) [6]byte {
|
||||
}
|
||||
|
||||
func UDPAddr2AddrPort(ua *net.UDPAddr) netip.AddrPort {
|
||||
if ua == nil {
|
||||
return netip.AddrPort{}
|
||||
}
|
||||
a, _ := netip.AddrFromSlice(ua.IP)
|
||||
return netip.AddrPortFrom(a, uint16(ua.Port))
|
||||
}
|
||||
|
@@ -12,6 +12,8 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/hahahrfool/v2ray_simple/utils"
|
||||
)
|
||||
@@ -83,7 +85,9 @@ var GeositeListMap = make(map[string]*GeositeList)
|
||||
//geosite:cn 这种是geosite列表匹配
|
||||
|
||||
func IsDomainInsideGeosite(geositeName string, domain string) bool {
|
||||
geositeName = strings.ToUpper(geositeName)
|
||||
glist := GeositeListMap[geositeName]
|
||||
//log.Println("IsDomainInsideGeosite called", geositeName, len(glist))
|
||||
if glist == nil {
|
||||
return false
|
||||
}
|
||||
@@ -91,11 +95,15 @@ func IsDomainInsideGeosite(geositeName string, domain string) bool {
|
||||
if _, found := glist.FullDomains[domain]; found {
|
||||
return true
|
||||
}
|
||||
if found := HasFullOrSubDomain(domain, MapGeositeDomainHaser(glist.Domains)); found {
|
||||
if HasFullOrSubDomain(domain, MapGeositeDomainHaser(glist.Domains)) {
|
||||
return true
|
||||
}
|
||||
|
||||
//todo: regex part
|
||||
for _, reg := range glist.RegexDomains {
|
||||
if reg.MatchString(domain) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
@@ -122,7 +130,7 @@ type GeositeList struct {
|
||||
|
||||
FullDomains map[string]GeositeDomain
|
||||
Domains map[string]GeositeDomain
|
||||
RegexDomains []GeositeDomain
|
||||
RegexDomains []*regexp.Regexp
|
||||
}
|
||||
|
||||
type MapGeositeDomainHaser map[string]GeositeDomain
|
||||
@@ -132,10 +140,15 @@ func (mdh MapGeositeDomainHaser) HasDomain(d string) bool {
|
||||
return found
|
||||
}
|
||||
|
||||
//从 geosite/data 文件夹中读取所有文件并加载到 GeositeListMap 中
|
||||
//从 geosite/data 文件夹中读取所有文件并加载到 GeositeListMap 中.
|
||||
//
|
||||
//该 geosite/data 就是 github.com/v2fly/domain-list-community 项目的 data文件夹.
|
||||
func LoadGeositeFiles() (err error) {
|
||||
dir := "geosite/data"
|
||||
dir = utils.GetFilePath(dir)
|
||||
if !utils.DirExist(dir) {
|
||||
return os.ErrNotExist
|
||||
}
|
||||
ref := make(map[string]*GeositeRawList)
|
||||
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
@@ -169,7 +182,7 @@ func LoadGeositeFiles() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 该函数适用于系统中没有git的情况, 如果有git我们直接 git clone就行了
|
||||
// 该函数适用于系统中没有git的情况, 如果有git我们直接 git clone就行了,而且还能不断pull进行滚动更新
|
||||
func DownloadCommunity_DomainListFiles() {
|
||||
resp, err := http.Get("https://api.github.com/repos/v2fly/domain-list-community/releases/latest")
|
||||
if err != nil {
|
||||
|
@@ -5,11 +5,12 @@ import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//来自 v2fly, 改动改了一下命名。
|
||||
//来自 v2fly, 有一定改动.
|
||||
|
||||
// GeositeRawList 用于序列化
|
||||
type GeositeRawList struct {
|
||||
@@ -34,7 +35,7 @@ func LoadGeositeFile(path string) (*GeositeRawList, error) {
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
entry, err := parseGeoSiteEntry(line)
|
||||
entry, err := parseGeositeEntry(line)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -44,7 +45,7 @@ func LoadGeositeFile(path string) (*GeositeRawList, error) {
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func parseGeoSiteEntry(line string) (GeositeDomain, error) {
|
||||
func parseGeositeEntry(line string) (GeositeDomain, error) {
|
||||
line = strings.TrimSpace(line)
|
||||
parts := strings.Split(line, " ")
|
||||
|
||||
@@ -219,13 +220,17 @@ func (grl *GeositeRawList) ToGeositeList() (gl *GeositeList) {
|
||||
gl.Name = grl.Name
|
||||
gl.Domains = make(map[string]GeositeDomain)
|
||||
gl.FullDomains = make(map[string]GeositeDomain)
|
||||
gl.RegexDomains = make([]GeositeDomain, 0)
|
||||
gl.RegexDomains = make([]*regexp.Regexp, 0)
|
||||
for _, v := range grl.Domains {
|
||||
switch v.Type {
|
||||
case "domain":
|
||||
gl.Domains[v.Value] = v
|
||||
case "regexp":
|
||||
gl.RegexDomains = append(gl.RegexDomains, v)
|
||||
reg, err := regexp.Compile(v.Value)
|
||||
if err == nil {
|
||||
gl.RegexDomains = append(gl.RegexDomains, reg)
|
||||
|
||||
}
|
||||
case "full":
|
||||
gl.FullDomains[v.Value] = v
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ package netLayer
|
||||
import (
|
||||
"math/rand"
|
||||
"net/netip"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/yl2chen/cidranger"
|
||||
@@ -55,7 +56,15 @@ type RouteSet struct {
|
||||
//网络层
|
||||
NetRanger cidranger.Ranger //一个范围
|
||||
IPs map[netip.Addr]bool //一个确定值
|
||||
Domains, InTags, Countries map[string]bool // Countries 使用 ISO 3166 字符串 作为key
|
||||
|
||||
//Match 匹配任意字符串
|
||||
//Domains匹配子域名,当此域名是目标域名或其子域名时,该规则生效
|
||||
//Full只匹配完整域名
|
||||
Domains, Full, InTags, Countries map[string]bool // Countries 使用 ISO 3166 字符串 作为key
|
||||
|
||||
//Regex是正则匹配域名
|
||||
Regex []*regexp.Regexp
|
||||
Match, Geosites []string
|
||||
|
||||
//传输层
|
||||
AllowedTransportLayerProtocols uint16
|
||||
@@ -76,7 +85,7 @@ func NewRouteSetForMyCountry(iso string) *RouteSet {
|
||||
AllowedTransportLayerProtocols: TCP | UDP, //默认即支持tcp和udp
|
||||
|
||||
}
|
||||
rs.Countries[iso] = true
|
||||
rs.Countries[strings.ToUpper(iso)] = true
|
||||
rs.Domains[strings.ToLower(iso)] = true //iso字符串的小写正好可以作为顶级域名
|
||||
return rs
|
||||
}
|
||||
@@ -85,7 +94,10 @@ func NewFullRouteSet() *RouteSet {
|
||||
return &RouteSet{
|
||||
NetRanger: cidranger.NewPCTrieRanger(),
|
||||
IPs: make(map[netip.Addr]bool),
|
||||
Match: make([]string, 0),
|
||||
Domains: make(map[string]bool),
|
||||
Full: make(map[string]bool),
|
||||
Geosites: make([]string, 0),
|
||||
InTags: make(map[string]bool),
|
||||
Countries: make(map[string]bool),
|
||||
AllowedTransportLayerProtocols: TCP | UDP, //默认即支持tcp和udp
|
||||
@@ -160,12 +172,45 @@ func (sg *RouteSet) IsAddrIn(a Addr) bool {
|
||||
}
|
||||
|
||||
if a.Name != "" {
|
||||
if sg.Domains != nil {
|
||||
|
||||
if len(sg.Full) > 0 {
|
||||
if _, found := sg.Full[a.Name]; found {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if len(sg.Domains) > 0 {
|
||||
|
||||
return HasFullOrSubDomain(a.Name, MapDomainHaser(sg.Domains))
|
||||
|
||||
}
|
||||
|
||||
if len(sg.Match) > 0 {
|
||||
for _, m := range sg.Match {
|
||||
if strings.Contains(a.Name, m) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(sg.Regex) > 0 {
|
||||
for _, reg := range sg.Regex {
|
||||
if reg.MatchString(a.Name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(sg.Geosites) > 0 && len(GeositeListMap) > 0 {
|
||||
|
||||
for _, g := range sg.Geosites {
|
||||
if IsDomainInsideGeosite(g, a.Name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -172,6 +173,14 @@ func LoadRulesForRoutePolicy(rules []*RuleConf, policy *netLayer.RoutePolicy) {
|
||||
}
|
||||
|
||||
func LoadRuleForRouteSet(rule *RuleConf) (rs *netLayer.RouteSet) {
|
||||
if len(netLayer.GeositeListMap) == 0 {
|
||||
err := netLayer.LoadGeositeFiles()
|
||||
if err != nil {
|
||||
if ce := utils.CanLogWarn("geosite folder not exist"); ce != nil {
|
||||
ce.Write(zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
rs = netLayer.NewFullRouteSet()
|
||||
|
||||
switch value := rule.DialTag.(type) {
|
||||
@@ -185,12 +194,37 @@ func LoadRuleForRouteSet(rule *RuleConf) (rs *netLayer.RouteSet) {
|
||||
rs.Countries[c] = true
|
||||
}
|
||||
|
||||
for _, c := range rule.Domains {
|
||||
rs.Domains[c] = true
|
||||
for _, d := range rule.Domains {
|
||||
colonIdx := strings.Index(d, ":")
|
||||
if colonIdx < 0 {
|
||||
rs.Match = append(rs.Match, d)
|
||||
|
||||
} else {
|
||||
switch d[:colonIdx] {
|
||||
case "geosite":
|
||||
if netLayer.GeositeListMap != nil {
|
||||
rs.Geosites = append(rs.Geosites, d[colonIdx+1:])
|
||||
|
||||
}
|
||||
case "full":
|
||||
rs.Full[d[colonIdx+1:]] = true
|
||||
case "domain":
|
||||
rs.Domains[d[colonIdx+1:]] = true
|
||||
case "regexp":
|
||||
reg, err := regexp.Compile(d[colonIdx+1:])
|
||||
if err == nil {
|
||||
rs.Regex = append(rs.Regex, reg)
|
||||
}
|
||||
}
|
||||
|
||||
for _, c := range rule.InTags {
|
||||
rs.InTags[c] = true
|
||||
}
|
||||
|
||||
continue
|
||||
|
||||
}
|
||||
|
||||
for _, t := range rule.InTags {
|
||||
rs.InTags[t] = true
|
||||
}
|
||||
|
||||
//ip 过滤 需要 分辨 cidr 和普通ip
|
||||
|
17
utils/log.go
17
utils/log.go
@@ -1,4 +1,3 @@
|
||||
// Package utils provides utilities that is used in all sub-packages in verysimple
|
||||
package utils
|
||||
|
||||
import (
|
||||
@@ -102,3 +101,19 @@ func CanLogFatal(msg string) *zapcore.CheckedEntry {
|
||||
return ZapLogger.Check(zap.FatalLevel, msg)
|
||||
|
||||
}
|
||||
|
||||
func Debug(msg string) {
|
||||
ZapLogger.Debug(msg)
|
||||
}
|
||||
func Info(msg string) {
|
||||
ZapLogger.Info(msg)
|
||||
}
|
||||
func Warn(msg string) {
|
||||
ZapLogger.Warn(msg)
|
||||
}
|
||||
func Error(msg string) {
|
||||
ZapLogger.Error(msg)
|
||||
}
|
||||
func Fatal(msg string) {
|
||||
ZapLogger.Fatal(msg)
|
||||
}
|
||||
|
14
utils/utils.go
Normal file
14
utils/utils.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Package utils provides utilities that is used in all codes in verysimple
|
||||
package utils
|
||||
|
||||
import "flag"
|
||||
|
||||
func IsFlagPassed(name string) bool {
|
||||
found := false
|
||||
flag.Visit(func(f *flag.Flag) {
|
||||
if f.Name == name {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
return found
|
||||
}
|
Reference in New Issue
Block a user