Apache server – the base

 

  • Introduction

  • Installation

    • Start up and test after installation

  • Basic Configuration

    • Main File

    • Files Include

  • Default Virtual Host

  • Server settings

    • Configuring the Directory Configuration

      • Changing the root directory (DocumentRoot)

      • Access authorization by hostname or ip (Require)

      • Using Virtual Host by default (good practice)

    • Organization of the configuration (context)

    • Overdefinition of the configuration in the .htaccess file

      • Permission to redefine configurations

    • Good practice using the .htaccess file

  • VirtualHost

    • Virtual servers by IP

    • Virtual Servers by Name

  • Organization of websites

    • Organization of virtual server directories

    • Apache configuration for virtual servers

    • Configuring logs for virtual servers

      • Rotating logs for virtual servers

    • Using the private directory

    • Using the configuration overload (htaccess)

    • Shared content / service (Alias)

    • Directory permissions

  • Using apache modules

  • Setting up a site in httpS

    • Theory of how certificates work

      • What is a Certificate?

      • Detail of the httpS communication

        • Protocols negotiation process supported

        • Certificate validation process

        • Exchange of a symmetric key

        • Detailed graphic representation of the SSL protocol

    • Simple configuration of a website with mod_ssl

Introduction

Apache appeared in April 1995. At first, it was a collection of fixes and additions to the NCSA HTTPd 1.3 server, which was in the public domain and the most popular HTTP server. From this origin, many people claim that the Apache name comes from a patchy server, “a patched server”. Subsequently, Apache was completely rewritten, so that in version 2, there is no trace of NCSA HTTPd.

At first, Apache was the only serious and free alternative to the Netscape HTTP server (iPlanet, now Sun ONE). Since April 1996, according to Netcraft2’s ongoing study, Apache has become the most popular HTTP server on the Internet.

Apache market share:

 

  • In May 1999, it was running 57% of the Web servers, at the beginning of 2004, it was about 69% of market share, and it holds only 50,61% of the market at the end of January 2008;

  • In February 2008, Apache accounted for 50.93% of market share;

  • In November 2008, 72.45% market share for Apache;

  • In November 2011, 65.00% market share for Apache;

  • In May 2014, 38.00% market share for Apache and 33.00% for Microsoft IIS.

  • In January 2015 on the analysis of 876,812,666 sites, corresponding to 5,061,365 front-end computers, the market shares are 39.74% for Apache, and 27.52% for IIS. On the market share of active servers (excluding parking sites) by cons, 50.72% for Apache, 14.82% for Nginx and IIS is in 3rd position with only 10.55%, losing 1.17% share compared to the previous month.

The popularity of GNU / Linux owes much to the Apache web server and the rise of the Internet. It is undeniable that the organizations were looking for a “free” solution and performance to provide Internet service. Sometimes it does not take much for the popularity of an application or system to see the day …

We will see the structure of the software, Apache function with a module system to add features. Apache configuration this structure according to a parameter hierarchy defined under context, allowing us to define values in a granular way.

Good finish the intro we will play a little: D.

 

Installation

If there is an application tested and validated in a distribution is the Apache! To my knowledge all the distributions offer the software. Of course the installation may be different, here’s how to proceed for Ubuntu and Redhat.

# Pour Ubuntu $ sudo apt-get install apache2 # Pour RedHat $ sudo yum install httpd

If we look at the file structure we will see that it differs for Ubuntu:

$ ls -l /etc/apache2/ total 80 -rw-r--r-- 1 root root 7115 Jan 7 2014 apache2.conf drwxr-xr-x 2 root root 4096 Nov 25 08:20 conf-available drwxr-xr-x 2 root root 4096 Nov 25 08:20 conf-enabled -rw-r--r-- 1 root root 1782 Jan 3 2014 envvars -rw-r--r-- 1 root root 31063 Jan 3 2014 magic drwxr-xr-x 2 root root 12288 Nov 25 08:20 mods-available 1drwxr-xr-x 2 root root 4096 Nov 25 08:20 mods-enabled -rw-r--r-- 1 root root 320 Jan 7 2014 ports.conf drwxr-xr-x 2 root root 4096 Nov 25 08:20 sites-available drwxr-xr-x 2 root root 4096 Nov 25 08:20 sites-enabled

