Help us shape the future of Go! Take the 2026 Go Developer Survey

geoip

package
v1.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 2, 2026 License: MIT Imports: 20 Imported by: 0

README

geoip

Resolves the IP address on an auth request into a country, city, coordinates and a set of connection flags.

On its own this plugin blocks nothing. It's the data layer the rest of the security plugins read from, so if you plan to run geofence, vpndetect or impossibletravel, you need this one registered first. Lookups go through a MaxMind GeoLite2 database on local disk and get cached, so the hot path stays cheap.

Use it when

  • You want the country and city recorded on every sign-in for your audit trail
  • You're enabling any of the location-aware security plugins, which all read the location this plugin attaches
  • You want to show users a readable "signed in from Lagos, Nigeria" in a session list

Skip it when

  • You don't ship a GeoLite2 database with your deployment. Without DatabasePath there is nothing to look up
  • Your traffic is entirely server-to-server on a private network, where the source IP tells you nothing about a person

Wiring

authsome.WithPlugin(geoip.New(geoip.Config{
    DatabasePath: "/var/lib/geoip/GeoLite2-City.mmdb",
    CacheTTL:     24 * time.Hour,
}))

Register it before the plugins that depend on it.

Config

Field Type Default What it does
DatabasePath string none Path to the MaxMind GeoLite2-City.mmdb file. Required
CacheTTL time.Duration 24h How long a resolved location stays cached

Settings

Tunable at runtime from the admin dashboard or the settings API.

Key Default
geoip.cache_ttl_hours 24

Lifecycle hooks

Hook What happens
BeforeSignUp Resolves the request IP and attaches the location to context
BeforeSignIn Same, so downstream plugins can read it before the decision is made
AfterSignIn Records the resolved location against the session
OnShutdown Closes the database handle

Downstream plugins pull the location off the context with geoip.WithGeoLocation.

geofence and vpndetect read this plugin's output directly. impossibletravel needs the coordinates it resolves. anomaly uses the country for its new-country signal.

Documentation

Overview

contract.go: Wires the geoip plugin into the forge-dashboard contract surface via plugin.ContractContributor.

Package geoip provides GeoIP location resolution for authentication events. It resolves IP addresses to geographic locations and stores the result in context for downstream plugins (geofence, impossible travel, etc.).

Index

Constants

This section is empty.

Variables

View Source
var (
	// SettingCacheTTLHours controls how long GeoIP lookup results are cached.
	SettingCacheTTLHours = settings.Define("geoip.cache_ttl_hours", 24,
		settings.WithDisplayName("Cache TTL (hours)"),
		settings.WithDescription("How long GeoIP lookup results are cached, in hours"),
		settings.WithCategory("GeoIP"),
		settings.WithScopes(settings.ScopeGlobal),
		settings.WithHelpText("How long GeoIP lookup results are cached, in hours"),
		settings.WithOrder(10),
	)
)

Functions

func Haversine

func Haversine(lat1, lon1, lat2, lon2 float64) float64

Haversine calculates the distance in kilometers between two geographic coordinates using the Haversine formula.

func WithGeoLocation

func WithGeoLocation(ctx context.Context, loc *GeoLocation) context.Context

WithGeoLocation stores a GeoLocation in the context.

Types

type Cache

type Cache struct {
	// contains filtered or unexported fields
}

Cache is a thread-safe TTL cache for GeoLocation lookups.

func NewCache

func NewCache(ttl time.Duration) *Cache

NewCache creates a new GeoIP cache with the given TTL.

func (*Cache) Get

func (c *Cache) Get(ip string) *GeoLocation

Get returns a cached GeoLocation or nil if not found/expired.

The returned value is a copy. Handing out the stored pointer would make this type thread-safe only for callers that never write: one caller mutating what it got back would corrupt the entry every other caller sees for the rest of the ttl, and that write races every concurrent Get, since it happens outside the lock. Plugin.Resolve returns this value straight through to anomaly, geofence, impossibletravel and vpndetect, so the pointer would be shared across plugins as well as goroutines.

func (*Cache) Set

func (c *Cache) Set(ip string, loc *GeoLocation)

Set stores a GeoLocation in the cache. The value is copied on the way in for the mirror-image reason Get copies on the way out: otherwise a caller that mutates loc after Set returns rewrites the cached entry behind the lock's back.

type Config

type Config struct {
	// DatabasePath is the path to the MaxMind GeoLite2-City.mmdb file.
	DatabasePath string

	// CacheTTL is how long GeoIP results are cached (default: 24h).
	CacheTTL time.Duration
}

Config configures the GeoIP plugin.

type GeoLocation

