mirror of
https://github.com/safing/portmaster
synced 2025-04-07 12:39:09 +00:00
* [service] Add reading of PID in ETW DNS event * [service] Use PID of the ETW DNS events * [service] Fix use of nil pointer * [service] Fix compiler error
139 lines
3.3 KiB
Go
139 lines
3.3 KiB
Go
package dnsmonitor
|
|
|
|
import (
|
|
"errors"
|
|
"net"
|
|
"strings"
|
|
|
|
"github.com/miekg/dns"
|
|
|
|
"github.com/safing/portmaster/base/database"
|
|
"github.com/safing/portmaster/base/log"
|
|
"github.com/safing/portmaster/service/compat"
|
|
"github.com/safing/portmaster/service/integration"
|
|
"github.com/safing/portmaster/service/mgr"
|
|
"github.com/safing/portmaster/service/network/netutils"
|
|
"github.com/safing/portmaster/service/resolver"
|
|
)
|
|
|
|
var ResolverInfo = resolver.ResolverInfo{
|
|
Name: "SystemResolver",
|
|
Type: resolver.ServerTypeMonitor,
|
|
}
|
|
|
|
type DNSMonitor struct {
|
|
instance instance
|
|
mgr *mgr.Manager
|
|
|
|
listener *Listener
|
|
}
|
|
|
|
// Manager returns the module manager.
|
|
func (dl *DNSMonitor) Manager() *mgr.Manager {
|
|
return dl.mgr
|
|
}
|
|
|
|
// Start starts the module.
|
|
func (dl *DNSMonitor) Start() error {
|
|
// Initialize dns event listener
|
|
var err error
|
|
dl.listener, err = newListener(dl)
|
|
if err != nil {
|
|
log.Warningf("dnsmonitor: failed to start dns listener: %s", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Stop stops the module.
|
|
func (dl *DNSMonitor) Stop() error {
|
|
if dl.listener != nil {
|
|
err := dl.listener.stop()
|
|
if err != nil {
|
|
log.Errorf("dnsmonitor: failed to close listener: %s", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Flush flushes the buffer forcing all events to be processed.
|
|
func (dl *DNSMonitor) Flush() error {
|
|
return dl.listener.flush()
|
|
}
|
|
|
|
func saveDomain(domain string, ips []net.IP, cnames map[string]string, profileScope string) {
|
|
fqdn := dns.Fqdn(domain)
|
|
// Create new record for this IP.
|
|
record := resolver.ResolvedDomain{
|
|
Domain: fqdn,
|
|
Resolver: &ResolverInfo,
|
|
DNSRequestContext: &resolver.DNSRequestContext{},
|
|
Expires: 0,
|
|
}
|
|
|
|
// Process cnames
|
|
record.AddCNAMEs(cnames)
|
|
|
|
// Add to cache
|
|
saveIPsInCache(ips, profileScope, record)
|
|
}
|
|
|
|
func New(instance instance) (*DNSMonitor, error) {
|
|
// Initialize module
|
|
m := mgr.New("DNSMonitor")
|
|
module := &DNSMonitor{
|
|
mgr: m,
|
|
instance: instance,
|
|
}
|
|
|
|
return module, nil
|
|
}
|
|
|
|
type instance interface {
|
|
OSIntegration() *integration.OSIntegration
|
|
}
|
|
|
|
func processIfSelfCheckDomain(fqdn string) bool {
|
|
// Check for compat check dns request.
|
|
if strings.HasSuffix(fqdn, compat.DNSCheckInternalDomainScope) {
|
|
subdomain := strings.TrimSuffix(fqdn, compat.DNSCheckInternalDomainScope)
|
|
_ = compat.SubmitDNSCheckDomain(subdomain)
|
|
log.Infof("dnsmonitor: self-check domain received")
|
|
// No need to parse the answer.
|
|
return true
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// saveIPsInCache saves the provided ips in the dns cashe assoseted with the record Domain and CNAMEs.
|
|
func saveIPsInCache(ips []net.IP, profileID string, record resolver.ResolvedDomain) {
|
|
// Package IPs and CNAMEs into IPInfo structs.
|
|
for _, ip := range ips {
|
|
// Never save domain attributions for localhost IPs.
|
|
if netutils.GetIPScope(ip) == netutils.HostLocal {
|
|
continue
|
|
}
|
|
|
|
ipString := ip.String()
|
|
info, err := resolver.GetIPInfo(profileID, ipString)
|
|
if err != nil {
|
|
if !errors.Is(err, database.ErrNotFound) {
|
|
log.Errorf("dnsmonitor: failed to search for IP info record: %s", err)
|
|
}
|
|
|
|
info = &resolver.IPInfo{
|
|
IP: ipString,
|
|
ProfileID: profileID,
|
|
}
|
|
}
|
|
|
|
// Add the new record to the resolved domains for this IP and scope.
|
|
info.AddDomain(record)
|
|
|
|
// Save if the record is new or has been updated.
|
|
if err := info.Save(); err != nil {
|
|
log.Errorf("dnsmonitor: failed to save IP info record: %s", err)
|
|
}
|
|
}
|
|
}
|