Apache 2, eAccelerator, Mod Security y cifrado SSL: Instalación y configuración en GNU/Linux debian.
Este artículo tratara sobre la instalación y configuración del servidor web Apache en su versión 2.2 sobre una plataforma GNU/Linux Debian en su versión estable, actualmente 4.0 etch, con soporte para php, mysql y ssl, con optimizaciones, tanto de rendimiento mediante eAccelerator como de seguridad mediante Mod Security.
Versiones:
Apache 2.2.3-4
PHP 5.2.0-8
mysql 5.0.32
eAccelerator 0.9.5.2
Mod_Security 2.5.2
Requisitos previos: GNU/Linux debian etch instalado y actualizado y una interfaz de red configurada con una dirección IP estática, se asumirá que la instalación se ha hecho en su forma más básica y sin ningún tipo de servicio.
Recomendación previa: la instalación de eAccelerator y Mod Security es recomendable pero totalmente opcional, su no instalación no afectará el funcionamiento de apache o el resto de los elementos.
Contenido:
1. Instalación
1.1 Instalación de Apache
1.2 Instalación de PHP 5
1.3 Instalación de MySQL
1.4 Instalación de soporte para perl
1.5 Instalación de eAccelerator
1.6 Instalación de Mod Security
2. Configuraciones
2.1 Directivas
2.1.1 La directiva NameVirtualHost
2.1.2 La directiva <VirtualHost>
2.1.3 La directiva ServerAdmin
2.1.4 La directiva ServerName
2.1.5 La directiva ServerAlias
2.1.6 La directiva DocumentRoot
2.1.7 La directiva <Directory>
2.1.8 La directiva Options
2.1.9 La directiva DirectoryIndex
2.1.10 La directiva AllowOverride
2.1.11 Las directivas Order, Allow y Deny
2.1.12 La directiva ServerSignature
2.2 Agregando Cifrado ssl
2.2.1 La directiva SSLEngine
2.2.2 La directiva SSLCertificateFile
2.2.3 La directiva SSLCertificateKeyFile
2.2.4 La directiva ErrorLog
2.2.5 La directiva CustomLog
2.2.6 La directiva LogLevel
2.3 Redireccionando a partir de una página sin cifrar
2.3.1 La directiva Redirect
3 Seguridad
3.1 Oscuridad
3.2 El módulo mod_security
4 Referencias
1. Instalación
1.1 Instalación de Apache
# aptitude install apache2
Esto instalará Apache 2 y todas sus dependencias, ahora nos dirigiremos al directorio /etc/apache2/ donde nos encontraremos con una serie de archivos, en el archivo ports.conf debe decir Listen 80, lo cual indica que se estará escuchando en el puerto 80, si quisiéramos que nuestro apache escuche en otro puerto diferente modificamos ese valor, si deseamos escuchar peticiones en mas de un puerto agregamos una nueva línea, por ejemplo Listen 443 que se utiliza para aceptar peticiones mediante el protocolo https en su puerto estándar. El archivo apache2.conf es el archivo principal de configuración de nuestro apache, no lo modificaremos por el momento. También podemos encontrar el archivo httpd.conf, este archivo esta vacío y así lo dejaremos, su fin es simplemente garantizar compatibilidad con versiones anteriores de apache. Encontramos también una serie de directorios, mas adelante veremos que contiene cada uno, por el momento solo mencionare el directorio conf.d y su contenido, el archivo charset, ya que podemos modificar este archivo para cambiar el set de caracteres por defecto, si editamos este archivo vemos que dice AddDefaultCharset UTF-8, lo podemos reemplazar por AddDefaultCharset ISO-8859-1, esto hace que el set de caracteres por default sea ISO-8859-1 el cual se corresponde con la codificación Latin1 que es también muy utilizada. UTF-8 será la adecuada en la mayoría de los casos pero si nuestro apache utilizara por ejemplo una base de datos mysql 4 o inferior, debemos saber que esta solo soporta el set de caracteres ISO-8859-1, en tal caso debemos utilizar ISO-8859-1 o tendremos problemas por ejemplo con las tildes, donde una letra con acento será reemplazada por un ?.
Reiniciemos apache:
# /etc/init.d/apache2 restart
Para asegurarnos que todo marcha bien podemos desde cualquier navegador, en una PC que tenga acceso a la IP de nuestro servidor, escribir como URL la dirección IP del servidor, deberíamos recibir una página en blanco con la frase It Works! (Funciona!)
1.2 Instalación de PHP 5
# aptitude install php5 php5-mysql
Esto instalara PHP 5 y todas sus dependencias y los módulos necesarios para una comunicación con bases de datos mysql, para asegurarnos que fue correcto podemos ingresar, al igual que lo hicimos después de la instalación de apache2,la dirección del servidor en el navegador web pero esta vez agregar al final de la misma una palabra cualquiera de modo que la URL quede algo como 192.168.1.2/loquesea. Esto nos devolverá una página indicándonos Error 404 Not Found (No se encuentra), lo cual es lógico ya que lo que acabamos de hacer es solicitar que se nos entregue la página de nombre loquesea, la cual no existe. Observemos que la página nos indica además el nombre y versión del servidor web y el nombre del sistema operativo, así como también que utiliza PHP 5 lo cual nos indica que la instalación de PHP fue exitosa.
1.3 Instalación de MySQL
# aptitude install mysql-server
Esto instalara mysql server 5.0, el cliente mysql y todas sus dependencias. Para asegurarnos que todo ha salido bien podemos ejecutar en una terminal:
# mysql
y deberíamos poder acceder al cliente mysql (también llamado monitor) desde donde podemos crear los usuarios y las bases de datos necesarias, escribiendo quit salimos del mismo. Cabe aclarar que, si bien es muy común que las páginas web interactúen con bases de datos, estas no tienen ninguna relación con apache. El acceso a las bases de datos mysql estará a cargo de PHP y el modulo php5-mysql por lo que no se mencionará mas mysql ni su utilización.
1.4 Instalación de soporte para perl
# aptitude install libapache2-mod-perl2
Con esto habremos agregado soporte para perl a nuestro servidor apache, ahora debemos activar el modulo y reiniciar apache:
# a2enmod perl
# /etc/init.d/apache2 restart
El mismo programa a2enmod nos dice que debemos reiniciar apache mediante /etc/init.d/apache2 force-reload, podemos hacerlo de ese modo también, la diferencia entre estas dos opciones, restart y force-reload, es que en el primer caso el servidor apache se detiene para luego volver a iniciar mientras que en el segundo solo se carga la configuración sin detener el servicio, esto es lo que se utiliza cuando se trabaja con servidores en producción. Para saber si todo funciona podemos hacer lo mismo que hicimos para verificar el soporte para php. Cabe aclarar que no siempre será necesario tener soporte para lenguajes como perl, si el sitio que nos interesa servir no lo necesita es siempre recomendable que el modulo no se instale o, en su defecto, que no se active. La instalación del modulo perl se explico con el único fin de generalizar la forma de agregar y activar módulos en apache.
1.5 Instalación de eAccelerator
En este caso nos encontraremos con un pequeño inconveniente, no se cuenta con eAccelerator en los repositorios oficiales de debian, por lo que será necesario compilarlo de acuerdo a nuestras necesidades y tener un par de cosas en cuenta de aquí en adelante. El compilar eAccelerator es sumamente sencillo pero deberemos ser cuidadosos de ahora en más si decidiéramos hacer un upgrade del sistema ya que en tal caso seria necesario recompilar eAccelerator en el caso de que cambiara la versión de apache o php.
Pero primero, ¿Que es eAccelerator?
eAccelerator es un acelerador de entregas mediante una caché de código compilado de PHP, esto no parece explicar mucho y menos aún a quien ha programado en PHP y sabe que es un lenguaje interpretado. Tratare de ser mas claro, como sabemos php es un lenguaje de programación y como tal produce programas que se ejecutan, ya sea que el lenguaje sea ejecutable o interpretable, este debe ejecutarse en algún lado, en el caso de php el código es interpretable y se ejecuta en el servidor. Veamos que sucede cuando un cliente se conecta a nuestro servidor y solicita una página en php, el servidor deberá buscar el código en php, ejecutarlo (este podría contener por ejemplo consultas a una base de datos las cuales dependen de datos enviados por le cliente) y enviar al cliente el resultado de la ejecución, esto supone una carga de trabajo para el servidor y mas para uno muy atareado, eAccelerator lo que hace es almacenar el resultado de las ejecuciones en una caché y liberar del trabajo de compilación al servidor cada vez que un cliente solicita una página solicitada anteriormente entregando directamente el código compilado
Ahora que sabemos qué es eAccelerator, las ventajas de su uso y vemos que si vale la pena instalarlo por mas que sea necesario compilarlo, procedamos a instalarlo.
Lo primero será descargar los fuentes de eAccelerator de la página oficial del autor, lo descargaremos en el formato tar.bz2.Al momento de la redacción de este artículo, eAccelerator se encontraba en su versión 0.9.5.2, lo que haremos entonces es movernos a un directorio temporal, /tmp por ejemplo, y ejecutar lo siguiente:
# wget http://bart.eaccelerator.net/source/0.9.5.2/eaccelerator-0.9.5.2.tar.bz2... tar xvfj eaccelerator-0.9.5.2.tar.bz2
Lo anterior descargará eAccelerator y lo desempaquetara en el directorio eaccelerator-0.9.5.2, movemos este directorio a /opt o /usr/lib, esto queda a su criterio, accedemos al directorio y procedemos a generar el archivo de configuración que necesita make para compilar el eaccelerator, para esto necesitamos tener instalado php-dev por lo que lo instalaremos:
# aptitude install php5-dev
Para la compilación de eAccelerator también necesitaremos tener el compilador y las librerías necesarias, procedemos entonces:
# aptitude install build-essential
Ahora si, dentro del directorio eaccelerator-0.9.5.2 ejecutamos:
# phpize
Esto genera el archivo configure que necesitamos para generar el archivo make.ini necesario para la compilación, ejecutamos entonces configure con las siguientes opciones:
# ./configure --enable-eaccelerator=shared --with-php-config=/usr/bin/php-config
Y procedemos entonces a compilar:
# make
E instalar:
# make install
Ahora es necesario indicarle a php que debe utilizar eAcelerator, para esto deberemos modificar el archivo php.ini el cual, en nuestro caso ya que utilizamos apache2,se encuentra en /etc/php5/apache2/php.ini y agregar lo siguiente al final del archivo:
extension="eaccelerator.so"
eaccelerator.shm_size="16"
eaccelerator.caché_dir="/var/cache/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"
Como podemos ver en la tercer línea, se menciona el directorio /var/caché/eaccelerator, este es el directorio donde se almacenará la caché de eAccelerator, a tal directorio deberemos crearlo
# mkdir -p /var/caché/eaccelerator
Y otorgarle los permisos necesarios:
# chown www-data:www-data /var/caché/eaccelerator
# chmod 0744 /var/caché/eaccelerator
Bien, solo resta reiniciar apache para que tome la configuración:
# /etc/init.d/apache2 restart
Para asegurarnos que php esta utilizando eAccelerator podemos hacer lo siguiente, en el directorio /var/www/ se encuentran una serie de directorios y archivos que son los encargados de mostrarnos una página de inicio para saber si apache esta funcionando, esta página es la que vimos cuando verificamos que apache funcionaba y no dice mucho mas que la frase "It Works!", lo que haremos ahora es crear el archivo info.php dentro de este directorio en el cual simplemente escribiremos lo siguiente:
<?php
phpinfo();
?>
Luego, desde un navegador escribimos como URL la dirección del servidor y solicitamos la página info.php, de modo que quede algo como lo 192.16.1.2/info.php, esto nos debería devolver una página bastante extensa en la cual figuran las características de PHP, al final del primer cuadro debería decir que PHP esta utilizando Zend Engine con eAccelerator.
1.6 Instalación de Mod Security
Malas noticias de nuevo, a diferencia de debian sarge, Mod Security no se encuentra en los repositorios oficiales de debian etch. La versión actual de Mod Security es 2.5.2, existen repositorios no oficiales pero la versión disponible en esos repositorios es la 2.1.5, si queremos la última versión deberemos compilarla nosotros mismos, y eso es lo que haremos. Cabe aclarar que si el lector desea realizar la instalación desde los repositorios, o bien omitir la instalación de Mod Security, lo puede hacer sin problemas.
Primero la introducción de rigor ¿Que es Mod Security?
Mod Secutity es lo que se denomina un firewall de aplicación diseñado para correr en servidores web, mas específicamente apache. Fue creado en 2002 por Ivan Ristic, especialista en seguridad web y posee muchas características que lo hacen muy eficiente en la detección y prevención de ataques:
- Filtrado de peticiones.
- Técnicas antievasión.
- Comprensión del protocolo http y https.
- Verificación del rango de bytes para evitar shellcodes.
- Log de auditoria.
Hay información abundante sobre que es Mod Security, lamentablemente no tanta sobre su configuración.
Comencemos con la instalación, lo primero es detener apache
# /etc/init.d/apache2 stop
Ahora nos movemos a un directorio temporal, por ejemplo /tmp, y descargamos los fuentes:
# wget http://www.modsecurity.org/download/modsecurity-apache_2.5.2.tar.gz
Descomprimimos y desempaquetamos:
# tar -zxvf modsecurity-apache_2.5.2.tar.gz
Y como podemos ver en la documentación en /tmp/modsecurity-apache_2.5.2/doc/ Mod Security requiere de la previa instilación de libxml2 y Lua, por lo que procedemos
a ello:
# aptitude install libxml2 libxml2-dev lua5.1 liblua5.1-dev
Lo que no dice es que también necesitaremos apache2-prefork-dev, procedemos a instalarlo:
# aptitude install apache2-prefork-dev
También dice que debemos tener instalado y activo mod_unique_id, encargado de identificar cada transacción (conexión) con un ID único, el modulo ya está instalado pero resta activarlo:
# a2enmod unique_id
Ahora accedemos al directorio /tmp/modsecurity-apache_2.5.2/apache2 y ejecutamos el archivo configure, el cual generará el archivo make.ini necesario para la compilación:
# ./configure
Compilamos, haré mención a que para esto necesitamos build-essential, paquete que debiéramos haber instalamos cuando compilamos eAccelerator:
# make
Chequeamos que todo ha salido bien mediante:
# make test
Lo cual nos debería decir, al final de una larga lista de acciones, all tests passed. Ahora instalemos:
# make install
Y ya debiéramos tener instalado Mod Security, resta decirle a apache que cargue el modulo, por un tema de dependencias debemos cargar también libxml2 y liblua por lo que modificaremos el archivo /etc/apache2/apache2.conf y agregaremos lo siguiente al final del archivo:
LoadFile /usr/lib/libxml2.so
LoadFile /usr/lib/liblua5.1.so
LoadModule security2_module /usr/lib/apache2/modules/mod_security2.so
Ahora resta la configuración de las reglas ya que si no agregamos reglas Mod Security no cumplirá ninguna función útil, eso se explicara en la sección de seguridad, por el momento solo diré que hay reglas predefinidas escritas ya en archivos que se pueden descargar desde la página web del autor. Se debe indicar a apache que cargue tales archivos por lo que crearemos el directorio modsecurity:
# mkdir /etc/apache2/modsecurity
Y editamos nuevamente el archivo /etc/apache2/apache2.conf para agregar la linea:
Include /etc/apache2/modsecurity/*.conf
Con esto le indicaremos a apache que cargue todos los archivos de extensión .conf que se encuentren en el directorio /etc/apache2/modsecurity, luego solo resta agregar los archivos con las reglas en esta ubicación asegurándonos por supuesto que la extensión de los mismos sea conf, si deseamos copiar al directorio un archivo de reglas pero no deseamos que sea cargado solo debemos renombrarlo con extensión diferente. Y ya podemos reiniciar apache para ver felizmente que funciona
y no emite ningún error:
#/etc/init.d/apache2 start
Agregaré un comentario en este punto, la compilación e instalación no ha resultado complicada pero tendremos un problema si ocurriera algún error, la documentación sobre como compilar e instalar mod security no es tan abundante como uno quisiera y si un usuario no experimentado se enconara con problemas aún después de seguir correctamente los pasos aquí explicados le resultara muy difícil solucionarlo. Si esto le ocurre yo sinceramente le aconsejaría que desista de instalar Mod Security mediante este método e instale desde los repositorios.
2 Configuraciones
Teniendo todo instalado y funcionando, comencemos con las configuraciones, lo primero que haremos es por supuesto copiar los archivos de nuestro sitio web al servidor, léase CMSs como drupal, joomla, props, etc o una pagina realizada por nosotros mismos, normalmente estos archivos están alojados en /var/www, esto no es un requerimiento pero es bueno atenerse a las costumbres, copiamos nuestros archivos en /var/www/ejemplo.
Ahora debemos indicarle a apache que utilice ese directorio como un sitio web, para hacer esto echemos primero una mirada al directorio /etc/apache2/, dentro se encuentra el ya mencionado conf.d, y además otros cuatro directorios que son:
- sites-available: contiene los archivos de configuración de los sitios web.
- sites-enabled: contiene enlaces a archivos de configuración alojados en sites-available, solo los archivos en sites-available que se encuentren enlazados en este directorio estarán activos y serán accesibles a través de apache.
- mods-available:contiene los archivos de configuración de los módulos instalados.
- mods-enabled: contiene enlaces a archivos de configuración alojados en mods-available, solo los archivos en mods-available que se encuentren enlazados en este directorio estarán activos y podrán serán usados por apache.
Los enlaces en sites-enabled y mods-enabled pueden crearse del modo tradicional, mediante ln -s, nosotros utilizaremos las utilidades a2ensite y a2enmod para la activación de sitios y módulos respectivamente. Del mismo modo utilizaremos a2dissite y a2dismod para desactivar sitios y módulos.
Crearemos el archivo de configuración de nuestro sitio web, denominado Virtual Host, lo que haremos es crear en /etc/apache2/sites-available una archivo de texto con el nombre de nuestro sitio web, es decir, si nuestro sitio se llamara www.ejemplo.com crearemos el archivo /etc/apache2/sites-available/www.ejemplo.com, esto tampoco es obligatorio, el archivo podría tener cualquier nombre, incluso ni siquiera es necesario que exista un archivo por virtual host, todos podrían configurarse dentro de un mismo archivo, por ejemplo en el archivo ya existente /etc/apache2/sites-availables/default o en el mismísimo /etc/apache2/apache.conf, pero por supuesto es recomendable hacerlo en archivos separados ya que de este modo podemos activar y desactivar los sitios más fácilmente. Creamos el archivo con nuestro editor favorito, en mi caso utilizare nano debido a que, si me han hecho caso e instalaron debian en su forma mas básica, no contaran con otro que no sea nano o vim, yo utilizo nano
# nano /etc/apache2/sites-available/www.ejemplo.com
Aquí será necesario tener un poco de criterio y conocimiento de los requerimientos de la página web que vamos a servir, conocer que módulos necesita y demás, por el momento supondremos que se trata de un sitio web básico, con elementos en php y que accede a una base de datos mysql, la configuración que se muestra a continuación es a modo de ejemplo y es la adecuada para el funcionamiento de la mayoría de los CMSs - todos los que conozco al menos -, en ella se han incluido algunas directivas que pueden no ser necesarias en la mayor parte de los casos con el solo fin de explicarlas mas adelante. Esta configuración puede tomarse como base para las configuraciones futuras pero solo si se ha leído la explicación de cada directiva y se ha comprendido su significado.
1 <VirtualHost *>
2 ServerAdmin webmaster@ejemplo.com
3 ServerName www.ejemplo.com
4 ServerAlias ejemplo.com
5 DocumentRoot /var/www/ejemplo
6 <Directory />
7 Options FollowSymLinks
8 AllowOverride None
9 </Directory>
10 <Directory "/var/www/ejemplo">
11 Options Indexes FollowSymLinks
12 AllowOverride None
13 Order allow,deny
14 allow from all
15 </Directory>
16 ServerSignature On
17 </VirtualHost>
Y activamos el sitio con
# a2ensite www.ejemplo.com
Lo cual creó un enlace simbólico en /etc/apache2/sites-enabled/www.ejemplo.com que apunta a /etc/apache2/sites-available/www.ejemplo.com
Reiniciamos apache:
# /etc/init.d/apache2 restart
Y si contamos con un servidor DNS que resuelva del nombre www.ejemplo.com la IP de nuestro servidor ya tenemos la página accesible desde un navegador. Un pequeño truco para los que no cuentan con servidor DNS y no desean modificar su archivo /etc/hosts, simplemente configuren su navegador web para que utilice como servidor Proxy la IP del servidor apache y en el puerto 80.
Muy bien pero, ¿Que significa todo eso dentro de nuestro archivo /etc/apache2/sites-available/www.ejemplo.com?
No es el fin de este documento dar una explicación detallada de cada directiva, para una información detallada deberán dirigirse a la documentación oficial de apache, sin embargo daré una breve descripción de las directivas usadas por nosotros.
2.1 Directivas
Lo primero que haremos es ver el archivo /etc/apache2/sites-available/default, ya que este contiene algunas directivas importantes que no se encuentran en nuestro archivo /etc/apache2/sites-available/www.ejemplo.com
1 NameVirtualHost *
2 <VirtualHost *>
3 ServerAdmin webmaster@localhost
4 DocumentRoot /var/www/
5 <Directory />
6 Options FollowSymLinks
7 AllowOverride None
8 </Directory>
9 <Directory /var/www/>
10 Options Indexes FollowSymLinks MultiViews
11 AllowOverride None
12 Order allow,deny
13 allow from all
14 RedirectMatch ^/$ /apache2-default/
15 </Directory>
16 ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
17 <Directory "/usr/lib/cgi-bin">
18 AllowOverride None
19 Options ExecCGI -MultiViews +SymLinksIfOwnerMatch
20 Order allow,deny
21 Allow from all
22 </Directory>
23 ErrorLog /var/log/apache2/error.log
24 LogLevel warn
25 CustomLog /var/log/apache2/access.log combined
26 ServerSignature On
27 Alias /doc/ "/usr/share/doc/"
28 <Directory "/usr/share/doc/">
29 Options Indexes MultiViews FollowSymLinks
30 AllowOverride None
31 Order deny,allow
32 Deny from all
33 Allow from 127.0.0.0/255.0.0.0 ::1/128
34 </Directory>
35 </VirtualHost>
2.1.1 La directiva NameVirtualHost
La primer directiva, NameVirtualHost *, es obligatoria y significa que se utilizara Host Virtuales, y el * significa que se escuchara en todas las direcciones de red en todos los puertos definidos en /etc/apache2/ports.conf. Al decir "todas la direcciones de red" me estoy refiriendo a que nuestro servidor podría por ejemplo contar con mas de una dirección IP, lo que se especifica entonces es la dirección IP a través de la cual se aceptarán peticiones.
Esta directiva va una y sólo una vez en alguno de los archivos en /etc/apache2/sites-available que se encuentre enlazado en /etc/apache2/sites-enabled, por comodidad la dejaremos en el archivo /etc/apache2/sites-available/default ya que más adelante mostrare la utilidad que le daremos.
2.1.2 La directiva <VirtualHost>
Sigamos analizando el archivo /etc/apache2/sites-available/default, la cabecera <VirtualHost *> indica que se comenzara con la definición de un nuevo Host Virtual, definición que terminara cuando se encuentre con un </VirtualHost>, nótese que posee una notación XML. Esta cláusula debe corresponderse con algún NameVirtualHost, ¿que significa esto?, bien, podríamos haber definido varios NameVirtualHost, por ejemplo:
NameVirtualHost 192.168.1.1:80
NameVirtualHost 192.168.1.2:80
NameVirtualHost 192.168.1.2:443
Esto habría significado que se definirán Hosts virtuales para aceptar peticiones en las direcciones 192.168.1.1 en el puerto 80, 192.168.1.2 en el puerto 80 y 192.168.1.2 en el puerto 443. Pues bien, cuando se define un nuevo Host Virtual se debe indicar a que NameVirtualHost pertenece y eso se hace respetando la sintaxis, en el caso del ejemplo anterior deberemos definir los Host virtuales como alguno de los siguientes:
<VirtualHost 192.168.1.1:80>
<VirtualHost 192.168.1.2:80>
<VirtualHost 192.168.1.2:443>
Cualquier directiva que se coloque en un bloque VirtualHost se aplicará solo a ese VirtualHost, por ejemplo podríamos colocar en este bloque la directiva AddDefaultCharset ISO-8859-1 para forzar la utilización de latin 1 como juego de caracteres para ese VirtualHost por sobre lo establecido en el archivo charset. Pueden agregarse también reglas de Mod Security dentro del bloque para lograr que solo se apliquen cuando se acceda a ese VirtualHost y no a los demás.
Cabe aclarar también que si definimos un NameVirtualHost entonces debe haber al menos un Host Virtual que lo utilice de lo contrario cuando intente iniciar apache nos emitirá un mensaje de error.
También nos puede surgir una pregunta, si utilizar Host Virtuales significa que nuestro servidor será capaz de servir mas de un sitio web y no solo uno como podría pensarse lógico, y teniendo en cuenta que las peticiones se reciben a través de la misma dirección IP ¿Cómo sabe el servidor que página web debe retornar al cliente?, la respuesta la trae el protocolo http, el cual incluye en la cabecera del mensaje la URL original que se ha ingresado en el navegador y es así como nuestro servidor sabrá que Host Virtual corresponde.
Volvamos al archivo de configuración de nuestro sitio web,el archivo /etc/apache2/sites-available/www.ejemplo.com, definiremos entonces un Host virtual, el cual se encontrara entre las cláusulas <VirtualHost *> y </VirtualHost> y hemos decidido que colocaremos cada uno de ellos en un archivo diferente para facilitar la activación/desactivación.
2.1.3 La directiva ServerAdmin
Esta directiva es opcional e indica la dirección de correo electrónico del administrador del servidor (del host virtual en este caso), en caso de generarse un mensaje de error esta dirección de correo será enviada al cliente junto con el mensaje.
2.1.4 La directiva ServerName
La siguiente es ServerName www.ejemplo.com, y es el nombre del sitio web al cual se le dará acceso en el Host Virtual, notemos que esta directiva no se encuentra en el archivo /etc/apache2/sites-available/default, esto se debe a que esta directiva es opcional. Eso no parece del todo lógico, si el sitio no tiene nombre y dijimos que es a través del nombre que el servidor sabe con que Host Virtual responder al cliente entonces ¿cuando será entregado el mismo? Bien, primeramente debemos saber que el archivo default es un tanto particular debido a que este archivo se ha creado automáticamente en la instalación. Daré ahora una serie de pautas sobre el funcionamiento de apache que nos ayudarán a entender esto y varias cosas mas, tengamos en cuenta primero que no es obligación la utilización de host virtuales, podríamos definir nuestro servidor para prestar servicio a un solo sitio web y en tal caso seria mas lógico pensar que no sea obligación definir el nombre del mismo ya que es el único, la definición en este tipo de configuración seria la siguiente: como es lógico no se colocarían las directivas <VirtualHost> y </VirtualHost>, tampoco la directiva NameVirtualHost, si recordamos yo había dicho que esta directiva es obligatoria, pues en realidad es obligatoria si se utilizara Host Virtuales, de lo contrario se coloca en lugar de ella, y es muy recomendable que se lo haga, la directiva ServerName nombre.¿Qué sucede si no se coloca esta directiva? Pues eso puede ser un problema, apache asumirá que su ServerName es el nombre y dominio del host, por lo que en /etc/resolv.conf deberá existir la línea domain ejemplo.com , o en su defecto la linea search ejemplo.com, además en /etc/hosts debe estar la correspondencia entre www.ejemplo.com y nuestra dirección IP y en /etc/hostname debe figurar www como nuestro nombre de host, si nada de lo anterior se cumple apache hará un último intento por determinar su nombre mediante una resolución DNS inversa a partir de su dirección IP, si esto tampoco tiene exito veremos un mensaje en cada reinicio de apache diciéndonos algo como:
Apache2: Could not reliably determine de server's fully qualified domain name,
using 127.0.0.1 for ServerName.
Donde apache nos comunica que no ha sido capaz de determinar su nombre y asumirá que es 127.0.0.1 (por lo general asume que su nombre es nuestra dirección IP). Mensaje que muy probablemente ya hemos visto cada vez que reiniciábamos apache debido a que esta aclaración no la había hecho aún. Seria recomendable realizar las modificaciones mencionadas en los archivos /etc/resolv.conf,/etc/hosts y /etc/hostname.
Continuemos entonces, el archivo de configuración del host si no utilizamos host virtuales será por supuesto único y claro, podría conservarse el archivo /etc/apache2/sites-available/default, dirijámonos ahora al directorio /etc/apache2/sites-enabled, vemos que el enlace al archivo default se encuentra ahí pero no tiene por nombre default sino 000-default, recordemos este detalle para mas adelante y volvamos a la idea de Host Virtuales, dije anteriormente que es buena idea definir cada host virtual dentro de un archivo diferente, el cual se colocara en /etc/apache2/sites-available y se enlazara en /etc/apache2/sites-enabled mediante la utilidad a2ensite, que creara el enlace dándole el mismo nombre que el archivo original. Una vez que tenemos varios Host virtuales creados y funcionando el servidor distinguirá con que página debe responder a cada petición basándose en la cabecera http… pero, ¿Qué sucede si la cabecera contiene una dirección URL que no se corresponde con ninguno de los host virtuales? ¿Con que página se le responde al cliente?, rechazar la petición no seria correcto, después de todo si el cliente llegó a comunicarse es porque de algún modo fue direccionado hacia nosotros, ¿qué hacer entonces? Una solución seria responder al cliente con cualquier página. Pues apache hace algo como eso, responderá con la primer página, y la primer página es aquella que se leyó primero de /etc/apache2/sites-enabled/ en orden alfabético.
Y ahora todo cierra, el enlace a /etc/apache2/sites-available/default se llama 000-default para asegurar que sea el primer host virtual en ser leído y esta no necesita ServerName ya que se responderá con ella siempre que la solicitud del cliente no coincida con ningún ServerName de los demás host virtuales.
¿Y si un Host virtual no posee ServerName y no es el primero en cargarse? ¿Nunca se utilizara? Pues no, nunca. Una buena idea será editar el archivo /var/www/apache2-default/index.html para que muestre una página que amablemente explique al usuario cliente que no hay ninguna página disponible para atender su petición. Sería recomendable renombrar el directorio como /var/www/default, y modificar el archivo /etc/apache2/sites-available/default por supuesto, para evitar que el archivo index.html sea reemplazado durante una actualización.
2.1.5 La directiva ServerAlias
La siguiente es ServerAlias ejemplo.com, y es un alias del nombre del sitio web, es decir que se responderá tanto si la cabecera http solicita la URL www.ejemplo.com como si solicita ejemplo.com. Esta directiva solo es válida para Host Virtuales y es opcional. Si se tiene más de un alias se colocan separados por espacios del modo:
ServerAlias nombre1 nombre2 [… nombreN]
2.1.6 La directiva DocumentRoot
La directiva DocumentRoot define la raiz del sitio Web y es a partir de el que se accede a los documentos, por ejemplo, si se define DocumentRoot /var/www y el cliente solicita la URL www.ejemplo.com/index.html de le entregará el archivo /var/www/index.html.Es importante notar que se debe colocar la ruta completa al directorio y no agregar un slash (/) al final de la misma.
2.1.7 La directiva <Directory>
Esta directiva encierra entre las etiquetas <Directory> y </Directory> los permisos de acceso que se desean para el directorio especificado. El directorio al cual se hace referencia en este caso es / y hace referencia al directorio raíz del sistema de archivos del sistema y NO al DocumentRoot Mediante esta directiva se indica a apache que comportamiento debe tener dentro del directorio, como por ejemplo, si debe aceptar o ignorar archivos .htacces, si debe o no seguir enlaces simbólicos y muchas otras, algunas de las cuales se explicaran mas adelante
2.1.8 La directiva Options
Esta directiva establece que características estarán disponibles para el directorio, por defecto toma el valor All, lo cual es para nada seguro por lo que modificaremos estos valores en todos los casos. La sintaxis de esta directiva es
Options [+|-]opción [[+|-]opción] …
Los símbolos + y - indican si se acepta o se quita la opción, es opcional y se utiliza para forzar la utilización/No utilización de una opción que quedaría contenida dentro de otra mas global, esto puede resultar complicado y su mala utilización se presta a resultados inesperados por lo que no mencionaremos ni utilizaremos estos símbolos.
Las opciones disponibles son muchas, mencionaremos las que nos interesan:
- None: Ninguna característica será permitida en el directorio.
- All: Todas las características serán permitidas en el directorio.
- FollowSymLinks: establece si se permitirá o no que se sigan enlaces simbólicos dentro del directorio.
- ExecCGI: Si se permitirá o no la ejecución de scripts CGI.
- Indexes: Si se accede a un directorio el cual no posee un archivo index.html (ni ninguno especificado en la directiva DirectoryIndex) esta opción hace que se entregue al cliente la lista de archivos y directorios presentes en el directorio especificado. Es muy utilizada para sitios de descarga de archivos, donde se permite al cliente navegar por la estructura de directorios. Esta opción nunca debe utilizarse sobre /, por seguridad es recomendable utilizar esta opción en directorios ubicados al menos en un nivel mayor de profundidad que el directorio definido como DocumentRoot
2.1.9 La directiva DirectoryIndex
Esta directiva no esta siendo utilizada por nosotros pero la explicare debido a que la he mencionado, la directiva DirectoryIndex especifica la lista de archivos en orden de prioridad que se buscará para entregar al cliente cuando este accede a un directorio, por ejemplo DocumentRoot. Seré mas claro,cuando el cliente solicite la página www.ejemplo.com nosotros esperamos que este reciba la página principal de nuestro sitio web, esta página esta definida en un archivo y este archivo tiene generalmente por nombre index.html y es ese el archivo con el cual nuestro servidor responde al cliente. La directiva DirectoryIndex tendrá por ejemplo la forma DirectoryIndex index.html index.php lo cual le indica a apache que debe responder al cliente con el archivo index.html si existe, de lo contrario con el archivo index.php si existe, etc. Si ninguno de los nombres de archivos existiera y la opción Indexes estuviera permitida en el directorio, la respuesta del servidor será la lista de directorios y archivos presentes en el directorio. Si ninguna de estas circunstancias se diera se responderá con un error 403 Forbidden. Si la directiva no se especifica, como en nuestro caso, se tomara el valor especificado en el archivo apache2.conf, que generalmente es:
DirectoryIndex index.html index.cgi index.pl index.php index.xhtml
2.1.10 La directiva AllowOverride
Esta directiva se coloca en un contexto <Directory> e indica si debe procesarse el archivo .htacces en caso de que existiera en el directorio. ¿Qué es un archivo .htacces? Es un archivo que contiene directivas que se aplican al directorio en el que se encuentra, las directivas son las mismas que se colocan en un contexto Directory, como Order, Options, etc y suele resultar útil ya que permite al Webmaster incluir directivas de control de acceso al directorio sin necesidad de modificar el archivo de configuración del host, lo cual requeriría la intervención del administrador del servidor web. El valor por defecto es AllowOverride All, nosotros preferiremos no procesar ningún archivo .htacces por lo que la establecemos a AllowOverride None. Mencionaré que es posible también indicarle que tipo de directivas debe procesar del archivo .htacces y cuales ignorar pero no se explicara eso en este articulo.
2.1.11 Las directivas Order, Allow y Deny
Estas directivas están muy relacionadas entre si, se colocan en un contexto <Directory> y se encargan del control de acceso al directorio. Las directivas Allow y Deny tiene siempre la forma Allow form y Deny form respectivamente, y se especifica a continuación una lista de lo host o nombres de host de la forma Allow form Lista o bien Deny form lista.En el caso de Allow se indica la lista de hosts a la que se le permitirá acceso al directorio, en el caso de Deny se indica la lista de hosts a los cuales se denegará el acceso. En la lista se pueden mencionar IPs o redes completas, como por ejemplo Allow from 172.16.0.0/255.255.0.0 significa que se permitirá acceder al directorio a cualquier host cuya IP esté dentro del rango 172.16.0.1 y 172.16.255.254. También pueden mencionarse dominios, en tal caso se evaluará como coincidencia cualquier nombre que pertenezca al dominio, por ejemplo la directiva Allow from midominio.com coincide con el nombre foo.midominio.com pero no con foomidominio.com ya que no se evalúa como expresión regular. También puede utilizarse la palabra All del modo Allow from All o bien Deny from All para indicar Todos. La directiva Order especifica en que orden se evaluarán las directivas Allow y Deny. Siempre tendrá una de las siguientes dos formas:
Order Allow,Deny
o bien
Order Deny,Allow.
El comportamiento que posee puede no ser muy intuitivo, el uso de dos listas que aceptan rangos hace evidente que un mismo nombre o dirección IP podría coincidir en ambas o en ninguna, en cualquiera de estos dos casos tomara el valor de la segunda directiva y no de la primera como se podría pensar. El comportamiento de las evaluaciones se explica en el siguiente cuadro:
Resultado de la evaluación | Order Deny,Allow | Order Allow,Deny |
-----------------------------------------------------------------------------
Coincide solo en Allow | Se permite acceso | Se permite acceso |
Coincide solo en Deny | No se permite acceso | No se permite acceso |
No hay coincidencia | Se permite acceso | No se permite acceso |
Coincide en ambas | Se permite acceso | No se permite acceso |
2.1.12 La directiva ServerSignature
Indica si se agregará o no una línea en pié de página con información del servidor en los mensajes de error que genera el servidor, suele ser útil para la depuración.
2.2 Agregando Cifrado ssl
Supongamos ahora que deseamos agregar un nuevo sitio pero que la comunicación entre el cliente y el servidor sea cifrada mediante el uso de https. Lo primero que haremos es, al igual que en el caso anterior, copiar los archivos de nuestro sitio web al servidor, los ubicaremos en /var/www/páginacifrada.Ahora nos toca activar el cifrado ssl en apache, lo hacemos mediante la utilidad a2enmod ejecutando:
# a2enmod ssl
También debemos decir a apache que debe aceptar solicitudes en el puerto 443 que es el puerto estándar de https por lo que editamos el archivo /etc/apache2/ports.conf y agregamos la línea Listen 443
Ahora necesitamos crear los certificados que utilizaremos para el cifrado, para ello utilizaremos OpenSSL, deberemos instalarlo ejecutando
# aptitude install openssl
Una vez hecho esto nos movemos a un directorio temporal, por ejemplo /tmp, y generamos los certificados
# openssl genrsa -out privado.pem 2048
Y luego
# openssl req -new -key privado.pem -out peticion.pem
Luego de ejecutar este último comando se nos solicitara una serie de datos, cuando se nos solicite ingresar Common Name ingresaremos www.páginacifrada.com. Con esto hemos generado el certificado de clave privada, el cual se almaceno en el archivo privado.pem y una petición de certificado que se almaceno en el archivo peticion.pem. En este punto debemos decidir si haremos firmar nuestro certificado público por una entidad certificadora o lo auto firmaremos nosotros mismos, si nos decidiéramos por auto firmar el certificado entonces lo que hacemos es
#openssl x509 -req -days 3650 -in peticion.pem -signkey privado.pem -out publico.pem
Esto ha generado nuestro certificado público en el archivo publico.pem, a continuación lo que haremos es crear los directorios /etc/ssl/private y /etc/ssl/certs, copiamos el certificado de clave pública publico.pem a /etc/ssl/certs y el certificado de clave privada privatdo.pem a /etc/ssl/private
Debido a la importancia de preservar en secreto el certificado privado es común que este se lo genere cifrado, en tal caso apache nos solicitara en cada inicio que ingresemos la clave de cifrado del mismo, en nuestro caso el certificado de clave privada lo almacenamos sin cifrar para evitar este inconveniente pero queda a criterio del lector que método desea utilizar. Lo que si haremos, para mejorar la seguridad de nuestro certificado de clave privada, es restringir el acceso al mismo colocando permisos de lectura solo para root.
# chmod 400 /etc/ssl/private/privado.pem
Podría surgir la siguiente pregunta: ¿Cómo hace apache para leer este archivo si corre como el usuario www-data y no como root?, bien, apache corre como www-data pero inicia como root por lo que eso no será un inconveniente.
Lo que haremos ahora es diferenciar los Host virtuales que funcionan cifrados de los que no lo hacen del siguiente modo: editaremos el archivo /etc/apache2/sites-available/default y modificaremos la línea que dice:
NameVirtualHost * poniendo NameVirtualHost *:80
y agregaremos abajo de esta una nueva línea en la que dirá:
NameVirtualHost *:443
Si recuerdan, cuando explique la directiva VirtualHost dije que en la definición de los host virtuales la directiva VirtualHost debía respetar el nombre del NameVirtualHost por lo que editaremos la directiva VirtualHost tanto en /etc/apache2/sites-available/default como en /etc/apache2/sites-available/www.ejemplo.com para que esto se cumpla, quedara entonces en ambos archivos:
<VirtualHost *:80>
También dije que si se crea un NameVirtualHost debe haber al menos un VirtualHost que haga uso de el, por lo tanto creamos el archivo /etc/apache2/sites-available/www.páginacifrada.com y lo editamos agregando lo siguiente:
1 <VirtualHost *:443>
2 ServerName www.páginacifrada.com
3 ServerAlias páginacifrada.com
4 ServerAdmin webmaster@páginacifrada.com
5 DocumentRoot /var/www/ páginacifrada
6 <Directory />
7 Options FollowSymLinks
8 AllowOverride None
9 </Directory>
10 <Directory "/var/www/ páginacifrada">
11 Options Indexes FollowSymLinks MultiViews
12 AllowOverride None
13 Order allow,deny
14 allow from all
15 </Directory>
16 SSLEngine on
17 SSLCertificateFile "/etc/ssl/certs/publico.pem"
18 SSLCertificateKeyFile "/etc/ssl/private/privado.pem"
19 ErrorLog /var/log/apache2/páginacifrada.error.log
20 LogLevel warn
21 CustomLog /var/log/apache2/access.log combined
22 </VirtualHost>
Luego solo resta reiniciar apache
# /etc/init.d/apache2 restart
Y si poseemos un servidor DNS que resuelva el nombre www.páginacifrada.com a la dirección IP de nuestro servidor (para esto ya no nos servirá el truco del servidor proxy) ya podremos acceder escribiendo en la barra de direcciones de nuestro navegador
https://www.páginacifrada.com
Nuestro navegador nos pregunta si deseamos aceptar el certificado, le decimos que si, esto sucede debido a que lo hemos auto firmado, si se hubiera firmado el certificado por una autoridad certificadora como Thawte o Verisign esto no sucedería pero claro, para eso hay que pagar una buena suma de dinero. Existe la posibilidad de firmar nuestro certificado por Cacert, una entidad certificadora sin costo. En tal caso nuestro navegador debería tener instalado el certificado raíz de Cacert.
Veamos ahora el significado de las nuevas directivas que pueden verse en /etc/apache2/sites-available/www.páginacifrada.com
2.2.1 La directiva SSLEngine
Esta directiva establece si se utilizará cifrado ssl, dicha característica viene dada por el modulo mod_ssl que activamos previamente y por default esta desactivada. Para activarla: SSLEngine on.
2.2.2 La directiva SSLCertificateFile
Mediante esta directiva se le indica a apache la ruta al certificado público.
2.2.3 La directiva SSLCertificateKeyFile
Mediante esta directiva se le indica a apache la ruta al certificado privado.
2.2.4 La directiva ErrorLog
Mediante esta directiva se le indica a apache la ruta al archivo de log de errores.
2.2.5 La directiva CustomLog
Mediante esta directiva se le indica a apache la ruta al archivo de log. El segundo argumento de la directiva específica el formato con el que se almacenaran los registros de log, se pueden especificar el formato indicando los valores que se desean almacenar, fecha y hora del evento, IP del host remoto, la URL solicitada, etc. Al final quedará algo como "%h %l %u %t "%r" %>s %b", pueden especificarse formatos prediseñados, combined es uno de ellos.
2.2.6 La directiva LogLevel
Mediante esta directiva se le indica a apache el nivel de relevancia que debe poseer un mensaje de error para que sea registrado en el log especificado en la directiva ErrorLog. Los niveles son varios y van desde solo registrar errores que hacen imposible el funcionamiento hasta el registro de mensajes de información que pueden utilizarse durante la depuración. El nivel por defecto es warn (de Warning: Alerta) y es el que utilizaremos.
2.3 Redireccionando a partir de una página sin cifrar
Seguramente nos hemos dado cuenta que para poder acceder a nuestra página cifrada hemos escrito https://www.páginacifrada.com en la barra de direcciones del navegador, habrá quien ha intentado acceder sin colocar https:// delante de la dirección y se han desilusionado al ver que no se puede acceder de ese modo, otros se dan cuenta recién ahora que es por eso que no funciona la página cifrada ya que han intentado acceder de ese modo desde el principio y pensaron que estaban haciendo algo mal en la configuración.
Bien, es lógico que no funcione sin colocar https:// ya que los navegadores asumen muchas cosas cuando se conecta a un sitio web. En general intentaran por defecto conectarse mediante http utilizando el puerto 80, es decir, el navegador asume que es eso lo que queremos hacer, por lo que si queremos utilizar https a través del puerto 443 deberemos hacerlo diciendo explícitamente al navegador que protocolo utilizar.
Podrán decir que ustedes nunca necesitaron hacer eso para conectarse a un sitio seguro, eso es porque se han conectado a un servidor web mediante http y este los ha redireccionado hacia una página https, eso es lo haremos nosotros.
Lo primero es editar el archivo de configuración de nuestro sitio donde agregaremos un nuevo host virtual que acepte peticiones en el puerto 80 y que lo único que haga sea redireccionar hacia nuestro sitio seguro.
En el archivo /etc/apache2/sites-available/www.páginacifrada.com quedara entonces algo como esto:
1 <VirtualHost *:80>
2 ServerName www.páginacifrada.com
3 ServerAlias páginacifrada.com
4 Redirect permanent / https://www.páginacifrada.com/
5 </VirtualHost>
6 <VirtualHost *:443>
7 ServerName www.páginacifrada.com
8 ServerAlias páginacifrada.com
9 ServerAdmin webmaster@páginacifrada.com
10 DocumentRoot /var/www/páginacifrada
11 <Directory />
12 Options FollowSymLinks
13 AllowOverride None
14 </Directory>
15 <Directory "/var/www/páginacifrada">
16 Options Indexes FollowSymLinks MultiViews
17 AllowOverride None
18 Order allow,deny
19 allow from all
20 </Directory>
21 SSLEngine on
22 SSLCertificateFile "/etc/ssl/certs/publico.pem"
23 SSLCertificateKeyFile "/etc/ssl/private/privado.pem"
24 ErrorLog /var/log/apache2/páginacifrada.error.log
25 LogLevel warn
26 </VirtualHost>
Donde se puede ver una nueva directiva.
2.3.1 La directiva Redirect
Esta directiva redirecciona una URL a otra. El redireccionamiento se hace a través del cliente y no del servidor, el servidor se limita a enviar al cliente un mensaje indicando que la URL se ha movido y el cliente debe aceptar la redirección, por lo general los navegadores aceptan esta redirección sin intervención del usuario por lo que, si bien el redireccionamiento no es transparente al cliente, si lo es para el usuario. El modificador permanent indica que debe enviarse al cliente el código de estado 301 Redirect (Permanent redirect status) que indica que la página ha sido movida permanentemente. La sintaxis es:
Redirect [status] Objeto_redireccionado URL_destino
Donde Objeto_redireccionado es la ruta relativa a partir de DocumentRoot del objeto que se redireccionara y URL_destino es la URL absoluta a la cual se ha movido el objeto. En nuestro caso redireccionamos el DocumentRoot, por lo que estamos diciendo que todo el sitio se ha movido a la url URL_destino.
Muy bien, reiniciemos apache
# /etc/init.d/apache2 restart
Y ya podemos acceder a nuestra página cifrada a través de la dirección www.páginacifrada.com.
3 Seguridad
Evidentemente al momento de establecer opciones dentro de las directivas Directory estamos pensando en seguridad, el realizar un control de acceso a los recursos es necesario siempre pero no es suficiente para lograr un nivel de seguridad aceptable.
La seguridad debe realizarse a conciencia y es una tarea que debe hacerse de modo constante, el chequear los archivos de log es una tarea que cualquier administrador medianamente responsable realizará a diario, la correcta ubicación y configuración de un firewall, el uso y configuración conciente de servicios como ssh o sftp, la fortaleza de las contraseñas y el control de acceso físico al servidor son cuestiones básicas que hacen a la seguridad, hay además infinidad de herramientas que permiten agregar seguridad a un servidor web, en este articulo nos centraremos exclusivamente en el uso de elementos incluidos en apache, por esto mencionaremos aspectos en la configuración que son deseables en cuanto a seguridad así como también el uso de Mod Security, herramienta de la cual se dará una breve introducción de sus uso y configuración.
3.1 Oscuridad
Este método de seguridad nunca será suficiente pero es siempre deseable que se utilice. Seguridad por oscuridad es ocultar todo lo posible aspectos que pudieran ser de utilidad para un atacante, es algo así como enterrar el tesoro, nunca será tan seguro como meterlo en una caja fuerte pero mientras nadie sepa donde está estará a salvo. Utilicemos esa idea. Recordemos el error 404 que generamos intencionalmente en el paso de instalación de PHP cuando solicitamos al servidor un archivo inexistente, como pudimos notar el servidor nos retorno una página informándonos del error y al pie de página incluyó una línea que menciona el nombre y versión del servidor web, nombre y versión del sistema operativo y los módulos cargados, información que será imprescindible para cualquier atacante y nosotros se la estamos brindando con toda facilidad. Para evitar esto modificaremos en la configuración de nuestros host virtuales la directiva ServerSignature quedando así:
ServerSignature Off.
Pero debido a que esta opción se incluye en cada host virtual y podríamos olvidar quitarla en alguno, nos aseguraremos que nuestro servidor nunca comparta esta información, editaremos el archivo /etc/apache2/apache2.conf modificando la línea ServerSigature para establecer que, por defecto, no se incluya pié de página. Lamentablemente esto no es suficiente, aunque la información no se mostrará en la página de error aún se incluye en la cabecera http del mensaje, por lo tanto también modificaremos la línea ServerTokens para indicarle a apache que el servidor se encuentra en producción y evitar que emita esa información:
ServerTokens Prod
ServerSigature Off
Recordemos también que, después de la instalación de eAccelerator creamos en /var/www/ un archivo de nombre info.php que utilizamos para saber que eAccelerator se encontraba activo, asegurémonos de haber borrado ese archivo. Pensemos ahora en los archivos de nuestras páginas web, nosotros simplemente copiamos los archivos a /var/www pero nunca hicimos mención de que usuario seria el propietario de dichos archivos, por lo general el propietario de tales archivos es el usuario que el webmaster utiliza para transferir los archivos via sftp, eso estará bien, es importante que, siempre que sea posible, estos archivos no sean propiedad del usuario con el cual corre apache, en nuestro caso www-data, y que tampoco tenga permisos de modificación sobre ellos por supuesto. De ese modo evitaremos que los archivos puedan ser modificados por un atacante en el supuesto caso que lograra obtener acceso como ese usuario, este ataque se conoce como defacing. También deberíamos hacer uso de las directivas Directory, alow, deny y order para lograr que el acceso a directorios de configuración como por ejemplo los direccionados habitualmente por URLs de la forma www.dominio.com/admin sean restringidos a una dirección IP o dominio conocido.
Si utilizáramos páginas cifradas será muy buena idea que el certificado de clave privada se almacene cifrado, en nuestro caso lo habíamos almacenado sin cifrar por comodidad y muy comúnmente se hace de ese modo, si quisiéramos agregar seguridad podemos crear el certificado ya cifrado o bien cifrarlo luego, un certificado puede cifrarse y descifrarse en cualquier momento. Podemos entonces ejecutar:
# openssl rsa -in privado.key -out privado_cif.key -des3
Esto nos pedirá un password y su confirmación y luego almacenará de forma cifrada nuestra clave privada privado.key en el archivo privado_cif.key, dicho password será solicitado por apache en cada reinicio. Para quitar el cifrado ejecutamos:
# openssl rsa -in privado_cif.key -out privado.key
Lo que nos solicitará el password y luego almacenara en privado.key nuestra clave privada sin cifrar. Por experiencia aconsejo que el certificado se almacene cifrado en el servidor pero que como respaldo guarden el certificado sin cifrar en algún lugar seguro por si olvidaran el password. Los mas paranoicos solemos imprimir en papel el certificado privado sin cifrar y guardarlo bajo llave, si examinan el archivo verán que es un simple archivo de texto, en caso de perdida el certificado original puede ser reconstruido a partir de la impresión en papel.
3.2 El módulo mod_security
Ya tenemos el módulo Mod Security instalado y funcionando, ahora solo debemos agregar las reglas. Como se mencionó durante la etapa de instalación hay disponibles en la página web del autor de Mod Security un conjunto de archivos con reglas prediseñadas, en general este grupo de reglas será suficiente para la mayoría de los casos. Creamos un directorio donde descargar las reglas, por ejemplo /root/rules, nos ubicamos en el y ejecutamos:
# wget http://www.modsecurity.org/download/modsecurity-core-rules_2.5-1.6.0.tar.gz
Descomprimimos y desempaquetamos:
# tar -zxvf modsecurity-core-rules_2.5-1.6.0.tar.gz
Y ya tenemos a la vista el grupo de archivos con las diferentes reglas.
El grupo de reglas que se escogerá depende de nuestras necesidades por lo que se necesitará de criterio y conocimiento, en algunos casos no podremos agregar todas ya que esto podría limitar o impedir el funcionamiento de nuestro sitio web ya que se limita la interacción que el cliente puede tener con el servidor pero en los casos en que la interacción con el cliente sea mínima será posible agregarlas todas.
Lo básico es agregar el archivo modsecurity_crs_10_config.conf que es el que contiene la configuración básica de Mod Security, este archivo, si bien esta en inglés, explica muy bien el significado de cada directiva que contiene y podemos modificarlo según nuestro parecer. Las modificaciones serán necesarias ya que en este archivo se hace referencia a archivos inexistentes como los de log y debug y debemos especificar una ruta valida hacia ellos, por ejemplo podemos crear el directorio /var/log/mod_security para almacenar los archivos de log y debug y luego modificar modsecurity_crs_10_config.conf para que quede como sigue:
SecAuditLog /var/log/mod_security/audit.log
SecDebugLog /var/log/mod_security/debug.log
El resto de los archivos deberemos examinarlos nosotros para asegurarnos de que no presentaran problemas al normal funcionamiento de nuestro sitio web. Esto no es fácil y lleva bastante tiempo pero cabe aclarar que Mod Security no es algo simple de manejar así como la administración de redes y servidores no es algo simple de hacer, requiere de mucho conocimiento y sobre todo dedicación.
Si lo deseamos, podemos agregar reglas personalizadas, para esto deberemos conocer sobre expresiones regulares y respetar el formato que deben tener las reglas. Para eso deberemos dirigirnos a la documentación pero daré una breve idea de su manejo:
Mod Security es un firewall y como tal lo que hace es ver pasar la información y determinar que cumple con determinadas características y que no para así realizar acciones al respecto. Al ser un firewall de aplicación destinado especialmente a servidores web comprende los protocolos http y https por lo que es capaz de diferenciar lo que es la cabecera de un mensaje http, el cuerpo del mensaje, un archivo, el conjunto de parámetros que el cliente envía al servidor, el valor de esos parámetros, el conjunto de caracteres, etc. Mod Security llama Variable a cada uno de estos datos, cuando se define una regla se esta diciendo a mod security que busque en una variable o conjunto de variables un patrón determinado, este patrón podría ser desde la coincidencia con una expresión regular hasta si la o las variable cumplen cierta característica, por ejemplo si esta en codificación UTF-8 o si posee la forma correcta de una URL. El método a utilizar para realizar la búsqueda dentro de la variable se especifica mediante lo que se denomina un Operador. Cuando una regla se cumple, se lleva a cabo una serie de acciones especificadas en la misma regla, estas acciones podrían ser denegar el acceso, responder al cliente con un mensaje determinado y crear un registro en un archivo de log con toda la información necesaria.
Las reglas tienen la forma:
SecRule Variable[ | Variable] Operador [Acción]
Donde:
- Variable es el dato o conjunto de datos que se analizará. Estas variables ya están predefinidas, la lista completa de variables está disponible en http://www.modsecurity.org/documentation/modsecurity-apache/2.5.1/modsec...
- Operador es el método por el cual se buscara y, si el operador lo requiere, lo que se buscará. Esta expresión retorna verdadero o falso indicando si la regla coincide o no con la expresión buscada. Por defecto es rx que busca como expresión regular y es el utilizado si se omitiera el operador. Si se desea especificar otro operador se especifica colocando @Operador. Por ejemplo "@rx algo" es equivalente a "algo" y, en ambos casos, se busca en la variable la coincidencia con la expresión regular "algo", si se desea saber si en la variable existe la frase "algo" pero no como expresión regular sino exactamente se utilizará del modo "@streq algo", las comillas dobles son necesarias debido a que la expresión contiene espacios en blanco. El operador puede no requerir valor alguno, por ejemplo si se utilizara @validateUtf8Encoding chequea si la variable esta codificada en UTF-8 o no. Si se colocara !@ en lugar de @ se estará negando el resultado de la expresión. La lista completa de operadores está disponible en http://www.modsecurity.org/documentation/modsecurity-apache/2.5.1/modsec...
- El ultimo parámetro, Acción, es opcional y especifica que acciones se llevaran a cabo si la regla encontrara coincidencia, si se omite se tomara la acción por default especificada en la directiva SecDefaultAction, ésta directiva se encuentra en el archivo modsecurity_crs_10_config.conf pero está comentada, es necesario des comentarla si se desea utilizar una acción por default. La lista completa de acciones está disponible en http://www.modsecurity.org/documentation/mod-security-apache/2.5.1/modse...
Por ejemplo:
SecRule REQUEST_HEADERS:User-Agent "mozilla" "log,drop"
Es una regla que examina la cabecera del mensaje y si el agente de usuario es mozilla entonces almacena un registro de log y deniega el acceso. Si se utilizara:
SecRule REQUEST_HEADERS "mozilla" "log,drop"
Entonces se buscaría la coincidencia en toda la cabecera y no solo en el parámetro User-Agent. Cabe aclarar que, como se explico anteriormente, la expresión "mozilla" se evalúa como una expresión regular ya que se ha omitido el operador. La evaluación como expresión regular es el operador mas utilizado y por eso es tan importante tener conocimiento de ellas. Para darnos cuenta basta con examinar las reglas que hemos bajado, por ejemplo la siguiente regla se encuentra en el archivo modsecurity_crs_40_generic_attacks.conf y su fin es detectar un intento de ataque del tipo "SQL Injection", ataque que consiste en ingresar, por ejemplo en un campo de texto de un formulario para login, un fragmento de código SQL para intentar que el motor de base de datos lo incluya en la consulta SQL y así burlar la autenticación, como podemos ver la regla posee un gran nivel de complejidad:
SecRule REQUEST_HEADERS|XML:/*|!REQUEST_HEADERS:Referer "(?:b(?:(?:s(?:electb(?:.{1,100}?b(?:(?:length|count|top)b.{1,100}?bfrom|fromb.{1,100}?bwhere)|.*?b(?:d(?:umpb.*bfrom|ata_type)|(?:to_(?:numbe|cha)|inst)r))|p_(?:(?:addextendedpro|sqlexe)c|(?:oacreat|prepar)e|execute(?:sql)?|makewebtask)|ql_(?:longvarchar|variant))|xp_(?:reg(?:re(?:movemultistring|ad)|delete(?:value|key)|enum(?:value|key)s|addmultistring|write)|e(?:xecresultset|numdsn)|(?:terminat|dirtre)e|availablemedia|loginconfig|cmdshell|filelist|makecab|ntsec)|u(?:nionb.{1,100}?bselect|tl_(?:file|http))|groupb.*bbyb.{1,100}?bhaving|d(?:eletebW*?bfrom|bms_java)|loadbW*?bdatab.*binfile|(?:n?varcha|tbcreato)r)b|i(?:n(?:tobW*?b(?:dump|out)file|sertbW*?binto|nerbW*?bjoin)b|(?:f(?:bW*?(W*?bbenchmark|nullb)|snullb)W*?()|a(?:ndb ?(?:d{1,10}|['"][^º=]{1,10}['"]) ?[=<>]+|utonomous_transactionb)|o(?:rb ?(?:d{1,10}|['"][^=]{1,10}['"]) ?[=<>]+|pen(?:rowset|query)b)|havingb ?(?:d{1,10}|['"][^=]{1,10}['"]) ?[=<>]+|printbW*?@@|castbW*?()|(?:;W*?b(?:shutdown|drop)|@@version)b|'(?:s(?:qloledb|a)|msdasql|dbo)')" "capture,t:urlDecodeUni,t:htmlEntityDecode,t:replaceComments,t:compressWhiteSpace,t:lowercase,ctl:auditLogParts=+E,deny,log,auditlog,status:501,msg:'SQL Injection Attack',id:'959001',tag:'WEB_ATTACK/SQL_INJECTION',logdata:'%{TX.0}',severity:'2'"
Como se dijo anteriormente, si se desea que una regla de mod security se aplique a un VirtualHost en particular debe agregarse dicha regla entre las directivas <VirtualHost> y </VirtualHost> correspondientes
Para confirmar que Mod Security esta operando podemos intentar simular un par de ataques a nuestro propio servidor web, por ejemplo, ingresar en la barra de direcciones la dirección de nuestro servidor y luego algunos símbolos para que quede algo como www.ejemplo.com/&%$$%B7%22&& de modo de simular un intento de ataque a un buffer overflow y podremos ver la respuesta, un Error 400 Bad Request y además podemos dirigirnos al archivo de log de Mod Security y constatar que se ha registrado el evento. También podemos probar con algo como www.ejemplo.com/algo" or "1"="1 y ver que en el archivo audit.log se ha registrado el evento como un intento de ataque SQL Injection y que ha sido considerado por Mod Security como de severidad "CRITICA". Si no hubiéramos deshabilitado las opciones ServerSignature nos daríamos cuenta también que nuestro servidor se identifica ahora con el cliente diciendo que corre sobre un Sistema Fedora, esto es lo especificado en la directiva SecServerSignature que se encuentra en el archivo modsecurity_crs_10_config.conf y podemos modificarla a nuestro parecer.
4. Referencias:
http://www.debian.org/
http://httpd.apache.org/docs/2.2/
http://eaccelerator.net/
http://howtoforge.com/eaccelerator_php5_debian_etch
http://www.modsecurity.org/documentation/modsecurity-apache/2.5.2/modsec...
http://www.openssl.org/
- 782 lecturas
- Responder