PHP-FPM's chroot execution Environment _php example

Source: Internet
Author: User
Tags bz2 chmod fpm time zones mkdir sessions time and date file permissions

PHP-FPM in the establishment of chroot, has a very good isolation, improve the security of the system, but to establish a reasonable PHP-FPM chroot environment is a bit more difficult, than the use of debootstrap and other tools to build more trouble, the following by reference to the relevant information, The php-fpm of the chroot implementation of the environment to be sorted out, share to everyone.

Taking 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. CentOS Please adjust yourself.

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

1. Building the directory structure

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

Perform the following command to establish a basic directory structure:

Bash
mkdir-p/var/www/chroot/
cd/var/www/chroot
mkdir-p public bin Dev tmp usr/sbin/usr/share/zoneinfo/v Ar/run/nscd/var/lib/php5/sessions var/www
cp-a/dev/zero/dev/urandom/dev/null dev/#注3 chmod--reference=/
TMP tmp/
chmod--reference=/var/lib/php5/sessions var/lib/php5/sessions #注4
chown-r root:root.     #注2
chown-r www-data:www-data public/#注2
cd var/www
ln-s. /.. Chroot     #注1

Here is the directory structure, and then something new is added:

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

Note 1: This soft connection is used to solve the problem that the script_filename passed to PHP-FPM after entering the chroot and cannot find the file (accessing the PHP page to return "File not Found") Apache/nginx.

Take Nginx as an example, usually set Script_filename to $document _root$fastcgi_script_name, and the script path passed to PHP-FPM is/var/www/chroot/public/ index.php. And because PHP-FPM is in chroot environment, so the path that it actually attempts to visit becomes/var/www/chroot +/var/www/chroot/public/index.php of course does not exist.

So using a soft connection to link the/var/www/chroot in the chroot environment to the root directory, you can access the script normally.

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

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

Note 3:cp-a In addition to copy the contents of the file will also copy the file permissions, patterns and other information, it is convenient to directly copy zero, urandom and null these three key device files. Mknod seems to be a more secure way, but cp-a I don't seem to have any problems with it.

Note 4:chmod--reference=xxx will refer to the permissions after the XXX permission setting. TMP is not mentioned, the key is the following var/lib/php5/sessions is PHP to store the directory of session files, you need to let Www-data have read and write permissions. After the proposal is set, take another look. Of course, there will be tests behind it.

Configuration of 2.PHP-FPM

Create a new PHP-FPM executive pool to build the chroot environment. It is not recommended to modify php-fpm.conf directly, as this is a 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 on a server all the sites share a set of configuration, especially a common set of php.ini configuration, is actually unreasonable. The pool should be set up separately and the parameters adjusted in accordance with the requirements of the site.

Create a new chroot.conf under/etc/php5/fpm/pool.d/(note that you must end with. conf to be called php-fpm.conf):

[Chroot]
user = Www-data
group = www-data
listen =/var/run/php-chroot.sock
Listen.owner = Www-data
Listen.group = www-data

pm = dynamic
Pm.max_children = 5
pm.start_servers = 1
pm.min_spare_servers = 1< C10/>pm.max_spare_servers = 3

chroot =/var/www/chroot
chdir =/public
; security.limit_extensions =. php
php_flag[display_errors] = on
Php_value[date.timezone] = Asia/hong_kong
;p hp_admin_value[ Session.gc_probability] = 1
;p hp_admin_value[open_basedir] = "/tmp/:/public/:/var/www/chroot/public/"

The previous parameters are more familiar. Simply set the chroot for the configured environment root directory to open the chroot. After testing by performing php5-fpm-t, the new pool is enabled with the service php5-fpm reload. Of course Apache/nginx the corresponding configuration to set the back end.

Mention the last few lines. The fourth line of the countdown opens the display_errors so that you can then test the PHP functionality under Chroot, and remember to comment it out when the test is finished.

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 sessions in the chroot environment. Of course, you can also add their own cron.d under the automatic execution of the script to clean, you do not have to open this option.

3. Repair the functions of PHP in chroot environment

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

