Skip to content

Commit

Permalink
feat(resolver): add resolvers for IPv4
Browse files Browse the repository at this point in the history
  • Loading branch information
Damien Abos committed Jan 7, 2023
1 parent ae67e0f commit 1331916
Show file tree
Hide file tree
Showing 14 changed files with 553 additions and 69 deletions.
3 changes: 1 addition & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ powerdns-remote-backend-darwin-arm64:
powerdns-remote-backend-windows-arm64.exe:
env GOOS=windows GOARCH=arm64 go build -o powerdns-remote-backend-windows-arm64.exe

test:
govet-report.json test-report.json coverage.out
test: govet-report.json test-report.json coverage.out

lint:
go help lint
Expand Down
8 changes: 6 additions & 2 deletions dabdns.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
delegates:
- domain: dev.dabdns.com.
lookup:
resolvers:
- builtin:ipv4dotted
- builtin:ipv4dashed
- builtin:ipv4hexa
- builtin:ipv4b32crockford
soa:
default:
mname: ns1.dabdns.com.
Expand All @@ -9,12 +14,11 @@ delegates:
entries:
ns1.dabdns.com.: 82.66.188.8
test.dev.dabdns.com. : 192.168.0.1
0000000.dev.dabdns.com. : 127.0.0.1
aaaa:
default: ::1
entries:
ns1.dabdns.com.: 2a01:e0a:250:6220::1
ns:
default: ~
entries:
dev.dabdns.com.: ns1.dabdns.com.
getAllDomainMetadata:
Expand Down
31 changes: 27 additions & 4 deletions pkg/backend/base_delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,36 @@ const (
)

type DelegateBase struct {
Conf config.DelegateConfig
Conf *config.DelegateConfig
resolvers []Resolver
}

