Fix: Mailbox Stats über Dovecot mit config/mailpool.php

main v1.0.100
boban 2025-10-29 19:24:36 +01:00
parent 385b67c3c5
commit e3c7e8de33
2 changed files with 52 additions and 22 deletions

View File

@ -6,29 +6,45 @@ use Livewire\Component;
class Fail2BanCard extends Component
{
public bool $available = true;
public bool $permDenied = false; // neu
public int $activeBans = 0;
public array $jails = [];
public array $topIps = [];
public bool $available = true; // fail2ban-client vorhanden?
public bool $permDenied = false; // Socket/Root-Rechte fehlen?
public int $activeBans = 0; // Summe gebannter IPs über alle Jails
public array $jails = []; // [['name'=>'sshd','banned'=>2,'ips'=>['1.2.3.4',...]], ...]
public array $topIps = []; // [['ip'=>'x.x.x.x','count'=>N], ...]
// ...
public function mount(): void
{
$this->load();
}
public function render()
{
return view('livewire.ui.security.fail2-ban-card');
}
// Wird vom Button "Neu prüfen" genutzt
public function refresh(): void
{
$this->load(true);
}
/* --------------------- intern --------------------- */
protected function load(bool $force = false): void
{
// existiert fail2ban-client?
$bin = trim((string) @shell_exec('command -v fail2ban-client 2>/dev/null')) ?: '';
if ($bin === '') {
$this->available = false;
$this->available = false;
$this->permDenied = false;
$this->activeBans = 0;
$this->jails = [];
$this->topIps = [];
$this->jails = [];
$this->topIps = [];
return;
}
// ping → prüft zugleich Rechte (liefert Fehlertext, wenn Socket gesperrt)
[$ok, $raw] = $this->f2b('ping'); // ok==true wenn "pong"
// ping → prüft zugleich Rechte (bei Permission-Fehler kommt Klartext)
[$ok, $raw] = $this->f2b('ping'); // ok == "pong" erkannt
if (!$ok && stripos($raw, 'permission denied') !== false) {
$this->available = true;
$this->permDenied = true;
@ -38,7 +54,7 @@ class Fail2BanCard extends Component
return;
}
// Jails
// Jails auflisten
[, $status] = $this->f2b('status');
$jailsLn = $this->firstMatch('/Jail list:\s*(.+)$/mi', $status);
$jails = $jailsLn ? array_filter(array_map('trim', preg_split('/\s*,\s*/', $jailsLn))) : [];
@ -60,13 +76,13 @@ class Fail2BanCard extends Component
$this->topIps = $this->collectTopIps();
}
/** führt fail2ban-client aus; mit sudo-Fallback; gibt [ok, output] zurück */
/** führt fail2ban-client via sudo aus; gibt [ok, output] zurück */
private function f2b(string $args): array
{
$sudo = '/usr/bin/sudo';
$f2b = '/usr/bin/fail2ban-client';
$cmd = "timeout 2 $sudo -n $f2b $args 2>&1";
$out = (string) @shell_exec($cmd);
$sudo = '/usr/bin/sudo';
$f2b = '/usr/bin/fail2ban-client';
$cmd = "timeout 2 $sudo -n $f2b $args 2>&1";
$out = (string) @shell_exec($cmd);
$ok = stripos($out, 'Status') !== false
|| stripos($out, 'Jail list') !== false
@ -80,9 +96,22 @@ class Fail2BanCard extends Component
return preg_match($pattern, $haystack, $m) ? trim($m[1]) : null;
}
/** Zählt die häufigsten IPs aus den letzten Fail2Ban-Logs (ban/unban Events) */
private function collectTopIps(): array
{
// … (deine vorhandene Methode aus meiner letzten Antwort passt)
// lässt du unverändert.
// Zieh nur fail2ban.log, nicht auth/mail präziser & schneller
$cmd = 'tail -n 2000 /var/log/fail2ban.log 2>/dev/null'
. ' | grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}"'
. ' | sort | uniq -c | sort -nr | head -5';
$log = (string) @shell_exec($cmd);
$rows = [];
if ($log !== '') {
foreach (preg_split('/\R+/', trim($log)) as $l) {
if (preg_match('/^\s*(\d+)\s+(\d+\.\d+\.\d+\.\d+)/', $l, $m)) {
$rows[] = ['ip'=>$m[2], 'count'=>(int)$m[1]];
}
}
}
return $rows;
}
}

View File

@ -58,10 +58,11 @@
</div>
<div class="mt-4 flex justify-end">
<button wire:click="refresh"
<button wire:click="refresh" wire:loading.attr="disabled"
class="px-3 py-1.5 text-[12px] rounded-lg bg-white/5 border border-white/10 hover:bg-white/10">
<i class="ph ph-arrows-clockwise text-[13px]"></i>
Neu prüfen
<span wire:loading.remove>Neu prüfen</span>
<span wire:loading>prüfe…</span>
</button>
</div>
@endif