blocky/resolver/resolver.go

170 lines
3.4 KiB
Go

package resolver
import (
"fmt"
"net"
"strings"
"time"
"github.com/0xERR0R/blocky/log"
"github.com/0xERR0R/blocky/util"
"github.com/miekg/dns"
"github.com/sirupsen/logrus"
)
// RequestProtocol represents the server protocol
type RequestProtocol uint8
const (
// TCP is the TPC protocol
TCP RequestProtocol = iota
// UDP is the UDP protocol
UDP
)
func (r RequestProtocol) String() string {
names := [...]string{
"TCP",
"UDP"}
return names[r]
}
// Request represents client's DNS request
type Request struct {
ClientIP net.IP
Protocol RequestProtocol
ClientNames []string
Req *dns.Msg
Log *logrus.Entry
RequestTS time.Time
}
func newRequest(question string, rType uint16, logger ...*logrus.Entry) *Request {
var loggerEntry *logrus.Entry
if len(logger) == 1 {
loggerEntry = logger[0]
} else {
loggerEntry = logrus.NewEntry(log.Log())
}
return &Request{
Req: util.NewMsgWithQuestion(question, rType),
Log: loggerEntry,
Protocol: UDP,
}
}
func newRequestWithClient(question string, rType uint16, ip string, clientNames ...string) *Request {
return &Request{
ClientIP: net.ParseIP(ip),
ClientNames: clientNames,
Req: util.NewMsgWithQuestion(question, rType),
Log: logrus.NewEntry(log.Log()),
RequestTS: time.Time{},
Protocol: UDP,
}
}
// ResponseType represents the type of the response
type ResponseType int
const (
// RESOLVED the response was resolved by the external upstream resolver
RESOLVED ResponseType = iota
// CACHED the response was resolved from cache
CACHED
// BLOCKED the query was blocked
BLOCKED
// CONDITIONAL the query was resolved by the conditional upstream resolver
CONDITIONAL
// CUSTOMDNS the query was resolved by a custom rule
CUSTOMDNS
)
func (r ResponseType) String() string {
names := [...]string{
"RESOLVED",
"CACHED",
"BLOCKED",
"CONDITIONAL",
"CUSTOMDNS"}
return names[r]
}
// Response represents the response of a DNS query
type Response struct {
Res *dns.Msg
Reason string
RType ResponseType
}
// Resolver generic interface for all resolvers
type Resolver interface {
// Resolve performs resolution of a DNS request
Resolve(req *Request) (*Response, error)
// Configuration prints 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
}
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 {
return strings.Split(fmt.Sprintf("%T", resolver), ".")[1]
}