true, 'localhost' => true, ]; $denyRootHosts = [ 'seo.chaegeon.com' => true, ]; function collectFiles(array $paths): array { $files = []; foreach ($paths as $path) { if (is_file($path)) { $files[] = $path; continue; } if (!is_dir($path)) { continue; } $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS) ); foreach ($it as $file) { if (!$file->isFile()) { continue; } $name = $file->getFilename(); if ( str_ends_with($name, '.conf') || str_contains($name, 'ReverseProxy') || str_contains($name, 'nginx') || str_contains($file->getPathname(), 'sites-enabled') ) { $files[] = $file->getPathname(); } } } return array_values(array_unique($files)); } function extractServerBlocks(string $text): array { $blocks = []; $len = strlen($text); $pos = 0; while (($serverPos = strpos($text, 'server', $pos)) !== false) { $before = $serverPos > 0 ? $text[$serverPos - 1] : ' '; $after = $text[$serverPos + 6] ?? ' '; if (preg_match('/[a-zA-Z0-9_\-]/', $before) || preg_match('/[a-zA-Z0-9_\-]/', $after)) { $pos = $serverPos + 6; continue; } $brace = strpos($text, '{', $serverPos); if ($brace === false) { break; } $depth = 0; for ($i = $brace; $i < $len; $i++) { if ($text[$i] === '{') { $depth++; } elseif ($text[$i] === '}') { $depth--; if ($depth === 0) { $blocks[] = substr($text, $serverPos, $i - $serverPos + 1); $pos = $i + 1; break; } } } if ($pos <= $serverPos) { break; } } return $blocks; } function cleanNginxText(string $text): string { $text = preg_replace('/#.*$/m', '', $text); return $text ?? ''; } function extractServerNames(string $block): array { preg_match_all('/server_name\s+([^;]+);/i', $block, $matches); $names = []; foreach ($matches[1] ?? [] as $line) { foreach (preg_split('/\s+/', trim($line)) as $host) { $host = trim($host); if ($host === '' || $host === '_' || str_contains($host, '$')) { continue; } if (str_starts_with($host, '~')) { continue; } $host = trim($host, '.'); if (filter_var($host, FILTER_VALIDATE_IP)) { continue; } if (preg_match('/^[a-zA-Z0-9.-]+$/', $host)) { $names[] = strtolower($host); } } } return array_values(array_unique($names)); } function detectScheme(string $block): string { if (preg_match('/listen\s+[^;]*443[^;]*ssl/i', $block)) { return 'https'; } if (preg_match('/ssl_certificate\s+/i', $block)) { return 'https'; } return 'http'; } function isBlockedServer(string $block): bool { if (preg_match('/return\s+444\s*;/i', $block)) { return true; } if (preg_match('/deny\s+all\s*;/i', $block) && !preg_match('/proxy_pass|fastcgi_pass|root\s+/i', $block)) { return true; } return false; } function extractLocations(string $block): array { return ['/']; } function extractDocumentRoot(string $block): ?string { if (!preg_match('/^\s*root\s+([^;]+);/mi', $block, $matches)) { return null; } $root = trim($matches[1], " \t\n\r\0\x0B\"'"); if ($root === '' || str_contains($root, '$') || !is_dir($root)) { return null; } $root = rtrim($root, '/'); if ($root === '') { return null; } return $root; } function discoverPhpEntryPaths(?string $root): array { if ($root === null) { return []; } $paths = []; $allowedFiles = [ 'index.php' => true, 'monitor.php' => true, ]; $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS) ); foreach ($it as $file) { if (!$file->isFile()) { continue; } $filename = $file->getFilename(); if (!isset($allowedFiles[$filename])) { continue; } $relative = substr($file->getPathname(), strlen($root)); if ($relative === false || $relative === '') { continue; } $relative = str_replace(DIRECTORY_SEPARATOR, '/', $relative); if ($relative === '/index.php') { continue; } $depth = substr_count(trim($relative, '/'), '/'); if ($depth > 1) { continue; } $paths[] = $relative; } sort($paths, SORT_NATURAL); return array_values(array_unique($paths)); } $items = []; $files = collectFiles($nginxFiles); foreach ($files as $file) { $raw = @file_get_contents($file); if ($raw === false) { continue; } $text = cleanNginxText($raw); $blocks = extractServerBlocks($text); foreach ($blocks as $block) { if (isBlockedServer($block)) { continue; } $hosts = extractServerNames($block); if (!$hosts) { continue; } $scheme = detectScheme($block); if ($scheme !== 'https') { continue; } $paths = array_values(array_unique(array_merge( extractLocations($block), discoverPhpEntryPaths(extractDocumentRoot($block)) ))); foreach ($hosts as $host) { if (str_contains($host, 'webdav')) { continue; } if (isset($denyHosts[$host])) { continue; } foreach ($paths as $path) { if ($path === '/' && isset($denyRootHosts[$host])) { continue; } $url = $scheme . '://' . $host . $path; $items[$url] = [ 'url' => $url, 'host' => $host, 'scheme' => $scheme, ]; } } } } ksort($items, SORT_NATURAL); ?>