diff --git a/cron/check_dns.php b/cron/check_dns.php index bec6c3f..d7eb2be 100644 --- a/cron/check_dns.php +++ b/cron/check_dns.php @@ -95,12 +95,27 @@ $startTime = microtime(true); logMessage("=== Starting DNS check cron job ==="); -$domains = $domainModel->where('is_active', 1); -$domains = array_values(array_filter($domains, fn($d) => ($d['dns_monitoring_enabled'] ?? 1) == 1)); -logMessage("Found " . count($domains) . " domain(s) with DNS monitoring enabled"); +// Only check domains that are registered and in use (active or expiring_soon). +// Skip available, expired, error, redemption_period, pending_delete — they typically have no DNS. +$checkableStatuses = ['active', 'expiring_soon']; + +$allDnsEnabled = array_values(array_filter( + $domainModel->where('is_active', 1), + static fn($d): bool => ($d['dns_monitoring_enabled'] ?? 1) == 1 +)); +$domains = array_values(array_filter($allDnsEnabled, static function ($d) use ($checkableStatuses): bool { + $status = strtolower($d['status'] ?? ''); + return in_array($status, $checkableStatuses, true); +})); +$skippedByStatus = count($allDnsEnabled) - count($domains); +logMessage("Found " . count($domains) . " domain(s) with DNS monitoring enabled and checkable status (active/expiring_soon)"); +if ($skippedByStatus > 0) { + logMessage("Skipped " . $skippedByStatus . " domain(s) with non-checkable status (available/expired/error/redemption_period/pending_delete)"); +} $stats = [ 'checked' => 0, + 'skipped_by_status' => $skippedByStatus, 'changes_detected' => 0, 'records_added' => 0, 'records_removed' => 0, @@ -833,6 +848,7 @@ function printSummary(array $stats, float $startTime): void logMessage("\n=== DNS cron job completed ==="); logMessage("Domains checked: {$stats['checked']}"); + logMessage("Skipped (by status): {$stats['skipped_by_status']}"); logMessage("Skipped (unresolved): {$stats['skipped_unresolved']}"); logMessage("Crt.sh fetched: {$stats['crtsh_fetched']}"); logMessage("Crt.sh skipped (cached): {$stats['crtsh_skipped']}"); diff --git a/cron/check_ssl.php b/cron/check_ssl.php index 1c7224b..b67ca03 100644 --- a/cron/check_ssl.php +++ b/cron/check_ssl.php @@ -60,13 +60,29 @@ $startTime = microtime(true); logMessage("=== Starting SSL check cron job ==="); -$domains = $domainModel->where('is_active', 1); -$domains = array_values(array_filter($domains, static fn(array $domain): bool => ($domain['ssl_monitoring_enabled'] ?? 0) == 1)); -logMessage("Found " . count($domains) . " domain(s) with SSL monitoring enabled"); +// Only check domains that are registered and in use (active or expiring_soon). +// Skip available, expired, error, redemption_period, pending_delete — they typically have no DNS/SSL. +$checkableStatuses = ['active', 'expiring_soon']; + +$allSslEnabled = array_values(array_filter( + $domainModel->where('is_active', 1), + static fn(array $d): bool => ($d['ssl_monitoring_enabled'] ?? 0) == 1 +)); +$domains = array_values(array_filter($allSslEnabled, static function (array $domain) use ($checkableStatuses): bool { + $status = strtolower($domain['status'] ?? ''); + return in_array($status, $checkableStatuses, true); +})); +$skippedByStatus = count($allSslEnabled) - count($domains); +logMessage("Found " . count($domains) . " domain(s) with SSL monitoring enabled and checkable status (active/expiring_soon)"); +if ($skippedByStatus > 0) { + logMessage("Skipped " . $skippedByStatus . " domain(s) with non-checkable status (available/expired/error/redemption_period/pending_delete)"); +} $stats = [ 'checked_domains' => 0, 'checked_hosts' => 0, + 'skipped_by_status' => $skippedByStatus, + 'skipped_unresolved' => 0, 'issues_detected' => 0, 'notifications_sent' => 0, 'in_app_notifications' => 0, @@ -115,6 +131,13 @@ foreach ($domains as $domain) { $hostname = $target['hostname']; $port = (int)($target['port'] ?? 443); $endpointLabel = $sslService->formatTargetLabel($hostname, $port); + + if (!hostnameResolves($hostname)) { + logMessage(" {$endpointLabel}: skipped (hostname does not resolve)"); + $stats['skipped_unresolved']++; + continue; + } + $existing = $sslModel->findByDomainAndHost($domain['id'], $hostname, $port); $previousStatus = $existing['status'] ?? null; @@ -200,6 +223,8 @@ $settingModel->setValue('last_ssl_check_run', date('Y-m-d H:i:s')); logMessage("\n=== SSL cron job completed ==="); logMessage("Domains checked: {$stats['checked_domains']}"); +logMessage("Domains skipped: {$stats['skipped_by_status']} (non-checkable status)"); +logMessage("Endpoints skipped: {$stats['skipped_unresolved']} (hostname does not resolve)"); logMessage("Endpoints checked: {$stats['checked_hosts']}"); logMessage("Status changes: {$stats['status_changes']}"); logMessage("Issue endpoints: {$stats['issues_detected']}"); @@ -337,6 +362,13 @@ function logTimeSince(float $since): void logMessage(" -> " . formatDuration(microtime(true) - $since)); } +function hostnameResolves(string $hostname): bool +{ + return @checkdnsrr($hostname, 'SOA') + || @checkdnsrr($hostname, 'A') + || @checkdnsrr($hostname, 'AAAA'); +} + function formatDuration(float $seconds): string { if ($seconds < 60) { diff --git a/database/migrations/028_add_ssl_monitoring.sql b/database/migrations/028_add_ssl_monitoring.sql index 7ef8b53..bf526e9 100644 --- a/database/migrations/028_add_ssl_monitoring.sql +++ b/database/migrations/028_add_ssl_monitoring.sql @@ -35,24 +35,6 @@ ALTER TABLE domains ADD COLUMN ssl_last_checked TIMESTAMP NULL AFTER dns_last_checked, ADD COLUMN ssl_monitoring_enabled TINYINT(1) NOT NULL DEFAULT 0 COMMENT '1=SSL monitoring active, 0=disabled' AFTER dns_monitoring_enabled; --- Preserve existing monitored SSL domains when upgrading -UPDATE domains d -SET d.ssl_monitoring_enabled = 1 -WHERE EXISTS ( - SELECT 1 - FROM ssl_certificates s - WHERE s.domain_id = d.id -); - --- Carry forward the latest stored SSL check time -UPDATE domains d -JOIN ( - SELECT domain_id, MAX(last_checked) AS max_checked - FROM ssl_certificates - GROUP BY domain_id -) s ON s.domain_id = d.id -SET d.ssl_last_checked = s.max_checked; - -- Add SSL monitoring cron settings INSERT INTO settings (setting_key, setting_value, `type`, `description`) VALUES ('ssl_check_interval_hours', '12', 'string', 'SSL certificate check interval in hours'),