mirror of
https://github.com/netbirdio/netbird.git
synced 2025-08-16 10:08:12 +02:00
This PR introduces a new inactivity package responsible for monitoring peer activity and notifying when peers become inactive. Introduces a new Signal message type to close the peer connection after the idle timeout is reached. Periodically checks the last activity of registered peers via a Bind interface. Notifies via a channel when peers exceed a configurable inactivity threshold. Default settings DefaultInactivityThreshold is set to 15 minutes, with a minimum allowed threshold of 1 minute. Limitations This inactivity check does not support kernel WireGuard integration. In kernel–user space communication, the user space side will always be responsible for closing the connection.
105 lines
2.1 KiB
Go
105 lines
2.1 KiB
Go
package activity
|
|
|
|
import (
|
|
"net"
|
|
"net/netip"
|
|
"sync"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
|
|
|
"github.com/netbirdio/netbird/client/internal/lazyconn"
|
|
peerid "github.com/netbirdio/netbird/client/internal/peer/id"
|
|
)
|
|
|
|
type WgInterface interface {
|
|
RemovePeer(peerKey string) error
|
|
UpdatePeer(peerKey string, allowedIps []netip.Prefix, keepAlive time.Duration, endpoint *net.UDPAddr, preSharedKey *wgtypes.Key) error
|
|
}
|
|
|
|
type Manager struct {
|
|
OnActivityChan chan peerid.ConnID
|
|
|
|
wgIface WgInterface
|
|
|
|
peers map[peerid.ConnID]*Listener
|
|
done chan struct{}
|
|
|
|
mu sync.Mutex
|
|
}
|
|
|
|
func NewManager(wgIface WgInterface) *Manager {
|
|
m := &Manager{
|
|
OnActivityChan: make(chan peerid.ConnID, 1),
|
|
wgIface: wgIface,
|
|
peers: make(map[peerid.ConnID]*Listener),
|
|
done: make(chan struct{}),
|
|
}
|
|
return m
|
|
}
|
|
|
|
func (m *Manager) MonitorPeerActivity(peerCfg lazyconn.PeerConfig) error {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
if _, ok := m.peers[peerCfg.PeerConnID]; ok {
|
|
log.Warnf("activity listener already exists for: %s", peerCfg.PublicKey)
|
|
return nil
|
|
}
|
|
|
|
listener, err := NewListener(m.wgIface, peerCfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
m.peers[peerCfg.PeerConnID] = listener
|
|
|
|
go m.waitForTraffic(listener, peerCfg.PeerConnID)
|
|
return nil
|
|
}
|
|
|
|
func (m *Manager) RemovePeer(log *log.Entry, peerConnID peerid.ConnID) {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
listener, ok := m.peers[peerConnID]
|
|
if !ok {
|
|
return
|
|
}
|
|
log.Debugf("removing activity listener")
|
|
delete(m.peers, peerConnID)
|
|
listener.Close()
|
|
}
|
|
|
|
func (m *Manager) Close() {
|
|
m.mu.Lock()
|
|
defer m.mu.Unlock()
|
|
|
|
close(m.done)
|
|
for peerID, listener := range m.peers {
|
|
delete(m.peers, peerID)
|
|
listener.Close()
|
|
}
|
|
}
|
|
|
|
func (m *Manager) waitForTraffic(listener *Listener, peerConnID peerid.ConnID) {
|
|
listener.ReadPackets()
|
|
|
|
m.mu.Lock()
|
|
if _, ok := m.peers[peerConnID]; !ok {
|
|
m.mu.Unlock()
|
|
return
|
|
}
|
|
delete(m.peers, peerConnID)
|
|
m.mu.Unlock()
|
|
|
|
m.notify(peerConnID)
|
|
}
|
|
|
|
func (m *Manager) notify(peerConnID peerid.ConnID) {
|
|
select {
|
|
case <-m.done:
|
|
case m.OnActivityChan <- peerConnID:
|
|
}
|
|
}
|