geoip.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. package geoip
  2. import (
  3. "fmt"
  4. "net"
  5. gg "github.com/oschwald/geoip2-golang"
  6. )
  7. // Anonymous contains information about whether an IP address is anonymous
  8. type Anonymous struct {
  9. // from geoip2-golang.AnonymousIP
  10. IsAnonymous bool `json:"is_anonymous"`
  11. IsAnonymousVPN bool `json:"is_anonymous_vpn"`
  12. IsHostingProvider bool `json:"is_hosting_provider"`
  13. IsPublicProxy bool `json:"is_public_proxy"`
  14. IsTorExitNode bool `json:"is_tor_exit_node"`
  15. }
  16. // City contains geographic data on a city level for a given IP address
  17. type City struct {
  18. Name string `json:"name"`
  19. Continent string `json:"continent"`
  20. ContinentCode string `json:"continent_code"`
  21. Country string `json:"country"`
  22. CountryCode string `json:"country_code"`
  23. AccuracyRadius uint16 `json:"accuracy_radius"`
  24. Latitude float64 `json:"latitude"`
  25. Longitude float64 `json:"longitude"`
  26. MetroCode uint `json:"metro_code"`
  27. Timezone string `json:"timezone"`
  28. Postcode string `json:"postcode"`
  29. RegisteredCountry string `json:"registered_country"`
  30. RegisteredCountryCode string `json:"registered_country_code"`
  31. RepresentedCountry string `json:"represented_country"`
  32. RepresentedCountryCode string `json:"represented_country_code"`
  33. RepresentedCountryType string `json:"represented_country_type"`
  34. Subdivisions []string `json:"subdivisions"`
  35. IsAnonymousProxy bool `json:"is_anonymous_proxy"`
  36. IsSatelliteProvider bool `json:"is_satellite_provider"`
  37. }
  38. // ConnectionType denotes the connection type for a given IP address
  39. type ConnectionType struct {
  40. Type string `json:"connection_type"`
  41. }
  42. // Country contains geographic data on a country level for a given IP address
  43. type Country struct {
  44. ContinentCode string `json:"continent_code"`
  45. Continent string `json:"continent"`
  46. CountryCode string `json:"country_code"`
  47. Country string `json:"country"`
  48. RegisteredCountryCode string `json:"registered_country_code"`
  49. RegisteredCountry string `json:"registered_country"`
  50. RepresentedCountryCode string `json:"represented_country_code"`
  51. RepresentedCountryType string `json:"represented_country_type"`
  52. RepresentedCountry string `json:"represented_country"`
  53. IsAnonymousProxy bool `json:"is_anonymous_proxy"`
  54. IsSatelliteProvider bool `json:"is_satellite_provider"`
  55. }
  56. // Domain denotes the domain for a given IP address
  57. type Domain struct {
  58. Domain string `json:"domain"`
  59. }
  60. // ISP contains information about the autonomous system for the given IP address
  61. type ISP struct {
  62. AutonomousSystemNumber uint `json:"autonomous_system_number"`
  63. AutonomousSystemOrganization string `json:"autonomous_system_organization"`
  64. ISP string `json:"isp"`
  65. Organization string `json:"organization"`
  66. }
  67. // GeoIP contains metadata for an IP address from the Maxmind GeoIP databases
  68. type GeoIP struct {
  69. db *gg.Reader
  70. IP net.IP `json:"ip" bson:"ip"`
  71. Anonymous Anonymous `json:"anonymous" bson:"anon"`
  72. City City `json:"city" bson:"city"`
  73. Country Country `json:"country" bson:"country"`
  74. Domain Domain `json:"domain" bson:"domain"`
  75. ISP ISP `json:"isp" bson:"isp"`
  76. }
  77. // NewGeoIP creates a new GeoIP data structure
  78. func NewGeoIP(dbpath string) (*GeoIP, error) {
  79. ggReader, err := gg.Open(dbpath)
  80. if err != nil {
  81. return nil, err
  82. }
  83. g := GeoIP{
  84. db: ggReader,
  85. }
  86. return &g, nil
  87. }
  88. // Close closes the GeoIP database
  89. func (g *GeoIP) Close() {
  90. g.db.Close()
  91. }
  92. // Lookup performs a geo ip lookup for ipAddr in the maxmind geoip database
  93. func (g *GeoIP) Lookup(ipAddr string) error {
  94. g.IP = net.ParseIP(ipAddr)
  95. if g.IP == nil {
  96. return fmt.Errorf("%s is not a valid IP address!", ipAddr)
  97. }
  98. // ANONYMOUS IP
  99. //
  100. anon, err := g.db.AnonymousIP(g.IP)
  101. if err == nil {
  102. g.Anonymous = Anonymous{
  103. IsAnonymous: anon.IsAnonymous,
  104. IsAnonymousVPN: anon.IsAnonymousVPN,
  105. IsHostingProvider: anon.IsHostingProvider,
  106. IsPublicProxy: anon.IsPublicProxy,
  107. IsTorExitNode: anon.IsTorExitNode,
  108. }
  109. }
  110. // CITY
  111. //
  112. city, err := g.db.City(g.IP)
  113. if err == nil {
  114. subdivisions := make([]string, len(city.Subdivisions), len(city.Subdivisions))
  115. for i, sd := range city.Subdivisions {
  116. subdivisions[i] = sd.Names["en"]
  117. }
  118. g.City = City{
  119. AccuracyRadius: city.Location.AccuracyRadius,
  120. Continent: city.Continent.Names["en"],
  121. ContinentCode: city.Continent.Code,
  122. Country: city.Country.Names["en"],
  123. CountryCode: city.Country.IsoCode,
  124. IsAnonymousProxy: city.Traits.IsAnonymousProxy,
  125. IsSatelliteProvider: city.Traits.IsSatelliteProvider,
  126. Latitude: city.Location.Latitude,
  127. Longitude: city.Location.Longitude,
  128. MetroCode: city.Location.MetroCode,
  129. Name: city.City.Names["en"],
  130. Postcode: city.Postal.Code,
  131. RegisteredCountry: city.RegisteredCountry.Names["en"],
  132. RegisteredCountryCode: city.RegisteredCountry.IsoCode,
  133. RepresentedCountry: city.RepresentedCountry.Names["en"],
  134. RepresentedCountryCode: city.RepresentedCountry.IsoCode,
  135. RepresentedCountryType: city.RepresentedCountry.Type,
  136. Subdivisions: subdivisions,
  137. Timezone: city.Location.TimeZone,
  138. }
  139. }
  140. // COUNTRY
  141. //
  142. country, err := g.db.Country(g.IP)
  143. if err == nil {
  144. g.Country = Country{
  145. Continent: country.Continent.Names["en"],
  146. ContinentCode: country.Continent.Code,
  147. Country: country.Country.Names["en"],
  148. CountryCode: country.Country.IsoCode,
  149. IsAnonymousProxy: country.Traits.IsAnonymousProxy,
  150. IsSatelliteProvider: country.Traits.IsSatelliteProvider,
  151. RegisteredCountry: country.RegisteredCountry.Names["en"],
  152. RegisteredCountryCode: country.RegisteredCountry.IsoCode,
  153. RepresentedCountry: country.RepresentedCountry.Names["en"],
  154. RepresentedCountryCode: country.RepresentedCountry.IsoCode,
  155. RepresentedCountryType: country.RepresentedCountry.Type,
  156. }
  157. }
  158. /*
  159. // DOMAIN
  160. //
  161. domain, err := g.db.Domain(g.IP)
  162. if err == nil {
  163. g.Domain = &Domain{
  164. Domain: domain.Domain,
  165. }
  166. } else {
  167. g.Domain = nil
  168. }
  169. // ISP
  170. //
  171. isp, err := g.db.ISP(g.IP)
  172. if err == nil {
  173. g.ISP = &ISP{
  174. AutonomousSystemNumber: isp.AutonomousSystemNumber,
  175. AutonomousSystemOrganization: isp.AutonomousSystemOrganization,
  176. ISP: isp.ISP,
  177. Organization: isp.Organization,
  178. }
  179. } else {
  180. g.ISP = nil
  181. }
  182. */
  183. return nil
  184. }