网上关于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 安全配置
以上我都不打算多说了。参数意思可以看看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版本 支持使用变量了。 (责任编辑:IT) |