diff --git a/profile/config-update.go b/profile/config-update.go index 1e73d4fe..3a6cd246 100644 --- a/profile/config-update.go +++ b/profile/config-update.go @@ -14,12 +14,13 @@ import ( var ( cfgLock sync.RWMutex - cfgDefaultAction uint8 - cfgEndpoints endpoints.Endpoints - cfgServiceEndpoints endpoints.Endpoints - cfgSPNUsagePolicy endpoints.Endpoints - cfgSPNExitHubPolicy endpoints.Endpoints - cfgFilterLists []string + cfgDefaultAction uint8 + cfgEndpoints endpoints.Endpoints + cfgServiceEndpoints endpoints.Endpoints + cfgSPNUsagePolicy endpoints.Endpoints + cfgSPNTransitHubPolicy endpoints.Endpoints + cfgSPNExitHubPolicy endpoints.Endpoints + cfgFilterLists []string ) func registerConfigUpdater() error { @@ -83,6 +84,13 @@ func updateGlobalConfigProfile(ctx context.Context, task *modules.Task) error { lastErr = err } + list = cfgOptionTransitHubPolicy() + cfgSPNTransitHubPolicy, err = endpoints.ParseEndpoints(list) + if err != nil { + // TODO: module error? + lastErr = err + } + list = cfgOptionExitHubPolicy() cfgSPNExitHubPolicy, err = endpoints.ParseEndpoints(list) if err != nil { diff --git a/profile/config.go b/profile/config.go index 624605d5..782d4673 100644 --- a/profile/config.go +++ b/profile/config.go @@ -132,11 +132,15 @@ var ( // Setting "Home Node Rules" at order 145. + CfgOptionTransitHubPolicyKey = "spn/transitHubPolicy" + cfgOptionTransitHubPolicy config.StringArrayOption + cfgOptionTransitHubPolicyOrder = 146 + CfgOptionExitHubPolicyKey = "spn/exitHubPolicy" cfgOptionExitHubPolicy config.StringArrayOption - cfgOptionExitHubPolicyOrder = 146 + cfgOptionExitHubPolicyOrder = 147 - // Setting "DNS Exit Node Rules" at order 147. + // Setting "DNS Exit Node Rules" at order 148. ) // A list of all security level settings. @@ -720,6 +724,34 @@ Please note that if you are using the system resolver, bypass attempts might be cfgOptionSPNUsagePolicy = config.Concurrent.GetAsStringArray(CfgOptionSPNUsagePolicyKey, []string{}) cfgStringArrayOptions[CfgOptionSPNUsagePolicyKey] = cfgOptionSPNUsagePolicy + // Transit Node Rules + err = config.Register(&config.Option{ + Name: "Transit Node Rules", + Key: CfgOptionTransitHubPolicyKey, + Description: `Customize which countries should or should not be used as Transit Nodes. Transit Nodes are used to transit the SPN from your Home to your Exit Node.`, + Help: SPNRulesHelp, + Sensitive: true, + OptType: config.OptTypeStringArray, + ExpertiseLevel: config.ExpertiseLevelExpert, + ReleaseLevel: config.ReleaseLevelBeta, + DefaultValue: []string{}, + Annotations: config.Annotations{ + config.StackableAnnotation: true, + config.CategoryAnnotation: "Routing", + config.DisplayOrderAnnotation: cfgOptionTransitHubPolicyOrder, + config.DisplayHintAnnotation: endpoints.DisplayHintEndpointList, + config.QuickSettingsAnnotation: SPNRulesQuickSettings, + endpoints.EndpointListVerdictNamesAnnotation: SPNRulesVerdictNames, + }, + ValidationRegex: endpoints.ListEntryValidationRegex, + ValidationFunc: endpoints.ValidateEndpointListConfigOption, + }) + if err != nil { + return err + } + cfgOptionTransitHubPolicy = config.Concurrent.GetAsStringArray(CfgOptionTransitHubPolicyKey, []string{}) + cfgStringArrayOptions[CfgOptionTransitHubPolicyKey] = cfgOptionTransitHubPolicy + // Exit Node Rules err = config.Register(&config.Option{ Name: "Exit Node Rules", diff --git a/profile/profile-layered.go b/profile/profile-layered.go index 1310f15c..6ed2ad92 100644 --- a/profile/profile-layered.go +++ b/profile/profile-layered.go @@ -382,6 +382,23 @@ func (lp *LayeredProfile) MatchSPNUsagePolicy(ctx context.Context, entity *intel return cfgSPNUsagePolicy.Match(ctx, entity) } +// StackedTransitHubPolicies returns all transit hub policies of the layered profile, including the global one. +func (lp *LayeredProfile) StackedTransitHubPolicies() []endpoints.Endpoints { + policies := make([]endpoints.Endpoints, 0, len(lp.layers)+3) // +1 for global policy, +2 for intel policies + + for _, layer := range lp.layers { + if layer.spnTransitHubPolicy.IsSet() { + policies = append(policies, layer.spnTransitHubPolicy) + } + } + + cfgLock.RLock() + defer cfgLock.RUnlock() + policies = append(policies, cfgSPNTransitHubPolicy) + + return policies +} + // StackedExitHubPolicies returns all exit hub policies of the layered profile, including the global one. func (lp *LayeredProfile) StackedExitHubPolicies() []endpoints.Endpoints { policies := make([]endpoints.Endpoints, 0, len(lp.layers)+3) // +1 for global policy, +2 for intel policies diff --git a/profile/profile.go b/profile/profile.go index 1fa12ff8..1838e534 100644 --- a/profile/profile.go +++ b/profile/profile.go @@ -127,15 +127,16 @@ type Profile struct { //nolint:maligned // not worth the effort layeredProfile *LayeredProfile // Interpreted Data - configPerspective *config.Perspective - dataParsed bool - defaultAction uint8 - endpoints endpoints.Endpoints - serviceEndpoints endpoints.Endpoints - filterListsSet bool - filterListIDs []string - spnUsagePolicy endpoints.Endpoints - spnExitHubPolicy endpoints.Endpoints + configPerspective *config.Perspective + dataParsed bool + defaultAction uint8 + endpoints endpoints.Endpoints + serviceEndpoints endpoints.Endpoints + filterListsSet bool + filterListIDs []string + spnUsagePolicy endpoints.Endpoints + spnTransitHubPolicy endpoints.Endpoints + spnExitHubPolicy endpoints.Endpoints // Lifecycle Management outdated *abool.AtomicBool @@ -224,6 +225,15 @@ func (profile *Profile) parseConfig() error { } } + list, ok = profile.configPerspective.GetAsStringArray(CfgOptionTransitHubPolicyKey) + profile.spnTransitHubPolicy = nil + if ok { + profile.spnTransitHubPolicy, err = endpoints.ParseEndpoints(list) + if err != nil { + lastErr = err + } + } + list, ok = profile.configPerspective.GetAsStringArray(CfgOptionExitHubPolicyKey) profile.spnExitHubPolicy = nil if ok {