github.com/GuanceCloud/cliutils@v1.1.21/pipeline/ptinput/ipdb/iploc/iploc.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the MIT License. 3 // This product includes software developed at Guance Cloud (https://www.guance.com/). 4 // Copyright 2021-present Guance, Inc. 5 6 // Package iploc implement ipdb. 7 package iploc 8 9 import ( 10 "bufio" 11 "fmt" 12 "os" 13 "path/filepath" 14 "strings" 15 16 "github.com/GuanceCloud/cliutils/logger" 17 "github.com/GuanceCloud/cliutils/pipeline/ptinput/ipdb" 18 "github.com/GuanceCloud/cliutils/pipeline/ptinput/utils" 19 "github.com/ip2location/ip2location-go" 20 ) 21 22 var _ ipdb.IPdb = (*IPloc)(nil) 23 24 var l = logger.DefaultSLogger("iploc") 25 26 type DB interface { 27 Get_all(ipaddress string) (ip2location.IP2Locationrecord, error) 28 } 29 30 var openDB = func(f string) (DB, error) { 31 db, err := ip2location.OpenDB(f) 32 return db, err 33 } 34 35 const ( 36 FileSeparator = " " 37 38 ErrInvalidIP = "Invalid IP address" 39 ErrInvalidDB = "Invalid database file" 40 41 geoDefaultVal = "unknown" 42 ) 43 44 func InitLog() { 45 l = logger.SLogger("iploc") 46 } 47 48 type IPloc struct { 49 db DB 50 ispDB map[string]string 51 } 52 53 func (iploc *IPloc) Init(dataDir string, config map[string]string) { 54 ipdbDir := filepath.Join(dataDir, "ipdb", "iploc") 55 iplocFile := "iploc.bin" 56 ispFile := "ip2isp.txt" 57 58 if file, ok := config["iploc_file"]; ok { 59 if len(file) > 0 { 60 iplocFile = file 61 } 62 } 63 64 if file, ok := config["isp_file"]; ok { 65 if len(file) > 0 { 66 ispFile = file 67 } 68 } 69 70 if err := iploc.loadIPLib(filepath.Join(ipdbDir, iplocFile)); err != nil { 71 l.Warnf("iploc load ip lib error: %s", err.Error()) 72 } 73 74 iploc.ispDB = map[string]string{} 75 76 if err := iploc.loadISP(filepath.Join(ipdbDir, ispFile)); err != nil { 77 l.Warnf("isp file load error: %s", err.Error()) 78 } 79 } 80 81 func (iploc *IPloc) loadIPLib(f string) error { 82 if !utils.FileExist(f) { 83 l.Warnf("%v not found", f) 84 return nil 85 } 86 87 db, err := openDB(f) 88 if err != nil { 89 return err 90 } else { 91 iploc.db = db 92 } 93 94 return nil 95 } 96 97 func (iploc *IPloc) loadISP(f string) error { 98 m := make(map[string]string) 99 100 if !utils.FileExist(f) { 101 l.Warnf("%v not found", f) 102 return nil 103 } 104 105 fd, err := os.Open(filepath.Clean(f)) 106 if err != nil { 107 return err 108 } 109 110 defer fd.Close() //nolint:errcheck,gosec 111 112 scanner := bufio.NewScanner(fd) 113 for scanner.Scan() { 114 contents := strings.Split(scanner.Text(), FileSeparator) 115 if len(contents) != 2 { 116 continue 117 } 118 119 ipBitStr, err := ipdb.ParseIPCIDR(contents[0]) 120 if err != nil { 121 continue 122 } 123 m[ipBitStr] = contents[1] 124 } 125 126 if len(m) != 0 { 127 iploc.ispDB = m 128 l.Infof("found new %d rules", len(m)) 129 } else { 130 l.Infof("no rules founded") 131 } 132 133 return nil 134 } 135 136 func (iploc *IPloc) SearchIsp(ip string) string { 137 if len(iploc.ispDB) == 0 { 138 return "unknown" 139 } 140 141 for i := 32; i > 0; i-- { 142 ipCidr := fmt.Sprintf("%s/%v", ip, i) 143 ipBitStr, _ := ipdb.ParseIPCIDR(ipCidr) 144 if v, ok := iploc.ispDB[ipBitStr]; ok { 145 return v 146 } 147 } 148 return "unknown" 149 } 150 151 func (iploc *IPloc) Geo(ip string) (*ipdb.IPdbRecord, error) { 152 record := &ipdb.IPdbRecord{} 153 if iploc.db == nil { 154 return record, nil 155 } 156 157 r, err := iploc.get(ip) 158 if err != nil { 159 return nil, err 160 } 161 162 switch r.City { 163 case ErrInvalidIP, ErrInvalidDB: 164 r.City = geoDefaultVal 165 } 166 167 switch r.Region { 168 case ErrInvalidIP, ErrInvalidDB: 169 r.Region = geoDefaultVal 170 } 171 172 switch r.Country_short { 173 case ErrInvalidIP, ErrInvalidDB: 174 r.Country_short = geoDefaultVal 175 } 176 177 record.City = r.City 178 record.Region = r.Region 179 record.Country = r.Country_short 180 181 return record.CheckData(), err 182 } 183 184 func (iploc *IPloc) get(ip string) (*ip2location.IP2Locationrecord, error) { 185 if iploc.db == nil { 186 return nil, fmt.Errorf("GEO DB not set") 187 } 188 189 r, err := iploc.db.Get_all(ip) 190 if err != nil { 191 return nil, err 192 } 193 194 return &r, nil 195 }