mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Add simple packet metrics
This commit is contained in:
parent
c01d61dcd9
commit
7a83e772f4
7 changed files with 181 additions and 17 deletions
|
@ -25,7 +25,18 @@ func Start() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
return start()
|
||||
var ch = Packets
|
||||
if packetMetricsDestination != "" {
|
||||
go metrics.writeMetrics()
|
||||
ch = make(chan packet.Packet)
|
||||
go func() {
|
||||
for p := range ch {
|
||||
Packets <- tracePacket(p)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return start(ch)
|
||||
}
|
||||
|
||||
// Stop starts the interception.
|
||||
|
@ -34,5 +45,7 @@ func Stop() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
close(metrics.done)
|
||||
|
||||
return stop()
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
)
|
||||
|
||||
// start starts the interception.
|
||||
func start() error {
|
||||
func start(ch chan packet.Packet) error {
|
||||
log.Info("interception: this platform has no support for packet interception - a lot of functionality will be broken")
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package interception
|
||||
|
||||
import "github.com/safing/portmaster/network/packet"
|
||||
|
||||
// start starts the interception.
|
||||
func start() error {
|
||||
return StartNfqueueInterception()
|
||||
func start(ch chan packet.Packet) error {
|
||||
return StartNfqueueInterception(ch)
|
||||
}
|
||||
|
||||
// stop starts the interception.
|
||||
|
|
|
@ -7,11 +7,12 @@ import (
|
|||
"github.com/safing/portbase/notifications"
|
||||
"github.com/safing/portbase/utils/osdetail"
|
||||
"github.com/safing/portmaster/firewall/interception/windowskext"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
"github.com/safing/portmaster/updates"
|
||||
)
|
||||
|
||||
// start starts the interception.
|
||||
func start() error {
|
||||
func start(ch chan packet.Packet) error {
|
||||
dllFile, err := updates.GetPlatformFile("kext/portmaster-kext.dll")
|
||||
if err != nil {
|
||||
return fmt.Errorf("interception: could not get kext dll: %s", err)
|
||||
|
@ -31,7 +32,7 @@ func start() error {
|
|||
return fmt.Errorf("interception: could not start windows kext: %s", err)
|
||||
}
|
||||
|
||||
go windowskext.Handler(Packets)
|
||||
go windowskext.Handler(ch)
|
||||
go handleWindowsDNSCache()
|
||||
|
||||
return nil
|
||||
|
|
78
firewall/interception/introspection.go
Normal file
78
firewall/interception/introspection.go
Normal file
|
@ -0,0 +1,78 @@
|
|||
package interception
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
)
|
||||
|
||||
var (
|
||||
packetMetricsDestination string
|
||||
metrics = &packetMetrics{
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&packetMetricsDestination, "packet-metrics", "", "Write packet metrics")
|
||||
}
|
||||
|
||||
type (
|
||||
performanceRecord struct {
|
||||
start int64
|
||||
duration time.Duration
|
||||
verdict string
|
||||
}
|
||||
|
||||
packetMetrics struct {
|
||||
done chan struct{}
|
||||
l sync.Mutex
|
||||
records []*performanceRecord
|
||||
}
|
||||
)
|
||||
|
||||
func (pm *packetMetrics) record(tp *tracedPacket, verdict string) {
|
||||
go func(start int64, duration time.Duration) {
|
||||
pm.l.Lock()
|
||||
defer pm.l.Unlock()
|
||||
|
||||
pm.records = append(pm.records, &performanceRecord{
|
||||
start: start,
|
||||
duration: duration,
|
||||
verdict: verdict,
|
||||
})
|
||||
}(tp.start.UnixNano(), time.Since(tp.start))
|
||||
}
|
||||
|
||||
func (pm *packetMetrics) writeMetrics() {
|
||||
if packetMetricsDestination == "" {
|
||||
return
|
||||
}
|
||||
|
||||
f, err := os.Create(packetMetricsDestination)
|
||||
if err != nil {
|
||||
log.Errorf("Failed to create packet metrics file: %s", err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-pm.done:
|
||||
return
|
||||
case <-time.After(time.Second * 5):
|
||||
}
|
||||
pm.l.Lock()
|
||||
records := pm.records
|
||||
pm.records = nil
|
||||
pm.l.Unlock()
|
||||
|
||||
for _, r := range records {
|
||||
fmt.Fprintf(f, "%d;%s;%s;%.2f\n", r.start, r.verdict, r.duration, float64(r.duration)/float64(time.Microsecond))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -223,7 +223,7 @@ func deactivateIPTables(protocol iptables.Protocol, rules, chains []string) erro
|
|||
}
|
||||
|
||||
// StartNfqueueInterception starts the nfqueue interception.
|
||||
func StartNfqueueInterception() (err error) {
|
||||
func StartNfqueueInterception(packets chan<- packet.Packet) (err error) {
|
||||
// @deprecated, remove in v1
|
||||
if experimentalNfqueueBackend {
|
||||
log.Warningf("[DEPRECATED] --experimental-nfqueue has been deprecated as the backend is now used by default")
|
||||
|
@ -257,7 +257,7 @@ func StartNfqueueInterception() (err error) {
|
|||
return fmt.Errorf("nfqueue(IPv6, in): %w", err)
|
||||
}
|
||||
|
||||
go handleInterception()
|
||||
go handleInterception(packets)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -286,23 +286,26 @@ func StopNfqueueInterception() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func handleInterception() {
|
||||
func handleInterception(packets chan<- packet.Packet) {
|
||||
for {
|
||||
var pkt packet.Packet
|
||||
select {
|
||||
case <-shutdownSignal:
|
||||
return
|
||||
case pkt := <-out4Queue.PacketChannel():
|
||||
case pkt = <-out4Queue.PacketChannel():
|
||||
pkt.SetOutbound()
|
||||
Packets <- pkt
|
||||
case pkt := <-in4Queue.PacketChannel():
|
||||
case pkt = <-in4Queue.PacketChannel():
|
||||
pkt.SetInbound()
|
||||
Packets <- pkt
|
||||
case pkt := <-out6Queue.PacketChannel():
|
||||
case pkt = <-out6Queue.PacketChannel():
|
||||
pkt.SetOutbound()
|
||||
Packets <- pkt
|
||||
case pkt := <-in6Queue.PacketChannel():
|
||||
case pkt = <-in6Queue.PacketChannel():
|
||||
pkt.SetInbound()
|
||||
Packets <- pkt
|
||||
}
|
||||
|
||||
select {
|
||||
case packets <- pkt:
|
||||
case <-shutdownSignal:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
67
firewall/interception/packet_tracer.go
Normal file
67
firewall/interception/packet_tracer.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package interception
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
)
|
||||
|
||||
type tracedPacket struct {
|
||||
start time.Time
|
||||
packet.Packet
|
||||
}
|
||||
|
||||
func tracePacket(p packet.Packet) packet.Packet {
|
||||
return &tracedPacket{
|
||||
start: time.Now(),
|
||||
Packet: p,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *tracedPacket) markServed(v string) {
|
||||
if packetMetricsDestination == "" {
|
||||
return
|
||||
}
|
||||
|
||||
metrics.record(p, v)
|
||||
}
|
||||
|
||||
func (p *tracedPacket) Accept() error {
|
||||
defer p.markServed("accept")
|
||||
return p.Packet.Accept()
|
||||
}
|
||||
|
||||
func (p *tracedPacket) Block() error {
|
||||
defer p.markServed("block")
|
||||
return p.Packet.Block()
|
||||
}
|
||||
|
||||
func (p *tracedPacket) Drop() error {
|
||||
defer p.markServed("drop")
|
||||
return p.Packet.Drop()
|
||||
}
|
||||
|
||||
func (p *tracedPacket) PermanentAccept() error {
|
||||
defer p.markServed("perm-accept")
|
||||
return p.Packet.PermanentAccept()
|
||||
}
|
||||
|
||||
func (p *tracedPacket) PermanentBlock() error {
|
||||
defer p.markServed("perm-block")
|
||||
return p.Packet.PermanentBlock()
|
||||
}
|
||||
|
||||
func (p *tracedPacket) PermanentDrop() error {
|
||||
defer p.markServed("perm-drop")
|
||||
return p.Packet.PermanentDrop()
|
||||
}
|
||||
|
||||
func (p *tracedPacket) RerouteToNameserver() error {
|
||||
defer p.markServed("reroute-ns")
|
||||
return p.Packet.RerouteToNameserver()
|
||||
}
|
||||
|
||||
func (p *tracedPacket) RerouteToTunnel() error {
|
||||
defer p.markServed("reroute-tunnel")
|
||||
return p.Packet.RerouteToTunnel()
|
||||
}
|
Loading…
Add table
Reference in a new issue