PHP-FPM chroot Execution Environment _php example

Source: Internet
Author: User
Tags time zones sessions time and date vps hosting
In the php-fpm set up chroot, has a good isolation effect, improve the system security, but to establish a reasonable PHP-FPM chroot environment is a bit more difficult, than with the debootstrap and other tools to establish the trouble, the following through reference to relevant information, The php-fpm of the chroot implementation of the environment to organize out, share to everyone.

This article takes Ubuntu 14.04.2 as an example, PHP-FPM uses the PHP5.6 version provided by ppa:ondrej/php5-5.6, which should be consistent with the system's own and the PHP-FPM and system directory structure of the Debian system. Please adjust the centos yourself.

The chroot environment configuration of the PHP-FPM is not associated with the server front end being used, nor is it forced to Apache/nginx chroot. Of course, that's safer--and more complicated.

1. Create a directory structure

The Chroot directory is selected as/var/www/chroot, where the paging file is placed in/var/www/chroot/public.

Execute the following command to establish 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/#注3chmod--reference=/tmp tmp/chmod--reference=/ Var/lib/php5/sessions var/lib/php5/sessions #注4chown-R root:root.     #注2chown-R www-data:www-data public/#注2cd var/wwwln-s. /.. Chroot     #注1

Here's the directory structure, and then add something new:

/var/www/chroot/├──bin├──dev│├──null│├──urandom│└──zero├──public├──tmp├──usr│├──sbin│└──share│└──zoneinfo └──var├──lib│└──php5│└──sessions├──run│└──nscd└──www└──chroot. /.. #注1

Note 1: This soft connection is used to resolve the problem that the Apache/nginx passed to PHP-FPM Script_filename cannot find the file after entering the chroot (Accessing the PHP page returns "File not Found").

In Nginx, for example, the script_filename is usually set to $document _root$fastcgi_script_name, and the script path passed to PHP-FPM is/var/www/chroot/public/ index.php. And because the PHP-FPM is in the chroot environment, so it actually tries to visit the path to become/var/www/chroot +/var/www/chroot/public/index.php Of course does not exist.

Therefore, using a soft connection to link the/var/www/chroot in the chroot environment to the root directory, the script can be accessed normally.

Of course, you can also set Script_filename to/public$fastcgi_script_name. However, this hard coding is not conducive to the configuration of the migration, only can be used in the chroot environment, switch back to non-chroot environment also need to modify the configuration. So it is not advisable to do so. (By the way, there are many old tutorials also do not use $document _root, directly hardcoded root directory, of course, is also undesirable)

Note The 2:chroot environment is not 100% secure. Because PHP-FPM is www-data in the chroot environment, it is still recommended that the owner of the non-essential directory be set to root to reduce unnecessary access. Chroot is not equal to security, refer to some of the principles outlined in Chroot best practices. From a more secure point of view, it is best to also Bin, Lib, sbin and other directories to remove the read and write permissions, only to leave the executable permission, but there is no big difference ...

Note 3:CP-A In addition to copying the contents of the file will also copy the file permissions, patterns and other information, can be easily copied directly to the zero, urandom and null of the three key device files. Mknod seems to be a much more secure way, but I don't seem to have any problem with cp-a.

Note 4:chmod--reference=xxx will refer to the permissions set after the XXX. TMP does not mention, the key is that the following var/lib/php5/sessions is the directory of PHP storage session files, need to let Www-data have read and write permissions. After the proposal is set, take a look. Of course, there will be tests later.

Configuration of the 2.PHP-FPM

Build a new PHP-FPM execution pool to build the chroot environment. It is not recommended to modify php-fpm.conf directly, because this is the global effect, if there are multiple PHP sites will share a set of chroot environment.

In fact, many php-fpm tutorials ignore the PHP-FPM pool configuration, resulting in a lot of people all sites on a server share a set of configurations, especially a common set of php.ini configuration, is actually unreasonable. The pool should be created separately from the requirements of the site and adjusted in the parameters.

