This chapter presents the implementation of a LAMP platform (Linux, Apache, MySQL, PHP). It describes the installation method, service specific elements, as well a the initial configuration.
Mandriva Enterprise Server 5 provides a number of packages to install the Apache web server, including respectively the server itself, tools and modules.
You can complete this list
according to your needs and install more modules to handle PHP
scripts, SSL secure connections, authentication, etc. These packages
are names
apache-mod_*.
/var/www :/var/log/httpd/ :/etc/httpd :/etc/httpd/conf :
contains all the basic configuration files of the
server ;
/etc/httpd/conf/fileprotector.conf :
rules to protect critical files
(eg. : php) ;
/etc/httpd/conf/httpd.conf :
server's main configuration file;
/etc/httpd/conf/vhosts.d :
directory containing the
virtualhosts' configuration
files;
/etc/httpd/conf/webapps.d :
configuration files for web applications;
/etc/httpd/conf.d :
contains links to
Apache modules, library, log files, module's configuration
files.
In the
server section, click on the Apache
server icon. The welcome screen is divided in two
parts, general configuration and virtual server configuration.
virtualhost refers to the possibility of
hosting many sites on the same Apache server. The global
configuration applies to all virtual hosts.
The standard configuration
provided often works without any modification. One of the
most used features is virtualhosts. To activate them, make sure you
have to following 2 lines in
/etc/httpd/conf/httpd.conf :
NameVirtualHost *:80
Include conf/vhosts.d/*.conf
You only have to declare
them in a file indicating the DocumenRoot (where the files are physically) and the
ServerName (to identify the virtual
host). According to the default configuration provided with
Mandriva Linux, you need to provide a file named
*.conf placed in
/etc/httpd/conf/vhosts.d.
Let's illustrate our discussion with an example :
<VirtualHost *:80>
DocumentRoot /var/www/html/test1
ServerName www.test1.com
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /var/www/html/test2
ServerName www.test2.org
</VirtualHost>
The initscript
/etc/init.d/httpd has options to manage the
start, stop and information queries:
# service httpd stop
Shutting down httpd: [ OK ]
# service httpd start
Starting httpd: [ OK ]
# service httpd restart
Shutting down httpd: [ OK ]
Starting httpd: [ OK ]
Reload the configuration du serveur :
# service httpd reload
Reloading httpd: [ OK ]
# service httpd status Apache is running. httpd: 12137 12136 12135 12134 12133 12132 12131 12130 12122
# service httpd extendedstatus
Apache Server Status for localhost
Server Version: Apache/2.2.9 (Mandriva Linux/PREFORK-12mdv2009.0)
mod_ssl/2.2.9 OpenSSL/0.9.8h PHP/5.2.6 with Suhosin-Patch
Server Built: Sep 20 2008 03:50:58
__________________________________________________________________
Current Time: Wednesday, 06-May-2009 11:42:39 CEST
Restart Time: Wednesday, 06-May-2009 11:42:37 CEST
Parent Server Generation: 0
Server uptime: 1 second
Total accesses: 0 - Total Traffic: 0 kB
CPU Usage: u0 s0 cu0 cs0
0 requests/sec - 0 B/second -
1 requests currently being processed, 7 idle workers
W_______........................................................
................................................................
................................................................
................................................................
Scoreboard Key:
"_" Waiting for Connection, "S" Starting up, "R" Reading Request,
"W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
"C" Closing connection, "L" Logging, "G" Gracefully finishing,
"I" Idle cleanup of worker, "." Open slot with no current process
#######################################
#######################################
Check Apache configuration d'Apache (httpd.conf) :
# service httpd configtest checking apache configuration integrity : [ OK ]
Check virtual host configuration :
# service httpd configtest_vhosts checking apache configuration integrity : [ OK ]
Starting the server in debug mode during pre-production tests :
# service httpd debug Starting httpd (debug mode and in the foreground): [Fri Sep 01 05:51:53 2008] [notice] core dump file size limit raised to 4294967295 bytes [Fri Sep 01 05:51:53 2008] [info] mod_unique_id: using ip addr 192.168.40.140 [Fri Sep 01 05:51:54 2008] [notice] Digest: generating secret for digest authentication ... [Fri Sep 01 05:51:54 2008] [notice] Digest: done [Fri Sep 01 05:51:54 2008] [info] mod_unique_id: using ip addr 192.168.40.140
Apart from the commands suggested above, you can validate the proper operation of the server with telnet on port 80 or 443 :
By default, a private key and
a certificate are issued during the installation. To generate
keys, you need openssl. Keys and certificates
are kept, by default, in
/etc/pki/tls/private/localhost.key and
/etc/pki/tls/certs/localhost.crt.
You need to edit a section
in the file
/etc/httpd/modules.d/41_mod_ssl.default-vhost.conf
to enable the certificate on part of the server.
<IfDefine HAVE_SSL> <IfModule !mod_ssl.c>
LoadModule ssl_module modules/mod_ssl.so </IfModule>
</IfDefine>
<IfModule mod_ssl.c>
NameVirtualHost 192.168.40.119:443
<VirtualHost toto:443>
ServerName toto
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
DocumentRoot /var/www/html/vhost4
ErrorLog logs/ssl_error_log
<IfModule mod_log_config.c>
TransferLog logs/ssl_access_log
</IfModule>
</VirtualHost>
</IfModule>
Reload your server, you
should now be able to access the URL
https://192.168.40.119 and accept the
certificate for your machine.
Securing Apache essentially implies modifying the base configuration provided
during installation, mainly located in
/etc/httpd/conf/httpd.conf.
First, delete the service
banner, as it provides valuable information to guide attackers. In
/etc/httpd/conf/httpd.conf :
ServerSignature Off
ServerTokens Prod
$ HEAD http://dhcp140 200 OK Connection: close Date: Wed, 06 May 2009 09:43:52 GMT Accept-Ranges: bytes ETag: "1bdd3-d7-452ee8885b240" Server: Apache/2.2.9 (Mandriva Linux/PREFORK-12mdv2009.0) Content-Length: 215 Content-Type: text/html Last-Modified: Sat, 26 Jul 2008 14:59:13 GMT Client-Date: Wed, 06 May 2009 09:43:52 GMT Client-Peer: 192.168.40.140:80 Client-Response-Num: 1
$ HEAD http://dhcp140 200 OK Connection: close Date: Wed, 06 May 2009 09:50:04 GMT Accept-Ranges: bytes ETag: "1bdd3-d7-452ee8885b240" Server: Apache Content-Length: 215 Content-Type: text/html Last-Modified: Sat, 26 Jul 2008 14:59:13 GMT Client-Date: Wed, 06 May 2009 09:50:04 GMT Client-Peer: 192.168.40.140:80 Client-Response-Num: 1
We also recommend deleting
the name resolution: it creates unnecessary network traffic. In
/etc/httpd/conf/httpd.conf:
HostnameLookups Off
Also, let's delete the
possibility for users to publish web pages from their
/home directories (Apache
mod_userdir module). This module is no longer installed
by default, but lets make sure it's not there:
# rpm -qa | grep apache-mod_userdir
Comment the following line in
/etc/httpd/conf/httpd.conf :
# LoadModule userdir_module modules/mod_userdir.so
Forbid page index posting:
in the directives definition <Directory>,
disable Indexes as much as possible. Check for
the presence of the <Directory /> directive
in /etc/httpd/conf/httpd.conf. It must
include at least the following elements :
<Directory />
Options -Indexes
AllowOverride None
</Directory>
If you use virtualhosts on this machine, create a “virtualhost catch-all”. This way, if a visitor launches a request on the IP address instead of the “virtualhost” name, you will be able to control the page posted.
<VirtualHost _default_:*>
DocumentRoot /var/www/html/defaut
</VirtualHost
Remember to create the
matching directory for the specified
DocumentRoot and place an
index.html file within this directory.
It is also very useful to have specific log files for each virtualhost to quickly identify future problems. This will give you the following log file tree (to create):
/var/log/httpd/ |-virtualhost1 | |-access_log | `-error_log |-virtualhost2 | |-access_log | `-error_log ...
Below, you have an example of a vitrualhost configuration file using this log file separation:
# cat /etc/httpd/conf/vhosts.d/virtualhost1
<VirtualHost 172.20.30.40>
DocumentRoot /var/www/html/virtualhost1
ServerName virtualhost1.domaine.com
ErrorLog logs/virtualhost1/error_log
CustomLog logs/virtualhost1/access_log combined
</VirtualHost>
You also need to update the Apache log rotation system to take the new log files into account :
# cat /etc/logrotate.d/httpd
/var/log/httpd/*_log /var/log/httpd/virtualhost1/*_log
/var/log/httpd/apache_runtime_status /var/log/httpd/ssl_mutex {
rotate 5
monthly
missingok
notifempty
nocompress
prerotate
/etc/rc.d/init.d/httpd closelogs > /dev/null 2><1
endscript
postrotate
/etc/rc.d/init.d/httpd closelogs > /dev/null 2><1
endscript
}
Only PHP5 is provided by Mandriva Enterprise Server 5. By default, PHP5 is compiled with the hardened-php patch that increases security, such as disabling unsecured code. More info is available at: the hardened PHP project site.
The main package to install is apache-mod_php which will modify the Apache configuration to take php into account and restart Apache. You will also have to satisfy some dependencies with some basic php modules required in most configurations.
To setup a “LAMP” environment, you'll also need to install the Apache module enabling SQL support for PHP: php-mysql
PHP configuration is mainly
done within the /etc/php.ini file. Each
feature is introduced in [bloc ] form. Each variable is described
as following:
variable = value
The default file is usually enough to have a working php environment. We will look at improving php security in the next chapter.
Mandriva Enterprise Server 5 contains the
following difference: /etc/php.d. To simplify
your php.ini file, all dynamic modules have
their own dedicated file in /etc/php.d and
are included in the global configuration. By default, we have the
following files: :
# ls /etc/php.d 12_ctype.ini 22_ftp.ini 37_mysqli.ini 57_sysvsem.ini 13_curl.ini 23_gd.ini 42_pgsql.ini 58_sysvshm.ini 18_dom.ini 24_gettext.ini 43_posix.ini 60_tokenizer.ini 21_openssl.ini 26_iconv.ini 47_session.ini 62_xml.ini 21_zlib.ini 28_ldap.ini 54_hash.ini 62_xmlrpc.ini 63_xmlreader.ini 64_xmlwriter.ini 70_pdo.ini 78_sqlite.ini 81_filter.ini 82_json.ini 98_suhosin.ini
We suggest a number of
improvements to the default configuration. All of these should be
accomplished within /etc/php.ini.
Disable global variables if applications support it:
register_globals = Off
Remove php information from the banner: php availability will not appear in the server banner:
expose_php = Off
Disable the posting of error messages for php scripts as these may give vulnerability information:
display_errors = Off
Activate php logs to quickly debug scripts from the logs generated by the syslogd deamon:
log_errors = Off
error_log = syslog
file_uploads = Off
magic_quotes_gpc = Off
magic_quotes_runtime = Off
magic_quotes_sybase = Off
Prevent external module loading :
enable_dl = Off
Forbid treating URLs as files: this parameter would allow you to download from another server :
allow_url_fopen = Off
Delete . from the library path: should be used with caution since some scripts may not work anymore :
include_path = "/usr/lib/php/:/usr/share/pear/"
Sandbox the execution of php scripts: limits the directories allowed to run php scripts. You can specify many directories, separated with commas :
open_basedir = /var/www/html/appli
With virtualhosts, this option is more significant if specified in the virtualhosts' configuration file, which refines the behavior of php :
<VirtualHost 127.0.0.1>
DocumentRoot /var/www/html/virtualhost1/html
ServerName virtualhost1.domaine.com
php_admin_value open_basedir /var/www/html/virtualhost1
</VirtualHost>
Specify unauthorized functions in scripts which can endanger the system security. You may specify many functions, separated by commas :
disable_functions = exec,system
$ lynx -dump http://fr.php.net/manual/fr/ref.filesystem.php |
grep 'function\.' | awk -F'.' '{ print $5 }'
This section aims at establishing a caching proxy, mainly for clients using the HTTP protocol (see FTP). Main functions are :
Squid is an Internet proxy server providing many functions.
A proxy server acts as an intermediary between the client and the resource to reach. It optimizes the original request and controls its validity. Here, request optimization is done through the use of a local copy of the most requested Internet resources: the cache.
When a client requests a resource, the proxy checks if it has a recent copy of this resource. If this is the case, it returns the local copy, instead of letting the client access the distant resource. This reduces outside traffic accordingly.
SSquid is a service daemon listening on a determined HTTP/HTTPS/FTP port (3128 by default, 8080 is often used for proxy).
When a request is received, the proxy validates the following authorizations :
Is the machine that sends this request included in an IP range authorized for this service? Is the user specified (when authorization is used) allowed to use this service? Does the schedule allow you to access this service at this time?
If one of these conditions is not fulfilled, the proxy returns a significant error. If not, the procedure continues with the verification of the content on cache (in the case of a caching-proxy). One of the following behaviors is then possible :
The requested resource is not in cache. Squid relays this request to through the web (and keeps a copy in cache) ;
The requested resource is in cache. If this resource is not too old, this local copy will be returned to the client. (if not, Squid relays the request to through the web and keeps a copy in cache.
Squid configuration is based on the creation of access control list (ACL) for the HTTP resource. This control is based on the filters concerning: source, destination, schedule, protocols (HTTP/HTTPS/FTP) and methods used (GET/POST).
These
ACLs can establish access authorization as well
as the resource caching. ACL configuration is
located in /etc/squid/squid.conf.
acl aclname proxy_auth username ... acl aclname proxy_auth_regex [-i] pattern ...
acl aclname src ip-address/netmask ... (clients IP address) acl aclname src addr1-addr2/netmask ... (range of addresses)
acl aclname srcdomain .foo.com ... # reverse lookup, client IP
Number of simultaneous connections for a given client :
acl aclname maxconn number acl aclname max_user_ip [-s] number
acl aclname browser [-i] regexp ... # pattern match on User-Agent header
acl aclname dst ip-address/netmask ... (URL host's IP address) acl aclname dstdomain .foo.com ... # Destination server from URL
acl aclname dstdom_regex [-i] xxx ... # regex matching server acl aclname url_regex [-i] ^http:// ... # regex matching on whole URL acl aclname urlpath_regex [-i] \.gif$ ... # regex matching on URL path
acl aclname time [day-abbrevs] [h1:m1-h2:m2]
Protocols (HTTP/HTTPS/FTP) and methods (GET/POST/) :
acl aclname proto HTTP FTP ... acl aclname method GET POST ...
This list is not complete, but illustrates the most common ACLs.
By default, the server listens on port 3128 and no client/network is authorized to pass through the proxy.
http_port 3128 #Recommended minimum configuration: acl all src 0.0.0.0/0.0.0.0 acl localhost src 127.0.0.1/255.255.255.255 http_access allow localhost http_access deny all
Only the proxy (acl localhost src 127.0.0.1/255.255.255.255) is authorized to use the (http_access allow localhost). All other machines, no matter what their IP is, (acl all src 0.0.0.0/0.0.0.0) will have their request denied (http_access deny all).
To authorize the local network to use the proxy, it must be declared with an ACL which specifies the appropriate network :
acl MyNetworks src 10.0.0.0/24 192.168.0.0/24
http_access allow MyNetworks
Which gives the following configuration :
acl all src 0.0.0.0/0.0.0.0 acl localhost src 127.0.0.1/255.255.255.255 acl MyNetworks src 10.0.0.0/24 192.168.0.0/24 ... http_access allow localhost http_access allow MyNetworks http_access deny all
We can consider modifying the “all” ACL instead of adding a new one, but that may cause a problem, since there is no default policy.
Here is a combination of ACLs on the IP and the schedule :
You must first define the network(s) concerned :
acl MyNetworks src 10.0.0.0/24
192.168.0.0/24
Then, the connection schedule (monday to friday, 8 h 30 à 18 h 30) :
acl WORKING time MTWHF 08:30-18:30
Assemble the two ACLs so that machines from the specified network(s) may use the proxy during the defined schedule :
http_access allow MyNetwork WORKING
Which gives us the following global configuration :
acl all src 0.0.0.0/0.0.0.0 acl localhost src 127.0.0.1/255.255.255.255 acl MyNetworks src 10.0.0.0/24 192.168.0.0/24 acl WORKING time MTWHF 08:30-18:30 ... http_access allow localhost http_access allow MyNetworks WORKING http_access deny all
The cache is the memory of Squid. Like access, it is possible to use ACLs to authorize or deny caching of certain objects. In general, we will not cache dynamic pages, such as CGI, and general requests with a “?” in the URL.
acl QUERY urlpath_regex cgi-bin \?
no_cache deny QUERY
The cache works with a system of disk swap. Most recent objects are kept in memory, while older ones a kept on disk. Hence, you need to adjust the size of the memory cache (directive cache_mem, by default 8M) and on disk (directive cache_dir, 100M by default) according to your Internet load to reduce swapping.
You also need to establish minimum and maximum size of the objects to put in your cache. (directives minimum_object_size – default 0KB, maximum_object_size - default 4096KB, maximum_object_size_in_memory – default 8KB). To have an efficient cache, make sure you have enough RAM and fast disk drives (SCSI).
You can set up authentication to validate that a user, identified by his login and password, has the rights (or not) to surf the Web. This authentication can be based on by many user management structure: LDAP, NCSA (.htpasswd), MSNT/SMB/winbind/NTLM, PAM, getpwam (based on /etc/passwd), sasl, Digest. We will use LDAP.
Authentication is validated by an external programm (squid_ldap_auth) which returns true or false for login and password match.
Therefore, you need to create an ACL that calls authentication, (acl ACLName proxy_auth REQUIRED), and associate it to the ACL which defines request sources (in this case, external networkds acl ACLName src 10.0.0.0/24).
auth_param basic children 5 auth_param basic program /usr/lib/squid/squid_ldap_auth -v 3 -b ou=Users,dc=example,dc=com localhost auth_param basic realm Example.com Squid Server auth_param basic credentialsttl 2 hours ... acl password proxy_auth REQUIRED ... acl all src 0.0.0.0/0.0.0.0 acl localhost src 127.0.0.1/255.255.255.255 acl MyNetworks src 10.0.0.0/24 192.168.0.0/24 ... http_access allow localhost http_access allow MyNetworks password http_access deny all
![]() |
Tip |
|---|---|
The squid package provides the squidclient command. This allows you to quickly test the proper functioning of your server and returns the entire dialog between client and server on the shell. |
squidclient http://localhost HTTP/1.0 200 OK Date: Fri, 01 Sep 2008 10:11:24 GMT Server: Apache Last-Modified: Fri, 28 Jul 2008 10:57:38 GMT ETag: "4355-2c-2e3d2c80" Accept-Ranges: bytes Content-Length: 44 Content-Type: text/html X-Cache: MISS from unconfigured Via: 1.0 unconfigured:3128 (squid/2.6.STABLE1) Proxy-Connection: close <html><body><h1>It works!</h1></body></html>