exec(" CREATE TABLE IF NOT EXISTS certs ( domain TEXT PRIMARY KEY, expires INTEGER, checked_at INTEGER, error TEXT )"); $domains = file("/var/www/domains.txt", FILE_IGNORE_NEW_LINES); function check_ssl($domain) { $ctx = stream_context_create([ "socket" => ["bindto" => "0.0.0.0:0"], "ssl" => [ "capture_peer_cert" => true, "verify_peer" => false, "verify_peer_name" => false, "SNI_enabled" => true, "peer_name" => $domain ] ]); $client = @stream_socket_client( "ssl://$domain:443", $errno, $errstr, 5, STREAM_CLIENT_CONNECT, $ctx ); if (!$client) return [null, $errstr]; $params = stream_context_get_params($client); if (!isset($params["options"]["ssl"]["peer_certificate"])) { return [null, "No certificate"]; } $cert = openssl_x509_parse($params["options"]["ssl"]["peer_certificate"]); return [$cert["validTo_time_t"] ?? null, null]; } foreach ($domains as $domain) { [$expiry, $error] = check_ssl($domain); $stmt = $db->prepare(" INSERT INTO certs(domain, expires, checked_at, error) VALUES(:d,:e,:c,:er) ON CONFLICT(domain) DO UPDATE SET expires=:e, checked_at=:c, error=:er "); $stmt->execute([ ":d" => $domain, ":e" => $expiry, ":c" => time(), ":er" => $error ]); usleep(200000); // anti-rate-limit (0.2s) } echo "SSL check completed\n";