wgctl/modules/monitor.module.sh

133 lines
3.3 KiB
Bash

#!/usr/bin/env bash
# ============================================
# Config
# ============================================
MONITOR_DIR="$(ctx::daemon)"
WATCHLIST_FILE="${MONITOR_DIR}/watchlist.json"
EVENTS_LOG="${MONITOR_DIR}/events.log"
ENDPOINT_CACHE="${MONITOR_DIR}/endpoint_cache.json"
FW_EVENTS_LOG="${MONITOR_DIR}/fw_events.log"
MONITOR_SERVICE="wgctl-monitor"
# ============================================
# Lifecycle
# ============================================
function monitor::on_load() {
if [[ ! -f "$WATCHLIST_FILE" ]]; then
echo '{}' > "$WATCHLIST_FILE"
fi
if [[ ! -f "$EVENTS_LOG" ]]; then
touch "$EVENTS_LOG"
fi
}
# ============================================
# Watchlist
# ============================================
function monitor::watch() {
local ip="$1" client="$2"
json::set "$WATCHLIST_FILE" "$ip" "$client"
log::debug "Watching: ${client} (${ip})"
}
function monitor::unwatch() {
local ip="$1"
json::delete "$WATCHLIST_FILE" "$ip"
}
function monitor::is_watched() {
local ip="$1"
json::has_key "$WATCHLIST_FILE" "$ip"
}
function monitor::unwatch_client() {
local name="$1"
json::filter_values "$WATCHLIST_FILE" "value" "$name"
log::debug "Unwatched client: ${name}"
}
# ============================================
# Events
# ============================================
function monitor::last_attempt() {
local client="$1"
json::last_event "$EVENTS_LOG" "client" "timestamp" "$client"
}
function monitor::last_endpoint() {
local client="$1"
json::last_event "$EVENTS_LOG" "client" "endpoint" "$client"
}
function monitor::events_for() {
local ip="$1"
local limit="${2:-50}"
json::events_for "$EVENTS_LOG" "$ip" "$limit"
}
# ============================================
# Endpoint Cache (for blocked clients)
# ============================================
ENDPOINT_CACHE="${WGCTL_DIR}/daemon/endpoint_cache.json"
function monitor::cache_endpoint() {
local client="$1" ip="$2"
json::set "$ENDPOINT_CACHE" "$client" "$ip"
}
function monitor::get_cached_endpoint() {
local client="$1"
json::get "$ENDPOINT_CACHE" "$client"
}
function monitor::update_endpoint_cache() {
while IFS=$'\t' read -r key endpoint; do
[[ "$endpoint" == "(none)" ]] && continue
local ip
ip=$(echo "$endpoint" | cut -d':' -f1)
local client
client=$(keys::find_by_public "$key") || continue
monitor::cache_endpoint "$client" "$ip"
done < <(wg show "$(config::interface)" endpoints 2>/dev/null)
}
# ============================================
# Endpoint (from wg show, for active clients)
# ============================================
function monitor::endpoint_for_key() {
local public_key="$1"
wg show "$(config::interface)" endpoints 2>/dev/null \
| grep "^${public_key}" \
| awk '{print $2}' \
| cut -d':' -f1
}
# ============================================
# Service
# ============================================
function monitor::start() {
systemctl start "$MONITOR_SERVICE"
log::debug "Monitor daemon started"
}
function monitor::stop() {
systemctl stop "$MONITOR_SERVICE"
log::debug "Monitor daemon stopped"
}
function monitor::restart() {
systemctl restart "$MONITOR_SERVICE"
log::debug "Monitor daemon restarted"
}
function monitor::is_running() {
systemctl is-active --quiet "$MONITOR_SERVICE"
}