geoipchecker.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. package thoth
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "log/slog"
  7. "net/http"
  8. "strings"
  9. "time"
  10. "github.com/TecharoHQ/anubis/lib/policy/checker"
  11. iptoasnv1 "github.com/TecharoHQ/thoth-proto/gen/techaro/thoth/iptoasn/v1"
  12. )
  13. func (c *Client) GeoIPCheckerFor(countries []string) checker.Impl {
  14. countryMap := map[string]struct{}{}
  15. var sb strings.Builder
  16. fmt.Fprintln(&sb, "GeoIPChecker")
  17. for _, cc := range countries {
  18. countryMap[cc] = struct{}{}
  19. fmt.Fprintln(&sb, cc)
  20. }
  21. return &GeoIPChecker{
  22. IPToASN: c.IPToASN,
  23. Countries: countryMap,
  24. hash: sb.String(),
  25. }
  26. }
  27. type GeoIPChecker struct {
  28. IPToASN iptoasnv1.IpToASNServiceClient
  29. Countries map[string]struct{}
  30. hash string
  31. }
  32. func (gipc *GeoIPChecker) Check(r *http.Request) (bool, error) {
  33. ctx, cancel := context.WithTimeout(r.Context(), 500*time.Millisecond)
  34. defer cancel()
  35. ipInfo, err := gipc.IPToASN.Lookup(ctx, &iptoasnv1.LookupRequest{
  36. IpAddress: r.Header.Get("X-Real-Ip"),
  37. })
  38. if err != nil {
  39. switch {
  40. case errors.Is(err, context.DeadlineExceeded):
  41. slog.Debug("error contacting thoth", "err", err, "actionable", false)
  42. return false, nil
  43. default:
  44. slog.Error("error contacting thoth, please contact support", "err", err, "actionable", true)
  45. return false, nil
  46. }
  47. }
  48. // If IP is not publicly announced, return false
  49. if !ipInfo.GetAnnounced() {
  50. return false, nil
  51. }
  52. _, ok := gipc.Countries[strings.ToLower(ipInfo.GetCountryCode())]
  53. return ok, nil
  54. }
  55. func (gipc *GeoIPChecker) Hash() string {
  56. return gipc.hash
  57. }