Copy 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 are: Session, DNS resolution, time and date, mail Mail () functions.

Visit the test page above to indicate that no such directory or file or permission denied the session is configured incorrectly. gethostbyname return is not 127.0.0.1 or:: 1, the DNS resolution is not in effect. Tip timezone The database is corrupt, and so on, stating that there are errors in time and date. Mail () also has various error prompts.

Session will not mention, set the directory permissions are no problem. Mainly deal with the following three questions, but also PHP's chroot environment to deal with the main content.

3.1 Domain name resolution/time zone and other issues

Mail () solution is similar, after the interview. The previous domain name resolution and so on issues here I introduce two kinds of solutions. 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 the "Name Service Caching Daemon" of glibc (e). In addition to dealing with functions such as gethostbyname (), you also handle functions such as Getpwnam () that require access to/etc/passwd. (e) glibc access to NSCD UNIX sockets,/var/run/nscd/socket to get them through NSCD, and then resolve them if they cannot connect to NSCD.

In other words, as long as the NSCD, and let the chroot environment in the program can access to the socket connection NSCD, you can chroot in the environment of the resolution request transferred from the chroot outside smoothly. Because/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 to the same location in the chroot environment.

In the same way, 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 resolution of time zone problems.

First perform the Apt-get install NSCD installation NSCD, and then save the following script as a mount-bind to allow/etc/init.d/php-chroot to perform 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 S Ockets and data into a php-fpm-chroot
### end INIT INFO
chroot=/var/www/chroot
dirs= "/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
 ;;
Esac
Exit 0

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

The benefits of this approach are simple and straightforward, without the need to copy a large number of etc configuration files and library files into the chroot environment. The use of NSCD in resolving domain name access problems in the process has also been resolved/etc/passwd and/etc/group. However, the security of Bind-mount and NSCD is still not exact, only to say so and so far good. In addition, Mount-bind will consume a certain amount of 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 and library files

This is the most traditional and commonly used method, but also relatively complex. It is difficult to decide which configuration to copy and which library files will vary from release and software versions. And once the system upgrades, the corresponding library files need to be updated, the workload is very large. I did not use this method, but briefly introduced some of the more reliable ways to share.

Domain name resolution. Need to copy/etc/resolv.conf,/etc/hosts,/etc/nsswitch.conf to the chroot environment under the ETC directory. You also need to copy a series of library files, mainly libnss_*.so,libresolv.so,libsoftokn3.so. Specific libnss_*.so copy which, you can open nsswitch.conf see what listed.

The time zone configuration. Copy/etc/localtime,/usr/share/zoneinfo/zone.tab, and files for the time zone used in the/usr/share/zoneinfo directory.

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

If you still have problems with your use, you can use Strace to see which library files are used by PHP for which calls. First Execute:

Copy Code code as follows:

Bash
PS aux | grep php | grep ' chroot ' #chroot是php的pool名

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

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

This approach is cumbersome, especially when you first install setup and follow up on system updates. Of course, being a transport worker writing a shell script simplification is certainly a basic skill. This method has no additional memory consumption, can deploy a large number of chroot environment, of course, hard disk consumption is higher, and security has undergone a long test

3.2 Repair mail ()

If you are using WordPress, you can also use plug-ins such as mailchimp do not use the system's own mail services. In fact, because of the increasingly stringent spam standards, and the limitations of the VPS host, I now prefer to simply do not deploy the mail service in the system, so the PHP mail () function is a waste of ... Of course, if need to also can be very simple to set up good.

PHP's Mail () function is to use System () invoke SendMail to send mail operation, so need to chroot the environment has the ability to call the SendMail program. The common alternative is mini_sendmail, which is more ssmtp,msmtp and similar.

Prerequisites: Handling/bin/sh

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

Copy Code code as follows:

Bash
#cp/bin/dash/var/www/chroot/bin/sh

Notice which library files you need to copy to run Ldd/bin/dash observation. My echo here is:

