Tag Archives: Apache

Apache AuthBasic con ActiveDirectory

En esta entrada veremos como configurar el módulo AuthBasic de Apache para que autentique contra LDAP de ActiveDirectory.

Ya tenemos instalado Apache con el módulo habilitado y tenemos que añadir el siguiente bloque dentro de la definición del VirtualHost.

AuthType Basic
AuthBasicProvider ldap
AuthName "Introduzca sus credenciales"
AuthzLDAPAuthoritative off # Aquí indicamos que podemos tener otras formas de autenticación
AuthLDAPBindDN "Usuario de busqueda en LDAP"
AuthLDAPBindPassword "Contraseña para el usuario de búsqueda en LDAP"
AuthLDAPURL "ldap://SERVER:3268/Cadena de conexión al árbol LDAP" NONE # El NONE indica que no hay cifrado en la conexión, podemos usar TLS, SSL, etc.
Require valid-user

Esta configuración seria suficiente para que los usuarios del Dominio se autentiquen ante Apache con sus credenciales.

Directiva Satisfy

En el servidor Apache podemos restringir los accesos a nivel de hosts con las directivas allow y deny o a nivel de usuarios con Auth. El orden en el que se aplican estas directivas lo decidimos con la directiva Satisfy.

Así nos podemos encontrar en una situación en la que queramos restringir el acceso sólo desde nuestra red local y necesitemos que algunos usuarios conecten desde casa.

La directiva Satisfy, como comentamos, conmuta entre las restricción a nivel de host y la autenticación de usuarios.

El valor por defecto es All lo que significa que debe cumplir con todas las restricciones, para que no sea tan extricto cambiamos el valor a Any con el que permitimos que cumpla al menos una. De esta forma, en nuestro ejemplo, si estamos en la red local no preguntará contraseña porque cumplirá la restricción de hosts y si estamos en casa, deberemos responder al usuario y contraseña.

Nuestro fichero de configuración tendría una pinta parecida a esta:

AuthUserFile /etc/apache2/users
AuthName Sitio Local
AuthType Basic
Satisfy Any
<LIMIT GET POST>
order deny,allow
deny from all
allow from 192.168.
require user local
</LIMIT>

Fuente: Linux System Administration Recipes, Juliet Kemp, APress, 2009

Montar un Servidor Web

Hay muchas formas de llevar a cabo la tarea de desplegar un servidor Web, incluso se puede optar por algún servicio que nos ofrezca un panel de control para administrar el contenido perdidiendo la capacidad de administrar físicamente los servicios. Como digo, existen muchas maneras de hacer esto, esta es una de ellas.

Introducción

No entramos en detalles sobre el hardware de la máquina, ya está instalado un sistema GNU/Linux Debian Squezee. Hemos contratado un servidor que incluye nombre DNS para nuestro dominio midominio.com.

El usuario

La ejecución del servidor debe ser bajo un usuario no privilegiado y sin shell válida en el sistema. En Debian, tras instalar Apache, se crea un usuario www-data para esta tarea, pero lo vamos a cambiar por otro por no mantener, en la medida de lo posible, los valores por defecto. Nuestro usuario será webuser que es bastante descriptivo de la labor que tendrá.

Creamos el grupo y el usuario y le asignamos contraseña:

# groupadd webuser
# useradd -d /home/webuser -s /bin/false -g webuser -m webuser
# passwd webuser
Introduzca la nueva contraseña de UNIX: 
Vuelva a escribir la nueva contraseña de UNIX: 
passwd: contraseña actualizada correctamente

Con esto contamos con el usuario, vamos a instalar Apache.

Instalando Apache

Vamos a instalarlo mediante la utilidad tasksel que es gráfica de consola y nos ahorra escribir.

# tasksel

De las opciones disponibles, elegimos la de Servidor Web, como vemos en la imagen, luego le damos a aceptar.

Tasksel

Tasksel

Instalará Apache y todas las dependencias.

Instalando

Instalando

Ya podemos pasar a configurar el servidor.

Configurando Apache

La configuración que trae Debian para Apache es la que me hace elegir esta distribución frente a otras como CentOS que también es conocida por estar presente en muchos servidores web de internet. El primer fichero que vamos a configurar es /etc/apache2/envvars y añadimos el usuario y grupo que hemos creado.

# vim /etc/apache2/envvars
[...]
export APACHE_RUN_USER=webuser
export APACHE_RUN_GROUP=webuser
[...]

