From 8b044136577f334a3e6f9e0e6f7e23375f6b42e8 Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 17 Feb 2022 15:42:33 +0100 Subject: [PATCH 01/10] Add home and DNS exit node rules --- cabin/config-public.go | 10 +++--- captain/config.go | 77 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/cabin/config-public.go b/cabin/config-public.go index c150398..a4834bf 100644 --- a/cabin/config-public.go +++ b/cabin/config-public.go @@ -240,9 +240,8 @@ func prepPublicHubConfig() error { ExpertiseLevel: config.ExpertiseLevelExpert, DefaultValue: publicCfgOptionEntryDefault, Annotations: config.Annotations{ - config.DisplayOrderAnnotation: publicCfgOptionEntryOrder, - config.DisplayHintAnnotation: endpoints.DisplayHintEndpointList, - endpoints.EndpointListAnnotation: []string{endpoints.EndpointListIP}, + config.DisplayOrderAnnotation: publicCfgOptionEntryOrder, + config.DisplayHintAnnotation: endpoints.DisplayHintEndpointList, }, }) if err != nil { @@ -258,9 +257,8 @@ func prepPublicHubConfig() error { ExpertiseLevel: config.ExpertiseLevelExpert, DefaultValue: publicCfgOptionExitDefault, Annotations: config.Annotations{ - config.DisplayOrderAnnotation: publicCfgOptionExitOrder, - config.DisplayHintAnnotation: endpoints.DisplayHintEndpointList, - endpoints.EndpointListAnnotation: []string{endpoints.EndpointListIP}, + config.DisplayOrderAnnotation: publicCfgOptionExitOrder, + config.DisplayHintAnnotation: endpoints.DisplayHintEndpointList, }, }) if err != nil { diff --git a/captain/config.go b/captain/config.go index 878caef..1e54764 100644 --- a/captain/config.go +++ b/captain/config.go @@ -1,12 +1,28 @@ package captain -import "github.com/safing/portbase/config" +import ( + "sync" + + "github.com/safing/portbase/utils" + + "github.com/safing/portbase/config" + "github.com/safing/portmaster/profile" + "github.com/safing/portmaster/profile/endpoints" +) var ( // CfgOptionEnableSPNKey is the configuration key for the SPN module. CfgOptionEnableSPNKey = "spn/enable" cfgOptionEnableSPNOrder = 128 + CfgOptionHomeHubPolicyKey = "spn/homePolicy" + cfgOptionHomeHubPolicy config.StringArrayOption + cfgOptionHomeHubPolicyOrder = 131 + + CfgOptionDNSExitHubPolicyKey = "spn/dnsExitPolicy" + cfgOptionDNSExitHubPolicy config.StringArrayOption + cfgOptionDNSExitHubPolicyOrder = 133 + // Special Access Code. cfgOptionSpecialAccessCodeKey = "spn/specialAccessCode" cfgOptionSpecialAccessCodeDefault = "none" @@ -15,7 +31,66 @@ var ( ) func prepConfig() error { + // Home Node Rules err := config.Register(&config.Option{ + Name: "Home Node Rules", + Key: CfgOptionHomeHubPolicyKey, + Description: `Customize which countries should or should not be used for your Home Node. The Home Node is your entry into the SPN. You connect directly to it and all your connections are routed through it. + +By default, the Portmaster tries to choose the nearest node as your Home Node in order to reduce your exposure to the open Internet. + +Reconnect to the SPN in order to apply new rules.`, + Help: profile.SPNRulesHelp, + OptType: config.OptTypeStringArray, + ExpertiseLevel: config.ExpertiseLevelExpert, + DefaultValue: []string{}, + Annotations: config.Annotations{ + config.StackableAnnotation: true, + config.CategoryAnnotation: "Routing", + config.DisplayOrderAnnotation: cfgOptionHomeHubPolicyOrder, + config.DisplayHintAnnotation: endpoints.DisplayHintEndpointList, + config.QuickSettingsAnnotation: profile.SPNRulesQuickSettings, + endpoints.EndpointListVerdictNamesAnnotation: profile.SPNRulesVerdictNames, + }, + ValidationRegex: endpoints.ListEntryValidationRegex, + ValidationFunc: endpoints.ValidateEndpointListConfigOption, + }) + if err != nil { + return err + } + cfgOptionHomeHubPolicy = config.Concurrent.GetAsStringArray(CfgOptionHomeHubPolicyKey, []string{}) + + // DNS Exit Node Rules + err = config.Register(&config.Option{ + Name: "DNS Exit Node Rules", + Key: CfgOptionDNSExitHubPolicyKey, + Description: `Customize which countries should or should not be used as DNS Exit Nodes. + +By default, the Portmaster will exit DNS requests directly at your Home Node in order to keep them fast and close to your location. This is important, as DNS resolution often takes your approximate location into account when deciding which optimized DNS records are returned to you. As the Portmaster encrypts your DNS requests by default, you effectively gain a two-hop security level for your DNS requests in order to protect your privacy. + +This setting mainly exists for when you need to simulate your presence in another location on a lower level too. This might be necessary to defeat more intelligent geo-blocking systems.`, + Help: profile.SPNRulesHelp, + OptType: config.OptTypeStringArray, + RequiresRestart: true, + ExpertiseLevel: config.ExpertiseLevelExpert, + DefaultValue: []string{}, + Annotations: config.Annotations{ + config.StackableAnnotation: true, + config.CategoryAnnotation: "Routing", + config.DisplayOrderAnnotation: cfgOptionDNSExitHubPolicyOrder, + config.DisplayHintAnnotation: endpoints.DisplayHintEndpointList, + config.QuickSettingsAnnotation: profile.SPNRulesQuickSettings, + endpoints.EndpointListVerdictNamesAnnotation: profile.SPNRulesVerdictNames, + }, + ValidationRegex: endpoints.ListEntryValidationRegex, + ValidationFunc: endpoints.ValidateEndpointListConfigOption, + }) + if err != nil { + return err + } + cfgOptionDNSExitHubPolicy = config.Concurrent.GetAsStringArray(CfgOptionDNSExitHubPolicyKey, []string{}) + + err = config.Register(&config.Option{ Name: "Special Access Code", Key: cfgOptionSpecialAccessCodeKey, Description: "Special Access Codes grant access to the SPN for testing or evaluation purposes.", From 5abb39e528f50b8f2535749df7b502963972b581 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 18 Feb 2022 14:15:09 +0100 Subject: [PATCH 02/10] Integrate SPN route manipulation settings --- captain/config.go | 35 ++++++++++- captain/navigation.go | 68 +++++++++++++++++++--- captain/piers.go | 33 +++++++++-- crew/policy.go | 20 +------ go.sum | 2 + hub/hub.go | 29 +++++++++- navigator/api.go | 2 +- navigator/findnearest.go | 2 +- navigator/findnearest_test.go | 6 +- navigator/findroutes.go | 10 ++-- navigator/intel.go | 8 +++ navigator/measurements.go | 2 +- navigator/optimize.go | 6 +- navigator/optimize_test.go | 2 +- navigator/options.go | 106 +++++++++++++++++----------------- navigator/routing-profiles.go | 75 ++++++++++++++---------- 16 files changed, 277 insertions(+), 129 deletions(-) diff --git a/captain/config.go b/captain/config.go index 1e54764..016f8e4 100644 --- a/captain/config.go +++ b/captain/config.go @@ -104,8 +104,41 @@ This setting mainly exists for when you need to simulate your presence in anothe if err != nil { return err } - cfgOptionSpecialAccessCode = config.Concurrent.GetAsString(cfgOptionSpecialAccessCodeKey, "") return nil } + +var ( + homeHubPolicy endpoints.Endpoints + homeHubPolicyData []string + homeHubPolcyLock sync.Mutex +) + +func getHomeHubPolicy() (endpoints.Endpoints, error) { + homeHubPolcyLock.Lock() + defer homeHubPolcyLock.Unlock() + + // Get config data and check if it changed. + newData := cfgOptionHomeHubPolicy() + if utils.StringSliceEqual(newData, homeHubPolicyData) { + return homeHubPolicy, nil + } + + // Check if policy is empty and return without parsing. + if len(newData) == 0 { + homeHubPolicy = nil + return homeHubPolicy, nil + } + + // Parse policy. + policy, err := endpoints.ParseEndpoints(newData) + if err != nil { + homeHubPolicy = nil + return nil, err + } + + // Save and return the new policy. + homeHubPolicy = policy + return homeHubPolicy, nil +} diff --git a/captain/navigation.go b/captain/navigation.go index bdb1184..05fdd93 100644 --- a/captain/navigation.go +++ b/captain/navigation.go @@ -6,6 +6,9 @@ import ( "fmt" "time" + "github.com/safing/portmaster/intel" + "github.com/safing/portmaster/profile/endpoints" + "github.com/safing/portbase/log" "github.com/safing/portbase/modules" "github.com/safing/portbase/notifications" @@ -20,6 +23,10 @@ import ( const stopCraneAfterBeingUnsuggestedFor = 6 * time.Hour +var ( + ErrAllHomeHubsExcluded = errors.New("all home hubs are excluded") +) + func homeHubManager(ctx context.Context) (err error) { defer ready.UnSet() defer netenv.ConnectedToSPN.UnSet() @@ -49,12 +56,28 @@ managing: err = establishHomeHub(ctx) if err != nil { log.Warningf("failed to establish connection to home hub: %s", err) - notifications.NotifyWarn( - "spn:home-hub-failure", - "SPN Failed to Connect", - fmt.Sprintf("Failed to connect to a home hub: %s. The Portmaster will retry to connect automatically.", err), - spnSettingsButton, - ).AttachToModule(module) + switch { + case errors.Is(err, ErrAllHomeHubsExcluded): + notifications.NotifyError( + "spn:all-home-hubs-excluded", + "All Home Nodes Excluded", + "Your current Home Node Rules exclude all available SPN Nodes. Please change your rules to allow for at least one available Home Node.", + notifications.Action{ + Text: "Configure", + Type: notifications.ActionTypeOpenSetting, + Payload: ¬ifications.ActionTypeOpenSettingPayload{ + Key: CfgOptionHomeHubPolicyKey, + }, + }, + ).AttachToModule(module) + default: + notifications.NotifyWarn( + "spn:home-hub-failure", + "SPN Failed to Connect", + fmt.Sprintf("Failed to connect to a home hub: %s. The Portmaster will retry to connect automatically.", err), + spnSettingsButton, + ).AttachToModule(module) + } resetSPNStatus(StatusFailed) select { case <-ctx.Done(): @@ -125,12 +148,38 @@ func establishHomeHub(ctx context.Context) error { locations.BestV6(), ) + // Get own entity. + // Checking the entity against the entry policies is somewhat hit and miss + // anyway, as the device location is an approximation. + var myEntity *intel.Entity + if dl := locations.BestV4(); dl != nil && dl.IP != nil { + myEntity = &intel.Entity{} + myEntity.SetIP(dl.IP) + myEntity.FetchData(ctx) + } else if dl := locations.BestV6(); dl != nil && dl.IP != nil { + myEntity = &intel.Entity{} + myEntity.SetIP(dl.IP) + myEntity.FetchData(ctx) + } + + // Get home hub policy for selecting the home hub. + homePolicy, err := getHomeHubPolicy() + if err != nil { + return err + } + + // Build navigation options for searching for a home hub. + opts := &navigator.Options{ + HubPolicies: []endpoints.Endpoints{homePolicy}, + CheckHubEntryPolicyWith: myEntity, + } + // Find nearby hubs. findCandidates: candidates, err := navigator.Main.FindNearestHubs( locations.BestV4().LocationOrNil(), locations.BestV6().LocationOrNil(), - nil, navigator.HomeHub, 10, + opts, navigator.HomeHub, 10, ) if err != nil { if errors.Is(err, navigator.ErrEmptyMap) { @@ -145,6 +194,11 @@ findCandidates: return fmt.Errorf("failed to find nearby hubs: %w", err) } + // Check if any candidates were returned. + if len(candidates) == 0 && len(homePolicy) > 0 { + return ErrAllHomeHubsExcluded + } + // Try connecting to a hub. var tries int var candidate *hub.Hub diff --git a/captain/piers.go b/captain/piers.go index cadc32d..055f03f 100644 --- a/captain/piers.go +++ b/captain/piers.go @@ -2,10 +2,14 @@ package captain import ( "context" + "fmt" "sync" "github.com/safing/portbase/log" "github.com/safing/portbase/modules" + "github.com/safing/portmaster/intel" + "github.com/safing/portmaster/network/netutils" + "github.com/safing/portmaster/profile/endpoints" "github.com/safing/spn/docks" "github.com/safing/spn/hub" "github.com/safing/spn/ships" @@ -82,10 +86,10 @@ func dockingRequestHandler(ctx context.Context) error { // TODO: Do actual pier management. log.Errorf("spn/captain: pier %s failed: %s", r.Pier.Transport(), r.Err) case r.Ship != nil: - if checkDockingPermission(r.Ship) { - handleDockingRequest(r.Ship) + if err := checkDockingPermission(ctx, r.Ship); err != nil { + log.Warningf("spn/captain: denied ship from %s to dock at pier %s: %s", r.Ship.RemoteAddr(), r.Pier.Transport(), err) } else { - log.Warningf("spn/captain: denied ship from %s to dock at pier %s", r.Ship.RemoteAddr(), r.Pier.Transport()) + handleDockingRequest(r.Ship) } default: log.Warningf("spn/captain: received invalid docking request without ship for pier %s", r.Pier.Transport()) @@ -94,9 +98,26 @@ func dockingRequestHandler(ctx context.Context) error { } } -func checkDockingPermission(ship ships.Ship) (ok bool) { - // TODO: check docking policies (hub entry policy) - return true +func checkDockingPermission(ctx context.Context, ship ships.Ship) error { + remoteIP, err := netutils.IPFromAddr(ship.RemoteAddr()) + if err != nil { + return fmt.Errorf("failed to parse remote IP: %w", err) + } + + // Create entity. + entity := &intel.Entity{} + entity.SetIP(remoteIP) + entity.FetchData(ctx) + + // TODO: Do we want to handle protocol and port too? + + // Check against policy. + result, reason := publicIdentity.Hub.GetInfo().EntryPolicy().Match(ctx, entity) + if result == endpoints.Denied { + return fmt.Errorf("entry policy violated: %s", reason) + } + + return nil } func handleDockingRequest(ship ships.Ship) { diff --git a/crew/policy.go b/crew/policy.go index b3cfc59..951fef2 100644 --- a/crew/policy.go +++ b/crew/policy.go @@ -11,10 +11,8 @@ import ( ) var ( - connectingHubLock sync.Mutex - connectingHub *hub.Hub - connectingHubExitPolicy endpoints.Endpoints - connectingHubInfoTimestamp int64 + connectingHubLock sync.Mutex + connectingHub *hub.Hub ) // EnableConnecting enables connecting from this Hub. @@ -23,7 +21,6 @@ func EnableConnecting(my *hub.Hub) { defer connectingHubLock.Unlock() connectingHub = my - connectingHubInfoTimestamp = -1 } func checkExitPolicy(request *ConnectRequest) *terminal.Error { @@ -35,17 +32,6 @@ func checkExitPolicy(request *ConnectRequest) *terminal.Error { return terminal.ErrPermissinDenied.With("connect requests disabled") } - // Get info and parse the exit policy, if needed. - info := connectingHub.GetInfo() - if info.Timestamp != connectingHubInfoTimestamp { - var err error - connectingHubExitPolicy, err = endpoints.ParseEndpoints(info.Exit) - if err != nil { - return terminal.ErrInternalError.With("failed to parse exit policy: %w", err) - } - connectingHubInfoTimestamp = info.Timestamp - } - // Create entity. entity := &intel.Entity{ Protocol: uint8(request.Protocol), @@ -56,7 +42,7 @@ func checkExitPolicy(request *ConnectRequest) *terminal.Error { entity.FetchData(context.TODO()) // Check against policy. - result, reason := connectingHubExitPolicy.Match(context.TODO(), entity) + result, reason := connectingHub.GetInfo().ExitPolicy().Match(context.TODO(), entity) if result == endpoints.Denied { return terminal.ErrPermissinDenied.With("connect request for %s violates the exit policy: %s", request, reason) } diff --git a/go.sum b/go.sum index bdcc25f..4e007f5 100644 --- a/go.sum +++ b/go.sum @@ -1640,3 +1640,5 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= diff --git a/hub/hub.go b/hub/hub.go index 42358b3..f93289d 100644 --- a/hub/hub.go +++ b/hub/hub.go @@ -1,6 +1,7 @@ package hub import ( + "fmt" "net" "sync" "time" @@ -9,6 +10,7 @@ import ( "github.com/safing/jess" "github.com/safing/portbase/database/record" + "github.com/safing/portmaster/profile/endpoints" ) // Scope is the network scope a Hub can be in. @@ -106,9 +108,11 @@ type Announcement struct { // } // protocols with metadata // Policies - default permit - Entry []string + Entry []string + entryPolicy endpoints.Endpoints // {"+ ", "- *"} - Exit []string + Exit []string + exitPolicy endpoints.Endpoints // {"- * TCP/25", "- US"} } @@ -311,9 +315,30 @@ func (a *Announcement) validateFormatting() (err error) { if err = checkStringSliceFormat("Exit", a.Exit, 255, 255); err != nil { return err } + return a.parsePolicies() +} + +func (a *Announcement) parsePolicies() error { + var err error + if a.entryPolicy, err = endpoints.ParseEndpoints(a.Entry); err != nil { + return fmt.Errorf("failed to parse entry policy: %w", err) + } + if a.exitPolicy, err = endpoints.ParseEndpoints(a.Exit); err != nil { + return fmt.Errorf("failed to parse exit policy: %w", err) + } return nil } +// EntryPolicy returns the Hub's entry policy. +func (a *Announcement) EntryPolicy() endpoints.Endpoints { + return a.entryPolicy +} + +// ExitPolicy returns the Hub's exit policy. +func (a *Announcement) ExitPolicy() endpoints.Endpoints { + return a.exitPolicy +} + // String returns the string representation of the scope. func (s Scope) String() string { switch s { diff --git a/navigator/api.go b/navigator/api.go index ab7e4dc..972facd 100644 --- a/navigator/api.go +++ b/navigator/api.go @@ -296,7 +296,7 @@ func handleMapMeasurementsTableRequest(ar *api.Request) (data []byte, err error) if !ok { return nil, errors.New("map not found") } - matcher := m.DefaultOptions().Matcher(TransitHub) + matcher := m.DefaultOptions().Matcher(TransitHub, m.GetIntel()) // Get and sort pins. list := m.pinList(true) diff --git a/navigator/findnearest.go b/navigator/findnearest.go index d956bbc..53d0cbf 100644 --- a/navigator/findnearest.go +++ b/navigator/findnearest.go @@ -118,7 +118,7 @@ func (m *Map) FindNearestHubs(locationV4, locationV6 *geoip.Location, opts *Opti } // Find nearest Pins. - nearby, err := m.findNearestPins(locationV4, locationV6, opts.Matcher(matchFor), maxMatches) + nearby, err := m.findNearestPins(locationV4, locationV6, opts.Matcher(matchFor, m.intel), maxMatches) if err != nil { return nil, err } diff --git a/navigator/findnearest_test.go b/navigator/findnearest_test.go index 60b1cc2..072959a 100644 --- a/navigator/findnearest_test.go +++ b/navigator/findnearest_test.go @@ -16,7 +16,7 @@ func TestFindNearest(t *testing.T) { // Create a random destination address ip4, loc4 := createGoodIP(true) - nbPins, err := m.findNearestPins(loc4, nil, m.DefaultOptions().Matcher(DestinationHub), 10) + nbPins, err := m.findNearestPins(loc4, nil, m.DefaultOptions().Matcher(DestinationHub, m.intel), 10) if err != nil { t.Error(err) } else { @@ -28,7 +28,7 @@ func TestFindNearest(t *testing.T) { // Create a random destination address ip6, loc6 := createGoodIP(true) - nbPins, err := m.findNearestPins(nil, loc6, m.DefaultOptions().Matcher(DestinationHub), 10) + nbPins, err := m.findNearestPins(nil, loc6, m.DefaultOptions().Matcher(DestinationHub, m.intel), 10) if err != nil { t.Error(err) } else { @@ -69,7 +69,7 @@ func findFakeHomeHub(m *Map) { _, loc4 := createGoodIP(true) _, loc6 := createGoodIP(false) - nbPins, err := m.findNearestPins(loc4, loc6, m.defaultOptions().Matcher(HomeHub), 10) + nbPins, err := m.findNearestPins(loc4, loc6, m.defaultOptions().Matcher(HomeHub, m.intel), 10) if err != nil { panic(err) } diff --git a/navigator/findroutes.go b/navigator/findroutes.go index 36cc6bd..0ec1ddd 100644 --- a/navigator/findroutes.go +++ b/navigator/findroutes.go @@ -29,14 +29,14 @@ func (m *Map) FindRoutes(ip net.IP, opts *Options, maxRoutes int) (*Routes, erro } // Handle special home routing profile. - if opts.RoutingProfile == RoutingProfileHomeName { + if opts.RoutingProfile == RoutingProfileHomeID { return &Routes{ All: []*Route{{ Path: []*Hop{{ pin: m.home, HubID: m.home.Hub.ID, }}, - Algorithm: RoutingProfileHomeName, + Algorithm: RoutingProfileHomeID, }}, }, nil } @@ -55,7 +55,7 @@ func (m *Map) FindRoutes(ip net.IP, opts *Options, maxRoutes int) (*Routes, erro } // Find nearest Pins. - nearby, err := m.findNearestPins(locationV4, locationV6, opts.Matcher(DestinationHub), maxRoutes) + nearby, err := m.findNearestPins(locationV4, locationV6, opts.Matcher(DestinationHub, m.intel), maxRoutes) if err != nil { return nil, err } @@ -70,8 +70,8 @@ func (m *Map) findRoutes(dsts *nearbyPins, opts *Options, maxRoutes int) (*Route // Initialize matchers. var done bool - transitMatcher := opts.Matcher(TransitHub) - destinationMatcher := opts.Matcher(DestinationHub) + transitMatcher := opts.Matcher(TransitHub, m.intel) + destinationMatcher := opts.Matcher(DestinationHub, m.intel) routingProfile := getRoutingProfile(opts.RoutingProfile) // Create routes collector. diff --git a/navigator/intel.go b/navigator/intel.go index fb8a989..6cae706 100644 --- a/navigator/intel.go +++ b/navigator/intel.go @@ -42,6 +42,14 @@ func (m *Map) UpdateIntel(update *hub.Intel) error { return nil } +// GetIntel returns the map's intel data. +func (m *Map) GetIntel() *hub.Intel { + m.RLock() + defer m.RUnlock() + + return m.intel +} + func (m *Map) updateIntelStatuses(pin *Pin) { // Reset all related states. pin.removeStates(StateTrusted | StateUsageDiscouraged | StateUsageAsHomeDiscouraged | StateUsageAsDestinationDiscouraged) diff --git a/navigator/measurements.go b/navigator/measurements.go index 2cd5d8b..756bf31 100644 --- a/navigator/measurements.go +++ b/navigator/measurements.go @@ -32,7 +32,7 @@ func (m *Map) measureHubs(ctx context.Context, _ *modules.Task) error { } var unknownErrCnt int - matcher := m.DefaultOptions().Matcher(TransitHub) + matcher := m.DefaultOptions().Matcher(TransitHub, m.GetIntel()) // Get list and sort in order to check near/low-cost hubs earlier. list := m.pinList(true) diff --git a/navigator/optimize.go b/navigator/optimize.go index ef8893d..7d27d2c 100644 --- a/navigator/optimize.go +++ b/navigator/optimize.go @@ -209,7 +209,7 @@ func (m *Map) optimize(opts *Options) (result *OptimizationResult, err error) { // Create result. result = &OptimizationResult{ opts: opts, - matcher: opts.Matcher(TransitHub), + matcher: opts.Matcher(TransitHub, m.intel), } // Setup analyis. @@ -286,7 +286,7 @@ func (m *Map) optimizeForBootstrappingAndDesegregation(result *OptimizationResul opts.Regard = StateNone opts.Disregard = StateSummaryDisregard // Collect Pins with matcher. - matcher := opts.Matcher(TransitHub) + matcher := opts.Matcher(TransitHub, m.intel) for _, pin := range m.all { if matcher(pin) { connectable = append(connectable, pin) @@ -324,7 +324,7 @@ func (m *Map) optimizeForBootstrappingAndDesegregation(result *OptimizationResul // Iterate over all Pins to find any matching Pin. desegregateWith := make([]*Pin, 0, len(m.all)-reachable) - matcher := opts.Matcher(TransitHub) + matcher := opts.Matcher(TransitHub, m.intel) for _, pin := range m.all { if matcher(pin) { desegregateWith = append(desegregateWith, pin) diff --git a/navigator/optimize_test.go b/navigator/optimize_test.go index 0d504f2..611f7ef 100644 --- a/navigator/optimize_test.go +++ b/navigator/optimize_test.go @@ -113,7 +113,7 @@ func TestOptimize(t *testing.T) { t.Parallel() m := getOptimizedDefaultTestMap(t) - matcher := m.defaultOptions().Matcher(DestinationHub) + matcher := m.defaultOptions().Matcher(DestinationHub, m.intel) originalHome := m.home for _, pin := range m.all { diff --git a/navigator/options.go b/navigator/options.go index 2068fcd..9a9c660 100644 --- a/navigator/options.go +++ b/navigator/options.go @@ -5,6 +5,7 @@ import ( "github.com/safing/portmaster/intel" "github.com/safing/portmaster/profile/endpoints" + "github.com/safing/spn/hub" ) // HubType is the usage type of a Hub in routing. @@ -29,20 +30,17 @@ type Options struct { //nolint:maligned // set, a basic set of undesirable states is added automatically. Disregard PinState - // HubPolicy is an endpoint list that all Hubs must pass in order to be taken into account for the operation. - HubPolicy endpoints.Endpoints + // HubPolicies is a collecion of endpoint lists that Hubs must pass in order + // to be taken into account for the operation. + HubPolicies []endpoints.Endpoints - // HomeHubPolicy is an endpoint list that Home Hubs must pass in order to be taken into account for the operation. - HomeHubPolicy endpoints.Endpoints + // CheckHubEntryPolicyWith provides an entity that must match the Hubs entry + // policy in order to be taken into account for the operation. + CheckHubEntryPolicyWith *intel.Entity - // DestinationHubPolicy is an endpoint list that Destination Hubs must pass in order to be taken into account for the operation. - DestinationHubPolicy endpoints.Endpoints - - // TODO - CheckHubEntryPolicy bool - - // TODO - CheckHubExitPolicy bool + // CheckHubExitPolicyWith provides an entity that must match the Hubs exit + // policy in order to be taken into account for the operation. + CheckHubExitPolicyWith *intel.Entity // NoDefaults declares whether default and recommended Regard and Disregard states should not be used. NoDefaults bool @@ -59,11 +57,9 @@ func (o *Options) Copy() *Options { return &Options{ Regard: o.Regard, Disregard: o.Disregard, - HubPolicy: o.HubPolicy, - HomeHubPolicy: o.HomeHubPolicy, - DestinationHubPolicy: o.DestinationHubPolicy, - CheckHubEntryPolicy: o.CheckHubEntryPolicy, - CheckHubExitPolicy: o.CheckHubExitPolicy, + HubPolicies: o.HubPolicies, + CheckHubEntryPolicyWith: o.CheckHubEntryPolicyWith, + CheckHubExitPolicyWith: o.CheckHubExitPolicyWith, NoDefaults: o.NoDefaults, RequireTrustedDestinationHubs: o.RequireTrustedDestinationHubs, RoutingProfile: o.RoutingProfile, @@ -83,20 +79,14 @@ func (m *Map) DefaultOptions() *Options { func (m *Map) defaultOptions() *Options { opts := &Options{ - RoutingProfile: RoutingProfileDefaultName, - } - - if m.intel != nil && m.intel.Parsed() != nil { - opts.HubPolicy = m.intel.Parsed().HubAdvisory - opts.HomeHubPolicy = m.intel.Parsed().HomeHubAdvisory - opts.DestinationHubPolicy = m.intel.Parsed().DestinationHubAdvisory + RoutingProfile: DefaultRoutingProfileID, } return opts } // Matcher generates a PinMatcher based on the Options. -func (o *Options) Matcher(hubType HubType) PinMatcher { +func (o *Options) Matcher(hubType HubType, intel *hub.Intel) PinMatcher { // Compile states to regard and disregard. regard := o.Regard disregard := o.Disregard @@ -126,45 +116,51 @@ func (o *Options) Matcher(hubType HubType) PinMatcher { regard |= StateTrusted } - // Copy and activate applicable policies. - hubPolicy := o.HubPolicy - var homeHubPolicy endpoints.Endpoints - var destinationHubPolicy endpoints.Endpoints - switch hubType { - case HomeHub: - homeHubPolicy = o.HomeHubPolicy - case TransitHub: - // Transit Hubs have no additional policy. - case DestinationHub: - destinationHubPolicy = o.DestinationHubPolicy + // Add intel policies. + hubPolicies := o.HubPolicies + if intel != nil && intel.Parsed() != nil { + switch hubType { + case HomeHub: + hubPolicies = append(hubPolicies, intel.Parsed().HubAdvisory, intel.Parsed().HomeHubAdvisory) + case TransitHub: + hubPolicies = append(hubPolicies, intel.Parsed().HubAdvisory) + case DestinationHub: + hubPolicies = append(hubPolicies, intel.Parsed().HubAdvisory, intel.Parsed().DestinationHubAdvisory) + } } + // Add entry/exit policiy checks. + checkHubEntryPolicyWith := o.CheckHubEntryPolicyWith + checkHubExitPolicyWith := o.CheckHubExitPolicyWith + return func(pin *Pin) bool { // Check required Pin States. if !pin.State.has(regard) || pin.State.hasAnyOf(disregard) { return false } - // Check main policy. - if hubPolicy != nil { - if endpointListMatch(hubPolicy, pin.EntityV4) == endpoints.Denied || - endpointListMatch(hubPolicy, pin.EntityV6) == endpoints.Denied { + // Check policies. + for _, policy := range hubPolicies { + switch { + case endpointListMatch(policy, pin.EntityV4) == endpoints.Denied: + // Hub is denied by policy with its IPv4 entity. + return false + case endpointListMatch(policy, pin.EntityV6) == endpoints.Denied: + // Hub is denied by policy with its IPv6 entity. return false } } - // Check type based policy. - switch { - case hubType == HomeHub && homeHubPolicy != nil: - if endpointListMatch(homeHubPolicy, pin.EntityV4) == endpoints.Denied || - endpointListMatch(homeHubPolicy, pin.EntityV6) == endpoints.Denied { - return false - } - case hubType == DestinationHub && destinationHubPolicy != nil: - if endpointListMatch(destinationHubPolicy, pin.EntityV4) == endpoints.Denied || - endpointListMatch(destinationHubPolicy, pin.EntityV6) == endpoints.Denied { - return false - } + // Check entry/exit policies. + if checkHubEntryPolicyWith != nil && + endpointListMatch(pin.Hub.GetInfo().EntryPolicy(), checkHubEntryPolicyWith) == endpoints.Denied { + // Hub does not allow entry from the given entity. + return false + } + if checkHubExitPolicyWith != nil && + endpointListMatch(pin.Hub.GetInfo().EntryPolicy(), checkHubExitPolicyWith) == endpoints.Denied { + // Hub does not allow exit to the given entity. + return false } return true // All checks have passed. @@ -172,6 +168,12 @@ func (o *Options) Matcher(hubType HubType) PinMatcher { } func endpointListMatch(list endpoints.Endpoints, entity *intel.Entity) endpoints.EPResult { + // Check if endpoint list and entity are available. + if !list.IsSet() || entity == nil { + return endpoints.NoMatch + } + + // Match and return result only. result, _ := list.Match(context.TODO(), entity) return result } diff --git a/navigator/routing-profiles.go b/navigator/routing-profiles.go index 60cfe93..09de192 100644 --- a/navigator/routing-profiles.go +++ b/navigator/routing-profiles.go @@ -1,13 +1,12 @@ package navigator -import ( - "github.com/safing/portbase/log" -) - // RoutingProfile defines a routing algorithm with some options. type RoutingProfile struct { ID string + // Name is the human readable name of the profile. + Name string + // MinHops defines how many hops a route must have at minimum. In order to // reduce confusion, the Home Hub is also counted. MinHops int @@ -31,42 +30,60 @@ type RoutingProfile struct { // Routing Profile Names. const ( - RoutingProfileDefaultName = "default" - RoutingProfileShortestName = "shortest" - RoutingProfileHomeName = "home" + RoutingProfileHomeID = "home" + RoutingProfileSingleHopID = "single-hop" + RoutingProfileDoubleHopID = "double-hop" + RoutingProfileTripleHopID = "triple-hop" + + DefaultRoutingProfileID = RoutingProfileDoubleHopID ) // Routing Profiles. var ( - RoutingProfileDefault = &RoutingProfile{ - ID: RoutingProfileDefaultName, - MinHops: 3, - MaxHops: 5, - MaxExtraHops: 2, - MaxExtraCost: 100, // TODO: implement costs + RoutingProfileHome = &RoutingProfile{ + ID: "home", + Name: "Plain VPN Mode", + MinHops: 1, + MaxHops: 1, } - - RoutingProfileShortest = &RoutingProfile{ - ID: RoutingProfileShortestName, + RoutingProfileSingleHop = &RoutingProfile{ + ID: "single-hop", + Name: "Speed Focused", MinHops: 1, - MaxHops: 5, + MaxHops: 2, MaxExtraHops: 1, - MaxExtraCost: 100, // TODO: implement costs + MaxExtraCost: 10000, + } + RoutingProfileDoubleHop = &RoutingProfile{ + ID: "double-hop", + Name: "Balanced", + MinHops: 2, + MaxHops: 3, + MaxExtraHops: 2, + MaxExtraCost: 10000, + } + RoutingProfileTripleHop = &RoutingProfile{ + ID: "triple-hop", + Name: "Privacy Focused", + MinHops: 3, + MaxHops: 4, + MaxExtraHops: 3, + MaxExtraCost: 10000, } ) -func getRoutingProfile(name string) *RoutingProfile { - switch name { - case RoutingProfileDefaultName: - return RoutingProfileDefault - case RoutingProfileShortestName: - return RoutingProfileShortest - case RoutingProfileHomeName: - log.Warningf("spn/navigator: routing profile %q is special and cannot be used for calculation, falling back to default", name) - return RoutingProfileDefault +func getRoutingProfile(id string) *RoutingProfile { + switch id { + case RoutingProfileHomeID: + return RoutingProfileHome + case RoutingProfileSingleHopID: + return RoutingProfileSingleHop + case RoutingProfileDoubleHopID: + return RoutingProfileDoubleHop + case RoutingProfileTripleHopID: + return RoutingProfileTripleHop default: - log.Warningf("spn/navigator: routing profile %q does not exist, falling back to default", name) - return RoutingProfileDefault + return RoutingProfileDoubleHop } } From a50fcb08315611e12cecc5024c3dd2ce3ef35c12 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 18 Feb 2022 14:16:12 +0100 Subject: [PATCH 03/10] Check existing hub route before using in new route --- navigator/routing-profiles.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/navigator/routing-profiles.go b/navigator/routing-profiles.go index 09de192..2583f0b 100644 --- a/navigator/routing-profiles.go +++ b/navigator/routing-profiles.go @@ -115,6 +115,13 @@ func (rp *RoutingProfile) checkRouteCompliance(route *Route, foundRoutes *Routes } } + // Check if hub is already in use, if so check if the route matches. + lastPinConnection := route.Path[len(route.Path)-1].pin.Connection + if lastPinConnection != nil && + lastPinConnection.Route.Path[len(lastPinConnection.Route.Path)-2].HubID != route.Path[len(route.Path)-2].HubID { + return routeDisqualified + } + // Abort route exploration when we are outside the optimization boundaries. if len(foundRoutes.All) > 0 { // Get the best found route. From 6cc61b24a53880369eb27bd0739d159744a0042d Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Feb 2022 16:53:19 +0100 Subject: [PATCH 04/10] Update SPN settings order --- captain/config.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/captain/config.go b/captain/config.go index 016f8e4..1ea73f4 100644 --- a/captain/config.go +++ b/captain/config.go @@ -17,17 +17,17 @@ var ( CfgOptionHomeHubPolicyKey = "spn/homePolicy" cfgOptionHomeHubPolicy config.StringArrayOption - cfgOptionHomeHubPolicyOrder = 131 + cfgOptionHomeHubPolicyOrder = 145 CfgOptionDNSExitHubPolicyKey = "spn/dnsExitPolicy" cfgOptionDNSExitHubPolicy config.StringArrayOption - cfgOptionDNSExitHubPolicyOrder = 133 + cfgOptionDNSExitHubPolicyOrder = 147 // Special Access Code. cfgOptionSpecialAccessCodeKey = "spn/specialAccessCode" cfgOptionSpecialAccessCodeDefault = "none" cfgOptionSpecialAccessCode config.StringOption //nolint:unused // Linter, you drunk? - cfgOptionSpecialAccessCodeOrder = 144 + cfgOptionSpecialAccessCodeOrder = 160 ) func prepConfig() error { From 67992ae5c9741a4e3db027608dfde93509adc684 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Feb 2022 22:47:13 +0100 Subject: [PATCH 05/10] Fix and improve session path checking --- navigator/routing-profiles.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/navigator/routing-profiles.go b/navigator/routing-profiles.go index 2583f0b..2e6d8fd 100644 --- a/navigator/routing-profiles.go +++ b/navigator/routing-profiles.go @@ -1,5 +1,7 @@ package navigator +import "github.com/safing/portbase/log" + // RoutingProfile defines a routing algorithm with some options. type RoutingProfile struct { ID string @@ -116,10 +118,26 @@ func (rp *RoutingProfile) checkRouteCompliance(route *Route, foundRoutes *Routes } // Check if hub is already in use, if so check if the route matches. - lastPinConnection := route.Path[len(route.Path)-1].pin.Connection - if lastPinConnection != nil && - lastPinConnection.Route.Path[len(lastPinConnection.Route.Path)-2].HubID != route.Path[len(route.Path)-2].HubID { - return routeDisqualified + if len(route.Path) >= 2 { + // Get active connection to the last pin of the current path. + lastPinConnection := route.Path[len(route.Path)-1].pin.Connection + + switch { + case lastPinConnection == nil: + // Last pin is not yet connected. + case len(lastPinConnection.Route.Path) < 2: + // Path of last pin does not have enough hops. + // This is unexpected and should not happen. + log.Errorf( + "navigator: expected active connection to %s to have 2 hops or more on path, but it had %d", + route.Path[len(route.Path)-1].pin.Hub.StringWithoutLocking(), + len(lastPinConnection.Route.Path), + ) + case lastPinConnection.Route.Path[len(lastPinConnection.Route.Path)-2].pin.Hub.ID != route.Path[len(route.Path)-2].pin.Hub.ID: + // The previous hop of the existing route and the one we are evaluating don't match. + // Currently, we only allow one session per Hub. + return routeDisqualified + } } // Abort route exploration when we are outside the optimization boundaries. From 5bc040b4c7b762ce35615e3b3f1130f6ab5db4df Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Feb 2022 22:47:55 +0100 Subject: [PATCH 06/10] Improve and add home / dns exit hub policy parsing --- captain/config.go | 57 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/captain/config.go b/captain/config.go index 1ea73f4..a7666c6 100644 --- a/captain/config.go +++ b/captain/config.go @@ -3,8 +3,6 @@ package captain import ( "sync" - "github.com/safing/portbase/utils" - "github.com/safing/portbase/config" "github.com/safing/portmaster/profile" "github.com/safing/portmaster/profile/endpoints" @@ -110,29 +108,23 @@ This setting mainly exists for when you need to simulate your presence in anothe } var ( - homeHubPolicy endpoints.Endpoints - homeHubPolicyData []string - homeHubPolcyLock sync.Mutex + homeHubPolicy endpoints.Endpoints + homeHubPolicyLock sync.Mutex + homeHubPolicyConfigFlag = config.NewValidityFlag() ) func getHomeHubPolicy() (endpoints.Endpoints, error) { - homeHubPolcyLock.Lock() - defer homeHubPolcyLock.Unlock() + homeHubPolicyLock.Lock() + defer homeHubPolicyLock.Unlock() - // Get config data and check if it changed. - newData := cfgOptionHomeHubPolicy() - if utils.StringSliceEqual(newData, homeHubPolicyData) { - return homeHubPolicy, nil - } - - // Check if policy is empty and return without parsing. - if len(newData) == 0 { - homeHubPolicy = nil + // Return cached value if config is still valid. + if homeHubPolicyConfigFlag.IsValid() { return homeHubPolicy, nil } + homeHubPolicyConfigFlag.Refresh() - // Parse policy. - policy, err := endpoints.ParseEndpoints(newData) + // Parse new policy. + policy, err := endpoints.ParseEndpoints(cfgOptionHomeHubPolicy()) if err != nil { homeHubPolicy = nil return nil, err @@ -142,3 +134,32 @@ func getHomeHubPolicy() (endpoints.Endpoints, error) { homeHubPolicy = policy return homeHubPolicy, nil } + +var ( + dnsExitHubPolicy endpoints.Endpoints + dnsExitHubPolicyLock sync.Mutex + dnsExitHubPolicyConfigFlag = config.NewValidityFlag() +) + +// GetDNSExitHubPolicy return the current DNS exit policy. +func GetDNSExitHubPolicy() (endpoints.Endpoints, error) { + dnsExitHubPolicyLock.Lock() + defer dnsExitHubPolicyLock.Unlock() + + // Return cached value if config is still valid. + if dnsExitHubPolicyConfigFlag.IsValid() { + return dnsExitHubPolicy, nil + } + dnsExitHubPolicyConfigFlag.Refresh() + + // Parse new policy. + policy, err := endpoints.ParseEndpoints(cfgOptionDNSExitHubPolicy()) + if err != nil { + dnsExitHubPolicy = nil + return nil, err + } + + // Save and return the new policy. + dnsExitHubPolicy = policy + return dnsExitHubPolicy, nil +} From 61603dba7c9f4f38408083a19ce59d95f429b358 Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 25 Feb 2022 22:48:43 +0100 Subject: [PATCH 07/10] Add function to check if any hub policies are set --- navigator/options.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/navigator/options.go b/navigator/options.go index 9a9c660..17b8674 100644 --- a/navigator/options.go +++ b/navigator/options.go @@ -85,6 +85,16 @@ func (m *Map) defaultOptions() *Options { return opts } +// HubPoliciesAreSet returns whether any hub policies are set and non-empty. +func (o *Options) HubPoliciesAreSet() bool { + for _, policy := range o.HubPolicies { + if policy.IsSet() { + return true + } + } + return false +} + // Matcher generates a PinMatcher based on the Options. func (o *Options) Matcher(hubType HubType, intel *hub.Intel) PinMatcher { // Compile states to regard and disregard. From 57d13af71f041b7632138de0a98f571018d3ed32 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 2 Mar 2022 09:49:24 +0100 Subject: [PATCH 08/10] Fix linter errors --- captain/config.go | 2 ++ captain/navigation.go | 10 ++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/captain/config.go b/captain/config.go index a7666c6..7b60c8a 100644 --- a/captain/config.go +++ b/captain/config.go @@ -13,10 +13,12 @@ var ( CfgOptionEnableSPNKey = "spn/enable" cfgOptionEnableSPNOrder = 128 + // CfgOptionHomeHubPolicyKey is the configuration key for the SPN home policy. CfgOptionHomeHubPolicyKey = "spn/homePolicy" cfgOptionHomeHubPolicy config.StringArrayOption cfgOptionHomeHubPolicyOrder = 145 + // CfgOptionDNSExitHubPolicyKey is the configuration key for the SPN DNS exit policy. CfgOptionDNSExitHubPolicyKey = "spn/dnsExitPolicy" cfgOptionDNSExitHubPolicy config.StringArrayOption cfgOptionDNSExitHubPolicyOrder = 147 diff --git a/captain/navigation.go b/captain/navigation.go index 05fdd93..7c73ccc 100644 --- a/captain/navigation.go +++ b/captain/navigation.go @@ -6,14 +6,13 @@ import ( "fmt" "time" - "github.com/safing/portmaster/intel" - "github.com/safing/portmaster/profile/endpoints" - "github.com/safing/portbase/log" "github.com/safing/portbase/modules" "github.com/safing/portbase/notifications" + "github.com/safing/portmaster/intel" "github.com/safing/portmaster/netenv" "github.com/safing/portmaster/network/netutils" + "github.com/safing/portmaster/profile/endpoints" "github.com/safing/spn/access" "github.com/safing/spn/docks" "github.com/safing/spn/hub" @@ -23,9 +22,8 @@ import ( const stopCraneAfterBeingUnsuggestedFor = 6 * time.Hour -var ( - ErrAllHomeHubsExcluded = errors.New("all home hubs are excluded") -) +// ErrAllHomeHubsExcluded is returned when all available home hubs were excluded. +var ErrAllHomeHubsExcluded = errors.New("all home hubs are excluded") func homeHubManager(ctx context.Context) (err error) { defer ready.UnSet() From a17386d879e61c3a496de4f8a20fa53ff83e4319 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 2 Mar 2022 09:49:47 +0100 Subject: [PATCH 09/10] Abort crane msg submitting when crane is shutting down --- docks/crane.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docks/crane.go b/docks/crane.go index de7b8ae..b7f40c9 100644 --- a/docks/crane.go +++ b/docks/crane.go @@ -348,11 +348,17 @@ func (crane *Crane) AbandonTerminal(id uint32, err *terminal.Error) { } func (crane *Crane) submitImportantTerminalMsg(c *container.Container) { - crane.importantMsgs <- c + select { + case crane.importantMsgs <- c: + case <-crane.ctx.Done(): + } } func (crane *Crane) submitTerminalMsg(c *container.Container) { - crane.terminalMsgs <- c + select { + case crane.terminalMsgs <- c: + case <-crane.ctx.Done(): + } } func (crane *Crane) encrypt(shipment *container.Container) (encrypted *container.Container, err error) { From e8d72d4d0429ded76d8ca0f02327907d2b3d56c2 Mon Sep 17 00:00:00 2001 From: Daniel Date: Wed, 2 Mar 2022 09:49:53 +0100 Subject: [PATCH 10/10] Update deps --- go.mod | 10 ++++++++-- go.sum | 34 +++++++++++++++++----------------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 8b8827d..b2bf48a 100644 --- a/go.mod +++ b/go.mod @@ -6,12 +6,18 @@ require ( github.com/awalterschulze/gographviz v2.0.3+incompatible github.com/brianvoe/gofakeit v3.18.0+incompatible github.com/ghodss/yaml v1.0.0 + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect github.com/mitchellh/copystructure v1.2.0 github.com/mr-tron/base58 v1.2.0 github.com/rot256/pblind v0.0.0-20211117203330-22455f90b565 github.com/safing/jess v0.2.3 - github.com/safing/portbase v0.13.6 - github.com/safing/portmaster v0.8.0 + github.com/safing/portbase v0.14.0 + github.com/safing/portmaster v0.8.5-interdep github.com/stretchr/testify v1.7.0 github.com/tevino/abool v1.2.0 + github.com/tklauser/go-sysconf v0.3.10 // indirect + golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect + golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect + golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect ) diff --git a/go.sum b/go.sum index 4e007f5..920af79 100644 --- a/go.sum +++ b/go.sum @@ -68,8 +68,6 @@ contrib.go.opencensus.io/exporter/stackdriver v0.13.8/go.mod h1:huNtlWx75MwO7qMs contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AlecAivazis/survey/v2 v2.0.7/go.mod h1:mlizQTaPjnR4jcpwRSaSlkbsRfYFEyKgLQvYTzxxiHA= -github.com/AlecAivazis/survey/v2 v2.3.2 h1:TqTB+aDDCLYhf9/bD2TwSO8u8jDSmMUd2SUVO4gCnU8= -github.com/AlecAivazis/survey/v2 v2.3.2/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96 h1:cTp8I5+VIoKjsnZuH8vjyaysT/ses3EvZeaV/1UkF2M= github.com/AndreasBriese/bbloom v0.0.0-20190825152654-46b345b51c96/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= github.com/Azure/azure-amqp-common-go/v3 v3.1.0/go.mod h1:PBIGdzcO1teYoufTKMcGibdKaYZv4avS+O6LNIp8bq0= @@ -356,8 +354,9 @@ github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e h1:BWhy2j3IXJhjCbC68Fp github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.5/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= +github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= @@ -470,8 +469,9 @@ github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7 github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosimple/slug v1.10.0/go.mod h1:MICb3w495l9KNdZm+Xn5b6T2Hn831f9DMxiJ1r+bAjw= github.com/gosimple/unidecode v1.0.0/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -666,8 +666,6 @@ github.com/mdlayher/socket v0.2.0/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= @@ -797,10 +795,10 @@ github.com/safing/portbase v0.13.1/go.mod h1:5vj5IK5WJoSGareDe6yCMZfnF7txVRx7jZy github.com/safing/portbase v0.13.2/go.mod h1:5vj5IK5WJoSGareDe6yCMZfnF7txVRx7jZyTZInISP0= github.com/safing/portbase v0.13.3/go.mod h1:5vj5IK5WJoSGareDe6yCMZfnF7txVRx7jZyTZInISP0= github.com/safing/portbase v0.13.4/go.mod h1:5vj5IK5WJoSGareDe6yCMZfnF7txVRx7jZyTZInISP0= -github.com/safing/portbase v0.13.5 h1:WtDvnTh8reBMnhPiyAr62qkBeBUri0EaNlb0u2msNNM= github.com/safing/portbase v0.13.5/go.mod h1:5vj5IK5WJoSGareDe6yCMZfnF7txVRx7jZyTZInISP0= -github.com/safing/portbase v0.13.6 h1:0tAa4fyCdlZy4J+Ne9G5JshV+Cmu+Ol0m5AftPHnjvE= github.com/safing/portbase v0.13.6/go.mod h1:G0maDSQxYDuluNhMzA1zVd/nfXawfECv5H7+fnTfVhM= +github.com/safing/portbase v0.14.0 h1:6+sdUs1tdRCKnyuzy/zHrvUsdO1GdI0l4gZaoYJmJ5Q= +github.com/safing/portbase v0.14.0/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6XBBtN3bDI= github.com/safing/portmaster v0.7.3/go.mod h1:o//kZ8eE+5vT1V22mgnxHIAdlEz42sArsK5OF2Lf/+s= github.com/safing/portmaster v0.7.4/go.mod h1:Q93BWdF1oAL0oUMukshl8W1aPZhmrlTGi6tFTFc3pTw= github.com/safing/portmaster v0.7.6/go.mod h1:qOs9hQtvAzTVICRbwLg3vddqOaqJHeWBjWQ0C+TJ/Bw= @@ -812,8 +810,9 @@ github.com/safing/portmaster v0.7.16/go.mod h1:IueFG2XOqt74nU22I3JG1nC2MgtgEJBUA github.com/safing/portmaster v0.7.17/go.mod h1:TCWK75oZtkWv9bPyYIAILOma5G6VSK5FD3ovlZ1Ws2Q= github.com/safing/portmaster v0.7.18/go.mod h1:NXd1l1z0oKy0WfXMhv/gpAXz+pUHnlNuYPBSaMZe7uw= github.com/safing/portmaster v0.7.21/go.mod h1:Jy0G6x6m5dE36Mv9grXHI77cxysQ0fIQV1EYQ00WEiQ= -github.com/safing/portmaster v0.8.0 h1:ITsUrJ6T1FhlXItnYPx/xhgXx4Vf38aPPhTuoYvGqjs= github.com/safing/portmaster v0.8.0/go.mod h1:lY2/WvOlH8kl1AwkixdWCjlo+PZQv+oEOQhIaSS/+wA= +github.com/safing/portmaster v0.8.5-interdep h1:bCaSprkau6ec9gngRJjuvzstBWhJ55L40NdNvHhu5Gc= +github.com/safing/portmaster v0.8.5-interdep/go.mod h1:A+zAVEKjr057ktgiMSJRdUmOF+FPW8XY/5LqGnbsKbU= github.com/safing/spn v0.3.4/go.mod h1:TfzNsZCbnlWv0UFDILFOUSudVKJZlnBVoR1fDXrjOK0= github.com/safing/spn v0.3.5/go.mod h1:jHkFF2Yu1fnjFu4KXjVA+iagMr/z4eB4p3jiwikvKj8= github.com/safing/spn v0.3.6/go.mod h1:RSeFb/h5Wt3yDVezXj3lhXJ/Iwd7FbtsGf5E+p5J2YQ= @@ -826,6 +825,7 @@ github.com/safing/spn v0.3.16/go.mod h1:NMaHlnIHcTHMxxz6PuaBg0rJdYc8LhyF5N6v+Iie github.com/safing/spn v0.3.17/go.mod h1:Fq/70Hl0OUxtYuY5NATv5q468hvfDDEFwN3mivEecic= github.com/safing/spn v0.3.19/go.mod h1:phCnWjWOgdVMXaMsmDr6izR/ROVElSZGdIm7j7PIit4= github.com/safing/spn v0.4.0/go.mod h1:0jBetnYCfxqO5PJskhPOxJ/v6VRfE+bQU98XW240BNw= +github.com/safing/spn v0.4.2/go.mod h1:yZPezHDEYyhei8n13tTxjQCGq6LRr5svz9WFAAeDPec= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -928,8 +928,9 @@ github.com/tidwall/sjson v1.2.4/go.mod h1:098SZ494YoMWPmMO6ct4dcFnqxwj9r/gF0Etp1 github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= github.com/tjfoc/gmsm v1.4.1/go.mod h1:j4INPkHWMrhJb38G+J6W4Tw0AbuN8Thu3PbdVYhVcTE= github.com/tklauser/go-sysconf v0.3.4/go.mod h1:Cl2c8ZRWfHD5IrfHo9VN+FX9kCFjIOyVklgXycLB6ek= -github.com/tklauser/go-sysconf v0.3.9 h1:JeUVdAOWhhxVcU6Eqr/ATFHgXk/mmiItdKeJPev3vTo= github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= +github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= +github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1gBkr4QyP8= github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= @@ -1044,8 +1045,9 @@ golang.org/x/crypto v0.0.0-20211115234514-b4de73f9ece8/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506 h1:EuGTJDfeg/PGZJp3gq1K+14eSLFTsrj1eg8KQuiUyKg= golang.org/x/crypto v0.0.0-20220213190939-1e6e3497d506/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1160,8 +1162,9 @@ golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220121210141-e204ce36a2ba/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1311,15 +1314,14 @@ golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.0.0-20210916214954-140adaaadfaf/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1640,5 +1642,3 @@ rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=