Create a new chroot.conf under/etc/php5/fpm/pool.d/(note that you must end with. conf to be called by 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/CHROOTC Hdir =/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 previous parameters are more familiar. Simply set the chroot to the configured environment root directory to open chroot. After performing a php5-fpm-t test, the new pool can be enabled with service php5-fpm reload. Of course Apache/nginx the corresponding configuration to set the back end.

Mention the last few lines. The bottom fourth line opens the Display_errors, in order to later the chroot PHP function to test, the test is finished, remember to comment out.

Setting session.gc_probability allows the PHP process to delete the session itself. Normally the session is cleaned up by a cron task added by PHP, but it seems that PHP does not automatically clean up the session in the CHROOT environment. Of course, you can also add the automatic execution of the script under the CRON.D to clean up, you do not have to open this option.

3. Fix PHP functions in chroot Environment

Create a new test.php under/var/www/chroot/public and write the following:

Copy the Code code as follows:
Php
<?php
Session_Start ();
Header ("Content-type:text/plain");
Echo (gethostbyname ("localhost"). " \ n ");
Print_r (GETDATE ());
Mail ("your@address", "Subject", "message");

The main tests here are: Session, DNS resolution, time and date, mail message () function.

Visit the test page above to indicate that no such directory or file or permission denied indicates that the session is not configured correctly. GetHostByName returned is not 127.0.0.1 or:: 1, the DNS resolution did not take effect. Tip timezone database is corrupt, stating the time and date errors. Mail () also has various error prompts.

The session will not mention, set the directory permissions there is no problem. The main processing of the following three questions, but also the PHP chroot environment mainly need to deal with the content.

3.1 Domain name resolution/time zone and other issues

The solution of Mail () is similar, after the interview. Previous domain name resolution and other issues here I introduce two workarounds. Method 1 is an easy way to refer to Kienzl, and Method 2 is the method used in most tutorials.

Method 1: Use NSCD

NSCD is (e) glibc "Name Service Caching Daemon". In addition to working with functions such as gethostbyname (), it also handles functions such as Getpwnam () that require access to/etc/passwd. (e) glibc accesses NSCD's UNIX sockets,/var/run/nscd/socket to obtain them through nscd, and resolves themselves if they cannot connect to NSCD.

In other words, as long as the installation of NSCD, and let the chroot environment of the program can access the socket connection NSCD, you can chroot in the environment of the resolution of the request to go smoothly outside the chroot. Since/var/run is generally TMPFS, hard links cannot be used across file systems, so you can use Mount-bind to mount the/VAR/RUN/NSCD directory in the same location as the chroot environment.

Similarly, using Mount-bind to mount the/usr/share/zoneinfo directory into the chroot environment, with the PHP-FPM pool set Date.timezone can be very direct and violent solution to the time zone problem.

Perform the Apt-get install NSCD installation NSCD First, and then save the following script as/etc/init.d/php-chroot in order to allow Mount-bind to execute automatically

bash#!/bin/sh### BEGIN INIT info# provides:  php5-fpm-chroot-setup# required-start:nscd# required-stop:# Default-start:  2 3 4 AA default-stop:0 1 6# short-description:bind-mounts needed sockets and data into a PHP-FPM-CHR oot### END INIT infochroot=/var/www/chrootdirs= "/var/run/nscd/usr/share/zoneinfo" case "$" in start) $ 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; does  umount "${chroot}${d}" done;;  *) echo "Usage: $N {start|stop}" >&2 exit 1;; Esacexit 0

Execute UPDATE-RC.D php-chroot defaults to let the script execute at startup. If you have multiple chroot environments and multiple directories require Bind-mount, you can add a loop rewrite yourself.

The benefits of this approach are simple, without the need to copy large volumes of etc configuration files and library files into the chroot environment. The use of NSCD in resolving the problem of domain name access also solves the/etc/passwd and/etc/group. But the safety of Bind-mount and NSCD is not yet clear, only so far so good. In addition Mount-bind will consume certain system resources, commented that about a mount will probably consume 500k of memory, so for a large number of chroot environment (hundreds of) is not suitable.

Method 2: Copy/etc configuration files and library files

This is the most traditional and commonly used method, but also relatively complex. It is difficult to determine which configuration to copy and which library files vary by release and software version. And once the system is upgraded, the corresponding library files also need to be updated, a lot of work. I did not use this method, but briefly introduce some of the more reliable ways to share it.

Domain name resolution. Need to copy/etc/resolv.conf,/etc/hosts,/etc/nsswitch.conf to chroot environment under the ETC directory. It is also necessary to copy a series of library files, mainly libnss_*.so,libresolv.so,libsoftokn3.so. Specific libnss_*.so copies of which can be opened nsswitch.conf see which are listed.

Time zone configuration. Copies/etc/localtime,/usr/share/zoneinfo/zone.tab, and files used in the/usr/share/zoneinfo directory using the time zone.

Other common configurations. /ETC/PASSWD and/etc/group are sometimes needed, but the content seems to be forged, at least selectively, without having to completely copy the main system.

If you still have problems when you use them, you can use Strace to see which library files are being used by PHP. Execute First:

Copy the Code code as follows:
Bash
PS aux | grep php | grep ' chroot ' #chroot是php的pool名

View the process PID of the pool (you can limit the number of processes in the pool setting to 1 for easy debugging). Then execute:

Bash
Strace-p process Pid-o chroot1.txt& #有多个子进程就修改pid执行多次, output changed to Chroot2/3.txt save to different files
At this point in the page to perform various functions, and then look at the output file records which library files, the corresponding copy to the chroot environment.

This method is cumbersome, especially when installing settings and subsequent system updates. Of course, as an OPS person, writing shell scripts to simplify the work is certainly the basic skills. This method has no additional memory consumption, can deploy a large number of chroot environment, of course, hard disk consumption will be a bit higher, and security has gone through a long test

3.2 Fix Mail ()

If using WordPress, you can also take advantage of MailChimp and other plugins do not use the system's own mail services. In fact, because of the increasingly stringent standards of spam, and VPS hosting restrictions, I am now more inclined to simply do not deploy the mail service in the system, so the PHP mail () function is considered to be discarded ... Of course, if necessary, it can be easily set up.

The Mail () function of PHP uses the system () call SendMail to send the message, so you need to have a SendMail program that can be called in the chroot environment. A common alternative is mini_sendmail, where the introduction of SSMTP,MSMTP is similar.

Premise: Handling/bin/sh

The command line generated by the system () call is/bin/sh-c command. Calling an external program in a chroot environment must exist/bin/sh, a basic shell. Usually choose to copy dash:

Copy the Code code as follows:
Bash
#cp/bin/dash/var/www/chroot/bin/sh

Note Run Ldd/bin/dash to see which library files need to be copied. My echo here is:

Copy the Code code 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)

