jueves, noviembre 01, 2007

Fortificando un Servidor Apache (III de IV)

***************************************************************************************
- Fortificando un Servidor Apache (I de IV)
- Fortificando un Servidor Apache (II de IV)
- Fortificando un Servidor Apache (III de IV)
- Fortificando un Servidor Apache (IV de IV)
***************************************************************************************

En estas dos últimas partes, vamos a tratar de varios aspectos importantes en la fortificación de un servidor Apache, a saber, en primer lugar vamos a ver como configurar los sistemas de cifrado de comunicaciones con SSL/TLS con nuestros sitios web; en segundo lugar la configuración de los registros de actividad para su posterior análisis, es decir, los logs; en tercer lugar vamos a ver los sistemas de autenticación de usuarios y por último como configurar mod_security para filtrar las URLs de acceso a nuestros sitios. En esta tercer parte Mod_SSL y la Gestión de Logs.

Mod_SSL

El protocolo de comunicaciones SSL/TLS se utiliza para cifrar la comunicación entre dos equipos y autenticar a los participantes de la misma. Este artículo no pretende mostrar el funcionamiento del sistema SSL, ampliamente descrito en numerosos artículos desde su aparición, sino simplemente como se debe configurar en un servidor Apache para que las conexiones a nuestro servidor estén cifradas y, en caso de que así se desee, también autenticadas.

Siempre que se utilice SSL/TLS estamos cifrando las comunicaciones extremo a extremo, sin embargo el proceso de autenticación requiere de una configuración con más cuidado. Si se desea autenticar al servidor, es decir, que los clientes tengan la certeza de que se están comunicando con el servidor que ellos desean, es necesario utilizar un certificado emitido por una Entidad Emisora de Certificados contrastable por los usuarios de nuestro sistema, o lo que es lo mismo, una Entidad en la que los clientes confíen y tengan la clave pública de esta instalada en su máquina. Si esto no se produce, el uso de SSL ayuda a cifrar las comunicaciones pero no ayudará a detectar un certificado falso (fake) emitido por un atacante en medio. Es por ello, a pesar de que en el presente artículo, y, como muestra didáctica únicamente, se utiliza un certificado emitido por nosotros mismos, se recomienda utilizar un certificado de servidor emitido por una CA de confianza para nuestros usuarios.

Con SSL, además de autenticar el servidor, se pueden autenticar a los clientes mediante certificados digitales a la hora de iniciar la conexión con SSL, aunque esta no es una práctica muy extendida debido a la complejidad en el despliegue y mantenimiento de los certificados de los clientes.

