parent
8b4f2d9fe8
commit
67b6e1fa02
|
|
@ -18,7 +18,7 @@ class GuestOnlyMiddleware
|
|||
{
|
||||
if (Auth::check()) {
|
||||
// Eingeloggt → z. B. Dashboard weiterleiten
|
||||
return redirect()->route('dashboard');
|
||||
return redirect()->route('ui.dashboard');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ class Fail2BanCard extends Component
|
|||
{
|
||||
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 int $activeBans = 0; // Summe gebannter IPs über alle Jails
|
||||
public array $jails = []; // [['name','banned','bantime','ips'=>[['ip','remaining','until'],...]],...]
|
||||
public array $topIps = []; // [['ip'=>'x.x.x.x','count'=>N], ...]
|
||||
|
||||
public function mount(): void
|
||||
|
|
@ -22,7 +22,7 @@ class Fail2BanCard extends Component
|
|||
return view('livewire.ui.security.fail2-ban-card');
|
||||
}
|
||||
|
||||
// Wird vom Button "Neu prüfen" genutzt
|
||||
/** Button „Neu prüfen“ */
|
||||
public function refresh(): void
|
||||
{
|
||||
$this->load(true);
|
||||
|
|
@ -33,56 +33,89 @@ class Fail2BanCard extends Component
|
|||
protected function load(bool $force = false): void
|
||||
{
|
||||
// existiert fail2ban-client?
|
||||
$bin = trim((string) @shell_exec('command -v fail2ban-client 2>/dev/null')) ?: '';
|
||||
$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 (bei Permission-Fehler kommt Klartext)
|
||||
[$ok, $raw] = $this->f2b('ping'); // ok == "pong" erkannt
|
||||
if (!$ok && stripos($raw, 'permission denied') !== false) {
|
||||
$this->available = true;
|
||||
$this->available = true;
|
||||
$this->permDenied = true;
|
||||
$this->activeBans = 0;
|
||||
$this->jails = [];
|
||||
$this->topIps = $this->collectTopIps();
|
||||
$this->jails = [];
|
||||
$this->topIps = $this->collectTopIps();
|
||||
return;
|
||||
}
|
||||
|
||||
// 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))) : [];
|
||||
$jails = $jailsLn ? array_filter(array_map('trim', preg_split('/\s*,\s*/', $jailsLn))) : [];
|
||||
|
||||
$total = 0;
|
||||
$rows = [];
|
||||
|
||||
$total = 0; $rows = [];
|
||||
foreach ($jails as $j) {
|
||||
[, $s] = $this->f2b('status '.escapeshellarg($j));
|
||||
$banned = (int) ($this->firstMatch('/Currently banned:\s+(\d+)/i', $s) ?: 0);
|
||||
$bantimeSecs = $this->getBantime($j); // Sek., -1 = permanent
|
||||
|
||||
[, $s] = $this->f2b('status ' . escapeshellarg($j));
|
||||
$banned = (int)($this->firstMatch('/Currently banned:\s+(\d+)/i', $s) ?: 0);
|
||||
$ipList = $this->firstMatch('/Banned IP list:\s*(.+)$/mi', $s) ?: '';
|
||||
$ips = $ipList !== '' ? array_values(array_filter(array_map('trim', preg_split('/\s+/', $ipList)))) : [];
|
||||
$rows[] = ['name'=>$j,'banned'=>$banned,'ips'=>array_slice($ips, 0, 8)];
|
||||
$ips = $ipList !== '' ? array_values(array_filter(array_map('trim', preg_split('/\s+/', $ipList)))) : [];
|
||||
|
||||
// Restzeiten je IP bestimmen (aus /var/log/fail2ban.log)
|
||||
$ipDetails = [];
|
||||
foreach (array_slice($ips, 0, 50) as $ip) {
|
||||
$banAt = $this->lastBanTimestamp($j, $ip); // Unix-Timestamp oder null
|
||||
$remaining = null;
|
||||
$until = null;
|
||||
|
||||
if ($banAt !== null) {
|
||||
if ((int)$bantimeSecs === -1) {
|
||||
$remaining = -1; // permanent
|
||||
} else {
|
||||
$remaining = max(0, $bantimeSecs - (time() - $banAt));
|
||||
$until = $remaining > 0 ? ($banAt + $bantimeSecs) : null;
|
||||
}
|
||||
}
|
||||
|
||||
$ipDetails[] = [
|
||||
'ip' => $ip,
|
||||
'remaining' => $remaining, // -1 = permanent, 0 = abgelaufen, >0 Sek.
|
||||
'until' => $until, // Unix-Timestamp oder null
|
||||
];
|
||||
}
|
||||
|
||||
$rows[] = [
|
||||
'name' => $j,
|
||||
'banned' => $banned,
|
||||
'ips' => $ipDetails,
|
||||
'bantime' => (int)$bantimeSecs,
|
||||
];
|
||||
$total += $banned;
|
||||
}
|
||||
|
||||
$this->available = true;
|
||||
$this->available = true;
|
||||
$this->permDenied = false;
|
||||
$this->activeBans = $total;
|
||||
$this->jails = $rows;
|
||||
$this->topIps = $this->collectTopIps();
|
||||
$this->jails = $rows;
|
||||
$this->topIps = $this->collectTopIps();
|
||||
}
|
||||
|
||||
/** 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);
|
||||
$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
|
||||
|
|
@ -91,44 +124,282 @@ class Fail2BanCard extends Component
|
|||
return [$ok, $out];
|
||||
}
|
||||
|
||||
private function getBantime(string $jail): int
|
||||
{
|
||||
[, $out] = $this->f2b('get ' . escapeshellarg($jail) . ' bantime');
|
||||
$val = trim($out);
|
||||
if (preg_match('/-?\d+/', $val, $m)) {
|
||||
return (int)$m[0];
|
||||
}
|
||||
return 600; // defensiver Default
|
||||
}
|
||||
|
||||
/** letzte Ban-Zeile aus /var/log/fail2ban.log → Unix-Timestamp */
|
||||
private function lastBanTimestamp(string $jail, string $ip): ?int
|
||||
{
|
||||
$cmd = "grep -F \"[{$jail}] Ban {$ip}\" /var/log/fail2ban.log 2>/dev/null | tail -n 1";
|
||||
$line = trim((string)@shell_exec($cmd));
|
||||
if ($line === '') return null;
|
||||
|
||||
// "YYYY-MM-DD HH:MM:SS,mmm ..."
|
||||
if (preg_match('/^(\d{4}-\d{2}-\d{2})\s+(\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
|
||||
{
|
||||
return preg_match($pattern, $haystack, $m) ? trim($m[1]) : null;
|
||||
}
|
||||
|
||||
/** Zählt die häufigsten IPs aus den letzten Fail2Ban-Logs (ban/unban Events) */
|
||||
/** Top-IPs grob zählen (aus der aktuellen Jail-Liste; Fallback: Log) */
|
||||
private function collectTopIps(): array
|
||||
{
|
||||
// 1. Versuch: IPs direkt aus den Jails
|
||||
$rows = [];
|
||||
$map = [];
|
||||
foreach ($this->jails as $jail) {
|
||||
foreach ($jail['ips'] as $ip) {
|
||||
$rows[$ip] = ($rows[$ip] ?? 0) + 1;
|
||||
foreach ($jail['ips'] as $row) {
|
||||
$ip = $row['ip'] ?? null;
|
||||
if (!$ip) continue;
|
||||
$map[$ip] = ($map[$ip] ?? 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($rows)) {
|
||||
arsort($rows);
|
||||
return collect($rows)
|
||||
->map(fn($count, $ip) => ['ip' => $ip, 'count' => $count])
|
||||
->values()
|
||||
->take(5)
|
||||
->toArray();
|
||||
if (!empty($map)) {
|
||||
arsort($map);
|
||||
$out = [];
|
||||
foreach (array_slice($map, 0, 5, true) as $ip => $count) {
|
||||
$out[] = ['ip' => $ip, 'count' => $count];
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
// 2. Fallback: Falls keine Jails/IPs → Logdatei
|
||||
// Fallback: aus fail2ban.log
|
||||
$cmd = 'grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}" /var/log/fail2ban.log 2>/dev/null'
|
||||
. ' | sort | uniq -c | sort -nr | head -5';
|
||||
$log = (string) @shell_exec($cmd);
|
||||
|
||||
$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]];
|
||||
$rows[] = ['ip' => $m[2], 'count' => (int)$m[1]];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
//namespace App\Livewire\Ui\Security;
|
||||
//
|
||||
//use Livewire\Component;
|
||||
//
|
||||
//class Fail2BanCard extends Component
|
||||
//{
|
||||
// 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->permDenied = false;
|
||||
// $this->activeBans = 0;
|
||||
// $this->jails = [];
|
||||
// $this->topIps = [];
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 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;
|
||||
// $this->activeBans = 0;
|
||||
// $this->jails = [];
|
||||
// $this->topIps = $this->collectTopIps();
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// // 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))) : [];
|
||||
//
|
||||
// $total = 0; $rows = [];
|
||||
//// ... in load() NACH dem Einlesen der Jail-Liste:
|
||||
// $rows = [];
|
||||
// foreach ($jails as $j) {
|
||||
// $bantimeSecs = $this->getBantime($j); // konfigurierter Wert (Sekunden, -1 = permanent)
|
||||
//
|
||||
// [, $s] = $this->f2b('status '.escapeshellarg($j));
|
||||
// $banned = (int)($this->firstMatch('/Currently banned:\s+(\d+)/i', $s) ?: 0);
|
||||
// $ipList = $this->firstMatch('/Banned IP list:\s*(.+)$/mi', $s) ?: '';
|
||||
// $ips = $ipList !== '' ? array_values(array_filter(array_map('trim', preg_split('/\s+/', $ipList)))) : [];
|
||||
//
|
||||
// // Restzeiten je IP bestimmen (aus /var/log/fail2ban.log)
|
||||
// $ipDetails = [];
|
||||
// foreach (array_slice($ips, 0, 50) as $ip) {
|
||||
// $banAt = $this->lastBanTimestamp($j, $ip); // Unix-Timestamp oder null
|
||||
// $remaining = null;
|
||||
// $until = null;
|
||||
//
|
||||
// if ($banAt !== null) {
|
||||
// if ((int)$bantimeSecs === -1) {
|
||||
// $remaining = -1; // permanent
|
||||
// } else {
|
||||
// $remaining = max(0, $bantimeSecs - (time() - $banAt));
|
||||
// $until = $remaining > 0 ? ($banAt + $bantimeSecs) : null;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// $ipDetails[] = [
|
||||
// 'ip' => $ip,
|
||||
// 'remaining' => $remaining, // -1 = permanent, 0 = abgelaufen, >0 Sek.
|
||||
// 'until' => $until, // Unix-Timestamp oder null
|
||||
// ];
|
||||
// }
|
||||
//
|
||||
// $rows[] = [
|
||||
// 'name' => $j,
|
||||
// 'banned' => $banned,
|
||||
// 'ips' => $ipDetails, // jetzt mit Details
|
||||
// 'bantime' => (int)$bantimeSecs,
|
||||
// ];
|
||||
// $total += $banned;
|
||||
// }
|
||||
//
|
||||
// // foreach ($jails as $j) {
|
||||
//// [, $s] = $this->f2b('status '.escapeshellarg($j));
|
||||
//// $banned = (int) ($this->firstMatch('/Currently banned:\s+(\d+)/i', $s) ?: 0);
|
||||
//// $ipList = $this->firstMatch('/Banned IP list:\s*(.+)$/mi', $s) ?: '';
|
||||
//// $ips = $ipList !== '' ? array_values(array_filter(array_map('trim', preg_split('/\s+/', $ipList)))) : [];
|
||||
//// $rows[] = ['name'=>$j,'banned'=>$banned,'ips'=>array_slice($ips, 0, 8)];
|
||||
//// $total += $banned;
|
||||
//// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// $this->available = true;
|
||||
// $this->permDenied = false;
|
||||
// $this->activeBans = $total;
|
||||
// $this->jails = $rows;
|
||||
// $this->topIps = $this->collectTopIps();
|
||||
// }
|
||||
//
|
||||
// /** 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);
|
||||
//
|
||||
// $ok = stripos($out, 'Status') !== false
|
||||
// || stripos($out, 'Jail list') !== false
|
||||
// || stripos($out, 'pong') !== false;
|
||||
//
|
||||
// return [$ok, $out];
|
||||
// }
|
||||
//
|
||||
// private function getBantime(string $jail): int
|
||||
// {
|
||||
// [, $out] = $this->f2b('get '.escapeshellarg($jail).' bantime');
|
||||
// // fail2ban liefert Seconds als Zahl (oder mit Newline)
|
||||
// $val = trim($out);
|
||||
// // Fallback: manche Versionen geben nur Zahl ohne Kontext zurück,
|
||||
// // sonst aus jail.local ermitteln wäre overkill -> einfache Zahl extrahieren:
|
||||
// if (preg_match('/-?\d+/', $val, $m)) {
|
||||
// return (int)$m[0];
|
||||
// }
|
||||
// // wenn nicht ermittelbar: 600 Sekunden als conservative default
|
||||
// return 600;
|
||||
// }
|
||||
//
|
||||
// /** Sucht die letzte "Ban <IP>"-Zeile für Jail in /var/log/fail2ban.log und gibt Unix-Timestamp zurück. */
|
||||
// private function lastBanTimestamp(string $jail, string $ip): ?int
|
||||
// {
|
||||
// // Beispiel-Logzeilen:
|
||||
// // 2025-10-29 18:07:11,436 fail2ban.actions [12345]: NOTICE [sshd] Ban 1.2.3.4
|
||||
// // Wir holen die letzte passende Zeile (tail mit grep), dann parsen Datum.
|
||||
// $pattern = escapeshellarg(sprintf('\\[%s\\] Ban %s', $jail, $ip));
|
||||
// $cmd = "grep -F \"[{$jail}] Ban {$ip}\" /var/log/fail2ban.log 2>/dev/null | tail -n 1";
|
||||
// $line = (string)@shell_exec($cmd);
|
||||
// $line = trim($line);
|
||||
// if ($line === '') {
|
||||
// return null;
|
||||
// }
|
||||
// // Datumsformat am Anfang: "YYYY-MM-DD HH:MM:SS,mmm"
|
||||
// if (preg_match('/^(\d{4}-\d{2}-\d{2})\s+(\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
|
||||
// {
|
||||
// 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
|
||||
// {
|
||||
// // 1. Versuch: IPs direkt aus den Jails
|
||||
// $rows = [];
|
||||
// foreach ($this->jails as $jail) {
|
||||
// foreach ($jail['ips'] as $ip) {
|
||||
// $rows[$ip] = ($rows[$ip] ?? 0) + 1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (!empty($rows)) {
|
||||
// arsort($rows);
|
||||
// return collect($rows)
|
||||
// ->map(fn($count, $ip) => ['ip' => $ip, 'count' => $count])
|
||||
// ->values()
|
||||
// ->take(5)
|
||||
// ->toArray();
|
||||
// }
|
||||
//
|
||||
// // 2. Fallback: Falls keine Jails/IPs → Logdatei
|
||||
// $cmd = 'grep -Eo "([0-9]{1,3}\.){3}[0-9]{1,3}" /var/log/fail2ban.log 2>/dev/null'
|
||||
// . ' | 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;
|
||||
// }
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -26,14 +26,36 @@
|
|||
<div class="rounded-xl border border-white/10 bg-white/5 px-3 py-2">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-white/85 font-medium">{{ $j['name'] }}</div>
|
||||
<span class="px-2 py-0.5 rounded-full border text-[11px]
|
||||
{{ $j['banned']>0 ? 'text-amber-200 border-amber-400/30 bg-amber-500/10' : 'text-white/60 border-white/20 bg-white/5' }}">
|
||||
{{ $j['banned'] }} gebannt
|
||||
</span>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-[11px] text-white/50">
|
||||
Bannzeit:
|
||||
@if($j['bantime'] === -1) permanent
|
||||
@else {{ $j['bantime'] }}s
|
||||
@endif
|
||||
</span>
|
||||
<span class="px-2 py-0.5 rounded-full border text-[11px]
|
||||
{{ $j['banned']>0 ? 'text-amber-200 border-amber-400/30 bg-amber-500/10' : 'text-white/60 border-white/20 bg-white/5' }}">
|
||||
{{ $j['banned'] }} gebannt
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if(!empty($j['ips']))
|
||||
<div class="mt-1 text-[12px] text-white/65 font-mono break-words">
|
||||
{{ implode(', ', $j['ips']) }}
|
||||
<div class="mt-2 grid gap-1">
|
||||
@foreach($j['ips'] as $ip)
|
||||
<div class="flex items-center gap-2 text-[12px] text-white/80 font-mono">
|
||||
<span>{{ $ip['ip'] }}</span>
|
||||
@if($ip['remaining'] === -1)
|
||||
<span class="px-1.5 py-0.5 rounded border border-rose-400/30 bg-rose-500/10 text-rose-200">
|
||||
permanent
|
||||
</span>
|
||||
@elseif(is_int($ip['remaining']) && $ip['remaining'] > 0)
|
||||
<span class="px-1.5 py-0.5 rounded border border-amber-400/30 bg-amber-500/10 text-amber-100">
|
||||
{{ gmdate('H\h i\m s\s', $ip['remaining']) }}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
|
@ -43,7 +65,7 @@
|
|||
</div>
|
||||
|
||||
{{-- Top IPs aus Ban-Events --}}
|
||||
<div class="mt-3">
|
||||
<div class="mt-4">
|
||||
<div class="text-sm text-white/70">Top IPs (letzte Fail2Ban-Logs):</div>
|
||||
<ul class="mt-2 space-y-1 text-sm">
|
||||
@forelse($topIps as $i)
|
||||
|
|
@ -67,3 +89,85 @@
|
|||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
{{--<div class="glass-card p-4 rounded-2xl border border-white/10 bg-white/5">--}}
|
||||
{{-- <div class="flex items-center justify-between mb-3">--}}
|
||||
{{-- <div class="inline-flex items-center gap-2 bg-white/5 border border-white/10 px-2.5 py-1 rounded-full">--}}
|
||||
{{-- <i class="ph ph-shield-checkered text-white/70 text-[13px]"></i>--}}
|
||||
{{-- <span class="text-[11px] uppercase text-white/70">Fail2Ban</span>--}}
|
||||
{{-- </div>--}}
|
||||
|
||||
{{-- @if($available)--}}
|
||||
{{-- <span class="px-2 py-0.5 rounded-full border text-xs--}}
|
||||
{{-- {{ $activeBans>0 ? 'text-amber-200 border-amber-400/30 bg-amber-500/10' : 'text-emerald-300 border-emerald-400/30 bg-emerald-500/10' }}">--}}
|
||||
{{-- {{ $activeBans }} aktuell--}}
|
||||
{{-- </span>--}}
|
||||
{{-- @else--}}
|
||||
{{-- <span class="px-2 py-0.5 rounded-full border text-xs text-rose-300 border-rose-400/30 bg-rose-500/10">--}}
|
||||
{{-- nicht installiert--}}
|
||||
{{-- </span>--}}
|
||||
{{-- @endif--}}
|
||||
{{-- </div>--}}
|
||||
|
||||
{{-- @if(!$available)--}}
|
||||
{{-- <div class="text-sm text-white/60">fail2ban-client wurde nicht gefunden.</div>--}}
|
||||
{{-- @else--}}
|
||||
{{-- --}}{{-- Jails --}}
|
||||
{{-- <div class="space-y-2">--}}
|
||||
{{-- @forelse($jails as $j)--}}
|
||||
{{-- <div class="rounded-xl border border-white/10 bg-white/5 px-3 py-2">--}}
|
||||
{{-- <div class="flex items-center justify-between">--}}
|
||||
{{-- <div class="text-white/85 font-medium">{{ $j['name'] }}</div>--}}
|
||||
{{-- <span class="px-2 py-0.5 rounded-full border text-[11px]--}}
|
||||
{{-- {{ $j['banned']>0 ? 'text-amber-200 border-amber-400/30 bg-amber-500/10' : 'text-white/60 border-white/20 bg-white/5' }}">--}}
|
||||
{{-- {{ $j['banned'] }} gebannt--}}
|
||||
{{-- </span>--}}
|
||||
{{-- </div>--}}
|
||||
{{-- @if(!empty($j['ips']))--}}
|
||||
{{-- <div class="mt-1 text-[12px] text-white/65 font-mono break-words">--}}
|
||||
{{-- {{ implode(', ', $j['ips']) }}--}}
|
||||
{{-- </div>--}}
|
||||
{{-- @endif--}}
|
||||
{{-- </div>--}}
|
||||
{{-- @empty--}}
|
||||
{{-- <div class="text-sm text-white/60">Keine Jails gefunden.</div>--}}
|
||||
{{-- @endforelse--}}
|
||||
{{-- </div>--}}
|
||||
|
||||
{{-- --}}{{-- Top IPs aus Ban-Events --}}
|
||||
{{-- <div class="mt-3">--}}
|
||||
{{-- <div class="text-sm text-white/70">Top IPs (letzte Fail2Ban-Logs):</div>--}}
|
||||
{{-- <ul class="mt-2 space-y-1 text-sm">--}}
|
||||
{{-- @foreach($j['ips'] as $ip)--}}
|
||||
{{-- <div class="flex items-center gap-2 text-[12px] text-white/80 font-mono">--}}
|
||||
{{-- <span>{{ $ip['ip'] }}</span>--}}
|
||||
{{-- @if($ip['remaining'] === -1)--}}
|
||||
{{-- <span class="px-1.5 py-0.5 rounded border border-rose-400/30 bg-rose-500/10 text-rose-200">permanent</span>--}}
|
||||
{{-- @elseif(is_int($ip['remaining']) && $ip['remaining'] > 0)--}}
|
||||
{{-- <span class="px-1.5 py-0.5 rounded border border-amber-400/30 bg-amber-500/10 text-amber-100">--}}
|
||||
{{-- {{ gmdate('H\h i\m s\s', $ip['remaining']) }}--}}
|
||||
{{-- </span>--}}
|
||||
{{-- @endif--}}
|
||||
{{-- </div>--}}
|
||||
{{-- @endforeach--}}
|
||||
{{-- @forelse($topIps as $i)--}}
|
||||
{{-- <li class="flex justify-between">--}}
|
||||
{{-- <span class="text-white/80 font-mono">{{ $i['ip'] }}</span>--}}
|
||||
{{-- <span class="text-white/60">{{ $i['count'] }}</span>--}}
|
||||
{{-- </li>--}}
|
||||
{{-- @empty--}}
|
||||
{{-- <li class="text-white/50">–</li>--}}
|
||||
{{-- @endforelse--}}
|
||||
{{-- </ul>--}}
|
||||
{{-- </div>--}}
|
||||
|
||||
{{-- <div class="mt-4 flex justify-end">--}}
|
||||
{{-- <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>--}}
|
||||
{{-- <span wire:loading.remove>Neu prüfen</span>--}}
|
||||
{{-- <span wire:loading>prüfe…</span>--}}
|
||||
{{-- </button>--}}
|
||||
{{-- </div>--}}
|
||||
{{-- @endif--}}
|
||||
{{--</div>--}}
|
||||
|
|
|
|||
Loading…
Reference in New Issue