From 5b47866f13d680cb48626d79a41078f627573fd5 Mon Sep 17 00:00:00 2001 From: Andrevich <47223721+1andrevich@users.noreply.github.com> Date: Sat, 28 Sep 2024 20:13:42 +0400 Subject: [PATCH] commit --- refilter-domain/go.mod | 14 - refilter-domain/go.sum | 22 - refilter-domain/main.go | 391 ---------------- refilter-geoip/config-example.json | 146 ------ refilter-geoip/config.json | 27 -- refilter-geoip/go.mod | 28 -- refilter-geoip/go.sum | 175 ------- refilter-geoip/init.go | 8 - refilter-geoip/lib/config.go | 128 ------ refilter-geoip/lib/error.go | 13 - refilter-geoip/lib/func.go | 43 -- refilter-geoip/lib/instance.go | 65 --- refilter-geoip/lib/lib.go | 458 ------------------- refilter-geoip/main.go | 41 -- refilter-geoip/plugin/maxmind/country_csv.go | 214 --------- refilter-geoip/plugin/maxmind/mmdb_in.go | 227 --------- refilter-geoip/plugin/plaintext/text_in.go | 227 --------- refilter-geoip/plugin/plaintext/text_out.go | 166 ------- refilter-geoip/plugin/special/cutter.go | 96 ---- refilter-geoip/plugin/special/private.go | 94 ---- refilter-geoip/plugin/special/test.go | 74 --- refilter-geoip/plugin/v2ray/dat_in.go | 204 --------- refilter-geoip/plugin/v2ray/dat_out.go | 227 --------- 23 files changed, 3088 deletions(-) delete mode 100644 refilter-domain/go.mod delete mode 100644 refilter-domain/go.sum delete mode 100644 refilter-domain/main.go delete mode 100644 refilter-geoip/config-example.json delete mode 100644 refilter-geoip/config.json delete mode 100644 refilter-geoip/go.mod delete mode 100644 refilter-geoip/go.sum delete mode 100644 refilter-geoip/init.go delete mode 100644 refilter-geoip/lib/config.go delete mode 100644 refilter-geoip/lib/error.go delete mode 100644 refilter-geoip/lib/func.go delete mode 100644 refilter-geoip/lib/instance.go delete mode 100644 refilter-geoip/lib/lib.go delete mode 100644 refilter-geoip/main.go delete mode 100644 refilter-geoip/plugin/maxmind/country_csv.go delete mode 100644 refilter-geoip/plugin/maxmind/mmdb_in.go delete mode 100644 refilter-geoip/plugin/plaintext/text_in.go delete mode 100644 refilter-geoip/plugin/plaintext/text_out.go delete mode 100644 refilter-geoip/plugin/special/cutter.go delete mode 100644 refilter-geoip/plugin/special/private.go delete mode 100644 refilter-geoip/plugin/special/test.go delete mode 100644 refilter-geoip/plugin/v2ray/dat_in.go delete mode 100644 refilter-geoip/plugin/v2ray/dat_out.go diff --git a/refilter-domain/go.mod b/refilter-domain/go.mod deleted file mode 100644 index e57ef79..0000000 --- a/refilter-domain/go.mod +++ /dev/null @@ -1,14 +0,0 @@ -module github.com/v2fly/domain-list-community - -go 1.19 - -require ( - github.com/v2fly/v2ray-core/v5 v5.15.1 - google.golang.org/protobuf v1.33.0 -) - -require ( - github.com/adrg/xdg v0.4.0 // indirect - github.com/golang/protobuf v1.5.4 // indirect - golang.org/x/sys v0.18.0 // indirect -) diff --git a/refilter-domain/go.sum b/refilter-domain/go.sum deleted file mode 100644 index 6b1b8db..0000000 --- a/refilter-domain/go.sum +++ /dev/null @@ -1,22 +0,0 @@ -github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= -github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/v2fly/v2ray-core/v5 v5.15.1 h1:n5Xvv3RkDcBYtHDpS6rkrOAS2WURfhZWSfvkxsgTK9M= -github.com/v2fly/v2ray-core/v5 v5.15.1/go.mod h1:IMP4oFah0SjutOQ3MTWmTz2LZeIielqE/sBhdAnhfd0= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/refilter-domain/main.go b/refilter-domain/main.go deleted file mode 100644 index d874270..0000000 --- a/refilter-domain/main.go +++ /dev/null @@ -1,391 +0,0 @@ -package main - -import ( - "bufio" - "errors" - "flag" - "fmt" - "os" - "path/filepath" - "sort" - "strconv" - "strings" - - router "github.com/v2fly/v2ray-core/v5/app/router/routercommon" - "google.golang.org/protobuf/proto" -) - -var ( - dataPath = flag.String("datapath", "./data", "Path to your custom 'data' directory") - outputName = flag.String("outputname", "dlc.dat", "Name of the generated dat file") - outputDir = flag.String("outputdir", "./", "Directory to place all generated files") - exportLists = flag.String("exportlists", "", "Lists to be flattened and exported in plaintext format, separated by ',' comma") -) - -type Entry struct { - Type string - Value string - Attrs []*router.Domain_Attribute -} - -type List struct { - Name string - Entry []Entry -} - -type ParsedList struct { - Name string - Inclusion map[string]bool - Entry []Entry -} - -func (l *ParsedList) toPlainText(listName string) error { - var entryBytes []byte - for _, entry := range l.Entry { - var attrString string - if entry.Attrs != nil { - for _, attr := range entry.Attrs { - attrString += "@" + attr.GetKey() + "," - } - attrString = strings.TrimRight(":"+attrString, ",") - } - // Entry output format is: type:domain.tld:@attr1,@attr2 - entryBytes = append(entryBytes, []byte(entry.Type+":"+entry.Value+attrString+"\n")...) - } - if err := os.WriteFile(filepath.Join(*outputDir, listName+".txt"), entryBytes, 0644); err != nil { - return fmt.Errorf(err.Error()) - } - return nil -} - -func (l *ParsedList) toProto() (*router.GeoSite, error) { - site := &router.GeoSite{ - CountryCode: l.Name, - } - for _, entry := range l.Entry { - switch entry.Type { - case "domain": - site.Domain = append(site.Domain, &router.Domain{ - Type: router.Domain_RootDomain, - Value: entry.Value, - Attribute: entry.Attrs, - }) - case "regexp": - site.Domain = append(site.Domain, &router.Domain{ - Type: router.Domain_Regex, - Value: entry.Value, - Attribute: entry.Attrs, - }) - case "keyword": - site.Domain = append(site.Domain, &router.Domain{ - Type: router.Domain_Plain, - Value: entry.Value, - Attribute: entry.Attrs, - }) - case "full": - site.Domain = append(site.Domain, &router.Domain{ - Type: router.Domain_Full, - Value: entry.Value, - Attribute: entry.Attrs, - }) - default: - return nil, errors.New("unknown domain type: " + entry.Type) - } - } - return site, nil -} - -func exportPlainTextList(list []string, refName string, pl *ParsedList) { - for _, listName := range list { - if strings.EqualFold(refName, listName) { - if err := pl.toPlainText(strings.ToLower(refName)); err != nil { - fmt.Println("Failed: ", err) - continue - } - fmt.Printf("'%s' has been generated successfully.\n", listName) - } - } -} - -func removeComment(line string) string { - idx := strings.Index(line, "#") - if idx == -1 { - return line - } - return strings.TrimSpace(line[:idx]) -} - -func parseDomain(domain string, entry *Entry) error { - kv := strings.Split(domain, ":") - if len(kv) == 1 { - entry.Type = "domain" - entry.Value = strings.ToLower(kv[0]) - return nil - } - - if len(kv) == 2 { - entry.Type = strings.ToLower(kv[0]) - entry.Value = strings.ToLower(kv[1]) - return nil - } - - return errors.New("Invalid format: " + domain) -} - -func parseAttribute(attr string) (*router.Domain_Attribute, error) { - var attribute router.Domain_Attribute - if len(attr) == 0 || attr[0] != '@' { - return &attribute, errors.New("invalid attribute: " + attr) - } - - // Trim attribute prefix `@` character - attr = attr[1:] - parts := strings.Split(attr, "=") - if len(parts) == 1 { - attribute.Key = strings.ToLower(parts[0]) - attribute.TypedValue = &router.Domain_Attribute_BoolValue{BoolValue: true} - } else { - attribute.Key = strings.ToLower(parts[0]) - intv, err := strconv.Atoi(parts[1]) - if err != nil { - return &attribute, errors.New("invalid attribute: " + attr + ": " + err.Error()) - } - attribute.TypedValue = &router.Domain_Attribute_IntValue{IntValue: int64(intv)} - } - return &attribute, nil -} - -func parseEntry(line string) (Entry, error) { - line = strings.TrimSpace(line) - parts := strings.Split(line, " ") - - var entry Entry - if len(parts) == 0 { - return entry, errors.New("empty entry") - } - - if err := parseDomain(parts[0], &entry); err != nil { - return entry, err - } - - for i := 1; i < len(parts); i++ { - attr, err := parseAttribute(parts[i]) - if err != nil { - return entry, err - } - entry.Attrs = append(entry.Attrs, attr) - } - - return entry, nil -} - -func Load(path string) (*List, error) { - file, err := os.Open(path) - if err != nil { - return nil, err - } - defer file.Close() - - list := &List{ - Name: strings.ToUpper(filepath.Base(path)), - } - scanner := bufio.NewScanner(file) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - line = removeComment(line) - if len(line) == 0 { - continue - } - entry, err := parseEntry(line) - if err != nil { - return nil, err - } - list.Entry = append(list.Entry, entry) - } - - return list, nil -} - -func isMatchAttr(Attrs []*router.Domain_Attribute, includeKey string) bool { - isMatch := false - mustMatch := true - matchName := includeKey - if strings.HasPrefix(includeKey, "!") { - isMatch = true - mustMatch = false - matchName = strings.TrimLeft(includeKey, "!") - } - - for _, Attr := range Attrs { - attrName := Attr.Key - if mustMatch { - if matchName == attrName { - isMatch = true - break - } - } else { - if matchName == attrName { - isMatch = false - break - } - } - } - return isMatch -} - -func createIncludeAttrEntrys(list *List, matchAttr *router.Domain_Attribute) []Entry { - newEntryList := make([]Entry, 0, len(list.Entry)) - matchName := matchAttr.Key - for _, entry := range list.Entry { - matched := isMatchAttr(entry.Attrs, matchName) - if matched { - newEntryList = append(newEntryList, entry) - } - } - return newEntryList -} - -func ParseList(list *List, ref map[string]*List) (*ParsedList, error) { - pl := &ParsedList{ - Name: list.Name, - Inclusion: make(map[string]bool), - } - entryList := list.Entry - for { - newEntryList := make([]Entry, 0, len(entryList)) - hasInclude := false - for _, entry := range entryList { - if entry.Type == "include" { - refName := strings.ToUpper(entry.Value) - if entry.Attrs != nil { - for _, attr := range entry.Attrs { - InclusionName := strings.ToUpper(refName + "@" + attr.Key) - if pl.Inclusion[InclusionName] { - continue - } - pl.Inclusion[InclusionName] = true - - refList := ref[refName] - if refList == nil { - return nil, errors.New(entry.Value + " not found.") - } - attrEntrys := createIncludeAttrEntrys(refList, attr) - if len(attrEntrys) != 0 { - newEntryList = append(newEntryList, attrEntrys...) - } - } - } else { - InclusionName := refName - if pl.Inclusion[InclusionName] { - continue - } - pl.Inclusion[InclusionName] = true - refList := ref[refName] - if refList == nil { - return nil, errors.New(entry.Value + " not found.") - } - newEntryList = append(newEntryList, refList.Entry...) - } - hasInclude = true - } else { - newEntryList = append(newEntryList, entry) - } - } - entryList = newEntryList - if !hasInclude { - break - } - } - pl.Entry = entryList - - return pl, nil -} - -func main() { - flag.Parse() - - dir := *dataPath - fmt.Println("Use domain lists in", dir) - - ref := make(map[string]*List) - err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - list, err := Load(path) - if err != nil { - return err - } - ref[list.Name] = list - return nil - }) - if err != nil { - fmt.Println("Failed: ", err) - os.Exit(1) - } - - // Create output directory if not exist - if _, err := os.Stat(*outputDir); os.IsNotExist(err) { - if mkErr := os.MkdirAll(*outputDir, 0755); mkErr != nil { - fmt.Println("Failed: ", mkErr) - os.Exit(1) - } - } - - protoList := new(router.GeoSiteList) - var existList []string - for refName, list := range ref { - pl, err := ParseList(list, ref) - if err != nil { - fmt.Println("Failed: ", err) - os.Exit(1) - } - site, err := pl.toProto() - if err != nil { - fmt.Println("Failed: ", err) - os.Exit(1) - } - protoList.Entry = append(protoList.Entry, site) - - // Flatten and export plaintext list - if *exportLists != "" { - if existList != nil { - exportPlainTextList(existList, refName, pl) - } else { - exportedListSlice := strings.Split(*exportLists, ",") - for _, exportedListName := range exportedListSlice { - fileName := filepath.Join(dir, exportedListName) - _, err := os.Stat(fileName) - if err == nil || os.IsExist(err) { - existList = append(existList, exportedListName) - } else { - fmt.Printf("'%s' list does not exist in '%s' directory.\n", exportedListName, dir) - } - } - if existList != nil { - exportPlainTextList(existList, refName, pl) - } - } - } - } - - // Sort protoList so the marshaled list is reproducible - sort.SliceStable(protoList.Entry, func(i, j int) bool { - return protoList.Entry[i].CountryCode < protoList.Entry[j].CountryCode - }) - - protoBytes, err := proto.Marshal(protoList) - if err != nil { - fmt.Println("Failed:", err) - os.Exit(1) - } - if err := os.WriteFile(filepath.Join(*outputDir, *outputName), protoBytes, 0644); err != nil { - fmt.Println("Failed: ", err) - os.Exit(1) - } else { - fmt.Println(*outputName, "has been generated successfully.") - } -} diff --git a/refilter-geoip/config-example.json b/refilter-geoip/config-example.json deleted file mode 100644 index 8313a88..0000000 --- a/refilter-geoip/config-example.json +++ /dev/null @@ -1,146 +0,0 @@ -{ - "input": [ - { - "type": "v2rayGeoIPDat", - "action": "add", - "args": { - "uri": "./geoip.dat", - "wantedList": ["cn", "us"], - "onlyIPType": "ipv4" - } - }, - { - "type": "v2rayGeoIPDat", - "action": "add", - "args": { - "uri": "https://raw.githubusercontent.com/v2fly/geoip/release/geoip.dat", - "onlyIPType": "ipv6" - } - }, - { - "type": "maxmindGeoLite2CountryCSV", - "action": "add", - "args": { - "country": "./geolite2/GeoLite2-Country-Locations-en.csv", - "ipv4": "./geolite2/GeoLite2-Country-Blocks-IPv4.csv", - "ipv6": "./geolite2/GeoLite2-Country-Blocks-IPv6.csv", - "wantedList": ["cn", "us"] - } - }, - { - "type": "maxmindMMDB", - "action": "add" - }, - { - "type": "maxmindMMDB", - "action": "add", - "args": { - "uri": "./path/to/your/mmdb/file", - "wantedList": ["cn", "us"], - "onlyIPType": "ipv4" - } - }, - { - "type": "maxmindMMDB", - "action": "add", - "args": { - "uri": "https://example.com/link/to/your/mmdb/file" - } - }, - { - "type": "maxmindMMDB", - "action": "remove", - "args": { - "uri": "https://example.com/link/to/your/mmdb/file", - "wantedList": ["jp", "sg"], - "onlyIPType": "ipv6" - } - }, - { - "type": "cutter", - "action": "remove", - "args": { - "wantedList": ["cn", "us"], - "onlyIPType": "ipv4" - } - }, - { - "type": "cutter", - "action": "remove", - "args": { - "onlyIPType": "ipv6" - } - }, - { - "type": "text", - "action": "add", - "args": { - "inputDir": "./data" - } - }, - { - "type": "text", - "action": "add", - "args": { - "name": "mylist", - "uri": "./an/example/dir/mycidr.txt", - "onlyIPType": "ipv6" - } - }, - { - "type": "text", - "action": "add", - "args": { - "name": "cn", - "uri": "https://raw.githubusercontent.com/17mon/china_ip_list/master/china_ip_list.txt", - "onlyIPType": "ipv4" - } - }, - { - "type": "private", - "action": "add" - }, - { - "type": "test", - "action": "add" - } - ], - "output": [ - { - "type": "v2rayGeoIPDat", - "action": "output", - "args": { - "outputName": "geoip.dat", - "outputDir": "./publish" - } - }, - { - "type": "v2rayGeoIPDat", - "action": "output", - "args": { - "outputName": "geoip-only-cn-private.dat", - "outputDir": "./publish", - "wantedList": ["cn", "private"] - } - }, - { - "type": "v2rayGeoIPDat", - "action": "output", - "args": { - "outputDir": "./publish", - "oneFilePerList": true, - "wantedList": ["cn", "private", "test"], - "onlyIPType": "ipv4" - } - }, - { - "type": "text", - "action": "output", - "args": { - "outputDir": "./publish", - "wantedList": ["cn", "us", "private"], - "onlyIPType": "ipv6" - } - } - ] -} diff --git a/refilter-geoip/config.json b/refilter-geoip/config.json deleted file mode 100644 index 0d69df9..0000000 --- a/refilter-geoip/config.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "input": [ - { - "type": "text", - "action": "add", - "args": { - "name": "refilter", - "uri": "https://raw.githubusercontent.com/1andrevich/Re-filter-lists/refs/heads/main/ipsum.lst", - "onlyIPType": "ipv4" - } - }, - { - "type": "private", - "action": "add" - } - ], - "output": [ - { - "type": "v2rayGeoIPDat", - "action": "output", - "args": { - "outputName": "geoip.dat", - "wantedList": ["refilter", "private"] - } - } - ] -} diff --git a/refilter-geoip/go.mod b/refilter-geoip/go.mod deleted file mode 100644 index 8254451..0000000 --- a/refilter-geoip/go.mod +++ /dev/null @@ -1,28 +0,0 @@ -module github.com/v2fly/geoip - -go 1.19 - -require ( - github.com/oschwald/maxminddb-golang v1.10.0 - github.com/v2fly/v2ray-core/v5 v5.4.1 - go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 - google.golang.org/protobuf v1.30.0 -) - -require ( - github.com/adrg/xdg v0.4.0 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/kr/pretty v0.3.1 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect - github.com/pires/go-proxyproto v0.6.2 // indirect - github.com/quic-go/qtls-go1-18 v0.2.0 // indirect - github.com/quic-go/qtls-go1-19 v0.2.1 // indirect - github.com/quic-go/qtls-go1-20 v0.1.1 // indirect - github.com/quic-go/quic-go v0.33.0 // indirect - go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect - golang.org/x/crypto v0.14.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect -) diff --git a/refilter-geoip/go.sum b/refilter-geoip/go.sum deleted file mode 100644 index 0ad6acd..0000000 --- a/refilter-geoip/go.sum +++ /dev/null @@ -1,175 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= -github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= -github.com/aead/cmac v0.0.0-20160719120800-7af84192f0b1 h1:+JkXLHME8vLJafGhOH4aoV2Iu8bR55nU6iKMVfYVLjY= -github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= -github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= -github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvPTF58Vq+qgmZEYZttJK+CWtSZhKenI= -github.com/bufbuild/protocompile v0.2.1-0.20230123224550-da57cd758c2f h1:IXSA5gow10s7zIOJfPOpXDtNBWCTA0715BDAhoJBXEs= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165 h1:BS21ZUJ/B5X2UVUbczfmdWH7GapPWAhxcMsDnjJTU1E= -github.com/ebfe/bcrypt_pbkdf v0.0.0-20140212075826-3c8d2dcb253a h1:YtdtTUN1iH97s+6PUjLnaiKSQj4oG1/EZ3N9bx6g4kU= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= -github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/jhump/protoreflect v1.15.0 h1:U5T5/2LF0AZQFP9T4W5GfBjBaTruomrKobiR4E+oA/Q= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/cpuid v1.2.3 h1:CCtW0xUnWGVINKvE/WWOYKdsPV6mawAtvQuSl8guwQs= -github.com/klauspost/reedsolomon v1.9.3 h1:N/VzgeMfHmLc+KHMD1UL/tNkfXAt8FnUqlgXGIduwAY= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= -github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= -github.com/mustafaturan/bus v1.0.2 h1:2x3ErwZ0uUPwwZ5ZZoknEQprdaxr68Yl3mY8jDye1Ws= -github.com/mustafaturan/monoton v1.0.0 h1:8SCej+JiNn0lyps7V+Jzc1CRAkDR4EZPWrTupQ61YCQ= -github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI= -github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= -github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg= -github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0= -github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pion/dtls/v2 v2.2.4 h1:YSfYwDQgrxMYXLBc/m7PFY5BVtWlNm/DN4qoU2CbcWg= -github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= -github.com/pion/sctp v1.7.6 h1:8qZTdJtbKfAns/Hv5L0PAj8FyXcsKhMH1pKUCGisQg4= -github.com/pion/transport/v2 v2.0.0 h1:bsMYyqHCbkvHwj+eNCFBuxtlKndKfyGI2vaQmM3fIE4= -github.com/pion/udp v0.1.4 h1:OowsTmu1Od3sD6i3fQUJxJn2fEvJO6L1TidgadtbTI8= -github.com/pires/go-proxyproto v0.6.2 h1:KAZ7UteSOt6urjme6ZldyFm4wDe/z0ZUP0Yv0Dos0d8= -github.com/pires/go-proxyproto v0.6.2/go.mod h1:Odh9VFOZJCf9G8cLW5o435Xf1J95Jw9Gw5rnCjcwzAY= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U= -github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc= -github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= -github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= -github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= -github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= -github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0= -github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA= -github.com/refraction-networking/utls v1.3.1 h1:3zVomUqx7nCmyGuU/6kYA/jp5NcqX8KQSGko8pY5Ch4= -github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/secure-io/siv-go v0.0.0-20180922214919-5ff40651e2c4 h1:zOjq+1/uLzn/Xo40stbvjIY/yehG0+mfmlsiEmc0xmQ= -github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/v2fly/BrowserBridge v0.0.0-20210430233438-0570fc1d7d08 h1:4Yh46CVE3k/lPq6hUbEdbB1u1anRBXLewm3k+L0iOMc= -github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848 h1:p1UzXK6VAutXFFQMnre66h7g1BjRKUnLv0HfmmRoz7w= -github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI= -github.com/v2fly/v2ray-core/v5 v5.4.1 h1:1l3KIFKoOlZkUp6D9MUlN/gz6aOEx09YfRVmnwnoGIQ= -github.com/v2fly/v2ray-core/v5 v5.4.1/go.mod h1:8JUFMS/1biOF9rWV7V5IU3NKU8GhCd442MqW3DgdFKw= -github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432 h1:I/ATawgO2RerCq9ACwL0wBB8xNXZdE3J+93MCEHReRs= -github.com/xtaci/smux v1.5.15 h1:6hMiXswcleXj5oNfcJc+DXS8Vj36XX2LaX98udog6Kc= -go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g= -go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk= -go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo= -go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= -golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/refilter-geoip/init.go b/refilter-geoip/init.go deleted file mode 100644 index c137de8..0000000 --- a/refilter-geoip/init.go +++ /dev/null @@ -1,8 +0,0 @@ -package main - -import ( - _ "github.com/v2fly/geoip/plugin/maxmind" - _ "github.com/v2fly/geoip/plugin/plaintext" - _ "github.com/v2fly/geoip/plugin/special" - _ "github.com/v2fly/geoip/plugin/v2ray" -) diff --git a/refilter-geoip/lib/config.go b/refilter-geoip/lib/config.go deleted file mode 100644 index 20e5137..0000000 --- a/refilter-geoip/lib/config.go +++ /dev/null @@ -1,128 +0,0 @@ -package lib - -import ( - "encoding/json" - "errors" - "fmt" - "strings" -) - -var ( - inputConfigCreatorCache = make(map[string]inputConfigCreator) - outputConfigCreatorCache = make(map[string]outputConfigCreator) -) - -type inputConfigCreator func(Action, json.RawMessage) (InputConverter, error) - -type outputConfigCreator func(Action, json.RawMessage) (OutputConverter, error) - -func RegisterInputConfigCreator(id string, fn inputConfigCreator) error { - id = strings.ToLower(id) - if _, found := inputConfigCreatorCache[id]; found { - return errors.New("config creator has already been registered") - } - inputConfigCreatorCache[id] = fn - return nil -} - -func createInputConfig(id string, action Action, data json.RawMessage) (InputConverter, error) { - id = strings.ToLower(id) - fn, found := inputConfigCreatorCache[id] - if !found { - return nil, errors.New("unknown config type") - } - return fn(action, data) -} - -func RegisterOutputConfigCreator(id string, fn outputConfigCreator) error { - id = strings.ToLower(id) - if _, found := outputConfigCreatorCache[id]; found { - return errors.New("config creator has already been registered") - } - outputConfigCreatorCache[id] = fn - return nil -} - -func createOutputConfig(id string, action Action, data json.RawMessage) (OutputConverter, error) { - id = strings.ToLower(id) - fn, found := outputConfigCreatorCache[id] - if !found { - return nil, errors.New("unknown config type") - } - return fn(action, data) -} - -type config struct { - Input []*inputConvConfig `json:"input"` - Output []*outputConvConfig `json:"output"` -} - -type inputConvConfig struct { - iType string - action Action - converter InputConverter -} - -func (i *inputConvConfig) UnmarshalJSON(data []byte) error { - var temp struct { - Type string `json:"type"` - Action Action `json:"action"` - Args json.RawMessage `json:"args"` - } - - if err := json.Unmarshal(data, &temp); err != nil { - return err - } - - if !ActionsRegistry[temp.Action] { - return fmt.Errorf("invalid action %s in type %s", temp.Action, temp.Type) - } - - config, err := createInputConfig(temp.Type, temp.Action, temp.Args) - if err != nil { - return err - } - - i.iType = config.GetType() - i.action = config.GetAction() - i.converter = config - - return nil -} - -type outputConvConfig struct { - iType string - action Action - converter OutputConverter -} - -func (i *outputConvConfig) UnmarshalJSON(data []byte) error { - var temp struct { - Type string `json:"type"` - Action Action `json:"action"` - Args json.RawMessage `json:"args"` - } - - if err := json.Unmarshal(data, &temp); err != nil { - return err - } - - if temp.Action == "" { - temp.Action = ActionOutput - } - - if !ActionsRegistry[temp.Action] { - return fmt.Errorf("invalid action %s in type %s", temp.Action, temp.Type) - } - - config, err := createOutputConfig(temp.Type, temp.Action, temp.Args) - if err != nil { - return err - } - - i.iType = config.GetType() - i.action = config.GetAction() - i.converter = config - - return nil -} diff --git a/refilter-geoip/lib/error.go b/refilter-geoip/lib/error.go deleted file mode 100644 index 5778e96..0000000 --- a/refilter-geoip/lib/error.go +++ /dev/null @@ -1,13 +0,0 @@ -package lib - -import "errors" - -var ( - ErrDuplicatedConverter = errors.New("duplicated converter") - ErrUnknownAction = errors.New("unknown action") - ErrInvalidIPType = errors.New("invalid IP type") - ErrInvalidIP = errors.New("invalid IP address") - ErrInvalidIPLength = errors.New("invalid IP address length") - ErrInvalidIPNet = errors.New("invalid IPNet address") - ErrInvalidPrefixType = errors.New("invalid prefix type") -) diff --git a/refilter-geoip/lib/func.go b/refilter-geoip/lib/func.go deleted file mode 100644 index 8cef3ce..0000000 --- a/refilter-geoip/lib/func.go +++ /dev/null @@ -1,43 +0,0 @@ -package lib - -import ( - "fmt" - "strings" -) - -var ( - inputConverterMap = make(map[string]InputConverter) - outputConverterMap = make(map[string]OutputConverter) -) - -func ListInputConverter() { - fmt.Println("All available input formats:") - for name, ic := range inputConverterMap { - fmt.Printf(" - %s (%s)\n", name, ic.GetDescription()) - } -} - -func RegisterInputConverter(name string, c InputConverter) error { - name = strings.TrimSpace(name) - if _, ok := inputConverterMap[name]; ok { - return ErrDuplicatedConverter - } - inputConverterMap[name] = c - return nil -} - -func ListOutputConverter() { - fmt.Println("All available output formats:") - for name, oc := range outputConverterMap { - fmt.Printf(" - %s (%s)\n", name, oc.GetDescription()) - } -} - -func RegisterOutputConverter(name string, c OutputConverter) error { - name = strings.TrimSpace(name) - if _, ok := outputConverterMap[name]; ok { - return ErrDuplicatedConverter - } - outputConverterMap[name] = c - return nil -} diff --git a/refilter-geoip/lib/instance.go b/refilter-geoip/lib/instance.go deleted file mode 100644 index 5631766..0000000 --- a/refilter-geoip/lib/instance.go +++ /dev/null @@ -1,65 +0,0 @@ -package lib - -import ( - "encoding/json" - "errors" - "os" -) - -type Instance struct { - config *config - input []InputConverter - output []OutputConverter -} - -func NewInstance() (*Instance, error) { - return &Instance{ - config: new(config), - input: make([]InputConverter, 0), - output: make([]OutputConverter, 0), - }, nil -} - -func (i *Instance) Init(configFile string) error { - content, err := os.ReadFile(configFile) - if err != nil { - return err - } - - if err := json.Unmarshal(content, &i.config); err != nil { - return err - } - - for _, input := range i.config.Input { - i.input = append(i.input, input.converter) - } - - for _, output := range i.config.Output { - i.output = append(i.output, output.converter) - } - - return nil -} - -func (i *Instance) Run() error { - if len(i.input) == 0 || len(i.output) == 0 { - return errors.New("input type and output type must be specified") - } - - var err error - container := NewContainer() - for _, ic := range i.input { - container, err = ic.Input(container) - if err != nil { - return err - } - } - - for _, oc := range i.output { - if err := oc.Output(container); err != nil { - return err - } - } - - return nil -} diff --git a/refilter-geoip/lib/lib.go b/refilter-geoip/lib/lib.go deleted file mode 100644 index d1d23ab..0000000 --- a/refilter-geoip/lib/lib.go +++ /dev/null @@ -1,458 +0,0 @@ -package lib - -import ( - "fmt" - "log" - "net" - "net/netip" - "strings" - "sync" - - "go4.org/netipx" -) - -const ( - ActionAdd Action = "add" - ActionRemove Action = "remove" - ActionOutput Action = "output" - - IPv4 IPType = "ipv4" - IPv6 IPType = "ipv6" -) - -var ActionsRegistry = map[Action]bool{ - ActionAdd: true, - ActionRemove: true, - ActionOutput: true, -} - -type Action string - -type IPType string - -type Typer interface { - GetType() string -} - -type Actioner interface { - GetAction() Action -} - -type Descriptioner interface { - GetDescription() string -} - -type InputConverter interface { - Typer - Actioner - Descriptioner - Input(Container) (Container, error) -} - -type OutputConverter interface { - Typer - Actioner - Descriptioner - Output(Container) error -} - -type Entry struct { - name string - mu *sync.Mutex - ipv4Builder *netipx.IPSetBuilder - ipv6Builder *netipx.IPSetBuilder -} - -func NewEntry(name string) *Entry { - return &Entry{ - name: strings.ToUpper(strings.TrimSpace(name)), - mu: new(sync.Mutex), - ipv4Builder: new(netipx.IPSetBuilder), - ipv6Builder: new(netipx.IPSetBuilder), - } -} - -func (e *Entry) GetName() string { - return e.name -} - -func (e *Entry) hasIPv4Builder() bool { - return e.ipv4Builder != nil -} - -func (e *Entry) hasIPv6Builder() bool { - return e.ipv6Builder != nil -} - -func (e *Entry) processPrefix(src any) (*netip.Prefix, IPType, error) { - switch src := src.(type) { - case net.IP: - ip, ok := netipx.FromStdIP(src) - if !ok { - return nil, "", ErrInvalidIP - } - switch { - case ip.Is4(): - prefix := netip.PrefixFrom(ip, 32) - return &prefix, IPv4, nil - case ip.Is6(): - prefix := netip.PrefixFrom(ip, 128) - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case *net.IPNet: - prefix, ok := netipx.FromStdIPNet(src) - if !ok { - return nil, "", ErrInvalidIPNet - } - ip := prefix.Addr() - switch { - case ip.Is4(): - return &prefix, IPv4, nil - case ip.Is6(): - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case netip.Addr: - switch { - case src.Is4(): - prefix := netip.PrefixFrom(src, 32) - return &prefix, IPv4, nil - case src.Is6(): - prefix := netip.PrefixFrom(src, 128) - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case *netip.Addr: - switch { - case src.Is4(): - prefix := netip.PrefixFrom(*src, 32) - return &prefix, IPv4, nil - case src.Is6(): - prefix := netip.PrefixFrom(*src, 128) - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case netip.Prefix: - ip := src.Addr() - switch { - case ip.Is4(): - return &src, IPv4, nil - case ip.Is6(): - return &src, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case *netip.Prefix: - ip := src.Addr() - switch { - case ip.Is4(): - return src, IPv4, nil - case ip.Is6(): - return src, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - case string: - _, network, err := net.ParseCIDR(src) - switch err { - case nil: - prefix, ok := netipx.FromStdIPNet(network) - if !ok { - return nil, "", ErrInvalidIPNet - } - ip := prefix.Addr() - switch { - case ip.Is4(): - return &prefix, IPv4, nil - case ip.Is6(): - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - - default: - ip, err := netip.ParseAddr(src) - if err != nil { - return nil, "", err - } - switch { - case ip.Is4(): - prefix := netip.PrefixFrom(ip, 32) - return &prefix, IPv4, nil - case ip.Is6(): - prefix := netip.PrefixFrom(ip, 128) - return &prefix, IPv6, nil - default: - return nil, "", ErrInvalidIPLength - } - } - } - - return nil, "", ErrInvalidPrefixType -} - -func (e *Entry) add(prefix *netip.Prefix, ipType IPType) error { - e.mu.Lock() - defer e.mu.Unlock() - - switch ipType { - case IPv4: - if !e.hasIPv4Builder() { - e.ipv4Builder = new(netipx.IPSetBuilder) - } - e.ipv4Builder.AddPrefix(*prefix) - case IPv6: - if !e.hasIPv6Builder() { - e.ipv6Builder = new(netipx.IPSetBuilder) - } - e.ipv6Builder.AddPrefix(*prefix) - default: - return ErrInvalidIPType - } - - return nil -} - -func (e *Entry) remove(prefix *netip.Prefix, ipType IPType) error { - e.mu.Lock() - defer e.mu.Unlock() - - switch ipType { - case IPv4: - if e.hasIPv4Builder() { - e.ipv4Builder.RemovePrefix(*prefix) - } - case IPv6: - if e.hasIPv6Builder() { - e.ipv6Builder.RemovePrefix(*prefix) - } - default: - return ErrInvalidIPType - } - - return nil -} - -func (e *Entry) AddPrefix(cidr any) error { - prefix, ipType, err := e.processPrefix(cidr) - if err != nil { - return err - } - if err := e.add(prefix, ipType); err != nil { - return err - } - return nil -} - -func (e *Entry) RemovePrefix(cidr string) error { - prefix, ipType, err := e.processPrefix(cidr) - if err != nil { - return err - } - if err := e.remove(prefix, ipType); err != nil { - return err - } - return nil -} - -func (e *Entry) MarshalText(opts ...IgnoreIPOption) ([]string, error) { - var ignoreIPType IPType - for _, opt := range opts { - if opt != nil { - ignoreIPType = opt() - } - } - disableIPv4, disableIPv6 := false, false - switch ignoreIPType { - case IPv4: - disableIPv4 = true - case IPv6: - disableIPv6 = true - } - - prefixSet := make([]string, 0, 1024) - - if !disableIPv4 && e.hasIPv4Builder() { - ipv4set, err := e.ipv4Builder.IPSet() - if err != nil { - return nil, err - } - prefixes := ipv4set.Prefixes() - for _, prefix := range prefixes { - prefixSet = append(prefixSet, prefix.String()) - } - } - - if !disableIPv6 && e.hasIPv6Builder() { - ipv6set, err := e.ipv6Builder.IPSet() - if err != nil { - return nil, err - } - prefixes := ipv6set.Prefixes() - for _, prefix := range prefixes { - prefixSet = append(prefixSet, prefix.String()) - } - } - - if len(prefixSet) > 0 { - return prefixSet, nil - } - - return nil, fmt.Errorf("entry %s has no prefix", e.GetName()) -} - -type IgnoreIPOption func() IPType - -func IgnoreIPv4() IPType { - return IPv4 -} - -func IgnoreIPv6() IPType { - return IPv6 -} - -type Container interface { - GetEntry(name string) (*Entry, bool) - Add(entry *Entry, opts ...IgnoreIPOption) error - Remove(name string, opts ...IgnoreIPOption) - Loop() <-chan *Entry -} - -type container struct { - entries *sync.Map // map[name]*Entry -} - -func NewContainer() Container { - return &container{ - entries: new(sync.Map), - } -} - -func (c *container) isValid() bool { - if c == nil || c.entries == nil { - return false - } - return true -} - -func (c *container) GetEntry(name string) (*Entry, bool) { - if !c.isValid() { - return nil, false - } - val, ok := c.entries.Load(strings.ToUpper(strings.TrimSpace(name))) - if !ok { - return nil, false - } - return val.(*Entry), true -} - -func (c *container) Loop() <-chan *Entry { - ch := make(chan *Entry, 300) - go func() { - c.entries.Range(func(key, value any) bool { - ch <- value.(*Entry) - return true - }) - close(ch) - }() - return ch -} - -func (c *container) Add(entry *Entry, opts ...IgnoreIPOption) error { - var ignoreIPType IPType - for _, opt := range opts { - if opt != nil { - ignoreIPType = opt() - } - } - - name := entry.GetName() - val, found := c.GetEntry(name) - switch found { - case true: - var ipv4set, ipv6set *netipx.IPSet - var err4, err6 error - if entry.hasIPv4Builder() { - ipv4set, err4 = entry.ipv4Builder.IPSet() - if err4 != nil { - return err4 - } - } - if entry.hasIPv6Builder() { - ipv6set, err6 = entry.ipv6Builder.IPSet() - if err6 != nil { - return err6 - } - } - switch ignoreIPType { - case IPv4: - if !val.hasIPv6Builder() { - val.ipv6Builder = new(netipx.IPSetBuilder) - } - val.ipv6Builder.AddSet(ipv6set) - case IPv6: - if !val.hasIPv4Builder() { - val.ipv4Builder = new(netipx.IPSetBuilder) - } - val.ipv4Builder.AddSet(ipv4set) - default: - if !val.hasIPv4Builder() { - val.ipv4Builder = new(netipx.IPSetBuilder) - } - if !val.hasIPv6Builder() { - val.ipv6Builder = new(netipx.IPSetBuilder) - } - val.ipv4Builder.AddSet(ipv4set) - val.ipv6Builder.AddSet(ipv6set) - } - c.entries.Store(name, val) - - case false: - switch ignoreIPType { - case IPv4: - entry.ipv4Builder = nil - case IPv6: - entry.ipv6Builder = nil - } - c.entries.Store(name, entry) - } - - return nil -} - -func (c *container) Remove(name string, opts ...IgnoreIPOption) { - val, found := c.GetEntry(name) - if !found { - log.Printf("failed to remove non-existent entry %s", name) - return - } - - var ignoreIPType IPType - for _, opt := range opts { - if opt != nil { - ignoreIPType = opt() - } - } - - switch ignoreIPType { - case IPv4: - val.ipv6Builder = nil - c.entries.Store(name, val) - case IPv6: - val.ipv4Builder = nil - c.entries.Store(name, val) - default: - c.entries.Delete(name) - } -} diff --git a/refilter-geoip/main.go b/refilter-geoip/main.go deleted file mode 100644 index c35696b..0000000 --- a/refilter-geoip/main.go +++ /dev/null @@ -1,41 +0,0 @@ -// GeoIP generator -// -// Before running this file, the GeoIP database must be downloaded and present. -// To download GeoIP database: https://dev.maxmind.com/geoip/geoip2/geolite2/ -// Inside you will find block files for IPv4 and IPv6 and country code mapping. -package main - -import ( - "flag" - "log" - - "github.com/v2fly/geoip/lib" -) - -var ( - list = flag.Bool("l", false, "List all available input and output formats") - configFile = flag.String("c", "config.json", "Path to the config file") -) - -func main() { - flag.Parse() - - if *list { - lib.ListInputConverter() - lib.ListOutputConverter() - return - } - - instance, err := lib.NewInstance() - if err != nil { - log.Fatal(err) - } - - if err := instance.Init(*configFile); err != nil { - log.Fatal(err) - } - - if err := instance.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/refilter-geoip/plugin/maxmind/country_csv.go b/refilter-geoip/plugin/maxmind/country_csv.go deleted file mode 100644 index 7773491..0000000 --- a/refilter-geoip/plugin/maxmind/country_csv.go +++ /dev/null @@ -1,214 +0,0 @@ -package maxmind - -import ( - "encoding/csv" - "encoding/json" - "errors" - "os" - "path/filepath" - "strings" - - "github.com/v2fly/geoip/lib" -) - -const ( - typeCountryCSV = "maxmindGeoLite2CountryCSV" - descCountryCSV = "Convert MaxMind GeoLite2 country CSV data to other formats" -) - -var ( - defaultCCFile = filepath.Join("./", "geolite2", "GeoLite2-Country-Locations-en.csv") - defaultIPv4File = filepath.Join("./", "geolite2", "GeoLite2-Country-Blocks-IPv4.csv") - defaultIPv6File = filepath.Join("./", "geolite2", "GeoLite2-Country-Blocks-IPv6.csv") -) - -func init() { - lib.RegisterInputConfigCreator(typeCountryCSV, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return newGeoLite2CountryCSV(action, data) - }) - lib.RegisterInputConverter(typeCountryCSV, &geoLite2CountryCSV{ - Description: descCountryCSV, - }) -} - -func newGeoLite2CountryCSV(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - var tmp struct { - CountryCodeFile string `json:"country"` - IPv4File string `json:"ipv4"` - IPv6File string `json:"ipv6"` - Want []string `json:"wantedList"` - OnlyIPType lib.IPType `json:"onlyIPType"` - } - - if len(data) > 0 { - if err := json.Unmarshal(data, &tmp); err != nil { - return nil, err - } - } - - if tmp.CountryCodeFile == "" { - tmp.CountryCodeFile = defaultCCFile - } - - if tmp.IPv4File == "" { - tmp.IPv4File = defaultIPv4File - } - - if tmp.IPv6File == "" { - tmp.IPv6File = defaultIPv6File - } - - return &geoLite2CountryCSV{ - Type: typeCountryCSV, - Action: action, - Description: descCountryCSV, - CountryCodeFile: tmp.CountryCodeFile, - IPv4File: tmp.IPv4File, - IPv6File: tmp.IPv6File, - Want: tmp.Want, - OnlyIPType: tmp.OnlyIPType, - }, nil -} - -type geoLite2CountryCSV struct { - Type string - Action lib.Action - Description string - CountryCodeFile string - IPv4File string - IPv6File string - Want []string - OnlyIPType lib.IPType -} - -func (g *geoLite2CountryCSV) GetType() string { - return g.Type -} - -func (g *geoLite2CountryCSV) GetAction() lib.Action { - return g.Action -} - -func (g *geoLite2CountryCSV) GetDescription() string { - return g.Description -} - -func (g *geoLite2CountryCSV) Input(container lib.Container) (lib.Container, error) { - ccMap, err := g.getCountryCode() - if err != nil { - return nil, err - } - - entries := make(map[string]*lib.Entry) - - if g.IPv4File != "" { - if err := g.process(g.IPv4File, ccMap, entries); err != nil { - return nil, err - } - } - - if g.IPv6File != "" { - if err := g.process(g.IPv6File, ccMap, entries); err != nil { - return nil, err - } - } - - var ignoreIPType lib.IgnoreIPOption - switch g.OnlyIPType { - case lib.IPv4: - ignoreIPType = lib.IgnoreIPv6 - case lib.IPv6: - ignoreIPType = lib.IgnoreIPv4 - } - - for name, entry := range entries { - switch g.Action { - case lib.ActionAdd: - if err := container.Add(entry, ignoreIPType); err != nil { - return nil, err - } - case lib.ActionRemove: - container.Remove(name, ignoreIPType) - default: - return nil, lib.ErrUnknownAction - } - } - - return container, nil -} - -func (g *geoLite2CountryCSV) getCountryCode() (map[string]string, error) { - ccReader, err := os.Open(g.CountryCodeFile) - if err != nil { - return nil, err - } - defer ccReader.Close() - - reader := csv.NewReader(ccReader) - lines, err := reader.ReadAll() - if err != nil { - return nil, err - } - - ccMap := make(map[string]string) - for _, line := range lines[1:] { - id := strings.TrimSpace(line[0]) - countryCode := strings.TrimSpace(line[4]) - if id == "" || countryCode == "" { - continue - } - ccMap[id] = strings.ToUpper(countryCode) - } - return ccMap, nil -} - -func (g *geoLite2CountryCSV) process(file string, ccMap map[string]string, entries map[string]*lib.Entry) error { - if len(ccMap) == 0 { - return errors.New("country code list must be specified") - } - if entries == nil { - entries = make(map[string]*lib.Entry) - } - - fReader, err := os.Open(file) - if err != nil { - return err - } - defer fReader.Close() - - reader := csv.NewReader(fReader) - lines, err := reader.ReadAll() - if err != nil { - return err - } - - // Filter want list - wantList := make(map[string]bool) - for _, want := range g.Want { - if want = strings.ToUpper(strings.TrimSpace(want)); want != "" { - wantList[want] = true - } - } - - for _, line := range lines[1:] { - ccID := strings.TrimSpace(line[1]) - if countryCode, found := ccMap[ccID]; found { - if len(wantList) > 0 { - if _, found := wantList[countryCode]; !found { - continue - } - } - cidrStr := strings.ToLower(strings.TrimSpace(line[0])) - entry, found := entries[countryCode] - if !found { - entry = lib.NewEntry(countryCode) - } - if err := entry.AddPrefix(cidrStr); err != nil { - return err - } - entries[countryCode] = entry - } - } - - return nil -} diff --git a/refilter-geoip/plugin/maxmind/mmdb_in.go b/refilter-geoip/plugin/maxmind/mmdb_in.go deleted file mode 100644 index 9261f18..0000000 --- a/refilter-geoip/plugin/maxmind/mmdb_in.go +++ /dev/null @@ -1,227 +0,0 @@ -package maxmind - -import ( - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "strings" - - "github.com/oschwald/maxminddb-golang" - "github.com/v2fly/geoip/lib" -) - -const ( - typeMaxmindMMDBIn = "maxmindMMDB" - descMaxmindMMDBIn = "Convert MaxMind mmdb database to other formats" -) - -var ( - defaultMMDBFile = filepath.Join("./", "geolite2", "GeoLite2-Country.mmdb") - tempMMDBPath = filepath.Join("./", "tmp") - tempMMDBFile = filepath.Join(tempMMDBPath, "input.mmdb") -) - -func init() { - lib.RegisterInputConfigCreator(typeMaxmindMMDBIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return newMaxmindMMDBIn(action, data) - }) - lib.RegisterInputConverter(typeMaxmindMMDBIn, &maxmindMMDBIn{ - Description: descMaxmindMMDBIn, - }) -} - -func newMaxmindMMDBIn(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - var tmp struct { - URI string `json:"uri"` - Want []string `json:"wantedList"` - OnlyIPType lib.IPType `json:"onlyIPType"` - } - - if len(data) > 0 { - if err := json.Unmarshal(data, &tmp); err != nil { - return nil, err - } - } - - if tmp.URI == "" { - tmp.URI = defaultMMDBFile - } - - return &maxmindMMDBIn{ - Type: typeMaxmindMMDBIn, - Action: action, - Description: descMaxmindMMDBIn, - URI: tmp.URI, - Want: tmp.Want, - OnlyIPType: tmp.OnlyIPType, - }, nil -} - -type maxmindMMDBIn struct { - Type string - Action lib.Action - Description string - URI string - Want []string - OnlyIPType lib.IPType -} - -func (g *maxmindMMDBIn) GetType() string { - return g.Type -} - -func (g *maxmindMMDBIn) GetAction() lib.Action { - return g.Action -} - -func (g *maxmindMMDBIn) GetDescription() string { - return g.Description -} - -func (g *maxmindMMDBIn) Input(container lib.Container) (lib.Container, error) { - var fd io.ReadCloser - var err error - switch { - case strings.HasPrefix(g.URI, "http://"), strings.HasPrefix(g.URI, "https://"): - fd, err = g.downloadFile(g.URI) - default: - fd, err = os.Open(g.URI) - } - - if err != nil { - return nil, err - } - - err = g.moveFile(fd) - if err != nil { - return nil, err - } - - entries := make(map[string]*lib.Entry) - err = g.generateEntries(entries) - if err != nil { - return nil, err - } - - if len(entries) == 0 { - return nil, fmt.Errorf("❌ [type %s | action %s] no entry is newly generated", typeMaxmindMMDBIn, g.Action) - } - - var ignoreIPType lib.IgnoreIPOption - switch g.OnlyIPType { - case lib.IPv4: - ignoreIPType = lib.IgnoreIPv6 - case lib.IPv6: - ignoreIPType = lib.IgnoreIPv4 - } - - // Filter want list - wantList := make(map[string]bool) - for _, want := range g.Want { - if want = strings.ToUpper(strings.TrimSpace(want)); want != "" { - wantList[want] = true - } - } - - for _, entry := range entries { - name := entry.GetName() - if len(wantList) > 0 && !wantList[name] { - continue - } - - switch g.Action { - case lib.ActionAdd: - if err := container.Add(entry, ignoreIPType); err != nil { - return nil, err - } - case lib.ActionRemove: - container.Remove(name, ignoreIPType) - } - } - - return container, nil -} - -func (g *maxmindMMDBIn) downloadFile(url string) (io.ReadCloser, error) { - resp, err := http.Get(url) - if err != nil { - return nil, err - } - - if resp.StatusCode != 200 { - return nil, fmt.Errorf("failed to get remote file %s, http status code %d", url, resp.StatusCode) - } - - return resp.Body, nil -} - -func (g *maxmindMMDBIn) moveFile(src io.ReadCloser) error { - defer src.Close() - - err := os.MkdirAll(tempMMDBPath, 0755) - if err != nil { - return err - } - - out, err := os.Create(tempMMDBFile) - if err != nil { - return err - } - defer out.Close() - - _, err = io.Copy(out, src) - - return err -} - -func (g *maxmindMMDBIn) generateEntries(entries map[string]*lib.Entry) error { - db, err := maxminddb.Open(tempMMDBFile) - if err != nil { - return err - } - defer db.Close() - - record := struct { - Country struct { - IsoCode string `maxminddb:"iso_code"` - } `maxminddb:"country"` - }{} - - networks := db.Networks(maxminddb.SkipAliasedNetworks) - for networks.Next() { - subnet, err := networks.Network(&record) - if err != nil { - continue - } - - var entry *lib.Entry - name := strings.ToUpper(record.Country.IsoCode) - if theEntry, found := entries[name]; found { - entry = theEntry - } else { - entry = lib.NewEntry(name) - } - - switch g.Action { - case lib.ActionAdd: - if err := entry.AddPrefix(subnet); err != nil { - return err - } - case lib.ActionRemove: - if err := entry.RemovePrefix(subnet.String()); err != nil { - return err - } - } - - entries[name] = entry - } - - if networks.Err() != nil { - return networks.Err() - } - - return nil -} diff --git a/refilter-geoip/plugin/plaintext/text_in.go b/refilter-geoip/plugin/plaintext/text_in.go deleted file mode 100644 index f3fd7ed..0000000 --- a/refilter-geoip/plugin/plaintext/text_in.go +++ /dev/null @@ -1,227 +0,0 @@ -package plaintext - -import ( - "bufio" - "encoding/json" - "fmt" - "io" - "net/http" - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/v2fly/geoip/lib" -) - -const ( - typeTextIn = "text" - descTextIn = "Convert plaintext IP and CIDR to other formats" -) - -func init() { - lib.RegisterInputConfigCreator(typeTextIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return newTextIn(action, data) - }) - lib.RegisterInputConverter(typeTextIn, &textIn{ - Description: descTextIn, - }) -} - -func newTextIn(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - var tmp struct { - Name string `json:"name"` - URI string `json:"uri"` - InputDir string `json:"inputDir"` - OnlyIPType lib.IPType `json:"onlyIPType"` - } - - if len(data) > 0 { - if err := json.Unmarshal(data, &tmp); err != nil { - return nil, err - } - } - - if tmp.Name == "" && tmp.URI == "" && tmp.InputDir == "" { - return nil, fmt.Errorf("type %s | action %s missing inputdir or name or uri", typeTextIn, action) - } - - if (tmp.Name != "" && tmp.URI == "") || (tmp.Name == "" && tmp.URI != "") { - return nil, fmt.Errorf("type %s | action %s name & uri must be specified together", typeTextIn, action) - } - - return &textIn{ - Type: typeTextIn, - Action: action, - Description: descTextIn, - Name: tmp.Name, - URI: tmp.URI, - InputDir: tmp.InputDir, - OnlyIPType: tmp.OnlyIPType, - }, nil -} - -type textIn struct { - Type string - Action lib.Action - Description string - Name string - URI string - InputDir string - OnlyIPType lib.IPType -} - -func (t *textIn) GetType() string { - return t.Type -} - -func (t *textIn) GetAction() lib.Action { - return t.Action -} - -func (t *textIn) GetDescription() string { - return t.Description -} - -func (t *textIn) Input(container lib.Container) (lib.Container, error) { - entries := make(map[string]*lib.Entry) - var err error - - switch { - case t.InputDir != "": - err = t.walkDir(t.InputDir, entries) - case t.Name != "" && t.URI != "": - switch { - case strings.HasPrefix(t.URI, "http://"), strings.HasPrefix(t.URI, "https://"): - err = t.walkRemoteFile(t.URI, t.Name, entries) - default: - err = t.walkLocalFile(t.URI, t.Name, entries) - } - default: - return nil, fmt.Errorf("config missing argument inputDir or name or uri") - } - - if err != nil { - return nil, err - } - - var ignoreIPType lib.IgnoreIPOption - switch t.OnlyIPType { - case lib.IPv4: - ignoreIPType = lib.IgnoreIPv6 - case lib.IPv6: - ignoreIPType = lib.IgnoreIPv4 - } - - if len(entries) == 0 { - return nil, fmt.Errorf("type %s | action %s no entry are generated", t.Type, t.Action) - } - - for _, entry := range entries { - switch t.Action { - case lib.ActionAdd: - if err := container.Add(entry, ignoreIPType); err != nil { - return nil, err - } - case lib.ActionRemove: - container.Remove(entry.GetName(), ignoreIPType) - } - } - - return container, nil -} - -func (t *textIn) walkDir(dir string, entries map[string]*lib.Entry) error { - err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if info.IsDir() { - return nil - } - - if err := t.walkLocalFile(path, "", entries); err != nil { - return err - } - - return nil - }) - - return err -} - -func (t *textIn) walkLocalFile(path, name string, entries map[string]*lib.Entry) error { - name = strings.TrimSpace(name) - var filename string - if name != "" { - filename = name - } else { - filename = filepath.Base(path) - } - - // check filename - if !regexp.MustCompile(`^[a-zA-Z0-9_.\-]+$`).MatchString(filename) { - return fmt.Errorf("filename %s cannot be entry name, please remove special characters in it", filename) - } - dotIndex := strings.LastIndex(filename, ".") - if dotIndex > 0 { - filename = filename[:dotIndex] - } - - if _, found := entries[filename]; found { - return fmt.Errorf("found duplicated file %s", filename) - } - - entry := lib.NewEntry(filename) - file, err := os.Open(path) - if err != nil { - return err - } - defer file.Close() - if err := t.scanFile(file, entry); err != nil { - return err - } - - entries[filename] = entry - - return nil -} - -func (t *textIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry) error { - resp, err := http.Get(url) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("failed to get remote file %s, http status code %d", url, resp.StatusCode) - } - - entry := lib.NewEntry(name) - if err := t.scanFile(resp.Body, entry); err != nil { - return err - } - - entries[name] = entry - return nil -} - -func (t *textIn) scanFile(reader io.Reader, entry *lib.Entry) error { - scanner := bufio.NewScanner(reader) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if line == "" { - continue - } - if err := entry.AddPrefix(line); err != nil { - return err - } - } - - if err := scanner.Err(); err != nil { - return err - } - - return nil -} diff --git a/refilter-geoip/plugin/plaintext/text_out.go b/refilter-geoip/plugin/plaintext/text_out.go deleted file mode 100644 index 68f1d92..0000000 --- a/refilter-geoip/plugin/plaintext/text_out.go +++ /dev/null @@ -1,166 +0,0 @@ -package plaintext - -import ( - "bytes" - "encoding/json" - "log" - "os" - "path/filepath" - "strings" - - "github.com/v2fly/geoip/lib" -) - -const ( - typeTextOut = "text" - descTextOut = "Convert data to plaintext CIDR format" -) - -var ( - defaultOutputDir = filepath.Join("./", "output", "text") -) - -func init() { - lib.RegisterOutputConfigCreator(typeTextOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) { - return newTextOut(action, data) - }) - lib.RegisterOutputConverter(typeTextOut, &textOut{ - Description: descTextOut, - }) -} - -func newTextOut(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) { - var tmp struct { - OutputDir string `json:"outputDir"` - Want []string `json:"wantedList"` - OnlyIPType lib.IPType `json:"onlyIPType"` - } - - if len(data) > 0 { - if err := json.Unmarshal(data, &tmp); err != nil { - return nil, err - } - } - - if tmp.OutputDir == "" { - tmp.OutputDir = defaultOutputDir - } - - return &textOut{ - Type: typeTextOut, - Action: action, - Description: descTextOut, - OutputDir: tmp.OutputDir, - Want: tmp.Want, - OnlyIPType: tmp.OnlyIPType, - }, nil -} - -type textOut struct { - Type string - Action lib.Action - Description string - OutputDir string - Want []string - OnlyIPType lib.IPType -} - -func (t *textOut) GetType() string { - return t.Type -} - -func (t *textOut) GetAction() lib.Action { - return t.Action -} - -func (t *textOut) GetDescription() string { - return t.Description -} - -func (t *textOut) Output(container lib.Container) error { - // Filter want list - wantList := make(map[string]bool) - for _, want := range t.Want { - if want = strings.ToUpper(strings.TrimSpace(want)); want != "" { - wantList[want] = true - } - } - - switch len(wantList) { - case 0: - for entry := range container.Loop() { - cidrList, err := t.marshalText(entry) - if err != nil { - return err - } - filename := strings.ToLower(entry.GetName()) + ".txt" - if err := t.writeFile(filename, cidrList); err != nil { - return err - } - } - - default: - for name := range wantList { - entry, found := container.GetEntry(name) - if !found { - log.Printf("❌ entry %s not found", name) - continue - } - cidrList, err := t.marshalText(entry) - if err != nil { - return err - } - filename := strings.ToLower(entry.GetName()) + ".txt" - if err := t.writeFile(filename, cidrList); err != nil { - return err - } - } - } - - return nil -} - -func (t *textOut) marshalText(entry *lib.Entry) ([]string, error) { - var entryCidr []string - var err error - switch t.OnlyIPType { - case lib.IPv4: - entryCidr, err = entry.MarshalText(lib.IgnoreIPv6) - if err != nil { - return nil, err - } - case lib.IPv6: - entryCidr, err = entry.MarshalText(lib.IgnoreIPv4) - if err != nil { - return nil, err - } - default: - entryCidr, err = entry.MarshalText() - if err != nil { - return nil, err - } - } - - return entryCidr, nil -} - -func (t *textOut) writeFile(filename string, cidrList []string) error { - var buf bytes.Buffer - for _, cidr := range cidrList { - buf.WriteString(cidr) - buf.WriteString("\n") - } - cidrBytes := buf.Bytes() - - if err := os.MkdirAll(t.OutputDir, 0755); err != nil { - return err - } - - if err := os.WriteFile(filepath.Join(t.OutputDir, filename), cidrBytes, 0644); err != nil { - return err - } - - log.Printf("✅ [%s] %s --> %s", t.Type, filename, t.OutputDir) - - return nil -} diff --git a/refilter-geoip/plugin/special/cutter.go b/refilter-geoip/plugin/special/cutter.go deleted file mode 100644 index 8a8fdba..0000000 --- a/refilter-geoip/plugin/special/cutter.go +++ /dev/null @@ -1,96 +0,0 @@ -package special - -import ( - "encoding/json" - "fmt" - "strings" - - "github.com/v2fly/geoip/lib" -) - -const ( - typeCutter = "cutter" - descCutter = "Remove data from previous steps" -) - -func init() { - lib.RegisterInputConfigCreator(typeCutter, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return newCutter(action, data) - }) - lib.RegisterInputConverter(typeCutter, &cutter{ - Description: descCutter, - }) -} - -func newCutter(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - var tmp struct { - Want []string `json:"wantedList"` - OnlyIPType lib.IPType `json:"onlyIPType"` - } - - if len(data) > 0 { - if err := json.Unmarshal(data, &tmp); err != nil { - return nil, err - } - } - - if action != lib.ActionRemove { - return nil, fmt.Errorf("type %s only supports `remove` action", typeCutter) - } - - return &cutter{ - Type: typeCutter, - Action: action, - Description: descCutter, - Want: tmp.Want, - OnlyIPType: tmp.OnlyIPType, - }, nil -} - -type cutter struct { - Type string - Action lib.Action - Description string - Want []string - OnlyIPType lib.IPType -} - -func (c *cutter) GetType() string { - return c.Type -} - -func (c *cutter) GetAction() lib.Action { - return c.Action -} - -func (c *cutter) GetDescription() string { - return c.Description -} - -func (c *cutter) Input(container lib.Container) (lib.Container, error) { - var ignoreIPType lib.IgnoreIPOption - switch c.OnlyIPType { - case lib.IPv4: - ignoreIPType = lib.IgnoreIPv6 - case lib.IPv6: - ignoreIPType = lib.IgnoreIPv4 - } - - // Filter want list - wantList := make(map[string]bool) - for _, want := range c.Want { - if want = strings.ToUpper(strings.TrimSpace(want)); want != "" { - wantList[want] = true - } - } - - for entry := range container.Loop() { - name := entry.GetName() - if len(wantList) > 0 && !wantList[name] { - continue - } - container.Remove(name, ignoreIPType) - } - - return container, nil -} diff --git a/refilter-geoip/plugin/special/private.go b/refilter-geoip/plugin/special/private.go deleted file mode 100644 index e9dceca..0000000 --- a/refilter-geoip/plugin/special/private.go +++ /dev/null @@ -1,94 +0,0 @@ -package special - -import ( - "encoding/json" - - "github.com/v2fly/geoip/lib" -) - -const ( - entryNamePrivate = "private" - typePrivate = "private" - descPrivate = "Convert LAN and private network CIDR to other formats" -) - -var privateCIDRs = []string{ - "0.0.0.0/8", - "10.0.0.0/8", - "100.64.0.0/10", - "127.0.0.0/8", - "169.254.0.0/16", - "172.16.0.0/12", - "192.0.0.0/24", - "192.0.2.0/24", - "192.88.99.0/24", - "192.168.0.0/16", - "198.18.0.0/15", - "198.51.100.0/24", - "203.0.113.0/24", - "224.0.0.0/4", - "240.0.0.0/4", - "255.255.255.255/32", - "::/128", - "::1/128", - "fc00::/7", - "fe80::/10", - "ff00::/8", -} - -func init() { - lib.RegisterInputConfigCreator(typePrivate, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return newPrivate(action, data) - }) - lib.RegisterInputConverter(typePrivate, &private{ - Description: descPrivate, - }) -} - -func newPrivate(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return &private{ - Type: typePrivate, - Action: action, - Description: descPrivate, - }, nil -} - -type private struct { - Type string - Action lib.Action - Description string -} - -func (p *private) GetType() string { - return p.Type -} - -func (p *private) GetAction() lib.Action { - return p.Action -} - -func (p *private) GetDescription() string { - return p.Description -} - -func (p *private) Input(container lib.Container) (lib.Container, error) { - entry := lib.NewEntry(entryNamePrivate) - for _, cidr := range privateCIDRs { - if err := entry.AddPrefix(cidr); err != nil { - return nil, err - } - } - - switch p.Action { - case lib.ActionAdd: - if err := container.Add(entry); err != nil { - return nil, err - } - case lib.ActionRemove: - container.Remove(entryNamePrivate) - default: - return nil, lib.ErrUnknownAction - } - - return container, nil -} diff --git a/refilter-geoip/plugin/special/test.go b/refilter-geoip/plugin/special/test.go deleted file mode 100644 index 1a48893..0000000 --- a/refilter-geoip/plugin/special/test.go +++ /dev/null @@ -1,74 +0,0 @@ -package special - -import ( - "encoding/json" - - "github.com/v2fly/geoip/lib" -) - -const ( - entryNameTest = "test" - typeTest = "test" - descTest = "Convert specific CIDR to other formats (for test only)" -) - -var testCIDRs = []string{ - "127.0.0.0/8", -} - -func init() { - lib.RegisterInputConfigCreator(typeTest, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return newTest(action, data) - }) - lib.RegisterInputConverter(typeTest, &test{ - Description: descTest, - }) -} - -func newTest(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return &test{ - Type: typeTest, - Action: action, - Description: descTest, - }, nil -} - -type test struct { - Type string - Action lib.Action - Description string -} - -func (t *test) GetType() string { - return t.Type -} - -func (t *test) GetAction() lib.Action { - return t.Action -} - -func (t *test) GetDescription() string { - return t.Description -} - -func (t *test) Input(container lib.Container) (lib.Container, error) { - entry := lib.NewEntry(entryNameTest) - for _, cidr := range testCIDRs { - if err := entry.AddPrefix(cidr); err != nil { - return nil, err - } - } - - switch t.Action { - case lib.ActionAdd: - if err := container.Add(entry); err != nil { - return nil, err - } - case lib.ActionRemove: - container.Remove(entryNameTest) - default: - return nil, lib.ErrUnknownAction - } - - return container, nil -} diff --git a/refilter-geoip/plugin/v2ray/dat_in.go b/refilter-geoip/plugin/v2ray/dat_in.go deleted file mode 100644 index 03874a7..0000000 --- a/refilter-geoip/plugin/v2ray/dat_in.go +++ /dev/null @@ -1,204 +0,0 @@ -package v2ray - -import ( - "encoding/json" - "fmt" - "io" - "net" - "net/http" - "os" - "strings" - - "github.com/v2fly/geoip/lib" - router "github.com/v2fly/v2ray-core/v5/app/router/routercommon" - "google.golang.org/protobuf/proto" -) - -const ( - typeGeoIPdatIn = "v2rayGeoIPDat" - descGeoIPdatIn = "Convert V2Ray GeoIP dat to other formats" -) - -func init() { - lib.RegisterInputConfigCreator(typeGeoIPdatIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - return newGeoIPDatIn(action, data) - }) - lib.RegisterInputConverter(typeGeoIPdatIn, &geoIPDatIn{ - Description: descGeoIPdatIn, - }) -} - -func newGeoIPDatIn(action lib.Action, data json.RawMessage) (lib.InputConverter, error) { - var tmp struct { - URI string `json:"uri"` - Want []string `json:"wantedList"` - OnlyIPType lib.IPType `json:"onlyIPType"` - } - - if len(data) > 0 { - if err := json.Unmarshal(data, &tmp); err != nil { - return nil, err - } - } - - if tmp.URI == "" { - return nil, fmt.Errorf("[type %s | action %s] uri must be specified in config", typeGeoIPdatIn, action) - } - - return &geoIPDatIn{ - Type: typeGeoIPdatIn, - Action: action, - Description: descGeoIPdatIn, - URI: tmp.URI, - Want: tmp.Want, - OnlyIPType: tmp.OnlyIPType, - }, nil -} - -type geoIPDatIn struct { - Type string - Action lib.Action - Description string - URI string - Want []string - OnlyIPType lib.IPType -} - -func (g *geoIPDatIn) GetType() string { - return g.Type -} - -func (g *geoIPDatIn) GetAction() lib.Action { - return g.Action -} - -func (g *geoIPDatIn) GetDescription() string { - return g.Description -} - -func (g *geoIPDatIn) Input(container lib.Container) (lib.Container, error) { - entries := make(map[string]*lib.Entry) - var err error - - switch { - case strings.HasPrefix(g.URI, "http://"), strings.HasPrefix(g.URI, "https://"): - err = g.walkRemoteFile(g.URI, entries) - default: - err = g.walkLocalFile(g.URI, entries) - } - - if err != nil { - return nil, err - } - - if len(entries) == 0 { - return nil, fmt.Errorf("❌ [type %s | action %s] no entry is newly generated", typeGeoIPdatIn, g.Action) - } - - var ignoreIPType lib.IgnoreIPOption - switch g.OnlyIPType { - case lib.IPv4: - ignoreIPType = lib.IgnoreIPv6 - case lib.IPv6: - ignoreIPType = lib.IgnoreIPv4 - } - - // Filter want list - wantList := make(map[string]bool) - for _, want := range g.Want { - if want = strings.ToUpper(strings.TrimSpace(want)); want != "" { - wantList[want] = true - } - } - - for _, entry := range entries { - name := entry.GetName() - if len(wantList) > 0 && !wantList[name] { - continue - } - - switch g.Action { - case lib.ActionAdd: - if err := container.Add(entry, ignoreIPType); err != nil { - return nil, err - } - case lib.ActionRemove: - container.Remove(name, ignoreIPType) - } - } - - return container, nil -} - -func (g *geoIPDatIn) walkLocalFile(path string, entries map[string]*lib.Entry) error { - file, err := os.Open(path) - if err != nil { - return err - } - defer file.Close() - - if err := g.generateEntries(file, entries); err != nil { - return err - } - - return nil -} - -func (g *geoIPDatIn) walkRemoteFile(url string, entries map[string]*lib.Entry) error { - resp, err := http.Get(url) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != 200 { - return fmt.Errorf("failed to get remote file %s, http status code %d", url, resp.StatusCode) - } - - if err := g.generateEntries(resp.Body, entries); err != nil { - return err - } - - return nil -} - -func (g *geoIPDatIn) generateEntries(reader io.Reader, entries map[string]*lib.Entry) error { - geoipBytes, err := io.ReadAll(reader) - if err != nil { - return err - } - - var geoipList router.GeoIPList - if err := proto.Unmarshal(geoipBytes, &geoipList); err != nil { - return err - } - - for _, geoip := range geoipList.Entry { - var entry *lib.Entry - name := geoip.CountryCode - if theEntry, found := entries[name]; found { - fmt.Printf("⚠️ [type %s | action %s] found duplicated entry: %s. Process anyway\n", typeGeoIPdatIn, g.Action, name) - entry = theEntry - } else { - entry = lib.NewEntry(name) - } - - for _, v2rayCIDR := range geoip.Cidr { - ipStr := net.IP(v2rayCIDR.GetIp()).String() + "/" + fmt.Sprint(v2rayCIDR.GetPrefix()) - switch g.Action { - case lib.ActionAdd: - if err := entry.AddPrefix(ipStr); err != nil { - return err - } - case lib.ActionRemove: - if err := entry.RemovePrefix(ipStr); err != nil { - return err - } - } - } - - entries[name] = entry - } - - return nil -} diff --git a/refilter-geoip/plugin/v2ray/dat_out.go b/refilter-geoip/plugin/v2ray/dat_out.go deleted file mode 100644 index 3c4ba23..0000000 --- a/refilter-geoip/plugin/v2ray/dat_out.go +++ /dev/null @@ -1,227 +0,0 @@ -package v2ray - -import ( - "encoding/json" - "fmt" - "log" - "os" - "path/filepath" - "sort" - "strings" - - "github.com/v2fly/geoip/lib" - router "github.com/v2fly/v2ray-core/v5/app/router/routercommon" - "github.com/v2fly/v2ray-core/v5/infra/conf/rule" - "google.golang.org/protobuf/proto" -) - -const ( - typeGeoIPdatOut = "v2rayGeoIPDat" - descGeoIPdatOut = "Convert data to V2Ray GeoIP dat format" -) - -var ( - defaultOutputName = "geoip.dat" - defaultOutputDir = filepath.Join("./", "output", "dat") -) - -func init() { - lib.RegisterOutputConfigCreator(typeGeoIPdatOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) { - return newGeoIPDat(action, data) - }) - lib.RegisterOutputConverter(typeGeoIPdatOut, &geoIPDatOut{ - Description: descGeoIPdatOut, - }) -} - -func newGeoIPDat(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) { - var tmp struct { - OutputName string `json:"outputName"` - OutputDir string `json:"outputDir"` - Want []string `json:"wantedList"` - OneFilePerList bool `json:"oneFilePerList"` - OnlyIPType lib.IPType `json:"onlyIPType"` - } - - if len(data) > 0 { - if err := json.Unmarshal(data, &tmp); err != nil { - return nil, err - } - } - - if tmp.OutputName == "" { - tmp.OutputName = defaultOutputName - } - - if tmp.OutputDir == "" { - tmp.OutputDir = defaultOutputDir - } - - return &geoIPDatOut{ - Type: typeGeoIPdatOut, - Action: action, - Description: descGeoIPdatOut, - OutputName: tmp.OutputName, - OutputDir: tmp.OutputDir, - Want: tmp.Want, - OneFilePerList: tmp.OneFilePerList, - OnlyIPType: tmp.OnlyIPType, - }, nil -} - -type geoIPDatOut struct { - Type string - Action lib.Action - Description string - OutputName string - OutputDir string - Want []string - OneFilePerList bool - OnlyIPType lib.IPType -} - -func (g *geoIPDatOut) GetType() string { - return g.Type -} - -func (g *geoIPDatOut) GetAction() lib.Action { - return g.Action -} - -func (g *geoIPDatOut) GetDescription() string { - return g.Description -} - -func (g *geoIPDatOut) Output(container lib.Container) error { - // Filter want list - wantList := make(map[string]bool) - for _, want := range g.Want { - if want = strings.ToUpper(strings.TrimSpace(want)); want != "" { - wantList[want] = true - } - } - - geoIPList := new(router.GeoIPList) - geoIPList.Entry = make([]*router.GeoIP, 0, 300) - updated := false - switch len(wantList) { - case 0: - for entry := range container.Loop() { - geoIP, err := g.generateGeoIP(entry) - if err != nil { - return err - } - geoIPList.Entry = append(geoIPList.Entry, geoIP) - updated = true - - if g.OneFilePerList { - geoIPBytes, err := proto.Marshal(geoIPList) - if err != nil { - return err - } - filename := strings.ToLower(entry.GetName()) + ".dat" - if err := g.writeFile(filename, geoIPBytes); err != nil { - return err - } - geoIPList.Entry = nil - } - } - - default: - for name := range wantList { - entry, found := container.GetEntry(name) - if !found { - log.Printf("❌ entry %s not found", name) - continue - } - geoIP, err := g.generateGeoIP(entry) - if err != nil { - return err - } - geoIPList.Entry = append(geoIPList.Entry, geoIP) - updated = true - - if g.OneFilePerList { - geoIPBytes, err := proto.Marshal(geoIPList) - if err != nil { - return err - } - filename := strings.ToLower(entry.GetName()) + ".dat" - if err := g.writeFile(filename, geoIPBytes); err != nil { - return err - } - geoIPList.Entry = nil - } - } - } - - // Sort to make reproducible builds - g.sort(geoIPList) - - if !g.OneFilePerList && updated { - geoIPBytes, err := proto.Marshal(geoIPList) - if err != nil { - return err - } - if err := g.writeFile(g.OutputName, geoIPBytes); err != nil { - return err - } - } - - return nil -} - -func (g *geoIPDatOut) generateGeoIP(entry *lib.Entry) (*router.GeoIP, error) { - var entryCidr []string - var err error - switch g.OnlyIPType { - case lib.IPv4: - entryCidr, err = entry.MarshalText(lib.IgnoreIPv6) - case lib.IPv6: - entryCidr, err = entry.MarshalText(lib.IgnoreIPv4) - default: - entryCidr, err = entry.MarshalText() - } - if err != nil { - return nil, err - } - - v2rayCIDR := make([]*router.CIDR, 0, 1024) - for _, cidrStr := range entryCidr { - cidr, err := rule.ParseIP(cidrStr) - if err != nil { - return nil, err - } - v2rayCIDR = append(v2rayCIDR, cidr) - } - - if len(v2rayCIDR) > 0 { - return &router.GeoIP{ - CountryCode: entry.GetName(), - Cidr: v2rayCIDR, - }, nil - } - - return nil, fmt.Errorf("entry %s has no CIDR", entry.GetName()) -} - -// Sort by country code to make reproducible builds -func (g *geoIPDatOut) sort(list *router.GeoIPList) { - sort.SliceStable(list.Entry, func(i, j int) bool { - return list.Entry[i].CountryCode < list.Entry[j].CountryCode - }) -} - -func (g *geoIPDatOut) writeFile(filename string, geoIPBytes []byte) error { - if err := os.MkdirAll(g.OutputDir, 0755); err != nil { - return err - } - - if err := os.WriteFile(filepath.Join(g.OutputDir, filename), geoIPBytes, 0644); err != nil { - return err - } - - log.Printf("✅ [%s] %s --> %s", g.Type, filename, g.OutputDir) - - return nil -}