def find_stale_wireguard_clients(wg_interface: str) -> List: """Fetches and returns a list of peers which have not had recent handshakes. Arguments: wg_interface: The WireGuard interface to query. Returns: # A list of peers which have not recently seen a handshake. """ three_hrs_in_secs = int( (datetime.now() - timedelta(hours=_PEER_TIMEOUT_HOURS)).timestamp() ) with pyroute2.WireGuard() as wg: all_clients = [] infos = wg.info(wg_interface) for info in infos: clients = info.get_attr("WGDEVICE_A_PEERS") if clients is not None: all_clients.extend(clients) ret = [ client.get_attr("WGPEER_A_PUBLIC_KEY").decode("utf-8") for client in all_clients if client.get_attr("WGPEER_A_LAST_HANDSHAKE_TIME").get("tv_sec", int()) < three_hrs_in_secs ] return ret
def update_wireguard_peer(client: WireGuardClient) -> Dict: """Handles updates of WireGuard peers to netlink. Note that set will remove a peer if remove is set to True. Arguments: client: The WireGuard peer to update. Returns: A dict. """ # TODO(ruairi): Splice this into an add_ and remove_ function. with pyroute2.WireGuard() as wg: wg_peer = { "public_key": client.public_key, "persistent_keepalive": _PERSISTENT_KEEPALIVE_SECONDS, "allowed_ips": [client.lladdr], "remove": client.remove, } return wg.set(client.wg_interface, peer=wg_peer)
def pull_from_wireguard(self): with pyroute2.WireGuard() as wg: infos = wg.info(self.wg_interface) for info in infos: clients = info.WGDEVICE_A_PEERS.value for client in clients: if "tv_sec" not in client.WGPEER_A_LAST_HANDSHAKE_TIME: continue latest_handshake = client.WGPEER_A_LAST_HANDSHAKE_TIME[ "tv_sec"] public_key = client.WGPEER_A_PUBLIC_KEY["value"].decode( "utf-8") peer = self.find_by_public_key(public_key) if len(peer) < 1: peer = WireGuardPeer(public_key) self.all_peers.append(peer) else: peer = peer[0] peer.latest_handshake = datetime.fromtimestamp( latest_handshake)