mailwolt/app/Livewire/Ui/Security/Fail2banBanlist.php

111 lines
3.1 KiB
PHP

<?php
namespace App\Livewire\Ui\Security;
use Livewire\Attributes\On;
use Livewire\Component;
class Fail2banBanlist extends Component
{
/**
* null oder '*' => alle Jails
* 'recidive' => nur dieses Jail
* 'mailwolt-blacklist' etc.
*/
public ?string $jail = null;
/** @var array<int,string> */
public array $banned = [];
#[On('f2b:refresh')]
public function refreshList(): void
{
$this->loadBannedIps();
}
public function mount(?string $jail = null): void
{
// erlaubt optionalen Param via <livewire ... :jail="'recidive'" />
$this->jail = $jail;
$this->loadBannedIps();
}
public function render()
{
return view('livewire.ui.security.fail2ban-banlist');
}
/* ================= core ================= */
private function loadBannedIps(): void
{
$jails = $this->jailList();
// ggf. nur ein bestimmtes Jail anzeigen
if (is_string($this->jail) && $this->jail !== '' && $this->jail !== '*') {
$jails = in_array($this->jail, $jails, true) ? [$this->jail] : [];
}
$ips = [];
foreach ($jails as $j) {
$out = $this->f2b("status ".escapeshellarg($j));
if (preg_match('/IP list:\s*(.+)$/mi', $out, $m)) {
$parts = preg_split('/\s+/', trim($m[1]));
foreach ($parts as $ip) {
if (filter_var($ip, FILTER_VALIDATE_IP)) $ips[] = $ip;
}
}
}
$this->banned = array_values(array_unique($ips));
}
/** Entbannt IP in allen passenden Jails */
public function unban(string $ip): void
{
if (!filter_var($ip, FILTER_VALIDATE_IP)) return;
$jails = $this->jailList();
if (is_string($this->jail) && $this->jail !== '' && $this->jail !== '*') {
$jails = in_array($this->jail, $jails, true) ? [$this->jail] : [];
}
$cnt = 0;
foreach ($jails as $j) {
$this->f2b("set ".escapeshellarg($j)." unbanip ".escapeshellarg($ip));
$cnt++;
}
$this->loadBannedIps();
$this->dispatch('toast',
type: 'done',
badge: 'Fail2Ban',
title: 'IP entbannt',
text: ($this->jail && $this->jail !== '*')
? "IP {$ip} in Jail „{$this->jail}“ entbannt."
: "IP {$ip} in {$cnt} Jail(s) entbannt.",
duration: 5000,
);
}
/* ================= helpers ================= */
/** Liefert Liste aller Jails über fail2ban-client */
private function jailList(): array
{
$out = $this->f2b('status');
if (preg_match('/Jail list:\s*(.+)$/mi', $out, $m)) {
$jails = array_map('trim', preg_split('/\s*,\s*/', trim($m[1])));
return array_values(array_filter($jails, fn($v) => $v !== ''));
}
return [];
}
/** führt fail2ban-client via sudo aus und gibt stdout zurück */
private function f2b(string $args): string
{
return (string) @shell_exec('sudo -n /usr/bin/fail2ban-client '.$args.' 2>&1');
}
}