mirror of
https://github.com/safing/portmaster
synced 2025-04-22 20:09:09 +00:00
* Move portbase into monorepo * Add new simple module mgr * [WIP] Switch to new simple module mgr * Add StateMgr and more worker variants * [WIP] Switch more modules * [WIP] Switch more modules * [WIP] swtich more modules * [WIP] switch all SPN modules * [WIP] switch all service modules * [WIP] Convert all workers to the new module system * [WIP] add new task system to module manager * [WIP] Add second take for scheduling workers * [WIP] Add FIXME for bugs in new scheduler * [WIP] Add minor improvements to scheduler * [WIP] Add new worker scheduler * [WIP] Fix more bug related to new module system * [WIP] Fix start handing of the new module system * [WIP] Improve startup process * [WIP] Fix minor issues * [WIP] Fix missing subsystem in settings * [WIP] Initialize managers in constructor * [WIP] Move module event initialization to constrictors * [WIP] Fix setting for enabling and disabling the SPN module * [WIP] Move API registeration into module construction * [WIP] Update states mgr for all modules * [WIP] Add CmdLine operation support * Add state helper methods to module group and instance * Add notification and module status handling to status package * Fix starting issues * Remove pilot widget and update security lock to new status data * Remove debug logs * Improve http server shutdown * Add workaround for cleanly shutting down firewall+netquery * Improve logging * Add syncing states with notifications for new module system * Improve starting, stopping, shutdown; resolve FIXMEs/TODOs * [WIP] Fix most unit tests * Review new module system and fix minor issues * Push shutdown and restart events again via API * Set sleep mode via interface * Update example/template module * [WIP] Fix spn/cabin unit test * Remove deprecated UI elements * Make log output more similar for the logging transition phase * Switch spn hub and observer cmds to new module system * Fix log sources * Make worker mgr less error prone * Fix tests and minor issues * Fix observation hub * Improve shutdown and restart handling * Split up big connection.go source file * Move varint and dsd packages to structures repo * Improve expansion test * Fix linter warnings * Fix interception module on windows * Fix linter errors --------- Co-authored-by: Vladimir Stoilov <vladimir@safing.io>
189 lines
5.1 KiB
Go
189 lines
5.1 KiB
Go
package docks
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
|
|
"github.com/safing/portmaster/base/log"
|
|
"github.com/safing/portmaster/spn/conf"
|
|
"github.com/safing/portmaster/spn/hub"
|
|
"github.com/safing/portmaster/spn/ships"
|
|
"github.com/safing/portmaster/spn/terminal"
|
|
)
|
|
|
|
var hubImportLock sync.Mutex
|
|
|
|
// ImportAndVerifyHubInfo imports the given hub message and verifies them.
|
|
func ImportAndVerifyHubInfo(ctx context.Context, hubID string, announcementData, statusData []byte, mapName string, scope hub.Scope) (h *hub.Hub, forward bool, tErr *terminal.Error) {
|
|
var firstErr *terminal.Error
|
|
|
|
// Synchronize import, as we might easily learn of a new hub from different
|
|
// gossip channels simultaneously.
|
|
hubImportLock.Lock()
|
|
defer hubImportLock.Unlock()
|
|
|
|
// Check arguments.
|
|
if announcementData == nil && statusData == nil {
|
|
return nil, false, terminal.ErrInternalError.With("no announcement or status supplied")
|
|
}
|
|
|
|
// Import Announcement, if given.
|
|
var hubKnown, hubChanged bool
|
|
if announcementData != nil {
|
|
hubFromMsg, known, changed, err := hub.ApplyAnnouncement(nil, announcementData, mapName, scope, false)
|
|
if err != nil {
|
|
firstErr = terminal.ErrInternalError.With("failed to apply announcement: %w", err)
|
|
}
|
|
if known {
|
|
hubKnown = true
|
|
}
|
|
if changed {
|
|
hubChanged = true
|
|
}
|
|
if hubFromMsg != nil {
|
|
h = hubFromMsg
|
|
}
|
|
}
|
|
|
|
// Import Status, if given.
|
|
if statusData != nil {
|
|
hubFromMsg, known, changed, err := hub.ApplyStatus(h, statusData, mapName, scope, false)
|
|
if err != nil && firstErr == nil {
|
|
firstErr = terminal.ErrInternalError.With("failed to apply status: %w", err)
|
|
}
|
|
if known && announcementData == nil {
|
|
// If we parsed an announcement before, "known" will always be true here,
|
|
// as we supply hub.ApplyStatus with a hub.
|
|
hubKnown = true
|
|
}
|
|
if changed {
|
|
hubChanged = true
|
|
}
|
|
if hubFromMsg != nil {
|
|
h = hubFromMsg
|
|
}
|
|
}
|
|
|
|
// Only continue if we now have a Hub.
|
|
if h == nil {
|
|
if firstErr != nil {
|
|
return nil, false, firstErr
|
|
}
|
|
return nil, false, terminal.ErrInternalError.With("got not hub after data import")
|
|
}
|
|
|
|
// Abort if the given hub ID does not match.
|
|
// We may have just connected to the wrong IP address.
|
|
if hubID != "" && h.ID != hubID {
|
|
return nil, false, terminal.ErrInternalError.With("hub mismatch")
|
|
}
|
|
|
|
// Verify hub if:
|
|
// - There is no error up until here.
|
|
// - There has been any change.
|
|
// - The hub is not verified yet.
|
|
// - We're a public Hub.
|
|
// - We're not testing.
|
|
if firstErr == nil && hubChanged && !h.Verified() && conf.PublicHub() && !runningTests {
|
|
if !conf.HubHasIPv4() && !conf.HubHasIPv6() {
|
|
firstErr = terminal.ErrInternalError.With("no hub networks set")
|
|
}
|
|
if h.Info.IPv4 != nil && conf.HubHasIPv4() {
|
|
err := verifyHubIP(ctx, h, h.Info.IPv4)
|
|
if err != nil {
|
|
firstErr = terminal.ErrIntegrity.With("failed to verify IPv4 address %s of %s: %w", h.Info.IPv4, h, err)
|
|
}
|
|
}
|
|
if h.Info.IPv6 != nil && conf.HubHasIPv6() {
|
|
err := verifyHubIP(ctx, h, h.Info.IPv6)
|
|
if err != nil {
|
|
firstErr = terminal.ErrIntegrity.With("failed to verify IPv6 address %s of %s: %w", h.Info.IPv6, h, err)
|
|
}
|
|
}
|
|
|
|
if firstErr != nil {
|
|
func() {
|
|
h.Lock()
|
|
defer h.Unlock()
|
|
h.InvalidInfo = true
|
|
}()
|
|
log.Warningf("spn/docks: failed to verify IPs of %s: %s", h, firstErr)
|
|
} else {
|
|
func() {
|
|
h.Lock()
|
|
defer h.Unlock()
|
|
h.VerifiedIPs = true
|
|
}()
|
|
log.Infof("spn/docks: verified IPs of %s: IPv4=%s IPv6=%s", h, h.Info.IPv4, h.Info.IPv6)
|
|
}
|
|
}
|
|
|
|
// Dismiss initial imports with errors.
|
|
if !hubKnown && firstErr != nil {
|
|
return nil, false, firstErr
|
|
}
|
|
|
|
// Don't do anything if nothing changed.
|
|
if !hubChanged {
|
|
return h, false, firstErr
|
|
}
|
|
|
|
// We now have one of:
|
|
// - A unknown Hub without error.
|
|
// - A known Hub without error.
|
|
// - A known Hub with error, which we want to save and propagate.
|
|
|
|
// Save the Hub to the database.
|
|
err := h.Save()
|
|
if err != nil {
|
|
log.Errorf("spn/docks: failed to persist %s: %s", h, err)
|
|
}
|
|
|
|
// Save the raw messages to the database.
|
|
if announcementData != nil {
|
|
err = hub.SaveHubMsg(h.ID, h.Map, hub.MsgTypeAnnouncement, announcementData)
|
|
if err != nil {
|
|
log.Errorf("spn/docks: failed to save raw announcement msg of %s: %s", h, err)
|
|
}
|
|
}
|
|
if statusData != nil {
|
|
err = hub.SaveHubMsg(h.ID, h.Map, hub.MsgTypeStatus, statusData)
|
|
if err != nil {
|
|
log.Errorf("spn/docks: failed to save raw status msg of %s: %s", h, err)
|
|
}
|
|
}
|
|
|
|
return h, true, firstErr
|
|
}
|
|
|
|
func verifyHubIP(ctx context.Context, h *hub.Hub, ip net.IP) error {
|
|
// Create connection.
|
|
ship, err := ships.Launch(ctx, h, nil, ip)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to launch ship to %s: %w", ip, err)
|
|
}
|
|
|
|
// Start crane for receiving reply.
|
|
crane, err := NewCrane(ship, h, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create crane: %w", err)
|
|
}
|
|
module.mgr.Go("crane unloader", crane.unloader)
|
|
defer crane.Stop(nil)
|
|
|
|
// Verify Hub.
|
|
err = crane.VerifyConnectedHub(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// End connection.
|
|
tErr := crane.endInit()
|
|
if tErr != nil {
|
|
log.Debugf("spn/docks: failed to end verification connection to %s: %s", ip, tErr)
|
|
}
|
|
|
|
return nil
|
|
}
|