Tag Archives: Apache - Page 3

Script para contar requests por IP de un access_log de Apache

Python

Python

El otro día necesitaba saber si había alguna/s IP/s que estuvieran haciendo muchos requests a un dominio, así que escribí un muy sencillo script en Python para obtener la cantidad de peticiones por IP en un access_log de Apache. Se los dejo por si a alguien le sirve. Se me ocurre que con bash y las distintas herramientas de unix para manipular archivos y strings quizás habría podido hacer algo un poco más óptimo (aunque esto anda bastante rápido), pero me sentía más cómodo con Python.

Script

#!/usr/bin/python
import sys
from operator import itemgetter

file = open(sys.argv[1], "r")
ips = {}
line = None
while line != "":
    line = file.readline()
    ip = line.rsplit(" ")[0]
    if ip != "":
        if ips.has_key(ip):
            ips[ip] = ips[ip] + 1
        else:
            ips[ip] = 1

file.close()
list = sorted(ips.items(), key=itemgetter(1), reverse=True)
for item in list:
        print item[0].rjust(15, " "), ": ", item[1]

Cómo usarlo

Guardar el script en un archivo por ejemplo countip.py. Luego darle permisos de ejecución y correrlo.

# chmod +x countip.py
# ./countip.py /var/log/httpd/access_log

Según mis pruebas el script procesa un log de más de 14 mil líneas en aproximadamente 0,09 segundos.

Instalar mod_evasive en Apache para dificultar ataques DoS

Apache Web Server

Apache Web Server

Describiremos a continuación los pasos para la instalación y configuración de mod_evasive, un módulo para Apache desarrollado por Nuclear Elephant para prevenir ataques DoS. Antes que nada es preciso advertir que no se trata de una solución definitiva y que, incluso, bajo ataques importantes, no sirve de mucho. Pero es una buena forma de evitar ataques pequeños y mantener la salud de nuestro servidor.

¿Cómo funciona?

Básicamente lo que hace es mantener una tabla dinámica con las URIs accedidas por las distintas IPs de los clientes del Apache, y permite ejecutar algunas acciones cuando una misma IP solicita un mismo recurso (una misma URI o elementos de un mismo sitio) más de n veces en m segundos. La acción por default que ejecuta el mod_evasive es, una vez superado el máximo de requests por segundo permitidos, bloquear durante una cantidad de segundos al cliente (la IP) devolviendo un error 403 (Forbidden) a la petición HTTP. Pero lo interesante es que también permite ejecutar un comando de sistema al registrarse un intento de ataque, con lo cual se puede agregar una regla al iptables para bloquear la IP del cliente.

Instalación

La instalación es muy sencilla. Basta con descargar el tar, descomprimirlo, compilarlo con apxs y habilitarlo en el httpd.conf.

# cd /usr/src
# wget http://www.zdziarski.com/projects/mod_evasive/mod_evasive_1.10.1.tar.gz
# tar zxvf mod_evasive_1.10.1.tar.gz
# cd mod_evasive
# apxs -cia mod_evasive20.c # para Apache 1.3 el comando sería apxs -cia mod_evasive.c
# vi /etc/httpd/conf/httpd.conf # editamos la configuracion
# service httpd restart # reiniciamos el Apache

En el httpd.conf habría que agregar las siguientes líneas.

<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSPageCount 2
DOSSiteCount 50
DOSPageInterval 1
DOSSiteInterval 1
DOSBlockingPeriod 300
</IfModule>

Opciones de configuración

