Merge pull request #1279 from safing/fix/conn-handling-history

Fix connection handling and improve history
This commit is contained in:
Daniel Hovie
2023-08-11 12:28:59 +02:00
committed by GitHub
8 changed files with 80 additions and 18 deletions

View File

@@ -177,6 +177,15 @@ func FilterResolvedDNS(
return rrCache
}
// Finalize verdict.
defer func() {
// Reset from previous filtering.
conn.Verdict.Active = network.VerdictUndecided
conn.Verdict.Worst = network.VerdictUndecided
// Update all values again.
finalizeVerdict(conn)
}()
// special grant for connectivity domains
if checkConnectivityDomain(ctx, conn, layeredProfile, nil) {
// returns true if check triggered

View File

@@ -31,7 +31,9 @@ type deciderFn func(context.Context, *network.Connection, *profile.LayeredProfil
var defaultDeciders = []deciderFn{
checkPortmasterConnection,
checkSelfCommunication,
// TODO: This is currently very slow.
// Find a way to improve performance using the eBPF data.
// checkSelfCommunication,
checkIfBroadcastReply,
checkConnectionType,
checkConnectionScope,
@@ -619,6 +621,11 @@ matchLoop:
}
func checkCustomFilterList(_ context.Context, conn *network.Connection, p *profile.LayeredProfile, _ packet.Packet) bool {
// Check if any custom list is loaded at all.
if !customlists.IsLoaded() {
return false
}
// block if the domain name appears in the custom filter list (check for subdomains if enabled)
if conn.Entity.Domain != "" {
if ok, match := customlists.LookupDomain(conn.Entity.Domain, p.FilterSubDomains()); ok {

View File

@@ -36,6 +36,25 @@ func initFilterLists() {
domainsFilterList = make(map[string]struct{})
}
// IsLoaded returns whether a custom filter list is loaded.
func IsLoaded() bool {
filterListLock.RLock()
defer filterListLock.RUnlock()
switch {
case len(domainsFilterList) > 0:
return true
case len(ipAddressesFilterList) > 0:
return true
case len(countryCodesFilterList) > 0:
return true
case len(autonomousSystemsFilterList) > 0:
return true
default:
return false
}
}
func parseFile(filePath string) error {
// Reset all maps, previous (if any) settings will be lost.
for key := range countryCodesFilterList {

View File

@@ -127,7 +127,7 @@ func (mng *Manager) HandleFeed(ctx context.Context, feed <-chan *network.Connect
// Save to netquery database.
// Do not include internal connections in history.
if err := mng.store.Save(ctx, *model, conn.HistoryEnabled && !conn.Internal); err != nil {
if err := mng.store.Save(ctx, *model, conn.HistoryEnabled); err != nil {
log.Errorf("netquery: failed to save connection %s in sqlite database: %s", conn.ID, err)
return
}

View File

@@ -81,6 +81,11 @@ func cleanConnections() (activePIDs map[int]struct{}) {
// Step 2: mark as ended
if !exists {
conn.Ended = nowUnix
// Stop the firewall handler, in case one is running.
conn.StopFirewallHandler()
// Save to database.
conn.Save()
}
@@ -93,8 +98,6 @@ func cleanConnections() (activePIDs map[int]struct{}) {
// DEBUG:
// log.Tracef("network.clean: deleted %s (ended at %s)", conn.DatabaseKey(), time.Unix(conn.Ended, 0))
// Stop the firewall handler, in case one is running.
conn.StopFirewallHandler()
// Remove connection from state.
conn.delete()
}

View File

@@ -578,8 +578,8 @@ func (conn *Connection) SetLocalIP(ip net.IP) {
conn.LocalIPScope = netutils.GetIPScope(ip)
}
// UpdateFeatures checks which connection related features may be used and sets
// the flags accordingly.
// UpdateFeatures checks which connection related features may and should be
// used and sets the flags accordingly.
// The caller must hold a lock on the connection.
func (conn *Connection) UpdateFeatures() error {
// Get user.
@@ -591,7 +591,15 @@ func (conn *Connection) UpdateFeatures() error {
// Check if history may be used and if it is enabled for this application.
conn.HistoryEnabled = false
if user.MayUse(account.FeatureHistory) {
switch {
case conn.Internal:
// Do not record internal connections, as they are of low interest in the history.
// TODO: Should we create a setting for this?
case conn.Entity.IPScope.IsLocalhost():
// Do not record localhost-only connections, as they are very low interest in the history.
// TODO: Should we create a setting for this?
case user.MayUse(account.FeatureHistory):
// Check if history may be used and is enabled.
lProfile := conn.Process().Profile()
if lProfile != nil {
conn.HistoryEnabled = lProfile.EnableHistory()

View File

@@ -196,7 +196,7 @@ func registerConfiguration() error { //nolint:maintidx
err := config.Register(&config.Option{
Name: "Default Network Action",
Key: CfgOptionDefaultActionKey,
Description: `The default network action is applied when nothing else allows or blocks an outgoing connection. Incoming connections are always blocked by default.`,
Description: `The default network action is applied when nothing else allows or blocks a connection. This affects both outgoing and incoming connections. This setting is the weakest of all and is commonly overruled by Force Block settings or Rules.`,
OptType: config.OptTypeString,
DefaultValue: DefaultActionPermitValue,
Annotations: config.Annotations{
@@ -252,9 +252,11 @@ func registerConfiguration() error { //nolint:maintidx
// Enable History
err = config.Register(&config.Option{
Name: "Enable Network History",
Key: CfgOptionEnableHistoryKey,
Description: "Save connections in a database (on disk) in order to view and search them later. Changes might take a couple minutes to apply to all connections.",
Name: "Enable Network History",
Key: CfgOptionEnableHistoryKey,
Description: `Save connections in a database (on disk) in order to view and search them later. Changes might take a couple minutes to apply to all connections.
In order to reduce noise optimize performance, internal and device-only (localhost) connections are not saved to history.`,
OptType: config.OptTypeBool,
ReleaseLevel: config.ReleaseLevelStable,
ExpertiseLevel: config.ExpertiseLevelUser,

View File

@@ -175,8 +175,12 @@ func createSpecialProfile(profileID string, path string) *Profile {
// attributed to a connection of a regular process. Otherwise, users
// would see two connection prompts for the same domain.
CfgOptionDefaultActionKey: DefaultActionPermitValue,
// Explicitly allow incoming connections.
CfgOptionBlockInboundKey: status.SecurityLevelOff,
// Disable force blockers.
CfgOptionBlockScopeInternetKey: status.SecurityLevelOff,
CfgOptionBlockScopeLANKey: status.SecurityLevelOff,
CfgOptionBlockScopeLocalKey: status.SecurityLevelOff,
CfgOptionBlockP2PKey: status.SecurityLevelOff,
CfgOptionBlockInboundKey: status.SecurityLevelOff,
// Explicitly allow localhost and answers to multicast protocols that
// are commonly used by system resolvers.
// TODO: When the Portmaster gains the ability to attribute multicast
@@ -233,7 +237,12 @@ func createSpecialProfile(profileID string, path string) *Profile {
Source: SourceLocal,
PresentationPath: path,
Config: map[string]interface{}{
CfgOptionDefaultActionKey: DefaultActionBlockValue,
CfgOptionDefaultActionKey: DefaultActionBlockValue,
CfgOptionBlockScopeInternetKey: status.SecurityLevelOff,
CfgOptionBlockScopeLANKey: status.SecurityLevelOff,
CfgOptionBlockScopeLocalKey: status.SecurityLevelOff,
CfgOptionBlockP2PKey: status.SecurityLevelOff,
CfgOptionBlockInboundKey: status.SecurityLevelsAll,
CfgOptionEndpointsKey: []string{
"+ Localhost",
"+ .safing.io",
@@ -248,7 +257,12 @@ func createSpecialProfile(profileID string, path string) *Profile {
Source: SourceLocal,
PresentationPath: path,
Config: map[string]interface{}{
CfgOptionDefaultActionKey: DefaultActionBlockValue,
CfgOptionDefaultActionKey: DefaultActionBlockValue,
CfgOptionBlockScopeInternetKey: status.SecurityLevelOff,
CfgOptionBlockScopeLANKey: status.SecurityLevelOff,
CfgOptionBlockScopeLocalKey: status.SecurityLevelOff,
CfgOptionBlockP2PKey: status.SecurityLevelOff,
CfgOptionBlockInboundKey: status.SecurityLevelsAll,
CfgOptionEndpointsKey: []string{
"+ Localhost",
},
@@ -281,11 +295,11 @@ func specialProfileNeedsReset(profile *Profile) bool {
switch profile.ID {
case SystemResolverProfileID:
return canBeUpgraded(profile, "21.10.2022")
return canBeUpgraded(profile, "12.8.2023") // FIXME: set one day after stable release date.
case PortmasterProfileID:
return canBeUpgraded(profile, "21.10.2022")
return canBeUpgraded(profile, "12.8.2023") // FIXME: set one day after stable release date.
case PortmasterAppProfileID:
return canBeUpgraded(profile, "8.9.2021")
return canBeUpgraded(profile, "12.8.2023") // FIXME: set one day after stable release date.
default:
// Not a special profile or no upgrade available yet.
return false