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, '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('notify', message: 'Gespeichert & Fail2Ban neu geladen.'); } protected function writeDefaultsConfig(): void { $s = $this->settings; $content = <<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; // //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::where('type', 'whitelist')->pluck('ip')->toArray(); // $this->blacklist = Fail2banIpList::where('type', 'blacklist')->pluck('ip')->toArray(); // } // // public function mount(): void // { // // Setting holen oder mit 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 füllen (KEINE Mixed-Objekte in Inputs binden) // $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->whitelist = Fail2banIpList::where('type','whitelist')->pluck('ip')->toArray(); // $this->blacklist = Fail2banIpList::where('type','blacklist')->pluck('ip')->toArray(); // } // // 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', // ]); // // $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, // ]); // // $this->writeDefaultsConfig(); // $this->writeWhitelistConfig(); // // @shell_exec('sudo fail2ban-client reload'); // $this->dispatch('notify', message: 'Gespeichert & Fail2Ban neu geladen.'); // } // // protected function writeDefaultsConfig(): void // { // $s = $this->settings; // $content = <<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; // file_put_contents('/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"; // file_put_contents('/etc/fail2ban/jail.d/mailwolt-whitelist.local', $content); // } // // private function writeRootFileViaTee(string $target, string $content): void // { // // Nur erlaubte Pfade (Hardening) // 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'], // stdin -> tee // 1 => ['pipe', 'w'], // stdout // 2 => ['pipe', 'w'], // stderr // ]; // // $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]); // $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 boolToStr(bool $v): string // { // return $v ? 'true' : 'false'; // } // // public function render() // { // return view('livewire.ui.security.fail2ban-settings'); // } //}