parent
2ef27b5e8f
commit
c8cae445c5
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace App\Livewire\Ui\Security;
|
||||
|
||||
use Livewire\Component;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Livewire\Component;
|
||||
|
||||
class RblCard extends Component
|
||||
{
|
||||
|
|
@ -15,6 +15,9 @@ class RblCard extends Component
|
|||
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();
|
||||
|
|
@ -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<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 [];
|
||||
}
|
||||
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<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;
|
||||
//
|
||||
|
|
|
|||
|
|
@ -4,17 +4,64 @@
|
|||
<i class="ph ph-shield-warning text-white/70 text-[13px]"></i>
|
||||
<span class="text-[11px] uppercase text-white/70">Reputation / RBL</span>
|
||||
</div>
|
||||
<div class="text-xs text-white/70">IP: <span class="text-white/90">{{ $ip }}</span></div>
|
||||
|
||||
<div class="text-xs text-white/70">
|
||||
IP: <span class="text-white/90">{{ $ip }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
@if($hits === 0)
|
||||
<span class="px-2 py-0.5 rounded-full border text-emerald-300 border-emerald-400/30 bg-emerald-500/10">Keine Treffer</span>
|
||||
<div class="flex items-center gap-2 text-emerald-300">
|
||||
<i class="ph ph-shield-check-thin text-lg"></i>
|
||||
<span>Deine IP ist aktuell auf keiner der geprüften Blacklists.</span>
|
||||
</div>
|
||||
<div class="mt-2 text-[11px] text-white/45">
|
||||
Geprüfte öffentliche RBLs: Spamhaus, PSBL, UCEPROTECT-1, s5h.
|
||||
</div>
|
||||
@else
|
||||
<div class="text-sm text-white/70">{{ $hits }} Treffer:</div>
|
||||
<div class="flex items-center gap-2 text-rose-300">
|
||||
<i class="ph ph-warning-circle text-lg"></i>
|
||||
<span>{{ $hits }} Treffer auf Blacklists:</span>
|
||||
</div>
|
||||
<ul class="mt-2 space-y-1 text-sm text-rose-300">
|
||||
@foreach($lists as $l)<li>• {{ $l }}</li>@endforeach
|
||||
@foreach($lists as $l)
|
||||
<li class="flex items-center gap-2">
|
||||
<span class="inline-block w-1.5 h-1.5 rounded-full bg-rose-400"></span>
|
||||
<span>{{ $l }}</span>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="mt-3">
|
||||
<button wire:click="refresh"
|
||||
class="inline-flex items-center gap-1.5 rounded-full text-[11px] px-3 py-1
|
||||
text-white/80 bg-white/10 border border-white/15
|
||||
hover:bg-white/15 hover:text-white">
|
||||
<i class="ph ph-arrows-clockwise text-[12px]"></i>
|
||||
Neu prüfen
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{--<div class="glass-card p-4 rounded-2xl border border-white/10 bg-white/5">--}}
|
||||
{{-- <div class="flex items-center justify-between">--}}
|
||||
{{-- <div class="inline-flex items-center gap-2 bg-white/5 border border-white/10 px-2.5 py-1 rounded-full">--}}
|
||||
{{-- <i class="ph ph-shield-warning text-white/70 text-[13px]"></i>--}}
|
||||
{{-- <span class="text-[11px] uppercase text-white/70">Reputation / RBL</span>--}}
|
||||
{{-- </div>--}}
|
||||
{{-- <div class="text-xs text-white/70">IP: <span class="text-white/90">{{ $ip }}</span></div>--}}
|
||||
{{-- </div>--}}
|
||||
|
||||
{{-- <div class="mt-3">--}}
|
||||
{{-- @if($hits === 0)--}}
|
||||
{{-- <span class="px-2 py-0.5 rounded-full border text-emerald-300 border-emerald-400/30 bg-emerald-500/10">Keine Treffer</span>--}}
|
||||
{{-- @else--}}
|
||||
{{-- <div class="text-sm text-white/70">{{ $hits }} Treffer:</div>--}}
|
||||
{{-- <ul class="mt-2 space-y-1 text-sm text-rose-300">--}}
|
||||
{{-- @foreach($lists as $l)<li>• {{ $l }}</li>@endforeach--}}
|
||||
{{-- </ul>--}}
|
||||
{{-- @endif--}}
|
||||
{{-- </div>--}}
|
||||
{{--</div>--}}
|
||||
|
|
|
|||
Loading…
Reference in New Issue