A continuación transcribo la descripción de las distintas opciones de configuración tomada de esta excelente guía de Xombra Team.

  • DOSHashTableSize <valor> – Establece el número de nodos a almacenar para cada proceso de peticiones de la tabla hash (contenedor asociativo de recuperación de peticiones por medio de claves que agiliza las respuestas del servidor). Si aplicamos un número alto a este parámetro obtendremos un rendimiento mayor, ya que las iteraciones necesarias para obtener un registro de la tabla son menores. Por contra, y de forma evidente, aumenta el consumo de memoria necesario para el almacenamiento de una tabla mayor. Se hace necesario incrementar este parámetro si el servidor atiende un número abultado de peticiones, aunque puede no servir de nada si la memoria de la máquina es escasa.
  • DOSPageCount <valor> – Indica el valor del umbral para el número de peticiones de una misma página (o URI) dentro del intervalo definido en DOSPageInterval. Cuando el valor del parámetro es excedido, la IP del cliente se añade a la lista de bloqueos.
  • DOSSiteCount <valor> – Cuenta cuántas peticiones de cualquier tipo puede hacer un cliente dentro del intervalo definido en DOSSiteInterval. Si se excede dicho valor, el cliente queda añadido a la lista de bloqueos.
  • DOSPageInterval <valor> – El intervalo, en segundos, para el umbral de petición de páginas.
  • DOSSiteInterval <valor> – El intervalo, en segundos, para el umbral de petición de objetos de cualquier tipo.
  • DOSBlockingPeriod <valor> – Establece el tiempo, en segundos, que un cliente queda bloqueado una vez que ha sido añadido a la lista de bloqueos. Como ya se indicó unas líneas atrás, todo cliente bloqueado recibirá una respuesta del tipo 403 (Forbidden) a cualquier petición que realice durante este periodo.
  • DOSEmailNotify <e-mail> – Un e-mail será enviado a la dirección especificada cuando una dirección IP quede bloqueada. La configuración del proceso de envío se establece en el fichero mod_evasive.c de la forma /bin/mail -t %s, siendo %s el parámetro que queda configurado en este parámetro. Será necesario cambiar el proceso si usamos un método diferente de envío de e-mails y volver a compilar el módulo con apxs (por ejemplo, la opción t ha quedado obsoleta en las últimas versiones del comando).
  • DOSSystemCommand <comando> – El comando reflejado se ejecutará cuando una dirección IP quede bloqueada. Se hace muy útil en llamadas a herramientas de filtrado o firewalls. Usaremos %s para especificar la dirección IP implicada. Por ejemplo, podemos establecer su uso con iptables de la forma siguiente:
    DOSSystemCommand “/sbin/iptables –I INPUT –p tcp –dport 80 –s %s –j DROP”
  • DOSLogDir <ruta> – Establece una ruta para el directorio temporal. Por defecto, dicha ruta queda establecida en /tmp, lo cual puede originar algunos agujeros de seguridad si el sistema resulta violado.
  • DOSWhitelist <IP> – La dirección IP indicada como valor del parámetro no será tenida en cuenta por el módulo en ningún caso. Para cada dirección IP a excluir ha de añadirse una nueva línea con el parámetro. Por ejemplo, dejaremos fuera del chequeo del módulo a un posible bot que use los siguientes rangos de direcciones:
    DOSWhitelist 66.249.65.*
    DOSWhitelist 66.249.66.*

Probarlo

¿Y cómo sé si está funcionando? mod_evasive viene con un pequeño script en perl para probar el funcionamiento del módulo. Para eso vamos al directorio de mod_evasive y ejecutamos el script test.pl:

# cd /usr/src/mod_evasive
# perl test.pl
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 200 OK
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden

Y si pusimos la directiva para bloquear la IP por iptables podemos verlo con:

# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp --  anywhere tcp dpt:http

Referencias

Apache: solucionar “(28) No space left on device”

Apache Web Server

Apache Web Server

Recién me topé con un error medio raro, que jamás me había sucedido y afortunadamente encontré rápido la solución en internet. Por eso me pareció bueno compartirlo, para que si se encuentran con este error sepan cómo corregirlo y para que quede la solución online por si a otra persona le sucede.

