diff --git a/firewall/dns.go b/firewall/dns.go index e49e9353..02268eb3 100644 --- a/firewall/dns.go +++ b/firewall/dns.go @@ -264,8 +264,9 @@ func UpdateIPsAndCNAMEs(q *resolver.Query, rrCache *resolver.RRCache, conn *netw // Create new record for this IP. record := resolver.ResolvedDomain{ Domain: q.FQDN, - Expires: rrCache.Expires, + RRCache: rrCache, Resolver: rrCache.Resolver, + 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 f89ad827..3efb5635 100644 --- a/nameserver/nameserver.go +++ b/nameserver/nameserver.go @@ -222,17 +222,27 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg) } } // Handle special cases. - switch { - case rrCache == nil: + if rrCache == nil { tracer.Warning("nameserver: received successful, but empty reply from resolver") return reply(nsutil.ServerFailure("internal error: empty reply")) - case rrCache.RCode == dns.RcodeNameError: + } + + // Add dns context and resolver to connection. + conn.DNSContext = rrCache + conn.Resolver = rrCache.Resolver + + // Return now if NXDomain. + if rrCache.RCode == dns.RcodeNameError { return reply(nsutil.NxDomain("no answer found (NXDomain)")) } 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 84a63db1..94ab3c31 100644 --- a/network/connection.go +++ b/network/connection.go @@ -143,6 +143,12 @@ type Connection struct { //nolint:maligned // TODO: fix alignment // that iniated the connection. It is set once when the connection // object is created and is considered immutable afterwards. ProcessContext ProcessContext + // DNSContext holds additional information about the DNS request that was + // probably used to resolve the IP of this connection. + DNSContext *resolver.RRCache + // TunnelContext holds additional information about the tunnel that this + // connection is using. + TunnelContext interface{} // Internal is set to true if the connection is attributed as an // Portmaster internal connection. Internal may be set at different // points and access to it must be guarded by the connection lock. @@ -327,6 +333,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection { var scope string var resolverInfo *resolver.ResolverInfo + var dnsContext *resolver.RRCache if inbound { @@ -358,6 +365,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection { scope = lastResolvedDomain.Domain entity.Domain = lastResolvedDomain.Domain entity.CNAME = lastResolvedDomain.CNAMEs + dnsContext = lastResolvedDomain.RRCache resolverInfo = lastResolvedDomain.Resolver removeOpenDNSRequest(proc.Pid, lastResolvedDomain.Domain) } @@ -401,6 +409,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection { IPProtocol: pkt.Info().Protocol, LocalPort: pkt.Info().LocalPort(), ProcessContext: getProcessContext(pkt.Ctx(), proc), + DNSContext: dnsContext, process: proc, // remote endpoint Entity: entity, diff --git a/resolver/ipinfo.go b/resolver/ipinfo.go index 7c5f3d5f..50a2eb75 100644 --- a/resolver/ipinfo.go +++ b/resolver/ipinfo.go @@ -44,6 +44,9 @@ type ResolvedDomain struct { // information. Resolver *ResolverInfo + // RRCache holds the DNS response that was received for this domain. + RRCache *RRCache + // Expires holds the timestamp when this entry expires. // This does not mean that the entry may not be used anymore afterwards, // but that this is used to calcuate the TTL of the database record. diff --git a/resolver/rrcache.go b/resolver/rrcache.go index f012b74d..de62b4e6 100644 --- a/resolver/rrcache.go +++ b/resolver/rrcache.go @@ -24,13 +24,13 @@ type RRCache struct { RCode int // Response Content - Answer []dns.RR - Ns []dns.RR - Extra []dns.RR + Answer []dns.RR `json:"-"` + Ns []dns.RR `json:"-"` + Extra []dns.RR `json:"-"` Expires int64 // Resolver Information - Resolver *ResolverInfo + Resolver *ResolverInfo `json:"-"` // Metadata about the request and handling ServedFromCache bool