func NewDelagateBase(conf config.DelegateConfig) *DelegateBase {
return &DelegateBase{
Conf: conf,
func NewDelagateBase(conf *config.DelegateConfig) (delegate *DelegateBase, err error) {
resolvers := []Resolver{}
if conf.Lookup.Resolvers != nil {
for _, resolverUri := range *conf.Lookup.Resolvers {
var resolver Resolver
var settings map[string]interface{}
settings, err = conf.AsMap()
if err == nil {
resolver, err = NewResolver(resolverUri, settings)
if err == nil {
resolvers = append(resolvers, resolver)
} else {
break
}
} else {
break
}
}
}
if err == nil {
delegate = &DelegateBase{
Conf: conf,
resolvers: resolvers,
}
}
return
}

func (*DelegateBase) Initialize() bool {
Expand Down
69 changes: 69 additions & 0 deletions pkg/backend/ipv4b32_builtin_resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package backend

import (
"fmt"
"net"
"regexp"
"strconv"
"strings"
)

const IPV4B32_BUILTIN_RESOLVER_NAME = "builtin:ipv4b32"

type IPv4B32Resolver struct {
settings map[string]interface{}
regexp *regexp.Regexp
ttl uint32
}

func NewIPv4B32Resolver(settings map[string]interface{}) *IPv4B32Resolver {
var domain, pattern string
var ttl uint32
domain, _ = settings["domain"].(string)
ttl, _ = settings["ttl"].(uint32)
pattern = fmt.Sprintf("([0-9a-wA-W]{5,7})\\.%s$", strings.ReplaceAll(domain, ".", "\\."))
re, _ := regexp.Compile(pattern)
return &IPv4B32Resolver{
settings: settings,
regexp: re,
ttl: ttl,
}
}

func (resolver *IPv4B32Resolver) Lookup(qtype string, qname string, _ string) (lookupResultArray []LookupResult, err error) {
lookupResultArray = []LookupResult{}
if qtype == A || qtype == AAAA || qtype == ANY {
a := resolver.regexp.FindStringSubmatch(qname)
if len(a) > 1 {
ipValue, convErr := strconv.ParseInt(a[1], 32, 33)
if convErr == nil {
var a, b, c, d byte
a = byte(ipValue & 0xFF000000 >> 24)
b = byte(ipValue & 0x00FF0000 >> 16)
c = byte(ipValue & 0x0000FF00 >> 8)
d = byte(ipValue & 0x000000FF)
ip := net.IPv4(a, b, c, d)
if ip != nil {
var lookupResult LookupResult
if qtype == A || qtype == ANY {
lookupResult = LookupResult{
QType: A,
QName: qname,
Content: ip.String(),
TTL: uint32(60),
}
} else {
lookupResult = LookupResult{
QType: AAAA,
QName: qname,
Content: fmt.Sprintf("::ffff:%s", ip.String()),
TTL: uint32(60),
}
}
lookupResultArray = append(lookupResultArray, lookupResult)
}
}
}
}
return
}
83 changes: 83 additions & 0 deletions pkg/backend/ipv4b32crockford_builtin_resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package backend

import (
"encoding/base32"
"fmt"
"net"
"regexp"
"strings"
)

// Base32 alphabets
const (
IPV4B32CROCKFORD_BUILTIN_RESOLVER_NAME string = "builtin:ipv4b32crockford"
lowercaseAlphabet string = "0123456789abcdefghjkmnpqrstvwxyz"
)

// Base32 encodings
var (
lowerEncoding = base32.NewEncoding(lowercaseAlphabet).WithPadding(base32.NoPadding)
)

type IPv4B32CrockfordResolver struct {
settings map[string]interface{}
regexp *regexp.Regexp
ttl uint32
}

func NewIPv4B32CrockfordResolver(settings map[string]interface{}) *IPv4B32CrockfordResolver {
var domain, pattern string
var ttl uint32
domain, _ = settings["domain"].(string)
ttl, _ = settings["ttl"].(uint32)
pattern = fmt.Sprintf("([0123456789abcdefghjkmnpqrstvwxyzABCDEFGHJKMNPQRSTVWXYZ]{5,7})\\.%s$", strings.ReplaceAll(domain, ".", "\\."))
re, _ := regexp.Compile(pattern)
return &IPv4B32CrockfordResolver{
settings: settings,
regexp: re,
ttl: ttl,
}
}

func (resolver *IPv4B32CrockfordResolver) Lookup(qtype string, qname string, _ string) (lookupResultArray []LookupResult, err error) {
lookupResultArray = []LookupResult{}
if qtype == A || qtype == AAAA || qtype == ANY {
a := resolver.regexp.FindStringSubmatch(qname)
if len(a) > 1 {
lower := strings.ToLower(a[1])
if len(lower) == 6 {
// add padding
lower = fmt.Sprintf("0%s", lower)
}
ipValue, convErr := lowerEncoding.DecodeString(lower)
if convErr == nil && len(ipValue) == 4 {
var a, b, c, d byte
a = ipValue[0]
b = ipValue[1]
c = ipValue[2]
d = ipValue[3]
ip := net.IPv4(a, b, c, d)
if ip != nil {
var lookupResult LookupResult
if qtype == A || qtype == ANY {
lookupResult = LookupResult{
QType: A,
QName: qname,
Content: ip.String(),
TTL: uint32(60),
}
} else {
lookupResult = LookupResult{
QType: AAAA,
QName: qname,
Content: fmt.Sprintf("::ffff:%s", ip.String()),
TTL: uint32(60),
}
}
lookupResultArray = append(lookupResultArray, lookupResult)
}
}
}
}
return
}
60 changes: 60 additions & 0 deletions pkg/backend/ipv4dashed_builtin_resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package backend

import (
"fmt"
"net"
"regexp"
"strings"
)

const IPV4DASHED_BUILTIN_RESOLVER_NAME = "builtin:ipv4dashed"

type IPv4DashedResolver struct {
settings map[string]interface{}
regexp *regexp.Regexp
ttl uint32
}

func NewIPv4DashedResolver(settings map[string]interface{}) *IPv4DashedResolver {
var domain, pattern string
var ttl uint32
domain, _ = settings["domain"].(string)
ttl, _ = settings["ttl"].(uint32)
pattern = fmt.Sprintf("(([0-9]{1,3}-){3}([0-9]{1,3}))\\.%s$", strings.ReplaceAll(domain, ".", "\\."))
re, _ := regexp.Compile(pattern)
return &IPv4DashedResolver{
settings: settings,
regexp: re,
ttl: ttl,
}
}

func (resolver *IPv4DashedResolver) Lookup(qtype string, qname string, _ string) (lookupResultArray []LookupResult, err error) {
lookupResultArray = []LookupResult{}
if qtype == A || qtype == AAAA || qtype == ANY {
a := resolver.regexp.FindStringSubmatch(qname)
if len(a) > 1 {
ip := net.ParseIP(strings.ReplaceAll(a[1], "-", "."))
if ip != nil {
var lookupResult LookupResult
if qtype == A || qtype == ANY {
lookupResult = LookupResult{
QType: A,
QName: qname,
Content: ip.String(),
TTL: uint32(60),
}
} else {
lookupResult = LookupResult{
QType: AAAA,
QName: qname,
Content: fmt.Sprintf("::ffff:%s", ip.String()),
TTL: uint32(60),
}
}
lookupResultArray = append(lookupResultArray, lookupResult)
}
}
}
return
}
60 changes: 60 additions & 0 deletions pkg/backend/ipv4dotted_builtin_resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package backend

import (
"fmt"
"net"
"regexp"
"strings"
)

const IPV4DOTTED_BUILTIN_RESOLVER_NAME = "builtin:ipv4dotted"

type IPv4DottedResolver struct {
settings map[string]interface{}
regexp *regexp.Regexp
ttl uint32
}

func NewIPv4DottedResolver(settings map[string]interface{}) *IPv4DottedResolver {
var domain, pattern string
var ttl uint32
domain, _ = settings["domain"].(string)
ttl, _ = settings["ttl"].(uint32)
pattern = fmt.Sprintf("(([0-9]{1,3}\\.){3}([0-9]{1,3}))\\.%s$", strings.ReplaceAll(domain, ".", "\\."))
re, _ := regexp.Compile(pattern)
return &IPv4DottedResolver{
settings: settings,
regexp: re,
ttl: ttl,
}
}

func (resolver *IPv4DottedResolver) Lookup(qtype string, qname string, _ string) (lookupResultArray []LookupResult, err error) {
lookupResultArray = []LookupResult{}
if qtype == A || qtype == AAAA || qtype == ANY {
a := resolver.regexp.FindStringSubmatch(qname)
if len(a) > 1 {
ip := net.ParseIP(a[1])
if ip != nil {
var lookupResult LookupResult
if qtype == A || qtype == ANY {
lookupResult = LookupResult{
QType: A,
QName: qname,
Content: ip.String(),
TTL: uint32(60),
}
} else {
lookupResult = LookupResult{
QType: AAAA,
QName: qname,
Content: fmt.Sprintf("::ffff:%s", ip.String()),
TTL: uint32(60),
}
}
lookupResultArray = append(lookupResultArray, lookupResult)
}
}
}
return
}
Loading

0 comments on commit 1331916

Please sign in to comment.