De repente me avisan que está caído el Apache de uno de los servers y que al reiniciarlo no levanta. Entro al servidor y veo que efectivamente falla al iniciar. Reviso el error log y veo lo siguiente:

[Tue Jan 13 14:34:03 2009] [notice] mod_python: Creating 8 session mutexes based on 450 max processes and 0 max threads.
[Tue Jan 13 14:34:03 2009] [notice] mod_python: using mutex_directory /tmp
[Tue Jan 13 14:34:03 2009] [error] (28)No space left on device: mod_python: Failed to create global mutex 0 of 8 (/tmp/mpmtx297990).
Configuration Failed

No me parecía que pudiera haber un error con mod_python porque siempre funcionó. De todas formas, lo deshabilité, probé de nuevo y me daba el mismo error en otra parte:

[Tue Jan 13 14:31:05 2009] [emerg] (28)No space left on device: Couldn't create accept lock (/var/logs/accept.lock.29427) (5)

Evidentemente el problema iba por otro lado, y lo primero que pensé era que me estaba quedando sin espacio en el disco. Revisé eso y tampoco. El consumo del disco era muy bajo (25%). Entonces recurrí a Google y encontré la solución en eHow.

Al parecer es un problema común, que se solucione revisando los arrays de semáforos que está usando el Apache y removiéndolos.

# Revisar los semáforos de Apache
ipcs -s | grep apache
# Remover todos los semáforos
for i in `ipcs -s | grep apache | awk '{print $2}'` ; do ipcrm -s $i; done
# Iniciar Apache
service httpd start

Fuente: http://www.ehow.com/how_4397601_error-no-space-left-device.html

Instalar mod_python para Apache 2.2

Apache Web Server

Revisando mis favoritos en busca de alguna guía interesante para publicar, encontré estos pequeños pasos para instalar mod_python para Apache 2.2. La guía original dice que es para instalar mod_python en servidores con Directadmin, pero lo cierto es que no tiene nada específico para este panel de control. La misma guía también advierte que estas instrucciones solamente sirven para Apache 2.2. La verdad es que yo lo probé únicamente para esa versión y no he intentado averiguar cómo hacerlo sobre otra versión.

cd /usr/local/src
wget http://www.apache.org/dist/httpd/modpython/mod_python-3.3.1.tgz
tar -zxvf mod_python-3.3.1.tgz
cd mod_python-3.3.1
./configure
make
make install
mod_python

mod_python

Luego hay que editar el httpd.conf, agregando la siguiente línea para cargar el módulo. Una buena práctica sería colocarlo a continuación de donde se carga el módulo de PHP.

LoadModule python_module /usr/lib/apache/mod_python.so

Para probar el funcionamiento del módulo debemos hacer lo siguiente. En primer lugar, vamos a necesitar definir un handler de python para los requests en un .htaccess. Allí escribimos algo como lo siguiente:

AddHandler mod_python .py
PythonHandler mod_python.publisher
PythonOption session DbmSession
PythonOption session_dbm /home/user/domains/test.com/session.dbm
PythonOption ApplicationPath /
PythonDebug On ## Turn this off when done with debugging

DirectoryIndex index.py

Por supuesto, habrá que ajustar los datos a lo que sea necesario.
Luego, creamos el índice de nuestro sitio, en este caso en /home/user/domains/test.com/public_html/index.py con el siguiente código:

## index.py
from mod_python import apache

def index(req):
req.content_type = 'text/plain'
req.write('Hello from mod_python\n')
return apache.OK

Luego accedemos a http://test.com/ y si vemos “Hello from mod_python”, es que hemos instalado correctamente mod_python.

Fuentes:

Prevenir hotlinking con .htaccess en Apache

El hotlinking (también conocido como inline linking y por otros varios sinónimos) es el uso de una imagen alojada en un sitio A para ser mostrada en un sitio B. Por ejemplo, yo podría en este blog incluir una imagen del sitio de Dataweb Hosting, pero en vez de descargarla y subirla a mi servidor, poner directamente el link a la imagen en el servidor de Dataweb, por ejemplo:

