mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Improve verdict handling and switch to immediate re-evaluation
This commit is contained in:
parent
57904426e3
commit
f63df67d23
12 changed files with 242 additions and 111 deletions
|
@ -187,7 +187,7 @@ func FilterResolvedDNS(
|
|||
|
||||
// Filter dns records and return if the query is blocked.
|
||||
rrCache = filterDNSResponse(ctx, conn, layeredProfile, rrCache, sysResolver)
|
||||
if conn.Verdict.Current == network.VerdictBlock {
|
||||
if conn.Verdict.Active == network.VerdictBlock {
|
||||
return rrCache
|
||||
}
|
||||
|
||||
|
|
|
@ -63,8 +63,8 @@ func RunInspectors(conn *network.Connection, pkt packet.Packet) (network.Verdict
|
|||
continue
|
||||
}
|
||||
|
||||
// check if the current verdict is already past the inspection criteria.
|
||||
if conn.Verdict.Current > inspectVerdicts[key] {
|
||||
// check if the active verdict is already past the inspection criteria.
|
||||
if conn.Verdict.Active > inspectVerdicts[key] {
|
||||
activeInspectors[key] = true
|
||||
continue
|
||||
}
|
||||
|
@ -86,11 +86,11 @@ func RunInspectors(conn *network.Connection, pkt packet.Packet) (network.Verdict
|
|||
continueInspection = true
|
||||
case BLOCK_CONN:
|
||||
conn.SetVerdict(network.VerdictBlock, "", "", nil)
|
||||
verdict = conn.Verdict.Current
|
||||
verdict = conn.Verdict.Active
|
||||
activeInspectors[key] = true
|
||||
case DROP_CONN:
|
||||
conn.SetVerdict(network.VerdictDrop, "", "", nil)
|
||||
verdict = conn.Verdict.Current
|
||||
verdict = conn.Verdict.Active
|
||||
activeInspectors[key] = true
|
||||
case STOP_INSPECTING:
|
||||
activeInspectors[key] = true
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
"github.com/safing/portmaster/network"
|
||||
"github.com/safing/portmaster/network/netutils"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
"github.com/safing/spn/captain"
|
||||
"github.com/safing/portmaster/network/reference"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -122,21 +122,55 @@ func resetAllConnectionVerdicts() {
|
|||
log.Info("interception: marking all connections for re-evaluation")
|
||||
|
||||
// reset all connection firewall handlers. This will tell the master to rerun the firewall checks.
|
||||
for _, conn := range network.GetAllConnections() {
|
||||
isSPNConnection := captain.IsExcepted(conn.Entity.IP) && conn.Process().Pid == ownPID
|
||||
// for _, conn := range network.GetAllConnections() {
|
||||
// isSPNConnection := captain.IsExcepted(conn.Entity.IP) && conn.Process().Pid == ownPID
|
||||
|
||||
// mark all non SPN connections to be processed by the firewall.
|
||||
if !isSPNConnection {
|
||||
// // mark all non SPN connections to be processed by the firewall.
|
||||
// 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.SetFirewallHandler(initialHandler)
|
||||
// Don't keep the previous tunneled value.
|
||||
conn.Tunneled = false
|
||||
// Reset entity if it exists.
|
||||
if conn.Entity != nil {
|
||||
conn.Entity.ResetLists()
|
||||
defer conn.Unlock()
|
||||
|
||||
// Skip internal connections:
|
||||
// - Pre-authenticated connections from Portmaster
|
||||
// - Redirected DNS requests
|
||||
// - 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()
|
||||
|
@ -418,6 +452,7 @@ func fastTrackedPermit(pkt packet.Packet) (handled bool) {
|
|||
func initialHandler(conn *network.Connection, pkt packet.Packet) {
|
||||
log.Tracer(pkt.Ctx()).Trace("filter: handing over to connection-based handler")
|
||||
|
||||
// Check for special (internal) connection cases.
|
||||
switch {
|
||||
case !conn.Inbound && localPortIsPreAuthenticated(conn.Entity.Protocol, conn.LocalPort):
|
||||
// Approve connection.
|
||||
|
@ -444,14 +479,31 @@ func initialHandler(conn *network.Connection, pkt packet.Packet) {
|
|||
conn.Internal = true
|
||||
// End directly, as no other processing is necessary.
|
||||
conn.StopFirewallHandler()
|
||||
finalizeVerdict(conn)
|
||||
issueVerdict(conn, pkt, 0, true)
|
||||
return
|
||||
}
|
||||
|
||||
case filterEnabled():
|
||||
log.Tracer(pkt.Ctx()).Trace("filter: starting decision process")
|
||||
DecideOnConnection(pkt.Ctx(), conn, pkt)
|
||||
// Apply privacy filter and check tunneling.
|
||||
filterConnection(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:
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -472,18 +524,19 @@ func initialHandler(conn *network.Connection, pkt packet.Packet) {
|
|||
}
|
||||
|
||||
// Check if connection should be tunneled.
|
||||
checkTunneling(pkt.Ctx(), conn, pkt)
|
||||
checkTunneling(ctx, conn)
|
||||
|
||||
// Handle verdict records and transitions.
|
||||
finalizeVerdict(conn)
|
||||
|
||||
switch {
|
||||
case conn.Inspecting:
|
||||
log.Tracer(pkt.Ctx()).Trace("filter: start inspecting")
|
||||
conn.SetFirewallHandler(inspectThenVerdict)
|
||||
inspectThenVerdict(conn, pkt)
|
||||
default:
|
||||
conn.StopFirewallHandler()
|
||||
issueVerdict(conn, pkt, 0, true)
|
||||
// Request tunneling if no tunnel is set and connection should be tunneled.
|
||||
if conn.Verdict.Active == network.VerdictRerouteToTunnel &&
|
||||
conn.TunnelContext == nil {
|
||||
err := requestTunneling(ctx, conn)
|
||||
if err != nil {
|
||||
conn.Failed(fmt.Sprintf("failed to request tunneling: %s", err), "")
|
||||
finalizeVerdict(conn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
if verdict < conn.Verdict.Current {
|
||||
verdict = conn.Verdict.Current
|
||||
if verdict < conn.Verdict.Active {
|
||||
verdict = conn.Verdict.Active
|
||||
}
|
||||
|
||||
var err error
|
||||
|
@ -561,17 +614,52 @@ func issueVerdict(conn *network.Connection, pkt packet.Packet, verdict network.V
|
|||
}
|
||||
}
|
||||
|
||||
func finalizeVerdict(conn *network.Connection) {
|
||||
// previously accepted or tunneled connections may need to be blocked
|
||||
if conn.Verdict.Current == network.VerdictAccept {
|
||||
switch {
|
||||
case conn.Verdict.Previous == network.VerdictRerouteToTunnel && !conn.Tunneled:
|
||||
conn.SetVerdictDirectly(network.VerdictBlock)
|
||||
case conn.Verdict.Previous == network.VerdictAccept && conn.Tunneled:
|
||||
conn.SetVerdictDirectly(network.VerdictBlock)
|
||||
case conn.Tunneled:
|
||||
conn.SetVerdictDirectly(network.VerdictRerouteToTunnel)
|
||||
// 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) {
|
||||
// Update worst verdict.
|
||||
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 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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package firewall
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portmaster/netenv"
|
||||
|
@ -16,7 +17,7 @@ import (
|
|||
"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.
|
||||
switch {
|
||||
case !tunnelEnabled():
|
||||
|
@ -28,9 +29,12 @@ func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Pa
|
|||
case conn.Inbound:
|
||||
// Can't tunnel incoming connections.
|
||||
return
|
||||
case conn.Verdict.Current != network.VerdictAccept:
|
||||
case conn.Verdict.Firewall != network.VerdictAccept:
|
||||
// Connection will be blocked.
|
||||
return
|
||||
case conn.IPProtocol != packet.TCP && conn.IPProtocol != packet.UDP:
|
||||
// Unsupported protocol.
|
||||
return
|
||||
case conn.Process().Pid == ownPID:
|
||||
// Bypass tunneling for certain own connections.
|
||||
switch {
|
||||
|
@ -101,11 +105,22 @@ func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Pa
|
|||
// Check if ready.
|
||||
if !captain.ClientReady() {
|
||||
// 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", "")
|
||||
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.
|
||||
conn.TunnelOpts = &navigator.Options{
|
||||
HubPolicies: layeredProfile.StackedExitHubPolicies(),
|
||||
|
@ -150,13 +165,11 @@ func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Pa
|
|||
}
|
||||
|
||||
// Queue request in sluice.
|
||||
err = sluice.AwaitRequest(conn, crew.HandleSluiceRequest)
|
||||
err := sluice.AwaitRequest(conn, crew.HandleSluiceRequest)
|
||||
if err != nil {
|
||||
log.Tracer(pkt.Ctx()).Warningf("failed to request tunneling: %s", 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
|
||||
return err
|
||||
}
|
||||
|
||||
log.Tracer(ctx).Trace("filter: tunneling requested")
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
|
|||
conn.Resolver = rrCache.Resolver
|
||||
}
|
||||
|
||||
switch conn.Verdict.Current {
|
||||
switch conn.Verdict.Active {
|
||||
// We immediately save blocked, dropped or failed verdicts so
|
||||
// they pop up in the UI.
|
||||
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:
|
||||
fallthrough
|
||||
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.
|
||||
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:
|
||||
tracer.Infof(
|
||||
"nameserver: returning %s response for %s to %s",
|
||||
conn.Verdict.Current.Verb(),
|
||||
conn.VerdictVerb(),
|
||||
q.ID(),
|
||||
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.
|
||||
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:
|
||||
tracer.Infof(
|
||||
"nameserver: returning %s response for %s to %s",
|
||||
conn.Verdict.Current.Verb(),
|
||||
conn.VerdictVerb(),
|
||||
q.ID(),
|
||||
conn.Process(),
|
||||
)
|
||||
|
@ -338,7 +338,7 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, request *dns.Msg)
|
|||
}
|
||||
tracer.Infof(
|
||||
"nameserver: returning %s response (%s%s) for %s to %s",
|
||||
conn.Verdict.Current.Verb(),
|
||||
conn.VerdictVerb(),
|
||||
dns.RcodeToString[rrCache.RCode],
|
||||
noAnswerIndicator,
|
||||
q.ID(),
|
||||
|
|
|
@ -155,7 +155,7 @@ func convertConnection(conn *network.Connection) (*Conn, error) {
|
|||
IPProtocol: conn.IPProtocol,
|
||||
LocalIP: conn.LocalIP.String(),
|
||||
LocalPort: conn.LocalPort,
|
||||
Verdict: conn.Verdict.User,
|
||||
Verdict: conn.Verdict.Firewall, // TODO: Expose both Worst and Firewall verdicts.
|
||||
Started: time.Unix(conn.Started, 0),
|
||||
Tunneled: conn.Tunneled,
|
||||
Encrypted: conn.Encrypted,
|
||||
|
@ -177,7 +177,7 @@ func convertConnection(conn *network.Connection) (*Conn, error) {
|
|||
c.Type = ""
|
||||
}
|
||||
|
||||
switch conn.Verdict.User {
|
||||
switch conn.Verdict.Firewall {
|
||||
case network.VerdictAccept, network.VerdictRerouteToNameserver, network.VerdictRerouteToTunnel:
|
||||
accepted := true
|
||||
c.Allowed = &accepted
|
||||
|
|
|
@ -152,7 +152,7 @@ func AddNetworkDebugData(di *debug.Info, profile, where string) {
|
|||
|
||||
// Count.
|
||||
total++
|
||||
switch conn.Verdict.Current { //nolint:exhaustive
|
||||
switch conn.Verdict.Firewall { //nolint:exhaustive
|
||||
case VerdictAccept,
|
||||
VerdictRerouteToNameserver,
|
||||
VerdictRerouteToTunnel:
|
||||
|
|
|
@ -41,13 +41,13 @@ var connectionTestData = []*Connection{
|
|||
ASN: 0,
|
||||
},
|
||||
Verdict: struct {
|
||||
Current Verdict
|
||||
Previous Verdict
|
||||
User Verdict
|
||||
Worst Verdict
|
||||
Active Verdict
|
||||
Firewall Verdict
|
||||
}{
|
||||
Current: 2,
|
||||
Previous: 2,
|
||||
User: 2,
|
||||
Worst: 2,
|
||||
Active: 2,
|
||||
Firewall: 2,
|
||||
},
|
||||
Reason: Reason{
|
||||
Msg: "incoming connection blocked by default",
|
||||
|
@ -89,13 +89,13 @@ var connectionTestData = []*Connection{
|
|||
ASN: 16509,
|
||||
},
|
||||
Verdict: struct {
|
||||
Current Verdict
|
||||
Previous Verdict
|
||||
User Verdict
|
||||
Worst Verdict
|
||||
Active Verdict
|
||||
Firewall Verdict
|
||||
}{
|
||||
Current: 2,
|
||||
Previous: 2,
|
||||
User: 2,
|
||||
Worst: 2,
|
||||
Active: 2,
|
||||
Firewall: 2,
|
||||
},
|
||||
Reason: Reason{
|
||||
Msg: "default permit",
|
||||
|
@ -140,13 +140,13 @@ var connectionTestData = []*Connection{
|
|||
ASN: 15169,
|
||||
},
|
||||
Verdict: struct {
|
||||
Current Verdict
|
||||
Previous Verdict
|
||||
User Verdict
|
||||
Worst Verdict
|
||||
Active Verdict
|
||||
Firewall Verdict
|
||||
}{
|
||||
Current: 2,
|
||||
Previous: 2,
|
||||
User: 2,
|
||||
Worst: 2,
|
||||
Active: 2,
|
||||
Firewall: 2,
|
||||
},
|
||||
Reason: Reason{
|
||||
Msg: "default permit",
|
||||
|
|
|
@ -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
|
||||
// connection lock.
|
||||
Verdict struct {
|
||||
// Current is the current decision that has been made for a connection.
|
||||
Current Verdict
|
||||
// Previous holds the previous verdict value, if there wasn't previous it will VerdictUndecided
|
||||
Previous Verdict
|
||||
// User holds the verdict that should be displayed in the user interface
|
||||
User Verdict
|
||||
// Worst verdict holds the worst verdict that was assigned to this
|
||||
// connection from a privacy/security perspective.
|
||||
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 holsd the last (most recent) decision by the firewall.
|
||||
Firewall Verdict
|
||||
}
|
||||
// Reason holds information justifying the verdict, as well as additional
|
||||
// information about the reason.
|
||||
|
@ -524,8 +527,6 @@ func (conn *Connection) Failed(reason, reasonOptionKey string) {
|
|||
func (conn *Connection) SetVerdict(newVerdict Verdict, reason, reasonOptionKey string, reasonCtx interface{}) (ok bool) {
|
||||
conn.SetVerdictDirectly(newVerdict)
|
||||
|
||||
// Only set if it matches the user verdict. For a consistent reason
|
||||
if newVerdict == conn.Verdict.User {
|
||||
conn.Reason.Msg = reason
|
||||
conn.Reason.Context = reasonCtx
|
||||
|
||||
|
@ -535,24 +536,26 @@ func (conn *Connection) SetVerdict(newVerdict Verdict, reason, reasonOptionKey s
|
|||
conn.Reason.OptionKey = reasonOptionKey
|
||||
conn.Reason.Profile = conn.Process().Profile().GetProfileSource(conn.Reason.OptionKey)
|
||||
}
|
||||
|
||||
return true // TODO: remove
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// SetVerdictDirectly sets the new verdict and stores the previous value.
|
||||
// SetVerdictDirectly sets the firewall verdict.
|
||||
func (conn *Connection) SetVerdictDirectly(newVerdict Verdict) {
|
||||
if newVerdict == conn.Verdict.Current {
|
||||
return
|
||||
conn.Verdict.Firewall = newVerdict
|
||||
}
|
||||
// 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
|
||||
if conn.Verdict.User != VerdictAccept {
|
||||
conn.Verdict.User = newVerdict
|
||||
// VerdictVerb returns the verdict as a verb, while taking any special states
|
||||
// into account.
|
||||
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.
|
||||
|
@ -679,7 +682,7 @@ func packetHandlerHandleConn(conn *Connection, pkt packet.Packet) {
|
|||
}
|
||||
|
||||
// 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.
|
||||
log.Tracer(pkt.Ctx()).Submit()
|
||||
|
||||
|
|
|
@ -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.
|
||||
func (conn *Connection) ReplyWithDNS(ctx context.Context, request *dns.Msg) *dns.Msg {
|
||||
// Select request responder.
|
||||
switch conn.Verdict.Current {
|
||||
switch conn.Verdict.Active {
|
||||
case VerdictBlock:
|
||||
return nsutil.BlockIP().ReplyWithDNS(ctx, request)
|
||||
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 {
|
||||
// Select level to add the verdict record with.
|
||||
var level log.Severity
|
||||
switch conn.Verdict.Current {
|
||||
switch conn.Verdict.Active {
|
||||
case VerdictFailed:
|
||||
level = log.ErrorLevel
|
||||
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.
|
||||
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 {
|
||||
log.Tracer(ctx).Warningf("filter: failed to add informational record to reply: %s", err)
|
||||
return nil
|
||||
|
|
|
@ -119,7 +119,7 @@ func (conn *Connection) addToMetrics() {
|
|||
}
|
||||
|
||||
// Check the verdict.
|
||||
switch conn.Verdict.Current { //nolint:exhaustive // Not critical.
|
||||
switch conn.Verdict.Firewall { //nolint:exhaustive // Not critical.
|
||||
case VerdictBlock, VerdictDrop:
|
||||
blockedOutConnCounter.Inc()
|
||||
conn.addedToMetrics = true
|
||||
|
|
|
@ -46,3 +46,30 @@ func GetProtocolNumber(protocol string) (number uint8, ok bool) {
|
|||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue