使用CURL检查网站是否使用SSL

8
我正在编写一个脚本,用于检查网站是否使用SSL。例如,我们使用"http://www.google.com/"将被重定向到"https://www.google.com/"。我该如何检查呢?我正在使用以下cURL代码获取网站的头部信息。
<?php
$url = 'https://www.google.com';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); // set url
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6"); // set browser/user agent
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header'); // get header
curl_exec($ch);

function read_header($ch, $string) {
    print "Received header: $string";
    return strlen($string);
}
?>

输出:

HTTP/1.1 302 Found 
Cache-Control: private 
Content-Type: text/html; charset=UTF-8 
Location: https://www.google.co.in/?gfe_rd=cr&ei=YEAkV7SEFrTv8wexyy0 
Content-Length: 259 
Date: Sat, 30 Apr 2016 05:19:28 GMT 
Alternate-Protocol: 443:quic 
Alt-Svc: quic=":443"; ma=2592000; v="33,32,31,30,29,28,27,26,25" 

@Dagon 我已经修改了代码。现在它可以访问http和https网站。但是头部没有任何区别。 - Gijo Varghese
使用此链接检查 PHP Curl 到 http://stackoverflow.com/questions/29605043/php-curl-to-check-ssl-connection。 - Jatinder Kaur
如果我理解问题正确的话,您是说即使使用HTTPS访问Web服务器,它仍会返回302?但这并不重要,因为您只需要检查响应中的头部“Location:”是否包含“https://”即可。 - IVO GELOV
@GijoVarghese,我的回答对你有用吗? - Shivam Mathur
这是我几个月前正在进行的一个项目。我很快会检查它。 - Gijo Varghese
显示剩余2条评论
2个回答

8

PHP - cURL

我认为使用cURL有些过度,但无论如何,下面是相关内容。

<?php
function ignoreHeader( $curl, $headerStr ) {
  return strlen( $headerStr );
}

$curl = curl_init( "https://example.com/" );
curl_setopt( $curl, CURLOPT_NOBODY, TRUE );
curl_setopt( $curl, CURL_HEADERFUNCTION, 'ignoreHeader' );
curl_exec( $curl );

$result = false;
if ( curl_errno($curl) == 0 ) {
  $info = curl_getinfo( $curl );
  if ( $info['http_code'] == 200 ) {
    $result = true;
  }
}
?>

PHP - 不使用cURL

如果你想检查一个网站是否有SSL证书,你可以打开一个流并检查SSL证书参数。

<?php
// Create a stream context
$stream = stream_context_create ( array( "ssl" => array( "capture_peer_cert" => true ) ) );

// Bind the resource 'https://www.example.com' to $stream
$read   = fopen( "https://www.example.com", "rb", false, $stream );

// Get stream parameters
$params  = stream_context_get_params( $read );

// Check that SSL certificate is not null
// $cert should be for example "resource(4) of type (OpenSSL X.509)" 
$cert   = $params["options"]["ssl"]["peer_certificate"];
$result = ( !is_null( $cert ) ) ? true : false;
?>

如果你想检查一个主机是否接受443端口的连接,你可以使用fsockopen来与主机建立套接字连接。

<?php
// Set host and port. 
$host   = 'example.com';
$port   = 443;

// Initiate a socket connection with 'example.com' and check the result. 
$fp     = fsockopen('ssl://'. $host, $port, $errno, $errstr, 30);
$result = ( !is_null( $fp ) ) ? true : false;
?>

2
为了满足“此站是否使用SSL”的要求,我们需要首先理解“使用SSL”实际上意味着什么。
在HTTP客户端的上下文中,它通常意味着服务器至少在标准SSL端口(443端口)上侦听HTTP请求。因此,一个很好的第一步检查可以是尝试在该端口上远程连接到服务器以初始化TCP连接。如果远程主机接受连接,我们至少知道要继续尝试,如果没有,我们就知道它没有在标准SSL端口上侦听。
对于这个问题,cURL过于高级,所以我们可以尝试使用fsockopen代替。这样可以简单地在指定的端口上打开这个Internet连接,并获取足够的信息以了解我们需要的内容。远程主机是否侦听此端口或接受连接?
function connect($host, $port, $timeOut = 5) {
    $fp = fsockopen($host, $port, $errno, $errstr, $timeOut);
    if (!$fp) {
        printf("It looks like the host '%s' does not accept connections on port %d - error #%d [%s]\n", $host, $port, $errno, $errstr);
        return true;
    } else {
        fclose($fp); // we know it's listening
        printf("It looks like the host '%s' does accept connections on port %d\n", $host, $port);
        return false;
    }
}

$host = "www.google.com";
$port = 443;
connect($host, $port);

这并不能确认远程主机是否确实使用SSL进行通信,但至少它可以告诉您是否值得尝试在标准SSL端口上与服务器通信。这是一种廉价的方法,因为我们不会首先尝试通过SSL发送请求。如果您想从那里尝试进一步通过https发送请求,并通过curl确认响应是否成功,当然也可以这样做。

尽管根据您的问题,我认为您假设仅因为服务器通过HTTP发送位置标头就可以得出该站点正在使用SSL。这是不正确的。远程主机可以接受两个端口的流量,并且通常会这样做。远程主机还可能不会将所有标准HTTP端口上的流量重定向到SSL端口(即尝试从http重定向到https)。事实上,远程主机可能根本没有侦听端口80。它可能依靠像HSTS或HTTP Strict Transport Security这样的东西。

在所有情况下,确认远程主机是否通过HTTP使用SSL传输的唯一方法是实际成功建立连接。假设您正在通过所有正确的SSL渠道进行对等证书和远程身份验证,那么通过curl的https请求成功产生响应的事实可以在某种程度上得出结论。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接