A continuación deshabilitamos los VirtualHosts que vienen por defecto para crear el nuestro, podemos crear tantos como sean necesarios.

# a2dissite 000-default
Site default disabled.
Run '/etc/init.d/apache2 reload' to activate new configuration!

Ahora creamos nuestro sitio empezando por crear la estructura de directorios. Para ello vamos a crear siguiendo la filosofía que vi en SuSE y me gustó.

# mkdir -p /server/midominio.com 

De esta forma, contamos con el directorio /server y de él colgaran todos los servidores virtuales.

Ajustamos los permisos del directorio:

# chown -R webuser.webuser /server

Configuramos ahora las stanzas para nuestro servidor, para ello creamos un nuevo fichero /etc/apache2/sites-available/misitio.

# vim /etc/apache2/sites-available/midominio.com
NameVirtualHost *:80
<VirtualHost *:80>
        ServerName midominio.com
        ServerAlias www.midominio.com
        ServerAdmin webmaster@midminio.com
        
        DocumentRoot /server/midominio.com/
        <Directory />
                Options FollowSymLinks
                AllowOverride all
        </Directory>
        <Directory /server/midominio.com/>
                Options FollowSymLinks Multiviews Indexes
                AllowOverride all
                Order allow,deny
                allow from all
        </Directory>

        ErrorLog /var/log/apache2/error.midominio.com.log
        LogLevel warn
        CustomLog /var/log/apache2/access.midominio.com.log combined
        ServerSignature Off
</VirtualHost>

Comentamos que permitimos AllowOverride a all para que podamos customizar el sitio a través de .htaccess y no tener que tocar mucho la configuración del servidor. También personalizamos los archivos de logs por si añadimos más servidores distinguir entre ellos.

Habilitamos el sitio.

# a2ensite misitio

Ya podemos arrancar el servidor.

# apache2ctl graceful

Ahora ya podemos abrir un navegador web y entrar en el sitio, aunque no tiene contenido, cosa que resolveremos ahora.

En nuestro panel de control habilitamos que tanto midominio.com como www.midominio.com resuelvan a nuestra web, luego podemos usar un truco como este para que por defecto se utilice las uves dobles que es mejor desde el punto de vista SEO.

Añadir contenido, el servidor FTP

El usuario no tiene shell, luego no podemos iniciar una sesión en el servidor para crear los archivos html que queramos servir ni copiarlos por ssh, así que desplegamos un servidor FTP, por razones más históricas que otra cosa, uso Proftpd que tiene una configuración modular similar a la de Apache. Tiene soporte de VirtualHost pero la limitación del protocolo hace que no se pueda usar el mismo puerto en todos los servidores, esto es, cada VirtualHost que configures estará asociado a un puerto.

Pasamos a instalarlo.

# apt-get install proftpd

Lo instalamos como servidor independiente.

La configuración es esta:

# /etc/proftpd/proftpd.conf -- This is a basic ProFTPD configuration file.
# To really apply changes reload proftpd after modifications.

# Includes DSO modules
Include /etc/proftpd/modules.conf

# Set off to disable IPv6 support which is annoying on IPv4 only boxes.
UseIPv6				off
# If set on you can experience a longer connection delay in many cases.
IdentLookups			off

ServerName			"Mi servidor FTP"
ServerType			standalone
DeferWelcome			off

MultilineRFC2228		on
DefaultServer			on
ShowSymlinks			on

TimeoutNoTransfer		600
TimeoutStalled			600
TimeoutIdle			1200

DisplayLogin                    welcome.msg
DisplayChdir               	.message true
ListOptions                	"-l"

DenyFilter			\*.*/

# Use this to jail all users in their homes 
# DefaultRoot			~

# Users require a valid shell listed in /etc/shells to login.
# Use this directive to release that constrain.
# RequireValidShell		off

# Port 21 is the standard FTP port.
Port				0

# In some cases you have to specify passive ports range to by-pass
# firewall limitations. Ephemeral ports can be used for that, but
# feel free to use a more narrow range.
PassivePorts                  49152 65534

# If your host was NATted, this option is useful in order to
# allow passive tranfers to work. You have to use your public
# address and opening the passive ports used on your firewall as well.
# MasqueradeAddress		1.2.3.4

# This is useful for masquerading address with dynamic IPs:
# refresh any configured MasqueradeAddress directives every 8 hours
<IfModule mod_dynmasq.c>
# DynMasqRefresh 28800
</IfModule>

