mirror of
https://github.com/safing/portmaster
synced 2025-09-02 02:29:12 +00:00
Merge pull request #261 from safing/feature/debug-info
Add Portmaster debug endpoints
This commit is contained in:
commit
d13cfb1bb4
9 changed files with 499 additions and 13 deletions
40
core/api.go
40
core/api.go
|
@ -1,13 +1,17 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
"github.com/safing/portbase/api"
|
"github.com/safing/portbase/api"
|
||||||
"github.com/safing/portbase/log"
|
"github.com/safing/portbase/log"
|
||||||
"github.com/safing/portbase/modules"
|
"github.com/safing/portbase/modules"
|
||||||
|
"github.com/safing/portbase/utils/debug"
|
||||||
|
"github.com/safing/portmaster/status"
|
||||||
"github.com/safing/portmaster/updates"
|
"github.com/safing/portmaster/updates"
|
||||||
)
|
)
|
||||||
|
|
||||||
func registerActions() error {
|
func registerAPIEndpoints() error {
|
||||||
if err := api.RegisterEndpoint(api.Endpoint{
|
if err := api.RegisterEndpoint(api.Endpoint{
|
||||||
Path: "core/shutdown",
|
Path: "core/shutdown",
|
||||||
Read: api.PermitSelf,
|
Read: api.PermitSelf,
|
||||||
|
@ -24,6 +28,22 @@ func registerActions() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := api.RegisterEndpoint(api.Endpoint{
|
||||||
|
Path: "debug/core",
|
||||||
|
Read: api.PermitAnyone,
|
||||||
|
DataFunc: debugInfo,
|
||||||
|
Name: "Get Debug Information",
|
||||||
|
Description: "Returns network debugging information, similar to debug/info, but with system status data.",
|
||||||
|
Parameters: []api.Parameter{{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Field: "style",
|
||||||
|
Value: "github",
|
||||||
|
Description: "Specify the formatting style. The default is simple markdown formatting.",
|
||||||
|
}},
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,3 +61,21 @@ func restart(_ *api.Request) (msg string, err error) {
|
||||||
updates.RestartNow()
|
updates.RestartNow()
|
||||||
return "restart initiated", nil
|
return "restart initiated", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// debugInfo returns the debugging information for support requests.
|
||||||
|
func debugInfo(ar *api.Request) (data []byte, err error) {
|
||||||
|
// Create debug information helper.
|
||||||
|
di := new(debug.Info)
|
||||||
|
di.Style = ar.Request.URL.Query().Get("style")
|
||||||
|
|
||||||
|
// Add debug information.
|
||||||
|
di.AddVersionInfo()
|
||||||
|
di.AddPlatformInfo(ar.Context())
|
||||||
|
status.AddToDebugInfo(di)
|
||||||
|
di.AddLastReportedModuleError()
|
||||||
|
di.AddLastUnexpectedLogs()
|
||||||
|
di.AddGoroutineStack()
|
||||||
|
|
||||||
|
// Return data.
|
||||||
|
return di.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ func start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := registerActions(); err != nil {
|
if err := registerAPIEndpoints(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
284
network/api.go
Normal file
284
network/api.go
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/safing/portbase/api"
|
||||||
|
"github.com/safing/portbase/database/query"
|
||||||
|
"github.com/safing/portbase/utils/debug"
|
||||||
|
"github.com/safing/portmaster/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
func registerAPIEndpoints() error {
|
||||||
|
if err := api.RegisterEndpoint(api.Endpoint{
|
||||||
|
Path: "debug/network",
|
||||||
|
Read: api.PermitUser,
|
||||||
|
DataFunc: debugInfo,
|
||||||
|
Name: "Get Network Debug Information",
|
||||||
|
Description: "Returns network debugging information, similar to debug/core, but with connection data.",
|
||||||
|
Parameters: []api.Parameter{
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Field: "style",
|
||||||
|
Value: "github",
|
||||||
|
Description: "Specify the formatting style. The default is simple markdown formatting.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Field: "profile",
|
||||||
|
Value: "<Source>/<ID>",
|
||||||
|
Description: "Specify a profile source and ID for which network connection should be reported.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Method: http.MethodGet,
|
||||||
|
Field: "where",
|
||||||
|
Value: "<query>",
|
||||||
|
Description: "Specify a query to limit the connections included in the report. The default is to include all connections.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// debugInfo returns the debugging information for support requests.
|
||||||
|
func debugInfo(ar *api.Request) (data []byte, err error) {
|
||||||
|
// Create debug information helper.
|
||||||
|
di := new(debug.Info)
|
||||||
|
di.Style = ar.Request.URL.Query().Get("style")
|
||||||
|
|
||||||
|
// Add debug information.
|
||||||
|
di.AddVersionInfo()
|
||||||
|
di.AddPlatformInfo(ar.Context())
|
||||||
|
status.AddToDebugInfo(di)
|
||||||
|
AddNetworkDebugData(
|
||||||
|
di,
|
||||||
|
ar.Request.URL.Query().Get("profile"),
|
||||||
|
ar.Request.URL.Query().Get("where"),
|
||||||
|
)
|
||||||
|
di.AddLastReportedModuleError()
|
||||||
|
di.AddLastUnexpectedLogs()
|
||||||
|
di.AddGoroutineStack()
|
||||||
|
|
||||||
|
// Return data.
|
||||||
|
return di.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AddNetworkDebugData(di *debug.Info, profile, where string) {
|
||||||
|
// Prepend where prefix to query if necessary.
|
||||||
|
if where != "" && !strings.HasPrefix(where, "where ") {
|
||||||
|
where = "where " + where
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build query.
|
||||||
|
q, err := query.ParseQuery("query network: " + where)
|
||||||
|
if err != nil {
|
||||||
|
di.AddSection(
|
||||||
|
fmt.Sprintf("Network: Debug Failed"),
|
||||||
|
debug.NoFlags,
|
||||||
|
fmt.Sprintf("Failed to build query: %s", err),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get iterator.
|
||||||
|
it, err := dbController.Query(q, true, true)
|
||||||
|
if err != nil {
|
||||||
|
di.AddSection(
|
||||||
|
fmt.Sprintf("Network: Debug Failed"),
|
||||||
|
debug.NoFlags,
|
||||||
|
fmt.Sprintf("Failed to run query: %s", err),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect matching connections.
|
||||||
|
var debugConns []*Connection
|
||||||
|
var accepted int
|
||||||
|
var total int
|
||||||
|
for maybeConn := range it.Next {
|
||||||
|
// Switch to correct type.
|
||||||
|
conn, ok := maybeConn.(*Connection)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the profile matches
|
||||||
|
if profile != "" {
|
||||||
|
found := false
|
||||||
|
|
||||||
|
// Get layer IDs and search for a match.
|
||||||
|
layerIDs := conn.Process().Profile().LayerIDs
|
||||||
|
for _, layerID := range layerIDs {
|
||||||
|
if profile == layerID {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if the profile does not match.
|
||||||
|
if !found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count.
|
||||||
|
total++
|
||||||
|
switch conn.Verdict {
|
||||||
|
case VerdictAccept,
|
||||||
|
VerdictRerouteToNameserver,
|
||||||
|
VerdictRerouteToTunnel:
|
||||||
|
accepted++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to list.
|
||||||
|
debugConns = append(debugConns, conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add it all.
|
||||||
|
di.AddSection(
|
||||||
|
fmt.Sprintf(
|
||||||
|
"Network: %d/%d Connections",
|
||||||
|
accepted,
|
||||||
|
total,
|
||||||
|
),
|
||||||
|
debug.UseCodeSection|debug.AddContentLineBreaks,
|
||||||
|
buildNetworkDebugInfoData(debugConns),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildNetworkDebugInfoData(debugConns []*Connection) string {
|
||||||
|
// Sort
|
||||||
|
sort.Sort(connectionsByStarted(debugConns))
|
||||||
|
|
||||||
|
// Format lines
|
||||||
|
var buf strings.Builder
|
||||||
|
currentBinaryPath := "__"
|
||||||
|
for _, conn := range debugConns {
|
||||||
|
conn.Lock()
|
||||||
|
|
||||||
|
// Add process infomration if it differs from previous connection.
|
||||||
|
if currentBinaryPath != conn.ProcessContext.BinaryPath {
|
||||||
|
if currentBinaryPath != "__" {
|
||||||
|
buf.WriteString("\n\n\n")
|
||||||
|
}
|
||||||
|
buf.WriteString("ProcessName: " + conn.ProcessContext.ProcessName)
|
||||||
|
buf.WriteString("\nProfileName: " + conn.ProcessContext.ProfileName)
|
||||||
|
buf.WriteString("\nBinaryPath: " + conn.ProcessContext.BinaryPath)
|
||||||
|
buf.WriteString("\nProfile: " + conn.ProcessContext.Profile)
|
||||||
|
buf.WriteString("\nSource: " + conn.ProcessContext.Source)
|
||||||
|
buf.WriteString("\n")
|
||||||
|
|
||||||
|
// Set current path in order to not print the process information again.
|
||||||
|
currentBinaryPath = conn.ProcessContext.BinaryPath
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add connection.
|
||||||
|
buf.WriteString("\n")
|
||||||
|
buf.WriteString(conn.debugInfoLine())
|
||||||
|
|
||||||
|
conn.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Connection) debugInfoLine() string {
|
||||||
|
var connectionData string
|
||||||
|
if conn.ID != "" {
|
||||||
|
// Format IP/Port pair for connections.
|
||||||
|
connectionData = fmt.Sprintf(
|
||||||
|
"% 15s:%- 5s %s % 15s:%- 5s",
|
||||||
|
conn.LocalIP,
|
||||||
|
strconv.Itoa(int(conn.LocalPort)),
|
||||||
|
conn.fmtProtocolAndDirectionComponent(conn.IPProtocol.String()),
|
||||||
|
conn.Entity.IP,
|
||||||
|
strconv.Itoa(int(conn.Entity.Port)),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Leave empty for DNS Requests.
|
||||||
|
connectionData = " "
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(
|
||||||
|
"% 14s %s%- 25s %s-%s P#%d [%s] %s - by %s @ %s",
|
||||||
|
conn.Verdict.Verb(),
|
||||||
|
connectionData,
|
||||||
|
conn.fmtDomainComponent(),
|
||||||
|
time.Unix(conn.Started, 0).Format("15:04:05"),
|
||||||
|
conn.fmtEndTimeComponent(),
|
||||||
|
conn.ProcessContext.PID,
|
||||||
|
conn.fmtFlagsComponent(),
|
||||||
|
conn.Reason.Msg,
|
||||||
|
conn.Reason.OptionKey,
|
||||||
|
conn.fmtReasonProfileComponent(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Connection) fmtDomainComponent() string {
|
||||||
|
if conn.Entity.Domain != "" {
|
||||||
|
return " to " + conn.Entity.Domain
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Connection) fmtProtocolAndDirectionComponent(protocol string) string {
|
||||||
|
if conn.Inbound {
|
||||||
|
return "<" + protocol
|
||||||
|
}
|
||||||
|
return protocol + ">"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Connection) fmtFlagsComponent() string {
|
||||||
|
var f string
|
||||||
|
|
||||||
|
if conn.Internal {
|
||||||
|
f += "I"
|
||||||
|
}
|
||||||
|
if conn.Encrypted {
|
||||||
|
f += "E"
|
||||||
|
}
|
||||||
|
if conn.Tunneled {
|
||||||
|
f += "T"
|
||||||
|
}
|
||||||
|
if len(conn.activeInspectors) > 0 {
|
||||||
|
f += "A"
|
||||||
|
}
|
||||||
|
if conn.addedToMetrics {
|
||||||
|
f += "M"
|
||||||
|
}
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Connection) fmtEndTimeComponent() string {
|
||||||
|
if conn.Ended == 0 {
|
||||||
|
return " " // Use same width as a timestamp.
|
||||||
|
}
|
||||||
|
return time.Unix(conn.Ended, 0).Format("15:04:05")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conn *Connection) fmtReasonProfileComponent() string {
|
||||||
|
if conn.Reason.Profile == "" {
|
||||||
|
return "global"
|
||||||
|
}
|
||||||
|
return conn.Reason.Profile
|
||||||
|
}
|
||||||
|
|
||||||
|
type connectionsByStarted []*Connection
|
||||||
|
|
||||||
|
func (a connectionsByStarted) Len() int { return len(a) }
|
||||||
|
func (a connectionsByStarted) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||||
|
func (a connectionsByStarted) Less(i, j int) bool {
|
||||||
|
if a[i].ProcessContext.BinaryPath != a[j].ProcessContext.BinaryPath {
|
||||||
|
return a[i].ProcessContext.BinaryPath < a[j].ProcessContext.BinaryPath
|
||||||
|
}
|
||||||
|
return a[i].Started < a[j].Started
|
||||||
|
}
|
145
network/api_test.go
Normal file
145
network/api_test.go
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
package network
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/safing/portmaster/intel"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDebugInfoLineFormatting(t *testing.T) {
|
||||||
|
for _, conn := range connectionTestData {
|
||||||
|
fmt.Println(conn.debugInfoLine())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDebugInfoFormatting(t *testing.T) {
|
||||||
|
fmt.Println(buildNetworkDebugInfoData(connectionTestData))
|
||||||
|
}
|
||||||
|
|
||||||
|
var connectionTestData = []*Connection{
|
||||||
|
{
|
||||||
|
ID: "17-255.255.255.255-29810-192.168.0.23-40672",
|
||||||
|
Scope: "IL",
|
||||||
|
IPVersion: 4,
|
||||||
|
Inbound: true,
|
||||||
|
IPProtocol: 17,
|
||||||
|
LocalIP: net.ParseIP("255.255.255.255"),
|
||||||
|
LocalPort: 29810,
|
||||||
|
Entity: &intel.Entity{
|
||||||
|
Protocol: 17,
|
||||||
|
Port: 40672,
|
||||||
|
Domain: "",
|
||||||
|
ReverseDomain: "",
|
||||||
|
IP: net.ParseIP("192.168.0.23"),
|
||||||
|
Country: "",
|
||||||
|
ASN: 0,
|
||||||
|
},
|
||||||
|
Verdict: 4,
|
||||||
|
Reason: Reason{
|
||||||
|
Msg: "incoming connection blocked by default",
|
||||||
|
OptionKey: "filter/serviceEndpoints",
|
||||||
|
Profile: "",
|
||||||
|
},
|
||||||
|
Started: 1614010349,
|
||||||
|
Ended: 1614010350,
|
||||||
|
VerdictPermanent: true,
|
||||||
|
Inspecting: false,
|
||||||
|
Tunneled: false,
|
||||||
|
Encrypted: false,
|
||||||
|
ProcessContext: ProcessContext{
|
||||||
|
ProcessName: "Unidentified Processes",
|
||||||
|
ProfileName: "Unidentified Processes",
|
||||||
|
BinaryPath: "",
|
||||||
|
PID: -1,
|
||||||
|
Profile: "_unidentified",
|
||||||
|
Source: "local",
|
||||||
|
},
|
||||||
|
Internal: false,
|
||||||
|
ProfileRevisionCounter: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "6-192.168.0.176-55216-13.32.6.15-80",
|
||||||
|
Scope: "PI",
|
||||||
|
IPVersion: 4,
|
||||||
|
Inbound: false,
|
||||||
|
IPProtocol: 6,
|
||||||
|
LocalIP: net.ParseIP("192.168.0.176"),
|
||||||
|
LocalPort: 55216,
|
||||||
|
Entity: &intel.Entity{
|
||||||
|
Protocol: 6,
|
||||||
|
Port: 80,
|
||||||
|
Domain: "",
|
||||||
|
ReverseDomain: "",
|
||||||
|
IP: net.ParseIP("13.32.6.15"),
|
||||||
|
Country: "DE",
|
||||||
|
ASN: 16509,
|
||||||
|
},
|
||||||
|
Verdict: 2,
|
||||||
|
Reason: Reason{
|
||||||
|
Msg: "default permit",
|
||||||
|
OptionKey: "filter/defaultAction",
|
||||||
|
Profile: "",
|
||||||
|
},
|
||||||
|
Started: 1614010475,
|
||||||
|
Ended: 1614010565,
|
||||||
|
VerdictPermanent: true,
|
||||||
|
Inspecting: false,
|
||||||
|
Tunneled: false,
|
||||||
|
Encrypted: false,
|
||||||
|
ProcessContext: ProcessContext{
|
||||||
|
ProcessName: "NetworkManager",
|
||||||
|
ProfileName: "Network Manager",
|
||||||
|
BinaryPath: "/usr/sbin/NetworkManager",
|
||||||
|
PID: 1273,
|
||||||
|
Profile: "3a9b0eb5-c7fe-4bc7-9b93-a90f4ff84b5b",
|
||||||
|
Source: "local",
|
||||||
|
},
|
||||||
|
Internal: true,
|
||||||
|
ProfileRevisionCounter: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: "6-192.168.0.176-49982-142.250.74.211-443",
|
||||||
|
Scope: "pkg.go.dev.",
|
||||||
|
IPVersion: 4,
|
||||||
|
Inbound: false,
|
||||||
|
IPProtocol: 6,
|
||||||
|
LocalIP: net.ParseIP("192.168.0.176"),
|
||||||
|
LocalPort: 49982,
|
||||||
|
Entity: &intel.Entity{
|
||||||
|
Protocol: 6,
|
||||||
|
Port: 443,
|
||||||
|
Domain: "pkg.go.dev.",
|
||||||
|
ReverseDomain: "",
|
||||||
|
CNAME: []string{
|
||||||
|
"ghs.googlehosted.com.",
|
||||||
|
},
|
||||||
|
IP: net.ParseIP("142.250.74.211"),
|
||||||
|
Country: "US",
|
||||||
|
ASN: 15169,
|
||||||
|
},
|
||||||
|
Verdict: 2,
|
||||||
|
Reason: Reason{
|
||||||
|
Msg: "default permit",
|
||||||
|
OptionKey: "filter/defaultAction",
|
||||||
|
Profile: "",
|
||||||
|
},
|
||||||
|
Started: 1614010415,
|
||||||
|
Ended: 1614010745,
|
||||||
|
VerdictPermanent: true,
|
||||||
|
Inspecting: false,
|
||||||
|
Tunneled: false,
|
||||||
|
Encrypted: false,
|
||||||
|
ProcessContext: ProcessContext{
|
||||||
|
ProcessName: "firefox",
|
||||||
|
ProfileName: "Firefox",
|
||||||
|
BinaryPath: "/usr/bin/firefox",
|
||||||
|
PID: 5710,
|
||||||
|
Profile: "74b30392-9e4d-4157-83a9-fffafd3e2bde",
|
||||||
|
Source: "local",
|
||||||
|
},
|
||||||
|
Internal: false,
|
||||||
|
ProfileRevisionCounter: 1,
|
||||||
|
},
|
||||||
|
}
|
|
@ -33,7 +33,7 @@ type ProcessContext struct {
|
||||||
ProfileName string
|
ProfileName string
|
||||||
// BinaryPath is the path to the process binary.
|
// BinaryPath is the path to the process binary.
|
||||||
BinaryPath string
|
BinaryPath string
|
||||||
// PID i the process identifier.
|
// PID is the process identifier.
|
||||||
PID int
|
PID int
|
||||||
// Profile is the ID of the main profile that
|
// Profile is the ID of the main profile that
|
||||||
// is applied to the process.
|
// is applied to the process.
|
||||||
|
@ -93,7 +93,7 @@ type Connection struct { //nolint:maligned // TODO: fix alignment
|
||||||
Reason Reason
|
Reason Reason
|
||||||
// Started holds the number of seconds in UNIX epoch time at which
|
// Started holds the number of seconds in UNIX epoch time at which
|
||||||
// the connection has been initated and first seen by the portmaster.
|
// the connection has been initated and first seen by the portmaster.
|
||||||
// Staretd is only every set when creating a new connection object
|
// Started is only ever set when creating a new connection object
|
||||||
// and is considered immutable afterwards.
|
// and is considered immutable afterwards.
|
||||||
Started int64
|
Started int64
|
||||||
// Ended is set to the number of seconds in UNIX epoch time at which
|
// Ended is set to the number of seconds in UNIX epoch time at which
|
||||||
|
|
|
@ -31,6 +31,10 @@ func start() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := registerAPIEndpoints(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
module.StartServiceWorker("clean connections", 0, connectionCleaner)
|
module.StartServiceWorker("clean connections", 0, connectionCleaner)
|
||||||
module.StartServiceWorker("write open dns requests", 0, openDNSRequestWriter)
|
module.StartServiceWorker("write open dns requests", 0, openDNSRequestWriter)
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,9 @@ func (v Verdict) Verb() string {
|
||||||
case VerdictDrop:
|
case VerdictDrop:
|
||||||
return "dropped"
|
return "dropped"
|
||||||
case VerdictRerouteToNameserver:
|
case VerdictRerouteToNameserver:
|
||||||
return "rerouted to nameserver"
|
return "to nameserver"
|
||||||
case VerdictRerouteToTunnel:
|
case VerdictRerouteToTunnel:
|
||||||
return "rerouted to tunnel"
|
return "to tunnel"
|
||||||
case VerdictFailed:
|
case VerdictFailed:
|
||||||
return "failed"
|
return "failed"
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -2,8 +2,10 @@ package status
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/safing/portbase/modules"
|
"github.com/safing/portbase/modules"
|
||||||
|
"github.com/safing/portbase/utils/debug"
|
||||||
"github.com/safing/portmaster/netenv"
|
"github.com/safing/portmaster/netenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,3 +41,16 @@ func start() error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddToDebugInfo adds the system status to the given debug.Info.
|
||||||
|
func AddToDebugInfo(di *debug.Info) {
|
||||||
|
di.AddSection(
|
||||||
|
fmt.Sprintf("Status: %s", SecurityLevelString(ActiveSecurityLevel())),
|
||||||
|
debug.UseCodeSection|debug.AddContentLineBreaks,
|
||||||
|
fmt.Sprintf("ActiveSecurityLevel: %s", SecurityLevelString(ActiveSecurityLevel())),
|
||||||
|
fmt.Sprintf("SelectedSecurityLevel: %s", SecurityLevelString(SelectedSecurityLevel())),
|
||||||
|
fmt.Sprintf("ThreatMitigationLevel: %s", SecurityLevelString(getHighestMitigationLevel())),
|
||||||
|
fmt.Sprintf("CaptivePortal: %s", netenv.GetCaptivePortal().URL),
|
||||||
|
fmt.Sprintf("OnlineStatus: %s", netenv.GetOnlineStatus()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -99,19 +99,19 @@ func SecurityLevelString(level uint8) string {
|
||||||
case SecurityLevelOff:
|
case SecurityLevelOff:
|
||||||
return "Off"
|
return "Off"
|
||||||
case SecurityLevelNormal:
|
case SecurityLevelNormal:
|
||||||
return "Normal"
|
return "Trusted"
|
||||||
case SecurityLevelHigh:
|
case SecurityLevelHigh:
|
||||||
return "High"
|
return "Untrusted"
|
||||||
case SecurityLevelExtreme:
|
case SecurityLevelExtreme:
|
||||||
return "Extreme"
|
return "Danger"
|
||||||
case SecurityLevelsNormalAndHigh:
|
case SecurityLevelsNormalAndHigh:
|
||||||
return "Normal and High"
|
return "Trusted and Untrusted"
|
||||||
case SecurityLevelsNormalAndExtreme:
|
case SecurityLevelsNormalAndExtreme:
|
||||||
return "Normal and Extreme"
|
return "Trusted and Danger"
|
||||||
case SecurityLevelsHighAndExtreme:
|
case SecurityLevelsHighAndExtreme:
|
||||||
return "High and Extreme"
|
return "Untrusted and Danger"
|
||||||
case SecurityLevelsAll:
|
case SecurityLevelsAll:
|
||||||
return "Normal, High and Extreme"
|
return "Trusted, Untrusted and Danger"
|
||||||
default:
|
default:
|
||||||
return "INVALID"
|
return "INVALID"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue