Credits
This article was inspired by Artur Maj’s article Securing Apache: Step-by-Step shows in a step-by-step fashion, how to install and configure the Apache 2.0.x series web server in much the same way as the 1.3.X covered in Artur’s article, i.e. “in order to mitigate or avoid successful break-in when new vulnerabilities in this software are found”.
Introduction
Configuring your Apache2 server in accordance to the specifications laid out in this howto will result in limited functionality. The following will be available:
· Apache2 will be accessible from the Internet
· only static pages will be served (e.g. HTML or XHTML)
· name based virtual hosting
· specified web pages can be accessible only from selected IP addresses or users (basic .htaccess authentication)
· all web requests will be logged including information about the browsers
This howto does not cover such things as relational databases (MySQL, PostgreSQL, etc.), scripting languages (Python, Perl, PHP, Tcl, etc.), or any of a myriad of server side gadgets for interaction with web services. The reasons for this are beyond the scope of this howto, but involve security on multiple levels. For a better explanation to this and a number of other good security oriented observations, read Artur’s article.
Setup
The rest of this howto has been performed on my LFS 3.3 ( Linux from scratch) based distribution of Linux called Jinx, running on a i586-pc-linux-gnu, with the 2.4.18 kernel (I know it’s not the latest kernel patch, but I’m such a lazy bastard).
I’m sure most of the stuff in this howto will be applicable in most unixes, but some variations may occur. I’ll try to add them, if you report them, with the exclusion of anything involving the microsoft corporation.
The first step in securing any service is to close as many security holes in the operating system and then start closing holes in the service itself. This so called hardening of the OS is beyond the scope of this article, but there are some very good articles about the issue on e.g. the SecurityFocus site. So feel free to stop by there and come back later for the Apache2 part.
Installation and settings
Once all the other planned hardening has been executed we can begin the process of bolting up Apache2.
The first thing is to create a new username and usergroup to be used only by Apache2. We can use the name for both “apache2″ and create the new group and regular user like this:
This sets the home directory to nada and gives no shell. Thus if the user account is compromised the cracker will have a hard time obtaining a shell from which to launch any serious attack.
Also, by default, the Apache2 processes run with privileges of user nobody (except the main process, which runs with root privileges) and GID of group nogroup. If the account was compromised the intruder would gain access to all processed running under user nobody and group nogroup. Hence we run Apache2 under the UID/GID of a unique regular user/group, dedicated to Apache2.
Getting Apache2
Next you need to download the latest stable version of the Apache2 web server from your nearest mirror. Since some of the options of Apache2 can only be disabled during compilation, you need to download the source instead of a binary release. It is also good practice to always compile your own software, since then you’ll know what crap got put in and what got left out, right?
If you download the software from a mirror, be sure to verify the authenticity of the packages with PGP, GPG or MD5 as instructed here.
After downloading and verifying the packets, you need to unpack them. Then you need to decide which modules are to remain enabled. All the modules available in the latest version of Apache 2.0.X (currently 2.0.47) can be found at http://httpd.apache.org/docs-2.0/mod.
Apache2 modules
The choice of modules is one of the most important steps in securing Apache2. The fewer you have, the better. In order to not incapasitate Apache2 completely and fulfill the functionality and security assumptions stated in the beginning, the following modules must remain enabled:
All of the aforementioned modules are installed by default, but a number of other modules are also installed by default. Since configure for Apache2 doesn’t seem to support the –disable-all switch you need to disable the ones you don’t want and leave untouched the default ones you want. The following modules should thus be removed:
· mod_actions
· mod_alias
· mod_asis
· mod_autoindex
· mod_cgi
· mod_env
· mod_imap
· mod_include
· mod_negotiation
· mod_setenvif
· mod_so
· mod_status
· mod_userdir
This will leave the wanted modules listed before and use the default MPM, prefork.c.
Now, you may choose to include some more modules and change the MPM to suit your needs better. It is, however, worth to note that some Apache2 modules are more dangerous than others. For a discussion of these, please refer to the original Securing Apache: Step-by-Step article or any number of security related sites for example SecurityFocus.
The next issue is whether to compile the modules dynamically or statically. Static is better. If new vulnerabilities in Apache2 are found, you will probably have to recompile the whole thing anyway and by choosing the static method, you eliminate the need of one more module, mod_so.
Compiling Apache2
The latest distribution should have all necessary security patches included, but if for some reason it does not, you need to apply all these patches. After this, the server can be compiled as follows:
· enable-so: to build dynamic modules
· enable-unique-id: mod_security requires this module
· enable-alias: to enable mod_alias
· enable-setenvif and enable-ssl: to enable SSL
· enable-status: to enable status of Apache
· enable-reqtimeout: mod_reqtimeout was introduced in Apache-2.2.15 to protect again Slowloris
The choice of prefix is naturally up to you, but I happen to use that one. It is a good idea not to leave any marks about the version of apache in use, thus for example –prefix=/usr/local/apache-2.0.47 would be a bad choice.
After configure, run make, switch to root, make sure the default access right settings for files and directories are proper, run make install and set the ownership for the new files and directories to root.
The actual Chrooting of Apache2
The next phase is to limit Apache2′s access to the filesystem. This can be achieved by chrooting it’s main daemon, httpd. Chrooting means creating a new root directory structure. Thus when you move daemon files to it, and run the proper daemon in the new environment, it and all it’s child processes will have access only to the new directory structure.
First you need to create the new root directory structure. I’ve done it under /chroot/httpd, you can choose whatever you like. To make the directory structure under /chroot/httpd, do this:
Naturally you’d want to put the zoneinfo, that’s relevant for you. The owner of all these directories must be root and the access rights must be set to 0755. Next you create the special device file, /dev/null and set its access rights:
Note: for FreeBSD systems this would be:
Also a log device must be created under the chroot jail. This can be achieved by adding the line
to the /etc/syslog.conf file and restarting the syslogd daemon.
Note: for FreeBSD systems you would need to change the /etc/rc.conf file.
After these comes the time consuming part. You need to check each and every program and library for dependancies. I used ldd to begin with and strace to get all the rest. You should get something like this, when you ldd the main daemon, httpd:
If you then run ldd for each of these files, you should get something resembling this:
You then strace the httpd into a file and grep that for the word open and you should get out something like this:
The reason why we strace the httpd is that you need to copy each of these open files to the chroot jail with the exeption of the /etc/ld.so.cache, which is created at runtime and the /etc/ld.so.preload, which is only found on some systems (excluding e.g. mine).
As you can see from the output of the httpd strace the daemon systematically first checks for the libraries from its own lib/ directory. Thus you can copy the libraries directly to the /chroot/httpd/usr/local/apache2/lib directory. You need to have ld-linux.so.2 and libc.so.6 in the /lib/ of the chroot, but all the rest can go straight to Apache2′s own lib/ directory.
So, moving on. You copy the libraries to the chroot jail and put them in the /usr/local/apache2/lib/ and /lib/ directories.
You need to remove all other lines from the passwd and group file except apache2 and nobody (and nogroup, if you happen to have one).
If you now try to run httpd with those files, it won’t work and if you strace it, you’ll find out, that you also need these files:
Obviously you want to use the zoneinfo, that’s correct for you time zone. I just happen to live in Saigon.
You might also want to put in these files, although Apache2 will run without them (or at least seems to):
Testing
Now it’s time to see if the bugger works. Copy one of the index files from /usr/local/apache2/htdocs/ to /chroot/httpd/web/index.html:
Change your /chroot/httpd/usr/local/apache2/conf/httpd.conf to point to it. You can change only the DocumentRoot variable to /web for testing. Then try to run Apache2 in the chroot jail:
If you made use of the virtual hosts then you need to make the directories to which you point i.e. I have the directories /chroot/httpd/usr/local/apache2/logs/abc.com/, /chroot/httpd/usr/local/apache2/logs/www.def.com/ /chroot/httpd/web/vhosts/abc.com/ and /chroot/httpd/web/vhosts/www.def.com/.
If Apache2 still won’t work, try to strace the httpd again and grep the file for ENOENT (something not found).
You can also try to increase the level of Apache2′s logging by changing the LogLevel in the httpd.conf to debug.
Tuning
Fine tuning the httpd.conf is an artform, but you can get far with something like this:
Final step
If your Apache now works properly, the only thing that is left to do is to create a script that will start Apache during system boot. In order to do this, the apache.sh script can be used, with the following content:
In case of our CentOS system, the above script should be placed in the /etc/init.d directory, under the name of mysql.
Make the script executable:
To make the script run at boot time:
To run the script manual:
In case of FreeBSD system, the above script should be placed in the /usr/local/etc/rc.d directory, under the name of apache.sh
To make the script run at boot time:
To run the script manual:
This article was inspired by Artur Maj’s article Securing Apache: Step-by-Step shows in a step-by-step fashion, how to install and configure the Apache 2.0.x series web server in much the same way as the 1.3.X covered in Artur’s article, i.e. “in order to mitigate or avoid successful break-in when new vulnerabilities in this software are found”.
Introduction
Configuring your Apache2 server in accordance to the specifications laid out in this howto will result in limited functionality. The following will be available:
· Apache2 will be accessible from the Internet
· only static pages will be served (e.g. HTML or XHTML)
· name based virtual hosting
· specified web pages can be accessible only from selected IP addresses or users (basic .htaccess authentication)
· all web requests will be logged including information about the browsers
This howto does not cover such things as relational databases (MySQL, PostgreSQL, etc.), scripting languages (Python, Perl, PHP, Tcl, etc.), or any of a myriad of server side gadgets for interaction with web services. The reasons for this are beyond the scope of this howto, but involve security on multiple levels. For a better explanation to this and a number of other good security oriented observations, read Artur’s article.
Setup
The rest of this howto has been performed on my LFS 3.3 ( Linux from scratch) based distribution of Linux called Jinx, running on a i586-pc-linux-gnu, with the 2.4.18 kernel (I know it’s not the latest kernel patch, but I’m such a lazy bastard).
I’m sure most of the stuff in this howto will be applicable in most unixes, but some variations may occur. I’ll try to add them, if you report them, with the exclusion of anything involving the microsoft corporation.
The first step in securing any service is to close as many security holes in the operating system and then start closing holes in the service itself. This so called hardening of the OS is beyond the scope of this article, but there are some very good articles about the issue on e.g. the SecurityFocus site. So feel free to stop by there and come back later for the Apache2 part.
Installation and settings
Once all the other planned hardening has been executed we can begin the process of bolting up Apache2.
The first thing is to create a new username and usergroup to be used only by Apache2. We can use the name for both “apache2″ and create the new group and regular user like this:
groupadd apache2
useradd apache2 -c “Apache2 server” -d /dev/null -g apache2 -s /bin/false
This sets the home directory to nada and gives no shell. Thus if the user account is compromised the cracker will have a hard time obtaining a shell from which to launch any serious attack.
Also, by default, the Apache2 processes run with privileges of user nobody (except the main process, which runs with root privileges) and GID of group nogroup. If the account was compromised the intruder would gain access to all processed running under user nobody and group nogroup. Hence we run Apache2 under the UID/GID of a unique regular user/group, dedicated to Apache2.
Getting Apache2
Next you need to download the latest stable version of the Apache2 web server from your nearest mirror. Since some of the options of Apache2 can only be disabled during compilation, you need to download the source instead of a binary release. It is also good practice to always compile your own software, since then you’ll know what crap got put in and what got left out, right?
If you download the software from a mirror, be sure to verify the authenticity of the packages with PGP, GPG or MD5 as instructed here.
After downloading and verifying the packets, you need to unpack them. Then you need to decide which modules are to remain enabled. All the modules available in the latest version of Apache 2.0.X (currently 2.0.47) can be found at http://httpd.apache.org/docs-2.0/mod.
Apache2 modules
The choice of modules is one of the most important steps in securing Apache2. The fewer you have, the better. In order to not incapasitate Apache2 completely and fulfill the functionality and security assumptions stated in the beginning, the following modules must remain enabled:
Module | Description |
core | Core Apache HTTP Server features that are always available |
mod_access | Access control based on client hostname, IP address, or other characteristics of the client request |
mod_auth | User authentication using text files |
mod_dir | Provides for “trailing slash” redirects and serving directory index files |
mod_log_config | Logging of the requests made to the server |
mod_mime | Associates the requested filename’s extensions with the file’s behavior (handlers and filters) and content (mime-type, language, character set and encoding) |
All of the aforementioned modules are installed by default, but a number of other modules are also installed by default. Since configure for Apache2 doesn’t seem to support the –disable-all switch you need to disable the ones you don’t want and leave untouched the default ones you want. The following modules should thus be removed:
· mod_actions
· mod_alias
· mod_asis
· mod_autoindex
· mod_cgi
· mod_env
· mod_imap
· mod_include
· mod_negotiation
· mod_setenvif
· mod_so
· mod_status
· mod_userdir
This will leave the wanted modules listed before and use the default MPM, prefork.c.
Now, you may choose to include some more modules and change the MPM to suit your needs better. It is, however, worth to note that some Apache2 modules are more dangerous than others. For a discussion of these, please refer to the original Securing Apache: Step-by-Step article or any number of security related sites for example SecurityFocus.
The next issue is whether to compile the modules dynamically or statically. Static is better. If new vulnerabilities in Apache2 are found, you will probably have to recompile the whole thing anyway and by choosing the static method, you eliminate the need of one more module, mod_so.
Compiling Apache2
The latest distribution should have all necessary security patches included, but if for some reason it does not, you need to apply all these patches. After this, the server can be compiled as follows:
./configure --prefix=/usr/local/apache2 --with-mpm=prefork --disable-env --disable-charset-lite --disable-include --disable-autoindex --disable-asis --disable-cgi --disable-negotiation --disable-imap --disable-actions --disable-userdir --disable-rewrite --enable-so --enable-unique-id --enable-alias --enable-setenvif --enable-ssl --enable-status --enable-reqtimeout
· enable-so: to build dynamic modules
· enable-unique-id: mod_security requires this module
· enable-alias: to enable mod_alias
· enable-setenvif and enable-ssl: to enable SSL
· enable-status: to enable status of Apache
· enable-reqtimeout: mod_reqtimeout was introduced in Apache-2.2.15 to protect again Slowloris
The choice of prefix is naturally up to you, but I happen to use that one. It is a good idea not to leave any marks about the version of apache in use, thus for example –prefix=/usr/local/apache-2.0.47 would be a bad choice.
After configure, run make, switch to root, make sure the default access right settings for files and directories are proper, run make install and set the ownership for the new files and directories to root.
make
su
umask 022
make install
chown -R root:root /usr/local/apache2
The actual Chrooting of Apache2
The next phase is to limit Apache2′s access to the filesystem. This can be achieved by chrooting it’s main daemon, httpd. Chrooting means creating a new root directory structure. Thus when you move daemon files to it, and run the proper daemon in the new environment, it and all it’s child processes will have access only to the new directory structure.
First you need to create the new root directory structure. I’ve done it under /chroot/httpd, you can choose whatever you like. To make the directory structure under /chroot/httpd, do this:
mkdir -p /chroot/httpd/dev && \
mkdir -p /chroot/httpd/etc && \
mkdir -p /chroot/httpd/lib && \
mkdir -p /chroot/httpd/usr/local/apache2/bin && \
mkdir -p /chroot/httpd/usr/local/apache2/logs && \
mkdir -p /chroot/httpd/usr/local/apache2/conf && \
mkdir -p /chroot/httpd/usr/local/apache2/lib && \
mkdir -p /chroot/httpd/usr/lib && \
mkdir -p /chroot/httpd/usr/libexec && \
mkdir -p /chroot/httpd/usr/share/zoneinfo/Asia && \
mkdir -p /chroot/httpd/var/run && \
mkdir -p /chroot/httpd/web
Naturally you’d want to put the zoneinfo, that’s relevant for you. The owner of all these directories must be root and the access rights must be set to 0755. Next you create the special device file, /dev/null and set its access rights:
mknod /chroot/httpd/dev/null c 1 3
chown root:root /chroot/httpd/dev/null
chmod 666 /chroot/httpd/dev/null
Note: for FreeBSD systems this would be:
mknod /chroot/httpd/dev/null c 2 2
chown root:root /chroot/httpd/dev/null
chmod 666 /chroot/httpd/dev/null
Also a log device must be created under the chroot jail. This can be achieved by adding the line
syslogd_flags=”-l chroot/httpd/dev/log”
to the /etc/syslog.conf file and restarting the syslogd daemon.
kill -SIGHUP ‘cat /var/run/syslogd.pid’
Note: for FreeBSD systems you would need to change the /etc/rc.conf file.
After these comes the time consuming part. You need to check each and every program and library for dependancies. I used ldd to begin with and strace to get all the rest. You should get something like this, when you ldd the main daemon, httpd:
#ldd /usr/local/apache2/bin/httpd
libaprutil-0.so.0 => /usr/local/apache2/lib/libaprutil-0.so.0 (0×40016000)
libgdbm.so.2 => /usr/lib/libgdbm.so.2 (0x4002d000)
libdb-4.1.so => /usr/lib/libdb-4.1.so (0×40033000)
libexpat.so.0 => /usr/local/apache2/lib/libexpat.so.0 (0x400d4000)
libapr-0.so.0 => /usr/local/apache2/lib/libapr-0.so.0 (0x400f1000)
librt.so.1 => /lib/librt.so.1 (0x4010f000)
libm.so.6 => /lib/libm.so.6 (0×40120000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0×40142000)
libnsl.so.1 => /lib/libnsl.so.1 (0x4016f000)
libdl.so.2 => /lib/libdl.so.2 (0×40184000)
libpthread.so.0 => /lib/libpthread.so.0 (0×40187000)
libc.so.6 => /lib/libc.so.6 (0x4019c000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
If you then run ldd for each of these files, you should get something resembling this:
#ldd /usr/local/apache2/lib/libaprutil-0.so.0
libc.so.6 => /lib/libc.so.6 (0×40018000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×80000000)
#ldd /usr/lib/libgdbm.so.2
libc.so.6 => /lib/libc.so.6 (0×40009000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×80000000)
#ldd /usr/lib/libdb-4.1.so
libc.so.6 => /lib/libc.so.6 (0x400a4000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×80000000)
#ldd /usr/local/apache2/lib/libexpat.so.0
libc.so.6 => /lib/libc.so.6 (0×40020000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×80000000)
#ldd /usr/local/apache2/lib/libapr-0.so.0
libc.so.6 => /lib/libc.so.6 (0×40021000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×80000000)
#ldd /lib/librt.so.1
libc.so.6 => /lib/libc.so.6 (0×40018000)
libpthread.so.0 => /lib/libpthread.so.0 (0x4013d000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
#ldd /lib/libm.so.6
libc.so.6 => /lib/libc.so.6 (0×40018000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
#ldd /lib/libcrypt.so.1
libc.so.6 => /lib/libc.so.6 (0×40018000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
#ldd /lib/libnsl.so.1
libc.so.6 => /lib/libc.so.6 (0×40018000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
#ldd /lib/libdl.so.2
libc.so.6 => /lib/libc.so.6 (0×40018000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
#ldd /lib/libpthread.so.0
libc.so.6 => /lib/libc.so.6 (0×40018000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
#ldd /lib/libc.so.6
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0×40000000)
You then strace the httpd into a file and grep that for the word open and you should get out something like this:
#strace -o /usr/local/httpd-trace /usr/local/apache2/bin/httpd
#cat /usr/local/httpd-trace | grep open
open(“/etc/ld.so.preload”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/local/apache2/lib/i586/mmx/libaprutil-0.so.0″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/local/apache2/lib/i586/libaprutil-0.so.0″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/local/apache2/lib/mmx/libaprutil-0.so.0″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/local/apache2/lib/libaprutil-0.so.0″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libgdbm.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/etc/ld.so.cache”, O_RDONLY) = 3
open(“/usr/lib/libgdbm.so.2″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libdb-4.1.so”, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/usr/lib/libdb-4.1.so”, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libexpat.so.0″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libapr-0.so.0″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/librt.so.1″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/lib/librt.so.1″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libm.so.6″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/lib/libm.so.6″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libcrypt.so.1″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/lib/libcrypt.so.1″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libnsl.so.1″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/lib/libnsl.so.1″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libdl.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/lib/libdl.so.2″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libpthread.so.0″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/lib/libpthread.so.0″, O_RDONLY) = 3
open(“/usr/local/apache2/lib/libc.so.6″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/lib/libc.so.6″, O_RDONLY) = 3
open(“/usr/local/apache2/conf/httpd.conf”, O_RDONLY) = 3
open(“/etc/nsswitch.conf”, O_RDONLY) = 4
open(“/usr/local/apache2/lib/libnss_files.so.2″, O_RDONLY) = -1 ENOENT (No such file or directory)
open(“/etc/ld.so.cache”, O_RDONLY) = 4
open(“/lib/libnss_files.so.2″, O_RDONLY) = 4
open(“/etc/passwd”, O_RDONLY) = 4
open(“/etc/group”, O_RDONLY) = 4
open(“/usr/local/apache2/logs/access_log”, O_WRONLY|O_APPEND|O_CREAT, 0666) = 4
The reason why we strace the httpd is that you need to copy each of these open files to the chroot jail with the exeption of the /etc/ld.so.cache, which is created at runtime and the /etc/ld.so.preload, which is only found on some systems (excluding e.g. mine).
As you can see from the output of the httpd strace the daemon systematically first checks for the libraries from its own lib/ directory. Thus you can copy the libraries directly to the /chroot/httpd/usr/local/apache2/lib directory. You need to have ld-linux.so.2 and libc.so.6 in the /lib/ of the chroot, but all the rest can go straight to Apache2′s own lib/ directory.
So, moving on. You copy the libraries to the chroot jail and put them in the /usr/local/apache2/lib/ and /lib/ directories.
cp /lib/ld-linux.so.2 /chroot/httpd/lib/ && \
cp /lib/libc.so.6 /chroot/httpd/lib/ && \
cp /lib/libcrypt.so.1 /chroot/httpd/usr/local/apache2/lib/ && \
cp /lib/libdl.so.2 /chroot/httpd/usr/local/apache2/lib/ && \
cp /lib/libm.so.6 /chroot/httpd/usr/local/apache2/lib/ && \
cp /lib/libnsl.so.1 /chroot/httpd/usr/local/apache2/lib/ && \
cp /lib/libnss_files.so.2 /chroot/httpd/usr/local/apache2/lib/ && \
cp /lib/libpthread.so.0 /chroot/httpd/usr/local/apache2/lib/ && \
cp /lib/librt.so.1 /chroot/httpd/usr/local/apache2/lib/ && \
cp /usr/lib/libdb-4.1.so /chroot/httpd/usr/local/apache2/lib/ && \
cp /usr/lib/libgdbm.so.2 /chroot/httpd/usr/local/apache2/lib/ && \
cp /usr/local/apache2/lib/libapr-0.so.0 /chroot/httpd/usr/local/apache2/lib/ && \
cp /usr/local/apache2/lib/libaprutil-0.so.0 /chroot/httpd/usr/local/apache2/lib/ && \
cp /usr/local/apache2/lib/libexpat.so.0 /chroot/httpd/usr/local/apache2/lib/
The next step is to copy the rest of the files mentioned in the strace:
cp /etc/nsswitch.conf /chroot/httpd/etc/
cp /etc/group /chroot/httpd/etc/
cp /etc/passwd /chroot/httpd/etc/
cp /usr/local/apache2/logs/access_log /chroot/httpd/usr/local/apache2/logs/
cp /usr/local/apache2/conf/httpd.conf /chroot/httpd/usr/local/apache2/conf/
You need to remove all other lines from the passwd and group file except apache2 and nobody (and nogroup, if you happen to have one).
If you now try to run httpd with those files, it won’t work and if you strace it, you’ll find out, that you also need these files:
cp /usr/local/apache2/conf/mime.types /chroot/httpd/usr/local/apache2/conf/
cp /usr/local/apache2/logs/error_log /chroot/httpd/usr/local/apache2/logs/
cp /usr/share/zoneinfo/Asia/Saigon /chroot/httpd/usr/share/zoneinfo/Asia/
Obviously you want to use the zoneinfo, that’s correct for you time zone. I just happen to live in Saigon.
You might also want to put in these files, although Apache2 will run without them (or at least seems to):
cp /etc/resolv.conf /chroot/httpd/etc/
cp /etc/hosts /chroot/httpd/etc/
Testing
Now it’s time to see if the bugger works. Copy one of the index files from /usr/local/apache2/htdocs/ to /chroot/httpd/web/index.html:
cp /usr/local/apache2/htdocs/index.html.en /chroot/httpd/web/index.html
Change your /chroot/httpd/usr/local/apache2/conf/httpd.conf to point to it. You can change only the DocumentRoot variable to /web for testing. Then try to run Apache2 in the chroot jail:
/usr/sbin/chroot /chroot/httpd/ /usr/local/apache2/bin/httpd
If you made use of the virtual hosts then you need to make the directories to which you point i.e. I have the directories /chroot/httpd/usr/local/apache2/logs/abc.com/, /chroot/httpd/usr/local/apache2/logs/www.def.com/ /chroot/httpd/web/vhosts/abc.com/ and /chroot/httpd/web/vhosts/www.def.com/.
If Apache2 still won’t work, try to strace the httpd again and grep the file for ENOENT (something not found).
You can also try to increase the level of Apache2′s logging by changing the LogLevel in the httpd.conf to debug.
Tuning
Fine tuning the httpd.conf is an artform, but you can get far with something like this:
# =================================================
# Basic settings
# =================================================
ServerRoot "/usr/local/apache2"
PidFile /usr/local/apache2/logs/httpd.pid
ScoreBoardFile /usr/local/apache2/logs/httpd.scoreboard
# =================================================
# Performance settings
# =================================================
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxClients 150
MaxRequestsPerChild 0
# Anti slowloris
RequestReadTimeout header=5-10,MinRate=500
# =================================================
# General settings
# =================================================
Listen 80
User apache
Group apache
ServerName edgestuff
ServerAdmin ltphong112@gmail.com
UseCanonicalName Off
ServerSignature Off
HostnameLookups Off
ServerTokens Prod
DirectoryIndex index.html index.jsp
DocumentRoot /usr/local/apache2/htdocs
ExtendedStatus On
# =================================================
# Access control
# =================================================
<Directory />
Options None
AllowOverride None
Order deny,allow
Deny from all
</Directory>
<Directory />
Options Indexes FollowSymLinks
AllowOverride None
DirectoryIndex index.html
Order allow,deny
Allow from all
</Directory>
<Directory /usr/local/apache2/htdocs>
Options Indexes FollowSymLinks
DirectoryIndex index.html
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<Directory /usr/local/tomcat/webapps/blog>
Options Indexes FollowSymLinks
DirectoryIndex index.html index.jsp
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<Location /server-status>
SetHandler server-status
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Location>
# =================================================
# MIME encoding
# =================================================
TypesConfig /usr/local/apache2/conf/mime.types
DefaultType text/plain
AddEncoding x-compress Z
AddEncoding x-gzip gz tgz
AddType application/x-tar .tgz
# =================================================
# Logs
# =================================================
LogLevel warn
LogFormat “%h %l %u %t \”%r\” %>s %b \”%{Referer}i\” \”%{User-Agent}i\”" combined
LogFormat “%h %l %u %t \”%r\” %>s %b” common
LogFormat “%{Referer}i -> %U” referer
LogFormat “%{User-agent}i” agent
ErrorLog /usr/local/apache2/logs/error_log
CustomLog /usr/local/apache2/logs/access_log combined
# =================================================
# Virtual hosts
# =================================================
NameVirtualHost *
<VirtualHost *>
DocumentRoot “/web/vhosts/abc.com”
ServerName “abc.com”
ServerAlias “www.abc.com”
ErrorLog logs/abc.com/error_log
CustomLog logs/abc.com/access_log combined
</VirtualHost>
<VirtualHost *>
DocumentRoot “/web/vhosts/www.def.com”
ServerName “www.def.com”
ServerAlias “def.com”
ErrorLog logs/www.def.com/error_log
CustomLog logs/www.def.com/access_log combined
</VirtualHost>
Final step
If your Apache now works properly, the only thing that is left to do is to create a script that will start Apache during system boot. In order to do this, the apache.sh script can be used, with the following content:
#!/bin/sh
# chkconfig: 2345 21 80
# description: apache
# Begin /etc/init.d/apache
. /etc/init.d/functions
case “$1″ in
start)
echo “Starting Apache …”
/usr/sbin/chroot /chroot/httpd /usr/local/apache2/bin/httpd
echo “Done!”
;;
stop)
echo “Stopping Apache …”
kill `cat /chroot/httpd/usr/local/apache2/logs/httpd.pid`
echo “Done!”
;;
restart)
echo “Stopping Apache …”
kill `cat /chroot/httpd/usr/local/apache2/logs/httpd.pid`
echo “Done!”
echo “Starting Apache …”
/usr/sbin/chroot /chroot/httpd /usr/local/apache2/bin/httpd
echo “Done!”
;;
*)
echo “”
echo “Usage: /etc/init.d/apache {start|stop|restart}”
exit 64
;;
esac
exit 0
In case of our CentOS system, the above script should be placed in the /etc/init.d directory, under the name of mysql.
Make the script executable:
chmod +x /etc/init.d/apache
To make the script run at boot time:
chkconfig --add apache
To run the script manual:
/etc/init.d/apche start|stop|restart
In case of FreeBSD system, the above script should be placed in the /usr/local/etc/rc.d directory, under the name of apache.sh
To make the script run at boot time:
chmod +x /usr/local/etc/rc.d/apache.sh
To run the script manual:
/usr/local/etc/rc.d/apache.sh start|stop|restart
No comments:
Post a Comment