mirror of
https://git.hexahost.dev/smueller/HexaHost-Frontend.git
synced 2026-06-02 08:58:43 +00:00
113 lines
2.7 KiB
PHP
113 lines
2.7 KiB
PHP
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getApiClientIp(): string {
|
|
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP'])
|
|
&& filter_var($_SERVER['HTTP_CF_CONNECTING_IP'], FILTER_VALIDATE_IP)) {
|
|
return $_SERVER['HTTP_CF_CONNECTING_IP'];
|
|
}
|
|
|
|
$remoteAddr = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
|
|
$isTrustedProxy = filter_var(
|
|
$remoteAddr,
|
|
FILTER_VALIDATE_IP,
|
|
FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE
|
|
) === false;
|
|
|
|
if ($isTrustedProxy) {
|
|
foreach (['HTTP_X_REAL_IP', 'HTTP_X_FORWARDED_FOR'] as $header) {
|
|
if (empty($_SERVER[$header])) {
|
|
continue;
|
|
}
|
|
$ip = trim(explode(',', $_SERVER[$header])[0]);
|
|
if (filter_var($ip, FILTER_VALIDATE_IP)) {
|
|
return $ip;
|
|
}
|
|
}
|
|
}
|
|
|
|
return $remoteAddr;
|
|
}
|
|
|
|
|
|
|
|
|
|
function checkApiRateLimit(string $endpoint, int $maxPerHour = 120): bool {
|
|
$ip = getApiClientIp();
|
|
$cacheFile = sys_get_temp_dir() . '/hexahost_api_' . md5($endpoint . '_' . $ip) . '.txt';
|
|
$currentTime = time();
|
|
$data = ['requests' => []];
|
|
|
|
$handle = @fopen($cacheFile, 'c+');
|
|
if ($handle === false) {
|
|
return true;
|
|
}
|
|
|
|
try {
|
|
if (!flock($handle, LOCK_EX)) {
|
|
return true;
|
|
}
|
|
|
|
$contents = stream_get_contents($handle);
|
|
if ($contents !== false && $contents !== '') {
|
|
$decoded = json_decode($contents, true);
|
|
if (is_array($decoded) && isset($decoded['requests'])) {
|
|
$data = $decoded;
|
|
}
|
|
}
|
|
|
|
$data['requests'] = array_values(array_filter(
|
|
$data['requests'],
|
|
static fn($timestamp) => ($currentTime - (int) $timestamp) < 3600
|
|
));
|
|
|
|
if (count($data['requests']) >= $maxPerHour) {
|
|
return false;
|
|
}
|
|
|
|
$data['requests'][] = $currentTime;
|
|
ftruncate($handle, 0);
|
|
rewind($handle);
|
|
fwrite($handle, json_encode($data));
|
|
} finally {
|
|
flock($handle, LOCK_UN);
|
|
fclose($handle);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
function getValidatedDomainParam(string $param = 'domain'): ?string {
|
|
if (empty($_GET[$param])) {
|
|
return null;
|
|
}
|
|
|
|
$domain = trim((string) $_GET[$param]);
|
|
$domain = preg_replace('/^(https?:\/\/)?/', '', $domain);
|
|
$domain = explode('/', $domain)[0];
|
|
$domain = explode(':', $domain)[0];
|
|
|
|
if (!preg_match('/^[a-zA-Z0-9][a-zA-Z0-9\-\.]*\.[a-zA-Z]{2,}$/', $domain)) {
|
|
return null;
|
|
}
|
|
|
|
return $domain;
|
|
}
|
|
|
|
|
|
|
|
|
|
function rejectApiRateLimit(): void {
|
|
http_response_code(429);
|
|
echo json_encode(['error' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.']);
|
|
exit;
|
|
}
|