运行stream_socket_server&时拒绝连接客户端通过apache

时间:2013-11-01 21:19:33

标签: php apache sockets centos

我有一个运行Apache 2.2.3和PHP 5.4.8的CentOS 5.9盒子。

我正在尝试使用PHP设置服务器,以便其他服务器上的C应用程序可以轻松地从我们的网络服务器查询某些信息。

我还希望能够在本地向服务器发送数据包 - 从同一个网络服务器 - 以方便地控制服务器。

问题是,当通过浏览器/ apache访问服务器和客户端时,客户端永远无法连接。当我通过CLI执行客户端或服务器时,它突然运行。

我在Ubuntu盒子上测试了相同的代码,它没有任何问题。

对于测试/调试,服务器会在30秒后自动关闭。

澄清:


  • 浏览器转到serverstart.php
  • 浏览器转到client.php
  • 结果:client.php一直加载,直到serverstart.php达到30秒关闭,然后响应Connection拒绝

  • 浏览器转到serverstart2.php,它使用exec,passthru或system('php -f serverstart.php');
  • 浏览器转到client.php
  • 结果:不起作用。客户端挂起,直到serverstart.php在30秒后关闭。

  • CLI:php -f serverstart.php
  • 浏览器转到client.php
  • 结果:正常工作

  • 浏览器转到serverstart.php
  • CLI:php -f client.php
  • 结果:正常工作

  • 浏览器转到serverstart.php
  • CLI:echo“Test”| nc localhost 8000
  • 结果:正常工作

client.php

<?php

$client = stream_socket_client("tcp://localhost:8000", $errno, $errorMessage);

if ($client === false) {
    echo "Failed to connect: $errorMessage";
}

fwrite($client, "This is a test" . PHP_EOL);
echo stream_get_contents($client);
fclose($client);

serverstart.php

<?PHP
$server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errorMessage);

if ($server === false) {
    throw new UnexpectedValueException("Could not bind to socket: $errorMessage");
}

$start = microtime(true);

while((microtime(true) - $start) < 30) { // 30 second timeout
    $client = @stream_socket_accept($server, 1);

    if ($client) {
        echo 'Client Found';
        $message = fgets($client, 1024);
        echo 'Client said:' . $message;
        fwrite($client, 'The local time is ' . date('n/j/Y g:i a') . PHP_EOL);
        fclose($client);
    }
}

任何人都知道这里有什么问题以及如何让它通过浏览器调用它们?

编辑:我想补充说框上没有运行防火墙。 iptables出现空白,SELinux被禁用。

1 个答案:

答案 0 :(得分:0)

相反延迟回答但不知道你的apache和php配置,或者你的Ubuntu和CentOS配置之间的差异。我认为权限可能是您问题的根源。

例如,当您通过CLI运行脚本并使用su apache; php serverstart.php;时,您应该获得与从浏览器运行时相同的结果。而不是以root身份运行CLI。这是因为apache没有权限连接指定的ip / port。

此外,确保您的端口8000未被Apache(或其他服务)使用,因为它是许多配置中的常见端口,并且在尝试通过php访问时可能会被阻止。通常在Apache配置中的某个位置它将包含Listen *:8000或类似的内容。

EG:http://localhost:8000 -> Apache -> php -> fsockopen('tcp://localhost:8000')(已在使用中),php超时,端口打开,然后client.php响应Connection Refused。

您可以通过创建仅包含<?php sleep(120);浏览http://localhost/test.php的脚本(test.php)来检查冲突,然后在test.php处于休眠状态时从CLI执行servertstart.php。

同样在您的serverstart.php中,请确保在脚本末尾执行fclose($server);stream_socket_shutdown($server, STREAM_SHUT_RDWR);,以确保服务器不会处于不可用状态。同时添加至少一个usleep(500)以防止额外的CPU使用。如果stream_socket_accept返回false,您也应该退出循环,因为它表示发生了错误,而不是从循环内调用@stream_socket_accept

while($timer < 30 && ($client = stream_socket_accept($server, 1))){
  $timer = (microtime(true) - $start);
  //code here
}

如果上述内容对我认为正在发生的事情没有帮助,那么默认情况下,您的Apache Web服务器充当PHP的包装器,并使用apache的用户和组权限执行。这就是为什么您的Web文件通常具有用户组apache权限,其中目录为750,文件为640。 这允许apache访问并拒绝匿名访问虚拟主机目录中的目录和文件,然后当它读取PHP文件时,apache执行php并将结果输出为text / html。 但是,Apache无权访问其他系统资源

您可以通过在一个脚本中执行echo exec('whoami');并从浏览器导航到该脚本来检查正在运行的用户。

权限问题有几种解决方法,其中大多数都是不好的做法,并且会在服务器上出现安全漏洞。

您可以通过在连接之前从serverstart.php和client.php中执行umask(0);来解决此问题。这意味着创建的任何内容都将使用0777权限,包括套接字。或者您可以尝试在serverstart.php和client.php上设置chmod(755),以查看允许匿名用户对文件执行权限是否可以解决问题。

否则,您可以考虑为您的Web服务创建一个包装器,例如suexecphp-fpm,并使用fastcgi通过Apache执行user-name / user-group和正确的umask设置来运行它。然后确保您的用户有权在指定的ip / port上打开连接。