【问题标题】:Unable to establish TLS connection in PHP via fsockopen无法通过 fsockopen 在 PHP 中建立 TLS 连接
【发布时间】:2011-10-06 04:42:42
【问题描述】:

几天以来,我一直在尝试通过我新安装的 Ubuntu 服务器上的 fsockopen() 与 PHP 中的 SMTP 服务器建立 TLS 连接。我几乎尝试了所有方法并在 Google 上搜索了几个小时,但仍然无法正常工作。

PHP 代码如下所示:

$fp = fsockopen("tls://smtp.xxxx.com", 25, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
 // some other stuff
}  

输出只是 (0),即 $errstr = null 和 $errno = 0。

OpenSSL 已安装并启用:

OpenSSL support: enabled
OpenSSL Library Version: OpenSSL 0.9.8o 01 Jun 2010
OpenSSL Header Version: OpenSSL 0.9.8o 01 Jun 2010

并注册了以下流套接字传输: tcp、udp、unix、udg、ssl、sslv3、sslv2、tls。

端口在控制台的 telnet 工作时打开。

任何想法有什么问题或我如何至少获得更多的调试输出?

谢谢, 马库斯

【问题讨论】:

  • 您在/etc/php/apache2/php.ini 中打开了错误日志记录?错误日志中的内容是什么?
  • 是的,它已启用。 apache 错误日志中的错误是:[Fri Jul 15 15:50:07 2011] [error] [client 95.233.109.135] PHP Warning: fsockopen(): unable to connect to tls://smtp.gmail.com:第 3 行 /var/www/test.php 中的 587(未知错误)我刚刚对其进行了测试。如果我通过“php test.php”从命令行执行脚本,它就可以工作。

标签: php ssl fsockopen


【解决方案1】:

您的连接没有多大意义。通过使用 TLS 处理程序,您希望在任何数据传输之前建立 TLS。但是端口 25 是标准 SMTP,它只能建立 TLSAFTER 您最初通过未加密的常规连接进行连接。建立初始连接后,您可以使用 STARTTLS 命令启用 TLS,以告知 SMTP 服务器进行切换。

如果您从一开始就想要 TLS,请使用端口 465,从一开始就是 ssl/tls。

【讨论】:

  • 也不适用于端口 465 或 587,但如果我直接从命令行调用脚本而不是通过 Apache(顺便说一句,它有一个静态的公共 IP)访问它,它就可以工作。
  • 试试fsockopen('smtp.xxx.com', 25),不指定任何协议。如果可以连接,但 tls 版本没有,那么 SSL 的东西就有点傻了。
  • 这行得通,但只要我在开头添加 tls://,它就不再通过 Apache 工作,而是继续从命令行工作。
  • 另一个测试是连接到 SSH 服务器(纯 ssl 协议),看看它是否有任何作用。如果发生同样的事情,那么您的配置有问题阻止 Apache 正确使用 SSL 库,或者阻止了来自 Apache 的那种类型的传出连接。
  • 发现这个:forums.powweb.com/showthread.php?t=73406 以明文连接开始,然后使用 stream_socket_enable_crypto() 切换到 TLS。
【解决方案2】:

如果它可以在命令行中运行,但不能在 Apache 中运行,那么 PHP 配置之间可能存在一些差异:在 /etc/php/apache2/php.ini/etc/php/cli/php.ini 之间进行比较,看看可能发生了什么变化。

【讨论】:

  • 好提示。但是并没有太大的区别。我做了一个差异,唯一的区别是我不允许 Apache 的短标签和不同的内存限制。
【解决方案3】:

使用 gmail,ssl 连接端口从一开始就具有 ssl,但是 tls 端口,您连接的是普通的,并且必须使用 STARTTLS 命令手动启动 tls。我猜这是一样的。这是gmail的示例,因此您可以看到发生了什么。 EHLO 命令显示 STARTTLS 命令,而如果您从一开始就以 ssl 开始,它会进入 AUTH XOAUTH 命令列表。

<?php
function get($socket,$length=1024){
    $send = '';
    $sr = fgets($socket,$length);
    while( $sr ){
        $send .= $sr;
        if( $sr[3] != '-' ){ break; }
        $sr = fgets($socket,$length);
    }
    return $send;
}
function put($socket,$cmd,$length=1024){
    fputs($socket,$cmd."\r\n",$length);
}
if (!($smtp = fsockopen("smtp.gmail.com", 587, $errno, $errstr, 15))) {
    die("Unable to connect");
}
echo "<pre>\n";
echo get($smtp); // should return a 220 if you want to check

$cmd = "EHLO ${_SERVER['HTTP_HOST']}";
echo $cmd."\r\n";
put($smtp,$cmd);
echo get($smtp); // 250

$cmd = "STARTTLS";
echo $cmd."\r\n";
put($smtp,$cmd);
echo get($smtp); // 220
if(false == stream_socket_enable_crypto($smtp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)){
    // fclose($smtp); // unsure if you need to close as I haven't run into a security fail at this point
    die("unable to start tls encryption");
}

$cmd = "EHLO ".$_SERVER['HTTP_HOST'];
echo $cmd;
put($smtp,$cmd);
echo get($smtp); // 250

$cmd = "QUIT";
echo $cmd."\r\n";
put($smtp,$cmd);
echo get($smtp);

echo "</pre>";

fclose($smtp);

【讨论】:

    猜你喜欢
    • 2013-06-10
    • 2019-07-11
    • 2015-01-27
    • 2018-12-30
    • 2020-11-07
    • 2012-02-03
    • 2021-12-02
    • 1970-01-01
    相关资源
    最近更新 更多