Add CNAME blocking support

This commit is contained in:
Patrick Pacher
2020-04-17 15:55:52 +02:00
parent 1f90c05654
commit bffe4a9eaf
9 changed files with 445 additions and 136 deletions

View File

@@ -30,6 +30,9 @@ var (
CfgOptionFilterSubDomainsKey = "filter/includeSubdomains"
cfgOptionFilterSubDomains config.IntOption // security level option
CfgOptionFilterCNAMEKey = "filter/includeCNAMEs"
cfgOptionFilterCNAME config.IntOption // security level option
CfgOptionBlockScopeLocalKey = "filter/blockLocal"
cfgOptionBlockScopeLocal config.IntOption // security level option
@@ -180,6 +183,23 @@ Examples:
cfgOptionFilterLists = config.Concurrent.GetAsStringArray(CfgOptionFilterListKey, []string{})
cfgStringArrayOptions[CfgOptionFilterListKey] = cfgOptionFilterLists
// Include CNAMEs
err = config.Register(&config.Option{
Name: "Filter CNAMEs",
Key: CfgOptionFilterCNAMEKey,
Description: "Also filter requests where a CNAME would be blocked",
OptType: config.OptTypeInt,
ExternalOptType: "security level",
DefaultValue: status.SecurityLevelsAll,
ValidationRegex: "^(7|6|4)$",
})
if err != nil {
return err
}
cfgOptionFilterCNAME = config.Concurrent.GetAsInt(CfgOptionFilterCNAMEKey, int64(status.SecurityLevelsAll))
cfgIntOptions[CfgOptionFilterCNAMEKey] = cfgOptionFilterCNAME
// Include subdomains
err = config.Register(&config.Option{
Name: "Filter SubDomains",
Key: CfgOptionFilterSubDomainsKey,

View File

@@ -31,35 +31,77 @@ type EndpointDomain struct {
Reason string
}
func (ep *EndpointDomain) check(entity *intel.Entity, domain string) (EPResult, string) {
switch ep.MatchType {
case domainMatchTypeExact:
if domain == ep.Domain {
return ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeZone:
if domain == ep.Domain {
return ep.matchesPPP(entity), ep.Reason
}
if strings.HasSuffix(domain, ep.DomainZone) {
return ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeSuffix:
if strings.HasSuffix(domain, ep.Domain) {
return ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypePrefix:
if strings.HasPrefix(domain, ep.Domain) {
return ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeContains:
if strings.Contains(domain, ep.Domain) {
return ep.matchesPPP(entity), ep.Reason
}
}
return NoMatch, ""
}
// Matches checks whether the given entity matches this endpoint definition.
func (ep *EndpointDomain) Matches(entity *intel.Entity) (result EPResult, reason string) {
if entity.Domain == "" {
return NoMatch, ""
}
switch ep.MatchType {
case domainMatchTypeExact:
if entity.Domain == ep.Domain {
return ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeZone:
if entity.Domain == ep.Domain {
return ep.matchesPPP(entity), ep.Reason
}
if strings.HasSuffix(entity.Domain, ep.DomainZone) {
return ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeSuffix:
if strings.HasSuffix(entity.Domain, ep.Domain) {
return ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypePrefix:
if strings.HasPrefix(entity.Domain, ep.Domain) {
return ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeContains:
if strings.Contains(entity.Domain, ep.Domain) {
return ep.matchesPPP(entity), ep.Reason
result, reason = ep.check(entity, entity.Domain)
if result != NoMatch {
return
}
if entity.CNAMECheckEnabled() {
for _, domain := range entity.CNAME {
switch ep.MatchType {
case domainMatchTypeExact:
if domain == ep.Domain {
result, reason = ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeZone:
if domain == ep.Domain {
result, reason = ep.matchesPPP(entity), ep.Reason
}
if strings.HasSuffix(domain, ep.DomainZone) {
result, reason = ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeSuffix:
if strings.HasSuffix(domain, ep.Domain) {
result, reason = ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypePrefix:
if strings.HasPrefix(domain, ep.Domain) {
result, reason = ep.matchesPPP(entity), ep.Reason
}
case domainMatchTypeContains:
if strings.Contains(domain, ep.Domain) {
result, reason = ep.matchesPPP(entity), ep.Reason
}
}
if result == Denied {
return result, reason
}
}
}

View File

@@ -43,6 +43,7 @@ type LayeredProfile struct {
RemoveOutOfScopeDNS config.BoolOption
RemoveBlockedDNS config.BoolOption
FilterSubDomains config.BoolOption
FilterCNAMEs config.BoolOption
PreventBypassing config.BoolOption
}
@@ -99,6 +100,10 @@ func NewLayeredProfile(localProfile *Profile) *LayeredProfile {
CfgOptionFilterSubDomainsKey,
cfgOptionFilterSubDomains,
)
new.FilterCNAMEs = new.wrapSecurityLevelOption(
CfgOptionFilterCNAMEKey,
cfgOptionFilterCNAME,
)
new.PreventBypassing = new.wrapSecurityLevelOption(
CfgOptionPreventBypassingKey,
cfgOptionPreventBypassing,
@@ -236,6 +241,7 @@ func (lp *LayeredProfile) MatchServiceEndpoint(entity *intel.Entity) (result end
// lists.
func (lp *LayeredProfile) MatchFilterLists(entity *intel.Entity) (endpoints.EPResult, string) {
entity.ResolveSubDomainLists(lp.FilterSubDomains())
entity.EnableCNAMECheck(lp.FilterCNAMEs())
lookupMap, hasLists := entity.GetListsMap()
if !hasLists {