Fix: Mailbox Stats über Dovecot mit config/mailpool.php
parent
d9867db546
commit
02e558bf4b
|
|
@ -179,13 +179,48 @@ class Fail2BanCard extends Component
|
|||
// return 600;
|
||||
// }
|
||||
|
||||
/** baut Detail-Liste inkl. Restzeit */
|
||||
/** Letzten Ban-Zeitpunkt (Unix-Timestamp) aus /var/log/fail2ban.log ermitteln. */
|
||||
private function lastBanTimestamp(string $jail, string $ip): ?int
|
||||
{
|
||||
$file = '/var/log/fail2ban.log';
|
||||
if (!is_readable($file)) return null;
|
||||
|
||||
// nur das Ende der Datei lesen (Performance, auch bei Rotation groß genug wählen)
|
||||
$tailBytes = 400000; // 400 KB
|
||||
$size = @filesize($file) ?: 0;
|
||||
$seek = max(0, $size - $tailBytes);
|
||||
|
||||
$fh = @fopen($file, 'rb');
|
||||
if (!$fh) return null;
|
||||
if ($seek > 0) fseek($fh, $seek);
|
||||
$data = stream_get_contents($fh) ?: '';
|
||||
fclose($fh);
|
||||
|
||||
// Beispielzeile:
|
||||
// 2025-10-30 22:34:20,797 fail2ban.actions [...] NOTICE [sshd] Ban 193.46.255.244
|
||||
$j = preg_quote($jail, '/');
|
||||
$p = preg_quote($ip, '/');
|
||||
$pattern = '/^(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2}),\d+.*\['.$j.'\]\s+Ban\s+'.$p.'\s*$/m';
|
||||
|
||||
if (preg_match_all($pattern, $data, $m) && !empty($m[1])) {
|
||||
$date = end($m[1]); // YYYY-MM-DD
|
||||
$time = end($m[2]); // HH:MM:SS
|
||||
$dt = \DateTime::createFromFormat('Y-m-d H:i:s', "$date $time", new \DateTimeZone(date_default_timezone_get()));
|
||||
return $dt ? $dt->getTimestamp() : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Baut Details inkl. Restzeit (Sekunden; -1 = permanent). */
|
||||
private function buildIpDetails(string $jail, array $ips, int $bantime): array
|
||||
{
|
||||
$now = time(); $out = [];
|
||||
$now = time();
|
||||
$out = [];
|
||||
|
||||
foreach ($ips as $ip) {
|
||||
$banAt = $this->lastBanTimestamp($jail, $ip);
|
||||
$remaining = null; $until = null;
|
||||
$remaining = null;
|
||||
$until = null;
|
||||
|
||||
if ($bantime === -1) {
|
||||
$remaining = -1; // permanent
|
||||
|
|
@ -194,37 +229,15 @@ class Fail2BanCard extends Component
|
|||
$until = $remaining > 0 ? ($banAt + $bantime) : null;
|
||||
}
|
||||
|
||||
$out[] = ['ip' => $ip, 'remaining' => $remaining, 'until' => $until];
|
||||
$out[] = [
|
||||
'ip' => $ip,
|
||||
'remaining' => $remaining, // -1 = permanent, null = Ban-Zeitpunkt nicht gefunden, >=0 = Sekunden
|
||||
'until' => $until, // Unix-Timestamp oder null
|
||||
];
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/** letzte "Ban <IP>"-Zeile finden (Log + Rotation + journald), liefert Unix-Timestamp oder null */
|
||||
private function lastBanTimestamp(string $jail, string $ip): ?int
|
||||
{
|
||||
// 1) zgrep in /var/log/fail2ban.log*
|
||||
$line = (string)@shell_exec(
|
||||
"zgrep -h -E '\\[{$jail}\\]\\s+Ban\\s+{$ip}' /var/log/fail2ban.log* 2>/dev/null | tail -n 1"
|
||||
);
|
||||
$line = trim($line);
|
||||
|
||||
// 2) Fallback: journald
|
||||
if ($line === '') {
|
||||
$line = (string)@shell_exec(
|
||||
"journalctl -u fail2ban --since '14 days ago' 2>/dev/null | grep -F '[{$jail}] Ban {$ip}' | tail -n 1"
|
||||
);
|
||||
$line = trim($line);
|
||||
}
|
||||
if ($line === '') return null;
|
||||
|
||||
// "YYYY-MM-DD HH:MM:SS,mmm ..." oder ISO im Text
|
||||
if (preg_match('/^(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})/', $line, $m)
|
||||
|| preg_match('/(\d{4}-\d{2}-\d{2})[ T](\d{2}:\d{2}:\d{2})/', $line, $m)) {
|
||||
$ts = strtotime($m[1].' '.$m[2]);
|
||||
return $ts ?: null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private function firstMatch(string $pattern, string $haystack): ?string
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue