'Method not allowed'])); } header('Content-Type: application/json'); // --- Konfiguration --- define('MATRIX_HOMESERVER', 'https://cyperpunk.de'); define('MATRIX_ACCESS_TOKEN', 'syt_cmVnaXN0cmF0aW9uLWJvdA_tWjAfJOYDoJSuoCWoYIQ_4YuoMw'); define('MATRIX_ROOM_ID', '!xBizjYatXLfpCorAXt:cyperpunk.de'); // Rate-Limit: max. Anfragen pro Zeitfenster define('RATE_LIMIT_MAX', 5); // Anfragen define('RATE_LIMIT_WINDOW', 300); // Sekunden (5 Minuten) define('RATE_LIMIT_DIR', sys_get_temp_dir() . '/matrix_reg_rl'); // --- IP ermitteln (auch hinter Proxies) --- function getClientIP(): string { $headers = ['HTTP_CF_CONNECTING_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_REAL_IP', 'REMOTE_ADDR']; foreach ($headers as $header) { if (!empty($_SERVER[$header])) { $ip = explode(',', $_SERVER[$header])[0]; $ip = trim($ip); if (filter_var($ip, FILTER_VALIDATE_IP)) { return $ip; } } } return 'unknown'; } // --- Rate-Limiting (dateibasiert) --- function checkRateLimit(string $ip): bool { $dir = RATE_LIMIT_DIR; if (!is_dir($dir)) { mkdir($dir, 0700, true); } $file = $dir . '/' . hash('sha256', $ip) . '.json'; $now = time(); $data = ['count' => 0, 'window_start' => $now]; if (file_exists($file)) { $data = json_decode(file_get_contents($file), true) ?? $data; // Zeitfenster abgelaufen → zurücksetzen if ($now - $data['window_start'] > RATE_LIMIT_WINDOW) { $data = ['count' => 0, 'window_start' => $now]; } } if ($data['count'] >= RATE_LIMIT_MAX) { return false; } $data['count']++; file_put_contents($file, json_encode($data), LOCK_EX); return true; } // --- Honeypot prüfen --- $input = json_decode(file_get_contents('php://input'), true); if (!empty($input['website'])) { // Bot hat das versteckte Feld ausgefüllt – still ablehnen http_response_code(200); exit(json_encode(['success' => true])); } // --- Rate-Limit prüfen --- $ip = getClientIP(); if (!checkRateLimit($ip)) { http_response_code(429); exit(json_encode(['error' => 'Zu viele Anfragen. Bitte warte einige Minuten.'])); } // --- Eingabe validieren --- $username = isset($input['username']) ? trim($input['username']) : ''; $email = isset($input['email']) ? trim($input['email']) : ''; if (empty($username) || empty($email)) { http_response_code(400); exit(json_encode(['error' => 'Benutzername und E-Mail sind erforderlich.'])); } if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { http_response_code(400); exit(json_encode(['error' => 'Ungültige E-Mail-Adresse.'])); } // Eingaben bereinigen $username = htmlspecialchars($username, ENT_QUOTES, 'UTF-8'); $email = htmlspecialchars($email, ENT_QUOTES, 'UTF-8'); // --- Nachricht zusammenstellen --- $timestamp = date('d.m.Y H:i:s T'); $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unbekannt'; $message = "🔐 Registration Request\n\n" . "Username: {$username}\n" . "E-Mail: {$email}\n" . "IP: {$ip}\n" . "Zeitstempel: {$timestamp}\n" . "User-Agent: {$userAgent}"; $formattedMessage = "🔐 Registration Request

" . "Username: {$username}
" . "E-Mail: {$email}
" . "IP: {$ip}
" . "Zeitstempel: {$timestamp}
" . "User-Agent: {$userAgent}"; // --- An Matrix senden --- $txnId = 'reg_' . time() . '_' . bin2hex(random_bytes(8)); $url = MATRIX_HOMESERVER . '/_matrix/client/v3/rooms/' . urlencode(MATRIX_ROOM_ID) . '/send/m.room.message/' . $txnId; $payload = json_encode([ 'msgtype' => 'm.text', 'body' => $message, 'format' => 'org.matrix.custom.html', 'formatted_body' => $formattedMessage, ]); $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_CUSTOMREQUEST => 'PUT', CURLOPT_POSTFIELDS => $payload, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . MATRIX_ACCESS_TOKEN, 'Content-Type: application/json', ], CURLOPT_TIMEOUT => 10, ]); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch); curl_close($ch); if ($curlError) { http_response_code(502); exit(json_encode(['error' => 'Verbindung zum Matrix-Server fehlgeschlagen.'])); } if ($httpCode >= 200 && $httpCode < 300) { http_response_code(200); exit(json_encode(['success' => true])); } else { $matrixError = json_decode($response, true); http_response_code(502); exit(json_encode(['error' => 'Matrix-Fehler: ' . ($matrixError['error'] ?? "HTTP {$httpCode}")])); }