In the PHP-FPM to set up chroot, has a good isolation function, improve the system security, but to establish a reasonable PHP-FPMChroot environment is a little difficult, than the use of debootstrap and other tools to build more trouble, this article introduces the Chroot execution environment of PHP-FPM in detail, set up chroot in PHP-FPM, has a good isolation function, improve the security of the system, however, to establish a reasonable PHP-FPM Chroot environment is a little difficult, than the use of debootstrap and other tools to establish more trouble, the following through the reference of relevant information, the PHP-FPM Chroot execution environment to sort out, share with you.
This article takes Ubuntu 14.04.2 as an example, php-fpm uses ppa: ondrej/PHP5.6 version provided by the php5-5.6, it should be consistent with the php-fpm and system directory structure of the system's built-in and Debian systems. Adjust CentOS by yourself.
The chroot environment configuration of php-fpm is not associated with the front-end of the used server, nor does it require Apache/Nginx to perform chroot. Of course, this is more secure-and more complex.
1. create a directory structure
Select/var/www/chroot as the chroot directory, and place the page files in/var/www/chroot/public.
Run the following command to create a basic directory structure:
Bashmkdir-p/var/www/chroot/cd/var/www/chrootmkdir-p public bin dev tmp usr/sbin/usr/share/zoneinfo/var/run/nscd/var /lib/php5/sessions var/wwwcp-a/dev/zero/dev/urandom/dev/null dev/# Note 3 chmod -- reference =/tmp/chmod -- reference = /var/lib/php5/sessions var/lib/php5/sessions # Note 4 chown-R root: root. # Note 2 chown-R www-data: www-data public/# note 2cd var/wwwln-s .. /.. chroot # Note 1
The following is the directory structure, and some new things will be added later:
/Var/www/chroot/── bin ├ ── dev │ ├ ── null │ ├ ── urandom │ zero ── public ├ ── tmp ── usr │ ── sbin │ └ ── share │ └ ── zoneinfo └ ── var ├ ── lib │ └ ── php5 │ └ ── sessions ── run │ └ ── nscd ── www └ ── chroot-> .. /.. # Note 1
Note 1: this soft connection is used to solve the problem that SCRIPT_FILENAME sent from Apache/nginx to php-fpm cannot find the File after entering chroot ("File not found" is returned when accessing the php page.
For nginx, we usually set SCRIPT_FILENAME to $ document_root $ fastcgi_script_name. The Script path passed to php-fpm is/var/www/chroot/public/index. php. Because php-fpm is in the chroot environment, the path it tries to access becomes/var/www/chroot +/var/www/chroot/public/index. of course, php does not exist.
Therefore, if you use a soft connection to link/var/www/chroot in the chroot environment to the root directory, you can access the script normally.
You can also set SCRIPT_FILENAME to/public $ fastcgi_script_name. However, such hard encoding is not conducive to configuration migration. it can only be used in the chroot environment. if you switch back to a non-chroot environment, you need to modify the configuration. We do not recommend that you do this. (By the way, the $ document_root is not used in many old tutorials, and the root directory is hard-coded directly. of course, this is also not desirable)
Note 2: The chroot environment is not 100% secure. Since the execution permission of php-fpm in the chroot environment is www-data, we recommend that you set the owner of unnecessary directories to root to reduce unnecessary access permissions. Chroot is not equal to security. refer to the principles listed in chroot best practices. From a more secure perspective, we 'd better remove the read and write permissions of the bin, lib, sbin, and other directories, leaving only executable permissions, but there is no big difference ......
Note 3: In addition to copying the file content, cp-a also copies information such as the permission and mode of the file, you can easily copy the key device files zero, urandom, and null. Mknod seems to be a more secure method, but cp-a seems okay for me.
Note 4: chmod -- reference = XXX will refer to the permission settings of XXX. Tmp is not mentioned. The key is that var/lib/php5/sessions is the directory where php stores session files, and www-data must have the read and write permissions. We recommend that you take a look at the settings. Of course there will be tests later.
2. configuration of PHP-FPM
Create a new php-fpm execution pool to build the chroot environment. It is not recommended to directly modify the php-fpm.conf, because it takes effect globally and will share a chroot environment if there are multiple php sites.
In fact, many php-fpm tutorials ignore the pool configuration of php-fpm. as a result, many people share a set of configurations for all sites on one server, especially a set of php. ini configuration is actually unreasonable. The pool should be created separately based on the site requirements and the parameters should be adjusted.
Create chroot. conf under/etc/php5/fpm/pool. d/(note that you must end with. conf to be called by the php-fpm.conf ):
[chroot]user = www-datagroup = www-datalisten = /var/run/php-chroot.socklisten.owner = www-datalisten.group = www-datapm = dynamicpm.max_children = 5pm.start_servers = 1pm.min_spare_servers = 1pm.max_spare_servers = 3chroot = /var/www/chrootchdir = /public;security.limit_extensions = .phpphp_flag[display_errors] = onphp_value[date.timezone] = Asia/Hong_Kong;php_admin_value[session.gc_probability] = 1;php_admin_value[open_basedir] = "/tmp/:/public/:/var/www/chroot/public/"
The preceding parameters are familiar. You only need to simply set chroot as the configured environment root directory to enable chroot. After you perform a php5-fpm-t test, use the service php5-fpm reload to enable the new pool. Of course, the backend must be set in the configuration corresponding to Apache/nginx.
The last few lines are mentioned. Display_errors is enabled in the last row, so that you can test the php function under chroot. after the test is complete, remember to comment out the function.
Set session. gc_probability to allow the php process to delete and recycle the session. Under normal circumstances, the session is cleared by the cron task added by php, but it seems that php does not automatically clean the session in the chroot environment. Of course, you can also add automatically executed scripts under cron. d to clear the script, so you do not need to enable this option.
3. Fixed various PHP functions in the Chroot environment.
Create a test. php file under/var/www/chroot/public and write the following content:
The code is as follows:
Php
<? Php
Session_start ();
Header ("Content-Type: text/plain ");
Echo (gethostbyname ("localhost"). "\ n ");
Print_r (getdate ());
Mail ("your @ address", "subject", "message ");
Here we mainly test the functions: session, DNS resolution, time and date, mail () function.
When you access the test page above, the system prompts No such directory or file or Permission denied, indicating that the session configuration is incorrect. If gethostbyname does not return 127.0.0.1 or: 1, DNS resolution does not take effect. The prompt timezone database is UPT indicates that the time and date are incorrect. Mail () also has a variety of error prompts.
The session is not mentioned, and the Directory permission setting is no problem. Mainly deal with the following three problems, which are also the main content to be processed in the php chroot environment.
3.1 domain name resolution/time zone
The solution for mail () is similar, and post-interview. Here are two solutions to the previous domain name resolution and other problems. Method 1 is a simple method for reference to Kienzl, and method 2 is the method used in most tutorials.
Method 1: Use nscd
Nscd is the "Name Service Caching Daemon" of (e) glibc ". In addition to functions such as gethostbyname (), getpwnam () and other functions that need to access/etc/passwd are also processed. (E) glibc accesses nscd's unix socket,/var/run/nscd/socket to obtain the content through nscd. if it cannot be connected to nscd, it will parse it on its own.
That is to say, as long as the nscd is installed and the program in the chroot environment can access the socket connection nscd, the resolution request in the chroot environment can be smoothly transferred from outside the chroot environment. Since/var/run is generally tmpfs, hard links cannot be used across file systems, therefore, you can use mount-bind to mount the/var/run/nscd directory to the same location in the chroot environment.
Similarly, mount the/usr/share/zoneinfo directory to the chroot environment using mount-bind, and set the date in the pool of php-fpm. timezone can solve the time zone issue very directly and violently.
Run apt-get install nscd to install nscd first, and then save the following script as/etc/init. d/php-chroot to make mount-bind run automatically.
bash#!/bin/sh### BEGIN INIT INFO# Provides: php5-fpm-chroot-setup# Required-Start: nscd# Required-Stop:# Default-Start: 2 3 4 5# Default-Stop: 0 1 6# Short-Description: Bind-mounts needed sockets and data into a php-fpm-chroot### END INIT INFOCHROOT=/var/www/chrootDIRS="/var/run/nscd /usr/share/zoneinfo"case "$1" in start) $0 stop 2>/dev/null for d in $DIRS; do mkdir -p "${CHROOT}${d}" mount --bind -o ro "${d}" "${CHROOT}${d}" done ;; stop) for d in $DIRS; do umount "${CHROOT}${d}" done ;; *) echo "Usage: $N {start|stop}" >&2 exit 1 ;;esacexit 0
Run the update-rc.d php-chroot defaults to run the script at startup. If multiple chroot environments and multiple directories require bind-mount, you can add a loop rewrite.
The advantage of this method is that it is easy to copy a large number of configuration files and library files under etc to the chroot environment. The use of nscd also resolves the/etc/passwd and/etc/group problems during domain name access. However, the security of bind-mount and nscd is not definite, so far so good. In addition, mount-bind consumes a certain amount of system resources. some comments say that about one mount consumes about kB of memory, so it is not suitable for a large number of chroot environments (several hundred.
Method 2: Copy the/etc configuration file and library file
This is the most traditional and commonly used method and is relatively complicated. Which configurations are copied and which library files vary with the release version and software version, so it is difficult to determine and debug the files. In addition, once the system is upgraded, the corresponding library files also need to be updated, resulting in a heavy workload. I didn't use this method, but I would like to briefly introduce some more reliable methods.
Domain name resolution. Copy/etc/resolv. conf,/etc/hosts,/etc/nsswitch. conf to The etc directory in the chroot environment. You also need to copy a series of library files, mainly libnss _ *. so, libresolv. so, and libsoftokn3.so. For details about which libnss _ *. so files are copied, you can open nsswitch. conf to see which files are listed.
Time zone configuration. Copy the files in the/etc/localtime,/usr/share/zoneinfo/zone. tab, and/usr/share/zoneinfo directories that use the time zone.
Other common configurations. /Etc/passwd and/etc/group are also sometimes required, but the content may seem to be forged. at least the optional input does not need to be completely copied from the main system.
If problems still occur during use, you can use strace to check which php calls are performed and which library files are used. Run the following command first:
The code is as follows:
Bash
Ps aux | grep php | grep 'chroot' # chroot is the php pool name
View the pool process pid (you can first limit the number of sub-processes to one in the pool settings for debugging ). Then execute:
Bash
Strace-p process pid-o chroot1.txt & # Modify the pid multiple times when multiple sub-processes exist. change the output to chroot2/3.txt and save it to different files.
In this case, execute various functions on the page, check which library files are recorded in the output file, and copy them to the chroot environment.
This method is very troublesome, especially when the first installation setup and subsequent system updates are made. Of course, as an O & M personnel, writing shell scripts to simplify the work is certainly a basic skill. This method has no additional memory consumption and can be used to deploy a large number of chroot environments. of course, the hard disk consumption is much higher, and the security has also been tested for a long time.
3.2 fix mail ()
If you are using WordPress, you can also use plug-ins such as MailChimp to not use the system's own mail service. In fact, due to increasingly strict spam standards and restrictions from VPS host providers, I am more inclined to simply deploy the email service in the system, so php mail () the function is suspended ...... Of course, you can set it easily if needed.
The mail () function of php uses system () to call sendmail for mail sending. Therefore, you must have a sendmail program that can be called in the chroot environment. The common alternative is mini_sendmail. here we will introduce ssmtp and msmtp.
Prerequisites: processing/bin/sh
The command line generated by the system () call is/bin/sh-c command. In the chroot environment, calling an external program must exist/bin/sh, a basic shell. Generally, copy dash:
The code is as follows:
Bash
# Cp/bin/dash/var/www/chroot/bin/sh
Run ldd/bin/dash to check which database files need to be copied. Here, the Echo is:
The code is as follows:
Bash
Ldd/bin/dash
Linux-vdso.so.1 => (0x00007fff779fe000)
Libc. so.6 =>/lib/x86_64-linux-gnu/libc. so.6 (0x00007f165620f000)
/Lib64/ld-linux-x86-64.so.2 (0x00007f16567fc000)
In the first example, only one file name is listed. The basic principle of the remaining library files is that if/lib64 is listed, it will be copied to/lib64 in the chroot environment. if/lib is listed, although there are many releases, most library files include libc. so is in the/lib/x86_64-linux-gnu/directory, also directly copy to the chroot environment/lib directory can be found normally.
But!
The above sentence "must exist/bin/sh, a basic shell" is not true. for mail () as long as there is a program that can accept the command after the-c parameter call. Therefore, Kienzl has written such a program:
c#include
#include
#include
#include
#define MAXARG 64int main( int argc, char* const argv[] ) { char* args[ MAXARG ] = {}; if( argc < 3 || strcmp( argv[1], "-c" ) != 0 ) { fprintf( stderr, "Usage: %s -c
\n", argv[0] ); return 1; } { char* token; int i = 0; char* argStr = strdup( argv[2] ); while( ( token = strsep( &argStr, " " ) ) != NULL ) { if( token && strlen( token ) ) args[ i++ ] = token; if( i >= MAXARG ) return 2; } } return execvp( args[0], args );}
Save it as sh. c and execute: gcc sh. c-o sh-static. then copy sh to the/bin directory of the chroot environment.
To some extent, such an incomplete shell enhances the security of the chroot environment.
Method 1: Use mini_sendmail
Mini_sendmail appears to be created for the chroot environment. After mini_sendmail is called, it will access port 25 of the local machine and send the mail through the local mail service. Therefore, if postfix/exim4 is installed in the main environment, you can use mini_sendmail to send emails in the chroot environment. this is the easiest method.
Installation of mini_sendmail is simple:
The code is as follows:
Bash
Wget http://www.acme.com/software/mini_sendmail/mini_sendmail-1.3.8.tar.gz
Tar zxf mini_sendmail-1.3.8.tar.gz
Cd mini_sendmail-1.3.8
Make
Cp mini_sendmail/var/www/chroot/usr/sbin/sendmail
Modify the Directory of the chroot environment on the last line. Remember to copy the file to the/usr/sbin Directory of the chroot environment and name it sendmail. Otherwise, you need to set the sendmail_path of The ini parameter in the pool to instruct php to find the sendmail program.
Because mini_sendmail is a static link by default, you do not need to copy other library files.
Method 2: Use ssmtp/msmtp
If the mail service is not installed on the local machine, you cannot use mini_sendmail. Both ssmtp and msmtp support sending requests to received emails to other SMTP servers. Note that ssl support requires more complex library files and configurations, so we do not recommend compiling ssl support for both ...... The following describes ssmtp as an example.
Bashwget ftp://ftp.debian.org/debian/pool/main/s/ssmtp/ssmtp_2.64.orig.tar.bz2tar jxf ssmtp_2.64.orig.tar.bz2cd ssmtp_2.64. /configure -- prefix =/# Do not forget prefixmake # Never shake make installcp ssmtp/var/www/chroot/usr/sbinmkdir-p/var/www/chroot/etc/ssmtpcp ssmtp. conf revaliases/var/www/chroot/etc/ssmtp # configuration file cd/var/www/chroot/usr/sbinln-s ssmtp sendmail
Remember ldd and copy the corresponding library file. In addition, ssmtp requires/etc/passwd and/etc/group. if nscd is not used above, you need to copy/forge the two files.
Ssmtp needs to be configured. The ssmtp. conf file is configured as follows:
Bashroot = admin@example.com # In fact this line seems to be able to write mailhub = smtp.example.com # smtp server address hostname = myexample.com # Here hostname seems to be used to generate the default root@myexample.com form of the sender address AuthUser = admin@example.com # use the real logon username AuthPass = password # password FromLineOverride = YES # Allow Sender Rewriting
In revaliases, configure the "sender" address and smtp server address used by each user when using ssmtp. You do not need to configure it, but the file must have it. The specific format is:
The code is as follows:
Bash
# Local user name: sender address: smtp server [: Port (25 by default)]
Root: admin@example.com: smtp.example.com
Www-data: noreply@example.com: smtp.example.com
You can use the chroot command to perform a test:
The code is as follows:
Bash
Chroot/var/www/chroot/bin/sh # at this time,/bin/sh must be the real shell
Echo "Subject: test" | sendmail-v username@server.com # Replace the email address with your own
In this case, the mail () function of php should be available.
4. Other problems
After configuring the chroot environment, remember to disable display_error in the php pool settings.
MySQL connection may encounter problems, because if localhost is entered, php will try to find MySQL unix socket to access mysqld. Enter 127.0.0.1 and use TCP connection.
The directory structure is described as follows:
/Var/www/chroot/── bin │ └ ── sh ├ ── dev │ ├ null │ ── urandom │ zero ├ ── etc │ ── ssmtp │ ── revaliases │ ── ssmtp. conf ├ ── lib │ ── libc. so.6 ── lib64 │ ── ld-linux-x86-64.so.2 ├ ── public ├ ── tmp ├ ── usr │ ├ ── sbin │ ── sendmail-> ssmtp | │ ── ssmtp │ share ── share │ shares ── zoneinfo │ ├ ── directory structure of a large number of time zones │ ── zone. tab ── var ├ ── lib │ └ ── php5 │ └ ── sessions ── run │ └ ── nscd │ ├ ── D. pid │ ── socket └ ── www └ ── chroot-> .. /..
The above is all the content of this article. I hope you will like it.