Skip to content

Repository files navigation

ipfilter

A package for IP Filtering in Go (golang)

Go ReferenceTests

Install

go get github.com/jpillora/ipfilter

Requires Go 1.25 or newer.

Features

  • Simple
  • Thread-safe
  • IPv4 / IPv6 support
  • Subnet support
  • Location filtering (via embedded MaxMind GeoLite2-Country data)
  • Simple HTTP middleware

Usage

Country-block HTTP middleware

h:= http.Handler(...)
myProtectedHandler:=ipfilter.Wrap(h, ipfilter.Options{
//block requests from China and Russia by IPBlockedCountries: []string{"CN", "RU"},
})
http.ListenAndServe(":8080", myProtectedHandler)

Trusted reverse proxy middleware

Only accept forwarding headers when the direct peer belongs to your proxy network:

myProtectedHandler:=ipfilter.Wrap(h, ipfilter.Options{
BlockedCountries: []string{"CN", "RU"},
TrustProxyCIDR: "10.0.0.0/8",
})

TrustProxy: true remains supported with its legacy trust-all behavior; its compatibility CIDR defaults to 0.0.0.0/0 while still accepting IPv6 proxy peers. Prefer an explicit, narrow TrustProxyCIDR for new code. Invalid CIDRs panic during construction so a proxy configuration typo cannot silently weaken the filter.

Country-block stand-alone

f:=ipfilter.New(ipfilter.Options{
BlockedCountries: []string{"CN"},
})
f.Blocked("116.31.116.51") //=> true (CN)f.Allowed("216.58.199.67") //=> true (US)

Async allow LAN hosts middleware

f:=ipfilter.New(ipfilter.Options{
BlockByDefault: true,
})
gofunc() {
time.Sleep(15*time.Second)
//react to admin change....f.AllowIP("192.168.0.23")
}()
h:= http.Handler(...)
myProtectedHandler:= f.Wrap(h)
http.ListenAndServe(":8080", myProtectedHandler)

Allow your entire LAN only

f:=ipfilter.New(ipfilter.Options{
AllowedIPs: []string{"192.168.0.0/24"},
BlockByDefault: true,
})
//only allow 192.168.0.X IPsf.Allowed("192.168.0.42") //=> truef.Allowed("10.0.0.42") //=> false

... and with dynamic list updates

//and allow 10.X.X.Xf.AllowIP("10.0.0.0/8")
f.Allowed("10.0.0.42") //=> truef.Allowed("203.25.111.68") //=> false//and allow everyone in Australiaf.AllowCountry("AU")
f.Allowed("203.25.111.68") //=> true

Check with net.IP

f.NetAllowed(net.IP{203,25,111,68}) //=> true

Low-level single IP to country

f.IPToCountry("203.25.111.68") //=> "AU"f.NetIPToCountry(net.IP{203,25,111,68}) //=> "AU"

Advanced HTTP middleware

Make your own with:

func (m*myMiddleware) ServeHTTP(w http.ResponseWriter, r*http.Request) {
//use remote addr as it cant be spoofedip, _, _:=net.SplitHostPort(r.RemoteAddr)
//show simple forbidden textif!m.IPFilter.Allowed(ip) {
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}
//success!m.next.ServeHTTP(w, r)
}

Issues

  • Due to the nature of IP address allocation, determining location based of a single IP address is quite difficult (if you're not Google) and is therefore not very reliable. For this reason BlockByDefault is off by default.

Todo

  • Use a good algorithm to perform faster prefix matches
  • Investigate reliability of other detectable attributes
  • Add TOR/anonymizer filter options
  • Add great-circle distance filter options (e.g. Allow 500KM radius from code/lat,lon)

Credits

Change log

  • v1.0.0 Use MaxMindDB IP data
  • v1.1.0 Use IP2Location LITE IP data
  • v1.2.3 Upgrade iploc, requires Go 1.16
  • v1.3.0 Replace phuslu/iploc with embedded MaxMind GeoLite2-Country data
  • v1.4.0 Add embedded MaxMind GeoLite2-ASN lookups

About

A package for IP Filtering in Go (golang)

Resources

Stars

399 stars

Watchers

8 watching

Forks

Releases

Packages

Used by

Contributors

Languages