Skip to content

Commit

Permalink
add mmdb support for rest ip match
Browse files Browse the repository at this point in the history
  • Loading branch information
alecthw committed Mar 17, 2023
1 parent ac99eb1 commit 088bf91
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 0 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ require (
github.com/mdlayher/netlink v1.7.1 // indirect
github.com/mdlayher/socket v0.4.0 // indirect
github.com/onsi/ginkgo/v2 v2.9.1 // indirect
github.com/oschwald/geoip2-golang v1.8.0 // indirect
github.com/oschwald/maxminddb-golang v1.10.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/onsi/ginkgo/v2 v2.9.1 h1:zie5Ly042PD3bsCvsSOPvRnFwyo3rKe64TJlD6nu0mk=
github.com/onsi/ginkgo/v2 v2.9.1/go.mod h1:FEcmzVcCHl+4o9bQZVab+4dC9+j+91t2FHSzmGAPfuo=
github.com/onsi/gomega v1.27.3 h1:5VwIwnBY3vbBDOJrNtA4rVdiTZCsq9B5F12pvy1Drmk=
github.com/oschwald/geoip2-golang v1.8.0 h1:KfjYB8ojCEn/QLqsDU0AzrJ3R5Qa9vFlx3z6SLNcKTs=
github.com/oschwald/geoip2-golang v1.8.0/go.mod h1:R7bRvYjOeaoenAp9sKRS8GX5bJWcZ0laWO5+DauEktw=
github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg=
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down
5 changes: 5 additions & 0 deletions plugin/data_provider/iface.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package data_provider
import (
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/domain"
"github.com/IrineSistiana/mosdns/v5/pkg/matcher/netlist"
"github.com/oschwald/geoip2-golang"
)

type DomainMatcherProvider interface {
Expand All @@ -31,3 +32,7 @@ type DomainMatcherProvider interface {
type IPMatcherProvider interface {
GetIPMatcher() netlist.Matcher
}

type MmdbMatcherProvider interface {
GetMmdbMatcher() *geoip2.Reader
}
42 changes: 42 additions & 0 deletions plugin/data_provider/mmdb/mmdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package mmdb

import (
"github.com/IrineSistiana/mosdns/v5/coremain"
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
"github.com/oschwald/geoip2-golang"
)

const PluginType = "mmdb"

func init() {
coremain.RegNewPluginFunc(PluginType, Init, func() any { return new(Args) })
}

func Init(bp *coremain.BP, args any) (any, error) {
return NewMmdb(bp, args.(*Args))
}

type Args struct {
File string `yaml:"file"`
}

var _ data_provider.MmdbMatcherProvider = (*Mmdb)(nil)

type Mmdb struct {
mmdb *geoip2.Reader
}

func (m *Mmdb) GetMmdbMatcher() *geoip2.Reader {
return m.mmdb
}

func NewMmdb(bp *coremain.BP, args *Args) (*Mmdb, error) {
m := &Mmdb{}

db, err := geoip2.Open(args.File)
if err == nil {
m.mmdb = db
}

return m, nil
}
2 changes: 2 additions & 0 deletions plugin/enabled_plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ package plugin
import (
_ "github.com/IrineSistiana/mosdns/v5/plugin/data_provider/domain_set"
_ "github.com/IrineSistiana/mosdns/v5/plugin/data_provider/ip_set"
_ "github.com/IrineSistiana/mosdns/v5/plugin/data_provider/mmdb"
)

// matches
Expand All @@ -39,6 +40,7 @@ import (
_ "github.com/IrineSistiana/mosdns/v5/plugin/matcher/random"
_ "github.com/IrineSistiana/mosdns/v5/plugin/matcher/rcode"
_ "github.com/IrineSistiana/mosdns/v5/plugin/matcher/resp_ip"
_ "github.com/IrineSistiana/mosdns/v5/plugin/matcher/resp_ip_mmdb"
)

// executables
Expand Down
108 changes: 108 additions & 0 deletions plugin/matcher/resp_ip_mmdb/resp_ip_mmdb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (C) 2020-2022, IrineSistiana
*
* This file is part of mosdns.
*
* mosdns is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* mosdns is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package resp_ip_mmdb

import (
"context"
"errors"
"fmt"
"net"
"strings"

"github.com/IrineSistiana/mosdns/v5/pkg/query_context"
"github.com/IrineSistiana/mosdns/v5/plugin/data_provider"
"github.com/IrineSistiana/mosdns/v5/plugin/executable/sequence"
"github.com/miekg/dns"
"github.com/oschwald/geoip2-golang"
)

const PluginType = "resp_ip_mmdb"

func init() {
sequence.MustRegMatchQuickSetup(PluginType, QuickSetup)
}

func QuickSetup(bq sequence.BQ, s string) (sequence.Matcher, error) {
if len(s) == 0 {
return nil, errors.New("a iso code probability is required")
}

args := strings.Fields(s)
if len(args) != 2 {
return nil, errors.New("probability error, must like: resp_ip_mmdb $plugin_name CN")
}

mmdbName, _ := cutPrefix(args[0], "$")

p := bq.M().GetPlugin(mmdbName)
provider, _ := p.(data_provider.MmdbMatcherProvider)
if provider == nil {
return nil, fmt.Errorf("cannot find mmdb %s", mmdbName)
}
m := provider.GetMmdbMatcher()

return &Matcher{args[1], m}, nil
}

type Matcher struct {
isoCode string
mmdb *geoip2.Reader
}

func (m *Matcher) Match(_ context.Context, qCtx *query_context.Context) (bool, error) {
r := qCtx.R()
if r == nil {
return false, nil
}

if m.mmdb == nil {
return false, nil
}

for _, rr := range r.Answer {
var ip net.IP
switch rr := rr.(type) {
case *dns.A:
ip = rr.A
case *dns.AAAA:
ip = rr.AAAA
default:
continue
}

record, err := m.mmdb.Country(ip)
if err != nil {
continue
}

if record.Country.IsoCode == m.isoCode {
return true, nil
}
}

return false, nil
}

func cutPrefix(s string, p string) (string, bool) {
if strings.HasPrefix(s, p) {
return strings.TrimPrefix(s, p), true
}
return s, false
}

0 comments on commit 088bf91

Please sign in to comment.