| Server IP : 202.61.199.114 / Your IP : 216.73.217.139 Web Server : nginx/1.22.1 System : Linux de.arni-solutions.de 6.1.0-49-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.174-1 (2026-05-26) x86_64 User : web20 ( 1018) PHP Version : 8.4.23 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /var/www/safemyident.de/web/api/lib/ |
Upload File : |
<?php
/**
* Erkennung: Tor-Exit, Cloud-/Hosting-Provider, Rechenzentrum vs. Privatanschluss.
* Ausschließlich frei verfügbare Signale (Tor-Exit-Liste, ASN-Heuristik).
*
* @package SafeMyIdent\Api
*/
declare(strict_types=1);
require_once __DIR__ . '/net.php';
/**
* Tor-Exit-Node-Liste (täglich gecacht) als Set.
*
* @return array<string,bool>
*/
function smi_tor_exit_set(): array
{
$hit = smi_cache_get('tor|exitlist');
if (is_array($hit)) {
return $hit;
}
$body = smi_provider_get('https://check.torproject.org/torbulkexitlist', 8, ['Accept' => 'text/plain']);
$set = [];
if ($body !== '') {
foreach (preg_split('/\R/', $body) as $line) {
$line = trim($line);
if ($line !== '' && smi_ip_version($line) > 0) {
$set[$line] = true;
}
}
}
// Auch leere Antwort cachen (kürzer), um Wiederholungen zu vermeiden.
smi_cache_set('tor|exitlist', $set, $set ? 86400 : 900);
return $set;
}
/**
* Ist die IP ein bekannter Tor-Exit-Node?
*
* @param string $ip IP.
* @return bool
*/
function smi_is_tor_exit(string $ip): bool
{
return isset(smi_tor_exit_set()[$ip]);
}
/**
* Cloud-/Hosting-Provider anhand AS-Name/ASN erkennen.
*
* @param string $asName AS-Name/Holder.
* @param string $asn ASN-Zahl.
* @return array{is_hosting:bool,provider:string,type:string}
* type: cloud | hosting | cdn | isp | unknown
*/
function smi_detect_network(string $asName, string $asn): array
{
$n = strtolower($asName);
$asn = preg_replace('/\D/', '', $asn);
// Bekannte Cloud/CDN nach ASN (Auszug) und Namensmuster.
$cloudAsn = [
'16509' => ['Amazon AWS', 'cloud'], '14618' => ['Amazon AWS', 'cloud'],
'15169' => ['Google Cloud', 'cloud'], '396982' => ['Google Cloud', 'cloud'],
'8075' => ['Microsoft Azure', 'cloud'],
'13335' => ['Cloudflare', 'cdn'], '14061' => ['DigitalOcean', 'cloud'],
'16276' => ['OVH', 'hosting'], '24940' => ['Hetzner', 'hosting'],
'20473' => ['Vultr / Choopa', 'hosting'], '63949' => ['Akamai / Linode', 'cloud'],
'14618' => ['Amazon AWS', 'cloud'], '20940' => ['Akamai', 'cdn'],
'45102' => ['Alibaba Cloud', 'cloud'], '132203' => ['Tencent Cloud', 'cloud'],
'14421' => ['Oracle Cloud', 'cloud'], '31898' => ['Oracle Cloud', 'cloud'],
'51167' => ['Contabo', 'hosting'], '60781' => ['LeaseWeb', 'hosting'],
'9009' => ['M247', 'hosting'], '35916' => ['MULTA (M247)', 'hosting'],
];
if ($asn !== '' && isset($cloudAsn[$asn])) {
return ['is_hosting' => true, 'provider' => $cloudAsn[$asn][0], 'type' => $cloudAsn[$asn][1]];
}
$map = [
'amazon' => ['Amazon AWS', 'cloud'], 'aws' => ['Amazon AWS', 'cloud'],
'google' => ['Google Cloud', 'cloud'], 'microsoft' => ['Microsoft Azure', 'cloud'], 'azure' => ['Microsoft Azure', 'cloud'],
'cloudflare' => ['Cloudflare', 'cdn'], 'akamai' => ['Akamai', 'cdn'], 'fastly' => ['Fastly', 'cdn'],
'hetzner' => ['Hetzner', 'hosting'], 'ovh' => ['OVH', 'hosting'], 'digitalocean' => ['DigitalOcean', 'cloud'],
'linode' => ['Linode', 'cloud'], 'vultr' => ['Vultr', 'hosting'], 'choopa' => ['Vultr / Choopa', 'hosting'],
'contabo' => ['Contabo', 'hosting'], 'leaseweb' => ['LeaseWeb', 'hosting'], 'm247' => ['M247', 'hosting'],
'alibaba' => ['Alibaba Cloud', 'cloud'], 'tencent' => ['Tencent Cloud', 'cloud'], 'oracle' => ['Oracle Cloud', 'cloud'],
'scaleway' => ['Scaleway', 'hosting'], 'gcore' => ['G-Core', 'cdn'], 'ionos' => ['IONOS', 'hosting'],
'netcup' => ['netcup', 'hosting'], 'servers' => ['Hosting', 'hosting'],
];
foreach ($map as $needle => $info) {
if (str_contains($n, $needle)) {
return ['is_hosting' => true, 'provider' => $info[0], 'type' => $info[1]];
}
}
// Heuristik: Hosting-typische Wörter.
foreach (['hosting', 'datacenter', 'data center', 'dedicated', 'server', 'vps', 'colo', 'cloud'] as $kw) {
if (str_contains($n, $kw)) {
return ['is_hosting' => true, 'provider' => $asName, 'type' => 'hosting'];
}
}
// Typische Consumer-ISP-Wörter.
foreach (['telekom', 'vodafone', 'telefonica', 'o2', 'kabel', 'comcast', 'at&t', 'verizon', 'orange', 'telecom', 'broadband', 'mobile', 'wireless', 'dsl', 'fiber'] as $kw) {
if (str_contains($n, $kw)) {
return ['is_hosting' => false, 'provider' => $asName, 'type' => 'isp'];
}
}
return ['is_hosting' => false, 'provider' => $asName, 'type' => 'unknown'];
}