geoip: read source IP from EDNS0 subnet if provided (#5183)

* geoip: read source IP from EDNS0 subnet if provided

This patch implements EDNS backend processing (similar in powerdns: https://doc.powerdns.com/authoritative/settings.html#setting-edns-subnet-processing). This feature comes very handy to test whether your geo config is working properly.

Signed-off-by: Balazs Nagy <julsevern@gmail.com>
This commit is contained in:
Balazs Nagy
2022-05-02 19:25:02 +02:00
committed by GitHub
parent 66f2ac7568
commit 4ae29a449c
5 changed files with 122 additions and 50 deletions

View File

@@ -20,8 +20,9 @@ var log = clog.NewWithPlugin(pluginName)
// GeoIP is a plugin that add geo location data to the request context by looking up a maxmind
// geoIP2 database, and which data can be later consumed by other middlewares.
type GeoIP struct {
Next plugin.Handler
db db
Next plugin.Handler
db db
edns0 bool
}
type db struct {
@@ -37,7 +38,7 @@ const (
var probingIP = net.ParseIP("127.0.0.1")
func newGeoIP(dbPath string) (*GeoIP, error) {
func newGeoIP(dbPath string, edns0 bool) (*GeoIP, error) {
reader, err := geoip2.Open(dbPath)
if err != nil {
return nil, fmt.Errorf("failed to open database file: %v", err)
@@ -66,7 +67,7 @@ func newGeoIP(dbPath string) (*GeoIP, error) {
return nil, fmt.Errorf("database does not provide city schema")
}
return &GeoIP{db: db}, nil
return &GeoIP{db: db, edns0: edns0}, nil
}
// ServeDNS implements the plugin.Handler interface.
@@ -79,6 +80,17 @@ func (g GeoIP) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
func (g GeoIP) Metadata(ctx context.Context, state request.Request) context.Context {
srcIP := net.ParseIP(state.IP())
if g.edns0 {
if o := state.Req.IsEdns0(); o != nil {
for _, s := range o.Option {
if e, ok := s.(*dns.EDNS0_SUBNET); ok {
srcIP = e.Address
break
}
}
}
}
switch {
case g.db.provides&city == city:
data, err := g.db.City(srcIP)