better user messages, linter errors, refactoring

This commit is contained in:
Vladimir Stoilov
2022-08-01 11:24:48 +02:00
committed by Daniel
parent a3c39b183e
commit d3def3ec94
6 changed files with 49 additions and 59 deletions

View File

@@ -619,7 +619,7 @@ func checkCustomFilterList(_ context.Context, conn *network.Connection, p *profi
// block if the domain name appears in the custom filter list (check for subdomains if enabled) // block if the domain name appears in the custom filter list (check for subdomains if enabled)
if conn.Entity.Domain != "" { if conn.Entity.Domain != "" {
if ok, match := customlists.LookupDomain(conn.Entity.Domain, p.FilterSubDomains()); ok { if ok, match := customlists.LookupDomain(conn.Entity.Domain, p.FilterSubDomains()); ok {
conn.Deny(fmt.Sprintf("domain %s matched %s in custom filter list", conn.Entity.Domain, match), customlists.CfgOptionCustomListBlockingKey) conn.Deny(fmt.Sprintf("domain %s matches %s in custom filter list", conn.Entity.Domain, match), customlists.CfgOptionCustomListBlockingKey)
return true return true
} }
} }
@@ -628,7 +628,7 @@ func checkCustomFilterList(_ context.Context, conn *network.Connection, p *profi
if p.FilterCNAMEs() { if p.FilterCNAMEs() {
for _, cname := range conn.Entity.CNAME { for _, cname := range conn.Entity.CNAME {
if ok, match := customlists.LookupDomain(cname, p.FilterSubDomains()); ok { if ok, match := customlists.LookupDomain(cname, p.FilterSubDomains()); ok {
conn.Deny(fmt.Sprintf("domain alias (CNAME) %s matched %s in custom filter list", cname, match), customlists.CfgOptionCustomListBlockingKey) conn.Deny(fmt.Sprintf("domain alias (CNAME) %s matches %s in custom filter list", cname, match), customlists.CfgOptionCustomListBlockingKey)
return true return true
} }
} }
@@ -637,7 +637,7 @@ func checkCustomFilterList(_ context.Context, conn *network.Connection, p *profi
// block if ip addresses appears in the custom filter list // block if ip addresses appears in the custom filter list
if conn.Entity.IP != nil { if conn.Entity.IP != nil {
if customlists.LookupIP(conn.Entity.IP) { if customlists.LookupIP(conn.Entity.IP) {
conn.Deny(fmt.Sprintf("IP address %s appears in the custom filter list", conn.Entity.IP), customlists.CfgOptionCustomListBlockingKey) conn.Deny("IP address is in the custom filter list", customlists.CfgOptionCustomListBlockingKey)
return true return true
} }
} }
@@ -645,7 +645,7 @@ func checkCustomFilterList(_ context.Context, conn *network.Connection, p *profi
// block autonomous system by its number if it appears in the custom filter list // block autonomous system by its number if it appears in the custom filter list
if conn.Entity.ASN != 0 { if conn.Entity.ASN != 0 {
if customlists.LookupASN(conn.Entity.ASN) { if customlists.LookupASN(conn.Entity.ASN) {
conn.Deny(fmt.Sprintf("autonomous system with number %d appears in the custom filter list", conn.Entity.ASN), customlists.CfgOptionCustomListBlockingKey) conn.Deny("AS is in the custom filter list", customlists.CfgOptionCustomListBlockingKey)
return true return true
} }
} }
@@ -653,7 +653,7 @@ func checkCustomFilterList(_ context.Context, conn *network.Connection, p *profi
// block if the country appears in the custom filter list // block if the country appears in the custom filter list
if conn.Entity.Country != "" { if conn.Entity.Country != "" {
if customlists.LookupCountry(conn.Entity.Country) { if customlists.LookupCountry(conn.Entity.Country) {
conn.Deny(fmt.Sprintf("country code %s appears in the custom filter list", conn.Entity.Country), customlists.CfgOptionCustomListBlockingKey) conn.Deny("country is in the custom filter list", customlists.CfgOptionCustomListBlockingKey)
return true return true
} }
} }

2
go.mod
View File

@@ -14,7 +14,7 @@ require (
github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/go-version v1.6.0
github.com/miekg/dns v1.1.50 github.com/miekg/dns v1.1.50
github.com/oschwald/maxminddb-golang v1.9.0 github.com/oschwald/maxminddb-golang v1.9.0
github.com/safing/portbase v0.14.5 github.com/safing/portbase v0.14.6
github.com/safing/spn v0.4.13 github.com/safing/spn v0.4.13
github.com/shirou/gopsutil v3.21.11+incompatible github.com/shirou/gopsutil v3.21.11+incompatible
github.com/spf13/cobra v1.5.0 github.com/spf13/cobra v1.5.0

2
go.sum
View File

@@ -831,6 +831,8 @@ github.com/safing/portbase v0.14.3/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6X
github.com/safing/portbase v0.14.4/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6XBBtN3bDI= github.com/safing/portbase v0.14.4/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6XBBtN3bDI=
github.com/safing/portbase v0.14.5 h1:+8H+mQ7AFjA04M7UPq0490pj3/+nvJj3pEUP1PYTMYc= github.com/safing/portbase v0.14.5 h1:+8H+mQ7AFjA04M7UPq0490pj3/+nvJj3pEUP1PYTMYc=
github.com/safing/portbase v0.14.5/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6XBBtN3bDI= github.com/safing/portbase v0.14.5/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6XBBtN3bDI=
github.com/safing/portbase v0.14.6 h1:AKj1TVJmqOrjXXWcPetchQhHVBwfD3/QDvgmkUj2FxY=
github.com/safing/portbase v0.14.6/go.mod h1:hC6KV9oZsD7yuAom42L5wgOEZ0yAjr2i1r2F5duBSA8=
github.com/safing/portmaster v0.7.3/go.mod h1:o//kZ8eE+5vT1V22mgnxHIAdlEz42sArsK5OF2Lf/+s= 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.4/go.mod h1:Q93BWdF1oAL0oUMukshl8W1aPZhmrlTGi6tFTFc3pTw=
github.com/safing/portmaster v0.7.6/go.mod h1:qOs9hQtvAzTVICRbwLg3vddqOaqJHeWBjWQ0C+TJ/Bw= github.com/safing/portmaster v0.7.6/go.mod h1:qOs9hQtvAzTVICRbwLg3vddqOaqJHeWBjWQ0C+TJ/Bw=

View File

@@ -14,34 +14,25 @@ var (
var getFilePath config.StringOption var getFilePath config.StringOption
func registerConfig() error { func registerConfig() error {
help := `The file should contain list of all domains, Ip addresses, country codes and autonomous system that you want to block, where each entry is on a new line. help := `The file is checked every couple minutes and will be automatically reloaded when it has changed.
Lines that start with a '#' symbol are ignored.
Everything after the first space/tab is ignored. Entries may be one of:
Example: - Domain: "example.com"
############# - IP Address: "10.0.0.1"
\# Domains: - Country Code (based on IP): "US"
example.com - AS (Autonomous System): "AS1234"
google.com
Everything after the first element of a line, comments starting with a '#', and empty lines are ignored.
\# IP addresses The settings "Block Subdomains of Filter List Entries" and "Block Domain Aliases" also apply to the custom filter list.
1.2.3.4 Lists in the "Hosts" format are not supported.
4.3.2.1
Please note that the custom filter list is fully loaded into memory. This can have a negative impact on your device if big lists are loaded.`
\# Countries
AU
BG
\# Autonomous Systems
AS123
#############
> * All the records are stored in RAM, careful with large block lists.
> * Hosts files are not supported.`
// register a setting for the file path in the ui // register a setting for the file path in the ui
err := config.Register(&config.Option{ err := config.Register(&config.Option{
Name: "Custom Filter List", Name: "Custom Filter List",
Key: CfgOptionCustomListBlockingKey, Key: CfgOptionCustomListBlockingKey,
Description: "Path to the file that contains a list of Domain, IP addresses, country codes and autonomous systems that you want to block", Description: "Specify the file path to a custom filter list, which will be automatically refreshed. Any connections matching a domain, IP address, Country or ASN in the file will be blocked.",
Help: help, Help: help,
OptType: config.OptTypeString, OptType: config.OptTypeString,
ExpertiseLevel: config.ExpertiseLevelExpert, ExpertiseLevel: config.ExpertiseLevelExpert,

View File

@@ -2,7 +2,6 @@ package customlists
import ( import (
"bufio" "bufio"
"bytes"
"fmt" "fmt"
"net" "net"
"os" "os"
@@ -10,7 +9,7 @@ import (
"strings" "strings"
"github.com/miekg/dns" "github.com/miekg/dns"
"github.com/safing/portbase/log" "github.com/safing/portbase/log" //nolint // weird error "Expected '\n', Found '\t'"
"github.com/safing/portbase/notifications" "github.com/safing/portbase/notifications"
"github.com/safing/portmaster/network/netutils" "github.com/safing/portmaster/network/netutils"
) )
@@ -25,6 +24,7 @@ var (
const ( const (
rationForInvalidLinesUntilWarning = 0.1 rationForInvalidLinesUntilWarning = 0.1
parseStatusNotificationID = "customlists:parse-status" parseStatusNotificationID = "customlists:parse-status"
parseWarningNotificationID = "customlists:parse-warning"
zeroIPNotificationID = "customlists:too-many-zero-ips" zeroIPNotificationID = "customlists:too-many-zero-ips"
) )
@@ -58,8 +58,8 @@ func parseFile(filePath string) error {
// open the file if possible // open the file if possible
file, err := os.Open(filePath) file, err := os.Open(filePath)
if err != nil { if err != nil {
log.Warningf("intel/customlists: failed to parse file %q ", err) log.Warningf("intel/customlists: failed to parse file %s", err)
module.Warning(parseStatusNotificationID, "Failed to open custom filter list", err.Error()) module.Warning(parseWarningNotificationID, "Failed to open custom filter list", err.Error())
return err return err
} }
defer func() { _ = file.Close() }() defer func() { _ = file.Close() }()
@@ -83,33 +83,34 @@ func parseFile(filePath string) error {
return err return err
} }
var invalidLinesRation float32 = float32(invalidLinesCount) / float32(allLinesCount) invalidLinesRation := float32(invalidLinesCount) / float32(allLinesCount)
if invalidLinesRation > rationForInvalidLinesUntilWarning { if invalidLinesRation > rationForInvalidLinesUntilWarning {
log.Warning("intel/customlists: Too many invalid lines") log.Warning("intel/customlists: Too many invalid lines")
module.Warning(zeroIPNotificationID, "Check your custom filter list, there is too many invalid lines", module.Warning(zeroIPNotificationID, "Custom filter list has many invalid entries",
fmt.Sprintf(`There are %d from total %d lines that we flagged as invalid. fmt.Sprintf(`%d out of %d entires are invalid.
Check if you are using the correct file format or if the path to the custom filter list is correct.`, invalidLinesCount, allLinesCount)) Check if you are using the correct file format and if the path to the custom filter list is correct.`, invalidLinesCount, allLinesCount))
} else { } else {
module.Resolve(zeroIPNotificationID) module.Resolve(zeroIPNotificationID)
} }
log.Infof("intel/customlists: list loaded successful: %s", filePath) allEntriesCount := len(domainsFilterList) + len(ipAddressesFilterList) + len(autonomousSystemsFilterList) + len(countryCodesFilterList)
log.Infof("intel/customlists: loaded %d entries from %s", allEntriesCount, filePath)
notifications.NotifyInfo(parseStatusNotificationID, notifications.NotifyInfo(parseStatusNotificationID,
"Custom filter list loaded successfully.", "Custom filter list loaded successfully.",
fmt.Sprintf(`Custom filter list loaded successfully from file %s fmt.Sprintf(`Custom filter list loaded successfully from file %s - loaded:
%d domains %d Domains
%d IPs %d IPs
%d autonomous systems %d Autonomous Systems
%d countries`, %d Countries`,
filePath, filePath,
len(domainsFilterList), len(domainsFilterList),
len(ipAddressesFilterList), len(ipAddressesFilterList),
len(autonomousSystemsFilterList), len(autonomousSystemsFilterList),
len(domainsFilterList))) len(countryCodesFilterList)))
module.Resolve(parseStatusNotificationID) module.Resolve(parseWarningNotificationID)
return nil return nil
} }
@@ -140,7 +141,7 @@ func parseLine(line string) bool {
ip := net.ParseIP(field) ip := net.ParseIP(field)
if ip != nil { if ip != nil {
// check for zero ip. // check for zero ip.
if bytes.Compare(ip, net.IPv4zero) == 0 || bytes.Compare(ip, net.IPv6zero) == 0 { if net.IP.Equal(ip, net.IPv4zero) || net.IP.Equal(ip, net.IPv6zero) {
return false return false
} }

View File

@@ -9,7 +9,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/safing/portbase/api" "github.com/safing/portbase/api" //nolint // completing about import order!?
"github.com/safing/portbase/modules" "github.com/safing/portbase/modules"
"golang.org/x/net/publicsuffix" "golang.org/x/net/publicsuffix"
) )
@@ -58,7 +58,7 @@ func start() error {
configChangeEvent, configChangeEvent,
"update custom filter list", "update custom filter list",
func(ctx context.Context, obj interface{}) error { func(ctx context.Context, obj interface{}) error {
_ = checkAndUpdateFilterList() checkAndUpdateFilterList()
return nil return nil
}, },
); err != nil { ); err != nil {
@@ -67,24 +67,21 @@ func start() error {
// create parser task and enqueue for execution. "checkAndUpdateFilterList" will schedule the next execution. // create parser task and enqueue for execution. "checkAndUpdateFilterList" will schedule the next execution.
parserTask = module.NewTask("intel/customlists:file-update-check", func(context.Context, *modules.Task) error { parserTask = module.NewTask("intel/customlists:file-update-check", func(context.Context, *modules.Task) error {
_ = checkAndUpdateFilterList() checkAndUpdateFilterList()
return nil return nil
}).Schedule(time.Now().Add(20 * time.Second)) }).Schedule(time.Now().Add(20 * time.Second))
// register api endpoint for updating the filter list // register api endpoint for updating the filter list
if err := api.RegisterEndpoint(api.Endpoint{ if err := api.RegisterEndpoint(api.Endpoint{
Path: "customlists/update", Path: "customlists/update",
Read: api.PermitUser, Write: api.PermitUser,
BelongsTo: module, BelongsTo: module,
ActionFunc: func(ar *api.Request) (msg string, err error) { ActionFunc: func(ar *api.Request) (msg string, err error) {
err = checkAndUpdateFilterList() checkAndUpdateFilterList()
if err != nil { return "Custom filter list loaded successfully.", nil
return "failed to load custom filter list.", err
}
return "custom filter list loaded successfully.", nil
}, },
Name: "Update custom filter list", Name: "Update custom filter list",
Description: "Load a filter list form a file defined by the user.", Description: "Reload the filter list from the configured file.",
}); err != nil { }); err != nil {
return err return err
} }
@@ -92,14 +89,14 @@ func start() error {
return nil return nil
} }
func checkAndUpdateFilterList() error { func checkAndUpdateFilterList() {
filterListLock.Lock() filterListLock.Lock()
defer filterListLock.Unlock() defer filterListLock.Unlock()
// get path and ignore if empty // get path and ignore if empty
filePath := getFilePath() filePath := getFilePath()
if filePath == "" { if filePath == "" {
return nil return
} }
// schedule next update check // schedule next update check
@@ -115,12 +112,11 @@ func checkAndUpdateFilterList() error {
if filterListFilePath != filePath || !filterListFileModifiedTime.Equal(modifiedTime) { if filterListFilePath != filePath || !filterListFileModifiedTime.Equal(modifiedTime) {
err := parseFile(filePath) err := parseFile(filePath)
if err != nil { if err != nil {
return nil return
} }
filterListFileModifiedTime = modifiedTime filterListFileModifiedTime = modifiedTime
filterListFilePath = filePath filterListFilePath = filePath
} }
return nil
} }
// LookupIP checks if the IP address is in a custom filter list. // LookupIP checks if the IP address is in a custom filter list.