diff --git a/app/Livewire/Ui/Security/RblCard.php b/app/Livewire/Ui/Security/RblCard.php index c04d3d5..ca79921 100644 --- a/app/Livewire/Ui/Security/RblCard.php +++ b/app/Livewire/Ui/Security/RblCard.php @@ -1,10 +1,10 @@ load(); @@ -33,33 +36,21 @@ class RblCard extends Component protected function load(bool $force = false): void { - // 1) IPv4/IPv6 bevorzugt aus /etc/mailwolt/installer.env [$ip4, $ip6] = $this->resolvePublicIpsFromInstallerEnv(); - // 2) Fallback auf .env - $this->ipv4 = $ip4 ?: trim((string) env('SERVER_PUBLIC_IPV4', '')) ?: '–'; - $this->ipv6 = $ip6 ?: trim((string) env('SERVER_PUBLIC_IPV6', '')) ?: '–'; + $this->ipv4 = $ip4 ?: trim((string)env('SERVER_PUBLIC_IPV4', '')) ?: '–'; + $this->ipv6 = $ip6 ?: trim((string)env('SERVER_PUBLIC_IPV6', '')) ?: '–'; - // 3) RBL-Ermittlung (cached) - $data = Cache::remember('dash.rbl', $force ? 1 : 21600, function () { - // bevorzugt eine valide IPv4 für den RBL-Check + $data = Cache::remember('dash.rbl', $force ? 1 : 6 * 3600, function () { $candidate = $this->validIPv4($this->ipv4 ?? '') ? $this->ipv4 : null; if (!$candidate) { - $fromFile = @file_get_contents('/etc/mailwolt/public_ip') ?: ''; - $fromFile = trim($fromFile); - if ($this->validIPv4($fromFile)) { - $candidate = $fromFile; - } + $fromFile = trim((string)@file_get_contents('/etc/mailwolt/public_ip')); + if ($this->validIPv4($fromFile)) $candidate = $fromFile; } - if (!$candidate) { - // letzter Fallback – kann auf Hardened-Systemen geblockt sein - $curl = @shell_exec("curl -fsS --max-time 2 ifconfig.me 2>/dev/null") ?: ''; - $curl = trim($curl); - if ($this->validIPv4($curl)) { - $candidate = $curl; - } + $curl = trim((string)@shell_exec("curl -fsS --max-time 2 ifconfig.me 2>/dev/null")); + if ($this->validIPv4($curl)) $candidate = $curl; } $ip = $candidate ?: '0.0.0.0'; @@ -68,82 +59,76 @@ class RblCard extends Component return ['ip' => $ip, 'hits' => count($lists), 'lists' => $lists]; }); - // 4) Werte ins Component-State - foreach ($data as $k => $v) { - $this->$k = $v; - } + foreach ($data as $k => $v) $this->$k = $v; } - /** Bevorzugt Installer-ENV; gibt [ipv4, ipv6] zurück oder [null, null]. */ + /** bevorzugt Installer-ENV */ private function resolvePublicIpsFromInstallerEnv(): array { $file = '/etc/mailwolt/installer.env'; - if (!is_readable($file)) { - return [null, null]; - } - - $ipv4 = null; - $ipv6 = null; + if (!is_readable($file)) return [null, null]; + $ipv4 = $ipv6 = null; $lines = @file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: []; foreach ($lines as $line) { - // Kommentare überspringen - if (preg_match('/^\s*#/', $line)) { - continue; - } - // KEY=VALUE (VALUE evtl. in "..." oder '...') - if (!str_contains($line, '=')) { - continue; - } + if (preg_match('/^\s*#/', $line) || !str_contains($line, '=')) continue; [$k, $v] = array_map('trim', explode('=', $line, 2)); $v = trim($v, " \t\n\r\0\x0B\"'"); - - if ($k === 'SERVER_PUBLIC_IPV4' && $this->validIPv4($v)) { - $ipv4 = $v; - } elseif ($k === 'SERVER_PUBLIC_IPV6' && $this->validIPv6($v)) { - $ipv6 = $v; - } + if ($k === 'SERVER_PUBLIC_IPV4' && $this->validIPv4($v)) $ipv4 = $v; + if ($k === 'SERVER_PUBLIC_IPV6' && $this->validIPv6($v)) $ipv6 = $v; } - return [$ipv4, $ipv6]; } private function validIPv4(?string $ip): bool { - return (bool) filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); + return (bool)filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); } private function validIPv6(?string $ip): bool { - return (bool) filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); + return (bool)filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); } /** - * Prüft die IP gegen ein paar gängige RBLs. - * Nutzt PHP-DNS (checkdnsrr), keine externen Tools. - * + * Prüft die IP gegen gängige **öffentliche** RBLs. * @return array gelistete RBL-Zonen */ private function queryRblLists(string $ip): array { - // Nur IPv4 prüfen (die meisten Listen hier sind v4) - if (!$this->validIPv4($ip)) { - return []; - } + if (!$this->validIPv4($ip)) return []; $rev = implode('.', array_reverse(explode('.', $ip))); - $sources = [ - 'zen.spamhaus.org', - 'bl.spamcop.net', - 'dnsbl.sorbs.net', - 'b.barracudacentral.org', + + // Öffentliche/abfragbare Zonen (keine Registrierung nötig) + $publicZones = [ + 'zen.spamhaus.org', // seriös, rate-limited + 'psbl.surriel.com', // public + 'dnsbl-1.uceprotect.net', // public (umstritten, aber abfragbar) + 'all.s5h.net', // public ]; + // Registrierungspflichtige – nur optional prüfen + $registeredZones = [ + 'b.barracudacentral.org', // benötigt Account + // weitere bei Bedarf + ]; + + $zones = $publicZones; + if ($this->includeRegistered) { + $zones = array_merge($zones, $registeredZones); + } + + // Vorab: Zone existiert? (NS-Record) – sonst überspringen + $zones = array_values(array_filter($zones, function ($z) { + return @checkdnsrr($z . '.', 'NS'); + })); + $listed = []; - foreach ($sources as $zone) { - $qname = "{$rev}.{$zone}"; - // A-Record oder TXT deuten auf Listing hin - if (@checkdnsrr($qname . '.', 'A') || @checkdnsrr($qname . '.', 'TXT')) { + foreach ($zones as $zone) { + $qname = "{$rev}.{$zone}."; + // Wenn A oder TXT existiert → gelistet + if (@checkdnsrr($qname, 'A') || @checkdnsrr($qname, 'TXT')) { $listed[] = $zone; } } @@ -151,6 +136,158 @@ class RblCard extends Component return $listed; } } +//declare(strict_types=1); +// +//namespace App\Livewire\Ui\Security; +// +//use Livewire\Component; +//use Illuminate\Support\Facades\Cache; +// +//class RblCard extends Component +//{ +// public string $ip = '–'; +// public int $hits = 0; +// public array $lists = []; +// +// public ?string $ipv4 = null; +// public ?string $ipv6 = null; +// +// public function mount(): void +// { +// $this->load(); +// } +// +// public function render() +// { +// return view('livewire.ui.security.rbl-card'); +// } +// +// public function refresh(): void +// { +// Cache::forget('dash.rbl'); +// $this->load(true); +// } +// +// protected function load(bool $force = false): void +// { +// // 1) IPv4/IPv6 bevorzugt aus /etc/mailwolt/installer.env +// [$ip4, $ip6] = $this->resolvePublicIpsFromInstallerEnv(); +// +// // 2) Fallback auf .env +// $this->ipv4 = $ip4 ?: trim((string) env('SERVER_PUBLIC_IPV4', '')) ?: '–'; +// $this->ipv6 = $ip6 ?: trim((string) env('SERVER_PUBLIC_IPV6', '')) ?: '–'; +// +// // 3) RBL-Ermittlung (cached) +// $data = Cache::remember('dash.rbl', $force ? 1 : 21600, function () { +// // bevorzugt eine valide IPv4 für den RBL-Check +// $candidate = $this->validIPv4($this->ipv4 ?? '') ? $this->ipv4 : null; +// +// if (!$candidate) { +// $fromFile = @file_get_contents('/etc/mailwolt/public_ip') ?: ''; +// $fromFile = trim($fromFile); +// if ($this->validIPv4($fromFile)) { +// $candidate = $fromFile; +// } +// } +// +// if (!$candidate) { +// // letzter Fallback – kann auf Hardened-Systemen geblockt sein +// $curl = @shell_exec("curl -fsS --max-time 2 ifconfig.me 2>/dev/null") ?: ''; +// $curl = trim($curl); +// if ($this->validIPv4($curl)) { +// $candidate = $curl; +// } +// } +// +// $ip = $candidate ?: '0.0.0.0'; +// $lists = $this->queryRblLists($ip); +// +// return ['ip' => $ip, 'hits' => count($lists), 'lists' => $lists]; +// }); +// +// // 4) Werte ins Component-State +// foreach ($data as $k => $v) { +// $this->$k = $v; +// } +// } +// +// /** Bevorzugt Installer-ENV; gibt [ipv4, ipv6] zurück oder [null, null]. */ +// private function resolvePublicIpsFromInstallerEnv(): array +// { +// $file = '/etc/mailwolt/installer.env'; +// if (!is_readable($file)) { +// return [null, null]; +// } +// +// $ipv4 = null; +// $ipv6 = null; +// +// $lines = @file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) ?: []; +// foreach ($lines as $line) { +// // Kommentare überspringen +// if (preg_match('/^\s*#/', $line)) { +// continue; +// } +// // KEY=VALUE (VALUE evtl. in "..." oder '...') +// if (!str_contains($line, '=')) { +// continue; +// } +// [$k, $v] = array_map('trim', explode('=', $line, 2)); +// $v = trim($v, " \t\n\r\0\x0B\"'"); +// +// if ($k === 'SERVER_PUBLIC_IPV4' && $this->validIPv4($v)) { +// $ipv4 = $v; +// } elseif ($k === 'SERVER_PUBLIC_IPV6' && $this->validIPv6($v)) { +// $ipv6 = $v; +// } +// } +// +// return [$ipv4, $ipv6]; +// } +// +// private function validIPv4(?string $ip): bool +// { +// return (bool) filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); +// } +// +// private function validIPv6(?string $ip): bool +// { +// return (bool) filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); +// } +// +// /** +// * Prüft die IP gegen ein paar gängige RBLs. +// * Nutzt PHP-DNS (checkdnsrr), keine externen Tools. +// * +// * @return array gelistete RBL-Zonen +// */ +// private function queryRblLists(string $ip): array +// { +// // Nur IPv4 prüfen (die meisten Listen hier sind v4) +// if (!$this->validIPv4($ip)) { +// return []; +// } +// +// $rev = implode('.', array_reverse(explode('.', $ip))); +// $sources = [ +// 'zen.spamhaus.org', +// 'bl.spamcop.net', +// 'dnsbl.sorbs.net', +// 'b.barracudacentral.org', +// ]; +// +// $listed = []; +// foreach ($sources as $zone) { +// $qname = "{$rev}.{$zone}"; +// // A-Record oder TXT deuten auf Listing hin +// if (@checkdnsrr($qname . '.', 'A') || @checkdnsrr($qname . '.', 'TXT')) { +// $listed[] = $zone; +// } +// } +// +// return $listed; +// } +//} // //namespace App\Livewire\Ui\Security; // diff --git a/resources/views/livewire/ui/security/rbl-card.blade.php b/resources/views/livewire/ui/security/rbl-card.blade.php index c44b94b..e9aabef 100644 --- a/resources/views/livewire/ui/security/rbl-card.blade.php +++ b/resources/views/livewire/ui/security/rbl-card.blade.php @@ -4,17 +4,64 @@ Reputation / RBL -
IP: {{ $ip }}
+ +
+ IP: {{ $ip }} +
@if($hits === 0) - Keine Treffer +
+ + Deine IP ist aktuell auf keiner der geprüften Blacklists. +
+
+ Geprüfte öffentliche RBLs: Spamhaus, PSBL, UCEPROTECT-1, s5h. +
@else -
{{ $hits }} Treffer:
+
+ + {{ $hits }} Treffer auf Blacklists: +
    - @foreach($lists as $l)
  • • {{ $l }}
  • @endforeach + @foreach($lists as $l) +
  • + + {{ $l }} +
  • + @endforeach
@endif
+ +
+ +
+{{--
--}} +{{--
--}} +{{--
--}} +{{-- --}} +{{-- Reputation / RBL--}} +{{--
--}} +{{--
IP: {{ $ip }}
--}} +{{--
--}} + +{{--
--}} +{{-- @if($hits === 0)--}} +{{-- Keine Treffer--}} +{{-- @else--}} +{{--
{{ $hits }} Treffer:
--}} +{{--
    --}} +{{-- @foreach($lists as $l)
  • • {{ $l }}
  • @endforeach--}} +{{--
--}} +{{-- @endif--}} +{{--
--}} +{{--
--}}