Skip to content

jpillora/ipfilter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

70 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ipfilter

A package for IP Filtering in Go (golang)

GoDoc Tests

Install

go get github.com/jpillora/ipfilter

Features

  • Simple
  • Thread-safe
  • IPv4 / IPv6 support
  • Subnet support
  • Location filtering (via phuslu/iploc)
  • Simple HTTP middleware

Usage

Country-block HTTP middleware

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

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,
})

go func() {
	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 IPs
f.Allowed("192.168.0.42") //=> true
f.Allowed("10.0.0.42") //=> false

... and with dynamic list updates

//and allow 10.X.X.X
f.AllowIP("10.0.0.0/8")
f.Allowed("10.0.0.42") //=> true
f.Allowed("203.25.111.68") //=> false
//and allow everyone in Australia
f.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 spoofed
	ip, _, _ := net.SplitHostPort(r.RemoteAddr)
	//show simple forbidden text
	if !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