And now for Redhat:

$ ls -l /etc/httpd/ total 8 drwxr-xr-x 2 root root 4096 Nov 20 09:29 conf drwxr-xr-x 2 root root 4096 Nov 20 09:29 conf.d lrwxrwxrwx 1 root root 19 Nov 20 09:29 logs -> ../../var/log/httpd lrwxrwxrwx 1 root root 27 Nov 20 09:29 modules -> ../../usr/lib/httpd/modules lrwxrwxrwx 1 root root 19 Nov 20 09:29 run -> ../../var/run/httpd

Start up and test after installation

Starting the Apache service:

# Pour Ubuntu $ sudo service apache2 start * Starting web server apache2 # Pour RedHat $ sudo service httpd start

You can now validate the installation by going to the URL http: // server-IP or http://127.0.0.1 if the installation is done directly on your computer. Here is the result for Ubuntu:

default<em>page</em>ubuntu.png

We will now put a small web page to show that we are able to edit the content. You can use your favorite editor to create the file /var/www/html/demo.html

$ cat /var/www/html/demo.html Bonjour Ceci fonctionne bien

To validate that everything is working fine you can go to the URL http: //IP-du-server/demo.html or http://127.0.0.1/demo.html. Already at this point it is possible to have his website available by installing all of your files in this directory.

We will now go a little further with the analysis of the configuration and better understand how all this works.

 

 

Configuration de Base

The whole writing of the configuration file is equivalent for both systems, the important thing is to know that it is the first file that is read when starting Apache. We will see when reading the configuration file that the first file makes include calls to load (“loader”) the other configuration files.

Main File

The main file is:

  • Redhat : /etc/httpd/conf/httpd.conf

  • Ubuntu : /etc/apache2/apache2.conf

NOTE / Info In order not to overload the training by duplicating the demonstrations of Ubuntu and Redhat we will focus only on Ubuntu. However the whole is equivalent between the 2 systems, because it is the same software, possibly if you do not manage to do the transposition, contact me I will put you on the track.

Redhat’s configuration is more linear than Ubuntu’s, but well we can not change the reference system each time just because one is simpler than the other ;-). We chose Ubuntu, we continue: D.

Visualization of the main file, To avoid overloading the documentation I will not put the complete file here however it is available by clicking on the link: /etc/apache2/apache2.conf

When reading the file we find that there is a lot of comment defined, like a lot of configuration file under GNU / Linux the character # (pound) is used. If we delete all comments as well as blank lines this gives:

 