Copy 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 that only lists a filename,=> there are no files behind the basically are not tube. The basic principle of the remaining library files is to copy to the/lib64 in the chroot environment if the list is/lib64, if/lib is listed, and 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 normal to find.

But!

The preceding sentence "must exist/bin/sh, a basic shell" is not true, for mail () as long as there is a can accept the C-parameter call after the command of the program can be. So Kienzl wrote such a program:

C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include < unistd.h>
#define MAXARG
int main (int argc, char* const argv[]) {char* args[maxarg
 ] = {};
 if (argc < 3 | | strcmp (ARGV[1], "-C")!= 0) {
 fprintf (stderr, "Usage:%s-c <cmd>\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 into SH.C execution: gcc sh.c-o sh-static then copy sh to the/bin directory of the chroot environment.

Such an incomplete shell is, to a certain extent, enhanced the security of the chroot environment.

Method 1: Use Mini_sendmail

Mini_sendmail seems to be born for the chroot environment. When Mini_sendmail is invoked, it accesses the local port of 25 and sends mail through the mail service on this computer. This is the easiest way to use Mini_sendmail to send mail in a chroot environment if the main environment has mail services such as installation POSTFIX/EXIM4.

The installation of Mini_sendmail is simple:

Copy 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 row modifies the directory of the Chroot environment. Remember to copy to the/usr/sbin directory of the chroot environment and name it sendmail. Otherwise, in the pool, set the INI parameter Sendmail_path to guide PHP to find the SendMail program.

Because Mini_sendmail is a static link by default, there is no need to copy other library files.

Method 2: Use SSMTP/MSMTP

You cannot use Mini_sendmail if you do not have mail services installed on this computer. Both SSMTP and MSMTP support sending requests for incoming mail to the other SMTP servers. It is to be noted that SSL support is not recommended for both because of the need for more complex library files and configurations. Let's take ssmtp as an example to introduce.

Bash
wget ftp://ftp.debian.org/debian/pool/main/s/ssmtp/ssmtp_2.64.orig.tar.bz2
tar jxf ssmtp_2.64. orig.tar.bz2
cd ssmtp_2.64
./configure--prefix=/#别忘了prefix
make     #千万别手抖make install
CP ssmtp/ Var/www/chroot/usr/sbin
mkdir-p/var/www/chroot/etc/ssmtp
CP ssmtp.conf revaliases/var/www/chroot/etc/ SSMTP #配置文件
cd/var/www/chroot/usr/sbin
ln-s ssmtp sendmail

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

SSMTP need to be configured. The ssmtp.conf files are configured as follows:

Bash
root=admin@example.com  #其实这行好像可以乱写

mailhub=smtp.example.com  #smtp服务器地址
hostname= myexample.com  #此处的hostname似乎会用于产生默认的 "root@myexample.com" form of sender address
authuser=admin@example.com # Here you use the real login username
authpass=password   #密码
fromlineoverride=yes   #允许改写发件人

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

Copy Code code as follows:

Bash
# Local Username: 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 (the real chroot command) to do a test:

Copy 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 #替换邮件地址为自己的

The PHP mail () function should be available at this time.

4. Other issues

After configuring the chroot environment, remember to display_error the PHP pool setting down.
MySQL connection may encounter problems because if you fill out localhost php will try to find MySQL UNIX socket to access mysqld. Fill in 127.0.0.1 There's no problem with the TCP connection.
After the completion of the directory structure, take me as an example for you to refer to:

/var/www/chroot/
├──bin
│└──sh
├──dev
│├──null
│├──urandom │└──zero ├──etc │└─ ─SSMTP
│├──revaliases
│└──ssmtp.conf
├──lib
│└──libc.so.6
├──lib64 86-64.so.2
├──public
├──tmp
├──usr
│├──sbin
││├──sendmail-> ssmtp |│└──ssmtp< C21/>│└──share
│└──zoneinfo
│  ├── directory structure for a large number of time zones
│  └──zone.tab
└──var
 ├──lib
 │└──php5
 │└──sessions
 ├──run
 │└──nscd
 │├──nscd.pid
 │└──socket └──chroot->. /..

The above is the entire 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.