Skip to content

Commit

Permalink
Delegate DNS queries with the same protocol as the incoming query
Browse files Browse the repository at this point in the history
  • Loading branch information
rtpt-erikgeiser committed Jun 7, 2024
1 parent 2fd2439 commit 7381fb1
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 23 deletions.
18 changes: 8 additions & 10 deletions dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ func createDNSReplyFromRequest(

shouldRespond, reason := shouldRespondToNameResolutionQuery(config, name, q.Qtype, peer, peerHostnames)
if !shouldRespond {
answers := handleIgnored(logger, q, name, queryType(q, request.Opcode), peer, reason, handlerType, delegateQuestion)
answers := handleIgnored(logger, q, name, queryType(q, request.Opcode),
peer, reason, handlerType, rw.RemoteAddr().Network(), delegateQuestion)
reply.Answer = append(reply.Answer, answers...)

continue
Expand Down Expand Up @@ -133,7 +134,7 @@ func createDNSReplyFromRequest(
})
default:
answers := handleIgnored(logger, q, name, queryType(q, request.Opcode), peer, IgnoreReasonQueryTypeUnhandled,
handlerType, delegateQuestion)
handlerType, rw.RemoteAddr().Network(), delegateQuestion)
reply.Answer = append(reply.Answer, answers...)