Para realizar un ejemplo de configuración, en este artículo hemos utilizado un Certificado Digital para servidores web creado por nosotros. Hemos utilizado para ello la utilizad OpenSSL [http://www.openssl.org] y hemos creado uno como se puede ver en la siguiente captura.

Imagen: Creación de un certificado digital con openssl

El proceso que hay que seguir para la creación del certificado es sencillo. Primero hay que instalar la herramienta openssl siguiendo los pasos de configuración (./configure), construcción (make) e instalación (make install). Una vez que tengamos funcionando la herramienta en nuestro sistema podremos crear el certificado con el comando que se ve en la imagen.

Con ese comando le estamos diciendo a la herramienta que nos cree un certificado X.509 con una caducidad de 1000 días, es decir, pasados estos 1000 días será necesario renovar el certificado. Este certificado va a ser creado con una clave de 1024 bytes y se van a generar dos ficheros, uno el del certificado y otro el de la petición y no van a estar protegidos por contraseña. Como se puede apreciar, hemos pedido que el certificado se emita para nuestro servidor al que hemos nombrado como “malignito.elladodelmal.com”.

Con el certificado digital emitido ya tenemos lo necesario para configurar el soporte SSL en nuestro servidor web. Lo primero que hemos de preparar el que el servidor Apache cargue el módulo SSL, para ello, como vimos en el artículo del mes pasado, realizando una configuración inicial podemos utilizar la opción de preparar el servidor con soporte para el mod_ssl usando configure –prefix=ruta –enable-ssl. Algunas distribuciones de Linux, como Debian, ofrecen una versión de Apache acompañada de algunas herramientas que ayudan en la gestión de módulos como a2enmod que permite agregar módulos a Apache. Como vimos en las partes anteriores, con el comando httpd –l se puede comprobar la lista de módulos que están activos.

Imagen: Lista de módulos cargados en Apache. Mod_ssl cargado.

Ya está cargado el modulo SSL en el servidor Apache, ahora deberemos configurar una serie de parámetros para dar soporte a SSL a nivel de servidor o de Virtual Host. Para ello se deben configurar las opciones en el archivo httpd.conf. SSL viene acompañado de muchas opciones y es recomendable, para ajustes especiales, consultar la documentación de mod_ssl que está disponible en la siguiente URL http://httpd.apache.org/docs/2.2/en/mod/mod_ssl.html. No obstante, la siguiente tabla muestra las configuraciones que se deben realizar para que nuestro servidor esté funcionando correctamente:

- SSLEngine on/off: Este parámetro activa el uso de SSL en nuestro servidor. Si, la configuración del servicio fuera errónea el soporte no se activaría y puede llegar a no levantar los demonios de Apache, luego es importante tener correctamente configurado el servicio antes de ponerlo activo.

- SSLProtocol:Este parámetro se utiliza para determinar cuáles van a ser los protocolos de cifrado que se van a utilizar en nuestro servidor. Hay que tener en cuenta que cuando se produce el “handshake” o saludo inicial entre el cliente y el servidor, estos negocian el protocolo a utilizar. Si no deseamos que se utilice un protocolo antiguo o inseguro debemos deshabilitar el uso de todos a excepción de los protocolos seguros. Esta acción puede producir problemas de acceso en clientes antiguos. La lista de protocolos que vienen con SSL son: SSLv2, SSLv3, TLSv1.

- SSLCipherSuite: Una vez elegido el protocolo SSL a utilizar, en mod_ssl podremos configurar las opciones de cifrado, para ello podemos elegir los algoritmos de generación de clave, decantándonos por el uso de RSA o de Diffie-Hellman con claves RSA o Diffie-Hellman con claves DSA, etc… Así mismo podremos elegir los algoritmos de firma, de codificación, y las longitudes de cifrado a usar. Es decir, podemos realizar un ajuste fino de la criptografía que nos va a permitir securizar las comunicaciones hasta nuestro deseo. Hay que tener en cuenta que el deshabilitar ciertas opciones de cifrado puede generar conflictos con clientes que no tengan una suite criptográfica amplia y moderna.

- SSLOptions: Este parámetro se va a utilizar para configurar diferentes comportamientos en diferentes situaciones. LA opción +StrictRequire se va a utilizar para deshabilitar el acceso por medio http a aquellas rutas en las que se exija SSL.

- SSLCertificateFile: Ruta al archivo del certificado del sitio

- SSLCertificateKeyFile: Ruta al archivo key del certificado.

- SSLCACertificateFile: El certificado digital de la Entididad Certificadora.

- SSLCARevocationFile: Archivo dónde se encuentra la CRL (Lista de Certificados Revocados).

- SSLRequire: Este parámetro se utiliza para exigir un cumplimiento de opciones SSL a la hora de acceder a una determinada ruta del servidor. Se utilizan expresiones regulares para poder afinar las restricciones.
SSLRequireSSL Parámetro para forzar el uso de http-s en un determinado directorio. Si está configurada la opción +StricRequire se prohibirá el uso de http.

En la siguiente captura tenemos una configuración válida del archivo httpd.conf que levanta los demonios httpd con soporte SSL. Como se puede ver se ha habilitado la escucha por el puerto 443, que es el que por defecto se utiliza para el protocolo https-s. Se han configurado los parámetros SSLEngine on para levantar los servicios SSL, SSLCertificateFile y SSLCertificateKeyFile con las rutas a los ficheros creados con el comando openssl; se ha activado el soporte para TLSv1 y SSLv3 en exclusividad y se ha configurado la suite de cifrado con soporte Medio y Alto y el uso de protocolos de firma SHA1 y MD5.
Después, en la ruta de acceso a los documentos se ha exigido el uso de SSL con el parámetro SSLRequireSSL.

Imagen: Configuración httpd.conf para soprote SSL.

Con esta configuración, cuando se levanta el servicio http y se intenta acceder a la ruta por defecto de nuestro servidor se obtendrá un mensaje de error, que puede ser personalizado como se explicó en el artículo del mes pasado, en el que nos avisa de que es estrictamente necesario el uso de httpd-s.

Imagen: Error, la conexión debe realizarse por medio de http-s.

Si se accede al servidor mediante el uso de una conexión http-s el acceso será concedido y se podrá consultar toda la información sobre el certificado digital que se está utilizando el servidor.

Imagen: Acceso mediante http-s

Gestión de Logs

La configuración de los registros de acceso y los eventos que ser producen en un servidor Web son de especial importancia pues pueden ayudar a detectar preventivamente un ataque al sistema, una debilidad que está siendo explotada o simplemente un fallo en la configuración o en el sistema. Para ello Apache dispone de herramientas flexibles que van a permitir una selección flexible de lo que se quiere guardar registro, dónde y en que formato se va a guardar esta información.
Apache gestiona, por defecto, tres tipos de registros: El registro de errores, el registro de acceso y el registro del identificador del proceso (PID) del demonio del servicio. El registro de errores se guarda en un fichero que es marcado por la directiva errorlog. Esta directiva también puede utilizarse para, en lugar de guardar la información en ficheros, utilizar el servicio syslog para registrar los eventos vía red y de forma centralizada. El uso del servicio syslog será de especial utilidad cuando tenemos sistemas de análisis de log centralizados o de correlación de eventos.

ErrorLog /ruta/ficheros/log/error_log ó ErrorLog syslog:user

El nivel de información que se va a almacenar en los ficheros de registro se configura con la directiva LogLevel en la que se pueden ajustar diferentes valores:

LogLevel

- Emerg: Sólo se almacenan los mensajes que dejan al sistema incapaz de ser utilizado.

- Alert: Cuando se produce un error en el sistema que requiere la ejecución inmediata de una acción para corregirlo.

- Crit: Fallos críticos del sistema. No requieren acción inmediata pero pueden dejar el sistema no disponible.

- Error: Condiciones de error en el uso del sistema. No tiene porque afectar al uso del sistema.

- Warn: Avisos. Se producen cuando algo no está realizándose correctamente. Puede producirse por un script o un cliente que no realiza la negociación correctamente con el servidor.

- Notice: Información significativa del funcionamiento del sistema.

- Info: Información general del sistema.

- debug: Información de debuging del sistema. Cuando abre o cierra conexiones o ficheros, etc…

Cuando se establece un valor de LogLevel, se van a registrar todos los eventos de mayor o igual importancia que la que se ha configurado, de tal manera, que si se establece el valor warn, se van a registrar los eventos de tipo warn, error, critical, alert y emergency.

Imagen: Archivo error_log configurado con nivel notice

Como se puede ver en la imagen anterior, se ha configurado el nivel notice, y así, por ejemplo, se puede observar el registro de los eventos info en los que se muestra la información relativa a la negociación SSL entre clientes y servidores. En un servidor de mucho tráfico este nivel de detalle puede generar un colapso en los almacenes de log.

Los registros de acceso al servidor se almacenan aparte de los errores del servidor. Estos registros guardan información relativa a todos los accesos a documentos o intentos de acceso a los documentos. Para almacenar estar información Apache se apoya en el uso de dos módulos, que son mod_log_confing y mod_setenvif. El primero se utiliza para configurar el lugar y el formato de los ficheros de registro y el segundo para utilizar variables de entorno que permitan generar ficheros de registro condicionales, que serán muy útiles a la hora de detectar sucesos en entornos con mucho tráfico.

Para configurar los registros de acceso utilizamos las directivas LogFormat y CustomLog.

LogFormat determina que información se va a escribir y de qué forma, en el fichero de registro. La forma común es tiene esta estructura:

LogFormat "%h %l %u %t \"%r\" %>s %b" common

- %h: IP del cliente.
- %I: Identificación del cliente utilizando el servido indentd. Esta información solo será accesible si Apache se ha configurado con Identitycheck activado. Esto puede generar un cuello de botella en la creación de los ficheros log, por lo que sólo se debe utilizar en entornos de Intranets, redes privadas, etc…, controlados.
- %u: Usuario cliente.
- %t: Fecha y hora.
- %r: Petición realizada
- %s: Código de status del servidor.
- %b: Tamaño de la respuesta.

Con la directiva LogFormat te puedes crear el formato de fichero log que a ti te convenga utilizando estas variables o añadiendo información de cabeceras del cliente como:

LogFormat "%h %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" miformato

Aquí hemos añadido % {Referer} y %{User-Agent} al formato de registro y hemos quitado %I y %u.

Una vez definido el formato que a utilizar hemos de marcar el lugar de registro con:

CustomLog /ruta/logs/access_log miformato

Podemos crear tantos ficheros de log como deseemos, así por ejemplo, en uno podemos almacenar la dirección IP y la hora y en otro La dirección IP, la petición y el referer.

Control de Logs

Los ficheros de log suelen tener un rápido crecimiento por lo que deben ser controlados y tener un mantenimiento muy ajustado. Para ello se pueden utilizar los sistemas de log rotacionales, que permiten, utilizando el programa externo rotatelog crear archivos automáticos cada cierto tamaño o tiempo. Para ello definimos en ErrorLog el formato de los ficheros:

ErrorLog "|bin/rotatelogs /var/logs/errorlog.%Y-%m-%d-%H_%M_%S 50M"

Es importante el uso del pipe para la dirección de los registros de logs. En este ejemplo se utilizan las variables de fechar %Y (year), %m (month), %d (day),… para crear un nuevo archivo de log cada 50 Megabytes de tamaño.

O directamente con CustomLog, que creará logapache.nnnn (nnnn el tiempo de creación)

CustomLog "|bin/rotatelogs /ruta/logs/logapache 50M" miformato

Otra opción para gestionar los logs en Apache es el uso de cronolog. Su funcionamiento es similar al del uso de logs rotacionales pero permite configuraciones más flexibles. No viene con Apache y hay que descargarlo desde la siguiente URL: http://cronolog.org/

9 comentarios:

palako dijo...

Como te lo curras! Si es que has nacío pa'enseñá!

Está de puta madre, super completo.

Dejame añadir una cosa que seguro que le va a ahorrar dolores de cabeza a más de uno.

En muchos de los casos lo que estás interesado en montar son servidores virtuales, de forma que con un sólo servidor apache puedas publicar distintos dominios. La configuración es muy fácil, básicamente igual que lo que en artículo dice entre <Directory></Directory> aquí lo haces entre <VirtualHost></VirtualHost>.

Pero hay una cosa a tener en cuenta, y es que los virtualhost se pueden hacer por IP o por nombre, y lo más común (y barato) es que sean por nombre, con una sola IP para todos los dominios.

Esta configuración NO es válida para https, porque la información del VirtualHost está ya en la capa de aplicación, es decir, apache necesita mirar dentro del contenido del paquete para ver a que virtualhost pertenece, pero claro, si el paquete va cifrado, ¿como lo hace? No puede.

Así que para tener soporte https en un entorno multidominio, los host virtuales deben tener ips distintas.

Saludos

Anónimo dijo...

maligno, eres grande!! Desde que encontré tu blog no dejo de leerte, creo que me he enamorado :-)

