geodb.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. package geodb
  2. import (
  3. _ "embed"
  4. "log"
  5. "net/http"
  6. "strings"
  7. "imuslab.com/zoraxy/mod/database"
  8. )
  9. //go:embed geoipv4.csv
  10. var geoipv4 []byte //Geodb dataset for ipv4
  11. //go:embed geoipv6.csv
  12. var geoipv6 []byte //Geodb dataset for ipv6
  13. type Store struct {
  14. BlacklistEnabled bool
  15. WhitelistEnabled bool
  16. geodb [][]string //Parsed geodb list
  17. geodbIpv6 [][]string //Parsed geodb list for ipv6
  18. geotrie *trie
  19. geotrieIpv6 *trie
  20. //geoipCache sync.Map
  21. sysdb *database.Database
  22. }
  23. type CountryInfo struct {
  24. CountryIsoCode string
  25. ContinetCode string
  26. }
  27. func NewGeoDb(sysdb *database.Database) (*Store, error) {
  28. parsedGeoData, err := parseCSV(geoipv4)
  29. if err != nil {
  30. return nil, err
  31. }
  32. parsedGeoDataIpv6, err := parseCSV(geoipv6)
  33. if err != nil {
  34. return nil, err
  35. }
  36. blacklistEnabled := false
  37. whitelistEnabled := false
  38. if sysdb != nil {
  39. err = sysdb.NewTable("blacklist-cn")
  40. if err != nil {
  41. return nil, err
  42. }
  43. err = sysdb.NewTable("blacklist-ip")
  44. if err != nil {
  45. return nil, err
  46. }
  47. err = sysdb.NewTable("whitelist-cn")
  48. if err != nil {
  49. return nil, err
  50. }
  51. err = sysdb.NewTable("whitelist-ip")
  52. if err != nil {
  53. return nil, err
  54. }
  55. err = sysdb.NewTable("blackwhitelist")
  56. if err != nil {
  57. return nil, err
  58. }
  59. sysdb.Read("blackwhitelist", "blacklistEnabled", &blacklistEnabled)
  60. sysdb.Read("blackwhitelist", "whitelistEnabled", &whitelistEnabled)
  61. } else {
  62. log.Println("Database pointer set to nil: Entering debug mode")
  63. }
  64. return &Store{
  65. BlacklistEnabled: blacklistEnabled,
  66. WhitelistEnabled: whitelistEnabled,
  67. geodb: parsedGeoData,
  68. geotrie: constrctTrieTree(parsedGeoData),
  69. geodbIpv6: parsedGeoDataIpv6,
  70. geotrieIpv6: constrctTrieTree(parsedGeoDataIpv6),
  71. sysdb: sysdb,
  72. }, nil
  73. }
  74. func (s *Store) ToggleBlacklist(enabled bool) {
  75. s.sysdb.Write("blackwhitelist", "blacklistEnabled", enabled)
  76. s.BlacklistEnabled = enabled
  77. }
  78. func (s *Store) ToggleWhitelist(enabled bool) {
  79. s.sysdb.Write("blackwhitelist", "whitelistEnabled", enabled)
  80. s.WhitelistEnabled = enabled
  81. }
  82. func (s *Store) ResolveCountryCodeFromIP(ipstring string) (*CountryInfo, error) {
  83. cc := s.search(ipstring)
  84. return &CountryInfo{
  85. CountryIsoCode: cc,
  86. ContinetCode: "",
  87. }, nil
  88. }
  89. func (s *Store) Close() {
  90. }
  91. /*
  92. Country code based black / white list
  93. */
  94. func (s *Store) AddCountryCodeToBlackList(countryCode string) {
  95. countryCode = strings.ToLower(countryCode)
  96. s.sysdb.Write("blacklist-cn", countryCode, true)
  97. }
  98. func (s *Store) RemoveCountryCodeFromBlackList(countryCode string) {
  99. countryCode = strings.ToLower(countryCode)
  100. s.sysdb.Delete("blacklist-cn", countryCode)
  101. }
  102. func (s *Store) AddCountryCodeToWhitelist(countryCode string) {
  103. countryCode = strings.ToLower(countryCode)
  104. s.sysdb.Write("whitelist-cn", countryCode, true)
  105. }
  106. func (s *Store) RemoveCountryCodeFromWhitelist(countryCode string) {
  107. countryCode = strings.ToLower(countryCode)
  108. s.sysdb.Delete("whitelist-cn", countryCode)
  109. }
  110. func (s *Store) IsCountryCodeBlacklisted(countryCode string) bool {
  111. countryCode = strings.ToLower(countryCode)
  112. var isBlacklisted bool = false
  113. s.sysdb.Read("blacklist-cn", countryCode, &isBlacklisted)
  114. return isBlacklisted
  115. }
  116. func (s *Store) IsCountryCodeWhitelisted(countryCode string) bool {
  117. countryCode = strings.ToLower(countryCode)
  118. var isWhitelisted bool = false
  119. s.sysdb.Read("whitelist-cn", countryCode, &isWhitelisted)
  120. return isWhitelisted
  121. }
  122. func (s *Store) GetAllBlacklistedCountryCode() []string {
  123. bannedCountryCodes := []string{}
  124. entries, err := s.sysdb.ListTable("blacklist-cn")
  125. if err != nil {
  126. return bannedCountryCodes
  127. }
  128. for _, keypairs := range entries {
  129. ip := string(keypairs[0])
  130. bannedCountryCodes = append(bannedCountryCodes, ip)
  131. }
  132. return bannedCountryCodes
  133. }
  134. func (s *Store) GetAllWhitelistedCountryCode() []string {
  135. whitelistedCountryCode := []string{}
  136. entries, err := s.sysdb.ListTable("whitelist-cn")
  137. if err != nil {
  138. return whitelistedCountryCode
  139. }
  140. for _, keypairs := range entries {
  141. ip := string(keypairs[0])
  142. whitelistedCountryCode = append(whitelistedCountryCode, ip)
  143. }
  144. return whitelistedCountryCode
  145. }
  146. /*
  147. IP based black / whitelist
  148. */
  149. func (s *Store) AddIPToBlackList(ipAddr string) {
  150. s.sysdb.Write("blacklist-ip", ipAddr, true)
  151. }
  152. func (s *Store) RemoveIPFromBlackList(ipAddr string) {
  153. s.sysdb.Delete("blacklist-ip", ipAddr)
  154. }
  155. func (s *Store) AddIPToWhiteList(ipAddr string) {
  156. s.sysdb.Write("whitelist-ip", ipAddr, true)
  157. }
  158. func (s *Store) RemoveIPFromWhiteList(ipAddr string) {
  159. s.sysdb.Delete("whitelist-ip", ipAddr)
  160. }
  161. func (s *Store) IsIPBlacklisted(ipAddr string) bool {
  162. var isBlacklisted bool = false
  163. s.sysdb.Read("blacklist-ip", ipAddr, &isBlacklisted)
  164. if isBlacklisted {
  165. return true
  166. }
  167. //Check for IP wildcard and CIRD rules
  168. AllBlacklistedIps := s.GetAllBlacklistedIp()
  169. for _, blacklistRule := range AllBlacklistedIps {
  170. wildcardMatch := MatchIpWildcard(ipAddr, blacklistRule)
  171. if wildcardMatch {
  172. return true
  173. }
  174. cidrMatch := MatchIpCIDR(ipAddr, blacklistRule)
  175. if cidrMatch {
  176. return true
  177. }
  178. }
  179. return false
  180. }
  181. func (s *Store) IsIPWhitelisted(ipAddr string) bool {
  182. var isBlacklisted bool = false
  183. s.sysdb.Read("whitelist-ip", ipAddr, &isBlacklisted)
  184. if isBlacklisted {
  185. return true
  186. }
  187. //Check for IP wildcard and CIRD rules
  188. AllBlacklistedIps := s.GetAllBlacklistedIp()
  189. for _, blacklistRule := range AllBlacklistedIps {
  190. wildcardMatch := MatchIpWildcard(ipAddr, blacklistRule)
  191. if wildcardMatch {
  192. return true
  193. }
  194. cidrMatch := MatchIpCIDR(ipAddr, blacklistRule)
  195. if cidrMatch {
  196. return true
  197. }
  198. }
  199. return false
  200. }
  201. func (s *Store) GetAllBlacklistedIp() []string {
  202. bannedIps := []string{}
  203. entries, err := s.sysdb.ListTable("blacklist-ip")
  204. if err != nil {
  205. return bannedIps
  206. }
  207. for _, keypairs := range entries {
  208. ip := string(keypairs[0])
  209. bannedIps = append(bannedIps, ip)
  210. }
  211. return bannedIps
  212. }
  213. func (s *Store) GetAllWhitelistedIp() []string {
  214. whitelistedIp := []string{}
  215. entries, err := s.sysdb.ListTable("whitelist-ip")
  216. if err != nil {
  217. return whitelistedIp
  218. }
  219. for _, keypairs := range entries {
  220. ip := string(keypairs[0])
  221. whitelistedIp = append(whitelistedIp, ip)
  222. }
  223. return whitelistedIp
  224. }
  225. /*
  226. Check if a IP address is blacklisted, in either country or IP blacklist
  227. IsBlacklisted default return is false (allow access)
  228. */
  229. func (s *Store) IsBlacklisted(ipAddr string) bool {
  230. if !s.BlacklistEnabled {
  231. //Blacklist not enabled. Always return false
  232. return false
  233. }
  234. if ipAddr == "" {
  235. //Unable to get the target IP address
  236. return false
  237. }
  238. countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
  239. if err != nil {
  240. return false
  241. }
  242. if s.IsCountryCodeBlacklisted(countryCode.CountryIsoCode) {
  243. return true
  244. }
  245. if s.IsIPBlacklisted(ipAddr) {
  246. return true
  247. }
  248. return false
  249. }
  250. /*
  251. IsWhitelisted check if a given IP address is in the current
  252. server's white list.
  253. Note that the Whitelist default result is true even
  254. when encountered error
  255. */
  256. func (s *Store) IsWhitelisted(ipAddr string) bool {
  257. if !s.WhitelistEnabled {
  258. //Whitelist not enabled. Always return true (allow access)
  259. return true
  260. }
  261. if ipAddr == "" {
  262. //Unable to get the target IP address, assume ok
  263. return true
  264. }
  265. countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
  266. if err != nil {
  267. return true
  268. }
  269. if s.IsCountryCodeWhitelisted(countryCode.CountryIsoCode) {
  270. return true
  271. }
  272. if s.IsIPWhitelisted(ipAddr) {
  273. return true
  274. }
  275. return false
  276. }
  277. func (s *Store) GetRequesterCountryISOCode(r *http.Request) string {
  278. ipAddr := GetRequesterIP(r)
  279. if ipAddr == "" {
  280. return ""
  281. }
  282. countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
  283. if err != nil {
  284. return ""
  285. }
  286. return countryCode.CountryIsoCode
  287. }