# To prevent DoS attacks, set the maximum number of child processes
# to 30.  If you need to allow more than 30 concurrent connections
# at once, simply increase this value.  Note that this ONLY works
# in standalone mode, in inetd mode you should use an inetd server
# that allows you to limit maximum number of processes per service
# (such as xinetd)
MaxInstances			30

# Set the user and group that the server normally runs at.
User				webuser
Group				webuser

# Umask 022 is a good standard umask to prevent new files and dirs
# (second parm) from being group and world writable.
Umask				022  022
# Normally, we want files to be overwriteable.
AllowOverwrite			on

# Uncomment this if you are using NIS or LDAP via NSS to retrieve passwords:
# PersistentPasswd		off

# This is required to use both PAM-based authentication and local passwords
# AuthOrder			mod_auth_pam.c* mod_auth_unix.c

# Be warned: use of this directive impacts CPU average load!
# Uncomment this if you like to see progress and transfer rate with ftpwho
# in downloads. That is not needed for uploads rates.
#
# UseSendFile			off

TransferLog /var/log/proftpd/xferlog
SystemLog   /var/log/proftpd/proftpd.log

<IfModule mod_quotatab.c>
QuotaEngine off
</IfModule>

<IfModule mod_ratio.c>
Ratios off
</IfModule>


# Delay engine reduces impact of the so-called Timing Attack described in
# http://security.lss.hr/index.php?page=details&ID=LSS-2004-10-02
# It is on by default. 
<IfModule mod_delay.c>
DelayEngine on
</IfModule>

<IfModule mod_ctrls.c>
ControlsEngine        off
ControlsMaxClients    2
ControlsLog           /var/log/proftpd/controls.log
ControlsInterval      5
ControlsSocket        /var/run/proftpd/proftpd.sock
</IfModule>

<IfModule mod_ctrls_admin.c>
AdminControlsEngine off
</IfModule>

<VirtualHost midominio.com>
        ServerName "midominio.com"
        Port 21
        DefaultRoot /server/midominio
        <Limit LOGIN>
                AllowUser webuser
                AllowGroup webuser
                DenyAll
        </Limit>
        RequireValidShell off
        AllowOverwrite on
</VirtualHost>

Hemos cambiado el puerto FTP por el 0 para usar el 21 para el VirtualHost e indicamos que el usuario (webuser) no requiere de una shell valida.

Ahora podemos usar un cliente FTP, por ejemplo Filezilla para subir ficheros al servidor.

Y ya hemos terminado, hemos creado un servidor web desde cero, aun quedan cosas por hacer pero lo básico está cubierto, os invito a seguir navegando por el blog y veáis como configurar mod_deflate para servir contenido comprimido, mod_evasive para evitar ataques DDOS, o mod_expires para almacenar contenido estático en la caché del usuario.

Alta Disponibilidad con Apache2 y Heartbeat en Debian Squeeze

A raíz de las últimas entradas en rm-rf.es y systemadmin.es quería probar el demonio de alta disponibilidad (heartbeat) sobre Debian, la entrada sobre Apache que publicó el primero me inspiró a hacer lo que contaba sobre la “distro” de la espiral.

Partimos de la misma configuración, tenemos dos servidores, cluster01 y cluster02 con las IPs 192.168.2.98 y 192.168.2.99 y una IP flotante 192.168.2.100

Configuradas ambas máquinas, instalamos los paquetes necesarios:

# apt-get install apache2

En nuestro caso, para la configuración de Apache editamos /etc/apache2/ports.conf y añadimos la IP flotante a la línea de NameVirtualHost así:

NameVirtualHost 192.168.2.100:80

Para que Apache no se levante al inicio ya que queremos que el que se encargue de esto es Heartbeat escribimos:

# update-rc.d apache2 remove

Y detenemos el servicio:

# /etc/init.d/apache2 stop

A continuación instalamos Heartbeat.

# apt-get install heartbeat

Y configuramos, estos ficheros de configuración se encuentran todos en /etc/ha.d/ y disponemos de plantillas para configurarlos en /usr/share/doc/heartbeat/. Podemos tomar ejemplo para configuraciones más específica.

Para el archivo ha.cf usamos la misma:

logfile /var/log/cluster.log
logfacility local0
warntime 5
deadtime 30
initdead 120
keepalive 2
bcast eth0
udpport 694
auto_failback on
node cluster01
node cluster02

