parent
d4255b08fa
commit
9aa9475387
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
namespace App\Livewire\Ui\Security;
|
||||
|
||||
use Livewire\Attributes\On;
|
||||
use Livewire\Component;
|
||||
use App\Models\Fail2banSetting;
|
||||
use App\Models\Fail2banIpList;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class Fail2banSettings extends Component
|
||||
{
|
||||
|
|
@ -31,13 +31,10 @@ class Fail2banSettings extends Component
|
|||
{
|
||||
$this->whitelist = Fail2banIpList::visibleWhitelist()->pluck('ip')->toArray();
|
||||
$this->blacklist = Fail2banIpList::visibleBlacklist()->pluck('ip')->toArray();
|
||||
// $this->whitelist = Fail2banIpList::where('type', 'whitelist')->pluck('ip')->toArray();
|
||||
// $this->blacklist = Fail2banIpList::where('type', 'blacklist')->pluck('ip')->toArray();
|
||||
}
|
||||
|
||||
public function mount(): void
|
||||
{
|
||||
// Setting holen oder Defaults anlegen
|
||||
$this->settings = Fail2banSetting::first() ?? Fail2banSetting::create([
|
||||
'bantime' => 3600,
|
||||
'max_bantime' => 43200,
|
||||
|
|
@ -50,7 +47,6 @@ class Fail2banSettings extends Component
|
|||
'external_mode' => false,
|
||||
]);
|
||||
|
||||
// Properties befüllen
|
||||
$this->fill([
|
||||
'bantime' => (int)$this->settings->bantime,
|
||||
'max_bantime' => (int)$this->settings->max_bantime,
|
||||
|
|
@ -78,29 +74,48 @@ class Fail2banSettings extends Component
|
|||
'cidr_v6' => 'required|integer|min:8|max:128',
|
||||
]);
|
||||
|
||||
// Einstellungen speichern
|
||||
$this->settings->update([
|
||||
'bantime' => $this->bantime,
|
||||
'max_bantime' => $this->max_bantime,
|
||||
'bantime_increment' => $this->bantime_increment,
|
||||
'bantime_factor' => $this->bantime_factor,
|
||||
'max_retry' => $this->max_retry,
|
||||
'findtime' => $this->findtime,
|
||||
'cidr_v4' => $this->cidr_v4,
|
||||
'cidr_v6' => $this->cidr_v6,
|
||||
'external_mode' => $this->external_mode,
|
||||
]);
|
||||
try {
|
||||
// Einstellungen speichern
|
||||
$this->settings->update([
|
||||
'bantime' => $this->bantime,
|
||||
'max_bantime' => $this->max_bantime,
|
||||
'bantime_increment' => $this->bantime_increment,
|
||||
'bantime_factor' => $this->bantime_factor,
|
||||
'max_retry' => $this->max_retry,
|
||||
'findtime' => $this->findtime,
|
||||
'cidr_v4' => $this->cidr_v4,
|
||||
'cidr_v6' => $this->cidr_v6,
|
||||
'external_mode' => $this->external_mode,
|
||||
]);
|
||||
|
||||
// Config-Dateien schreiben
|
||||
$this->writeDefaultsConfig();
|
||||
$this->writeWhitelistConfig();
|
||||
// Config-Dateien schreiben
|
||||
$this->writeDefaultsConfig();
|
||||
$this->writeWhitelistConfig();
|
||||
|
||||
// Fail2Ban reload
|
||||
$this->runCommand('sudo -n /usr/bin/fail2ban-client reload');
|
||||
// Fail2Ban reload
|
||||
$this->runCommand('sudo -n /usr/bin/fail2ban-client reload');
|
||||
|
||||
$this->dispatch('notify', message: 'Gespeichert & Fail2Ban neu geladen.');
|
||||
$this->dispatch('toast',
|
||||
type: 'success',
|
||||
badge: 'Fail2Ban',
|
||||
title: 'Einstellungen gespeichert',
|
||||
text: 'Die Fail2Ban-Konfiguration wurde erfolgreich übernommen und ist jetzt aktiv.',
|
||||
duration: 6000,
|
||||
);
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$this->dispatch('toast',
|
||||
type: 'error',
|
||||
badge: 'Fail2Ban',
|
||||
title: 'Fehler beim Anwenden',
|
||||
text: 'Die neuen Einstellungen konnten nicht angewendet werden: ' . $e->getMessage(),
|
||||
duration: 8000,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- Config-Dateien ---------------- */
|
||||
|
||||
protected function writeDefaultsConfig(): void
|
||||
{
|
||||
$s = $this->settings;
|
||||
|
|
@ -120,7 +135,8 @@ CONF;
|
|||
|
||||
protected function writeWhitelistConfig(): void
|
||||
{
|
||||
$ips = Fail2banIpList::where('type', 'whitelist')->pluck('ip')->toArray();
|
||||
// zieht System + User-Whitelist
|
||||
$ips = Fail2banIpList::allWhitelistForConfig();
|
||||
$ignore = implode(' ', array_unique(array_filter($ips)));
|
||||
|
||||
$content = "[DEFAULT]\nignoreip = {$ignore}\n";
|
||||
|
|
@ -128,9 +144,8 @@ CONF;
|
|||
$this->writeRootFileViaTee('/etc/fail2ban/jail.d/mailwolt-whitelist.local', $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schreibt Root-Dateien sicher via `sudo tee`
|
||||
*/
|
||||
/* ---------------- Helper ---------------- */
|
||||
|
||||
private function writeRootFileViaTee(string $target, string $content): void
|
||||
{
|
||||
if (!preg_match('#^/etc/fail2ban/jail\.d/[A-Za-z0-9._-]+\.local$#', $target)) {
|
||||
|
|
@ -138,32 +153,28 @@ CONF;
|
|||
}
|
||||
|
||||
$cmd = sprintf('sudo -n /usr/bin/tee %s >/dev/null', escapeshellarg($target));
|
||||
|
||||
$descriptorspec = [
|
||||
$desc = [
|
||||
0 => ['pipe', 'r'],
|
||||
1 => ['pipe', 'w'],
|
||||
2 => ['pipe', 'w'],
|
||||
];
|
||||
|
||||
$proc = proc_open($cmd, $descriptorspec, $pipes, null, null);
|
||||
$proc = proc_open($cmd, $desc, $pipes);
|
||||
if (!is_resource($proc)) {
|
||||
throw new \RuntimeException('Failed to start tee');
|
||||
throw new \RuntimeException('tee start fehlgeschlagen');
|
||||
}
|
||||
|
||||
fwrite($pipes[0], $content);
|
||||
fclose($pipes[0]);
|
||||
stream_get_contents($pipes[1]);
|
||||
stream_get_contents($pipes[2]);
|
||||
$exitCode = proc_close($proc);
|
||||
$code = proc_close($proc);
|
||||
|
||||
if ($exitCode !== 0) {
|
||||
if ($code !== 0) {
|
||||
throw new \RuntimeException("tee failed writing to {$target}");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Führt Systembefehle aus und wirft Exception bei Fehlern
|
||||
*/
|
||||
private function runCommand(string $cmd): void
|
||||
{
|
||||
$output = [];
|
||||
|
|
@ -186,6 +197,195 @@ CONF;
|
|||
}
|
||||
}
|
||||
|
||||
//namespace App\Livewire\Ui\Security;
|
||||
//
|
||||
//use Livewire\Attributes\On;
|
||||
//use Livewire\Component;
|
||||
//use App\Models\Fail2banSetting;
|
||||
//use App\Models\Fail2banIpList;
|
||||
//
|
||||
//class Fail2banSettings extends Component
|
||||
//{
|
||||
// // Formfelder
|
||||
// public int $bantime;
|
||||
// public int $max_bantime;
|
||||
// public bool $bantime_increment;
|
||||
// public float $bantime_factor;
|
||||
// public int $max_retry;
|
||||
// public int $findtime;
|
||||
// public int $cidr_v4;
|
||||
// public int $cidr_v6;
|
||||
// public bool $external_mode;
|
||||
//
|
||||
// public array $whitelist = [];
|
||||
// public array $blacklist = [];
|
||||
//
|
||||
// public Fail2banSetting $settings;
|
||||
//
|
||||
// #[On('f2b:refresh')]
|
||||
// public function refreshLists(): void
|
||||
// {
|
||||
// $this->whitelist = Fail2banIpList::visibleWhitelist()->pluck('ip')->toArray();
|
||||
// $this->blacklist = Fail2banIpList::visibleBlacklist()->pluck('ip')->toArray();
|
||||
// }
|
||||
//
|
||||
// public function mount(): void
|
||||
// {
|
||||
// // Setting holen oder Defaults anlegen
|
||||
// $this->settings = Fail2banSetting::first() ?? Fail2banSetting::create([
|
||||
// 'bantime' => 3600,
|
||||
// 'max_bantime' => 43200,
|
||||
// 'bantime_increment' => true,
|
||||
// 'bantime_factor' => 1.5,
|
||||
// 'max_retry' => 3,
|
||||
// 'findtime' => 600,
|
||||
// 'cidr_v4' => 32,
|
||||
// 'cidr_v6' => 128,
|
||||
// 'external_mode' => false,
|
||||
// ]);
|
||||
//
|
||||
// // Properties befüllen
|
||||
// $this->fill([
|
||||
// 'bantime' => (int)$this->settings->bantime,
|
||||
// 'max_bantime' => (int)$this->settings->max_bantime,
|
||||
// 'bantime_increment' => (bool)$this->settings->bantime_increment,
|
||||
// 'bantime_factor' => (float)$this->settings->bantime_factor,
|
||||
// 'max_retry' => (int)$this->settings->max_retry,
|
||||
// 'findtime' => (int)$this->settings->findtime,
|
||||
// 'cidr_v4' => (int)$this->settings->cidr_v4,
|
||||
// 'cidr_v6' => (int)$this->settings->cidr_v6,
|
||||
// 'external_mode' => (bool)$this->settings->external_mode,
|
||||
// ]);
|
||||
//
|
||||
// $this->refreshLists();
|
||||
// }
|
||||
//
|
||||
// public function save(): void
|
||||
// {
|
||||
// $this->validate([
|
||||
// 'bantime' => 'required|integer|min:60',
|
||||
// 'max_bantime' => 'required|integer|min:60',
|
||||
// 'bantime_factor' => 'required|numeric|min:1',
|
||||
// 'max_retry' => 'required|integer|min:1',
|
||||
// 'findtime' => 'required|integer|min:60',
|
||||
// 'cidr_v4' => 'required|integer|min:8|max:32',
|
||||
// 'cidr_v6' => 'required|integer|min:8|max:128',
|
||||
// ]);
|
||||
//
|
||||
// // Einstellungen speichern
|
||||
// $this->settings->update([
|
||||
// 'bantime' => $this->bantime,
|
||||
// 'max_bantime' => $this->max_bantime,
|
||||
// 'bantime_increment' => $this->bantime_increment,
|
||||
// 'bantime_factor' => $this->bantime_factor,
|
||||
// 'max_retry' => $this->max_retry,
|
||||
// 'findtime' => $this->findtime,
|
||||
// 'cidr_v4' => $this->cidr_v4,
|
||||
// 'cidr_v6' => $this->cidr_v6,
|
||||
// 'external_mode' => $this->external_mode,
|
||||
// ]);
|
||||
//
|
||||
// // Config-Dateien schreiben
|
||||
// $this->writeDefaultsConfig();
|
||||
// $this->writeWhitelistConfig();
|
||||
//
|
||||
// // Fail2Ban reload
|
||||
// $this->runCommand('sudo -n /usr/bin/fail2ban-client reload');
|
||||
//
|
||||
// $this->dispatch('toast',
|
||||
// type: 'done',
|
||||
// badge: 'Fail2Ban',
|
||||
// title: 'Einstellungen gespeichert',
|
||||
// text: 'Die Fail2Ban-Konfiguration wurde erfolgreich übernommen und ist jetzt aktiv.',
|
||||
// duration: 6000,
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// protected function writeDefaultsConfig(): void
|
||||
// {
|
||||
// $s = $this->settings;
|
||||
//
|
||||
// $content = <<<CONF
|
||||
//[DEFAULT]
|
||||
//bantime = {$s->bantime}
|
||||
//findtime = {$s->findtime}
|
||||
//maxretry = {$s->max_retry}
|
||||
//bantime.increment = {$this->boolToStr($s->bantime_increment)}
|
||||
//bantime.factor = {$s->bantime_factor}
|
||||
//bantime.maxtime = {$s->max_bantime}
|
||||
//CONF;
|
||||
//
|
||||
// $this->writeRootFileViaTee('/etc/fail2ban/jail.d/00-mailwolt-defaults.local', $content);
|
||||
// }
|
||||
//
|
||||
// protected function writeWhitelistConfig(): void
|
||||
// {
|
||||
// $ips = Fail2banIpList::where('type', 'whitelist')->pluck('ip')->toArray();
|
||||
// $ignore = implode(' ', array_unique(array_filter($ips)));
|
||||
//
|
||||
// $content = "[DEFAULT]\nignoreip = {$ignore}\n";
|
||||
//
|
||||
// $this->writeRootFileViaTee('/etc/fail2ban/jail.d/mailwolt-whitelist.local', $content);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Schreibt Root-Dateien sicher via `sudo tee`
|
||||
// */
|
||||
// private function writeRootFileViaTee(string $target, string $content): void
|
||||
// {
|
||||
// if (!preg_match('#^/etc/fail2ban/jail\.d/[A-Za-z0-9._-]+\.local$#', $target)) {
|
||||
// throw new \RuntimeException("Illegal path: $target");
|
||||
// }
|
||||
//
|
||||
// $cmd = sprintf('sudo -n /usr/bin/tee %s >/dev/null', escapeshellarg($target));
|
||||
//
|
||||
// $descriptorspec = [
|
||||
// 0 => ['pipe', 'r'],
|
||||
// 1 => ['pipe', 'w'],
|
||||
// 2 => ['pipe', 'w'],
|
||||
// ];
|
||||
//
|
||||
// $proc = proc_open($cmd, $descriptorspec, $pipes, null, null);
|
||||
// if (!is_resource($proc)) {
|
||||
// throw new \RuntimeException('Failed to start tee');
|
||||
// }
|
||||
//
|
||||
// fwrite($pipes[0], $content);
|
||||
// fclose($pipes[0]);
|
||||
// stream_get_contents($pipes[1]);
|
||||
// stream_get_contents($pipes[2]);
|
||||
// $exitCode = proc_close($proc);
|
||||
//
|
||||
// if ($exitCode !== 0) {
|
||||
// throw new \RuntimeException("tee failed writing to {$target}");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Führt Systembefehle aus und wirft Exception bei Fehlern
|
||||
// */
|
||||
// private function runCommand(string $cmd): void
|
||||
// {
|
||||
// $output = [];
|
||||
// $return = 0;
|
||||
// exec($cmd . ' 2>&1', $output, $return);
|
||||
//
|
||||
// if ($return !== 0) {
|
||||
// throw new \RuntimeException("Command failed ($return): {$cmd}\n" . implode("\n", $output));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private function boolToStr(bool $v): string
|
||||
// {
|
||||
// return $v ? 'true' : 'false';
|
||||
// }
|
||||
//
|
||||
// public function render()
|
||||
// {
|
||||
// return view('livewire.ui.security.fail2ban-settings');
|
||||
// }
|
||||
//}
|
||||
|
||||
//
|
||||
//namespace App\Livewire\Ui\Security;
|
||||
//
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class Fail2banIpModal extends ModalComponent
|
|||
throw ValidationException::withMessages(['ip' => 'Loopback/localhost ist bereits systemseitig erlaubt und kann nicht geändert werden.']);
|
||||
}
|
||||
|
||||
// Duplikate abfangen (es gibt einen Unique-Index ip+type; trotzdem user-freundlich)
|
||||
// Duplikate abfangen
|
||||
$exists = Fail2banIpList::where('ip', $ip)->where('type', $this->type)->exists();
|
||||
if ($exists) {
|
||||
throw ValidationException::withMessages(['ip' => ucfirst($this->type) . ' enthält diese IP bereits.']);
|
||||
|
|
@ -75,17 +75,36 @@ class Fail2banIpModal extends ModalComponent
|
|||
Fail2banIpList::create(['ip' => $ip, 'type' => $this->type]);
|
||||
|
||||
if ($this->type === 'whitelist') {
|
||||
$this->writeWhitelistConfig(); // schreibt /etc/fail2ban/jail.d/mailwolt-whitelist.local
|
||||
$this->reloadFail2ban(); // f2b neu laden
|
||||
// Whitelist-Datei aktualisieren + Fail2Ban reload
|
||||
$this->writeWhitelistConfig();
|
||||
$this->reloadFail2ban();
|
||||
|
||||
// UI aktualisieren & Toast
|
||||
$this->dispatch('f2b:refresh');
|
||||
$this->dispatch('toast',
|
||||
type: 'success',
|
||||
badge: 'Fail2Ban',
|
||||
title: 'Whitelist aktualisiert',
|
||||
text: 'Die IP wurde erfolgreich zur Whitelist hinzugefügt und ist nun freigegeben.',
|
||||
duration: 6000,
|
||||
);
|
||||
} else {
|
||||
// Blacklist = sofort bannen im dedizierten Jail
|
||||
// Blacklist = sofort bannen
|
||||
$this->banIp($ip);
|
||||
|
||||
// UI aktualisieren & Toast
|
||||
$this->dispatch('f2b:refresh');
|
||||
$this->dispatch('toast',
|
||||
type: 'warning',
|
||||
badge: 'Fail2Ban',
|
||||
title: 'Blacklist aktualisiert',
|
||||
text: 'Die IP wurde zur Blacklist hinzugefügt und umgehend blockiert.',
|
||||
duration: 6000,
|
||||
);
|
||||
}
|
||||
|
||||
$this->dispatch('f2b:refresh');
|
||||
$this->dispatch('notify', message: ucfirst($this->type) . ' aktualisiert.');
|
||||
// Modal bewusst am Ende schließen (Toast bleibt sichtbar)
|
||||
$this->closeModal();
|
||||
$this->dispatch('f2b:refresh');
|
||||
}
|
||||
|
||||
public function remove(): void
|
||||
|
|
@ -105,14 +124,29 @@ class Fail2banIpModal extends ModalComponent
|
|||
if ($this->type === 'whitelist') {
|
||||
$this->writeWhitelistConfig();
|
||||
$this->reloadFail2ban();
|
||||
|
||||
$this->dispatch('f2b:refresh');
|
||||
$this->dispatch('toast',
|
||||
type: 'info',
|
||||
badge: 'Fail2Ban',
|
||||
title: 'Whitelist geändert',
|
||||
text: 'Die IP wurde aus der Whitelist entfernt.',
|
||||
duration: 6000,
|
||||
);
|
||||
} else {
|
||||
$this->unbanIp($ip);
|
||||
|
||||
$this->dispatch('f2b:refresh');
|
||||
$this->dispatch('toast',
|
||||
type: 'info',
|
||||
badge: 'Fail2Ban',
|
||||
title: 'Blacklist geändert',
|
||||
text: 'Die IP wurde aus der Blacklist entfernt und ist wieder freigegeben.',
|
||||
duration: 6000,
|
||||
);
|
||||
}
|
||||
|
||||
$this->dispatch('f2b:refresh');
|
||||
$this->dispatch('notify', message: ucfirst($this->type) . ' Eintrag entfernt.');
|
||||
$this->closeModal();
|
||||
$this->dispatch('f2b:refresh');
|
||||
}
|
||||
|
||||
/* ---------------- helper ---------------- */
|
||||
|
|
@ -129,12 +163,11 @@ class Fail2banIpModal extends ModalComponent
|
|||
|
||||
private function writeWhitelistConfig(): void
|
||||
{
|
||||
// WICHTIG: inkl. System-IPs
|
||||
// WICHTIG: inkl. System-IPs (unsichtbar in der UI)
|
||||
$ips = Fail2banIpList::allWhitelistForConfig();
|
||||
$ignore = implode(' ', array_unique(array_filter($ips)));
|
||||
$content = "[DEFAULT]\nignoreip = {$ignore}\n";
|
||||
|
||||
// sicher in Root-Pfad schreiben (sudo tee)
|
||||
$this->writeRootFileViaTee('/etc/fail2ban/jail.d/mailwolt-whitelist.local', $content);
|
||||
}
|
||||
|
||||
|
|
@ -154,12 +187,14 @@ class Fail2banIpModal extends ModalComponent
|
|||
if (!is_resource($proc)) {
|
||||
throw new \RuntimeException('tee start fehlgeschlagen');
|
||||
}
|
||||
|
||||
fwrite($pipes[0], $content);
|
||||
fclose($pipes[0]);
|
||||
$stdout = stream_get_contents($pipes[1]);
|
||||
fclose($pipes[1]);
|
||||
$stderr = stream_get_contents($pipes[2]);
|
||||
fclose($pipes[2]);
|
||||
|
||||
$code = proc_close($proc);
|
||||
if ($code !== 0) {
|
||||
throw new \RuntimeException("tee failed (code $code): $stderr $stdout");
|
||||
|
|
@ -183,6 +218,194 @@ class Fail2banIpModal extends ModalComponent
|
|||
@shell_exec("sudo -n /usr/bin/fail2ban-client set mailwolt-blacklist unbanip {$ipEsc} 2>&1");
|
||||
}
|
||||
}
|
||||
|
||||
//namespace App\Livewire\Ui\Security\Modal;
|
||||
//
|
||||
//use LivewireUI\Modal\ModalComponent;
|
||||
//use App\Models\Fail2banIpList;
|
||||
//use Illuminate\Validation\ValidationException;
|
||||
//
|
||||
//class Fail2banIpModal extends ModalComponent
|
||||
//{
|
||||
// /** 'whitelist' | 'blacklist' */
|
||||
// public string $type = 'whitelist';
|
||||
//
|
||||
// /** 'add' | 'remove' */
|
||||
// public string $mode = 'add';
|
||||
//
|
||||
// /** IP/CIDR im Formular */
|
||||
// public string $ip = '';
|
||||
//
|
||||
// /** Für "remove" vorbefüllt */
|
||||
// public ?string $prefill = null;
|
||||
//
|
||||
// public static function modalMaxWidth(): string
|
||||
// {
|
||||
// return 'lg';
|
||||
// }
|
||||
//
|
||||
// public function mount(string $type = 'whitelist', string $mode = 'add', ?string $ip = null): void
|
||||
// {
|
||||
// $type = strtolower($type);
|
||||
// $mode = strtolower($mode);
|
||||
//
|
||||
// if (!in_array($type, ['whitelist', 'blacklist'], true)) {
|
||||
// throw new \InvalidArgumentException('Invalid type');
|
||||
// }
|
||||
// if (!in_array($mode, ['add', 'remove'], true)) {
|
||||
// throw new \InvalidArgumentException('Invalid mode');
|
||||
// }
|
||||
//
|
||||
// $this->type = $type;
|
||||
// $this->mode = $mode;
|
||||
// $this->ip = $ip ?? '';
|
||||
// $this->prefill = $ip;
|
||||
// }
|
||||
//
|
||||
// public function render()
|
||||
// {
|
||||
// return view('livewire.ui.security.modal.fail2ban-ip-modal');
|
||||
// }
|
||||
//
|
||||
// /* ---------------- actions ---------------- */
|
||||
//
|
||||
// public function save(): void
|
||||
// {
|
||||
// $this->assertAddMode();
|
||||
// $ip = trim($this->ip);
|
||||
//
|
||||
// if (!Fail2banIpList::isValidIpOrCidr($ip)) {
|
||||
// throw ValidationException::withMessages(['ip' => 'Ungültige IP oder CIDR.']);
|
||||
// }
|
||||
//
|
||||
// // Schutz: System-/Loopback-IPs darf der User nicht manuell pflegen
|
||||
// if (Fail2banIpList::isLoopback($ip)) {
|
||||
// throw ValidationException::withMessages(['ip' => 'Loopback/localhost ist bereits systemseitig erlaubt und kann nicht geändert werden.']);
|
||||
// }
|
||||
//
|
||||
// // Duplikate abfangen (es gibt einen Unique-Index ip+type; trotzdem user-freundlich)
|
||||
// $exists = Fail2banIpList::where('ip', $ip)->where('type', $this->type)->exists();
|
||||
// if ($exists) {
|
||||
// throw ValidationException::withMessages(['ip' => ucfirst($this->type) . ' enthält diese IP bereits.']);
|
||||
// }
|
||||
//
|
||||
// // DB schreiben
|
||||
// Fail2banIpList::create(['ip' => $ip, 'type' => $this->type]);
|
||||
//
|
||||
// if ($this->type === 'whitelist') {
|
||||
// $this->writeWhitelistConfig(); // schreibt /etc/fail2ban/jail.d/mailwolt-whitelist.local
|
||||
// $this->reloadFail2ban(); // f2b neu laden
|
||||
// } else {
|
||||
// // Blacklist = sofort bannen im dedizierten Jail
|
||||
// $this->banIp($ip);
|
||||
// }
|
||||
//
|
||||
// $this->closeModal();
|
||||
// $this->dispatch('f2b:refresh');
|
||||
// }
|
||||
//
|
||||
// public function remove(): void
|
||||
// {
|
||||
// $this->assertRemoveMode();
|
||||
// $ip = trim($this->prefill ?? $this->ip);
|
||||
// if ($ip === '') return;
|
||||
//
|
||||
// // System-Whitelist darf nicht entfernt werden
|
||||
// $row = Fail2banIpList::where('type', $this->type)->where('ip', $ip)->first();
|
||||
// if ($row && $row->is_system) {
|
||||
// throw ValidationException::withMessages(['ip' => 'Systemeintrag kann nicht entfernt werden.']);
|
||||
// }
|
||||
//
|
||||
// Fail2banIpList::where('type', $this->type)->where('ip', $ip)->delete();
|
||||
//
|
||||
// if ($this->type === 'whitelist') {
|
||||
// $this->writeWhitelistConfig();
|
||||
// $this->reloadFail2ban();
|
||||
// } else {
|
||||
// $this->unbanIp($ip);
|
||||
// }
|
||||
//
|
||||
// $this->closeModal();
|
||||
// $this->dispatch('f2b:refresh');
|
||||
// $this->dispatch('toast',
|
||||
// type: 'done',
|
||||
// badge: 'Fail2Ban',
|
||||
// title: 'Einstellungen gespeichert',
|
||||
// text: 'Die Fail2Ban-Konfiguration wurde erfolgreich übernommen und ist jetzt aktiv.',
|
||||
// duration: 6000,
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// /* ---------------- helper ---------------- */
|
||||
//
|
||||
// private function assertAddMode(): void
|
||||
// {
|
||||
// if ($this->mode !== 'add') throw new \LogicException('Wrong mode');
|
||||
// }
|
||||
//
|
||||
// private function assertRemoveMode(): void
|
||||
// {
|
||||
// if ($this->mode !== 'remove') throw new \LogicException('Wrong mode');
|
||||
// }
|
||||
//
|
||||
// private function writeWhitelistConfig(): void
|
||||
// {
|
||||
// // WICHTIG: inkl. System-IPs
|
||||
// $ips = Fail2banIpList::allWhitelistForConfig();
|
||||
// $ignore = implode(' ', array_unique(array_filter($ips)));
|
||||
// $content = "[DEFAULT]\nignoreip = {$ignore}\n";
|
||||
//
|
||||
// // sicher in Root-Pfad schreiben (sudo tee)
|
||||
// $this->writeRootFileViaTee('/etc/fail2ban/jail.d/mailwolt-whitelist.local', $content);
|
||||
// }
|
||||
//
|
||||
// private function writeRootFileViaTee(string $target, string $content): void
|
||||
// {
|
||||
// if (!preg_match('#^/etc/fail2ban/jail\.d/[A-Za-z0-9._-]+\.local$#', $target)) {
|
||||
// throw new \RuntimeException("Illegal path: $target");
|
||||
// }
|
||||
//
|
||||
// $cmd = sprintf('sudo -n /usr/bin/tee %s >/dev/null', escapeshellarg($target));
|
||||
// $desc = [
|
||||
// 0 => ['pipe', 'r'],
|
||||
// 1 => ['pipe', 'w'],
|
||||
// 2 => ['pipe', 'w'],
|
||||
// ];
|
||||
// $proc = proc_open($cmd, $desc, $pipes);
|
||||
// if (!is_resource($proc)) {
|
||||
// throw new \RuntimeException('tee start fehlgeschlagen');
|
||||
// }
|
||||
// fwrite($pipes[0], $content);
|
||||
// fclose($pipes[0]);
|
||||
// $stdout = stream_get_contents($pipes[1]);
|
||||
// fclose($pipes[1]);
|
||||
// $stderr = stream_get_contents($pipes[2]);
|
||||
// fclose($pipes[2]);
|
||||
// $code = proc_close($proc);
|
||||
// if ($code !== 0) {
|
||||
// throw new \RuntimeException("tee failed (code $code): $stderr $stdout");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private function reloadFail2ban(): void
|
||||
// {
|
||||
// @shell_exec('sudo -n /usr/bin/fail2ban-client reload 2>&1');
|
||||
// }
|
||||
//
|
||||
// private function banIp(string $ip): void
|
||||
// {
|
||||
// $ipEsc = escapeshellarg($ip);
|
||||
// @shell_exec("sudo -n /usr/bin/fail2ban-client set mailwolt-blacklist banip {$ipEsc} 2>&1");
|
||||
// }
|
||||
//
|
||||
// private function unbanIp(string $ip): void
|
||||
// {
|
||||
// $ipEsc = escapeshellarg($ip);
|
||||
// @shell_exec("sudo -n /usr/bin/fail2ban-client set mailwolt-blacklist unbanip {$ipEsc} 2>&1");
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//
|
||||
//namespace App\Livewire\Ui\Security\Modal;
|
||||
//
|
||||
|
|
|
|||
Loading…
Reference in New Issue