Total Pageviews

Friday 29 November 2013

SELinux 导致 PHP 无法使用 fsockopen 连接到Memcached 服务器

使用 memcache.php 来监控 Memcache 状态。然而却发现该工具无法连接上 Memcached 服务器。经检查,Memcached 服务器已经正常启动,使用 telnet 能够正常连接上去,使用 Memcached 的应用程序(PHP程序)也正常工作。查看 memcache.php 代码发现其是使用 fsockopen 来连接 Memcached 服务器,遂怀疑 Socket 扩展的问题。然而,检查发现可以在命令行中使用 fsockopen 连接到任意地址的任意端口,说明 Socket 扩展没问题。但在 httpd 中使用 fsockopen 来就只能连接本机的 80、8080、443 端口,连接其他端口均失败。

检查 httpd 的 log 也没发现任何问题。上网搜索也没发现类似问题,郁闷ing……

于是又想到是否是 SELinux 的问题。grep 了下 /var/log/audit/audit.log,发现以下线索:



    [liang@www ~]$ sudo grep denied /var/log/audit/audit.log

    type=AVC msg=audit(1280882021.681:780): avc:  denied  { name_connect } for  pid=3822 comm="httpd" dest=11211 scontext=user_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket
    type=AVC msg=audit(1280885410.800:805): avc:  denied  { name_connect } for  pid=3790 comm="httpd" dest=11211 scontext=user_u:system_r:httpd_t:s0 tcontext=system_u:object_r:http_cache_port_t:s0 tclass=tcp_socket

看来又是 SELinux 搞的鬼。继续检查,发现 /var/log/messages 有以下错误信息:

    Aug  4 08:11:59 www setroubleshoot: SELinux is preventing the http daemon from connecting to the itself or the relay ports For complete SELinux messages. run sealert -l 23d1381f-9d4b-439a-9ad6-d52f1025f247

果然是 SELinux 引起的问题。根据提示继续检查:

    [liang@www ~]$ sealert -l 23d1381f-9d4b-439a-9ad6-d52f1025f247

    Summary:

    SELinux is preventing the http daemon from connecting to the itself or the relay
    ports

    Detailed Description:

    SELinux has denied the http daemon from connecting to itself or the relay ports.
    An httpd script is trying to do a network connect to an http/ftp port. If you
    did not setup httpd to network connections, this could signal a intrusion
    attempt.

    Allowing Access:

    If you want httpd to connect to httpd/ftp ports you need to turn on the
    httpd_can_network_relay boolean: "setsebool -P httpd_can_network_relay=1"

    The following command will allow this access:

    setsebool -P httpd_can_network_relay=1

    Additional Information:

    Source Context                user_u:system_r:httpd_t
    Target Context                system_u:object_r:http_cache_port_t
    Target Objects                None [ tcp_socket ]

    ———————省略若干输出———————

错误信息说得很明了了:SELinux 阻止了 httpd 的连接。修改方式也给出来了,以 root 身份运行以下命令即可:

    [liang@www ~]$ sudo /usr/sbin/setsebool -P httpd_can_network_relay=1

注意该命令成功运行后没有任何输出。要检查是否设置成功,可以查看运行 getsebool 命令或者直接查看 log:

    [liang@www ~]$ /usr/sbin/getsebool httpd_can_network_relay
    httpd_can_network_relay –> on

    [liang@www ~]$ sudo tail /var/log/messages

    Aug  4 10:50:23 www setsebool: The httpd_can_network_relay policy boolean was changed to 1 by root

设置成功了。重新刷新下 memcache.php, 发现已经能够正常工作了。