Send notification instead of killing conflicting DNS service

This commit is contained in:
Daniel
2022-05-25 13:57:31 +02:00
parent 65f646aad0
commit 515f4686f7
3 changed files with 154 additions and 170 deletions

View File

@@ -13,6 +13,7 @@ import (
"github.com/safing/portbase/log"
"github.com/safing/portbase/modules"
"github.com/safing/portbase/modules/subsystems"
"github.com/safing/portbase/notifications"
"github.com/safing/portmaster/compat"
"github.com/safing/portmaster/firewall"
"github.com/safing/portmaster/netenv"
@@ -25,6 +26,9 @@ var (
stopListener1 func() error
stopListener2 func() error
stopListenersLock sync.Mutex
eventIDConflictingService = "nameserver:conflicting-service"
eventIDListenerFailed = "nameserver:listener-failed"
)
func init() {
@@ -133,24 +137,93 @@ func startListener(ip net.IP, port uint16, first bool) {
return nil
}
// Resolve generic listener error, if primary listener.
if first {
module.Resolve(eventIDListenerFailed)
}
// Start listening.
log.Infof("nameserver: starting to listen on %s", dnsServer.Addr)
err := dnsServer.ListenAndServe()
if err != nil {
// check if we are shutting down
// Stop worker without error if we are shutting down.
if module.IsStopping() {
return nil
}
// is something blocking our port?
checkErr := checkForConflictingService(ip, port)
if checkErr != nil {
return checkErr
}
log.Warningf("nameserver: failed to listen on %s: %s", dnsServer.Addr, err)
handleListenError(err, ip, port, first)
}
return err
})
}
func handleListenError(err error, ip net.IP, port uint16, primaryListener bool) {
var n *notifications.Notification
// Create suffix for secondary listener
var secondaryEventIDSuffix string
if !primaryListener {
secondaryEventIDSuffix = "-secondary"
}
// Find a conflicting service.
cfProcess := findConflictingProcess(ip, port)
if cfProcess != nil {
// Report the conflicting process.
// Build conflicting process description.
var cfDescription string
cfName, err := cfProcess.Name()
if err == nil && cfName != "" {
cfDescription = cfName
}
cfExe, err := cfProcess.Exe()
if err == nil && cfDescription != "" {
if cfDescription != "" {
cfDescription += " (" + cfExe + ")"
} else {
cfDescription = cfName
}
}
// Notify user about conflicting service.
n = notifications.Notify(&notifications.Notification{
EventID: eventIDConflictingService + secondaryEventIDSuffix,
Type: notifications.Error,
Title: "Conflicting DNS Software",
Message: fmt.Sprintf(
"Restart Portmaster after you have deactivated or properly configured the conflicting software: %s",
cfDescription,
),
ShowOnSystem: true,
AvailableActions: []*notifications.Action{
{
Text: "Open Docs",
Type: notifications.ActionTypeOpenURL,
Payload: "https://docs.safing.io/portmaster/install/status/software-compatibility",
},
},
})
} else {
// If no conflict is found, report the error directly.
n = notifications.Notify(&notifications.Notification{
EventID: eventIDListenerFailed + secondaryEventIDSuffix,
Type: notifications.Error,
Title: "Secure DNS Error",
Message: fmt.Sprintf(
"The internal DNS server failed. Restart Portmaster to try again. Error: %s",
err,
),
ShowOnSystem: true,
})
}
// Attach error to module, if primary listener.
if primaryListener {
n.AttachToModule(module)
}
}
func stop() error {
stopListenersLock.Lock()
defer stopListenersLock.Unlock()