continue
Expand All @@ -156,11 +157,11 @@ func createDNSReplyFromRequest(

func handleIgnored(
logger *Logger, rawQuestion dns.Question, name string, queryType string, peer net.IP, reason string,
handlerType HandlerType, delegateQuestion delegateQuestionFunc,
handlerType HandlerType, net string, delegateQuestion delegateQuestionFunc,
) []dns.RR {
switch {
case handlerType == HandlerTypeDNS && delegateQuestion != nil:
rr, err := delegateQuestion(rawQuestion)
rr, err := delegateQuestion(rawQuestion, net)
if err != nil {
logger.Errorf("cannot delegate %s query for %q from %s: %v", queryType, rawQuestion.Name, peer, err)
}
Expand Down Expand Up @@ -415,18 +416,15 @@ func hasSpecificIPv4Address(iface *net.Interface, ip net.IP) bool {
return false
}

type delegateQuestionFunc func(dns.Question) ([]dns.RR, error)
type delegateQuestionFunc func(q dns.Question, net string) ([]dns.RR, error)

func delegateToDNSServer(dnsServer string, timeout time.Duration) delegateQuestionFunc {
return func(q dns.Question) ([]dns.RR, error) {
return func(q dns.Question, net string) ([]dns.RR, error) {
c := &dns.Client{
Timeout: timeout,
}

if q.Qtype == dns.TypeANY || q.Qtype == dns.TypeTXT {
c.Net = "tcp"
}

c.Net = net
m1 := new(dns.Msg)
m1.Id = dns.Id()
m1.RecursionDesired = true
Expand Down
70 changes: 58 additions & 12 deletions dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,13 +246,14 @@ func TestDNSDelegation(t *testing.T) {
SpoofFor: []*hostMatcher{newHostMatcher("10.0.0.99", defaultLookupTimeout)},
}

reply := createDNSReplyFromRequest(mockRW, aQuery, nil, cfg, HandlerTypeDNS, func(q dns.Question) ([]dns.RR, error) {
if q.Qtype == dns.TypeA && q.Name == "host" {
return []dns.RR{&dns.A{Hdr: rrHeader(q.Name, dns.TypeA, 1*time.Second), A: delegatedResponseIP}}, nil
}
reply := createDNSReplyFromRequest(mockRW, aQuery, nil, cfg, HandlerTypeDNS,
func(q dns.Question, net string) ([]dns.RR, error) {
if q.Qtype == dns.TypeA && q.Name == "host" {
return []dns.RR{&dns.A{Hdr: rrHeader(q.Name, dns.TypeA, 1*time.Second), A: delegatedResponseIP}}, nil
}

return nil, nil
})
return nil, nil
})
if reply == nil {
t.Fatalf("no delegated reply")
}
Expand Down Expand Up @@ -306,13 +307,14 @@ func TestDelegatedUnhandledQuery(t *testing.T) {
SpoofFor: []*hostMatcher{newHostMatcher("10.0.0.99", defaultLookupTimeout)},
}

reply := createDNSReplyFromRequest(mockRW, aQuery, nil, cfg, HandlerTypeDNS, func(q dns.Question) ([]dns.RR, error) {
if q.Qtype == dns.TypePTR && q.Name == "host" {
return []dns.RR{&dns.PTR{Hdr: rrHeader(q.Name, dns.TypePTR, 1*time.Second), Ptr: delegatedPTR}}, nil
}
reply := createDNSReplyFromRequest(mockRW, aQuery, nil, cfg, HandlerTypeDNS,
func(q dns.Question, net string) ([]dns.RR, error) {
if q.Qtype == dns.TypePTR && q.Name == "host" {
return []dns.RR{&dns.PTR{Hdr: rrHeader(q.Name, dns.TypePTR, 1*time.Second), Ptr: delegatedPTR}}, nil
}

return nil, nil
})
return nil, nil
})
if reply == nil {
t.Fatalf("no delegated reply")
}
Expand All @@ -331,6 +333,50 @@ func TestDelegatedUnhandledQuery(t *testing.T) {
}
}

func TestDelegatedQueryUDP(t *testing.T) {
aQuery := &dns.Msg{}
aQuery.SetQuestion("host", dns.TypeANY)

relayIPv4 := mustParseIP(t, "10.0.0.2")
mockRW := mockResonseWriter{Remote: &net.UDPAddr{IP: mustParseIP(t, "10.0.0.1")}}

cfg := Config{RelayIPv4: relayIPv4}

reply := createDNSReplyFromRequest(mockRW, aQuery, nil, cfg, HandlerTypeDNS,
func(q dns.Question, net string) ([]dns.RR, error) {
if net != "udp" {
t.Fatalf("UDP query was delegated via %q", net)
}

return []dns.RR{&dns.ANY{Hdr: rrHeader(q.Name, dns.TypeANY, 1*time.Second)}}, nil
})
if reply == nil {
t.Fatalf("no delegated reply")
}
}

func TestDelegatedQueryTCP(t *testing.T) {
aQuery := &dns.Msg{}
aQuery.SetQuestion("host", dns.TypeA)

relayIPv4 := mustParseIP(t, "10.0.0.2")
mockRW := mockResonseWriter{Remote: &net.TCPAddr{IP: mustParseIP(t, "10.0.0.1")}}

cfg := Config{RelayIPv4: relayIPv4}

reply := createDNSReplyFromRequest(mockRW, aQuery, nil, cfg, HandlerTypeDNS,
func(q dns.Question, net string) ([]dns.RR, error) {
if net != "tcp" {
t.Fatalf("TCP query was delegated via %q", net)
}

return []dns.RR{&dns.A{Hdr: rrHeader(q.Name, dns.TypeA, 1*time.Second), A: relayIPv4}}, nil
})
if reply == nil {
t.Fatalf("no delegated reply")
}
}

func testReply(tb testing.TB, requestFileName string, replyFileName string) {
tb.Helper()

Expand Down
2 changes: 1 addition & 1 deletion filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ func TestFilterDHCP(t *testing.T) {
},
}

hostMatcherLookupFunction = func(host string, timeout time.Duration) ([]net.IP, error) {
hostMatcherLookupFunction = func(host string, _ time.Duration) ([]net.IP, error) {
switch host {
case "somehost":
return []net.IP{mustParseIP(t, "192.168.0.5")}, nil
Expand Down

0 comments on commit 7381fb1

Please sign in to comment.