mirror of https://github.com/0xERR0R/blocky.git
148 lines
3.5 KiB
Go
148 lines
3.5 KiB
Go
package resolver
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/0xERR0R/blocky/log"
|
|
"github.com/0xERR0R/blocky/model"
|
|
"github.com/0xERR0R/blocky/util"
|
|
"github.com/miekg/dns"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func newRequest(question string, rType dns.Type, logger ...*logrus.Entry) *model.Request {
|
|
var loggerEntry *logrus.Entry
|
|
if len(logger) == 1 {
|
|
loggerEntry = logger[0]
|
|
} else {
|
|
loggerEntry = logrus.NewEntry(log.Log())
|
|
}
|
|
|
|
return &model.Request{
|
|
Req: util.NewMsgWithQuestion(question, rType),
|
|
Log: loggerEntry,
|
|
Protocol: model.RequestProtocolUDP,
|
|
}
|
|
}
|
|
|
|
func newRequestWithClient(question string, rType dns.Type, ip string, clientNames ...string) *model.Request {
|
|
return &model.Request{
|
|
ClientIP: net.ParseIP(ip),
|
|
ClientNames: clientNames,
|
|
Req: util.NewMsgWithQuestion(question, rType),
|
|
Log: logrus.NewEntry(log.Log()),
|
|
RequestTS: time.Time{},
|
|
Protocol: model.RequestProtocolUDP,
|
|
}
|
|
}
|
|
|
|
// newResponseMsg creates a new dns.Msg as response for a request
|
|
func newResponseMsg(request *model.Request) *dns.Msg {
|
|
response := new(dns.Msg)
|
|
response.SetReply(request.Req)
|
|
|
|
return response
|
|
}
|
|
|
|
// returnResponseModel wrapps a dns.Msg into a model.Response
|
|
func returnResponseModel(response *dns.Msg, rtype model.ResponseType, reason string) (*model.Response, error) {
|
|
return &model.Response{
|
|
Res: response,
|
|
RType: rtype,
|
|
Reason: reason,
|
|
}, nil
|
|
}
|
|
|
|
func newRequestWithClientID(question string, rType dns.Type, ip string, requestClientID string) *model.Request {
|
|
return &model.Request{
|
|
ClientIP: net.ParseIP(ip),
|
|
RequestClientID: requestClientID,
|
|
Req: util.NewMsgWithQuestion(question, rType),
|
|
Log: logrus.NewEntry(log.Log()),
|
|
RequestTS: time.Time{},
|
|
Protocol: model.RequestProtocolUDP,
|
|
}
|
|
}
|
|
|
|
// Resolver generic interface for all resolvers
|
|
type Resolver interface {
|
|
|
|
// Resolve performs resolution of a DNS request
|
|
Resolve(req *model.Request) (*model.Response, error)
|
|
|
|
// Configuration returns current resolver configuration
|
|
Configuration() []string
|
|
}
|
|
|
|
// ChainedResolver represents a resolver, which can delegate result to the next one
|
|
type ChainedResolver interface {
|
|
Resolver
|
|
|
|
// Next sets the next resolver
|
|
Next(n Resolver)
|
|
|
|
// GetNext returns the next resolver
|
|
GetNext() Resolver
|
|
}
|
|
|
|
// NextResolver is the base implementation of ChainedResolver
|
|
type NextResolver struct {
|
|
next Resolver
|
|
}
|
|
|
|
// Next sets the next resolver
|
|
func (r *NextResolver) Next(n Resolver) {
|
|
r.next = n
|
|
}
|
|
|
|
// GetNext returns the next resolver
|
|
func (r *NextResolver) GetNext() Resolver {
|
|
return r.next
|
|
}
|
|
|
|
// NamedResolver is a resolver with a special name
|
|
type NamedResolver interface {
|
|
|
|
// Name returns the full name of the resolver
|
|
Name() string
|
|
}
|
|
|
|
func logger(prefix string) *logrus.Entry {
|
|
return log.PrefixedLog(prefix)
|
|
}
|
|
|
|
func withPrefix(logger *logrus.Entry, prefix string) *logrus.Entry {
|
|
return logger.WithField("prefix", prefix)
|
|
}
|
|
|
|
// Chain creates a chain of resolvers
|
|
func Chain(resolvers ...Resolver) Resolver {
|
|
for i, res := range resolvers {
|
|
if i+1 < len(resolvers) {
|
|
if cr, ok := res.(ChainedResolver); ok {
|
|
cr.Next(resolvers[i+1])
|
|
}
|
|
}
|
|
}
|
|
|
|
return resolvers[0]
|
|
}
|
|
|
|
// Name returns a user-friendly name of a resolver
|
|
func Name(resolver Resolver) string {
|
|
if named, ok := resolver.(NamedResolver); ok {
|
|
return named.Name()
|
|
}
|
|
|
|
return defaultName(resolver)
|
|
}
|
|
|
|
// defaultName returns a short user-friendly name of a resolver
|
|
func defaultName(resolver Resolver) string {
|
|
return strings.Split(fmt.Sprintf("%T", resolver), ".")[1]
|
|
}
|