The first one's got a file name.,=> There are no files behind it. The basic principle of the remaining library files is that if/lib64 is listed, it is copied to/lib64 in the chroot environment, if/lib is listed, although there are many distributions, most of the library files include libc.so in the/lib/x86_64-linux-gnu/directory, Also directly copied to the chroot environment of the/lib directory can be found normally.

But!

The previous sentence "must exist/bin/sh, a basic shell" is not really true, for mail () as long as there is a can accept the-c parameter call the following command of the program is OK. So Kienzl wrote a program like this:

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) {Fpri NTF (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++] = t Oken;  if (i >= maxarg)  return 2;}}  Return EXECVP (Args[0], args);}
     
      
    
     
   
    
  
   
 
  

Save to Sh.c execution: gcc sh.c-o sh-static then copy sh to the/bin directory of the chroot environment.

Such an incomplete shell has, to some extent, enhanced the security of the chroot environment.

Method 1: Use Mini_sendmail

Mini_sendmail seems to be built for the chroot environment. When Mini_sendmail is called, it will instead access the 25 port of the machine and send mail through the native mail service. This is the simplest way to use Mini_sendmail to send mail in a chroot environment if the main environment has a mail service such as installing POSTFIX/EXIM4.

The installation of the Mini_sendmail is simple:

Copy the Code code 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

The last line modifies the directory of the CHROOT environment itself. Remember to copy to the/usr/sbin directory of the chroot environment and name SendMail. Otherwise, in the pool to set the INI parameter Sendmail_path to guide PHP to find the SendMail program.

Since Mini_sendmail is statically linked by default, there is no need to copy other library files.

Method 2: Use SSMTP/MSMTP

You cannot use Mini_sendmail for a situation where the mail service is not installed on this computer. Both SSMTP and MSMTP support the sending of incoming mail requests to other SMTP servers instead. It is important to note that because SSL support requires more and more complex library files and configurations, it is not recommended to compile SSL support for both ... Let's take ssmtp as an example to explain.

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=/#别忘了prefixmake     #千万别手抖make INSTALLCP ssmtp/var/www/chroot/usr/sbinmkdir-p/var/ WWW/CHROOT/ETC/SSMTPCP ssmtp.conf revaliases/var/www/chroot/etc/ssmtp #配置文件cd/var/www/chroot/usr/sbinln-s ssmtp SendMail

Also remember LDD and then copy the corresponding library file in the past. In addition SSMTP need/etc/passwd and/etc/group, if not used above NSCD need to copy/forge these two files.

SSMTP needs to be configured. The ssmtp.conf file is configured as follows:

bashroot=admin@example.com  #其实这行好像可以乱写mailhub =smtp.example.com  #smtp服务器地址hostname =myexample.com  # The hostname here appears to be used to generate the default "root@myexample.com" form of the sender address authuser=admin@example.com #此处使用真实的登录用户名AuthPass =password   #密码FromLineOverride =yes   #允许改写发件人

Revaliases Configure the "from" Address and the SMTP server address that each user uses when using SSMTP. Can not be configured, but the file should have. The specific format is:

Copy the Code code as follows:
Bash
# Local User name: Sender Address: SMTP Server [: Port (default 25)]
Root:admin@example.com:smtp.example.com
Www-data:noreply@example.com:smtp.example.com

You can use Chroot (referred to as the real chroot command) to do a test:

Copy the Code code as follows:
Bash
Chroot/var/www/chroot/bin/sh #此时/bin/sh must be a real shell.
echo "Subject:test" |sendmail-v username@server.com #替换邮件地址为自己的

At this point the mail () function of PHP should be available.

4. Other issues

After configuring the chroot environment, remember to close the display_error in the PHP pool settings.
MySQL connection may be having problems, because if you fill in localhost, PHP will try to find MySQL's UNIX socket to access mysqld. Fill in 127.0.0.1 via TCP connection There's no problem.
After the completion of the directory structure, take me as an example to you for reference:

/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│└──zoneinfo│  ├── The directory structure of a large number of time zones │  └──zone.tab└──var├──lib│└──php5│└──sessions├──run │└──nscd│├──nscd.pid│└──socket└──www└──chroot. /..

The above is the whole content of this article, I hope you like.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.