392 lines
13 KiB
PHP
392 lines
13 KiB
PHP
<?php
|
||
// App\Livewire\Ui\Security\RblCard.php
|
||
namespace App\Livewire\Ui\Security;
|
||
|
||
use Livewire\Component;
|
||
use Illuminate\Support\Facades\Cache;
|
||
use Illuminate\Support\Facades\Artisan;
|
||
use App\Models\Setting;
|
||
|
||
class RblCard extends Component
|
||
{
|
||
public string $ip = '–';
|
||
public ?string $ipv4 = null;
|
||
public ?string $ipv6 = null;
|
||
|
||
public int $hits = 0;
|
||
public array $lists = []; // nur gelistete Zonen
|
||
public array $meta = []; // status je Zone
|
||
public ?string $checkedAt = null;
|
||
public ?string $validUntil = null;
|
||
|
||
public function mount(): void { $this->load(); }
|
||
public function render() { return view('livewire.ui.security.rbl-card'); }
|
||
|
||
public function refresh(): void
|
||
{
|
||
// Manuelles Re-Check via Command (asynchron, damit UI nicht blockiert)
|
||
@shell_exec('nohup php /var/www/mailwolt/artisan rbl:probe --force >/dev/null 2>&1 &');
|
||
// Sofortige UI-Aktualisierung aus Settings (altes Ergebnis) …
|
||
$this->load(true);
|
||
// … und kurzer Hinweis
|
||
$this->dispatch('toast', type:'info', title:'RBL-Prüfung gestartet', text:'Ergebnis wird aktualisiert, sobald verfügbar.', duration:2500);
|
||
}
|
||
|
||
protected function load(bool $force = false): void
|
||
{
|
||
$payload = $force
|
||
? (array) Setting::get('health.rbl', []) // direkt aus DB
|
||
: (array) (Cache::get('health.rbl') ?: Setting::get('health.rbl', []));
|
||
|
||
$this->ip = (string)($payload['ip'] ?? '–');
|
||
$this->ipv4 = $payload['ipv4'] ?? null;
|
||
$this->ipv6 = $payload['ipv6'] ?? null;
|
||
$this->hits = (int)($payload['hits'] ?? 0);
|
||
$this->lists = (array)($payload['lists'] ?? []);
|
||
$this->meta = (array)($payload['meta'] ?? []);
|
||
$this->checkedAt = $payload['checked_at'] ?? null;
|
||
$this->validUntil = $payload['valid_until'] ?? null;
|
||
}
|
||
}
|
||
|
||
//namespace App\Livewire\Ui\Security;
|
||
//
|
||
//use Illuminate\Support\Facades\Cache;
|
||
//use Livewire\Component;
|
||
//
|
||
//class RblCard extends Component
|
||
//{
|
||
// public string $ip = '–';
|
||
// public int $hits = 0;
|
||
// public array $lists = [];
|
||
//
|
||
// public ?string $ipv4 = null;
|
||
// public ?string $ipv6 = null;
|
||
//
|
||
// // Schalte registrierungspflichtige Listen (Barracuda etc.) optional zu
|
||
// private bool $includeRegistered = false; // env('RBL_INCLUDE_REGISTERED', false) wenn du willst
|
||
//
|
||
// 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
|
||
// {
|
||
// [$ip4, $ip6] = $this->resolvePublicIpsFromInstallerEnv();
|
||
//
|
||
// $this->ipv4 = $ip4 ?: trim((string)env('SERVER_PUBLIC_IPV4', '')) ?: '–';
|
||
// $this->ipv6 = $ip6 ?: trim((string)env('SERVER_PUBLIC_IPV6', '')) ?: '–';
|
||
//
|
||
// $data = Cache::remember('dash.rbl', $force ? 1 : 6 * 3600, function () {
|
||
// $candidate = $this->validIPv4($this->ipv4 ?? '') ? $this->ipv4 : null;
|
||
//
|
||
// if (!$candidate) {
|
||
// $fromFile = trim((string)@file_get_contents('/etc/mailwolt/public_ip'));
|
||
// if ($this->validIPv4($fromFile)) $candidate = $fromFile;
|
||
// }
|
||
// if (!$candidate) {
|
||
// $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';
|
||
// $lists = $this->queryRblLists($ip);
|
||
//
|
||
// return ['ip' => $ip, 'hits' => count($lists), 'lists' => $lists];
|
||
// });
|
||
//
|
||
// foreach ($data as $k => $v) $this->$k = $v;
|
||
// }
|
||
//
|
||
// /** bevorzugt Installer-ENV */
|
||
// private function resolvePublicIpsFromInstallerEnv(): array
|
||
// {
|
||
// $file = '/etc/mailwolt/installer.env';
|
||
// 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) {
|
||
// 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;
|
||
// 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);
|
||
// }
|
||
//
|
||
// private function validIPv6(?string $ip): bool
|
||
// {
|
||
// return (bool)filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
|
||
// }
|
||
//
|
||
// /**
|
||
// * Prüft die IP gegen gängige **öffentliche** RBLs.
|
||
// * @return array<string> gelistete RBL-Zonen
|
||
// */
|
||
// private function queryRblLists(string $ip): array
|
||
// {
|
||
// if (!$this->validIPv4($ip)) return [];
|
||
//
|
||
// $rev = implode('.', array_reverse(explode('.', $ip)));
|
||
//
|
||
// // nur Zonen prüfen, die es wirklich gibt
|
||
// $zones = [
|
||
// 'zen.spamhaus.org',
|
||
// 'psbl.surriel.com',
|
||
// 'dnsbl-1.uceprotect.net',
|
||
// 'all.s5h.net',
|
||
// ];
|
||
// $zones = array_values(array_filter($zones, fn($z) => @checkdnsrr($z.'.','NS')));
|
||
//
|
||
// $listed = [];
|
||
// foreach ($zones as $zone) {
|
||
// $q = "{$rev}.{$zone}.";
|
||
//
|
||
// $a = @dns_get_record($q, DNS_A) ?: [];
|
||
// if (!count($a)) continue;
|
||
//
|
||
// $ips = array_column($a, 'ip');
|
||
//
|
||
// // --- WICHTIG: Spamhaus "blocked" / Ratelimit ignorieren
|
||
// if (array_intersect($ips, ['127.255.255.254','127.255.255.255'])) {
|
||
// // optional: merk dir, dass Spamhaus blockt -> UI-Hinweis
|
||
// $listed[] = ['zone'=>$zone, 'code'=>'blocked', 'txt'=>null];
|
||
// continue;
|
||
// }
|
||
//
|
||
// $txtRecs = @dns_get_record($q, DNS_TXT) ?: [];
|
||
// $txt = $txtRecs[0]['txt'] ?? null;
|
||
//
|
||
// $listed[] = ['zone'=>$zone, 'code'=>$ips[0] ?? null, 'txt'=>$txt];
|
||
// }
|
||
//
|
||
// // Nur echte Treffer zurückgeben; „blocked“ separat signalisieren
|
||
// $real = array_values(array_filter($listed, fn($e) => ($e['code'] ?? null) !== 'blocked'));
|
||
//
|
||
// // Falls alles nur "blocked" war, gib leere Liste zurück
|
||
// return array_map(fn($e) => $e['zone'].($e['code'] ? " ({$e['code']})" : ''), $real);
|
||
// }
|
||
//}
|
||
////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<string> 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;
|
||
//
|
||
//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 { $this->load(true); }
|
||
//
|
||
// protected function load(bool $force=false): void
|
||
// {
|
||
// $this->ipv4 = trim(env('SERVER_PUBLIC_IPV4')) ?: '–';
|
||
// $this->ipv6 = trim(env('SERVER_PUBLIC_IPV6')) ?: '–';
|
||
//
|
||
// $data = Cache::remember('dash.rbl', $force ? 1 : 21600, function () {
|
||
// $ip = trim(@file_get_contents('/etc/mailwolt/public_ip') ?: '');
|
||
// if ($ip === '') $ip = trim(@shell_exec("curl -fsS --max-time 2 ifconfig.me 2>/dev/null") ?? '');
|
||
// if (!preg_match('/^\d+\.\d+\.\d+\.\d+$/', $ip)) $ip = '0.0.0.0';
|
||
//
|
||
// $rev = implode('.', array_reverse(explode('.', $ip)));
|
||
// $sources = [
|
||
// 'zen.spamhaus.org',
|
||
// 'bl.spamcop.net',
|
||
// 'dnsbl.sorbs.net',
|
||
// 'b.barracudacentral.org',
|
||
// ];
|
||
//
|
||
// $lists = [];
|
||
// foreach ($sources as $s) {
|
||
// $q = "$rev.$s";
|
||
// $res = trim(@shell_exec("dig +short ".escapeshellarg($q)." A 2>/dev/null") ?? '');
|
||
// if ($res !== '') $lists[] = $s;
|
||
// }
|
||
//
|
||
// return ['ip'=>$ip, 'hits'=>count($lists), 'lists'=>$lists];
|
||
// });
|
||
//
|
||
// foreach ($data as $k=>$v) $this->$k = $v;
|
||
// }
|
||
//}
|