T086学习网 | 站长学院 | 技术文档 | 成语 | 歇后语 | 帝国时代 | 代码收藏 | IP地址查询 | 生活百科 | 生日密码 | CSS压缩 | 用户评论 | 欣欣百宝箱

lnmp多用户安全运行环境(chroot)

【 作者:诡谲 更新时间:2013-11-13 | 字体:
[导读]lnmp发展到今日,已经相当稳定,大部分程序也都可以平滑从apache移到nginx环境下。网上流行的lnmp一键包使很多Linux初学者可以非常方便地搭建自己的网站服务器。但随着建立的网站越来越多,安全性越来越成为威胁,由...

lnmp发展到今日,已经相当稳定,大部分程序也都可以平滑从apache移到nginx环境下。网上流行的lnmp一键包使很多Linux初学者可以非常方便地搭建自己的网站服务器。但随着建立的网站越来越多,安全性越来越成为威胁,由于没有将用户空间进行隔离,可以很轻松的进行跨站攻击。

在php5.4之前可以启用安全模式和目录权限防范跨站的问题,另外也可以通过配置PHP.ini进行防范,参考:LNMP下防跨站、跨目录安全设置,仅支持PHP 5.3.3以上版本

php5.4之后没有了安全模式,这里提供一个解决方案,动手能力较好的朋友可以动手试试。提供了比较完善的安全环境,设置了shell chroot、隔离php执行身份、目录权限等。没有禁用任何一个php的函数。

特点:
1、高效的http请求处理能力,系统负载低
2、安全的SSH环境,php执行权限分离,各用户间互不影响

架构的简单说明
1、由Nginx处理http请求,nginx运行属主身份为www:www,执行php代理到后端php-fpm,php-fpm负责管理各用户间的php进程,用户运行php的组权限为nobody
2、默认为每个用户提供了SSH,方便用户直接进行管理。限定各SSH用户只能访问家目录的文件,访问系统级命令和访问其他非属主身份的路径显示为无权限。
3、关于用户目录权限的说明,建立的用户属主身份为user:nobody,家目录自身权限:drwxr-x--x,其创建的目录权限设置为drwx---r-x,文件权限设定为-rw----r--。(user为当前用户)
4、通过设定系统umask及ftp服务umask,确保用户家目录下创建的文件权限为-rw----r--,目录权限为drwx---r-x

基本信息:
用户家目录为/home/chroot/home/$user,软链接至/home/$user
nginx 路径:/usr/local/nginx
php 路径:/usr/local/php5.4
php-fpm全局配置:/usr/local/php5.4/etc/php-fpm.conf
php-fpm pools配置:/usr/local/php5.4/etc/fpm.d/php-fpm-$user.conf
mysql 路径:/usr/local/mysql
mysql Data路径:/usr/local/mysql/data
pureftpd 路径:/usr/local/pureftpd
Modify路径:/usr/local/sbin/Modify #创建用户、域名、数据库直接运行脚本Modify

以Centos 6.3 64bit为例,按照下述过程编译

如果是安装在小内存的VPS上,建议增加swap空间,以免后面编译php时出现内存不足的问题

dd if=/dev/zero of=/var/swapfile bs=1024 count=512000
/sbin/mkswap /var/swapfile
/sbin/swapon /var/swapfile
echo "/var/swapfile swap swap defaults 0 0" >> /etc/fstab

先安装必备的开发库,这里我一股脑把后面所需的软件包都安装了,最后再进行无依赖包的清理工作。
yum -y install gcc gcc-c++ file bison patch unzip mlocate flex wget diffutils automake autoconf kernel-devel lsof gd cpp readline-devel openssl openssl-devel vim-minimal nano sendmail libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel libtidy libtidy-devel zlib zlib-devel glibc glibc-devel libc-client libc-client-devel glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel libc-client-devel curl curl-devel e2fsprogs e2fsprogs-devel libidn libidn-devel openldap openldap-devel openldap-clients openldap-servers net-snmp net-snmp-devel nss_ldap gettext gettext-devel expat-devel libcap libcap-devel libtool libtool-ltdl-devel pam-devel pcre-devel ncurses-devel subversion bind-utils rsync libxslt groff pkgconfig

一、编译autoconf、libiconv、libmcrypt、mhash、mcrypt等
cd /usr/local/src
wget -c http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
wget -c http://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.14.tar.gz
wget -c http://dl.icodex.org/lnamp-1.0/src/libmcrypt-2.5.8.tar.bz2/mirror
wget -c http://dl.icodex.org/lnamp-1.0/src/mhash-0.9.9.9.tar.bz2/mirror
wget -c http://dl.icodex.org/lnamp-1.0/src/mcrypt-2.6.8.tar.gz/mirror

cd /usr/local/src
tar -zxvf autoconf-2.69.tar.gz
cd autoconf-2.69/
./configure
make && make install

cd /usr/local/src
tar -zxvf libiconv-1.14.tar.gz
cd libiconv-1.14/
./configure
make && make install

cd /usr/local/src
tar -jxvf libmcrypt-2.5.8.tar.bz2
cd libmcrypt-2.5.8/
./configure
make && make install
/sbin/ldconfig
cd libltdl/
./configure --enable-ltdl-install
make && make install

cd /usr/local/src
tar -jxvf mhash-0.9.9.9.tar.bz2
cd mhash-0.9.9.9/
./configure
make && make install

