Improve verdict handling and switch to immediate re-evaluation

This commit is contained in:
Daniel 2022-10-10 11:21:45 +02:00
parent 57904426e3
commit f63df67d23
12 changed files with 242 additions and 111 deletions

View file

@ -187,7 +187,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.Current == network.VerdictBlock { if conn.Verdict.Active == network.VerdictBlock {
return rrCache return rrCache
} }

View file

@ -63,8 +63,8 @@ func RunInspectors(conn *network.Connection, pkt packet.Packet) (network.Verdict
continue continue
} }
// check if the current verdict is already past the inspection criteria. // check if the active verdict is already past the inspection criteria.
if conn.Verdict.Current > inspectVerdicts[key] { if conn.Verdict.Active > 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.Current verdict = conn.Verdict.Active
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.Current verdict = conn.Verdict.Active
activeInspectors[key] = true activeInspectors[key] = true
case STOP_INSPECTING: case STOP_INSPECTING:
activeInspectors[key] = true activeInspectors[key] = true

View file

@ -24,7 +24,7 @@ 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/spn/captain" "github.com/safing/portmaster/network/reference"
) )
var ( var (
@ -122,21 +122,55 @@ func resetAllConnectionVerdicts() {
log.Info("interception: marking all connections for re-evaluation") log.Info("interception: marking all connections for re-evaluation")
// reset all connection firewall handlers. This will tell the master to rerun the firewall checks. // reset all connection firewall handlers. This will tell the master to rerun the firewall checks.
for _, conn := range network.GetAllConnections() { // for _, conn := range network.GetAllConnections() {
isSPNConnection := captain.IsExcepted(conn.Entity.IP) && conn.Process().Pid == ownPID // isSPNConnection := captain.IsExcepted(conn.Entity.IP) && conn.Process().Pid == ownPID
// mark all non SPN connections to be processed by the firewall. // // mark all non SPN connections to be processed by the firewall.
if !isSPNConnection { // if !isSPNConnection {
// conn.Lock()
// conn.SetFirewallHandler(initialHandler)
// // Don't keep the previous tunneled value.
// conn.Tunneled = false
// // Reset entity if it exists.
// if conn.Entity != nil {
// conn.Entity.ResetLists()
// }
// conn.Unlock()
// }
// }
// Create tracing context.
ctx, tracer := log.AddTracer(context.Background())
defer tracer.Submit()
for _, conn := range network.GetAllConnections() {
func() {
conn.Lock() conn.Lock()
conn.SetFirewallHandler(initialHandler) defer conn.Unlock()
// Don't keep the previous tunneled value.
conn.Tunneled = false // Skip internal connections:
// Reset entity if it exists. // - Pre-authenticated connections from Portmaster
if conn.Entity != nil { // - Redirected DNS requests
conn.Entity.ResetLists() // - SPN Uplink to Home Hub
if conn.Internal {
log.Tracef("skipping internal connection %s", conn)
return
} }
conn.Unlock()
} log.Tracer(ctx).Debugf("filter: re-evaluating verdict of %s", conn)
previousVerdict := conn.Verdict.Firewall
// Apply privacy filter and check tunneling.
filterConnection(ctx, conn, nil)
// Save if verdict changed.
if conn.Verdict.Firewall != previousVerdict {
conn.Save()
tracer.Infof("filter: verdict of connection %s changed from %s to %s", conn, previousVerdict.Verb(), conn.VerdictVerb())
} else {
tracer.Tracef("filter: verdict to connection %s unchanged at %s", conn, conn.VerdictVerb())
}
}()
} }
err := interception.ResetVerdictOfAllConnections() err := interception.ResetVerdictOfAllConnections()
@ -418,6 +452,7 @@ func fastTrackedPermit(pkt packet.Packet) (handled bool) {
func initialHandler(conn *network.Connection, pkt packet.Packet) { func initialHandler(conn *network.Connection, pkt packet.Packet) {
log.Tracer(pkt.Ctx()).Trace("filter: handing over to connection-based handler") log.Tracer(pkt.Ctx()).Trace("filter: handing over to connection-based handler")
// Check for special (internal) connection cases.
switch { switch {
case !conn.Inbound && localPortIsPreAuthenticated(conn.Entity.Protocol, conn.LocalPort): case !conn.Inbound && localPortIsPreAuthenticated(conn.Entity.Protocol, conn.LocalPort):
// Approve connection. // Approve connection.
@ -444,14 +479,31 @@ func initialHandler(conn *network.Connection, pkt packet.Packet) {
conn.Internal = true conn.Internal = true
// 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
}
case filterEnabled(): // Apply privacy filter and check tunneling.
log.Tracer(pkt.Ctx()).Trace("filter: starting decision process") filterConnection(pkt.Ctx(), conn, pkt)
DecideOnConnection(pkt.Ctx(), conn, pkt)
// Decide how to continue handling connection.
switch {
case conn.Inspecting:
log.Tracer(pkt.Ctx()).Trace("filter: start inspecting")
conn.SetFirewallHandler(inspectThenVerdict)
inspectThenVerdict(conn, pkt)
default: default:
conn.StopFirewallHandler()
issueVerdict(conn, pkt, 0, true)
}
}
func filterConnection(ctx context.Context, conn *network.Connection, pkt packet.Packet) {
if filterEnabled() {
log.Tracer(ctx).Trace("filter: starting decision process")
DecideOnConnection(ctx, conn, pkt)
} else {
conn.Accept("privacy filter disabled", noReasonOptionKey) conn.Accept("privacy filter disabled", noReasonOptionKey)
} }
@ -472,18 +524,19 @@ func initialHandler(conn *network.Connection, pkt packet.Packet) {
} }
// Check if connection should be tunneled. // Check if connection should be tunneled.
checkTunneling(pkt.Ctx(), conn, pkt) checkTunneling(ctx, conn)
// Handle verdict records and transitions.
finalizeVerdict(conn) finalizeVerdict(conn)
switch { // Request tunneling if no tunnel is set and connection should be tunneled.
case conn.Inspecting: if conn.Verdict.Active == network.VerdictRerouteToTunnel &&
log.Tracer(pkt.Ctx()).Trace("filter: start inspecting") conn.TunnelContext == nil {
conn.SetFirewallHandler(inspectThenVerdict) err := requestTunneling(ctx, conn)
inspectThenVerdict(conn, pkt) if err != nil {
default: conn.Failed(fmt.Sprintf("failed to request tunneling: %s", err), "")
conn.StopFirewallHandler() finalizeVerdict(conn)
issueVerdict(conn, pkt, 0, true) }
} }
} }
@ -514,8 +567,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.Current { if verdict < conn.Verdict.Active {
verdict = conn.Verdict.Current verdict = conn.Verdict.Active
} }
var err error var err error
@ -561,18 +614,53 @@ func issueVerdict(conn *network.Connection, pkt packet.Packet, verdict network.V
} }
} }
// verdictRating rates the privacy and security aspect of verdicts from worst to best.
var verdictRating = []network.Verdict{
network.VerdictAccept, // Connection allowed in the open.
network.VerdictRerouteToTunnel, // Connection allowed, but protected.
network.VerdictRerouteToNameserver, // Connection allowed, but resolved via Portmaster.
network.VerdictBlock, // Connection blocked, with feedback.
network.VerdictDrop, // Connection blocked, without feedback.
network.VerdictFailed,
network.VerdictUndeterminable,
network.VerdictUndecided,
}
func finalizeVerdict(conn *network.Connection) { func finalizeVerdict(conn *network.Connection) {
// previously accepted or tunneled connections may need to be blocked // Update worst verdict.
if conn.Verdict.Current == network.VerdictAccept { for _, worstVerdict := range verdictRating {
switch { if conn.Verdict.Firewall == worstVerdict {
case conn.Verdict.Previous == network.VerdictRerouteToTunnel && !conn.Tunneled: conn.Verdict.Worst = worstVerdict
conn.SetVerdictDirectly(network.VerdictBlock)
case conn.Verdict.Previous == network.VerdictAccept && conn.Tunneled:
conn.SetVerdictDirectly(network.VerdictBlock)
case conn.Tunneled:
conn.SetVerdictDirectly(network.VerdictRerouteToTunnel)
} }
} }
// 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 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) {

View file

@ -2,6 +2,7 @@ package firewall
import ( import (
"context" "context"
"errors"
"github.com/safing/portbase/log" "github.com/safing/portbase/log"
"github.com/safing/portmaster/netenv" "github.com/safing/portmaster/netenv"
@ -16,7 +17,7 @@ import (
"github.com/safing/spn/sluice" "github.com/safing/spn/sluice"
) )
func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Packet) { func checkTunneling(ctx context.Context, conn *network.Connection) {
// Check if the connection should be tunneled at all. // Check if the connection should be tunneled at all.
switch { switch {
case !tunnelEnabled(): case !tunnelEnabled():
@ -28,9 +29,12 @@ func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Pa
case conn.Inbound: case conn.Inbound:
// Can't tunnel incoming connections. // Can't tunnel incoming connections.
return return
case conn.Verdict.Current != network.VerdictAccept: case conn.Verdict.Firewall != network.VerdictAccept:
// Connection will be blocked. // Connection will be blocked.
return return
case conn.IPProtocol != packet.TCP && conn.IPProtocol != packet.UDP:
// Unsupported protocol.
return
case conn.Process().Pid == ownPID: case conn.Process().Pid == ownPID:
// Bypass tunneling for certain own connections. // Bypass tunneling for certain own connections.
switch { switch {
@ -101,11 +105,22 @@ func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Pa
// Check if ready. // Check if ready.
if !captain.ClientReady() { if !captain.ClientReady() {
// Block connection as SPN is not ready yet. // Block connection as SPN is not ready yet.
log.Tracer(pkt.Ctx()).Trace("SPN not ready for tunneling") log.Tracer(ctx).Trace("SPN not ready for tunneling")
conn.Failed("SPN not ready for tunneling", "") conn.Failed("SPN not ready for tunneling", "")
return return
} }
conn.SetVerdictDirectly(network.VerdictRerouteToTunnel)
conn.Tunneled = true
}
func requestTunneling(ctx context.Context, conn *network.Connection) error {
// Get profile.
layeredProfile := conn.Process().Profile()
if layeredProfile == nil {
return errors.New("no profile set")
}
// Set options. // Set options.
conn.TunnelOpts = &navigator.Options{ conn.TunnelOpts = &navigator.Options{
HubPolicies: layeredProfile.StackedExitHubPolicies(), HubPolicies: layeredProfile.StackedExitHubPolicies(),
@ -150,13 +165,11 @@ func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Pa
} }
// Queue request in sluice. // Queue request in sluice.
err = sluice.AwaitRequest(conn, crew.HandleSluiceRequest) err := sluice.AwaitRequest(conn, crew.HandleSluiceRequest)
if err != nil { if err != nil {
log.Tracer(pkt.Ctx()).Warningf("failed to request tunneling: %s", err) return err
conn.Failed("failed to request tunneling", "")
} else {
log.Tracer(pkt.Ctx()).Trace("filter: tunneling requested")
// set the flag so the verdict can be updated
conn.Tunneled = true
} }
log.Tracer(ctx).Trace("filter: tunneling requested")
return nil
} }

View file

@ -189,7 +189,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
conn.Resolver = rrCache.Resolver conn.Resolver = rrCache.Resolver
} }
switch conn.Verdict.Current { switch conn.Verdict.Active {
// 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:
@ -217,7 +217,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
case network.VerdictUndeterminable: case network.VerdictUndeterminable:
fallthrough fallthrough
default: default:
tracer.Warningf("nameserver: unexpected verdict %s for connection %s, not saving", conn.Verdict, conn) tracer.Warningf("nameserver: unexpected verdict %s for connection %s, not saving", conn.VerdictVerb(), conn)
} }
}() }()
@ -235,11 +235,11 @@ 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.Current { //nolint:exhaustive // Only checking for specific values. switch conn.Verdict.Active { //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",
conn.Verdict.Current.Verb(), conn.VerdictVerb(),
q.ID(), q.ID(),
conn.Process(), conn.Process(),
) )
@ -315,11 +315,11 @@ 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.Current { //nolint:exhaustive // Only checking for specific values. switch conn.Verdict.Active { //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",
conn.Verdict.Current.Verb(), conn.VerdictVerb(),
q.ID(), q.ID(),
conn.Process(), conn.Process(),
) )
@ -338,7 +338,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
} }
tracer.Infof( tracer.Infof(
"nameserver: returning %s response (%s%s) for %s to %s", "nameserver: returning %s response (%s%s) for %s to %s",
conn.Verdict.Current.Verb(), conn.VerdictVerb(),
dns.RcodeToString[rrCache.RCode], dns.RcodeToString[rrCache.RCode],
noAnswerIndicator, noAnswerIndicator,
q.ID(), q.ID(),

View file

@ -155,7 +155,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,
Verdict: conn.Verdict.User, Verdict: conn.Verdict.Firewall, // TODO: Expose both Worst and Firewall verdicts.
Started: time.Unix(conn.Started, 0), Started: time.Unix(conn.Started, 0),
Tunneled: conn.Tunneled, Tunneled: conn.Tunneled,
Encrypted: conn.Encrypted, Encrypted: conn.Encrypted,
@ -177,7 +177,7 @@ func convertConnection(conn *network.Connection) (*Conn, error) {
c.Type = "" c.Type = ""
} }
switch conn.Verdict.User { switch conn.Verdict.Firewall {
case network.VerdictAccept, network.VerdictRerouteToNameserver, network.VerdictRerouteToTunnel: case network.VerdictAccept, network.VerdictRerouteToNameserver, network.VerdictRerouteToTunnel:
accepted := true accepted := true
c.Allowed = &accepted c.Allowed = &accepted

View file

@ -152,7 +152,7 @@ func AddNetworkDebugData(di *debug.Info, profile, where string) {
// Count. // Count.
total++ total++
switch conn.Verdict.Current { //nolint:exhaustive switch conn.Verdict.Firewall { //nolint:exhaustive
case VerdictAccept, case VerdictAccept,
VerdictRerouteToNameserver, VerdictRerouteToNameserver,
VerdictRerouteToTunnel: VerdictRerouteToTunnel:

View file

@ -41,13 +41,13 @@ var connectionTestData = []*Connection{
ASN: 0, ASN: 0,
}, },
Verdict: struct { Verdict: struct {
Current Verdict Worst Verdict
Previous Verdict Active Verdict
User Verdict Firewall Verdict
}{ }{
Current: 2, Worst: 2,
Previous: 2, Active: 2,
User: 2, Firewall: 2,
}, },
Reason: Reason{ Reason: Reason{
Msg: "incoming connection blocked by default", Msg: "incoming connection blocked by default",
@ -89,13 +89,13 @@ var connectionTestData = []*Connection{
ASN: 16509, ASN: 16509,
}, },
Verdict: struct { Verdict: struct {
Current Verdict Worst Verdict
Previous Verdict Active Verdict
User Verdict Firewall Verdict
}{ }{
Current: 2, Worst: 2,
Previous: 2, Active: 2,
User: 2, Firewall: 2,
}, },
Reason: Reason{ Reason: Reason{
Msg: "default permit", Msg: "default permit",
@ -140,13 +140,13 @@ var connectionTestData = []*Connection{
ASN: 15169, ASN: 15169,
}, },
Verdict: struct { Verdict: struct {
Current Verdict Worst Verdict
Previous Verdict Active Verdict
User Verdict Firewall Verdict
}{ }{
Current: 2, Worst: 2,
Previous: 2, Active: 2,
User: 2, Firewall: 2,
}, },
Reason: Reason{ Reason: Reason{
Msg: "default permit", Msg: "default permit",

View file

@ -111,12 +111,15 @@ type Connection struct { //nolint:maligned // TODO: fix alignment
// 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 struct {
// Current is the current decision that has been made for a connection. // Worst verdict holds the worst verdict that was assigned to this
Current Verdict // connection from a privacy/security perspective.
// Previous holds the previous verdict value, if there wasn't previous it will VerdictUndecided Worst Verdict
Previous Verdict // Active verdict holds the verdict that Portmaster will respond with.
// User holds the verdict that should be displayed in the user interface // This is different from the Firewall verdict in order to guarantee proper
User Verdict // transition between verdicts that need the connection to be re-established.
Active Verdict
// Firewall holsd 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.
@ -524,35 +527,35 @@ func (conn *Connection) Failed(reason, reasonOptionKey string) {
func (conn *Connection) SetVerdict(newVerdict Verdict, reason, reasonOptionKey string, reasonCtx interface{}) (ok bool) { func (conn *Connection) SetVerdict(newVerdict Verdict, reason, reasonOptionKey string, reasonCtx interface{}) (ok bool) {
conn.SetVerdictDirectly(newVerdict) conn.SetVerdictDirectly(newVerdict)
// Only set if it matches the user verdict. For a consistent reason conn.Reason.Msg = reason
if newVerdict == conn.Verdict.User { conn.Reason.Context = reasonCtx
conn.Reason.Msg = reason
conn.Reason.Context = reasonCtx
conn.Reason.OptionKey = "" conn.Reason.OptionKey = ""
conn.Reason.Profile = "" conn.Reason.Profile = ""
if reasonOptionKey != "" && conn.Process() != nil { if reasonOptionKey != "" && conn.Process() != nil {
conn.Reason.OptionKey = reasonOptionKey conn.Reason.OptionKey = reasonOptionKey
conn.Reason.Profile = conn.Process().Profile().GetProfileSource(conn.Reason.OptionKey) conn.Reason.Profile = conn.Process().Profile().GetProfileSource(conn.Reason.OptionKey)
}
} }
return true return true // TODO: remove
} }
// SetVerdictDirectly sets the new verdict and stores the previous value. // SetVerdictDirectly sets the firewall verdict.
func (conn *Connection) SetVerdictDirectly(newVerdict Verdict) { func (conn *Connection) SetVerdictDirectly(newVerdict Verdict) {
if newVerdict == conn.Verdict.Current { conn.Verdict.Firewall = newVerdict
return }
}
// Save previous verdict and set new one
conn.Verdict.Previous = conn.Verdict.Current
conn.Verdict.Current = newVerdict
// if a connection is accepted once it should always show as accepted // VerdictVerb returns the verdict as a verb, while taking any special states
if conn.Verdict.User != VerdictAccept { // into account.
conn.Verdict.User = newVerdict func (conn *Connection) VerdictVerb() string {
if conn.Verdict.Firewall == conn.Verdict.Active {
return conn.Verdict.Firewall.Verb()
} }
return fmt.Sprintf(
"%s (transitioning to %s)",
conn.Verdict.Active.Verb(),
conn.Verdict.Firewall.Verb(),
)
} }
// Process returns the connection's process. // Process returns the connection's process.
@ -679,7 +682,7 @@ func packetHandlerHandleConn(conn *Connection, pkt packet.Packet) {
} }
// Log verdict. // Log verdict.
log.Tracer(pkt.Ctx()).Infof("filter: connection %s %s: %s", conn, conn.Verdict.Current.Verb(), conn.Reason.Msg) log.Tracer(pkt.Ctx()).Infof("filter: connection %s %s: %s", conn, conn.VerdictVerb(), conn.Reason.Msg)
// Submit trace logs. // Submit trace logs.
log.Tracer(pkt.Ctx()).Submit() log.Tracer(pkt.Ctx()).Submit()

View file

@ -115,7 +115,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.Current { switch conn.Verdict.Active {
case VerdictBlock: case VerdictBlock:
return nsutil.BlockIP().ReplyWithDNS(ctx, request) return nsutil.BlockIP().ReplyWithDNS(ctx, request)
case VerdictDrop: case VerdictDrop:
@ -136,7 +136,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.Current { switch conn.Verdict.Active {
case VerdictFailed: case VerdictFailed:
level = log.ErrorLevel level = log.ErrorLevel
case VerdictUndecided, VerdictUndeterminable, case VerdictUndecided, VerdictUndeterminable,
@ -148,7 +148,7 @@ func (conn *Connection) GetExtraRRs(ctx context.Context, request *dns.Msg) []dns
} }
// Create resource record with verdict and reason. // Create resource record with verdict and reason.
rr, err := nsutil.MakeMessageRecord(level, fmt.Sprintf("%s: %s", conn.Verdict.Current.Verb(), conn.Reason.Msg)) rr, err := nsutil.MakeMessageRecord(level, fmt.Sprintf("%s: %s", conn.VerdictVerb(), conn.Reason.Msg))
if err != nil { if err != nil {
log.Tracer(ctx).Warningf("filter: failed to add informational record to reply: %s", err) log.Tracer(ctx).Warningf("filter: failed to add informational record to reply: %s", err)
return nil return nil

View file

@ -119,7 +119,7 @@ func (conn *Connection) addToMetrics() {
} }
// Check the verdict. // Check the verdict.
switch conn.Verdict.Current { //nolint:exhaustive // Not critical. switch conn.Verdict.Firewall { //nolint:exhaustive // Not critical.
case VerdictBlock, VerdictDrop: case VerdictBlock, VerdictDrop:
blockedOutConnCounter.Inc() blockedOutConnCounter.Inc()
conn.addedToMetrics = true conn.addedToMetrics = true

View file

@ -46,3 +46,30 @@ func GetProtocolNumber(protocol string) (number uint8, ok bool) {
} }
return 0, false return 0, false
} }
// IsPacketProtocol returns whether the given protocol number is a known packet based protocol.
// Note: Not fully complete. Calling IsPacketProtocol() does not equal calling !IsStreamProtocol().
func IsPacketProtocol(protocol uint8) bool {
switch protocol {
case 1, // ICMP
17, // UDP
27, // RDP
58, // ICMP6
33, // DCCP
136: // UDP-LITE
return true
default:
return false
}
}
// IsStreamProtocol returns whether the given protocol number is a known stream based protocol.
// Note: Not fully complete. Calling IsPacketProtocol() does not equal calling !IsStreamProtocol().
func IsStreamProtocol(protocol uint8) bool {
switch protocol {
case 6: // TCP
return true
default:
return false
}
}