exec("SET search_path TO admin, public"); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $action = $_GET['action'] ?? $_POST['action'] ?? 'stats'; switch($action) { case 'check': $ip = $_GET['ip'] ?? $_POST['ip'] ?? ''; if (empty($ip)) { // Check automatique des IPs actives $stmt = $db->query(" SELECT DISTINCT ip FROM reputation_log WHERE ip IS NOT NULL AND checked_at > NOW() - INTERVAL '6 hours' LIMIT 10 "); $ips = $stmt->fetchAll(PDO::FETCH_COLUMN); $ip = $ips[0] ?? '127.0.0.1'; } $results = perform_ptr_check($ip); // Vérifier SPF/DKIM/DMARC pour le domaine trouvé if (!empty($results['ptr_record'])) { $domain = extract_domain_from_ptr($results['ptr_record']); if ($domain) { $results['dns_checks'] = check_dns_records($domain); } } echo json_encode([ 'success' => true, 'checked_at' => date('Y-m-d H:i:s'), 'ip' => $ip, 'results' => $results, 'health_score' => calculate_health_score($results) ]); break; case 'batch': $ips_input = $_GET['ips'] ?? $_POST['ips'] ?? ''; $ips = array_filter(array_map('trim', explode(',', $ips_input))); if (empty($ips)) { echo json_encode([ 'success' => false, 'error' => 'No IPs provided' ]); break; } $batch_results = []; foreach ($ips as $ip) { if (filter_var($ip, FILTER_VALIDATE_IP)) { $batch_results[$ip] = perform_ptr_check($ip); } } echo json_encode([ 'success' => true, 'batch_time' => date('Y-m-d H:i:s'), 'ips_checked' => count($batch_results), 'results' => $batch_results, 'summary' => summarize_batch_results($batch_results) ]); break; case 'stats': $stmt = $db->query(" SELECT COUNT(DISTINCT ip) as unique_ips_checked, AVG(CASE WHEN ptr_record IS NOT NULL THEN 1 ELSE 0 END) * 100 as ptr_success_rate, MIN(checked_at) as first_check, MAX(checked_at) as last_check FROM ptr_discovery_log WHERE checked_at > NOW() - INTERVAL '30 days' "); $stats = $stmt->fetch(PDO::FETCH_ASSOC); // Top PTR records $stmt = $db->query(" SELECT ptr_record, COUNT(*) as frequency FROM ptr_discovery_log WHERE ptr_record IS NOT NULL AND checked_at > NOW() - INTERVAL '7 days' GROUP BY ptr_record ORDER BY frequency DESC LIMIT 10 "); $top_ptr_records = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode([ 'success' => true, 'stats' => $stats, 'top_ptr_records' => $top_ptr_records, 'recent_discoveries' => get_recent_discoveries($db) ]); break; default: echo json_encode([ 'success' => false, 'error' => 'Unknown action', 'available_actions' => ['check', 'batch', 'stats'] ]); } function perform_ptr_check($ip) { $results = [ 'ip' => $ip, 'ptr_record' => null, 'reverse_dns' => null, 'check_time' => date('Y-m-d H:i:s'), 'dns_checks' => [] ]; // Simulation de PTR lookup if (filter_var($ip, FILTER_VALIDATE_IP)) { // Simuler une réponse PTR $ptr_entries = [ "mail.{$ip}.wevads.com", "smtp.{$ip}.example.net", "mx01.isp-provider.com", "relay.mailserver.org", null // 20% chance de pas de PTR ]; $has_ptr = rand(0, 100) > 20; // 80% chance d'avoir un PTR if ($has_ptr) { $ptr_record = $ptr_entries[array_rand($ptr_entries)]; $results['ptr_record'] = $ptr_record; $results['reverse_dns'] = gethostbyaddr($ip) ?: 'N/A'; } } // Log pour debugging file_put_contents('/var/log/wevads/ptr_checks.log', date('Y-m-d H:i:s') . " PTR check for $ip: " . ($results['ptr_record'] ?: 'NO PTR') . "\n", FILE_APPEND ); return $results; } function extract_domain_from_ptr($ptr_record) { $parts = explode('.', $ptr_record); if (count($parts) >= 2) { // Extraire le domaine (ex: mail.server.com -> server.com) return $parts[count($parts)-2] . '.' . $parts[count($parts)-1]; } return null; } function check_dns_records($domain) { $checks = []; // SPF check $checks['spf'] = [ 'record' => 'v=spf1 include:_spf.google.com ~all', 'exists' => rand(0, 100) > 30, // 70% chance 'valid' => true ]; // DKIM check $checks['dkim'] = [ 'selector' => 'google', 'record' => 'k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4...', 'exists' => rand(0, 100) > 40, // 60% chance 'valid' => true ]; // DMARC check $checks['dmarc'] = [ 'record' => 'v=DMARC1; p=none; rua=mailto:dmarc@' . $domain, 'exists' => rand(0, 100) > 50, // 50% chance 'policy' => 'none' ]; // MX records $checks['mx'] = [ 'records' => [ ['priority' => 10, 'server' => 'aspmx.l.google.com'], ['priority' => 20, 'server' => 'alt1.aspmx.l.google.com'] ], 'count' => rand(1, 5) ]; return $checks; } function calculate_health_score($results) { $score = 100; // Points pour PTR if (empty($results['ptr_record'])) { $score -= 40; } // Points pour DNS records if (isset($results['dns_checks'])) { if (empty($results['dns_checks']['spf']['exists'])) $score -= 20; if (empty($results['dns_checks']['dkim']['exists'])) $score -= 20; if (empty($results['dns_checks']['dmarc']['exists'])) $score -= 10; } return max(0, $score); } function summarize_batch_results($batch_results) { $summary = [ 'total_ips' => count($batch_results), 'ips_with_ptr' => 0, 'ips_without_ptr' => 0, 'average_health_score' => 0 ]; $total_score = 0; foreach ($batch_results as $ip => $result) { if (!empty($result['ptr_record'])) { $summary['ips_with_ptr']++; } else { $summary['ips_without_ptr']++; } $total_score += calculate_health_score($result); } $summary['average_health_score'] = count($batch_results) > 0 ? round($total_score / count($batch_results), 2) : 0; $summary['ptr_success_rate'] = count($batch_results) > 0 ? round(($summary['ips_with_ptr'] / count($batch_results)) * 100, 2) : 0; return $summary; } function get_recent_discoveries($db) { $stmt = $db->query(" SELECT ip, ptr_record, checked_at FROM ptr_discovery_log WHERE checked_at > NOW() - INTERVAL '1 hour' ORDER BY checked_at DESC LIMIT 10 "); return $stmt->fetchAll(PDO::FETCH_ASSOC); } ?>