1
0

geodb.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. package geodb
  2. import (
  3. "log"
  4. "net"
  5. "net/http"
  6. "strings"
  7. "imuslab.com/zoraxy/mod/database"
  8. )
  9. type Store struct {
  10. Enabled bool
  11. sysdb *database.Database
  12. }
  13. type CountryInfo struct {
  14. CountryIsoCode string
  15. ContinetCode string
  16. }
  17. func NewGeoDb(sysdb *database.Database) (*Store, error) {
  18. var err error
  19. blacklistEnabled := false
  20. if sysdb != nil {
  21. err = sysdb.NewTable("blacklist-cn")
  22. if err != nil {
  23. return nil, err
  24. }
  25. err = sysdb.NewTable("blacklist-ip")
  26. if err != nil {
  27. return nil, err
  28. }
  29. err = sysdb.NewTable("blacklist")
  30. if err != nil {
  31. return nil, err
  32. }
  33. sysdb.Read("blacklist", "enabled", &blacklistEnabled)
  34. } else {
  35. log.Println("Database pointer set to nil: Entering debug mode")
  36. }
  37. return &Store{
  38. Enabled: blacklistEnabled,
  39. sysdb: sysdb,
  40. }, nil
  41. }
  42. func (s *Store) ToggleBlacklist(enabled bool) {
  43. s.sysdb.Write("blacklist", "enabled", enabled)
  44. s.Enabled = enabled
  45. }
  46. func (s *Store) ResolveCountryCodeFromIP(ipstring string) (*CountryInfo, error) {
  47. cc := search(ipstring)
  48. return &CountryInfo{
  49. CountryIsoCode: cc,
  50. ContinetCode: "",
  51. }, nil
  52. }
  53. func (s *Store) Close() {
  54. }
  55. func (s *Store) AddCountryCodeToBlackList(countryCode string) {
  56. countryCode = strings.ToLower(countryCode)
  57. s.sysdb.Write("blacklist-cn", countryCode, true)
  58. }
  59. func (s *Store) RemoveCountryCodeFromBlackList(countryCode string) {
  60. countryCode = strings.ToLower(countryCode)
  61. s.sysdb.Delete("blacklist-cn", countryCode)
  62. }
  63. func (s *Store) IsCountryCodeBlacklisted(countryCode string) bool {
  64. countryCode = strings.ToLower(countryCode)
  65. var isBlacklisted bool = false
  66. s.sysdb.Read("blacklist-cn", countryCode, &isBlacklisted)
  67. return isBlacklisted
  68. }
  69. func (s *Store) GetAllBlacklistedCountryCode() []string {
  70. bannedCountryCodes := []string{}
  71. entries, err := s.sysdb.ListTable("blacklist-cn")
  72. if err != nil {
  73. return bannedCountryCodes
  74. }
  75. for _, keypairs := range entries {
  76. ip := string(keypairs[0])
  77. bannedCountryCodes = append(bannedCountryCodes, ip)
  78. }
  79. return bannedCountryCodes
  80. }
  81. func (s *Store) AddIPToBlackList(ipAddr string) {
  82. s.sysdb.Write("blacklist-ip", ipAddr, true)
  83. }
  84. func (s *Store) RemoveIPFromBlackList(ipAddr string) {
  85. s.sysdb.Delete("blacklist-ip", ipAddr)
  86. }
  87. func (s *Store) IsIPBlacklisted(ipAddr string) bool {
  88. var isBlacklisted bool = false
  89. s.sysdb.Read("blacklist-ip", ipAddr, &isBlacklisted)
  90. if isBlacklisted {
  91. return true
  92. }
  93. //Check for IP wildcard and CIRD rules
  94. AllBlacklistedIps := s.GetAllBlacklistedIp()
  95. for _, blacklistRule := range AllBlacklistedIps {
  96. wildcardMatch := MatchIpWildcard(ipAddr, blacklistRule)
  97. if wildcardMatch {
  98. return true
  99. }
  100. cidrMatch := MatchIpCIDR(ipAddr, blacklistRule)
  101. if cidrMatch {
  102. return true
  103. }
  104. }
  105. return false
  106. }
  107. func (s *Store) GetAllBlacklistedIp() []string {
  108. bannedIps := []string{}
  109. entries, err := s.sysdb.ListTable("blacklist-ip")
  110. if err != nil {
  111. return bannedIps
  112. }
  113. for _, keypairs := range entries {
  114. ip := string(keypairs[0])
  115. bannedIps = append(bannedIps, ip)
  116. }
  117. return bannedIps
  118. }
  119. // Check if a IP address is blacklisted, in either country or IP blacklist
  120. func (s *Store) IsBlacklisted(ipAddr string) bool {
  121. if !s.Enabled {
  122. //Blacklist not enabled. Always return false
  123. return false
  124. }
  125. if ipAddr == "" {
  126. //Unable to get the target IP address
  127. return false
  128. }
  129. countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
  130. if err != nil {
  131. return false
  132. }
  133. if s.IsCountryCodeBlacklisted(countryCode.CountryIsoCode) {
  134. return true
  135. }
  136. if s.IsIPBlacklisted(ipAddr) {
  137. return true
  138. }
  139. return false
  140. }
  141. func (s *Store) GetRequesterCountryISOCode(r *http.Request) string {
  142. ipAddr := GetRequesterIP(r)
  143. if ipAddr == "" {
  144. return ""
  145. }
  146. countryCode, err := s.ResolveCountryCodeFromIP(ipAddr)
  147. if err != nil {
  148. return ""
  149. }
  150. return countryCode.CountryIsoCode
  151. }
  152. // Utilities function
  153. func GetRequesterIP(r *http.Request) string {
  154. ip := r.Header.Get("X-Forwarded-For")
  155. if ip == "" {
  156. ip = r.Header.Get("X-Real-IP")
  157. if ip == "" {
  158. ip = strings.Split(r.RemoteAddr, ":")[0]
  159. }
  160. }
  161. return ip
  162. }
  163. // Match the IP address with a wildcard string
  164. func MatchIpWildcard(ipAddress, wildcard string) bool {
  165. // Split IP address and wildcard into octets
  166. ipOctets := strings.Split(ipAddress, ".")
  167. wildcardOctets := strings.Split(wildcard, ".")
  168. // Check that both have 4 octets
  169. if len(ipOctets) != 4 || len(wildcardOctets) != 4 {
  170. return false
  171. }
  172. // Check each octet to see if it matches the wildcard or is an exact match
  173. for i := 0; i < 4; i++ {
  174. if wildcardOctets[i] == "*" {
  175. continue
  176. }
  177. if ipOctets[i] != wildcardOctets[i] {
  178. return false
  179. }
  180. }
  181. return true
  182. }
  183. // Match ip address with CIDR
  184. func MatchIpCIDR(ip string, cidr string) bool {
  185. // parse the CIDR string
  186. _, cidrnet, err := net.ParseCIDR(cidr)
  187. if err != nil {
  188. return false
  189. }
  190. // parse the IP address
  191. ipAddr := net.ParseIP(ip)
  192. // check if the IP address is within the CIDR range
  193. return cidrnet.Contains(ipAddr)
  194. }