Report: Aktivster Tag über konfigurierbaren Zeitraum statt Berichtsperiode
This commit is contained in:
@@ -128,6 +128,12 @@ REPORT_FORMAT="html"
|
|||||||
# Mail-Befehl (z.B. "msmtp", "sendmail", "mail")
|
# Mail-Befehl (z.B. "msmtp", "sendmail", "mail")
|
||||||
REPORT_MAIL_CMD="msmtp"
|
REPORT_MAIL_CMD="msmtp"
|
||||||
|
|
||||||
|
# Zeitraum für "Aktivster Tag" im Report (in Tagen)
|
||||||
|
# Bestimmt, über wie viele Tage zurück der aktivste Tag ermittelt wird.
|
||||||
|
# 30 = Aktivster Tag der letzten 30 Tage (empfohlen)
|
||||||
|
# 0 = Nur innerhalb des Berichtszeitraums (altes Verhalten)
|
||||||
|
REPORT_BUSIEST_DAY_RANGE=30
|
||||||
|
|
||||||
# --- Externe Blocklist (optional) ---
|
# --- Externe Blocklist (optional) ---
|
||||||
# Aktiviert den externen Blocklist-Worker
|
# Aktiviert den externen Blocklist-Worker
|
||||||
EXTERNAL_BLOCKLIST_ENABLED=false
|
EXTERNAL_BLOCKLIST_ENABLED=false
|
||||||
|
|||||||
@@ -139,6 +139,7 @@ Regelmäßige Statistik-Reports per E-Mail. Voraussetzung ist ein funktionierend
|
|||||||
| `REPORT_EMAIL_FROM` | `adguard-shield@hostname` | E-Mail-Absender |
|
| `REPORT_EMAIL_FROM` | `adguard-shield@hostname` | E-Mail-Absender |
|
||||||
| `REPORT_FORMAT` | `html` | Format: `html` oder `txt` |
|
| `REPORT_FORMAT` | `html` | Format: `html` oder `txt` |
|
||||||
| `REPORT_MAIL_CMD` | `msmtp` | Mail-Befehl (`msmtp`, `sendmail`, `mail`) |
|
| `REPORT_MAIL_CMD` | `msmtp` | Mail-Befehl (`msmtp`, `sendmail`, `mail`) |
|
||||||
|
| `REPORT_BUSIEST_DAY_RANGE` | `30` | Zeitraum in Tagen für „Aktivster Tag“. `30` = letzte 30 Tage. `0` = nur Berichtszeitraum (altes Verhalten) |
|
||||||
|
|
||||||
> Siehe [E-Mail Report Dokumentation](report.md) für Details zu Inhalten, Templates und Befehlen.
|
> Siehe [E-Mail Report Dokumentation](report.md) für Details zu Inhalten, Templates und Befehlen.
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ sudo /opt/adguard-shield/report-generator.sh install
|
|||||||
| `REPORT_EMAIL_FROM` | `adguard-shield@hostname` | E-Mail-Absender |
|
| `REPORT_EMAIL_FROM` | `adguard-shield@hostname` | E-Mail-Absender |
|
||||||
| `REPORT_FORMAT` | `html` | Format: `html` oder `txt` |
|
| `REPORT_FORMAT` | `html` | Format: `html` oder `txt` |
|
||||||
| `REPORT_MAIL_CMD` | `msmtp` | Mail-Befehl (`msmtp`, `sendmail`, `mail`) |
|
| `REPORT_MAIL_CMD` | `msmtp` | Mail-Befehl (`msmtp`, `sendmail`, `mail`) |
|
||||||
|
| `REPORT_BUSIEST_DAY_RANGE` | `30` | Zeitraum in Tagen für „Aktivster Tag“ (0 = Berichtszeitraum) |
|
||||||
|
|
||||||
### Versandintervalle
|
### Versandintervalle
|
||||||
|
|
||||||
@@ -86,7 +87,7 @@ Die übrigen Zeiträume laufen vom Starttag 00:00 Uhr bis zum Zeitpunkt der Repo
|
|||||||
- Rate-Limit Sperren
|
- Rate-Limit Sperren
|
||||||
- Subdomain-Flood Sperren
|
- Subdomain-Flood Sperren
|
||||||
- Externe Blocklist Sperren
|
- Externe Blocklist Sperren
|
||||||
- Aktivster Tag im Berichtszeitraum
|
- Aktivster Tag – wird über einen konfigurierbaren Zeitraum ermittelt (Standard: letzte 30 Tage, `REPORT_BUSIEST_DAY_RANGE`). Zeigt zusätzlich die Anzahl der Sperren an diesem Tag. Bei `REPORT_BUSIEST_DAY_RANGE=0` wird nur der Berichtszeitraum betrachtet.
|
||||||
|
|
||||||
### Top 10 Listen
|
### Top 10 Listen
|
||||||
- **Auffälligste IPs** — Die 10 IPs mit den meisten Sperren (mit Balkendiagramm im HTML-Format)
|
- **Auffälligste IPs** — Die 10 IPs mit den meisten Sperren (mit Balkendiagramm im HTML-Format)
|
||||||
@@ -175,7 +176,8 @@ Die Templates verwenden Platzhalter (z.B. `{{TOTAL_BANS}}`, `{{TOP10_IPS_TABLE}}
|
|||||||
| `{{RATELIMIT_BANS}}` | Rate-Limit Sperren |
|
| `{{RATELIMIT_BANS}}` | Rate-Limit Sperren |
|
||||||
| `{{SUBDOMAIN_FLOOD_BANS}}` | Subdomain-Flood Sperren |
|
| `{{SUBDOMAIN_FLOOD_BANS}}` | Subdomain-Flood Sperren |
|
||||||
| `{{EXTERNAL_BLOCKLIST_BANS}}` | Externe Blocklist Sperren |
|
| `{{EXTERNAL_BLOCKLIST_BANS}}` | Externe Blocklist Sperren |
|
||||||
| `{{BUSIEST_DAY}}` | Aktivster Tag |
|
| `{{BUSIEST_DAY}}` | Aktivster Tag (Datum + Anzahl Sperren) |
|
||||||
|
| `{{BUSIEST_DAY_LABEL}}` | Dynamisches Label für den aktivsten Tag (z.B. „Aktivster Tag (30 Tage)“) |
|
||||||
| `{{TOP10_IPS_TABLE}}` | Top 10 IPs (HTML-Tabelle) |
|
| `{{TOP10_IPS_TABLE}}` | Top 10 IPs (HTML-Tabelle) |
|
||||||
| `{{TOP10_IPS_TEXT}}` | Top 10 IPs (Text-Tabelle) |
|
| `{{TOP10_IPS_TEXT}}` | Top 10 IPs (Text-Tabelle) |
|
||||||
| `{{TOP10_DOMAINS_TABLE}}` | Top 10 Domains (HTML-Tabelle) |
|
| `{{TOP10_DOMAINS_TABLE}}` | Top 10 Domains (HTML-Tabelle) |
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ REPORT_EMAIL_TO="${REPORT_EMAIL_TO:-}"
|
|||||||
REPORT_EMAIL_FROM="${REPORT_EMAIL_FROM:-adguard-shield@$(hostname -f 2>/dev/null || hostname)}"
|
REPORT_EMAIL_FROM="${REPORT_EMAIL_FROM:-adguard-shield@$(hostname -f 2>/dev/null || hostname)}"
|
||||||
REPORT_FORMAT="${REPORT_FORMAT:-html}"
|
REPORT_FORMAT="${REPORT_FORMAT:-html}"
|
||||||
REPORT_MAIL_CMD="${REPORT_MAIL_CMD:-msmtp}"
|
REPORT_MAIL_CMD="${REPORT_MAIL_CMD:-msmtp}"
|
||||||
|
REPORT_BUSIEST_DAY_RANGE="${REPORT_BUSIEST_DAY_RANGE:-30}"
|
||||||
BAN_HISTORY_FILE="${BAN_HISTORY_FILE:-/var/log/adguard-shield-bans.log}"
|
BAN_HISTORY_FILE="${BAN_HISTORY_FILE:-/var/log/adguard-shield-bans.log}"
|
||||||
BAN_HISTORY_RETENTION_DAYS="${BAN_HISTORY_RETENTION_DAYS:-0}"
|
BAN_HISTORY_RETENTION_DAYS="${BAN_HISTORY_RETENTION_DAYS:-0}"
|
||||||
STATE_DIR="${STATE_DIR:-/var/lib/adguard-shield}"
|
STATE_DIR="${STATE_DIR:-/var/lib/adguard-shield}"
|
||||||
@@ -325,6 +326,7 @@ calculate_stats() {
|
|||||||
SUBDOMAIN_FLOOD_BANS=0
|
SUBDOMAIN_FLOOD_BANS=0
|
||||||
EXTERNAL_BLOCKLIST_BANS=0
|
EXTERNAL_BLOCKLIST_BANS=0
|
||||||
BUSIEST_DAY="–"
|
BUSIEST_DAY="–"
|
||||||
|
BUSIEST_DAY_LABEL="Aktivster Tag"
|
||||||
TOP10_IPS=""
|
TOP10_IPS=""
|
||||||
TOP10_DOMAINS=""
|
TOP10_DOMAINS=""
|
||||||
PROTOCOL_STATS=""
|
PROTOCOL_STATS=""
|
||||||
@@ -333,16 +335,24 @@ calculate_stats() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Einen einzigen awk-Pass über den Cache: alle Statistiken auf einmal
|
# Einen einzigen awk-Pass über den Cache: alle Statistiken auf einmal
|
||||||
|
# Busiest-Day-Bereich berechnen (konfigurierbar, Standard: 30 Tage)
|
||||||
|
local busiest_start_epoch
|
||||||
|
if [[ "$REPORT_BUSIEST_DAY_RANGE" == "0" || -z "$REPORT_BUSIEST_DAY_RANGE" ]]; then
|
||||||
|
busiest_start_epoch="$start_epoch"
|
||||||
|
else
|
||||||
|
local today_midnight
|
||||||
|
today_midnight=$(get_today_midnight)
|
||||||
|
busiest_start_epoch=$((today_midnight - REPORT_BUSIEST_DAY_RANGE * 86400))
|
||||||
|
fi
|
||||||
|
|
||||||
local awk_result
|
local awk_result
|
||||||
awk_result=$(echo "$HISTORY_CACHE" | awk -F'|' -v s="$start_epoch" -v e="$end_epoch" '
|
awk_result=$(echo "$HISTORY_CACHE" | awk -F'|' -v s="$start_epoch" -v e="$end_epoch" -v bs="$busiest_start_epoch" '
|
||||||
$1 >= s && $1 <= e {
|
$1 >= s && $1 <= e {
|
||||||
action = $3
|
action = $3
|
||||||
if (action == "BAN") {
|
if (action == "BAN") {
|
||||||
bans++
|
bans++
|
||||||
ip_count[$4]++
|
ip_count[$4]++
|
||||||
ip_seen[$4] = 1
|
ip_seen[$4] = 1
|
||||||
day = substr($2, 1, 10)
|
|
||||||
day_count[day]++
|
|
||||||
dom = $5
|
dom = $5
|
||||||
if (dom != "" && dom != "-") dom_count[dom]++
|
if (dom != "" && dom != "-") dom_count[dom]++
|
||||||
proto = $8
|
proto = $8
|
||||||
@@ -359,11 +369,16 @@ calculate_stats() {
|
|||||||
unbans++
|
unbans++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# Aktivster Tag: separater Zeitraum (konfigurierbar, z.B. letzte 30 Tage)
|
||||||
|
$1 >= bs && $1 <= e && $3 == "BAN" {
|
||||||
|
bday = substr($2, 1, 10)
|
||||||
|
bday_count[bday]++
|
||||||
|
}
|
||||||
END {
|
END {
|
||||||
for (ip in ip_seen) unique++
|
for (ip in ip_seen) unique++
|
||||||
busiest = ""; max_d = 0
|
busiest = ""; max_d = 0
|
||||||
for (d in day_count) {
|
for (d in bday_count) {
|
||||||
if (day_count[d] > max_d) { max_d = day_count[d]; busiest = d }
|
if (bday_count[d] > max_d) { max_d = bday_count[d]; busiest = d; busiest_cnt = bday_count[d] }
|
||||||
}
|
}
|
||||||
print "BANS=" (bans+0)
|
print "BANS=" (bans+0)
|
||||||
print "UNBANS=" (unbans+0)
|
print "UNBANS=" (unbans+0)
|
||||||
@@ -373,6 +388,7 @@ calculate_stats() {
|
|||||||
print "SF=" (sf+0)
|
print "SF=" (sf+0)
|
||||||
print "EB=" (eb+0)
|
print "EB=" (eb+0)
|
||||||
print "BUSIEST=" busiest
|
print "BUSIEST=" busiest
|
||||||
|
print "BUSIEST_CNT=" (busiest_cnt+0)
|
||||||
for (ip in ip_count) print "IP\t" ip_count[ip] "\t" ip
|
for (ip in ip_count) print "IP\t" ip_count[ip] "\t" ip
|
||||||
for (d in dom_count) print "DOMAIN\t" dom_count[d] "\t" d
|
for (d in dom_count) print "DOMAIN\t" dom_count[d] "\t" d
|
||||||
for (p in proto_count) print "PROTO\t" proto_count[p] "\t" p
|
for (p in proto_count) print "PROTO\t" proto_count[p] "\t" p
|
||||||
@@ -395,12 +411,23 @@ calculate_stats() {
|
|||||||
|
|
||||||
local busiest_raw
|
local busiest_raw
|
||||||
busiest_raw=$(echo "$awk_result" | awk -F= '$1=="BUSIEST" {print $2; exit}')
|
busiest_raw=$(echo "$awk_result" | awk -F= '$1=="BUSIEST" {print $2; exit}')
|
||||||
|
local busiest_cnt
|
||||||
|
busiest_cnt=$(echo "$awk_result" | awk -F= '$1=="BUSIEST_CNT" {print $2; exit}')
|
||||||
if [[ -n "$busiest_raw" ]]; then
|
if [[ -n "$busiest_raw" ]]; then
|
||||||
BUSIEST_DAY=$(date -d "$busiest_raw" '+%d.%m.%Y' 2>/dev/null || echo "$busiest_raw")
|
local busiest_formatted
|
||||||
|
busiest_formatted=$(date -d "$busiest_raw" '+%d.%m.%Y' 2>/dev/null || echo "$busiest_raw")
|
||||||
|
BUSIEST_DAY="${busiest_formatted} (${busiest_cnt})"
|
||||||
else
|
else
|
||||||
BUSIEST_DAY="–"
|
BUSIEST_DAY="–"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Dynamisches Label für den aktivsten Tag
|
||||||
|
if [[ "$REPORT_BUSIEST_DAY_RANGE" == "0" || -z "$REPORT_BUSIEST_DAY_RANGE" ]]; then
|
||||||
|
BUSIEST_DAY_LABEL="Aktivster Tag"
|
||||||
|
else
|
||||||
|
BUSIEST_DAY_LABEL="Aktivster Tag (${REPORT_BUSIEST_DAY_RANGE} Tage)"
|
||||||
|
fi
|
||||||
|
|
||||||
# Top-Listen: Tab-getrennte Felder sortieren und in das erwartete Format bringen
|
# Top-Listen: Tab-getrennte Felder sortieren und in das erwartete Format bringen
|
||||||
TOP10_IPS=$( echo "$awk_result" | awk -F'\t' '$1=="IP" {print $2 " " $3}' | sort -rn | head -10)
|
TOP10_IPS=$( echo "$awk_result" | awk -F'\t' '$1=="IP" {print $2 " " $3}' | sort -rn | head -10)
|
||||||
TOP10_DOMAINS=$(echo "$awk_result" | awk -F'\t' '$1=="DOMAIN" {print $2 " " $3}' | sort -rn | head -10)
|
TOP10_DOMAINS=$(echo "$awk_result" | awk -F'\t' '$1=="DOMAIN" {print $2 " " $3}' | sort -rn | head -10)
|
||||||
@@ -786,6 +813,7 @@ generate_report() {
|
|||||||
report="${report//\{\{SUBDOMAIN_FLOOD_BANS\}\}/$SUBDOMAIN_FLOOD_BANS}"
|
report="${report//\{\{SUBDOMAIN_FLOOD_BANS\}\}/$SUBDOMAIN_FLOOD_BANS}"
|
||||||
report="${report//\{\{EXTERNAL_BLOCKLIST_BANS\}\}/$EXTERNAL_BLOCKLIST_BANS}"
|
report="${report//\{\{EXTERNAL_BLOCKLIST_BANS\}\}/$EXTERNAL_BLOCKLIST_BANS}"
|
||||||
report="${report//\{\{BUSIEST_DAY\}\}/$BUSIEST_DAY}"
|
report="${report//\{\{BUSIEST_DAY\}\}/$BUSIEST_DAY}"
|
||||||
|
report="${report//\{\{BUSIEST_DAY_LABEL\}\}/$BUSIEST_DAY_LABEL}"
|
||||||
report="${report//\{\{TOP10_IPS_TABLE\}\}/$top10_ips_table}"
|
report="${report//\{\{TOP10_IPS_TABLE\}\}/$top10_ips_table}"
|
||||||
report="${report//\{\{TOP10_DOMAINS_TABLE\}\}/$top10_domains_table}"
|
report="${report//\{\{TOP10_DOMAINS_TABLE\}\}/$top10_domains_table}"
|
||||||
report="${report//\{\{PROTOCOL_TABLE\}\}/$protocol_table}"
|
report="${report//\{\{PROTOCOL_TABLE\}\}/$protocol_table}"
|
||||||
@@ -832,6 +860,7 @@ generate_report() {
|
|||||||
report="${report//\{\{SUBDOMAIN_FLOOD_BANS\}\}/$SUBDOMAIN_FLOOD_BANS}"
|
report="${report//\{\{SUBDOMAIN_FLOOD_BANS\}\}/$SUBDOMAIN_FLOOD_BANS}"
|
||||||
report="${report//\{\{EXTERNAL_BLOCKLIST_BANS\}\}/$EXTERNAL_BLOCKLIST_BANS}"
|
report="${report//\{\{EXTERNAL_BLOCKLIST_BANS\}\}/$EXTERNAL_BLOCKLIST_BANS}"
|
||||||
report="${report//\{\{BUSIEST_DAY\}\}/$BUSIEST_DAY}"
|
report="${report//\{\{BUSIEST_DAY\}\}/$BUSIEST_DAY}"
|
||||||
|
report="${report//\{\{BUSIEST_DAY_LABEL\}\}/$BUSIEST_DAY_LABEL}"
|
||||||
report="${report//\{\{TOP10_IPS_TEXT\}\}/$top10_ips_txt}"
|
report="${report//\{\{TOP10_IPS_TEXT\}\}/$top10_ips_txt}"
|
||||||
report="${report//\{\{TOP10_DOMAINS_TEXT\}\}/$top10_domains_txt}"
|
report="${report//\{\{TOP10_DOMAINS_TEXT\}\}/$top10_domains_txt}"
|
||||||
report="${report//\{\{PROTOCOL_TEXT\}\}/$protocol_txt}"
|
report="${report//\{\{PROTOCOL_TEXT\}\}/$protocol_txt}"
|
||||||
@@ -983,6 +1012,7 @@ show_cron_status() {
|
|||||||
echo " Empfänger: ${REPORT_EMAIL_TO:-nicht konfiguriert}"
|
echo " Empfänger: ${REPORT_EMAIL_TO:-nicht konfiguriert}"
|
||||||
echo " Absender: ${REPORT_EMAIL_FROM}"
|
echo " Absender: ${REPORT_EMAIL_FROM}"
|
||||||
echo " Mail-Befehl: ${REPORT_MAIL_CMD}"
|
echo " Mail-Befehl: ${REPORT_MAIL_CMD}"
|
||||||
|
echo " Aktivster Tag: letzte ${REPORT_BUSIEST_DAY_RANGE:-30} Tage"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
if command -v "$REPORT_MAIL_CMD" &>/dev/null; then
|
if command -v "$REPORT_MAIL_CMD" &>/dev/null; then
|
||||||
|
|||||||
@@ -324,7 +324,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="stat-card success">
|
<div class="stat-card success">
|
||||||
<div class="stat-value">{{BUSIEST_DAY}}</div>
|
<div class="stat-value">{{BUSIEST_DAY}}</div>
|
||||||
<div class="stat-label">Aktivster Tag</div>
|
<div class="stat-label">{{BUSIEST_DAY_LABEL}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
Rate-Limit Sperren: {{RATELIMIT_BANS}}
|
Rate-Limit Sperren: {{RATELIMIT_BANS}}
|
||||||
Subdomain-Flood Sperren: {{SUBDOMAIN_FLOOD_BANS}}
|
Subdomain-Flood Sperren: {{SUBDOMAIN_FLOOD_BANS}}
|
||||||
Externe Blocklist: {{EXTERNAL_BLOCKLIST_BANS}}
|
Externe Blocklist: {{EXTERNAL_BLOCKLIST_BANS}}
|
||||||
Aktivster Tag: {{BUSIEST_DAY}}
|
{{BUSIEST_DAY_LABEL}}: {{BUSIEST_DAY}}
|
||||||
|
|
||||||
───────────────────────────────────────────────────────────────
|
───────────────────────────────────────────────────────────────
|
||||||
🏴☠️ TOP 10 – AUFFÄLLIGSTE IPs
|
🏴☠️ TOP 10 – AUFFÄLLIGSTE IPs
|
||||||
|
|||||||
Reference in New Issue
Block a user