You've already forked Atomcms-edit
Initial commit
This commit is contained in:
Executable
+184
@@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
||||
readonly class IpLookupService
|
||||
{
|
||||
private const array BLOCKLISTS = [
|
||||
// FireHol - All Levels (werkt)
|
||||
'firehol_level1' => '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',
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user