Research on Security Configuration of lnmp Virtual Host
0x00 background
As we all know, the security of virtual hosts is not good, especially preventing cross-directory attacks from becoming the focus. Apache + php servers are relatively simple to prevent cross-directory approaches. All mature web hosting solutions on the Internet are based on apache, such as directadmin and cpanel.
However, today is no longer the apache era. in linux + nginx + mysql + php, how can we prevent different virtual hosts from cross-site?
First, we need to clearly understand how Nginx runs, and then consider how to perform it. There is a good article: http://www.bkjia.com/Article/201403/289530.html, introduced the nginx security configuration, you can look.
Nginx is actually a reverse proxy server. After receiving the request, it will check whether the current request is a. php file. If so, it will be transferred to php-fpm for processing. After obtaining the result, it will be sent to the user. Therefore, you have two permissions: nginx permission and php-fpm permission. For example, nginx and php-fpm both need to read this file, so permission allocation is an important consideration.
There are three defense measures for Cross-Site defense. The first is to prevent other users from listing website directories, to prevent some of their sensitive file names from being seen and accessed, and the second is to prevent other users from reading their own files, prevent configuration information leakage. Third, prevent other users from writing shells to their directories.
Php has clearly considered this issue. open_basedir in its configuration file is a directory list that only allows php to access the given directory. By setting this open_basedir, we can defend php against reading and writing files outside the web directory, such as/etc/passwd.
But now the problem is that open_basedir is written in php. one configuration file in ini, and all virtual hosts use the same php. We can prevent php from accessing files outside the web directory, however, "VM 1" cannot prevent access to "VM 2" files because both files are in the web directory. Another bigger problem is that open_basedir of many php versions is unreliable and can be easily bypassed.
This is a problem. Solution: Enable each VM to start php-fpm independently with different users.
To implement the above method, we need to make some modifications to the installed lnmp. (I am using the widely used "lnmp one-key installation package" in China ").
0x01 lNMP reinforcement
For example, we have two virtual hosts, game01.com and game02.com, whose directories are/home/wwwroot/game01/AND/home/wwwroot/game02 /.
Here, the new version of the lnmp one-click installation package has its own anti-Cross-Site function, because php 5.3.3 and later can be added with the following statement at the end of php. ini:
[HOST=www.vpser.net] open_basedir=/home/wwwroot/www.vpser.net/:/tmp/ [PATH=/home/wwwroot/www.vpser.net] open_basedir=/home/wwwroot/www.vpser.net/:/tmp/
You can assign different open_basedir to different hosts. However, we don't need this method here. The first method is to restrict php versions above 5.3.3, and the second open_basedir is also limited and vulnerable, so we cannot rely solely on it. After the VM is created, comment out the content in/usr/local/php/etc/php. ini. (Annotator ;)
First, let different virtual machines run with different php-fpm:
1. Create a php-fpm.pid file for each site
cd /usr/local/php5/var/runtouch php-fpm-game01.pidtouch php-fpm-game02.pid
2. Create a php-fpm.conf file for each site
cd /usr/local/php5/etc/ cp php-fpm.conf php-fpm-game01.conf cp php-fpm.conf php-fpm-game02.conf
3. Create a php-cgi.sock file for each site
Touch/tmp/php-cgi-game01.sock # create a php-cgi.sock file chown www. www/tmp/php-cgi-game01.sock # Set the file owner to www (must be consistent with nginx users) touch/tmp/php-cgi-game02.sock chown www. php-cgi-game02.sock/www/tmp/
4. Modify Related Files
vi /usr/local/php5/etc/php-fpm-game01.conf pid = run/php-fpm-game01.pid listen =/tmp/php-cgi-game01.sock; vi /usr/local/php5/etc/php-fpm-game02.confpid = run/php-fpm-game02.pidlisten =/tmp/php-cgi-game02.sock; vi /etc/init.d/php-fpm vhost=$2 php_fpm_CONF=${prefix}/etc/php-fpm-$vhost.conf php_fpm_PID=${prefix}/var/run/php-fpm-$vhost.pid php_opts="-d open_basedir=/home/wwwroot/$vhost/:/tmp/ --fpm-config $php_fpm_CONF"
The last line above is the execution parameter of php-fpm, in which we set open_basedir to/home/wwwroot/$ vhost/:/tmp /, $ vhost is the second parameter $2 (game01 or game02) we passed in during runtime ).
Continue Modification
Vi/usr/local/nginx/conf/vhost/game01.com. conf # configuration file name may be different, according to the actual situation to change fastcgi_pass unix:/tmp/php-cgi-game01.sock; vi/usr/local/nginx/conf/vhost/game02.com. conf fastcgi_pass unix:/tmp/php-cgi-game02.sock;
5. Add boot items
vi /home/start.sh# !/bin/bashauto=$1 /bin/bash /etc/rc.d/init.d/php-fpm $auto game01 /bin/bash /etc/rc.d/init.d/php-fpm $auto game02chmod +x /home/start.sh
Edit/etc/rc. local and add start. sh to the startup Item. At this point, different virtual hosts run different php-fpm. We also need to run it with different user identities.
groupadd game01 groupadd game02 useradd game01 -M -s /sbin/nologin -g game01 useradd game02 -M -s /sbin/nologin -g game02
Added two users: game01.game01 and game02.game02. Modify/usr/local/php/etc/php-fpm-game01.conf:
listen.owner = game01listen.group = game01 user=game01 group=game01
The same is true for game02. In this way, we can run php-fpm with different users.
Go to/home/wwwroot /:
cd /home/wwwroot/ chown game01.game01 -R game01 chown game02.game02 -R game02
Grant the game01 and game02 folders to the user game01 and game02 respectively.
In addition, our nginx is run by default by www users, so we cannot read the game01 and game02 user files. If we set the File Permission to 777, it cannot prevent game01 from reading game02 files.
Therefore, we should add www users to the game01 and game02 groups, and then set the game01 and game02 files to the 750 permissions, in this way, you can allow www to read game01/game02 files (because the group permission is 5 or 5 in the same group) and prevent game01 from reading game02 files.
In linux, you can add a user to multiple groups as follows:
usermod -aG game01 www usermod -aG game02 www
At this time. Our defense actually has two layers.
01. Different php-fpm run php programs on two virtual hosts. They own their own open_basedir, so that they cannot run across directories.
02. Even if open_basedir is bypassed, php-fpm running as a game01 user cannot write or read game02 files because game02 has 750 permissions on all files. Other users do not have any permissions (0 ).
After everything is set up, let's talk about how to use it.
0x02 usage
Kill the existing php-fpm, restart nginx, and then start the new php-fpm at/home/start. sh.
/Etc/init. d/php-fpm start game01 start game01/etc/init separately. d/php-fpm start game02 start game02/etc/init separately. d/php-fpm stop game01 start game01/etc/init separately. d/php-fpm stop game02 start game02 separately
The above is a bit of a patchwork method, which may not be the best method (I am not familiar with the nginx mechanism, maybe there is a simpler way to solve this problem ), so I also hope that the experts can share their O & M methods and point out my shortcomings.
0x03 reference:
Http://www.bkjia.com/Article/201403/289530.html
Http://www.dedecms.com/knowledge/servers/linux-bsd/2012/0819/8389.html
Http://www.bkjia.com/Article/201407/318279.html