mirror of
https://github.com/safing/portmaster
synced 2025-09-02 10:39:22 +00:00
Revamped verdict handling
This commit is contained in:
parent
f2839c274a
commit
923ce2aa24
13 changed files with 55 additions and 154 deletions
|
@ -177,15 +177,6 @@ func FilterResolvedDNS(
|
||||||
return rrCache
|
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
|
// special grant for connectivity domains
|
||||||
if checkConnectivityDomain(ctx, conn, layeredProfile, nil) {
|
if checkConnectivityDomain(ctx, conn, layeredProfile, nil) {
|
||||||
// returns true if check triggered
|
// returns true if check triggered
|
||||||
|
@ -197,7 +188,7 @@ func FilterResolvedDNS(
|
||||||
|
|
||||||
// Filter dns records and return if the query is blocked.
|
// Filter dns records and return if the query is blocked.
|
||||||
rrCache = filterDNSResponse(ctx, conn, layeredProfile, rrCache, sysResolver)
|
rrCache = filterDNSResponse(ctx, conn, layeredProfile, rrCache, sysResolver)
|
||||||
if conn.Verdict.Active == network.VerdictBlock {
|
if conn.Verdict == network.VerdictBlock {
|
||||||
return rrCache
|
return rrCache
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ func RunInspectors(conn *network.Connection, pkt packet.Packet) (network.Verdict
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the active verdict is already past the inspection criteria.
|
// check if the active verdict is already past the inspection criteria.
|
||||||
if conn.Verdict.Active > inspectVerdicts[key] {
|
if conn.Verdict > inspectVerdicts[key] {
|
||||||
activeInspectors[key] = true
|
activeInspectors[key] = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -86,11 +86,11 @@ func RunInspectors(conn *network.Connection, pkt packet.Packet) (network.Verdict
|
||||||
continueInspection = true
|
continueInspection = true
|
||||||
case BLOCK_CONN:
|
case BLOCK_CONN:
|
||||||
conn.SetVerdict(network.VerdictBlock, "", "", nil)
|
conn.SetVerdict(network.VerdictBlock, "", "", nil)
|
||||||
verdict = conn.Verdict.Active
|
verdict = conn.Verdict
|
||||||
activeInspectors[key] = true
|
activeInspectors[key] = true
|
||||||
case DROP_CONN:
|
case DROP_CONN:
|
||||||
conn.SetVerdict(network.VerdictDrop, "", "", nil)
|
conn.SetVerdict(network.VerdictDrop, "", "", nil)
|
||||||
verdict = conn.Verdict.Active
|
verdict = conn.Verdict
|
||||||
activeInspectors[key] = true
|
activeInspectors[key] = true
|
||||||
case STOP_INSPECTING:
|
case STOP_INSPECTING:
|
||||||
activeInspectors[key] = true
|
activeInspectors[key] = true
|
||||||
|
|
|
@ -254,7 +254,7 @@ func UpdateVerdict(conn *network.Connection) error {
|
||||||
localPort: conn.LocalPort,
|
localPort: conn.LocalPort,
|
||||||
remoteIP: ipAddressToArray(conn.Entity.IP, isIpv6 == 1),
|
remoteIP: ipAddressToArray(conn.Entity.IP, isIpv6 == 1),
|
||||||
remotePort: conn.Entity.Port,
|
remotePort: conn.Entity.Port,
|
||||||
verdict: uint8(conn.Verdict.Active),
|
verdict: uint8(conn.Verdict),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make driver request
|
// Make driver request
|
||||||
|
|
|
@ -103,7 +103,7 @@ func decideOnConnection(ctx context.Context, conn *network.Connection, pkt packe
|
||||||
case profile.DefaultActionAsk:
|
case profile.DefaultActionAsk:
|
||||||
// Only prompt if there has not been a decision already.
|
// Only prompt if there has not been a decision already.
|
||||||
// This prevents prompts from being created when re-evaluating connections.
|
// This prevents prompts from being created when re-evaluating connections.
|
||||||
if conn.Verdict.Firewall == network.VerdictUndecided {
|
if conn.Verdict == network.VerdictUndecided {
|
||||||
prompt(ctx, conn)
|
prompt(ctx, conn)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"github.com/safing/portmaster/network"
|
"github.com/safing/portmaster/network"
|
||||||
"github.com/safing/portmaster/network/netutils"
|
"github.com/safing/portmaster/network/netutils"
|
||||||
"github.com/safing/portmaster/network/packet"
|
"github.com/safing/portmaster/network/packet"
|
||||||
"github.com/safing/portmaster/network/reference"
|
|
||||||
"github.com/safing/portmaster/process"
|
"github.com/safing/portmaster/process"
|
||||||
"github.com/safing/spn/access"
|
"github.com/safing/spn/access"
|
||||||
)
|
)
|
||||||
|
@ -132,13 +131,13 @@ func resetConnectionVerdict(ctx context.Context, conn *network.Connection) (verd
|
||||||
}
|
}
|
||||||
|
|
||||||
tracer.Debugf("filter: re-evaluating verdict of %s", conn)
|
tracer.Debugf("filter: re-evaluating verdict of %s", conn)
|
||||||
previousVerdict := conn.Verdict.Firewall
|
previousVerdict := conn.Verdict
|
||||||
|
|
||||||
// Apply privacy filter and check tunneling.
|
// Apply privacy filter and check tunneling.
|
||||||
FilterConnection(ctx, conn, nil, true, true)
|
FilterConnection(ctx, conn, nil, true, true)
|
||||||
|
|
||||||
// Stop existing SPN tunnel if not needed anymore.
|
// Stop existing SPN tunnel if not needed anymore.
|
||||||
if conn.Verdict.Active != network.VerdictRerouteToTunnel && conn.TunnelContext != nil {
|
if conn.Verdict != network.VerdictRerouteToTunnel && conn.TunnelContext != nil {
|
||||||
err := conn.TunnelContext.StopTunnel()
|
err := conn.TunnelContext.StopTunnel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tracer.Debugf("filter: failed to stopped unneeded tunnel: %s", err)
|
tracer.Debugf("filter: failed to stopped unneeded tunnel: %s", err)
|
||||||
|
@ -146,7 +145,11 @@ func resetConnectionVerdict(ctx context.Context, conn *network.Connection) (verd
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save if verdict changed.
|
// Save if verdict changed.
|
||||||
if conn.Verdict.Firewall != previousVerdict {
|
if conn.Verdict != previousVerdict {
|
||||||
|
err := interception.UpdateVerdictOfConnection(conn)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("filter: failed to update connection verdict: %s", err)
|
||||||
|
}
|
||||||
conn.Save()
|
conn.Save()
|
||||||
tracer.Infof("filter: verdict of connection %s changed from %s to %s", conn, previousVerdict.Verb(), conn.VerdictVerb())
|
tracer.Infof("filter: verdict of connection %s changed from %s to %s", conn, previousVerdict.Verb(), conn.VerdictVerb())
|
||||||
|
|
||||||
|
@ -368,16 +371,17 @@ func fastTrackHandler(conn *network.Connection, pkt packet.Packet) {
|
||||||
fastTrackedVerdict, permanent := fastTrackedPermit(conn, pkt)
|
fastTrackedVerdict, permanent := fastTrackedPermit(conn, pkt)
|
||||||
if fastTrackedVerdict != network.VerdictUndecided {
|
if fastTrackedVerdict != network.VerdictUndecided {
|
||||||
// Set verdict on connection.
|
// Set verdict on connection.
|
||||||
conn.Verdict.Active = fastTrackedVerdict
|
conn.Verdict = fastTrackedVerdict
|
||||||
conn.Verdict.Firewall = fastTrackedVerdict
|
|
||||||
// Apply verdict to (real) packet.
|
// Apply verdict to (real) packet.
|
||||||
if !pkt.InfoOnly() {
|
if !pkt.InfoOnly() {
|
||||||
issueVerdict(conn, pkt, fastTrackedVerdict, permanent)
|
issueVerdict(conn, pkt, fastTrackedVerdict, permanent)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop handler if permanent.
|
// Stop handler if permanent.
|
||||||
if permanent {
|
if permanent {
|
||||||
conn.SetVerdict(fastTrackedVerdict, "fast-tracked", "", nil)
|
conn.SetVerdict(fastTrackedVerdict, "fast-tracked", "", nil)
|
||||||
conn.Verdict.Worst = fastTrackedVerdict
|
|
||||||
// Do not finalize verdict, as we are missing necessary data.
|
// Do not finalize verdict, as we are missing necessary data.
|
||||||
conn.StopFirewallHandler()
|
conn.StopFirewallHandler()
|
||||||
}
|
}
|
||||||
|
@ -447,7 +451,7 @@ func filterHandler(conn *network.Connection, pkt packet.Packet) {
|
||||||
|
|
||||||
// End directly, as no other processing is necessary.
|
// End directly, as no other processing is necessary.
|
||||||
conn.StopFirewallHandler()
|
conn.StopFirewallHandler()
|
||||||
finalizeVerdict(conn)
|
|
||||||
issueVerdict(conn, pkt, 0, true)
|
issueVerdict(conn, pkt, 0, true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -504,19 +508,17 @@ func FilterConnection(ctx context.Context, conn *network.Connection, pkt packet.
|
||||||
checkTunneling(ctx, conn)
|
checkTunneling(ctx, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle verdict records and transitions.
|
|
||||||
finalizeVerdict(conn)
|
|
||||||
|
|
||||||
// Request tunneling if no tunnel is set and connection should be tunneled.
|
// Request tunneling if no tunnel is set and connection should be tunneled.
|
||||||
if conn.Verdict.Active == network.VerdictRerouteToTunnel &&
|
if conn.Verdict == network.VerdictRerouteToTunnel &&
|
||||||
conn.TunnelContext == nil {
|
conn.TunnelContext == nil {
|
||||||
err := requestTunneling(ctx, conn)
|
err := requestTunneling(ctx, conn)
|
||||||
if err != nil {
|
if err == nil {
|
||||||
|
conn.ConnectionEstablished = true
|
||||||
|
} else {
|
||||||
// Set connection to failed, but keep tunneling data.
|
// Set connection to failed, but keep tunneling data.
|
||||||
// The tunneling data makes connection easy to recognize as a failed SPN
|
// The tunneling data makes connection easy to recognize as a failed SPN
|
||||||
// connection and the data will help with debugging and displaying in the UI.
|
// connection and the data will help with debugging and displaying in the UI.
|
||||||
conn.Failed(fmt.Sprintf("failed to request tunneling: %s", err), "")
|
conn.Failed(fmt.Sprintf("failed to request tunneling: %s", err), "")
|
||||||
finalizeVerdict(conn)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -563,8 +565,8 @@ func issueVerdict(conn *network.Connection, pkt packet.Packet, verdict network.V
|
||||||
}
|
}
|
||||||
|
|
||||||
// do not allow to circumvent decision: e.g. to ACCEPT packets from a DROP-ed connection
|
// do not allow to circumvent decision: e.g. to ACCEPT packets from a DROP-ed connection
|
||||||
if verdict < conn.Verdict.Active {
|
if verdict < conn.Verdict {
|
||||||
verdict = conn.Verdict.Active
|
verdict = conn.Verdict
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
@ -622,53 +624,6 @@ var verdictRating = []network.Verdict{
|
||||||
network.VerdictUndecided,
|
network.VerdictUndecided,
|
||||||
}
|
}
|
||||||
|
|
||||||
func finalizeVerdict(conn *network.Connection) {
|
|
||||||
// Update worst verdict at the end.
|
|
||||||
defer func() {
|
|
||||||
for _, worstVerdict := range verdictRating {
|
|
||||||
if conn.Verdict.Firewall == worstVerdict {
|
|
||||||
conn.Verdict.Worst = worstVerdict
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Check for non-applicable verdicts.
|
|
||||||
// The earlier and clearer we do this, the better.
|
|
||||||
switch conn.Verdict.Firewall { //nolint:exhaustive
|
|
||||||
case network.VerdictUndecided, network.VerdictUndeterminable, network.VerdictFailed:
|
|
||||||
if conn.Inbound {
|
|
||||||
conn.Verdict.Active = network.VerdictDrop
|
|
||||||
} else {
|
|
||||||
conn.Verdict.Active = network.VerdictBlock
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply firewall verdict to active verdict.
|
|
||||||
switch {
|
|
||||||
case conn.Verdict.Active == network.VerdictUndecided:
|
|
||||||
// Apply first verdict without change.
|
|
||||||
conn.Verdict.Active = conn.Verdict.Firewall
|
|
||||||
|
|
||||||
case conn.Verdict.Worst == network.VerdictBlock ||
|
|
||||||
conn.Verdict.Worst == network.VerdictDrop ||
|
|
||||||
conn.Verdict.Worst == network.VerdictFailed ||
|
|
||||||
conn.Verdict.Worst == network.VerdictUndeterminable:
|
|
||||||
// Always allow to change verdict from any real initial/worst non-allowed state.
|
|
||||||
// Note: This check needs to happen before updating the Worst verdict.
|
|
||||||
conn.Verdict.Active = conn.Verdict.Firewall
|
|
||||||
|
|
||||||
case reference.IsPacketProtocol(conn.Entity.Protocol):
|
|
||||||
// For known packet protocols, apply firewall verdict unchanged.
|
|
||||||
conn.Verdict.Active = conn.Verdict.Firewall
|
|
||||||
|
|
||||||
case conn.Verdict.Active != conn.Verdict.Firewall:
|
|
||||||
// For all other protocols (most notably, stream protocols), always block after the first change.
|
|
||||||
// Block in both directions, as there is a live connection, which we want to actively kill.
|
|
||||||
conn.Verdict.Active = network.VerdictBlock
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// func tunnelHandler(pkt packet.Packet) {
|
// func tunnelHandler(pkt packet.Packet) {
|
||||||
// tunnelInfo := GetTunnelInfo(pkt.Info().Dst)
|
// tunnelInfo := GetTunnelInfo(pkt.Info().Dst)
|
||||||
// if tunnelInfo == nil {
|
// if tunnelInfo == nil {
|
||||||
|
|
|
@ -31,7 +31,7 @@ func checkTunneling(ctx context.Context, conn *network.Connection) {
|
||||||
case conn.Inbound:
|
case conn.Inbound:
|
||||||
// Can't tunnel incoming connections.
|
// Can't tunnel incoming connections.
|
||||||
return
|
return
|
||||||
case conn.Verdict.Firewall != network.VerdictAccept:
|
case conn.Verdict != network.VerdictAccept:
|
||||||
// Connection will be blocked.
|
// Connection will be blocked.
|
||||||
return
|
return
|
||||||
case conn.IPProtocol != packet.TCP && conn.IPProtocol != packet.UDP:
|
case conn.IPProtocol != packet.TCP && conn.IPProtocol != packet.UDP:
|
||||||
|
|
|
@ -199,7 +199,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch conn.Verdict.Active {
|
switch conn.Verdict {
|
||||||
// We immediately save blocked, dropped or failed verdicts so
|
// We immediately save blocked, dropped or failed verdicts so
|
||||||
// they pop up in the UI.
|
// they pop up in the UI.
|
||||||
case network.VerdictBlock, network.VerdictDrop, network.VerdictFailed, network.VerdictRerouteToNameserver, network.VerdictRerouteToTunnel:
|
case network.VerdictBlock, network.VerdictDrop, network.VerdictFailed, network.VerdictRerouteToNameserver, network.VerdictRerouteToTunnel:
|
||||||
|
@ -245,7 +245,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there is a Verdict to act upon.
|
// Check if there is a Verdict to act upon.
|
||||||
switch conn.Verdict.Active { //nolint:exhaustive // Only checking for specific values.
|
switch conn.Verdict { //nolint:exhaustive // Only checking for specific values.
|
||||||
case network.VerdictBlock, network.VerdictDrop, network.VerdictFailed:
|
case network.VerdictBlock, network.VerdictDrop, network.VerdictFailed:
|
||||||
tracer.Infof(
|
tracer.Infof(
|
||||||
"nameserver: returning %s response for %s to %s",
|
"nameserver: returning %s response for %s to %s",
|
||||||
|
@ -325,7 +325,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there is a Verdict to act upon.
|
// Check if there is a Verdict to act upon.
|
||||||
switch conn.Verdict.Active { //nolint:exhaustive // Only checking for specific values.
|
switch conn.Verdict { //nolint:exhaustive // Only checking for specific values.
|
||||||
case network.VerdictBlock, network.VerdictDrop, network.VerdictFailed:
|
case network.VerdictBlock, network.VerdictDrop, network.VerdictFailed:
|
||||||
tracer.Infof(
|
tracer.Infof(
|
||||||
"nameserver: returning %s response for %s to %s",
|
"nameserver: returning %s response for %s to %s",
|
||||||
|
|
|
@ -183,9 +183,7 @@ func convertConnection(conn *network.Connection) (*Conn, error) {
|
||||||
IPProtocol: conn.IPProtocol,
|
IPProtocol: conn.IPProtocol,
|
||||||
LocalIP: conn.LocalIP.String(),
|
LocalIP: conn.LocalIP.String(),
|
||||||
LocalPort: conn.LocalPort,
|
LocalPort: conn.LocalPort,
|
||||||
FirewallVerdict: conn.Verdict.Firewall,
|
ActiveVerdict: conn.Verdict,
|
||||||
ActiveVerdict: conn.Verdict.Active,
|
|
||||||
WorstVerdict: conn.Verdict.Worst,
|
|
||||||
Started: time.Unix(conn.Started, 0),
|
Started: time.Unix(conn.Started, 0),
|
||||||
Tunneled: conn.Tunneled,
|
Tunneled: conn.Tunneled,
|
||||||
Encrypted: conn.Encrypted,
|
Encrypted: conn.Encrypted,
|
||||||
|
@ -207,16 +205,7 @@ func convertConnection(conn *network.Connection) (*Conn, error) {
|
||||||
c.Type = ""
|
c.Type = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
switch conn.Verdict.Firewall {
|
c.Allowed = &conn.ConnectionEstablished
|
||||||
case network.VerdictAccept, network.VerdictRerouteToNameserver, network.VerdictRerouteToTunnel:
|
|
||||||
accepted := true
|
|
||||||
c.Allowed = &accepted
|
|
||||||
case network.VerdictBlock, network.VerdictDrop:
|
|
||||||
allowed := false
|
|
||||||
c.Allowed = &allowed
|
|
||||||
case network.VerdictUndecided, network.VerdictUndeterminable, network.VerdictFailed:
|
|
||||||
c.Allowed = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if conn.Ended > 0 {
|
if conn.Ended > 0 {
|
||||||
ended := time.Unix(conn.Ended, 0)
|
ended := time.Unix(conn.Ended, 0)
|
||||||
|
|
|
@ -139,8 +139,8 @@ func AddNetworkDebugData(di *debug.Info, profile, where string) {
|
||||||
debugConns []*Connection
|
debugConns []*Connection
|
||||||
accepted int
|
accepted int
|
||||||
total int
|
total int
|
||||||
transitioning int
|
|
||||||
)
|
)
|
||||||
|
|
||||||
for maybeConn := range it.Next {
|
for maybeConn := range it.Next {
|
||||||
// Switch to correct type.
|
// Switch to correct type.
|
||||||
conn, ok := maybeConn.(*Connection)
|
conn, ok := maybeConn.(*Connection)
|
||||||
|
@ -169,15 +169,13 @@ func AddNetworkDebugData(di *debug.Info, profile, where string) {
|
||||||
|
|
||||||
// Count.
|
// Count.
|
||||||
total++
|
total++
|
||||||
switch conn.Verdict.Firewall { //nolint:exhaustive
|
switch conn.Verdict { //nolint:exhaustive
|
||||||
case VerdictAccept,
|
case VerdictAccept,
|
||||||
VerdictRerouteToNameserver,
|
VerdictRerouteToNameserver,
|
||||||
VerdictRerouteToTunnel:
|
VerdictRerouteToTunnel:
|
||||||
|
|
||||||
accepted++
|
accepted++
|
||||||
}
|
}
|
||||||
if conn.Verdict.Active != conn.Verdict.Firewall {
|
|
||||||
transitioning++
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to list.
|
// Add to list.
|
||||||
debugConns = append(debugConns, conn)
|
debugConns = append(debugConns, conn)
|
||||||
|
@ -186,10 +184,9 @@ func AddNetworkDebugData(di *debug.Info, profile, where string) {
|
||||||
// Add it all.
|
// Add it all.
|
||||||
di.AddSection(
|
di.AddSection(
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"Network: %d/%d [~%d] Connections",
|
"Network: %d/%d Connections",
|
||||||
accepted,
|
accepted,
|
||||||
total,
|
total,
|
||||||
transitioning,
|
|
||||||
),
|
),
|
||||||
debug.UseCodeSection|debug.AddContentLineBreaks,
|
debug.UseCodeSection|debug.AddContentLineBreaks,
|
||||||
buildNetworkDebugInfoData(debugConns),
|
buildNetworkDebugInfoData(debugConns),
|
||||||
|
|
|
@ -40,15 +40,7 @@ var connectionTestData = []*Connection{
|
||||||
Country: "",
|
Country: "",
|
||||||
ASN: 0,
|
ASN: 0,
|
||||||
},
|
},
|
||||||
Verdict: struct {
|
Verdict: 2,
|
||||||
Worst Verdict
|
|
||||||
Active Verdict
|
|
||||||
Firewall Verdict
|
|
||||||
}{
|
|
||||||
Worst: 2,
|
|
||||||
Active: 2,
|
|
||||||
Firewall: 2,
|
|
||||||
},
|
|
||||||
Reason: Reason{
|
Reason: Reason{
|
||||||
Msg: "incoming connection blocked by default",
|
Msg: "incoming connection blocked by default",
|
||||||
OptionKey: "filter/serviceEndpoints",
|
OptionKey: "filter/serviceEndpoints",
|
||||||
|
@ -88,15 +80,7 @@ var connectionTestData = []*Connection{
|
||||||
Country: "DE",
|
Country: "DE",
|
||||||
ASN: 16509,
|
ASN: 16509,
|
||||||
},
|
},
|
||||||
Verdict: struct {
|
Verdict: 2,
|
||||||
Worst Verdict
|
|
||||||
Active Verdict
|
|
||||||
Firewall Verdict
|
|
||||||
}{
|
|
||||||
Worst: 2,
|
|
||||||
Active: 2,
|
|
||||||
Firewall: 2,
|
|
||||||
},
|
|
||||||
Reason: Reason{
|
Reason: Reason{
|
||||||
Msg: "default permit",
|
Msg: "default permit",
|
||||||
OptionKey: "filter/defaultAction",
|
OptionKey: "filter/defaultAction",
|
||||||
|
@ -139,15 +123,7 @@ var connectionTestData = []*Connection{
|
||||||
Country: "US",
|
Country: "US",
|
||||||
ASN: 15169,
|
ASN: 15169,
|
||||||
},
|
},
|
||||||
Verdict: struct {
|
Verdict: 2,
|
||||||
Worst Verdict
|
|
||||||
Active Verdict
|
|
||||||
Firewall Verdict
|
|
||||||
}{
|
|
||||||
Worst: 2,
|
|
||||||
Active: 2,
|
|
||||||
Firewall: 2,
|
|
||||||
},
|
|
||||||
Reason: Reason{
|
Reason: Reason{
|
||||||
Msg: "default permit",
|
Msg: "default permit",
|
||||||
OptionKey: "filter/defaultAction",
|
OptionKey: "filter/defaultAction",
|
||||||
|
|
|
@ -121,17 +121,9 @@ type Connection struct { //nolint:maligned // TODO: fix alignment
|
||||||
// Verdict holds the decisions that are made for a connection
|
// Verdict holds the decisions that are made for a connection
|
||||||
// The verdict may change so any access to it must be guarded by the
|
// The verdict may change so any access to it must be guarded by the
|
||||||
// connection lock.
|
// connection lock.
|
||||||
Verdict struct {
|
Verdict Verdict
|
||||||
// Worst verdict holds the worst verdict that was assigned to this
|
// Whether or not the connection has been established at least once.
|
||||||
// connection from a privacy/security perspective.
|
ConnectionEstablished bool
|
||||||
Worst Verdict
|
|
||||||
// Active verdict holds the verdict that Portmaster will respond with.
|
|
||||||
// This is different from the Firewall verdict in order to guarantee proper
|
|
||||||
// transition between verdicts that need the connection to be re-established.
|
|
||||||
Active Verdict
|
|
||||||
// Firewall holds the last (most recent) decision by the firewall.
|
|
||||||
Firewall Verdict
|
|
||||||
}
|
|
||||||
// Reason holds information justifying the verdict, as well as additional
|
// Reason holds information justifying the verdict, as well as additional
|
||||||
// information about the reason.
|
// information about the reason.
|
||||||
// Access to Reason must be guarded by the connection lock.
|
// Access to Reason must be guarded by the connection lock.
|
||||||
|
@ -722,22 +714,15 @@ func (conn *Connection) SetVerdict(newVerdict Verdict, reason, reasonOptionKey s
|
||||||
return true // TODO: remove
|
return true // TODO: remove
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVerdictDirectly sets the firewall verdict.
|
// SetVerdictDirectly sets the verdict.
|
||||||
func (conn *Connection) SetVerdictDirectly(newVerdict Verdict) {
|
func (conn *Connection) SetVerdictDirectly(newVerdict Verdict) {
|
||||||
conn.Verdict.Firewall = newVerdict
|
conn.Verdict = newVerdict
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerdictVerb returns the verdict as a verb, while taking any special states
|
// VerdictVerb returns the verdict as a verb, while taking any special states
|
||||||
// into account.
|
// into account.
|
||||||
func (conn *Connection) VerdictVerb() string {
|
func (conn *Connection) VerdictVerb() string {
|
||||||
if conn.Verdict.Firewall == conn.Verdict.Active {
|
return conn.Verdict.Verb()
|
||||||
return conn.Verdict.Firewall.Verb()
|
|
||||||
}
|
|
||||||
return fmt.Sprintf(
|
|
||||||
"%s (transitioning to %s)",
|
|
||||||
conn.Verdict.Active.Verb(),
|
|
||||||
conn.Verdict.Firewall.Verb(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DataIsComplete returns whether all information about the connection is
|
// DataIsComplete returns whether all information about the connection is
|
||||||
|
@ -766,6 +751,14 @@ func (conn *Connection) SaveWhenFinished() {
|
||||||
func (conn *Connection) Save() {
|
func (conn *Connection) Save() {
|
||||||
conn.UpdateMeta()
|
conn.UpdateMeta()
|
||||||
|
|
||||||
|
switch conn.Verdict {
|
||||||
|
case VerdictAccept, VerdictRerouteToNameserver:
|
||||||
|
conn.ConnectionEstablished = true
|
||||||
|
case VerdictRerouteToTunnel:
|
||||||
|
// this is already handled when the connection tunnel has been
|
||||||
|
// established.
|
||||||
|
}
|
||||||
|
|
||||||
// Do not save/update until data is complete.
|
// Do not save/update until data is complete.
|
||||||
if !conn.DataIsComplete() {
|
if !conn.DataIsComplete() {
|
||||||
return
|
return
|
||||||
|
@ -1003,7 +996,7 @@ func packetHandlerHandleConn(ctx context.Context, conn *Connection, pkt packet.P
|
||||||
switch {
|
switch {
|
||||||
case conn.DataIsComplete():
|
case conn.DataIsComplete():
|
||||||
tracer.Infof("filter: connection %s %s: %s", conn, conn.VerdictVerb(), conn.Reason.Msg)
|
tracer.Infof("filter: connection %s %s: %s", conn, conn.VerdictVerb(), conn.Reason.Msg)
|
||||||
case conn.Verdict.Firewall != VerdictUndecided:
|
case conn.Verdict != VerdictUndecided:
|
||||||
tracer.Debugf("filter: connection %s fast-tracked", pkt)
|
tracer.Debugf("filter: connection %s fast-tracked", pkt)
|
||||||
default:
|
default:
|
||||||
tracer.Debugf("filter: gathered data on connection %s", conn)
|
tracer.Debugf("filter: gathered data on connection %s", conn)
|
||||||
|
|
|
@ -208,7 +208,7 @@ func writeOpenDNSRequestsToDB() {
|
||||||
// ReplyWithDNS creates a new reply to the given request with the data from the RRCache, and additional informational records.
|
// ReplyWithDNS creates a new reply to the given request with the data from the RRCache, and additional informational records.
|
||||||
func (conn *Connection) ReplyWithDNS(ctx context.Context, request *dns.Msg) *dns.Msg {
|
func (conn *Connection) ReplyWithDNS(ctx context.Context, request *dns.Msg) *dns.Msg {
|
||||||
// Select request responder.
|
// Select request responder.
|
||||||
switch conn.Verdict.Active {
|
switch conn.Verdict {
|
||||||
case VerdictBlock:
|
case VerdictBlock:
|
||||||
return nsutil.BlockIP().ReplyWithDNS(ctx, request)
|
return nsutil.BlockIP().ReplyWithDNS(ctx, request)
|
||||||
case VerdictDrop:
|
case VerdictDrop:
|
||||||
|
@ -229,7 +229,7 @@ func (conn *Connection) ReplyWithDNS(ctx context.Context, request *dns.Msg) *dns
|
||||||
func (conn *Connection) GetExtraRRs(ctx context.Context, request *dns.Msg) []dns.RR {
|
func (conn *Connection) GetExtraRRs(ctx context.Context, request *dns.Msg) []dns.RR {
|
||||||
// Select level to add the verdict record with.
|
// Select level to add the verdict record with.
|
||||||
var level log.Severity
|
var level log.Severity
|
||||||
switch conn.Verdict.Active {
|
switch conn.Verdict {
|
||||||
case VerdictFailed:
|
case VerdictFailed:
|
||||||
level = log.ErrorLevel
|
level = log.ErrorLevel
|
||||||
case VerdictUndecided, VerdictUndeterminable,
|
case VerdictUndecided, VerdictUndeterminable,
|
||||||
|
|
|
@ -140,7 +140,7 @@ func (conn *Connection) addToMetrics() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check the verdict.
|
// Check the verdict.
|
||||||
switch conn.Verdict.Firewall { //nolint:exhaustive // Not critical.
|
switch conn.Verdict { //nolint:exhaustive // Not critical.
|
||||||
case VerdictBlock, VerdictDrop:
|
case VerdictBlock, VerdictDrop:
|
||||||
blockedOutConnCounter.Inc()
|
blockedOutConnCounter.Inc()
|
||||||
conn.addedToMetrics = true
|
conn.addedToMetrics = true
|
||||||
|
|
Loading…
Add table
Reference in a new issue