diff --git a/firewall/dns.go b/firewall/dns.go index 02268eb3..5aaeff26 100644 --- a/firewall/dns.go +++ b/firewall/dns.go @@ -263,10 +263,10 @@ func UpdateIPsAndCNAMEs(q *resolver.Query, rrCache *resolver.RRCache, conn *netw // Create new record for this IP. record := resolver.ResolvedDomain{ - Domain: q.FQDN, - RRCache: rrCache, - Resolver: rrCache.Resolver, - Expires: rrCache.Expires, + Domain: q.FQDN, + Resolver: rrCache.Resolver, + DNSRequestContext: rrCache.ToDNSRequestContext(), + Expires: rrCache.Expires, } // Resolve all CNAMEs in the correct order and add the to the record. diff --git a/nameserver/nameserver.go b/nameserver/nameserver.go index 3efb5635..44a37b2f 100644 --- a/nameserver/nameserver.go +++ b/nameserver/nameserver.go @@ -141,6 +141,12 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg) // Once we decided on the connection we might need to save it to the database, // so we defer that check for now. defer func() { + // Add metadata to connection. + if rrCache != nil { + conn.DNSContext = rrCache.ToDNSRequestContext() + conn.Resolver = rrCache.Resolver + } + switch conn.Verdict { // We immediately save blocked, dropped or failed verdicts so // they pop up in the UI. @@ -222,27 +228,19 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg) } } // Handle special cases. - if rrCache == nil { + switch { + case rrCache == nil: tracer.Warning("nameserver: received successful, but empty reply from resolver") return reply(nsutil.ServerFailure("internal error: empty reply")) - } - - // Add dns context and resolver to connection. - conn.DNSContext = rrCache - conn.Resolver = rrCache.Resolver - - // Return now if NXDomain. - if rrCache.RCode == dns.RcodeNameError { + case rrCache.RCode == dns.RcodeNameError: + // Return now if NXDomain. return reply(nsutil.NxDomain("no answer found (NXDomain)")) } + // Check with firewall again after resolving. tracer.Trace("nameserver: deciding on resolved dns") rrCache = firewall.FilterResolvedDNS(ctx, conn, q, rrCache) - // Add dns context and resolver to connection. - conn.DNSContext = rrCache - conn.Resolver = rrCache.Resolver - // Check again if there is a responder from the firewall. if responder, ok := conn.Reason.Context.(nsutil.Responder); ok { tracer.Infof("nameserver: handing over request for %s to special filter responder: %s", q.ID(), conn.Reason.Msg) diff --git a/network/connection.go b/network/connection.go index 94ab3c31..37005665 100644 --- a/network/connection.go +++ b/network/connection.go @@ -145,7 +145,7 @@ type Connection struct { //nolint:maligned // TODO: fix alignment ProcessContext ProcessContext // DNSContext holds additional information about the DNS request that was // probably used to resolve the IP of this connection. - DNSContext *resolver.RRCache + DNSContext *resolver.DNSRequestContext // TunnelContext holds additional information about the tunnel that this // connection is using. TunnelContext interface{} @@ -333,7 +333,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection { var scope string var resolverInfo *resolver.ResolverInfo - var dnsContext *resolver.RRCache + var dnsContext *resolver.DNSRequestContext if inbound { @@ -365,7 +365,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection { scope = lastResolvedDomain.Domain entity.Domain = lastResolvedDomain.Domain entity.CNAME = lastResolvedDomain.CNAMEs - dnsContext = lastResolvedDomain.RRCache + dnsContext = lastResolvedDomain.DNSRequestContext resolverInfo = lastResolvedDomain.Resolver removeOpenDNSRequest(proc.Pid, lastResolvedDomain.Domain) } diff --git a/resolver/ipinfo.go b/resolver/ipinfo.go index 50a2eb75..ff48dbde 100644 --- a/resolver/ipinfo.go +++ b/resolver/ipinfo.go @@ -44,8 +44,8 @@ type ResolvedDomain struct { // information. Resolver *ResolverInfo - // RRCache holds the DNS response that was received for this domain. - RRCache *RRCache + // DNSRequestContext holds the DNS request context. + DNSRequestContext *DNSRequestContext // Expires holds the timestamp when this entry expires. // This does not mean that the entry may not be used anymore afterwards, diff --git a/resolver/rr_context.go b/resolver/rr_context.go new file mode 100644 index 00000000..98fb7802 --- /dev/null +++ b/resolver/rr_context.go @@ -0,0 +1,39 @@ +package resolver + +import ( + "time" + + "github.com/miekg/dns" +) + +// DNSRequestContext is a static structure to add information to DNS request connections. +type DNSRequestContext struct { + Domain string + Question string + RCode string + + ServedFromCache bool + RequestingNew bool + IsBackup bool + Filtered bool + + Modified time.Time + Expires time.Time +} + +// ToDNSRequestContext returns a new DNSRequestContext of the RRCache. +func (rrCache *RRCache) ToDNSRequestContext() *DNSRequestContext { + return &DNSRequestContext{ + Domain: rrCache.Domain, + Question: rrCache.Question.String(), + RCode: dns.RcodeToString[rrCache.RCode], + + ServedFromCache: rrCache.ServedFromCache, + RequestingNew: rrCache.RequestingNew, + IsBackup: rrCache.IsBackup, + Filtered: rrCache.Filtered, + + Modified: time.Unix(rrCache.Modified, 0), + Expires: time.Unix(rrCache.Expires, 0), + } +} diff --git a/resolver/rrcache.go b/resolver/rrcache.go index 05a75ce1..de62b4e6 100644 --- a/resolver/rrcache.go +++ b/resolver/rrcache.go @@ -2,7 +2,6 @@ package resolver import ( "context" - "encoding/json" "fmt" "net" "time" @@ -45,25 +44,6 @@ type RRCache struct { Modified int64 } -func (rrCache *RRCache) MarshalJSON() ([]byte, error) { - var record = struct { - RRCache - - Question string - RCode string - Modified time.Time - Expires time.Time - }{ - RRCache: *rrCache, - Question: rrCache.Question.String(), - RCode: dns.RcodeToString[rrCache.RCode], - Modified: time.Unix(rrCache.Modified, 0), - Expires: time.Unix(rrCache.Expires, 0), - } - - return json.Marshal(record) -} - // ID returns the ID of the RRCache consisting of the domain and question type. func (rrCache *RRCache) ID() string { return rrCache.Domain + rrCache.Question.String()