From c870e064995fe85d36fd59a3850c3c2880e096f9 Mon Sep 17 00:00:00 2001 From: hwipl <33433250+hwipl@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:52:16 +0200 Subject: [PATCH 1/2] Start D-Bus API before TrafPol Signed-off-by: hwipl <33433250+hwipl@users.noreply.github.com> --- internal/daemon/daemon.go | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index a949eb7f..8d31c7d9 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -784,18 +784,6 @@ func (d *Daemon) Start() error { goto cleanup_profmon } - // start traffic policing - err = d.checkTrafPol() - if err != nil { - goto cleanup_trafpol - } - - // start TND - err = d.checkTND() - if err != nil { - goto cleanup_tnd - } - // start VPN setup d.vpnsetup.Start() @@ -822,19 +810,32 @@ func (d *Daemon) Start() error { d.setStatusServers(d.profile.GetVPNServerHostNames()) d.setStatusConnectedAt(0) + // start traffic policing + err = d.checkTrafPol() + if err != nil { + goto cleanup_trafpol + } + + // start TND + err = d.checkTND() + if err != nil { + goto cleanup_tnd + } + go d.start() return nil // clean up after error +cleanup_tnd: + d.stopTrafPol() +cleanup_trafpol: + d.dbus.Stop() + d.server.Stop() cleanup_dbus: d.server.Stop() cleanup_unix: d.runner.Stop() d.vpnsetup.Stop() - d.stopTND() -cleanup_tnd: - d.stopTrafPol() -cleanup_trafpol: d.profmon.Stop() cleanup_profmon: d.sleepmon.Stop() From 6240509fa3dd5eb7b8b1704370df6c17c463491c Mon Sep 17 00:00:00 2001 From: hwipl <33433250+hwipl@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:07:16 +0200 Subject: [PATCH 2/2] Add TrafPol State and Allowed Hosts to D-Bus Properties Signed-off-by: hwipl <33433250+hwipl@users.noreply.github.com> --- internal/client/client.go | 4 ++++ internal/daemon/daemon.go | 36 ++++++++++++++++++++++++++++++++++++ internal/dbusapi/service.go | 28 ++++++++++++++++++++++++++++ pkg/client/client.go | 8 ++++++++ pkg/client/client_test.go | 4 ++++ pkg/vpnstatus/status.go | 27 +++++++++++++++++++++++++++ pkg/vpnstatus/status_test.go | 19 +++++++++++++++++++ tools/dbusclient/main.go | 20 ++++++++++++++++++++ 8 files changed, 146 insertions(+) diff --git a/internal/client/client.go b/internal/client/client.go index 34702f68..1e635a5f 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -186,6 +186,10 @@ func printStatus(status *vpnstatus.Status) error { if !verbose { return nil } + + fmt.Printf("TrafPol State: %s\n", status.TrafPolState) + fmt.Printf("Allowed Hosts: %s\n", status.AllowedHosts) + if status.VPNConfig == nil { fmt.Printf("VPN Config:\n") } else { diff --git a/internal/daemon/daemon.go b/internal/daemon/daemon.go index 8d31c7d9..8486b361 100644 --- a/internal/daemon/daemon.go +++ b/internal/daemon/daemon.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "reflect" + "slices" "strconv" "strings" "syscall" @@ -200,6 +201,32 @@ func (d *Daemon) setStatusOCRunning(running bool) { d.dbus.SetProperty(dbusapi.PropertyOCRunning, ocrunning) } +// setStatusTrafPolState sets the TrafPol state in status. +func (d *Daemon) setStatusTrafPolState(state vpnstatus.TrafPolState) { + if d.status.TrafPolState == state { + // TrafPol state not changed + return + } + + // TrafPol state changed + log.WithField("TrafPolState", state).Info("Daemon changed TrafPolState status") + d.status.TrafPolState = state + d.dbus.SetProperty(dbusapi.PropertyTrafPolState, state) +} + +// setStatusAllowedHosts sets the allowed hosts in status. +func (d *Daemon) setStatusAllowedHosts(hosts []string) { + if slices.Equal(d.status.AllowedHosts, hosts) { + // allowed hosts not changed + return + } + + // allowed hosts changed + log.WithField("AllowedHosts", hosts).Info("Daemon changed AllowedHosts status") + d.status.AllowedHosts = hosts + d.dbus.SetProperty(dbusapi.PropertyAllowedHosts, hosts) +} + // setStatusVPNConfig sets the VPN config in status. func (d *Daemon) setStatusVPNConfig(config *vpnconfig.Config) { if d.status.VPNConfig.Equal(config) { @@ -662,6 +689,10 @@ func (d *Daemon) startTrafPol() error { return fmt.Errorf("Daemon could not start TrafPol: %w", err) } + // update trafpol status + d.setStatusTrafPolState(vpnstatus.TrafPolStateActive) + d.setStatusAllowedHosts(c.AllowedHosts) + if d.serverIP != nil { // VPN connection active, allow server IP d.serverIPAllowed = d.trafpol.AddAllowedAddr(d.serverIP) @@ -679,6 +710,10 @@ func (d *Daemon) stopTrafPol() { d.trafpol.Stop() d.trafpol = nil d.serverIPAllowed = false + + // update trafpol status + d.setStatusTrafPolState(vpnstatus.TrafPolStateInactive) + d.setStatusAllowedHosts(nil) } // checkTrafPol checks if traffic policing should be running and @@ -809,6 +844,7 @@ func (d *Daemon) Start() error { d.setStatusConnectionState(vpnstatus.ConnectionStateDisconnected) d.setStatusServers(d.profile.GetVPNServerHostNames()) d.setStatusConnectedAt(0) + d.setStatusTrafPolState(vpnstatus.TrafPolStateInactive) // start traffic policing err = d.checkTrafPol() diff --git a/internal/dbusapi/service.go b/internal/dbusapi/service.go index 608eb215..d3e95a1d 100644 --- a/internal/dbusapi/service.go +++ b/internal/dbusapi/service.go @@ -31,6 +31,8 @@ const ( PropertyConnectedAt = "ConnectedAt" PropertyServers = "Servers" PropertyOCRunning = "OCRunning" + PropertyTrafPolState = "TrafPolState" + PropertyAllowedHosts = "AllowedHosts" PropertyVPNConfig = "VPNConfig" ) @@ -87,6 +89,18 @@ const ( OCRunningRunning ) +// Property "TrafPol State" states. +const ( + TrafPolStateUnknown uint32 = iota + TrafPolStateInactive + TrafPolStateActive +) + +// Property "Allowed Hosts" values. +var ( + AllowedHostsInvalid []string +) + // Property "VPNConfig" values. const ( VPNConfigInvalid = "" @@ -234,6 +248,8 @@ func (s *Service) start() { s.props.SetMust(Interface, PropertyConnectedAt, ConnectedAtInvalid) s.props.SetMust(Interface, PropertyServers, ServersInvalid) s.props.SetMust(Interface, PropertyOCRunning, OCRunningUnknown) + s.props.SetMust(Interface, PropertyTrafPolState, TrafPolStateUnknown) + s.props.SetMust(Interface, PropertyAllowedHosts, AllowedHostsInvalid) s.props.SetMust(Interface, PropertyVPNConfig, VPNConfigInvalid) } @@ -344,6 +360,18 @@ func (s *Service) Start() error { Emit: prop.EmitTrue, Callback: nil, }, + PropertyTrafPolState: { + Value: TrafPolStateUnknown, + Writable: false, + Emit: prop.EmitTrue, + Callback: nil, + }, + PropertyAllowedHosts: { + Value: AllowedHostsInvalid, + Writable: false, + Emit: prop.EmitTrue, + Callback: nil, + }, PropertyVPNConfig: { Value: VPNConfigInvalid, Writable: false, diff --git a/pkg/client/client.go b/pkg/client/client.go index 705f545b..30cc721e 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -154,6 +154,10 @@ func updateStatusFromProperties(status *vpnstatus.Status, props map[string]dbus. err = v.Store(&dest.Servers) case dbusapi.PropertyOCRunning: err = v.Store(&dest.OCRunning) + case dbusapi.PropertyTrafPolState: + err = v.Store(&dest.TrafPolState) + case dbusapi.PropertyAllowedHosts: + err = v.Store(&dest.AllowedHosts) case dbusapi.PropertyVPNConfig: s := dbusapi.VPNConfigInvalid if err := v.Store(&s); err != nil { @@ -270,6 +274,10 @@ func handlePropertiesChanged(s *dbus.Signal, status *vpnstatus.Status) *vpnstatu status.Servers = dbusapi.ServersInvalid case dbusapi.PropertyOCRunning: status.OCRunning = vpnstatus.OCRunningUnknown + case dbusapi.PropertyTrafPolState: + status.TrafPolState = vpnstatus.TrafPolStateUnknown + case dbusapi.PropertyAllowedHosts: + status.AllowedHosts = dbusapi.AllowedHostsInvalid case dbusapi.PropertyVPNConfig: status.VPNConfig = nil } diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index afd68bea..5693811f 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -99,6 +99,8 @@ func TestDBusClientQuery(t *testing.T) { dbusapi.PropertyConnectedAt: dbus.MakeVariant(dbusapi.ConnectedAtInvalid), dbusapi.PropertyServers: dbus.MakeVariant(dbusapi.ServersInvalid), dbusapi.PropertyOCRunning: dbus.MakeVariant(dbusapi.OCRunningUnknown), + dbusapi.PropertyTrafPolState: dbus.MakeVariant(dbusapi.TrafPolStateUnknown), + dbusapi.PropertyAllowedHosts: dbus.MakeVariant(dbusapi.AllowedHostsInvalid), dbusapi.PropertyVPNConfig: dbus.MakeVariant(dbusapi.VPNConfigInvalid), }, { @@ -210,6 +212,8 @@ func TestDBusClientSubscribe(t *testing.T) { dbusapi.PropertyConnectedAt, dbusapi.PropertyServers, dbusapi.PropertyOCRunning, + dbusapi.PropertyTrafPolState, + dbusapi.PropertyAllowedHosts, dbusapi.PropertyVPNConfig, }}, }, diff --git a/pkg/vpnstatus/status.go b/pkg/vpnstatus/status.go index 64ad6540..c9c80e97 100644 --- a/pkg/vpnstatus/status.go +++ b/pkg/vpnstatus/status.go @@ -97,6 +97,29 @@ func (o OCRunning) String() string { return "" } +// TrafPolState is the current TrafPol state. +type TrafPolState uint32 + +// TrafPolState states. +const ( + TrafPolStateUnknown = iota + TrafPolStateInactive + TrafPolStateActive +) + +// String resturns TrafPolState as string. +func (t TrafPolState) String() string { + switch t { + case TrafPolStateUnknown: + return "unknown" + case TrafPolStateInactive: + return "inactive" + case TrafPolStateActive: + return "active" + } + return "" +} + // Status is a VPN status. type Status struct { TrustedNetwork TrustedNetwork @@ -108,6 +131,8 @@ type Status struct { ConnectedAt int64 Servers []string OCRunning OCRunning + TrafPolState TrafPolState + AllowedHosts []string VPNConfig *vpnconfig.Config } @@ -126,6 +151,8 @@ func (s *Status) Copy() *Status { ConnectedAt: s.ConnectedAt, Servers: append(s.Servers[:0:0], s.Servers...), OCRunning: s.OCRunning, + TrafPolState: s.TrafPolState, + AllowedHosts: append(s.AllowedHosts[:0:0], s.AllowedHosts...), VPNConfig: s.VPNConfig.Copy(), } } diff --git a/pkg/vpnstatus/status_test.go b/pkg/vpnstatus/status_test.go index fcdbe251..898c8b8d 100644 --- a/pkg/vpnstatus/status_test.go +++ b/pkg/vpnstatus/status_test.go @@ -116,6 +116,23 @@ func TestOCRunningString(t *testing.T) { } } +// TestTrafPolStateString tests String of TrafPolState. +func TestTrafPolStateString(t *testing.T) { + for v, s := range map[TrafPolState]string{ + // valid + TrafPolStateUnknown: "unknown", + TrafPolStateInactive: "inactive", + TrafPolStateActive: "active", + + // invalid + 123456: "", + } { + if v.String() != s { + t.Errorf("got %s, want %s", v.String(), s) + } + } +} + // TestStatusCopy tests Copy of Status. func TestStatusCopy(t *testing.T) { // test nil @@ -136,6 +153,8 @@ func TestStatusCopy(t *testing.T) { ConnectedAt: 1700000000, Servers: []string{"test server 1", "test server 2"}, OCRunning: OCRunningRunning, + TrafPolState: TrafPolStateActive, + AllowedHosts: []string{"test.example.com"}, VPNConfig: vpnconfig.New(), }, } { diff --git a/tools/dbusclient/main.go b/tools/dbusclient/main.go index 9a2af262..26ed4ced 100644 --- a/tools/dbusclient/main.go +++ b/tools/dbusclient/main.go @@ -39,6 +39,8 @@ func main() { connectedAt := dbusapi.ConnectedAtInvalid servers := dbusapi.ServersInvalid ocRunning := dbusapi.OCRunningUnknown + trafPolState := dbusapi.TrafPolStateUnknown + allowedHosts := dbusapi.AllowedHostsInvalid vpnConfig := dbusapi.VPNConfigInvalid getProperty := func(name string, val any) { @@ -57,6 +59,8 @@ func main() { getProperty(dbusapi.PropertyConnectedAt, &connectedAt) getProperty(dbusapi.PropertyServers, &servers) getProperty(dbusapi.PropertyOCRunning, &ocRunning) + getProperty(dbusapi.PropertyTrafPolState, &trafPolState) + getProperty(dbusapi.PropertyAllowedHosts, &allowedHosts) getProperty(dbusapi.PropertyVPNConfig, &vpnConfig) log.Println("TrustedNetwork:", trustedNetwork) @@ -68,6 +72,8 @@ func main() { log.Println("ConnectedAt:", connectedAt) log.Println("Servers:", servers) log.Println("OCRunning:", ocRunning) + log.Println("TrafPolState:", trafPolState) + log.Println("AllowedHosts:", allowedHosts) log.Println("VPNConfig:", vpnConfig) // handle signals @@ -141,6 +147,16 @@ func main() { log.Fatal(err) } fmt.Println(ocRunning) + case dbusapi.PropertyTrafPolState: + if err := value.Store(&trafPolState); err != nil { + log.Fatal(err) + } + fmt.Println(trafPolState) + case dbusapi.PropertyAllowedHosts: + if err := value.Store(&allowedHosts); err != nil { + log.Fatal(err) + } + fmt.Println(allowedHosts) case dbusapi.PropertyVPNConfig: if err := value.Store(&vpnConfig); err != nil { log.Fatal(err) @@ -176,6 +192,10 @@ func main() { servers = dbusapi.ServersInvalid case dbusapi.PropertyOCRunning: ocRunning = dbusapi.OCRunningUnknown + case dbusapi.PropertyTrafPolState: + trafPolState = dbusapi.TrafPolStateUnknown + case dbusapi.PropertyAllowedHosts: + allowedHosts = dbusapi.AllowedHostsInvalid case dbusapi.PropertyVPNConfig: vpnConfig = dbusapi.VPNConfigInvalid }