Add and improve InfoOnly and ExpectInfo packet flags

This commit is contained in:
Daniel
2023-07-18 16:16:41 +02:00
parent 83479acc95
commit 28d3d24988
8 changed files with 78 additions and 8 deletions

View File

@@ -173,9 +173,13 @@ func interceptionStart() error {
getConfig() getConfig()
startAPIAuth() startAPIAuth()
interceptionModule.StartServiceWorker("stat logger", 0, statLogger)
interceptionModule.StartServiceWorker("packet handler", 0, packetHandler) interceptionModule.StartServiceWorker("packet handler", 0, packetHandler)
// Start stat logger if logging is set to trace.
if log.GetLogLevel() == log.TraceLevel {
interceptionModule.StartServiceWorker("stat logger", 0, statLogger)
}
return interception.Start() return interception.Start()
} }
@@ -543,6 +547,11 @@ func inspectAndVerdictHandler(conn *network.Connection, pkt packet.Packet) {
} }
func issueVerdict(conn *network.Connection, pkt packet.Packet, verdict network.Verdict, allowPermanent bool) { func issueVerdict(conn *network.Connection, pkt packet.Packet, verdict network.Verdict, allowPermanent bool) {
// Check if packed was already fast-tracked by the OS integration.
if pkt.FastTrackedByIntegration() {
return
}
// enable permanent verdict // enable permanent verdict
if allowPermanent && !conn.VerdictPermanent { if allowPermanent && !conn.VerdictPermanent {
conn.VerdictPermanent = permanentVerdicts() conn.VerdictPermanent = permanentVerdicts()

View File

@@ -13,6 +13,12 @@ type infoPacket struct {
pmpacket.Base pmpacket.Base
} }
// InfoOnly returns whether the packet is informational only and does not
// represent an actual packet.
func (pkt *infoPacket) InfoOnly() bool {
return true
}
// LoadPacketData does nothing on Linux, as data is always fully parsed. // LoadPacketData does nothing on Linux, as data is always fully parsed.
func (pkt *infoPacket) LoadPacketData() error { func (pkt *infoPacket) LoadPacketData() error {
return fmt.Errorf("can't load data in info only packet") return fmt.Errorf("can't load data in info only packet")

View File

@@ -1,3 +1,6 @@
//go:build windows
// +build windows
package windowskext package windowskext
// This file contains example code how to read bandwidth stats from the kext. Its not ment to be used in production. // This file contains example code how to read bandwidth stats from the kext. Its not ment to be used in production.

View File

@@ -30,6 +30,11 @@ const (
// connection that was intercepted on an ALE layer instead of in the network // connection that was intercepted on an ALE layer instead of in the network
// stack itself. Thus, no packet data is available. // stack itself. Thus, no packet data is available.
VerdictRequestFlagSocketAuth = 2 VerdictRequestFlagSocketAuth = 2
// VerdictRequestFlagExpectSocketAuth indicates that the next verdict
// requests is expected to be an informational socket auth request from
// the ALE layer.
VerdictRequestFlagExpectSocketAuth = 4
) )
// Do not change the order of the members! The structure is used to communicate with the kernel extension. // Do not change the order of the members! The structure is used to communicate with the kernel extension.

View File

@@ -127,8 +127,10 @@ func RecvVerdictRequest() (*VerdictRequest, error) {
return nil, ErrKextNotReady return nil, ErrKextNotReady
} }
timestamp := time.Now() // DEBUG:
defer log.Tracef("winkext: getting verdict request took %s", time.Since(timestamp)) // timestamp := time.Now()
// defer log.Tracef("winkext: getting verdict request took %s", time.Since(timestamp))
// Initialize struct for the output data // Initialize struct for the output data
var new VerdictRequest var new VerdictRequest

View File

@@ -24,16 +24,21 @@ type Packet struct {
lock sync.Mutex lock sync.Mutex
} }
// FastTrackedByIntegration returns whether the packet has been fast-track
// accepted by the OS integration.
func (pkt *Packet) FastTrackedByIntegration() bool {
return pkt.verdictRequest.flags&VerdictRequestFlagFastTrackPermitted > 0
}
// InfoOnly returns whether the packet is informational only and does not // InfoOnly returns whether the packet is informational only and does not
// represent an actual packet. // represent an actual packet.
func (pkt *Packet) InfoOnly() bool { func (pkt *Packet) InfoOnly() bool {
return pkt.verdictRequest.flags&VerdictRequestFlagSocketAuth > 0 return pkt.verdictRequest.flags&VerdictRequestFlagSocketAuth > 0
} }
// FastTrackedByIntegration returns whether the packet has been fast-track // ExpectInfo returns whether the next packet is expected to be informational only.
// accepted by the OS integration. func (pkt *Packet) ExpectInfo() bool {
func (pkt *Packet) FastTrackedByIntegration() bool { return pkt.verdictRequest.flags&VerdictRequestFlagExpectSocketAuth > 0
return pkt.verdictRequest.flags&VerdictRequestFlagFastTrackPermitted > 0
} }
// GetPayload returns the full raw packet. // GetPayload returns the full raw packet.

View File

@@ -760,12 +760,46 @@ func (conn *Connection) packetHandlerWorker(ctx context.Context) error {
pktQueue = conn.pktQueue pktQueue = conn.pktQueue
}() }()
// pktSeq counts the seen packets.
var pktSeq int
for { for {
select { select {
case pkt := <-pktQueue: case pkt := <-pktQueue:
if pkt == nil { if pkt == nil {
return nil return nil
} }
pktSeq++
// Check if we should expect an(other) info only packet.
// Only wait if this is the first packet and is not an info packet itself.
if pktSeq == 1 && pkt.ExpectInfo() && !pkt.InfoOnly() {
// Debug: FIXME
// log.Debugf("filter: waiting for info only packet in order to pull forward: %s", pkt)
select {
case infoPkt := <-pktQueue:
if infoPkt != nil {
// Debug: FIXME
// log.Debugf("filter: packet #%d [pulled forward] info=%v PID=%d packet: %s", pktSeq, pkt.InfoOnly(), pkt.Info().PID, pkt)
packetHandlerHandleConn(ctx, conn, pkt)
pktSeq++
}
case <-time.After(5 * time.Millisecond):
}
}
// Debug: FIXME
// switch {
// case pkt.Info().Inbound:
// log.Debugf("filter: packet #%d info=%v PID=%d packet: %s", pktSeq, pkt.InfoOnly(), pkt.Info().PID, pkt)
// case pktSeq == 1 && !pkt.InfoOnly():
// log.Warningf("filter: packet #%d [should be info only!] info=%v PID=%d packet: %s", pktSeq, pkt.InfoOnly(), pkt.Info().PID, pkt)
// case pktSeq >= 2 && pkt.InfoOnly():
// log.Errorf("filter: packet #%d [should not be info only!] info=%v PID=%d packet: %s", pktSeq, pkt.InfoOnly(), pkt.Info().PID, pkt)
// default:
// log.Debugf("filter: packet #%d info=%v PID=%d packet: %s", pktSeq, pkt.InfoOnly(), pkt.Info().PID, pkt)
// }
packetHandlerHandleConn(ctx, conn, pkt) packetHandlerHandleConn(ctx, conn, pkt)
case <-ctx.Done(): case <-ctx.Done():
@@ -802,7 +836,7 @@ func packetHandlerHandleConn(ctx context.Context, conn *Connection, pkt packet.P
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.Firewall != VerdictUndecided:
tracer.Debugf("filter: connection %s fast-tracked", conn) tracer.Debugf("filter: connection %s fast-tracked", pkt)
default: default:
tracer.Infof("filter: gathered data on connection %s", conn) tracer.Infof("filter: gathered data on connection %s", conn)
} }

View File

@@ -30,6 +30,11 @@ func (pkt *Base) InfoOnly() bool {
return false return false
} }
// ExpectInfo returns whether the next packet is expected to be informational only.
func (pkt *Base) ExpectInfo() bool {
return false
}
// SetCtx sets the packet context. // SetCtx sets the packet context.
func (pkt *Base) SetCtx(ctx context.Context) { func (pkt *Base) SetCtx(ctx context.Context) {
pkt.ctx = ctx pkt.ctx = ctx
@@ -244,6 +249,7 @@ type Packet interface {
RerouteToTunnel() error RerouteToTunnel() error
FastTrackedByIntegration() bool FastTrackedByIntegration() bool
InfoOnly() bool InfoOnly() bool
ExpectInfo() bool
// Info. // Info.
SetCtx(context.Context) SetCtx(context.Context)