<img src="http://www.datawebhosting.com.ar/img/logo_dataweb_hosting.jpg">

Entonces, cuando alguien entre al blog, el browser automáticametne va a ir a buscar esa imagen al servidor de Dataweb. Esto es algo absolutamente “legal” y es de gran ayuda en muchos casos. De hecho, esto mismo se puede hacer con cualquier archivo que uno incluya en un sitio web (una imagen, un video, un script de Javascript, una hoja de estilos CSS, etc.). Esto nos permite, por ejemplo, incluir en nuestros sitios videos de YouTube, los scripts de publicidad de Google AdSense, etc.

Apache Web Server

Apache Web Server

Por supuesto, al incluir un recurso de esta forma, se genera tráfico en el servidor de orígen. En algunos casos puede ser un problema, porque si yo tengo alojado mi sitio en un servidor chico y una persona publica una imagen de mi servidor en un sitio muy concurrido, mi tráfico se puede incrementar a niveles que quizás no sea capaz de manejar. En ese momento el hotlinking resulta nocivo.

Afortunadamente, Apache tiene muchos features interesantes y jugando un poco con mod_rewrite podemos evitar el hotlinking. Para ello debemos tener en cuenta que los requests de estas imágenes van a llevar siempre un HTTP Referer que va a ser igual a la URL donde éstas están incluidas. En el ejemplo anterior, al servidor de Dataweb le llegaría un request del archivo logo_dataweb_hosting.jpg con un referer que podría ser “http://www.tail-f.com.ar/”. Entonces, en nuestro archivo .htaccess hacemos lo siguiente:

RewriteEngine On
RewriteCond %{HTTP_REFERER} !^http://(.+\.)?mysite\.com/ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule .*\.(jpe?g|gif|bmp|png)$ /images/nohotlink.jpg [L]

En este caso, cuando venga un request que tenga como referer una URL de un dominio diferente al mío (específicamente diferente de mi dominio principal y cualquier subdominio), que sea de un archivo con extensión jpeg, jpg, gif, bmp o png, se devolverá la imágen “nohotlink.jpg”.

Otra opción es bloquear el hotlinking por parte de dominios específicos. Por ejemplo:

RewriteEngine On
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?myspace\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?blogspot\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?livejournal\.com/ [NC]
RewriteRule .*\.(jpe?g|gif|bmp|png)$ /images/nohotlink.jpg [L]

En este caso, similar al anterior, lo que se bloquean son todos los requests que vengan de myspace.com, blogspot.com y livejournal.com.

Para cerrar debo decir que no estoy muy de acuerdo con estos métodos por una serie de razones. En primer lugar, por una cuestión de principios, siempre prefiero compartir mis imágenes (así como espero que los demás las compartan conmigo) a prohibir su uso. En segundo lugar, y más importante, este método dista mucho de ser ideal. De hecho, aunque usándolo el hotlinking resulte inútil para la persona del otro sitio que quiera usar nuestras imágenes, no dejamos de transferir la imagen nohotlink.jpg. Con lo cual, aunque se pudiera reducir el tráfico (suponemos que nohotlink.jpg sería una imagen muy liviana), no se reduciría la cantidad de requests que de por sí pueden resultar muy pesados para el servidor.

Una opción más interesante, porque evita transferir una imágen, es devolver un código de error HTTP, por ejemplo 403 (Forbidden). Para ello, en el código anterior reemplazaríamos:

RewriteRule .*\.(jpe?g|gif|bmp|png)$ /images/nohotlink.jpg [L]

por

RewriteRule .*\.(jpe?g|gif|bmp|png)$ - [F]

Sin embargo, me pareció un ejemplo interesante para publicar porque da más ideas sobre cómo usar mod_rewrite y puede aportar en la solución creativa de problemas similares.

Fuente: altlab.com