$ cat /etc/apache2/apache2.conf | grep -v "^#" | grep -v "^$" Mutex file:${APACHE_LOCK_DIR} default PidFile ${APACHE_PID_FILE} Timeout 300 KeepAlive On MaxKeepAliveRequests 100 KeepAliveTimeout 5 User ${APACHE_RUN_USER} Group ${APACHE_RUN_GROUP} HostnameLookups Off ErrorLog ${APACHE_LOG_DIR}/error.log LogLevel warn IncludeOptional mods-enabled/*.load IncludeOptional mods-enabled/*.conf Include ports.conf Options FollowSymLinks AllowOverride None Require all denied AllowOverride None Require all granted Options Indexes FollowSymLinks AllowOverride None Require all granted AccessFileName .htaccess <FilesMatch "^.ht"> Require all denied LogFormat "%v:%p %h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" vhost_combined LogFormat "%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined LogFormat "%h %l %u %t "%r" %>s %O" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent IncludeOptional conf-enabled/*.conf IncludeOptional sites-enabled/*.conf

39 Lines to dissect, given the extent of the work that Apache does it is not much: D, let’s be positive. We will also see that taken line by line the configuration is very simple … Especially when it’s been 15 years that we consult: P.

We will also rely on solid documentation available on the Apache website:

 

  • Ubuntu 14.04 (apache version 2.4 ) : https://httpd.apache.org/docs/2.4/

  • Redhat 6 (apache version 2.2) : https://httpd.apache.org/docs/2.2/.

We see in the variable file designated as $ {VariableName} the set of values are available in the file / etc / apache2 / envvars which here is the content

export APACHE_RUN_USER=www-data export APACHE_RUN_GROUP=www-data export APACHE_PID_FILE=/var/run/apache2/apache2$SUFFIX.pid export APACHE_RUN_DIR=/var/run/apache2$SUFFIX export APACHE_LOCK_DIR=/var/lock/apache2$SUFFIX export APACHE_LOG_DIR=/var/log/apache2$SUFFIX

The set of values will not be covered not that it is not interesting, we will be able to take the time in the future to dig deeper into detail. The goal for the moment is to be able to understand and configure Apache simply. Optimization and configuration improvement can be seen eventually in the future, we’ll talk about it again.

  • Global configuration

    • Timeout 300: Time in seconds that the server will wait for sending or receiving instructions to the client

    • KeepAlive On: Enables the ability to use persistent connections as defined in the HTTP 1.1 protocol

    • User $ {APACHE_RUN_USER}: Defines under which user the apache service will be executed, this prevents the service from running as a system administrator. The advantage is that if the apache service is compromised, the attacker only gets the rights allocated to the user APACHE_RUN_USER. Under Ubuntu the user is www-data

    • Group $ {APACHE_RUN_GROUP}: As for the user here we define the group that runs the application under Ubuntu the value is: www-data

    • HostnameLookups Off: When the connection is established by a client it is possible to do reverse DNS on the IP address in order to have the name of the client instead of the ip. Generally this configuration is OFF so as not to overload the unnecessary DNS query server as this slows down the response time of the apache server.

    • ErrorLog $ {APACHE_LOG_DIR} /error.log: Important definition of the log file containing the errors :). It is very likely that we will have to consult it :).

    • LogLevel warn: This makes it possible to define the level of severity of the alerts well, it is very rare that I change this values.

  • Inclusion

    • IncludeOptional mods-enabled / *. Load: With the statement IncludeOptional it is possible to load another configuration file in order to segment the files so that it is easier to read or to allow file editing for somebody without offering the main file. In this case the system loads the available modules installed on the system. (We will come back to the modules later)

    • IncludeOptional mods-enabled / *. Conf: Same as the previous statement but instead of loading the module files, we load the module configurations. (We will come back to the modules later)

    • Include ports.conf: Inclusion of the definition file containing the listening port, we will find in this file the instruction Listen this instruction indicates on which port to listen to receive the requests clients.

    • IncludeOptional conf-enabled / *. Conf: Allows you to include the configurations that must be active.

    • IncludeOptional sites-enabled / *. Conf: Allows you to load the configuration of sites that must be available on the server.

  • Directory The Directory statement sets permissions and configuration that are specific to the directory on the server’s file system. We will see that it is also possible with the Location statement to set permissions according to the URL of the website. The configuration defined for the parent directory is inherited by default at the child directory. In the configuration defined below all the directories under / var / www have the permissions defined by Directory / var / www, for the directory / home / bob or / tmp / they will have the permissions defined by the instruction Directory / . We will come back to the configurations and permission for the moment to see the default configuration.

    Options FollowSymLinks AllowOverride None Require all denied AllowOverride None Require all granted Options Indexes FollowSymLinks AllowOverride None Require all granted
  • LogFormat Definition of the log format during client access, this makes it possible to collect more information such as the user (% u) the request (% r) according to a defined order. This is mainly used when your static management system wants to have a particular format. 99% of the time I use vhost_combined that meets my need and my statistics software. Note: with version 2.4 it is also possible to change the format of the error message.

    LogFormat "%v:%p %h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" vhost_combined LogFormat "%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined LogFormat "%h %l %u %t "%r" %>s %O" common LogFormat "%{Referer}i -> %U" referer LogFormat "%{User-agent}i" agent

Files Include

Debian / Ubuntu structures in a particular way Apache files, we like or do not like I’m not here to say, but to explain the concept.

If we list the directories present in the directories we will see this:

 

$ ls -1 /etc/apache2/ conf-available conf-enabled mods-available mods-enabled sites-available sites-enabled

We can see 3 groups:

  • conf

    • conf-avaible

    • conf-enabled

  • mods

    • mods-avaible

    • mods-enables

  • sites

    • sites-avaible

    • sites-enabled

The concept is the follow all configurations are available in the conf-available directory and for enabled a symlink is created in the conf-enabled directory pointing to the original file in the conf-available directory. This philosophy applies to all three conf groups, mods and sites.

The clearest example is the loading of apache modules, let’s look at the list of files in the directory of available modules.

 

$ ls -l /etc/apache2/mods-available/ total 516 -rw-r--r-- 1 root root 100 Jan 7 2014 access_compat.load -rw-r--r-- 1 root root 377 Jan 3 2014 actions.conf -rw-r--r-- 1 root root 66 Jan 3 2014 actions.load -rw-r--r-- 1 root root 843 Jan 3 2014 alias.conf -rw-r--r-- 1 root root 62 Jan 3 2014 alias.load -rw-r--r-- 1 root root 76 Jan 3 2014 allowmethods.load -rw-r--r-- 1 root root 76 Jan 3 2014 asis.load [ .... ] [ .... ] # Soit 129 fichier $ ls -l /etc/apache2/mods-available/ | wc -l 129 # A présent les modules activés $ ls -l /etc/apache2/mods-enabled/ | head total 0 lrwxrwxrwx 1 root root 36 Nov 25 08:20 access_compat.load -> ../mods-available/access_compat.load lrwxrwxrwx 1 root root 28 Nov 25 08:20 alias.conf -> ../mods-available/alias.conf lrwxrwxrwx 1 root root 28 Nov 25 08:20 alias.load -> ../mods-available/alias.load lrwxrwxrwx 1 root root 33 Nov 25 08:20 auth_basic.load -> ../mods-available/auth_basic.load lrwxrwxrwx 1 root root 33 Nov 25 08:20 authn_core.load -> ../mods-available/authn_core.load lrwxrwxrwx 1 root root 33 Nov 25 08:20 authn_file.load -> ../mods-available/authn_file.load lrwxrwxrwx 1 root root 33 Nov 25 08:20 authz_core.load -> ../mods-available/authz_core.load lrwxrwxrwx 1 root root 33 Nov 25 08:20 authz_host.load -> ../mods-available/authz_host.load lrwxrwxrwx 1 root root 33 Nov 25 08:20 authz_user.load -> ../mods-available/authz_user.load [ .... ] [ .... ] # Il y a donc 28 fichiers de chargé par la configuration apache $ ls -l /etc/apache2/mods-enabled/ | wc -l 28

Conclusion on 129 files only 28 are actually loaded by Apache. We do not find this concept under Redhat. We will put aside all these configuration files that are loaded to view the configuration of the default website, in a second time during the configuration of our website we will return on the addition of functionality and modules. Of course it’s up to you to take a look at the files and look for the document on the Internet.

Default Virtual Host

All the sites are thus loaded by reading the files contained in / etc / apache2 / sites-enabled /. The system puts a default file with the name 000-default.conf. Here is the content (without comments):

ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined

We have the instruction:

  • VirtualHost *: 80: This statement indicates that there may be more than one web site on port 80 of Virtual Hosts … Thanks for the translation ;-), we will come back to this when we cover the possibility of having several websites . For people in a hurry, here is the link to the VirtualHot section

  • ServerAdmin: Administrator URL that can be displayed during error messages

  • DocumentRoot: Root directory of the website.

  • ErrorLog: Path or CLEAN error file to this website will be written. We would like to have an error file per website that greatly facilitates the identification of problems rather than having a big file for everyone. In addition we will be able to provide the file to the developer to analyze the problems.

  • CustomLog: File containing the access information of the clients as for the error file, a file of access by site. We find again the argument combined which is one of the format of log previously defined with the instruction Logformat

And here is :), this is what allowed us to put our file demo.html and view the content.

Server settings

Now that we’ve seen the general idea of the setup, it’s time to start putting some order or mess :).

Configuring the Directory Configuration

Changing the root directory (DocumentRoot)

For fun we will work by a clear example, because often a demonstration helps understanding. Let’s change the website of / var / www / html / to / data / www /, whatever the reason (hard disk space, reorganization of the system, …).

# Création du répertoire et copie des fichiers $ sudo mkdir -p /data/www $ sudo cp /var/www/html/*.html /data/www/

The files are now in the new directory and the configuration of the Web server remains to be changed. We will therefore modify the configuration of the DocumentRoot. Let’s edit the file /etc/apache2/sites-available/000-default.conf

# Changement de DocumentRoot /var/www/html # Pour la nouvelle valeur DocumentRoot /data/www

Validate the syntactic configuration of the server, it is always a good practice to carry out this operation after your modifications this makes it possible to correct problems even before reloading the configuration.

$ sudo apache2ctl configtest Syntax OK

Reload the configuration:

$ sudo service apache2 reload * Reloading web server apache2

Here is the result when we access the main page: http://127.0.0.1 or http://127.0.0.1/demo.html

 
So we have a 403 error which is a denial of access to the server. This corresponds to a denial of access you can have the list of state codes on Wikipedia: Code 4xx Error Client

 

The best way to understand the error is always the logs so see what we have in the files. To refresh our memory we will validate the definition of log files:

$ grep "log" /etc/apache2/sites-enabled/000-default.conf | grep -v "#" ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined # Et pour la valeur de ${APACHE_LOG_DIR} $ grep "APACHE_LOG_DIR" /etc/apache2/envvars export APACHE_LOG_DIR=/var/log/apache2
  • Access file /var/log/apache2/access.log:

    $ sudo tail -f /var/log/apache2/access.log 172.17.42.1 - - [27/Nov/2015:08:20:52 -0500] "GET / HTTP/1.1" 403 494 "-" "Mozilla/5.0 (X11; Linux i686; rv:42.0) Gecko/20100101 Firefox/42.0" 172.17.42.1 - - [27/Nov/2015:08:21:27 -0500] "GET /demo.html HTTP/1.1" 403 503 "-" "Mozilla/5.0 (X11; Linux i686; rv:42.0) Gecko/20100101 Firefox/42.0"
  • Error file /var/log/apache2/error.log

    $ sudo tail -f /var/log/apache2/error.log [Fri Nov 27 08:20:52.199792 2015] [authz_core:error] [pid 133:tid 3046103872] [client 172.17.42.1:58878] AH01630: client denied by server configuration: /data/www/ [Fri Nov 27 08:21:27.097668 2015] [authz_core:error] [pid 132:tid 3029318464] [client 172.17.42.1:58882] AH01630: client denied by server configuration: /data/www/demo.html

The server message is explicit the server configuration refuses to offer access to the file / data / www /. COOL !! The problem is clear and identify, it remains only THE solution :).

Access permission to the system tree is defined by the Directory configurations, we have this definition in the /etc/apache2/apache2.conf file

Options FollowSymLinks AllowOverride None Require all denied AllowOverride None Require all granted Options Indexes FollowSymLinks AllowOverride None Require all granted

The inherited configuration values according to the tree structure, which means that all the directories in the system file except for / usr / share and / var / www (including their subdirectory) have the following configuration:

Options FollowSymLinks AllowOverride None Require all denied

So we are currently blocked by the instruction: Require. Under Ubuntu all access to the file system is denied from the root (root /) outside the two named directories earlier.

You will probably ask me but why / usr / share to allow access to documentation, icons or custom page error file for 404 errors (not found) from the icons web interface.

We will confirm my comments, adding the following lines under the instruction, in the file /etc/apache2/apache2.conf here is the result:

Options FollowSymLinks AllowOverride None Require all denied Options FollowSymLinks AllowOverride None Require all granted [ .... ]

Validate the configuration before reloading the configuration:

$ sudo apachectl configtest Syntax OK $ sudo service apache2 reload * Reloading web server apache2 *

Let’s go to the URL: http://127.0.0.1/demo.html

This notion of inheritance of permissions is very important in understanding the permissive permission impact at the top level of the file system hierarchy.

Access authorization by hostname or ip (Require)

Take the opportunity to limit the access to a directory for only a network segment, because for the demonstration above we simply opened to ALL the access if we had an admin or private directory available for the internal network but which should not be available on the public internet. The require statement allows us to do this limitation. We will also see that it is possible to put an authentication system with username and password.

We will allow access only to the network 192.168.100.0/24 (so all ip addresses that starts with 192.168.100) and ip 192.168.42.42 (just to see the possibility to put multiple value :)). Here is the result :

Options FollowSymLinks AllowOverride None Require all granted Options FollowSymLinks AllowOverride None Require ip 192.168.100 192.168.42.42

Validation of the configuration (yes, I’m a little boring with that but honestly it helps a lot):

$ sudo apachectl configtest Syntax OK

 

 
In my case I should have had an access error because the ip of my machine does not correspond to that allowed, however I have a 404 error (page not found). This is understandable because we did not create the directory / data / www / admin. This means that Apache validates the existence of the directory before validating the access permissions, this is a detail however I wanted to share it, I thought it was the opposite: D.

So we will create the directory and put a small index.html file:

 

 

$ sudo mkdir /data/www/admin $ sudo vim /data/www/admin/index.html $ cat /data/www/admin/index.html section prive

Here is the good Message.

Organization of the configuration (context)

Let’s see the levels or organizational context of apache configurations before going further. I will use the configuration of the directory / data / www and / data / www / admin to make the demonstration. This section is very important because it helps to understand the configuration system in detail, nowadays set up a service is quite simple, a copy / pasted of a configuration found on the Internet is enough 90% of the time. The challenge comes with problems and / or integration of services, at this point it is important to understand the system.

There are 4 levels or context:

 

  • server configuration: A configuration set contained in apache server configuration files, such as the httpd.conf file, however this does not include instructions inside or tags. Likewise, it is not valid in .htaccess files.

  • virtual server: The set of instructions included in the tags.

  • directory: The set of instructions contained in the tags,,,, and.

  • .htaccess: The set of instructions contained in a .htaccess file.

Let’s take a look at our modification of the directory / data / www, as a base of reference and thus visualize the contexts that we have modified.

  1. We have modified the DocumentRoot directive, as a reminder that allowed us to modify the root of the website. If we look at documentation available for this instruction, here is the screenshot:

 
As you can see the DocumentRoot statement can be used in 2 context Server config and Virtual host. In our configuration we only have a DocumentRoot definition in the VirtualHost: sites-available / 000-default.conf

 

2 .Set access permissions for the directory / data / www with the Directory statement. This configuration is even more interesting because we have defined the permissions of this directory in 2 context. Let’s start by viewing the documentation

 
As you can see we can use the Directory directive in the Server config AND Virtual Host context. If we remember the configuration operation we defined our configuration in the 2 context. In context Server config when the configuration was present in the file /etc/apache2/apache2.conf and in the configuration of the Virtual Host when we repatriated the configuration in the Virtual Host.

 

3 . Definition of the Require statement which allowed us to limit the access to the admin directory thanks to the IP of origin. We put the configuration in the context of the directory were we obliged to do it?!?! What does the documentation say:
 
Again we had 2 possibilities where to dispose the instruction in context Directory or in context .htaccess. On reading this information this means that I can not set an IP limitation for the whole of a Virtual Host it must be by directory, so to limit access to the set I have to blocked to in the root directory.

But what happens if I am not the positioning guidelines of the configuration? Here is an example of an erroneous configuration, I defined the following statement directly in the VirtualHost:

 

 

$ cat /etc/apache2/sites-available/000-default.conf | grep -C 2 Require DocumentRoot /data/www Require ip 192.168.100 192.168.42.42 Options Indexes FollowSymLinks $ sudo apachectl configtest AH00526: Syntax error on line 14 of /etc/apache2/sites-enabled/000-default.conf: Require not allowed here Action 'configtest' failed. The Apache error log may have more information.

This is clearly an advantage to have such a clear message having used the command, apachectl configtest I had the information of the problem WITHOUT any interruption of the service.

We have seen 3 of the 4 context described earlier, the one that is missing is the .htaccess context, so in order to cover this possibility we will resume our configuration and see which instructions can be moved in context .htaccess. For people who are concerned about the light coverage achieved so far from the VirtualHost context do not worry we will cover the topics appropriately soon.

If we look at the only statement we can use in the .htaccess context is Require, we will proceed to the migration of the statement.

 

Overdefinition of the configuration in the .htaccess file

The purpose of the .htaccess file is to provide the ability to change the server configuration at the directory level. The main advantage of this feature is the ability to delegate the management of part of the configuration to the developer, however it is advisable to limit the scope of this feature, especially in production because this also includes potential security risks ( we will come back to this later).

The name of the .htaccess file is a convention this is defined by the AccessFileName statement

 
As we can see on the screenshot of the configuration this instruction can be defined in the configuration of the server OR in the configuration of the Virtual Host. I advise you not to change the name of the file, to facilitate reading by all stakeholders on your system. Personally if there is a problem on the site, I will look, if there is overload (redefinition) of the configuration with a .htaccess file, but if we change the name of the file it is unlikely that the considered.

Let’s proceed with the migration of the configuration to validate the behavior, the current configuration of the VirtualHost looks like this:

 

 

ServerAdmin webmaster@localhost DocumentRoot /data/www Options Indexes FollowSymLinks AllowOverride None Require all granted Options FollowSymLinks AllowOverride None Require ip 192.168.100 192.168.42.42 ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined

We will migrate the Require ip 192.168.100 192.168.42.42 directive into the .htaccess file.

  1. I delete the line defined in the directory configuration

  2. I create the file /data/www/admin/.htaccess with the following content

    $ sudo vim /data/www/admin/.htaccess Require ip 192.168.100 192.168.42.42 $ sudo apachectl configtest && sudo /etc/init.d/apache2 reload
  3. I had to reload the apache configuration so that the VirtualHost file was read again after deleting the Require definition

Validate the behavior, if I go to the page http: // Ip_du_server / admin /. My originating IP address being 172.17.42.1 access to the private section being allowed only since 192.168.100.0/24 AND 192.168.42.42, I am having the error message telling me that access is denied as before.

 

Oupsss the private section is accessible, but but …

 
Let’s proceed by validation:

 

  1. Re-validation of the server configuration

    $ sudo apachectl configtest Syntax OK
  2. Validation of the logs

    $ sudo tail /var/log/apache2/access.log /var/log/apache2/error.log ==> /var/log/apache2/access.log <== [... OUTPUT COUPÉ ...] 172.17.42.1 - - [17/Feb/2016:16:58:05 -0500] "GET /admin/ HTTP/1.1" 200 295 "-" "Mozilla/5.0 (X11; Linux i686; rv:42.0) Gecko/20100101 Firefox/42.0" ==> /var/log/apache2/error.log <== [... OUTPUT COUPÉ ...] [Wed Feb 17 16:45:39.294669 2016] [mpm_event:notice] [pid 53:tid 3075459712] AH00489: Apache/2.4.7 (Ubuntu) configured -- resuming normal operations [Wed Feb 17 16:45:39.295596 2016] [core:notice] [pid 53:tid 3075459712] AH00094: Command line: '/usr/sbin/apache2'

No error message so there is a bug in the apache software, or there is a configuration that is not compatible with our configuration. We will see the definition of the admin directory

Let’s look at the definition of the directory contained in the Virtual Host: /etc/apache2/sites-available/000-default.conf

 

Options FollowSymLinks AllowOverride None

Luckily the definition is short we can see “fast” the error, the AllowOverride statement is set to None, this indicates that the apache system is NOT looking if there is a .htaccess file in the directory. We will correct the configuration and proceed to the explanation later, we will change None by AuthConfig. Let’s see the result:

  1. File /etc/apache2/sites-available/000-default.conf:

    Options FollowSymLinks AllowOverride AuthConfig
  2. Recharge the configuration

    $ sudo apachectl configtest && sudo /etc/init.d/apache2 reload

It’s time to validate if now it’s OK !!

 
Woot, access is blocked, we can also see it in the logs

 

$ sudo tail /var/log/apache2/access.log /var/log/apache2/error.log ==> /var/log/apache2/access.log <== [ ... OUTPUT COUPÉ ... ] 172.17.42.1 - - [17/Feb/2016:17:14:05 -0500] "GET /admin/ HTTP/1.1" 403 499 "-" "Mozilla/5.0 (X11; Linux i686; rv:42.0) Gecko/20100101 Firefox/42.0" ==> /var/log/apache2/error.log <== [ ... OUTPUT COUPÉ ... ] [Wed Feb 17 17:13:49.432389 2016] [core:notice] [pid 173:tid 3075066496] AH00094: Command line: '/usr/sbin/apache2' [Wed Feb 17 17:14:05.152280 2016] [authz_core:error] [pid 176:tid 2979945280] [client 172.17.42.1:60578] AH01630: client denied by server configuration: /data/www/admin/
Let’s take a look at what the AllowOverride statement allows.

Permission to redefine configurations

The AllowOverride statement allows the Apache server to read the .htaccess file (or other file depending on the AccessFilename variable definition) in the directory.

 
The possible values at the statement are:

 

  • ALL: With this configuration Apache looks at the directory and all the subdirectory if there is a .htaccess file. If a file is found, the file is read and any instructions that can be set in the .htaccess context will be interpreted. Result The active configuration will be this defined in the .htaccess file.

  • None: With this configuration Apache does not even look if there is an .htaccess file in the directory

  • AuthConfig: Allows the use of authorization directives (AuthDBMGroupFilex, AuthDBMUserFile, AuthGroupFile, AuthName, AuthType, AuthUserFile, Require, etc …).

  • FileInfo: Enables the use of directives that control document types (ErrorDocument, ForceType, LanguagePriority, SetHandler, SetInputFilter, SetOutputFilter directives, and mod_mime Add * and Remove * module directives), document metadata (Header, RequestHeader, SetEnvIf , SetEnvIfNoCase, BrowserMatch, CookieExpires, CookieDomain, CookieStyle, CookieTracking, CookieName), mod_rewrite directives directive directives (RewriteEngine, RewriteOptions, RewriteBase, RewriteCond, RewriteRule), mod_alias directives directive directives (Redirect, RedirectTemp, RedirectPermanent, RedirectMatch), and the action directive of mod_actions module.

  • Indexes: Enables the use of directives that control directory indexing (AddDescription, AddIcon, AddIconByEncoding, AddIconByType, DefaultIcon, DirectoryIndex, FancyIndexing, HeaderName, IndexIgnore, IndexOptions, ReadmeName, etc …)

  • Limit: Allows the use of directives controlling access to the server (Allow, Deny and Order).

  • Nonfatal = [Override | Unknown | All]: Use the AllowOverride option to make non-fatal syntax errors in .htaccess files: instead of causing an Internal Server Error, unauthorized or unrecognized directives will be ignored and a warning saved in the log:

    • Nonfatal = Override makes AllowOverride forbidden directives non-fatal.

    • Nonfatal = Unknown makes the unknown directives non-fatal. This concerns typing errors and directives implemented by an unloaded module.

    • Nonfatal = All makes all previous directives non-fatal.

    • Note that a syntax error in a valid directive will always cause an internal server error.

  • Options [= Option, …]: Allows the use of directives controlling the specific features of a directory (Options and XBitHack). “Options” must be followed by an “equal” sign, then a comma separated list of options (no spaces); these options must be set using the Options command.

If we take our example of access limitation by IP address, we have defined in the .htaccess file the Require statement. In order for the configuration definition file to be interpreted we have to change the value of the AllowOverride statement from None to AuthConfig. We could also have set the statement to ALL in this situation we would be able to set not only authentication limitation instructions but also general system configurations. A little later I will demonstrate the risk of this possibility.

As part of the AuthConfig configuration the available option is relatively specific and contains little instruction, however if we look at the FileInfo statement the order number is more meaningful. If we want to offer the option to the developer to have the hand on the configuration to redefine for example the error documents, so that the error message is personalized with a beautiful image and a nice text. To perform this operation the developer will want to modify the ErrorDocument statement, and we will have to allow over-definition in AllowOverride with the FileInfo statement. The developer will therefore have much more instruction available than ErrorDocument.

Since version 2.4 of apache it is possible to be more specific on the instructions usable in the .htaccess file. It was introduced the AllowOverrideList directive, it allows to list only the instructions available in the .htaccess file. If we resume our need to be able to override the ErrorDocument option, but want ONLY this statement we could define it as follows:

AllowOverride None AllowOverrideList ErrorDocument

In this example, no configuration can be redefined in the .htaccess file, except for the ErrorDocument directive.

Take note that AllowOverride AND AllowOverrideList are combinatorial. In other words if I have the following instruction:

 

AllowOverride AuthConfig AllowOverrideList ErrorDocument

I will be able to use the instructions: ErrorDocument + AuthDBMGroupFilex, AuthDBMUserFile, AuthGroupFile, AuthName, AuthType, AuthUserFile, Require, etc …