1. Managing web services: LAMP and Proxy

1.1. Managing a LAMP server

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.

More information is available at:

1.1.1. Apache installation and tree.

Mandriva Enterprise Server 5 provides a number of packages to install the Apache web server, including respectively the server itself, tools and modules.

  • apache-mpm-prefork : contains the server daemon, MPM (Multi-Processing Module). If you chose to install Mandriva Server Setup, apache-mpm-prefork was automatically installed  ;

  • apache-base : includes Apache tools such as Apache Bench (ab) for load testing, tools and logs;

  • apache-modules : contains the Apache base modules;

  • apache-conf : contains all the Apache configuration files;

  • apache-doc : contains the Apache official documentation.

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_*.

Here is the Apache tree:

Data: /var/www :
  • /var/www/ : data root provided by Apache (DocumentRoot) ;

  • /var/www/cgi-bin: CGI script directory;

  • /var/www/error : http errors pages;

  • /var/www/html : root;

  • /var/www/admin : location of the web applications for management

  • /var/www/icons : icons in the public domain available for your applications;

  • /var/www/perl : perl scripts.

Apache logs : /var/log/httpd/ :
  • /var/log/httpd/access_log : page access logs ;

  • /var/log/httpd/error_log : error logs.

Apache executables:
  • /usr/sbin : all the server's executables and tools;

  • /etc/init.d/httpd : initscript for Apache.

Apache configuration files: /etc/httpd :
  • /etc/httpd : Apache configuration root (ServerRoot) ;

  • /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/mime.types : MIME type configuration;

  • /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.

1.1.2. Configure an Apache server

1.1.2.1. Basic Configuration

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.

[Warning] Warning

If you are using virtual servers with HTTPS, you must provide only 1 server per IP address.

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>

Restart Apache and test.

[Tip] Tip

To facilitate your administration, it is recommended that you plan a configuration file and a log file per virtualhost.

1.1.2.2. Apache management toolkit

The initscript /etc/init.d/httpd has options to manage the start, stop and information queries:

  • Stopping the server:

    # service httpd stop
           Shutting down httpd:			[  OK  ]
  • Starting the server :

    # service httpd start
           Starting httpd:					[  OK  ]
  • Restarting the server :

    # service httpd restart
           Shutting down httpd:			[  OK  ]
           Starting httpd:					[  OK  ]
  • Reload the configuration du serveur :

    # service httpd reload
           Reloading httpd:					[  OK  ]
  • View Server status :

    # service httpd status
    Apache is running.
    httpd: 12137 12136 12135 12134 12133 12132 12131 12130 12122
  • Extended status :

    # 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

    Detailed messages will appear in the console.

Apart from the commands suggested above, you can validate the proper operation of the server with telnet on port 80 or 443 :

  • A working server:

    # telnet example.com 80
    Trying 192.168.40.140...
    Connected to example.com (192.168.40.140).
    Escape character is '^]'.
  • A non-working server:

    # telnet example.com 80
    Trying 192.168.40.140...
    telnet: connect to address 192.168.40.140: Connection refused
    telnet: Unable to connect to remote host: Connection refused

1.1.3. Apache Advance configuration

1.1.3.1. https configuration
[Note] Note

You must have the apache-mod_ssl rpm installed.

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.

[Tip] Tip

Generating your own key

Run the following operations in the /etc/pki/tls/private/directory :

# openssl genrsa -des3  -out server.key 1024 

Remove the password from the private key: :

# openssl rsa -in server.key -out server.pem

Generate the new certificate. To do this, enter the command below. You can also enter the default certificate value by editing this file /usr/lib/ssl/openssl.cnf.

# openssl req -new -key server.key -out server.csr

You can sign it yourself with the following, if you do not have a certificate authority :

# openssl x509 -req -days 60 -in server.csr 
-signkey server.key -out server.crt

configuration files are :

  • /etc/cron.daily/certwatch

  • /etc/httpd/modules.d/40_mod_ssl.conf

  • /etc/httpd/modules.d/41_mod_ssl.default-vhost.conf

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.

1.1.4. Securing Apache

1.1.4.1. Securing the configuration de base

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

To check,use command HEAD :

  • with the banner :

    $ 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
  • without the banner :

    $ 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>
1.1.4.2. Securing virtualhosts

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
}
    

1.1.5. Enabling PHP

1.1.5.1. Installing and configuring PHP

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
1.1.5.2. PHP: improve the basic configuration

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
  • Disable file upload :

    file_uploads = Off
  • Disable magic quotes :

    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
[Tip] Tip

To establish the list of functions :

$ lynx -dump http://fr.php.net/manual/fr/ref.filesystem.php | 
grep 'function\.' | awk -F'.' '{ print $5 }'

1.2. Proxy setup

This section aims at establishing a caching proxy, mainly for clients using the HTTP protocol (see FTP). Main functions are :

  • Bandwidth optimization, when clients request the same resource ;

  • Access control and filtering (content, service authentication, schedule).

Squid is an Internet proxy server providing many functions.

1.2.1. Concepts

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.

1.2.2. Installation and file tree

Installation is straight forward. You simply need to install the squid package.

Here are the main components of the tree structure :

  • /etc/squid : contains squid's configuration files and squid.conf ;

  • /usr/lib/squid : outils tools such as cachemgr.cgi and squid_ldap_auth ;

  • /var/log/squid : contains squid server logs files ;

  • /var/spool/squid : contains the server cache.

1.2.3. Squid server configuration Squid

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).

1.2.3.1. ACL locations

These ACLs can establish access authorization as well as the resource caching. ACL configuration is located in /etc/squid/squid.conf.

Configuring the source
  • Password authentication :

    acl aclname proxy_auth username ...  acl aclname
    	  proxy_auth_regex [-i] pattern ...
  • IP address of the source :

    acl aclname src ip-address/netmask
    	 ... (clients IP address) acl aclname src addr1-addr2/netmask
    	 ... (range of addresses)
  • Source domain :

    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
  • Browser :

    	 acl aclname browser [-i] regexp ...
    # pattern match on
    	 User-Agent header
Configuring the destination
  • Destination domain :

    acl aclname dst ip-address/netmask ... (URL
    	 host's IP address) acl aclname dstdomain .foo.com ...  
    # Destination server from URL
  • 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
  • Connection schedule :

    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.

1.2.3.2. Access configuration

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

We must authorize this ACL:

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 :

  1. You must first define the network(s) concerned :

    acl MyNetworks src 10.0.0.0/24
           192.168.0.0/24
  2. Then, the connection schedule (monday to friday, 8 h 30 à 18 h 30) :

    acl WORKING time MTWHF
    	08:30-18:30
  3. 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
1.2.3.3. Configuring the cache

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).

[Tip] Tip

The FAQ states the following rule: you need 10MB of RAM for each GB of disk cache. Also, it is recommended that you have twice as much RAM as that which is required by Squid.

1.2.4. Access Authentication using LDAP

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] 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>