69 lines
2.6 KiB
Bash
69 lines
2.6 KiB
Bash
#!/bin/sh
|
|
# OpenVPN Access Tracker - Sampled Replay (Arthur's Gold Standard v1)
|
|
# Correlaciona usuários VPN com a tabela de estados do Packet Filter
|
|
# Compatível com: pfSense 2.x / FreeBSD
|
|
#
|
|
# Instalação:
|
|
# 1. Copie para /opt/zabbix/openvpn-access-tracker.sh
|
|
# 2. chmod +x /opt/zabbix/openvpn-access-tracker.sh
|
|
# 3. Adicione ao cron: */1 * * * * /opt/zabbix/openvpn-access-tracker.sh
|
|
#
|
|
# Output: /var/log/openvpn_user_activity.log
|
|
# Format: TIMESTAMP|USER|REAL_IP|DST_IP:PORT|PROTOCOL
|
|
|
|
METRICS_FILE="/tmp/openvpn_metrics.json"
|
|
LOG_FILE="/var/log/openvpn_user_activity.log"
|
|
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
|
|
|
|
# Verifica se temos dados de VPN
|
|
if [ ! -f "$METRICS_FILE" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Extrai lista de usuários e seus IPs virtuais
|
|
# Formato esperado: "user": { ... "virtual_ip": "10.0.8.5" ... }
|
|
user_ips=$(cat "$METRICS_FILE" | sed 's/},{/}\n{/g' | grep -oE '"[^"]+":{"bytes_recv"[^}]+' | \
|
|
sed 's/"//g' | awk -F: '{user=$1; for(i=2;i<=NF;i++) if($i ~ /virtual_ip/) {getline; print user":"$2}}' 2>/dev/null)
|
|
|
|
# Alternativa mais robusta: usar jq se disponível, senão parse manual
|
|
if command -v jq >/dev/null 2>&1; then
|
|
# jq disponível - parse limpo
|
|
user_list=$(jq -r 'to_entries[] | "\(.key):\(.value.virtual_ip)"' "$METRICS_FILE" 2>/dev/null)
|
|
else
|
|
# Parse manual simplificado
|
|
user_list=$(cat "$METRICS_FILE" | tr ',' '\n' | tr '{' '\n' | tr '}' '\n' | \
|
|
grep -E '^"[a-zA-Z0-9._-]+"|virtual_ip' | paste - - 2>/dev/null | \
|
|
sed 's/"//g;s/virtual_ip://g' | awk '{print $1":"$2}')
|
|
fi
|
|
|
|
# Se não temos usuários, sai
|
|
[ -z "$user_list" ] && exit 0
|
|
|
|
# Captura tabela de estados
|
|
state_table=$(pfctl -ss 2>/dev/null)
|
|
[ -z "$state_table" ] && exit 0
|
|
|
|
# Para cada usuário VPN, busca conexões na state table
|
|
echo "$user_list" | while IFS=: read -r user vip; do
|
|
[ -z "$user" ] || [ -z "$vip" ] && continue
|
|
|
|
# Busca estados onde o IP virtual é a origem
|
|
# Formato pfctl -ss: all tcp 10.0.8.5:54321 -> 192.168.1.100:443 ESTABLISHED:ESTABLISHED
|
|
echo "$state_table" | grep " $vip:" | while read -r state_line; do
|
|
# Extrai protocolo, destino
|
|
proto=$(echo "$state_line" | awk '{print $2}')
|
|
dst=$(echo "$state_line" | awk '{print $4}' | sed 's/->//g')
|
|
state=$(echo "$state_line" | awk '{print $NF}')
|
|
|
|
[ -z "$dst" ] && continue
|
|
|
|
# Loga a atividade
|
|
printf "%s|%s|%s|%s|%s|%s\n" "$TIMESTAMP" "$user" "$vip" "$dst" "$proto" "$state" >> "$LOG_FILE"
|
|
done
|
|
done
|
|
|
|
# Rotação simples: mantém só últimas 50000 linhas (~5MB)
|
|
if [ -f "$LOG_FILE" ] && [ $(wc -l < "$LOG_FILE") -gt 50000 ]; then
|
|
tail -40000 "$LOG_FILE" > "$LOG_FILE.tmp" && mv "$LOG_FILE.tmp" "$LOG_FILE"
|
|
fi
|