2014-12-29 4 views
5

Можно ли получить данные, например, если домен (скажем www.example.com) готов к HTTPS?Как проверить, имеет ли домен сертификат SSL или нет?

Мне нужно проверить некоторые URL-адреса, имеют ли они сертификат SSL или нет. Я знаю, используя $_SERVER['HTTPS'], мы можем проверить наши данные о сервере. но как я могу достичь того же для других доменов.

Любая помощь будет высоко оценена.

+1

Попробуйте подключиться к 'https: // www.example.com' с помощью любого метода, например, curl. – deceze

+0

@deceze Я так догадался, но я сомневаюсь, что все в порядке? Я имею в виду, что это правильный способ обнаружения? –

+0

На самом деле нет другого пути. Либо вы можете подключиться через SSL, либо не можете. Единственный способ узнать - попробовать. – deceze

ответ

7

Наконец, я закончил с следующим моим кодом:

$stream = stream_context_create (array("ssl" => array("capture_peer_cert" => true))); 
$read = fopen("https://www.example.com", "rb", false, $stream); 
$cont = stream_context_get_params($read); 
$var = ($cont["options"]["ssl"]["peer_certificate"]); 
$result = (!is_null($var)) ? true : false; 

Если HTTPS включен для домена, var_dump($var) дает выхода, как показано ниже:

resource(4) of type (OpenSSL X.509) 

Если это не существует, он возвращает NULL.

Я проверил несколько доменов. Кажется, он работает нормально. Надеюсь, это поможет кому-то.

+1

Опасность при таком подходе заключается в том, что вы не знаете, действителен ли сертификат. Многие серверы имеют SSL, настроенный для некоторых доменов (ур использует самоподписанные сертификаты), и обычно считается, что эти серверы возвращают первый доступный сертификат, если совпадение домена не выполняется (для поддержки клиентов без поддержки SNI). –

2

Вот другое решение, которое я нашел где-то на GitHub (не могу найти репозиторий снова ...)

Это подобный подход к принятому ответу, но использует fsockopen для проверки, если мы можем установить SSL соединение на порту 443. Если соединение отказано, домен не имеет сертификата ssl.

function has_ssl($domain) { 
    $ssl_check = @fsockopen('ssl://' . $domain, 443, $errno, $errstr, 30); 
    $res = !! $ssl_check; 
    if ($ssl_check) { fclose($ssl_check); } 
    return $res; 
} 

// Test it: 
print_r(has_ssl('google.com')); 
+0

Почему не просто 'function has_ssl ($ domain) { return @fsockopen ('ssl: //'. $ Domain, 443, $ errno, $ errstr, 30); } '? – Matt

5

Эта функция не только проверяет, имеет ли домен сертификат SSL, но также подтверждает, соответствует ли сертификат запрашиваемому домену.

Наиболее важной частью является функция openssl_x509_parse, которая анализирует сертификат и возвращает все детали в виде массива.

function has_ssl($domain) { 
    $res = false; 
    $stream = @stream_context_create(array('ssl' => array('capture_peer_cert' => true))); 
    $socket = @stream_socket_client('ssl://' . $domain . ':443', $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $stream); 

    // If we got a ssl certificate we check here, if the certificate domain 
    // matches the website domain. 
    if ($socket) { 
     $cont = stream_context_get_params($socket); 
     $cert_ressource = $cont['options']['ssl']['peer_certificate']; 
     $cert = openssl_x509_parse($cert_ressource); 

     // Expected name has format "/CN=*.yourdomain.com" 
     $namepart = explode('=', $cert['name']); 

     // We want to correctly confirm the certificate even 
     // for subdomains like "www.yourdomain.com" 
     if (count($namepart) == 2) { 
      $cert_domain = trim($namepart[1], '*. '); 
      $check_domain = substr($domain, -strlen($cert_domain)); 
      $res = ($cert_domain == $check_domain); 
     } 
    } 

    return $res; 
} 
+0

Работала с какой-то работой, почему-то у $ namepart всегда было 4 элемента вместо 2. – brace110

+0

Это не работает, если у сертификата есть несколько альтернативных имен, например, попробуйте на https://example.com/ –

+0

Я добавил это, чтобы заставить его работать: 'if (! $ res && strpos ($ cert ['extensions'] ['subjectAltName'] ?? ''," DNS: $ domain ")! == false) {return true;}' (он не обрабатывает случай, когда altName является подстановочным знаком) –

Смежные вопросы