ln -s /usr/local/lib/libmcrypt.la /usr/lib/libmcrypt.la
ln -s /usr/local/lib/libmcrypt.so /usr/lib/libmcrypt.so
ln -s /usr/local/lib/libmcrypt.so.4 /usr/lib/libmcrypt.so.4
ln -s /usr/local/lib/libmcrypt.so.4.4.8 /usr/lib/libmcrypt.so.4.4.8
ln -s /usr/local/lib/libmhash.a /usr/lib/libmhash.a
ln -s /usr/local/lib/libmhash.la /usr/lib/libmhash.la
ln -s /usr/local/lib/libmhash.so /usr/lib/libmhash.so
ln -s /usr/local/lib/libmhash.so.2 /usr/lib/libmhash.so.2
ln -s /usr/local/lib/libmhash.so.2.0.1 /usr/lib/libmhash.so.2.0.1

cd /usr/local/src
tar -zxvf mcrypt-2.6.8.tar.gz
cd mcrypt-2.6.8/
/sbin/ldconfig
./configure
make && make install

if [ `getconf WORD_BIT` = '32' ] && [ `getconf LONG_BIT` = '64' ] ; then
ln -s /usr/local/lib/libiconv.so.2.5.0 /lib64/libiconv.so.2
fi

二、安装数据库。这里启用了Google 开发的“google-perftools”中的TCMalloc,以增加数据库在高并发下的性能,降低系统负载。同时TCMalloc也同样适用于nginx,因此我们先安装TCMalloc库。以下是安装步骤
1、64位操作系统请先安装libunwind库,32位操作系统不要安装。libunwind库为基于64位CPU和操作系统的程序提供了基本的堆栈辗转开解功能,其中包括用于输出堆栈跟踪的API、用于以编程方式辗转开解堆栈的API以及支持C++异常处理机制的API。
cd /usr/local/src/
wget http://mirror.yongbok.net/nongnu/libunwind/libunwind-1.0.1.tar.gz
cd /usr/local/src/
tar -zxvf libunwind-1.0.1.tar.gz
cd libunwind-1.0.1/
CFLAGS=-fPIC ./configure
make CFLAGS=-fPIC
make CFLAGS=-fPIC install

2、安装google-perftools:
cd /usr/local/src/
wget http://gperftools.googlecode.com/files/gperftools-2.0.tar.gz
tar -zxvf gperftools-2.0.tar.gz
cd gperftools-2.0
./configure --enable-frame-pointers
make && make install

3、修改增加动态链接库
echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf
/sbin/ldconfig

4、修改MariaDB启动脚本(这个步骤我们在后面编译好MariaDB之后再增加)

然后安装最新版开源MariaDB。从MySQL/MariaDB 5.5开始,源码编译构建工具从GUN Autotools换成跨平台的cmake。
1、首先编译安装cmake,当前最新版本为2.8.9
rpm -e cmake

cd /usr/local/src/
wget http://www.cmake.org/files/v2.8/cmake-2.8.9.tar.gz
tar -zxvf cmake-2.8.9.tar.gz
cd cmake-2.8.9;
./bootstrap
make
make install

cd /usr/local/src/
wget http://ftp.gnu.org/gnu/bison/bison-2.7.1.tar.gz
tar -zxvf bison-2.7.1.tar.gz
cd bison-2.7.1
./configure
make
make install

2、编译MariaDB,当前版本号为5.5.32
首先新建MariaDB运行用户(组)
/usr/sbin/groupadd -g 27 -o -r mysql
/usr/sbin/useradd -M -g mysql -o -r -d /usr/local/mysql/data -s /bin/false -c "MariaDB Server" -u 27 mysql

cd /usr/local/src/
wget -O mariadb-5.5.32.tar.gz http://mirror.yongbok.net/mariadb/mariadb-5.5.32/kvm-tarbake-jaunty-x86/mariadb-5.5.32.tar.gz
tar -zxf mariadb-5.5.32.tar.gz
cd mariadb-5.5.32.tar.gz
CFLAGS="-O3" CXX=gcc
CXXFLAGS="-O3 -felide-constructors -fno-exceptions -fno-rtti"
cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/usr/local/mysql/data -DMYSQL_TCP_PORT=3306 -DMYSQL_UNIX_ADDR=/tmp/mysql.sock -DWITH_EMBEDDED_SERVER=0 -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_ARCHIVE_STORAGE_ENGINE=1 -DWITH_BLACKHOLE_STORAGE_ENGINE=1 -DWITH_PERFSCHEMA_STORAGE_ENGINE=1 -DWITH_PARTITION_STORAGE_ENGINE=1 -DWITH_FEDERATEDX_STORAGE_ENGINE=1 -DWITH_ARIA_STORAGE_ENGINE=1 -DWITH_XTRADB_STORAGE_ENGINE=1 -DDEFAULT_CHARSET=utf8 -DDEFAULT_COLLATION=utf8_general_ci -DENABLED_LOCAL_INFILE=1 -DWITH_EXTRA_CHARSETS=all -DWITH_READLINE=1 -DWITH_LIBWRAP=1 -DWITH_SSL=system -DWITH_ZLIB=system
make && make install

这里我把大部分数据库引擎都添加了,并设置默认字符集为utf8_general_ci,更多cmake选项,可以执行cmake . -LH|more进行查看。对于多核处理器,可以在make时增加-j选项,如8个核心:make -j 8

3、创建一些目录
mkdir -p /usr/local/mysql/InnoDB/redoLogs; mkdir -p /usr/local/mysql/InnoDB/undoLogs
chown -R mysql /usr/local/mysql/data
chgrp -R mysql /usr/local/mysql
mkdir /usr/local/mysql/logs /usr/local/mysql/tmp
chown mysql.mysql /usr/local/mysql/tmp
chown mysql.mysql /usr/local/mysql/logs

这里数据库data目录为/usr/local/mysql/data,为了方便习惯,也可以做个软连接到/var/lib/mysql
ln -s /usr/local/mysql/data /var/lib/mysql
chown -R mysql /var/lib/mysql

4、初始化第一个数据库mysql,这里存储了mysql用户表、权限表等
cd /usr/local/mysql
./scripts/mysql_install_db --user=mysql --datadir=/usr/local/mysql/data

