'https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset', 'firehol_level2' => 'https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level2.netset', 'firehol_level3' => 'https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level3.netset', 'firehol_level4' => 'https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level4.netset', // Spamhaus (werkt) 'spamhaus_drop' => 'https://www.spamhaus.org/drop/drop.txt', 'spamhaus_edrop' => 'https://www.spamhaus.org/drop/edrop.txt', // Threat Intelligence (werkt) 'dshield' => 'https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/dshield.netset', 'emerging_threats' => 'https://rules.emergingthreats.net/blockrules/compromised-ips.txt', // Blocklist.de (werkt) 'blocklist_de_all' => 'https://lists.blocklist.de/lists/all.txt', 'blocklist_de_mail' => 'https://lists.blocklist.de/lists/mail.txt', 'blocklist_de_ssh' => 'https://lists.blocklist.de/lists/ssh.txt', 'blocklist_de_ftp' => 'https://lists.blocklist.de/lists/ftp.txt', 'blocklist_de_sip' => 'https://lists.blocklist.de/lists/sip.txt', ]; private const int CACHE_TIME = 43200; public function getCountryInfo(string $ip): array { $cacheKey = "ip_country_{$ip}"; return Cache::remember($cacheKey, now()->addDays(7), function () use ($ip) { try { $response = Http::timeout(10)->get("http://ip-api.com/json/{$ip}"); if ($response->ok()) { $data = $response->json(); return [ 'country_code' => $data['countryCode'] ?? null, 'country_name' => $data['country'] ?? null, 'region' => $data['regionName'] ?? null, 'city' => $data['city'] ?? null, 'isp' => $data['isp'] ?? null, 'org' => $data['org'] ?? null, 'as' => $data['as'] ?? null, ]; } } catch (\Exception $e) { return ['error' => $e->getMessage()]; } return ['error' => 'Failed to fetch']; }); } public function checkVpnProxyTor(string $ip): array { $cacheKey = "ip_check_{$ip}"; return Cache::remember($cacheKey, now()->addHours(6), function () use ($ip) { $isBlocked = $this->isIpInAnyBlocklist($ip); return [ 'is_vpn' => $isBlocked, 'is_proxy' => $isBlocked, 'is_tor' => $isBlocked, 'is_malicious' => $isBlocked, 'source' => 'multi_blocklist', ]; }); } private function isIpInAnyBlocklist(string $ip): bool { foreach (self::BLOCKLISTS as $name => $url) { $cidrs = $this->getBlocklistCidrs($name, $url); foreach ($cidrs as $cidr) { if ($this->ipInCidr($ip, $cidr)) { return true; } } } return false; } private function getBlocklistCidrs(string $name, string $url): array { $cacheKey = "cidr_blocklist_{$name}"; return Cache::remember($cacheKey, now()->addHours(self::CACHE_TIME), function () use ($url) { try { $response = Http::timeout(120)->get($url); if (! $response->ok()) { return []; } $lines = explode("\n", $response->body()); $cidrs = []; foreach ($lines as $line) { $line = trim($line); if ($line === '' || $line === '0' || str_starts_with($line, '#') || str_starts_with($line, ';')) { continue; } if (str_contains($line, '/')) { $cidrs[] = $line; } elseif (filter_var($line, FILTER_VALIDATE_IP)) { $cidrs[] = $line . '/32'; } } return $cidrs; } catch (\Exception) { return []; } }); } private function ipInCidr(string $ip, string $cidr): bool { if (! str_contains($cidr, '/')) { return $ip === $cidr; } try { [$subnet, $mask] = explode('/', $cidr); $mask = (int) $mask; if ($mask < 0 || $mask > 32) { return false; } $ipLong = ip2long($ip); $subnetLong = ip2long($subnet); if ($ipLong === false || $subnetLong === false) { return false; } $maskLong = -1 << (32 - $mask); return ($ipLong & $maskLong) === ($subnetLong & $maskLong); } catch (\Exception) { return false; } } public function refreshBlocklists(): void { foreach (array_keys(self::BLOCKLISTS) as $name) { Cache::forget("cidr_blocklist_{$name}"); } } public function getBlocklistStats(): array { $totalCidrs = 0; foreach (self::BLOCKLISTS as $name => $url) { $cidrs = $this->getBlocklistCidrs($name, $url); $totalCidrs += count($cidrs); } return [ 'total' => $totalCidrs, 'source' => 'multi_blocklist', ]; } }