mirror of
https://github.com/safing/portmaster
synced 2025-09-02 10:39:22 +00:00
Add bandwidth stats support
This commit is contained in:
parent
e308543f4f
commit
7babfb13ab
6 changed files with 185 additions and 75 deletions
|
@ -30,14 +30,30 @@ func startInterception(packets chan packet.Packet) error {
|
||||||
|
|
||||||
// Start packet handler.
|
// Start packet handler.
|
||||||
module.StartServiceWorker("kext packet handler", 0, func(ctx context.Context) error {
|
module.StartServiceWorker("kext packet handler", 0, func(ctx context.Context) error {
|
||||||
windowskext.Handler(ctx, packets)
|
windowskext.Handler(ctx, packets, BandwidthUpdates)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
// Start bandwidth stats monitor.
|
// Start bandwidth stats monitor.
|
||||||
// module.StartServiceWorker("kext bandwidth stats monitor", 0, func(ctx context.Context) error {
|
module.StartServiceWorker("kext bandwidth request worker", 0, func(ctx context.Context) error {
|
||||||
// return windowskext.BandwidthStatsWorker(ctx, 1*time.Second, BandwidthUpdates)
|
timer := time.NewTicker(1 * time.Second)
|
||||||
// })
|
for {
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
{
|
||||||
|
err := windowskext.SendBandwidthStatsRequest()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case <-ctx.Done():
|
||||||
|
{
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Start kext logging. The worker will periodically send request to the kext to send logs.
|
// Start kext logging. The worker will periodically send request to the kext to send logs.
|
||||||
module.StartServiceWorker("kext log request worker", 0, func(ctx context.Context) error {
|
module.StartServiceWorker("kext log request worker", 0, func(ctx context.Context) error {
|
||||||
|
|
|
@ -81,7 +81,7 @@ func reportBandwidth(ctx context.Context, bandwidthUpdates chan *packet.Bandwidt
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartBandwithConsoleLogger() {
|
func StartBandwidthConsoleLogger() {
|
||||||
go func() {
|
go func() {
|
||||||
ticker := time.NewTicker(2 * time.Second)
|
ticker := time.NewTicker(2 * time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
|
@ -6,6 +6,7 @@ package windowskext
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/safing/portmaster/process"
|
"github.com/safing/portmaster/process"
|
||||||
|
@ -28,7 +29,7 @@ func (v *VersionInfo) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handler transforms received packets to the Packet interface.
|
// Handler transforms received packets to the Packet interface.
|
||||||
func Handler(ctx context.Context, packets chan packet.Packet) {
|
func Handler(ctx context.Context, packets chan packet.Packet, bandwidthUpdate chan *packet.BandwidthUpdate) {
|
||||||
for {
|
for {
|
||||||
packetInfo, err := RecvVerdictRequest()
|
packetInfo, err := RecvVerdictRequest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -36,9 +37,11 @@ func Handler(ctx context.Context, packets chan packet.Packet) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if packetInfo.Connection != nil {
|
switch {
|
||||||
log.Tracef("packet: %+v", packetInfo.Connection)
|
case packetInfo.ConnectionV4 != nil:
|
||||||
conn := packetInfo.Connection
|
{
|
||||||
|
log.Tracef("packet: %+v", packetInfo.ConnectionV4)
|
||||||
|
conn := packetInfo.ConnectionV4
|
||||||
// New Packet
|
// New Packet
|
||||||
new := &Packet{
|
new := &Packet{
|
||||||
verdictRequest: conn.Id,
|
verdictRequest: conn.Id,
|
||||||
|
@ -85,22 +88,106 @@ func Handler(ctx context.Context, packets chan packet.Packet) {
|
||||||
|
|
||||||
packets <- new
|
packets <- new
|
||||||
}
|
}
|
||||||
|
case packetInfo.ConnectionV6 != nil:
|
||||||
|
{
|
||||||
|
log.Tracef("packet: %+v", packetInfo.ConnectionV6)
|
||||||
|
conn := packetInfo.ConnectionV6
|
||||||
|
// New Packet
|
||||||
|
new := &Packet{
|
||||||
|
verdictRequest: conn.Id,
|
||||||
|
verdictSet: abool.NewBool(false),
|
||||||
|
}
|
||||||
|
info := new.Info()
|
||||||
|
info.Inbound = conn.Direction > 0
|
||||||
|
info.InTunnel = false
|
||||||
|
info.Protocol = packet.IPProtocol(conn.Protocol)
|
||||||
|
info.PID = int(conn.ProcessId)
|
||||||
|
info.SeenAt = time.Now()
|
||||||
|
|
||||||
// if packetInfo.LogLines != nil {
|
// Check PID
|
||||||
// for _, line := range *packetInfo.LogLines {
|
if info.PID == 0 {
|
||||||
// switch line.Severity {
|
// Windows does not have zero PIDs.
|
||||||
// case int(log.DebugLevel):
|
// Set to UndefinedProcessID.
|
||||||
// log.Debugf("kext: %s", line.Line)
|
info.PID = process.UndefinedProcessID
|
||||||
// case int(log.InfoLevel):
|
}
|
||||||
// log.Infof("kext: %s", line.Line)
|
|
||||||
// case int(log.WarningLevel):
|
// Set IP version
|
||||||
// log.Warningf("kext: %s", line.Line)
|
info.Version = packet.IPv6
|
||||||
// case int(log.ErrorLevel):
|
|
||||||
// log.Errorf("kext: %s", line.Line)
|
// Set IPs
|
||||||
// case int(log.CriticalLevel):
|
if info.Inbound {
|
||||||
// log.Criticalf("kext: %s", line.Line)
|
// Inbound
|
||||||
// }
|
info.Src = conn.RemoteIp[:]
|
||||||
// }
|
info.Dst = conn.LocalIp[:]
|
||||||
// }
|
} else {
|
||||||
|
// Outbound
|
||||||
|
info.Src = conn.LocalIp[:]
|
||||||
|
info.Dst = conn.RemoteIp[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set Ports
|
||||||
|
if info.Inbound {
|
||||||
|
// Inbound
|
||||||
|
info.SrcPort = conn.RemotePort
|
||||||
|
info.DstPort = conn.LocalPort
|
||||||
|
} else {
|
||||||
|
// Outbound
|
||||||
|
info.SrcPort = conn.LocalPort
|
||||||
|
info.DstPort = conn.RemotePort
|
||||||
|
}
|
||||||
|
|
||||||
|
packets <- new
|
||||||
|
}
|
||||||
|
case packetInfo.LogLine != nil:
|
||||||
|
{
|
||||||
|
line := packetInfo.LogLine
|
||||||
|
switch line.Severity {
|
||||||
|
case byte(log.DebugLevel):
|
||||||
|
log.Debugf("kext: %s", line.Line)
|
||||||
|
case byte(log.InfoLevel):
|
||||||
|
log.Infof("kext: %s", line.Line)
|
||||||
|
case byte(log.WarningLevel):
|
||||||
|
log.Warningf("kext: %s", line.Line)
|
||||||
|
case byte(log.ErrorLevel):
|
||||||
|
log.Errorf("kext: %s", line.Line)
|
||||||
|
case byte(log.CriticalLevel):
|
||||||
|
log.Criticalf("kext: %s", line.Line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case packetInfo.BandwidthStats != nil:
|
||||||
|
{
|
||||||
|
bandwidthStats := packetInfo.BandwidthStats
|
||||||
|
for _, stat := range bandwidthStats.ValuesV4 {
|
||||||
|
connID := packet.CreateConnectionID(
|
||||||
|
packet.IPProtocol(bandwidthStats.Protocol),
|
||||||
|
net.IP(stat.LocalIP[:]), stat.LocalPort,
|
||||||
|
net.IP(stat.RemoteIP[:]), stat.RemotePort,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
update := &packet.BandwidthUpdate{
|
||||||
|
ConnID: connID,
|
||||||
|
BytesReceived: stat.ReceivedBytes,
|
||||||
|
BytesSent: stat.TransmittedBytes,
|
||||||
|
Method: packet.Additive,
|
||||||
|
}
|
||||||
|
bandwidthUpdate <- update
|
||||||
|
}
|
||||||
|
for _, stat := range bandwidthStats.ValuesV6 {
|
||||||
|
connID := packet.CreateConnectionID(
|
||||||
|
packet.IPProtocol(bandwidthStats.Protocol),
|
||||||
|
net.IP(stat.LocalIP[:]), stat.LocalPort,
|
||||||
|
net.IP(stat.RemoteIP[:]), stat.RemotePort,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
update := &packet.BandwidthUpdate{
|
||||||
|
ConnID: connID,
|
||||||
|
BytesReceived: stat.ReceivedBytes,
|
||||||
|
BytesSent: stat.TransmittedBytes,
|
||||||
|
Method: packet.Additive,
|
||||||
|
}
|
||||||
|
bandwidthUpdate <- update
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,37 +77,41 @@ func Stop() error {
|
||||||
|
|
||||||
// Sends a shutdown request.
|
// Sends a shutdown request.
|
||||||
func shutdownRequest() error {
|
func shutdownRequest() error {
|
||||||
return kext_interface.WriteShutdownCommand(kextFile)
|
return kext_interface.SendShutdownCommand(kextFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send request for logs of the kext.
|
// Send request for logs of the kext.
|
||||||
func SendLogRequest() error {
|
func SendLogRequest() error {
|
||||||
return kext_interface.WriteGetLogsCommand(kextFile)
|
return kext_interface.SendGetLogsCommand(kextFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SendBandwidthStatsRequest() error {
|
||||||
|
return kext_interface.SendGetBandwidthStatsCommand(kextFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RecvVerdictRequest waits for the next verdict request from the kext. If a timeout is reached, both *VerdictRequest and error will be nil.
|
// RecvVerdictRequest waits for the next verdict request from the kext. If a timeout is reached, both *VerdictRequest and error will be nil.
|
||||||
func RecvVerdictRequest() (*kext_interface.Info, error) {
|
func RecvVerdictRequest() (*kext_interface.Info, error) {
|
||||||
return kext_interface.ReadInfo(kextFile)
|
return kext_interface.RecvInfo(kextFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetVerdict sets the verdict for a packet and/or connection.
|
// SetVerdict sets the verdict for a packet and/or connection.
|
||||||
func SetVerdict(pkt *Packet, verdict network.Verdict) error {
|
func SetVerdict(pkt *Packet, verdict network.Verdict) error {
|
||||||
if verdict == network.VerdictRerouteToNameserver {
|
if verdict == network.VerdictRerouteToNameserver {
|
||||||
redirect := kext_interface.RedirectV4{Id: pkt.verdictRequest, RemoteAddress: [4]uint8{127, 0, 0, 1}, RemotePort: 53}
|
redirect := kext_interface.RedirectV4{Id: pkt.verdictRequest, RemoteAddress: [4]uint8{127, 0, 0, 1}, RemotePort: 53}
|
||||||
kext_interface.WriteRedirectCommand(kextFile, redirect)
|
kext_interface.SendRedirectV4Command(kextFile, redirect)
|
||||||
} else if verdict == network.VerdictRerouteToTunnel {
|
} else if verdict == network.VerdictRerouteToTunnel {
|
||||||
redirect := kext_interface.RedirectV4{Id: pkt.verdictRequest, RemoteAddress: [4]uint8{192, 168, 122, 196}, RemotePort: 717}
|
redirect := kext_interface.RedirectV4{Id: pkt.verdictRequest, RemoteAddress: [4]uint8{192, 168, 122, 196}, RemotePort: 717}
|
||||||
kext_interface.WriteRedirectCommand(kextFile, redirect)
|
kext_interface.SendRedirectV4Command(kextFile, redirect)
|
||||||
} else {
|
} else {
|
||||||
verdict := kext_interface.Verdict{Id: pkt.verdictRequest, Verdict: uint8(verdict)}
|
verdict := kext_interface.Verdict{Id: pkt.verdictRequest, Verdict: uint8(verdict)}
|
||||||
kext_interface.WriteVerdictCommand(kextFile, verdict)
|
kext_interface.SendVerdictCommand(kextFile, verdict)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears the internal connection cache.
|
// Clears the internal connection cache.
|
||||||
func ClearCache() error {
|
func ClearCache() error {
|
||||||
return kext_interface.WriteClearCacheCommand(kextFile)
|
return kext_interface.SendClearCacheCommand(kextFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates a specific connection verdict.
|
// Updates a specific connection verdict.
|
||||||
|
@ -134,7 +138,7 @@ func UpdateVerdict(conn *network.Connection) error {
|
||||||
RedirectPort: uint16(redirectPort),
|
RedirectPort: uint16(redirectPort),
|
||||||
}
|
}
|
||||||
|
|
||||||
kext_interface.WriteUpdateCommand(kextFile, update)
|
kext_interface.SendUpdateV4Command(kextFile, update)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
package windowskext
|
package windowskext
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/tevino/abool"
|
"github.com/tevino/abool"
|
||||||
|
@ -42,7 +43,7 @@ func (pkt *Packet) ExpectInfo() bool {
|
||||||
|
|
||||||
// GetPayload returns the full raw packet.
|
// GetPayload returns the full raw packet.
|
||||||
func (pkt *Packet) LoadPacketData() error {
|
func (pkt *Packet) LoadPacketData() error {
|
||||||
return nil
|
return fmt.Errorf("Not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accept accepts the packet.
|
// Accept accepts the packet.
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -7,6 +7,8 @@ toolchain go1.21.2
|
||||||
// TODO: Remove when https://github.com/tc-hib/winres/pull/4 is merged or changes are otherwise integrated.
|
// TODO: Remove when https://github.com/tc-hib/winres/pull/4 is merged or changes are otherwise integrated.
|
||||||
replace github.com/tc-hib/winres => github.com/dhaavi/winres v0.2.2
|
replace github.com/tc-hib/winres => github.com/dhaavi/winres v0.2.2
|
||||||
|
|
||||||
|
replace github.com/vlabo/portmaster_windows_rust_kext/kext_interface => /home/vladimir/Dev/Safing/portmaster_windows_rust_kext/kext_interface
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Xuanwo/go-locale v1.1.0
|
github.com/Xuanwo/go-locale v1.1.0
|
||||||
github.com/agext/levenshtein v1.2.3
|
github.com/agext/levenshtein v1.2.3
|
||||||
|
|
Loading…
Add table
Reference in a new issue