5、设置修改配置文件my.cnf和init开机启动脚本
/usr/bin/install -m 755 /usr/local/mysql/support-files/my-innodb-heavy-4G.cnf /etc/my.cnf
/usr/bin/install -m 755 /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d/mysqld
chkconfig --add mysqld

sed -i '69 s/max_connections = 100/max_connections = 1000/' /etc/my.cnf
sed -i '181 s/default-storage-engine = MYISAM/default-storage-engine = innodb/' /etc/my.cnf
sed -i '/myisam_recover/a\skip-name-resolve\nskip-external-locking\nskip-host-cache' /etc/my.cnf
小内存机器建议修改innodb缓冲池大小,否则启动mysql后innodb将显示无法使用或无法启动服务
sed -i '368 s/innodb_buffer_pool_size = 2G/innodb_buffer_pool_size = 256M/' /etc/my.cnf

6、修改开机启动脚本,在/etc/rc.d/init.d/mysqld第46行、47行指定路径,直接用sed修改
sed -i '46 s#basedir=#basedir=/usr/local/mysql#' /etc/rc.d/init.d/mysqld
sed -i '47 s#datadir=#datadir=/usr/local/mysql/data#' /etc/rc.d/init.d/mysqld

7、修改MySQL启动脚本mysqld_safe,以支援TCMalloc,编辑文件/usr/local/mysql/bin/mysqld_safe,在# executing mysqld_safe的下一行,增加:#export LD_PRELOAD=/usr/local/lib/libtcmalloc.so 这里直接用sed修改了
sed -i '/# executing mysqld_safe/a\export LD_PRELOAD=/usr/local/lib/libtcmalloc.so' /usr/local/mysql/bin/mysqld_safe

8、收尾工作
echo 'PATH=$PATH:$HOME/bin:/usr/local/bin:/usr/local/mysql/bin' >> ~/.bashrc
source ~/.bash_profile
echo "/usr/local/mysql/lib" > /etc/ld.so.conf.d/mysql.conf
ldconfig
if [ `getconf WORD_BIT` = '32' ] && [ `getconf LONG_BIT` = '64' ] ; then
cd /usr/local/mysql
ln -s lib lib64
chown -R root.mysql lib64
fi