Ramón Sola dijo...

¡Plas, plas, plas, plas! Gran trabajo, Chema, para que luego digan cosas malas de ti. :-D

Veamos qué nos depara la cuarta y última parte.

Chema Alonso dijo...

@palako, otra opción es cambiar el puerto y mantener la IP, también funciona.

@nosoynadie y Ramón, gracias.

Anónimo dijo...

Es cierto lo que dice palako, pero no es elegante tene run servidor web en el puerto 81... no se. Molaría poder renegociarse el certificado...

palako dijo...

Tienes que dejar de escribir comentarios antes de las 7 de la mañana, no eres tu el que escribe; se apodera de ti el espíritu del tecnicoless con el que hayas tenido pesadillas esa noche.

¿Cómo vas a cambiar el puerto? ¿Que vas a tener, un puerto distinto para cada dominio? Y cómo le vas a decir a la gente que es tu url? ¿https://www.megustanlospuertos.com:xxx donde xxx es el puerto que le toque a tu dominio según el servidor de hosting en el que estés?

Vale, es verdad, técnicamente lo puedes hacer, pero la solución es como para uno de los vídeos esos cachondos en los que haces de consultor :-) Ya te vale!

Mejor gástate los 6 euros al mes de una ip nueva, que te vas a ahorrar muchos problemas!

Chema Alonso dijo...

@palako, cierto, la mejor opción es la ip, pero como el https no tiene porque estar en la página principal sino que puede estar "a un click botón" de la principal es algo que hacen bastantes personas, y te lo digo yo que he auditado bastantes intranets con subdominios. Lo mejor es la ip, pero lo del puerto rula y se usa.

saludos!

palako dijo...

¿En intranets con subdominios? ¡Peor me lo pones, las IPs internas son grátis! En vez de configurar ips virtuales en la máquina, ¿una instancia del servidor web por cada subdominio para lanzarlas en puertos distintos?

Lo que decíamos, rular rula, pero al sysadmin ponlo mejor a regar las plantas...

Chema Alonso dijo...

Y en intennete tb.

Entrada destacada

Tu Latch "Hack Your Innovation Contest": Haz un PoC & Hack por 1.000 €

El pasado Telefónica Innovation Day 2024 lanzamos oficialmente el " Tu Latch Hack Your Innovation Contest " en el que repartimos ...

Entradas populares