mirror of
https://github.com/folbricht/routedns.git
synced 2025-12-30 14:10:03 -06:00
* Migrate from logrus to slog * fully removing logrus * should be working now * Update pipeline.go Co-authored-by: Frank Olbricht <frank.olbricht@gmail.com> * Update response-blocklist-name.go Co-authored-by: Frank Olbricht <frank.olbricht@gmail.com> * added null logger * Update pipeline.go --------- Co-authored-by: Frank Olbricht <frank.olbricht@gmail.com>
97 lines
2.3 KiB
Go
97 lines
2.3 KiB
Go
package rdns
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
// Replace is a resolver that modifies queries according to regular expressions
|
|
// and forwards the modified queries to another resolver. Responses are then
|
|
// mapped back to the original query string.
|
|
type Replace struct {
|
|
id string
|
|
resolver Resolver
|
|
exp replaceExpressions
|
|
}
|
|
|
|
var _ Resolver = &Replace{}
|
|
|
|
type replaceExp struct {
|
|
from *regexp.Regexp
|
|
to string
|
|
}
|
|
|
|
type replaceExpressions []replaceExp
|
|
|
|
func (r replaceExpressions) apply(name string) string {
|
|
for _, e := range r {
|
|
name = e.from.ReplaceAllString(name, e.to)
|
|
}
|
|
return name
|
|
}
|
|
|
|
type ReplaceOperation struct {
|
|
From string
|
|
To string
|
|
}
|
|
|
|
// NewReplace returns a new instance of a Replace resolver.
|
|
func NewReplace(id string, resolver Resolver, list ...ReplaceOperation) (*Replace, error) {
|
|
var exp replaceExpressions
|
|
for _, o := range list {
|
|
re, err := regexp.Compile(o.From)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
exp = append(exp, replaceExp{re, o.To})
|
|
}
|
|
|
|
return &Replace{id: id, resolver: resolver, exp: exp}, nil
|
|
}
|
|
|
|
// Resolve a DNS query by first replacing the query string with another
|
|
// sending the query upstream and replace the name in the response with
|
|
// the original query string again.
|
|
func (r *Replace) Resolve(q *dns.Msg, ci ClientInfo) (*dns.Msg, error) {
|
|
if len(q.Question) < 1 {
|
|
return nil, errors.New("no question in query")
|
|
}
|
|
oldName := q.Question[0].Name
|
|
newName := r.exp.apply(oldName)
|
|
log := logger(r.id, q, ci)
|
|
|
|
// if nothing needs modifying, we can stop here and use the original query
|
|
if newName == oldName {
|
|
log.Debug("forwarding unmodified query to resolver")
|
|
return r.resolver.Resolve(q, ci)
|
|
}
|
|
|
|
// Modify the query string
|
|
q.Question[0].Name = newName
|
|
|
|
// Send the query upstream
|
|
log.With("new-qname", newName).With("resolver", r.resolver).Debug("forwarding modified query to resolver")
|
|
a, err := r.resolver.Resolve(q, ci)
|
|
if err != nil || a == nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Set the question back to the original name
|
|
a.Question[0].Name = oldName
|
|
|
|
// Now put the original name in all answer records that have the
|
|
// new name
|
|
for _, answer := range a.Answer {
|
|
if answer.Header().Name == newName {
|
|
answer.Header().Name = oldName
|
|
}
|
|
}
|
|
return a, nil
|
|
}
|
|
|
|
func (r *Replace) String() string {
|
|
return r.id
|
|
}
|