修改mysql root密码,这里使用生成的16位随机数,并将密码保存到/root/.my.cnf,这样管理员通过终端可直接跳过输入密码管理mysql服务(生产环境请不要这样做)。
service mysqld start
mysqlroot_passwd=`cat /dev/urandom | head -1 | md5sum | head -c 16`
echo $mysqlroot_passwd
/usr/local/mysql/bin/mysql -uroot -p
mysql<<EOF
use mysql;
update \`mysql\`.\`user\` set \`password\`=PASSWORD('$mysqlroot_passwd') where \`User\`='root';
flush privileges;
EOF
cat > /root/.my.cnf<<EOF
[client]
user=root
password=$mysqlroot_passwd
EOF
service mysqld stop

chmod 750 /usr/local/mysql /usr/local/mysql/data
chmod 640 /etc/my.cnf
chmod 600 /root/.my.cnf

三、安装Jailkit,Jailkit可以限制普通用户执行SSH时的家目录,旧版本会有一些问题,但最近这两年相当稳定,因此我在很多服务器都将其作为chroot必备的组件。后面php-fpm进行chroot设置时,也可以直接套用在这个基础上,因此这里先安装Jailkit。
1、安装最新版Jailkit,当前版本为2.16
cd /usr/local/src
wget -c http://olivier.sessink.nl/jailkit/jailkit-2.16.tar.gz
tar -zxf jailkit-2.16.tar.gz
cd jailkit-2.16
./configure
#sed -i '41 s#IBS =#IBS = -pthread#' src/Makefile
make && make install
设置开机启动
/usr/bin/install -m 755 extra/jailkit /etc/init.d/jailkit
chkconfig jailkit on
service jailkit start

2、创建chroot工作目录并设置权限,这里设置为/home/chroot
mkdir /home/chroot
chown root:root /home/chroot
chmod 751 /home/chroot
jk_init -v -j /home/chroot sftp scp jk_lsh extshellplusnet
jk_cp -v /home/chroot /usr/bin/id
jk_cp -v /home/chroot /usr/bin/unzip
jk_cp -v /home/chroot /usr/bin/zip
jk_cp -v /home/chroot /usr/bin/curl
jk_cp -v /home/chroot /etc/pki
jk_cp -v /home/chroot /usr/lib/libssh2.so.1
jk_cp -v /home/chroot /usr/lib/libcurl.so
jk_cp -v /home/chroot /usr/lib/libsoftokn3.so
jk_cp -v /home/chroot /usr/lib/libnssdbm3.so
jk_cp -v /home/chroot /usr/lib/libnss3.so
jk_cp -v /home/chroot /usr/lib/libnssckbi.so
jk_cp -v /home/chroot /usr/lib/libnsspem.so
jk_cp -v /home/chroot /usr/lib/libsmime3.so
jk_cp -v /home/chroot /usr/lib/libssl3.so
jk_cp -v /home/chroot /usr/lib64/libssh2.so.1
jk_cp -v /home/chroot /usr/lib64/libcurl.so
jk_cp -v /home/chroot /usr/lib64/libsoftokn3.so
jk_cp -v /home/chroot /usr/lib64/libnssdbm3.so
jk_cp -v /home/chroot /usr/lib64/libnss3.so
jk_cp -v /home/chroot /usr/lib64/libnssckbi.so
jk_cp -v /home/chroot /usr/lib64/libnsspem.so
jk_cp -v /home/chroot /usr/lib64/libsmime3.so
jk_cp -v /home/chroot /usr/lib64/libssl3.so
jk_cp -v /home/chroot /usr/bin/certutil
jk_cp -v /home/chroot /usr/bin/cmsutil
jk_cp -v /home/chroot /usr/bin/crlutil
jk_cp -v /home/chroot /usr/bin/modutil
jk_cp -v /home/chroot /usr/bin/pk12util
jk_cp -v /home/chroot /usr/bin/signtool
jk_cp -v /home/chroot /usr/bin/signver
jk_cp -v /home/chroot /usr/bin/ssltap
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/atob
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/btoa
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/derdump
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/ocspclnt
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/pp
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/selfserv
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/strsclnt
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/symkeyutil
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/tstclnt
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/vfychain
jk_cp -v /home/chroot /usr/lib/nss/unsupported-tools/vfyserv
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/atob
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/btoa
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/derdump
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/ocspclnt
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/pp
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/selfserv
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/strsclnt
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/symkeyutil
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/tstclnt
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/vfychain
jk_cp -v /home/chroot /usr/lib64/nss/unsupported-tools/vfyserv
mkdir -p {/home/chroot/opt,/home/chroot/tmp,/home/chroot/var/www}
chmod -R 755 /home/chroot/opt /home/chroot/var/www
chmod 1777 /home/chroot/tmp
echo "nobody:x:99:" >> /home/chroot/etc/group
echo "www:x:999:" >> /home/chroot/etc/group
echo "www:x:999:999::/home/www:/bin/nologin" >> /home/chroot/etc/passwd
chmod 644 /home/chroot/etc/group
chmod 644 /home/chroot/etc/passwd

3、修改监听chroot下的日志输出,方便debug
service rsyslog stop
rsyslogd -a /home/chroot/dev/log
service rsyslog restart

4、安装mini_sendmail,chroot环境下使用
#must install glibc-static under RHEL 6
yum install -y glibc-static
cd /usr/local/src
wget -c http://www.acme.com/software/mini_sendmail/mini_sendmail-1.3.6.tar.gz
tar -zxf mini_sendmail-1.3.6.tar.gz
cd mini_sendmail-1.3.6
wget -c http://dl.icodex.org/mini_sendmail_1.3.6.patch.tar.gz
tar -zxf mini_sendmail_1.3.6.patch.tar.gz
patch -p0 < mini_sendmail_1.3.6.patch
make
/usr/bin/install -m 755 mini_sendmail /home/chroot/usr/sbin/sendmail

四、编译PHP,这里选择了最新版本5.4.19。
1、首先创建用户
/usr/sbin/groupadd -g 999 -o -r www
/usr/sbin/useradd -M -g www -o -r -d /var/www/html -s /bin/false -c "Web Server" -u 999 www

2、开始编译
cd /usr/local/src
wget http://www.php.net/get/php-5.4.19.tar.bz2/from/hk2.php.net/mirror
tar -jxf php-5.4.19.tar.bz2
cd php-5.4.19/
if [ `getconf WORD_BIT` = '32' ] && [ `getconf LONG_BIT` = '64' ] ; then withlib="--with-libdir=lib64" ; else withlib="--with-libdir=lib" ; fi
./configure --prefix=/usr/local/php5.4 --with-config-file-path=/usr/local/php5.4/etc --with-iconv-dir --with-freetype-dir --with-jpeg-dir --with-png-dir --with-libxml-dir --with-pcre-regex --enable-xml --disable-phar --disable-rpath --enable-calendar --enable-bcmath --enable-calendar --enable-shmop --enable-sysvsem --enable-inline-optimization --with-curl --with-curlwrappers --enable-mbregex --with-ldap --with-ldap-sasl --enable-exif --enable-soap --enable-fpm --with-fpm-user=www --with-fpm-group=www --enable-soap --with-snmp --enable-wddx --enable-mbstring --with-mcrypt --enable-ftp --with-gd --enable-gd-native-ttf --enable-gd-jis-conv --with-openssl --with-mhash --enable-mysqlnd --with-mysql=mysqlnd --with-mysqli=mysqlnd --with-pdo-mysql=mysqlnd --enable-pdo --with-sqlite3 --with-pdo-sqlite --enable-pcntl --enable-sockets --with-xmlrpc --with-imap --with-imap-ssl --with-kerberos --with-tidy --with-bz2 --enable-zip --with-zlib --with-zlib-dir --enable-tokenizer --without-pear --with-gettext --disable-ipv6 --disable-debug $withlib
make ZEND_EXTRA_LIBS='-liconv'
make install

3、设置开机启动脚本
/usr/bin/install -m 755 sapi/fpm/init.d.php-fpm /etc/rc.d/init.d/php-fpm
sed -i '/### END INIT INFO/a\umask 072' /etc/rc.d/init.d/php-fpm # 该项是为了使chroot环境下php进程创建的文件(包括临时文件、上传的文件等)符合基本安全权限进行的设置
/sbin/chkconfig --add php-fpm
/sbin/chkconfig php-fpm on

4、安装pear,新版本编译安装时都没pear了
cd /usr/local/src
wget http://pear.php.net/go-pear.phar
/usr/local/php5.4/bin/php go-pear.phar

5、设置php.ini和常用的两个软链接
/bin/cp php.ini-production /usr/local/php5.4/etc/php.ini
ln -s /usr/local/php5.4/bin/php /usr/bin/php
ln -s /usr/local/php5.4/bin/phpize /usr/bin/phpize

6、创建php-fpm配置文件
mkdir /usr/local/php5.4/etc/fpm.d
cat >/usr/local/php5.4/etc/php-fpm.conf <<EOF
include=etc/fpm.d/*.conf
[global]
pid = run/php-fpm.pid
error_log = log/php-fpm.log
log_level = warning
emergency_restart_threshold = 10
emergency_restart_interval = 1m
process_control_timeout = 5s
process.max = 500
daemonize = yes
rlimit_files = 51200
rlimit_core = 0
events.mechanism = epoll
EOF

设置第一个php-fpm pool,文件名default.conf。
cat >/usr/local/php5.4/etc/fpm.d/default.conf <<EOF
[www]
listen = 127.0.0.1:9001
;listen = /usr/local/php5.4/var/run/php-fpm-www.sock
listen.allowed_clients = 127.0.0.1
listen.backlog = 8192
listen.mode = 0666
listen.owner = www
listen.group = nobody
user = www
group = nobody

chroot = /home/chroot
; Choose how the process manager will control the number of child processes.
pm = static
pm.max_children = 1
pm.start_servers = 1
pm.min_spare_servers = 1
pm.max_spare_servers = 1
pm.max_requests = 1000
request_terminate_timeout = 120s

; Pass environment variables
env[HOSTNAME] = \$HOSTNAME
env[PATH] = /usr/local/bin:/bin
env[TMP] = /var/www/tmp
env[TMPDIR] = /var/www/tmp
env[TEMP] = /var/www/tmp

; Specific php ini settings here
php_value[sendmail_path] = "/usr/sbin/sendmail -t -i -f noreply@evlit.com"
php_admin_value[open_basedir] = ".:/var/www:/proc:/tmp"
php_value[include_path] = ".:/var/www:/var/www/include"
php_value[axis2.log_path] = "/var/www/tmp"
php_value[session_pgsql.sem_file_name] = "/var/www/tmp/php_session_pgsql"
php_value[soap.wsdl_cache_dir] = "/var/www/tmp"
php_value[uploadprogress.file.filename_template] = "/var/www/tmp/upt_%s.txt"
php_value[xdebug.output_dir] = "/var/www/tmp"
php_value[xdebug.profiler_output_dir] = "/var/www/tmp"
php_value[xdebug.trace_output_dir] = "/var/www/tmp"
;php_admin_value[disable_functions] = "exec,system,passthru,shell_exec,ini_alter,dl,proc_open,proc_exec,proc_close,chroot,scandir,chgrp,chown,ini_restore,dbmopen,dbase_open,curl_multi_exec,multi_exec,gzinflate,parse_ini_file,show_source,escapeshellarg,escapeshellcmd,stream_socket_server,popepassthru,pfsockopen,set_time_limit"

; UPLOAD
php_admin_flag[file_uploads] = On
php_admin_value[upload_tmp_dir] = "/var/www/tmp"
;Maximum allowed size for uploaded files.
php_admin_value[upload_max_filesize] = "50M"
php_admin_value[max_input_time] = "120"
php_admin_value[post_max_size] = "50M"

; LOGS
php_admin_value[error_log] = "/var/www/logs/error.log"
php_admin_value[log_errors] = On
php_admin_value[display_errors] = Off
php_admin_value[html_errors] = Off
php_admin_value[display_startup_errors] = Off
php_admin_value[define_syslog_variables] = "1"
php_value[error_reporting] = "6143"

; Maximum execution time of each script, in seconds (30)
php_value[max_input_time] = "120"
; Maximum amount of time each script may spend parsing request data
php_value[max_execution_time] = "300"
; Maximum amount of memory a script may consume (8MB)
php_value[memory_limit] = "128M"

; Sessions: IMPORTANT reactivate garbage collector on Debian!!!
php_value[session.gc_maxlifetime] = "3600"
php_admin_value[session.gc_probability] = "1"
php_admin_value[session.gc_divisor] = "100"

; SECURITY
php_admin_value[session.auto_start] = Off
php_admin_value[mbstring.http_input] = pass
php_admin_value[mbstring.http_output] = pass
php_admin_value[mbstring.encoding_translation] = Off
php_admin_value[expose_php] = Off
php_admin_value[allow_url_fopen] = On
php_admin_value[variables_order] = PGCSE

; enforce filling PATH_INFO & PATH_TRANSLATED
; and not only SCRIPT_FILENAME
php_admin_value[cgi.fix_pathinfo] = "1"
; 1: will use PATH_TRANSLATED instead of SCRIPT_FILENAME
php_admin_value[cgi.discard_path] = "0"
EOF

mkdir -p {/var/www/tmp,/var/www/html,/var/www/logs}
chown -R www.www /var/www
chmod 751 /var/www /var/www/html /var/www/logs
mv /var/www /home/chroot/var/www
rm -rf /var/www
ln -s /home/chroot/var/www /var/www

设置fpm.d目录权限,防止被其他用户访问到
chmod 750 /usr/local/php5.4/etc/fpm.d

7、杂项,安装php扩展库和设置php.ini
cd /usr/local/src
wget http://pecl.php.net/get/memcache-3.0.6.tgz
tar -zxf memcache-3.0.6.tgz
cd memcache-3.0.6
/usr/local/php5.4/bin/phpize
./configure --with-php-config=/usr/local/php5.4/bin/php-config
make && make install

cat >>/usr/local/php5.4/etc/php.ini < <EOF
; Memcache Setting
extension="memcache.so"
memcache.allow_failover="1"
memcache.max_failover_attempts="20"
memcache.chunk_size="32768"
memcache.default_port="11211"
memcache.hash_strategy="standard"
memcache.hash_function="crc32"

EOF

cd /usr/local/src/
wget -c http://dl.icodex.org/files/ZendGuardLoader-70429-PHP-5.4-linux-glibc23-x86_64.tar.gz
tar -zxf ZendGuardLoader-70429-PHP-5.4-linux-glibc23-x86_64.tar.gz
cp ZendGuardLoader-70429-PHP-5.4-linux-glibc23-x86_64/php-5.4.x/ZendGuardLoader.so /usr/local/php5.4/include/php/Zend/
cat >>/usr/local/php5.4/etc/php.ini< <EOF
[ZendGuardLoader]
zend_extension="/usr/local/php5.4/include/php/Zend/ZendGuardLoader.so"
zend_loader.enable=1
zend_loader.disable_licensing=0
zend_loader.obfuscation_level_support=3
zend_loader.license_path=
EOF

sed -i 's#; extension_dir = "./"#extension_dir = "/usr/local/php5.4/lib/php/extensions/no-debug-non-zts-20100525/"#' /usr/local/php5.4/etc/php.ini
sed -i 's#;include_path = ".:/php/includes"#include_path = ".:/usr/local/php5.4/lib/php/:/usr/local/php5.4/share/pear"#g' /usr/local/php5.4/etc/php.ini
sed -i 's/post_max_size = 8M/post_max_size = 50M/g' /usr/local/php5.4/etc/php.ini
sed -i 's/upload_max_filesize = 2M/upload_max_filesize = 50M/g' /usr/local/php5.4/etc/php.ini
sed -i 's#;upload_tmp_dir =#upload_tmp_dir = /tmp/#g' /usr/local/php5.4/etc/php.ini
#sed -i 's/disable_functions =/disable_functions = exec,system,passthru,shell_exec,escapeshellcmd,ini_alter,dl,proc_open,proc_exec,proc_close,chown,ini_restore,dbmopen,dbase_open,curl_multi_exec,multi_exec,gzinflate,parse_ini_file,show_source,escapeshellarg,escapeshellcmd,stream_socket_server,popepassthru,pfsockopen,set_time_limit/g' /usr/local/php5.4/etc/php.ini
sed -i 's/;date.timezone =/date.timezone = PRC/g' /usr/local/php5.4/etc/php.ini
sed -i 's/short_open_tag = Off/short_open_tag = On/g' /usr/local/php5.4/etc/php.ini
sed -i 's/max_execution_time = 30/max_execution_time = 300/g' /usr/local/php5.4/etc/php.ini

五、编译nginx,引入两个模块,因基本缓存需要而增加了ngx_cache_purge,因rewrite的需要而增加pcre库。
1、编译最新版nginx,加入SPDY模块
rpm -Uvh http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/ius-release-1.0-11.ius.el6.noarch.rpm
yum install git gcc-c++ make pcre-devel openssl-devel libxslt-devel gd-devel zlib-devel geoip-devel yum-plugin-replace
yum replace openssl --replace-with=openssl10 --enablerepo=ius-testing
cd /usr/local/src
wget -c http://nginx.org/download/nginx-1.4.2.tar.gz
wget -c http://labs.frickle.com/files/ngx_cache_purge-2.1.tar.gz
wget -c http://sourceforge.net/projects/pcre/files/pcre/8.32/pcre-8.32.tar.gz/download
tar -zxf Nginx-accesskey-2.0.3.tar.gz
tar -zxf pcre-8.32.tar.gz
tar -zxf ngx_cache_purge-2.1.tar.gz
tar -zxf nginx-1.4.2.tar.gz
cd /usr/local/src/nginx-1.4.2
./configure --user=www --group=www --prefix=/usr/local/nginx --sbin-path=/usr/sbin/nginx --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_spdy_module --with-http_realip_module --with-http_sub_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_stub_status_module --with-http_addition_module --with-google_perftools_module --add-module=/usr/local/src/ngx_cache_purge-2.1 --with-pcre=/usr/local/src/pcre-8.32 --with-debug
make && make install
mkdir /usr/local/nginx/conf/vhosts

2、创建开机启动init脚本
wget -O /etc/rc.d/init.d/nginx http://dl.icodex.org/init.nginx
chmod +x /etc/rc.d/init.d/nginx
chkconfig --add nginx
chkconfig nginx on
service nginx start

3、设置nginx配置文件和几个在运行中可能引入的配置
cat >/usr/local/nginx/conf/fastcgi.inc <<EOF
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE "nginx";

fastcgi_param QUERY_STRING \$query_string;
fastcgi_param REQUEST_METHOD \$request_method;
fastcgi_param CONTENT_TYPE \$content_type;
fastcgi_param CONTENT_LENGTH \$content_length;

fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
fastcgi_param SCRIPT_NAME \$fastcgi_script_name;
fastcgi_param REQUEST_URI \$request_uri;
fastcgi_param DOCUMENT_URI \$document_uri;
fastcgi_param DOCUMENT_ROOT \$document_root;
fastcgi_param SERVER_PROTOCOL \$server_protocol;

fastcgi_param REMOTE_ADDR \$remote_addr;
fastcgi_param REMOTE_PORT \$remote_port;
fastcgi_param SERVER_ADDR \$server_addr;
fastcgi_param SERVER_PORT \$server_port;
fastcgi_param SERVER_NAME \$server_name;

fastcgi_param HTTPS \$https if_not_empty;
fastcgi_param HTTP_ACCEPT_ENCODING invalid;

# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;

try_files \$fastcgi_script_name =404;
EOF

cat >/usr/local/nginx/conf/fastcgi_cache.inc <<EOF
fastcgi_cache fastcgi;
fastcgi_cache_key \$request_method\$scheme\$host\$request_uri;
#fastcgi_cache_purge fastcgi \$request_method\$scheme\$host\$1;
fastcgi_cache_min_uses 1;
fastcgi_cache_valid 200 302 10m;
fastcgi_cache_valid 301 1h;
fastcgi_cache_valid any 1m;
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_cache_bypass \$skip_cache;
fastcgi_no_cache \$skip_cache;
add_header Nginx-Cache "$upstream_cache_status";
EOF

cat >/usr/local/nginx/conf/proxy.inc <<EOF
proxy_connect_timeout 600s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
proxy_buffer_size 64k;
proxy_buffers 32 32k;
proxy_busy_buffers_size 128k;
#proxy_pass http://127.0.0.1:81;
proxy_redirect off;
proxy_hide_header Vary;
proxy_set_header Accept-Encoding '';
proxy_ignore_headers Cache-Control Expires;
proxy_set_header Host \$host;
proxy_set_header Referer \$http_referer;
proxy_set_header Cookie \$http_cookie;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
proxy_pass_header Set-Cookie;
proxy_next_upstream error timeout invalid_header http_500 http_503 http_404;
client_max_body_size 100m;
client_body_buffer_size 128k;
add_header X-Via "CWS/2.2";
proxy_hide_header X-AspNet-Version;
proxy_hide_header X-Powered-By;
proxy_hide_header X-Varnish;
proxy_hide_header Age;
proxy_hide_header Via;
proxy_hide_header X-Via;
EOF

cat >/usr/local/nginx/conf/proxy_cache.inc <<EOF
proxy_cache proxy;
proxy_cache_key \$host\$uri\$is_args\$args;
#proxy_cache_purge proxy \$host\$1\$is_args\$args;
proxy_cache_min_uses 1;
proxy_cache_valid 200 301 302 1h;
proxy_cache_valid any 1m;
proxy_cache_use_stale error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_temp_file_write_size 64k;
proxy_max_temp_file_size 100m;
proxy_cache_bypass \$cookie_nocache \$arg_nocache \$arg_comment;
proxy_no_cache \$cookie_nocache \$arg_nocache \$arg_comment;
proxy_cache_bypass \$http_pragma \$http_authorization;
proxy_no_cache \$http_pragma \$http_authorization;
proxy_cache_bypass \$skip_cache;
proxy_no_cache \$skip_cache;
add_header Nginx-Cache "$upstream_cache_status";
EOF

cat >/usr/local/nginx/conf/fastcgi_purge_cache.inc <<EOF
set \$skip_cache 0;

# POST requests and urls with a query string should always go to PHP
if ( \$request_method = POST ) {
set \$skip_cache 1;
}
if ( \$query_string != "" ) {
set \$skip_cache 1;
}

if ( \$request_method = "PURGE" ) {
rewrite ^(.*) /purge\$1 last;
}

location ~ /purge(/.*) {
allow all;
fastcgi_cache_purge fastcgi \$request_method\$scheme\$host\$1;
error_page 405 =200 /purge\$1;
add_header Nginx-Cache "Purged";
}
EOF

cat >/usr/local/nginx/conf/proxy_purge_cache.inc <<EOF
set \$skip_cache 0;

# POST requests and urls with a query string should always go to PHP
if ( \$request_method = POST ) {
set \$skip_cache 1;
}
if ( \$query_string != "" ) {
set \$skip_cache 1;
}

if ( \$request_method = "PURGE" ) {
rewrite ^(.*) /purge\$1 last;
}

location ~ /purge(/.*) {
allow all;
proxy_cache_purge proxy \$host\$1\$is_args\$args;
error_page 405 =200 /purge\$1;
add_header Nginx-Cache "Purged";
}
EOF

cat >/usr/local/nginx/conf/nginx.conf <<EOF
user www;
google_perftools_profiles /tmp/tcmalloc;
#worker_cpu_affinity 01 10;
# no need for more workers in the proxy mode
worker_processes 1;
#error_log /var/log/nginx/error.log info;
error_log /dev/null info;
worker_rlimit_nofile 5120;
events {
worker_connections 5120; # increase for busier servers
use epoll; # you should use epoll here for Linux kernels 2.6.x
}
http {
access_log off;
log_format bytes "\$bytes_sent";
server_name_in_redirect off;
server_names_hash_max_size 2048;
server_names_hash_bucket_size 256;
server_tokens off;
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
client_header_timeout 60s;
client_body_timeout 60s;
send_timeout 600s;
reset_timedout_connection on;
keepalive_timeout 5 60;
# keepalive_requests 100;
# keepalive_timeout 0;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_keep_conn on;
fastcgi_buffer_size 16k;
fastcgi_buffers 16 16k;
fastcgi_busy_buffers_size 32k;
fastcgi_temp_file_write_size 32k;
fastcgi_intercept_errors on;
open_file_cache max=51200 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 1;
ssi on;
ssi_silent_errors on;
ssi_types text/shtml;
gzip on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";
gzip_vary on;
gzip_http_version 1.0;
gzip_min_length 1100;
gzip_comp_level 6;
gzip_buffers 16 16k;
gzip_proxied any;
gzip_types application/ecmascript;
gzip_types application/javascript;
gzip_types application/pdf;
gzip_types application/postscript;
gzip_types image/svg+xml;
gzip_types text/plain;
gzip_types text/css;
gzip_types text/csv;
gzip_types application/json;
gzip_types application/x-javascript;
gzip_types text/xml;
gzip_types application/xml;
gzip_types application/xml+rss;
gzip_types text/javascript;
connection_pool_size 256;
client_max_body_size 100m;
client_body_buffer_size 128k;
client_header_buffer_size 4k;
large_client_header_buffers 4 4k;
request_pool_size 32k;
output_buffers 4 32k;
postpone_output 1460;
client_body_temp_path /tmp/nginx_client;
proxy_temp_path /tmp/nginx_proxy;
fastcgi_temp_path /tmp/nginx_fastcgi;
uwsgi_temp_path /tmp/nginx_uwsgi;
scgi_temp_path /tmp/nginx_scgi;
proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=proxy:50m inactive=30m max_size=2m;
fastcgi_cache_path /var/cache/nginx/fastcgi_cache levels=1:2 keys_zone=fastcgi:50m inactive=30m max_size=2m;
limit_conn_zone \$binary_remote_addr zone=one:10m;

set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

include "/usr/local/nginx/conf/proxy/*.conf";
include "/usr/local/nginx/conf/vhosts/*.conf";
}
EOF

4、创建默认虚拟主机
cat >/usr/local/nginx/conf/vhosts/default.conf <<EOF
server {
listen 80 default;
listen 8080 default;
server_name _;
access_log /var/log/nginx/default-access.log combined;
error_log /var/log/nginx/default-error.log;
root /var/www/html;
index index.html index.htm index.php;
charset utf-8;

include fastcgi_purge_cache.inc;

if (-d \$request_filename){
rewrite ^/(.*)([^/])\$ \$scheme://\$host/\$1\$2/ permanent;
}

#include /var/www/html/nginx.conf;

location / {
rewrite ^/\$ http://www.google.com/ncr permanent;
}

error_page 404 http://www.google.com/ncr;

location ~* \.php {
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
include fastcgi.inc;
include fastcgi_cache.inc;
#fastcgi_param HTTPS on;
}

location ~* \.(ftpquota|htaccess|htpasswd|asp|aspx|jsp|asa|mdb)?\$ {
deny all;
}
}
EOF

5、杂项,修改配置路径及日志路径的目录权限
find /usr/local/nginx/conf/ -type f -exec chmod 0640 {} \;
find /usr/local/nginx/conf/ -type d -exec chmod 0750 {} \;
chmod 750 /var/log/nginx

6、测试
启动php-fpm和nginx,然后建立第一个网站路径
service php-fpm start
service nginx start

写个输出phpinfo的php
cat > /var/www/html/phpinfo.php <<EOF
< ?php
phpinfo();
?>
EOF

或者可以传个小马上来测试,比如下面这个一句话小马
cat > /var/www/html/t.php <<EOF
< ?php
\$run = \$_GET['r'];
echo \`\$run\`;
?>
EOF

打开浏览器,直接用小马探测下
比如执行pwd命令 http://ip/t.php?r=pwd
再比如执行ls命令 http://ip/t.php?r=ls

六、编译ftp软件Pure-FTPD,鉴权直接使用系统passwd,如果要配合其他程序,建议修改为mysql鉴权
1、开始编译
cd /usr/local/src/
wget http://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.36.tar.gz
tar -zxvf pure-ftpd-1.0.36.tar.gz
cd pure-ftpd-1.0.36/
./configure --prefix=/usr/local/pureftpd --with-puredb --with-shadow --with-pam --with-paranoidmsg --with-welcomemsg --with-uploadscript --with-cookie --with-virtualchroot --with-virtualhosts --with-virtualchroot --with-diraliases --with-quotas --with-sysquotas --with-ratios --with-ftpwho --with-throttling --with-tls --with-rfc2640 --with-bonjour
make && make install
/usr/bin/install -m 755 configuration-file/pure-config.pl /usr/local/pureftpd/sbin/pure-config.pl
mkdir -p {/usr/local/pureftpd/etc/,/var/ftp}
/usr/bin/install -m 644 configuration-file/pure-ftpd.conf /usr/local/pureftpd/etc/pure-ftpd.conf

2、创建开机启动init脚本
/usr/bin/install -m 755 contrib/redhat.init /etc/rc.d/init.d/pureftpd
chkconfig --add pureftpd
chkconfig --level 2345 pureftpd on

3、修改Pure-FTPD配置
sed -i '143 s/# //' /usr/local/pureftpd/etc/pure-ftpd.conf
sed -i '180 s/# //' /usr/local/pureftpd/etc/pure-ftpd.conf
sed -i '246 s/no/yes/' /usr/local/pureftpd/etc/pure-ftpd.conf
sed -i '336 s/#//' /usr/local/pureftpd/etc/pure-ftpd.conf
sed -i '351 s/#//' /usr/local/pureftpd/etc/pure-ftpd.conf

为FTP用户设置umask值
sed -i '234 s#133:022#173:072#' /usr/local/pureftpd/etc/pure-ftpd.conf

4、创建软链接及密码文件
ln -s /usr/local/pureftpd/sbin/pure-config.pl /usr/local/sbin/pure-config.pl
ln -s /usr/local/pureftpd/bin/pure-pw /usr/local/bin/pure-pw
ln -s /usr/local/pureftpd/sbin/pure-ftpwho /usr/local/sbin/pure-ftpwho
ln -s /usr/local/pureftpd/etc/pure-ftpd.conf /etc/pure-ftpd.conf

5、杂项,将日志从系统syslog中剥离开来
sed -i '42 s/cron.none/cron.none;ftp.none/' /etc/rsyslog.conf
echo "ftp.* -/var/log/pureftpd.log" >> /etc/rsyslog.conf
service rsyslog restart

七、最后启用所有服务
service mysqld start
service php-fpm start
service nginx start
service pureftpd start

快速创建用户的脚本,请下载此文件,放在/usr/local/sbin路径下
# cd /tmp;wget -O /usr/local/sbin/Modify http://dl.icodex.org/Modify.sh;chmod a+rx /usr/local/sbin/Modify
并赋予执行权限,使用方法:# Modify {create|chpasswd|remove}
例如创建一个用户为demo,绑定域名domain.com 执行<code># Modify create demo domain.com
执行后会随机生成16位密码,这个密码可以用于ftp登录、shell登录及数据库用户(创建的数据库名为demo_sql,数据库地址127.0.0.1)
修改密码 执行# Modify chpasswd demo
删除用户 执行# Modify remove demo

编译过程可能会遇到错误,根据出错提示到Google搜索解决方法(例如CentOS 库文件支持的问题),应该可以很容易找到问题点的。

原文:http://blog.icodex.org/2012/09/lnmp多用户安全运行环境-chroot/

  • 转载请注明来源:IT学习网 网址:http://www.t086.com/ 向您的朋友推荐此文章
  • 特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系我们,我们会尽快予以更正。
更多
留言建议ASP探针PHP探针站长Enjoy的Blog
© 2017 T086学习网 - T086.com(原itlearner.com)
RunTime:10.88ms QueryTime:7