La explicación

  • logfile y logfacility: Fichero de log y nivel.
  • warntime: Heartbeat avisará cuando un nodo falle tras 5 segundos.
  • deadtime: Hearbeat confirmará que un nodo ha caído, 30 segundos.
  • initdead: Tiempo máximo que Heartbeat esperará a que un nodo arranque, 60 segundos.
  • keepalive: Especifica cada cuanto tiempo Heartbeat enviará paquetes para comprobar la disponibilidad de los nodos, 2 segundos.
  • Las dos últimas líneas son las listas de nodos que conforman el cluster.

Para el fichero authkeys que es donde configuramos la comunicación entre los nodos del clúster, también para Debian podemos usar la original:

auth 2
2 sha1 clu$ter-4uth

Le asignamos los permisos para que sólo root tenga acceso.

# chmod 600 /etc/ha.d/authkeys

El último fichero cambia en Debian y es el haresources que queda con este aspecto:

cluster01 IPaddr2::192.168.2.100/24/eth0 apache2

Cambia la forma de escribir la IP flotante que está de una forma más completa y el script de inicio de Apache que en Debian es apache2.

Seguimos la entrada y la propagación se hace ejecutando el siguiente comando:

# /usr/share/heartbeat/ha_propagate

Levantamos el servicio.

/etc/init.d/heartbeat start

Ya está todo configurado, podemos probar a desactivar la interface de cluster01 y ver como al poco tiempo (el que hemos configurado) se levanta cluster02 para seguir sirviendo páginas.

La configuración entre CentOS y Debian es prácticamente la misma, pero tiene los suficientes detalles como para que los escriba aquí para no olvidar como se hace.

Añadiendo marcas de agua al vuelo para evitar hotlinking

A partir de una entrada que aparecía esta mañana en Tu Receta, he pasado el día intentando mejorar el sistema. Ellos proponen que cuando alguien enlace directamente a una foto de tu sitio, cambiar la url mediante mod_rewrite hacía otra imagen para que en el sitio sólo pueda mostrar una imagen con algún mensaje o similar, pero no las imágenes originales. Recordé que mi amigo Migue había pasado por eso y lo resolvió, así que empece a investigar para ver cómo podría solucionarlo.

Requerimientos:

  1. Tener activado mod_rewrite en nuestro servidor
  2. PHP5-GD para trabajar con imágenes
  3. Una imagen que será la marca de agua

Lo primero que hacemos es añadir a nuestro .htaccess las nuevas reglas para mod_rewrite que son las básicamente las mismas que en Tu Receta pero cambiamos la RewriteRule así:

RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.muspells.net/.*$      [NC]
RewriteCond %{HTTP_REFERER} !^http://www.muspells.net$      [NC]
RewriteRule ^(.*)\.(gif|jpg|png)$ image_script.php?image=$1\.$2   [R]

Cambiamos la regla de reescritura para que apunte a un script de PHP donde editaremos al vuelo la imagen para devolverla al REFERER con una marca de agua.

Hemos llamado al script image_script y lo hemos colocado en la raíz de documentos,

<?php

// En WordPress por ejemplo las imagenes se guardan en directorios,
// necesitamos el PATH completo a la imagen.
$URI = $_GET['image'];
$URI_PARSER = explode ('/', $URI);
$image = "/path/to/DocumentRoot/".$URI_PARSER[count($URI_PARSER) - 1];

switch (TRUE) {
   case stristr($image,'jpg'):
      $photoImage = ImageCreateFromJpeg("$image");
      break;
   case stristr($image,'gif'):
      $photoImage = ImageCreateFromGIF("$image");
      break;
   case stristr($image,'png'):
      $photoImage = ImageCreateFromPNG("$image");
      break;
}

ImageAlphaBlending($photoImage, true); 

// Añadimos aquí el fichero de marca de agua.
$logoImage = ImageCreateFromPNG("watermark.png"); 
$logoW = ImageSX($logoImage); 
$logoH = ImageSY($logoImage); 

// Los 1's representan el margen con el margen superior izquierdo
ImageCopy($photoImage, $logoImage, 1, 1, 0, 0, $logoW, $logoH); 

ImagePNG($photoImage); // output to browser 

ImageDestroy($photoImage); 
ImageDestroy($logoImage); 
?>

El script colocará la imagen watermark.png en la esquina superior izquierda.

Cuando accedemos a alguna imagen de nuestro sitio de forma legítima la veremos así:

gnu

GNU

Mientras que si accedemos enlazando directamente la veremos así:

gnu

Fuentes:

  1. Tu Receta: Evitar Hot-linking con .htaccess
  2. El script