diff --git a/configtypes.go b/configtypes.go index 370f740..3cbf728 100644 --- a/configtypes.go +++ b/configtypes.go @@ -5,7 +5,6 @@ import ( "io/ioutil" "net" "os" - "time" "github.com/go-playground/validator/v10" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" @@ -180,7 +179,7 @@ func (conf DsnetConfig) MustAllocateIP() net.IP { func (conf DsnetConfig) GetWgPeerConfigs() []wgtypes.PeerConfig { wgPeers := make([]wgtypes.PeerConfig, 0, len(conf.Peers)) - interval := time.Second * KEEPALIVE_SECONDS + interval := KEEPALIVE for _, peer := range conf.Peers { wgPeers = append(wgPeers, wgtypes.PeerConfig{ diff --git a/const.go b/const.go index a95972b..2e53a4a 100644 --- a/const.go +++ b/const.go @@ -1,5 +1,9 @@ package dsnet +import ( + "time" +) + const ( // could be overridden in future via env CONFIG_FILE = "/etc/dsnetconfig.json" @@ -11,7 +15,9 @@ const ( // keepalive always configured for everything. Set to a value likely to // stop most NATs from dropping the connection. - KEEPALIVE_SECONDS = 21 + KEEPALIVE = 21 * time.Second + // allow missing a single keepalive + margin. Received data resets timeout, too. + TIMEOUT = 50 * time.Second // when is a peer considered gone forever? (could remove) EXPIRY_DAYS = 28 diff --git a/reporttypes.go b/reporttypes.go index 4535ec0..f1ae33b 100644 --- a/reporttypes.go +++ b/reporttypes.go @@ -12,27 +12,28 @@ import ( type Status int const ( + StatusUnknown = iota // Host has not been loaded into wireguard yet - Pending = iota + StatusSyncRequired // Host has not transferred anything (not even a keepalive) for 30 seconds - Offline + StatusOffline // Host has transferred something in the last 30 seconds, keepalive counts - Online + StatusOnline // Host has not connected for 28 days and may be removed - Expired + StatusExpired ) // TODO pending/unknown func (s Status) String() string { switch s { - case Pending: - return "pending" - case Offline: + case StatusSyncRequired: + return "syncrequired" + case StatusOffline: return "offline" - case Online: + case StatusOnline: return "online" - case Expired: + case StatusExpired: return "expired" default: return "unknown" @@ -70,12 +71,24 @@ func GenerateReport(dev *wgtypes.Device, conf *DsnetConfig) DsnetReport { for i, peer := range conf.Peers { wgPeer, known := wgPeerIndex[peer.PublicKey.Key] + status := Status(StatusUnknown) + + if !known { + status = StatusSyncRequired + } else if wgPeer.LastHandshakeTime.After(time.Now().Add(-TIMEOUT)) { + status = StatusOnline + // TODO same test but with rx byte data from last report (otherwise + // peer can fake online status by disabling handshake) + } else { + status = StatusOffline + } + peerReports[i] = PeerReport{ Hostname: peer.Hostname, Owner: peer.Owner, Description: peer.Description, IP: peer.IP, - // TODO Status + Status: status, Networks: peer.Networks, LastHandshakeTime: wgPeer.LastHandshakeTime, ReceiveBytes: wgPeer.ReceiveBytes,