type GeoLocation struct {
	IP          string  `json:"ip"`
	Country     string  `json:"country"`      // ISO 3166-1 alpha-2
	CountryName string  `json:"country_name"` // human-readable
	Region      string  `json:"region,omitempty"`
	City        string  `json:"city,omitempty"`
	Timezone    string  `json:"timezone,omitempty"`
	ISP         string  `json:"isp,omitempty"`
	Latitude    float64 `json:"latitude"`
	Longitude   float64 `json:"longitude"`
	ASN         int     `json:"asn,omitempty"`
	IsProxy     bool    `json:"is_proxy,omitempty"`
	IsVPN       bool    `json:"is_vpn,omitempty"`
	IsTor       bool    `json:"is_tor,omitempty"`
}

GeoLocation represents the geographic location resolved from an IP address.

func GeoLocationFrom

func GeoLocationFrom(ctx context.Context) *GeoLocation

GeoLocationFrom extracts the GeoLocation from context. Returns nil if not present (e.g. geoip plugin not loaded).

type MaxMindProvider

type MaxMindProvider struct {
	// contains filtered or unexported fields
}

MaxMindProvider resolves IPs using a MaxMind GeoLite2 MMDB file.

func NewMaxMindProvider

func NewMaxMindProvider(dbPath string) (*MaxMindProvider, error)

NewMaxMindProvider opens a MaxMind MMDB file.

func (*MaxMindProvider) Close

func (p *MaxMindProvider) Close() error

Close closes the MMDB reader.

func (*MaxMindProvider) Lookup

func (p *MaxMindProvider) Lookup(ip net.IP) (*GeoLocation, error)

Lookup resolves an IP address to a GeoLocation.

type Plugin

type Plugin struct {
	// contains filtered or unexported fields
}

Plugin is the GeoIP location resolution plugin. It resolves IP addresses to geographic locations and stores results in context for downstream geo-security plugins.

func New

func New(cfg ...Config) *Plugin

New creates a new GeoIP plugin.

func NewTestPlugin

func NewTestPlugin(mapping map[string]*GeoLocation) *Plugin

NewTestPlugin creates a fully configured Plugin with a test provider and cache. This is intended for use in tests across geo-security plugin packages that depend on a working geoip.Plugin without a real MaxMind database.

func (*Plugin) DeclareSettings

func (p *Plugin) DeclareSettings(m *settings.Manager) error

DeclareSettings implements plugin.SettingsProvider. It registers all geoip-related configurable settings.

func (*Plugin) Name

func (p *Plugin) Name() string

Name returns the plugin name.

func (*Plugin) OnAfterSignIn

func (p *Plugin) OnAfterSignIn(ctx context.Context, u *user.User, s *session.Session) error

OnAfterSignIn enriches audit/relay events with geo metadata.

func (*Plugin) OnBeforeSignIn

func (p *Plugin) OnBeforeSignIn(_ context.Context, req *account.SignInRequest) error

OnBeforeSignIn resolves geo for the sign-in request and stores it in context.

func (*Plugin) OnBeforeSignUp

func (p *Plugin) OnBeforeSignUp(_ context.Context, req *account.SignUpRequest) error

OnBeforeSignUp resolves geo for the sign-up request.

func (*Plugin) OnInit

func (p *Plugin) OnInit(_ context.Context, engine plugin.Engine) error

OnInit opens the MaxMind database and discovers engine dependencies.

func (*Plugin) OnShutdown

func (p *Plugin) OnShutdown(_ context.Context) error

OnShutdown closes the GeoIP provider.

func (*Plugin) RegisterContract

func (p *Plugin) RegisterContract(
	d *dispatcher.Dispatcher,
	reg contract.Registry,
	wreg contract.WardenRegistry,
	engine plugin.Engine,
) error

func (*Plugin) Resolve

func (p *Plugin) Resolve(ipStr string) *GeoLocation

Resolve looks up the geographic location for an IP string. Results are cached. Returns nil for private/loopback IPs or if no provider is configured.

type Provider

type Provider interface {
	Lookup(ip net.IP) (*GeoLocation, error)
	Close() error
}

Provider resolves an IP address to a GeoLocation.

type TestProvider

type TestProvider struct {
	Mapping map[string]*GeoLocation
}

TestProvider is a mock GeoIP provider for use in tests. It maps IP string representations to pre-configured GeoLocation values.

func NewTestProvider

func NewTestProvider(m map[string]*GeoLocation) *TestProvider

NewTestProvider creates a TestProvider with the given IP-to-GeoLocation mapping.

func (*TestProvider) Close

func (tp *TestProvider) Close() error

Close is a no-op for the test provider.

func (*TestProvider) Lookup

func (tp *TestProvider) Lookup(ip net.IP) (*GeoLocation, error)

Lookup returns the pre-configured GeoLocation for the given IP.

Directories

Path Synopsis
Package contract wires the geoip plugin's deep-link settings page into the forge-dashboard contract registry.
Package contract wires the geoip plugin's deep-link settings page into the forge-dashboard contract registry.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL