zoukankan      html  css  js  c++  java
  • nginx+fastcgi+php安全虚拟主机隔离配制方法

    网上关于nginx +fastcgi+php 虚拟主机独立站点安全配置文章很多。

    其中 关于Nginx+PHP的虚拟主机目录权限控制的探究   文章已经讲的很详细了。方法很多,有设置http://www.cnblogs.com/http://www.cnblogs.com/ 特殊目录的,有通过open_basedir配制独立站点,独立目录的。 还有将所有站点目录都写在open_basedir里面。只是没有站点用比较特殊目录名称。别人不知道目录的。是进去不了。还有修改php 源码,加入root_path限制,访问目录。

    那么我写这篇文章,不想再去考虑怎么样限制在某个目录了。 我主要要说的是:、

    1,php.ini 安全配置

    2,通过启动多个php-cgi怎么样实现灵活配制

    3,nginx fastcgi_pass 怎么样控制发到不同的fastcgi

    如果你对这些都比较清楚,可以忽略跳过下面的了。

    1.php.ini 安全配置

    配制项目

    说明

    allow_url_fopen=Off
    allow_url_include=Off

    禁止远程包含

    register_globals=Off

    禁止自动注册全局变量

    open_basedir="\tmp:"

    限制操作文件路径(具体站点具体路径)

    safe_mode=Off
    safe_mode_gid=Off

    禁止使用安全模式

    max_execution_time=30
    max_input_time=60

    限制脚本执行时间(避免耗时限制语句)

    memory_limit=32M
    upload_max_filesize=5M
    post_max_size=8M
    max_input_nesting_levels=64

    限制内存,及文件尺寸

    display_errors=Off
    log_errors=On
    error_log="/var/log/nginx/phperror.log"

    安全的错误配制

    fastcgi.logging=0

    cgi.fix_pathinfo=0

    禁止fastcgi 的pathinfo

    最近nginx漏洞在此

    expose_php=Off

    隐藏php的版本信息

    enable_dl=Off

    关闭dl参数

    disable_functions =phpinfo,exec,passthru,shell_exec,system,proc_open,

    popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

    禁止恶意函数执行

    以上我都不打算多说了。参数意思可以看看php手册。

    2.fastcgi  启动脚本

    a.为每个站点建立一个独立用户,都属于同一个组

    [root@localhost ~]# groupadd webuser

    [root@localhost ~]# useradd   -M   -G webuser  -s /sbin/nologin web-a.com

    b.建立fastcgi通用启动脚本

     [root@www]# egrep -v '#.*|^$' php-cgi.sh

    . /etc/rc.d/init.d/functions  

    SPAWNFCGI="/usr/local/bin/spawn-fcgi" 

    FCGIPROGRAM="/usr/bin/php-cgi" 

    FCGIPROGRAM2="$FCGIPROGRAM $CGI_OPTIONS" 

    PHP_FCGI_MAX_REQUESTS=500 

    FCGI_WEB_SERVER_ADDRS="127.0.0.1" 

    ALLOWED_ENV="SHELL PATH USER" 

    if test x$PHP_FCGI_CHILDREN = x; then  

    PHP_FCGI_CHILDREN=5 

    fi  

    prog="${tmpfile%.*}-fcgi"

    FCGI_SOCKET="/tmp/$prog.sock"

    FCGI_PIDFILE="/var/run/$prog.pid"

    FCGI_LOCKFILE="/var/lock/subsys/$prog"

    export PHP_FCGI_MAX_REQUESTS  

    export FCGI_WEB_SERVER_ADDRS  

    ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS" 

    if test x$UID = x0; then  

    EX="$SPAWNFCGI -s $FCGI_SOCKET -f \"$FCGIPROGRAM2\" -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN -P $FCGI_PIDFILE" 

    else  

    EX="$SPAWNFCGI -s $FCGI_SOCKET -f \"$FCGIPROGRAM2\" -C $PHP_FCGI_CHILDREN -P $FCGI_PIDFILE" 

    fi  

    E=  

    for i in $ALLOWED_ENV; do  

    E="$E $i=${!i}" 

    done  

    RETVAL=0 

    status() {

    local pid

            echo $"Usage: status {program}"

            return 1

    fi

    pid=`pgrep $base -u $USERID | sed 's/\n/\t/g'`

    if [ -n "$pid" ]; then

            echo $"${prog} (pid $pid) is running..."

            return 0

    fi

    if [ -f $FCGI_PIDFILE ] ; then

            read pid < $FCGI_PIDFILE

            if [ -n "$pid" ]; then

                    echo $"${prog} dead but pid file exists"

                    return 1

            fi

    fi

    if [ -f $FCGI_LOCKFILE ]; then

            echo $"${prog} dead but subsys locked"

            return 2

    fi

    echo $"${prog} is stopped"

    return 3

    }

    start() {  

            echo -n $"Starting $prog: "   

            daemon env - $E $EX  

    chmod 777 $ FCGI_SOCKET

            RETVAL=$?  

            echo  

            [ $RETVAL -eq 0 ] && touch $FCGI_LOCKFILE  

            return $RETVAL  

    }  

    stop() {  

            echo -n $"Stopping $prog: "   

                    rm -f $FCGI_PIDFILE $FCGI_SOCKET  

                    RETVAL=$?  

                    [ "$RETVAL" -eq 0 ] && success "startup" || failure "startup"

                    echo  

                    [ $RETVAL -eq 0 ] && rm -f $FCGI_LOCKFILE  

                    return $RETVAL  

    }  

    case "$1" in  

    start)  

    start  

    ;;  

    stop)  

    stop  

    ;;  

    restart)   

    stop  

    start  

    ;;  

    condrestart)  

    if [ -f $FCGI_LOCKFILE ]; then  

    stop  

    start  

    fi  

    ;;  

    status)  

    status $FCGIPROGRAM  

    RETVAL=$?  

    ;;  

    *)  

    echo $"Usage: $0 {start|stop|restart|condrestart|status}"   

    RETVAL=1 

    esac  

    exit $RETVAL

    上面这个脚本是我用网上脚本改造而成,主要修改,当重启,或者stop 莫个站点php-cgi 实际是将所有站点都停止了。 这样不符合独立虚拟主机的独立管理原则。

     c.独立站点的 启动脚本

    web-chaohao.com通用包含脚本:

    [root@www]# egrep -v '#.*|^$' www.a.com.sh

    export PATH=/usr/bin:/bin:/usr/local/bin:/usr/X11R6/bin;

    export LANG=zh_CN.GB2312;

    #启动php-cgi 线程数量

    PHP_FCGI_CHILDREN=30;

    #启动账户

    USERID= web-a.com;

    #启动群组

    GROUPID=webuser;

    CGI_OPTIONS=" -d open_basedir=/home/www/a/:/tmp/ -C  ";

    TMPPATH=`dirname $0`;

    . $TMPPATH/php-cgi.sh;

    从上面脚本应该可以看出,这个是每个站点一个脚本,然后脚本,包含 通用脚本 php-cgi.sh

    www.a.com.sh  这个里面有个CGI_OPTIONS 配制选项,可以控制open_basedir 允许的站点。 当然,也可以配置其它php.ini  key=value 参数。

    值得注意的是:

    i. 多个配制的话,可以用多个-d 参数。  -d open_basedir=/tmp -d display_errors=on  这样就会覆盖掉php.ini 里面配置。 呵呵,比较简单吧。

    ii.很奇怪是当 php -v 版本是:5.1.6好像不起作用,后来升级到5.2.6 配制就生效了。 php-cgi -d 后面设置不生效的情况下,请看下你的php版本。

    iii.php-cgi.sh 与站点脚本www.a.com.sh 放到同一目录.

    d.启动站点

    chmod +x www.a.com.sh

    ./www.a.com.sh

    Usage: ./www.chaohao.com.sh {start|stop|restart|condrestart|status}

    可以带参数。

    ./www.a.com.sh start

    Starting www.a.com-fcgi:                             [  OK  ]

    ps aux | grep php-cgi

    可以看到脚本已经启动

     0.2  0.1 82040 7692 ?        Ss   16:35   0:00 /usr/bin/php-cgi -d open_basedir=/home/www/html/www.a.com/:/tmp/ -C

    ................

    e.脚本解析

    上面脚本,会自动创建

     /var/run/脚本文件名-fcgi.pid

    /tmp/脚本文件名-fcgi.sock

    文件。 如果执行脚本是,www.a.com.sh

    创建文件对应是:/var/run/www.a.com-fcgi.pid 以及 /tmp/www.a.com-fcgi.sock

    建议站点名称,最好能够跟用户名,以及脚本名称统一。如果你的站点是 www.b.com

    useradd 设置为 web-b.com

    shell脚本设置为b.com.sh

    3.nginx sever配制

    [root@web49 nginx]# egrep -v '#.*|^$'  /etc/nginx/host/webhost.conf

    server {

    listen       8888;

    #绑定域名

        server_name  www.a.com www.b.com;  

        access_log   /var/log/nginx/chaohao.access.log main;

        error_log    /var/log/nginx/chaohao.error.log;

        index index.php index.shtml;

        set $test_host www.chaohao.com;

        set     $Root_Path /home/www/html/$test_host;

        root    $Root_Path/html;

        set $sock_file www.chaohao.com-fcgi.sock;

        if ($host ~* www.a.com|www.b.com)

        {

             set $sock_file www.a.com-fcgi.sock;

        }

        set $sock_file unix:/tmp/$sock_file;

        location ~ \.php$ {

               include        /etc/nginx/fastcgi_params;

               fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;

               fastcgi_param  Root_Path    $Root_Path;

               fastcgi_param  Root_HTML    $document_root;

               fastcgi_index  index.php;

               fastcgi_pass   $sock_file;

         }

     }

    如果域名与站点设计比较好,可以直接通过读取$host 里面变量,作为fastcgi_pass 参数

    注意:

    fastcgi_pass 如果不支持变量,需要注意了。这个可能与你的nginx 版本有关系。

    测试发现 fastcgi_pass  nginx 0.639不支持使用变量。后来使用0.7.65版本 支持使用变量了。

  • 相关阅读:
    iOS拓展---[转载]视频相关,一定要看呀
    iOS拓展---碰到奇葩需求
    iOS拓展---【转载】成熟的夜间模式解决方案
    2018年度总结
    linux常用命令
    自我认识
    SpringBoot入门最详细教程
    SVN分支的合并和同步
    java Data、String、Long三种日期类型之间的相互转换
    徐胜治:我要留下真正的东西
  • 原文地址:https://www.cnblogs.com/chengmo/p/1773859.html
Copyright © 2011-2022 走看看