Ayuda con expresiones regulares

Publicado en 'GNU/Linux' por leonmorlando, 14 Oct 2015.





  1. leonmorlando

    leonmorlando Miembro de bronce

    Registro:
    21 Ene 2014
    Mensajes:
    1,578
    Likes:
    428




    Compatriotas Linuxeros, acudo a ustedes con poco de vergüenza porque no sé mucho sobre expresiones regulares, y esperaba a que me pudieran ayudar:
    Estuve tratando de hacer que mi servidor web bloquee a clientes (en mi caso, robots maliciosos) haciendo "crawling" y exploración/interrogación del mismo. En este caso, nginx me da la información mínima e indispensable, respondiendo con un HTTP 400 (bad request) a estos robots, pero necesito convertir esta información en expresiones regulares para poder pasarselas al software que se encarga de banear a estos clientes.
    Ejemplo: En mi access.log tengo:
    Código:
    198.20.69.74 - - [09/Oct/2015:06:11:40 -0400] "" 400 0 "-" "-"
    198.20.69.74 - - [09/Oct/2015:06:11:40 -0400] "" 400 0 "-" "-"
    198.20.69.74 - - [09/Oct/2015:06:11:41 -0400] "" 400 0 "-" "-"
    198.20.69.74 - - [09/Oct/2015:06:11:44 -0400] "quit" 400 166 "-" "-"
    198.20.69.74 - - [09/Oct/2015:06:11:45 -0400] "" 400 0 "-" "-"
    24.254.129.157 - - [09/Oct/2015:13:11:41 -0400] "GET /tmUnblock.cgi HTTP/1.1" 400 166 "-" "-"
    24.254.129.157 - - [09/Oct/2015:13:11:44 -0400] "GET / HTTP/1.1" 400 166 "-" "-"
    92.222.220.41 - - [09/Oct/2015:20:17:08 -0400] "GET /w00tw00t.at.ISC.SANS.DFind:) HTTP/1.1" 400 166 "-" "-"
    Lo que quisiera es crear un RegEx que funcione cada vez que se detecte un HTTP 400 (en mi ejemplo, los logs ya muestran esta información en el formato "HTTP/1.1" 400) pero no tengo idea de cómo generarlo.
    Agradeceré mucho si me pudieran dar algún ejemplo y cómo funciona o se forma el RegEx, para poder aprender y hacerlo por mi mismo en adelante. Gracias de antemano.
     


  2. gnox

    gnox Miembro maestro

    Registro:
    3 Ene 2013
    Mensajes:
    794
    Likes:
    252
    Tienes que leerte todo un libro para llegar a entender completamente regex, e igualmente a la semana se te olvida como funcionaba :risota:, pero lo básico para parsear un archivo es :

    1. ubicar exactamente lo que quieres extraer y su contexto , en este caso solo el texto "400" , pero si te fijas tambien tienes -0400 en cada linea, entonces tu cadena de búsqueda debe ser " 400 " con espacios al costado.

    2. no sobrecomplicarse, seguro que pensabas tambien hacer un regex de la IP en la misma linea capturarla como grupo y imprimir el grupo encontrado, buscando en google es algo como (?:^[0-9]{1,3}\. blabla /1 y mas blabla si quieres que la ip sea valida .. , pero si sabes que el log esta estructurado tratalo como un csv delimitido por espacio y usa algo que te facilite cortarlo.

    Código:
    $cat log.txt | sed -n '/ 400 /p' | cut -d " " -f1
    
    o tambien
    Código:
    $cat log.txt | awk -F " " '/ 400 / {print $1}'
    
    Si estas baneando ip's checa el programa fail2ban tiene varios ejemplos de como parsear distintos logs de servicios (apache, nginx, ssh, etc).
     
    A marcoponce le gustó este mensaje.
  3. leonmorlando

    leonmorlando Miembro de bronce

    Registro:
    21 Ene 2014
    Mensajes:
    1,578
    Likes:
    428
    Es correcto, estoy tratando de hacer regexes para Fail2ban. Intenté con un tutorial extenso pero bastante simple de entender, pero el problema es que eran regexes para perl y no python y Fai2ban trabaja en python. :plop:

    En fin, se me ocurrió seguir otro ejemplo en la internet, y terminé con:
    Código:
    failregex = ^<HOST>[^"]+"[^"]+" +40[1-5]
    Pero me salen puros "missed" al hacer el test con fail2ban-regex.
     
  4. gnox

    gnox Miembro maestro

    Registro:
    3 Ene 2013
    Mensajes:
    794
    Likes:
    252
    Y si usas el filtro que ya viene por defecto para bad robots del fail2ban ? : nginx-badbots
     
  5. leonmorlando

    leonmorlando Miembro de bronce

    Registro:
    21 Ene 2014
    Mensajes:
    1,578
    Likes:
    428
    No tengo un nginx-badbots.conf en filter.d. Tengo apache-badbots.conf pero al activarlo me da error, incluso cuando le cambio el log en jail.local a /var/log/nginx/access.log
    No estoy seguro de por qué no tengo un nginx-badbots.conf, pero no creo que sea error especifico de Debian.
     
  6. gnox

    gnox Miembro maestro

    Registro:
    3 Ene 2013
    Mensajes:
    794
    Likes:
    252
    Tienes razón me confundí con el nombre de sección :
    Código:
    [nginx-badbots]
    enabled = true
    filter = apache-badbots
    action = iptables-multiport[name=BadBots, port="http,https"]
    logpath = /var/log/nginx*/*access*.log
    bantime = 86400 # 1 day
    maxretry = 1
    
    que error te bota? .
     
  7. leonmorlando

    leonmorlando Miembro de bronce

    Registro:
    21 Ene 2014
    Mensajes:
    1,578
    Likes:
    428
    Errores que no me tomé el tiempo de documentar o buscar, por que eran errores de regex.
    Ahora, si me pasaras el tuyo para probar ¡estaría muy agradecido! :giggle:
     
  8. gnox

    gnox Miembro maestro

    Registro:
    3 Ene 2013
    Mensajes:
    794
    Likes:
    252
    Pues es el mismo que esta en el fuente del paquete :
    https://github.com/fail2ban/fail2ban/blob/master/config/filter.d/apache-badbots.conf

    o quieres banear algo mas ? , tu 40[1-5] banearia tambien a cualquiera que le de un 404 pagina no encontrada que es un falso - positivo ya que realmente es responsabilidad tuya que no exista el recurso.
     
  9. leonmorlando

    leonmorlando Miembro de bronce

    Registro:
    21 Ene 2014
    Mensajes:
    1,578
    Likes:
    428
    Cierto. No me quise complicar y me fui por lo más fácil, es todo. Ya que ahora estos IPs están baneados por un par de días se me ocurrió mejorar el regex para no penalizar a los 404, y pues terminé por pedir ayuda.
    Intenté fail2ban-regex con el archivo que enviaste, y este fue el resultado:
    Código:
    orlando@debianvps:~$ fail2ban-regex /var/log/nginx/access.log.1 /etc/fail2ban/filter.d/apache-badbots.conf
    
    Running tests
    =============
    
    Use   failregex file : /etc/fail2ban/filter.d/apache-badbots.conf
    Use      single line : /var/log/nginx/access.log.1
    
    
    Results
    =======
    
    Failregex: 0 total
    
    Ignoreregex: 0 total
    
    Date template hits:
    
    Lines: 1 lines, 0 ignored, 0 matched, 1 missed
    |- Missed line(s):
    |  /var/log/nginx/access.log.1
    `-
    orlando@debianvps:~$
    Está como "access.log.1" por el logrotate. "Access.log" me da el mismo resultado.
    Buscaré como agregar más definiciones de badbots en este archivo para bloquear scripts. (el w00tw00t es el más prominente, seguido de scripts que generan "bad requests")
     
  10. gnox

    gnox Miembro maestro

    Registro:
    3 Ene 2013
    Mensajes:
    794
    Likes:
    252
    leyendo el codigo los regular expression son lo mismo lo unico que hace el programa de python fail2ban es reemplazar(macro-sustitucion) cadenas comunes %(algo) = variable.

    Match de los que tengan cadena GET/POST...HTTP y error 400
    Código:
    [Definition]
    hay400=400
    failregex = ^<HOST> -.*"(GET|POST).*HTTP.*(?:%(hay400)s).*$
    ignoreregex =
    
    Match de todos los 400
    Código:
    hay400=400
    failregex = ^<HOST> -.* (?:%(hay400)s) .*$
    
    notese los espacios en blanco, despues de ".*" y antes de ".*".
     
  11. leonmorlando

    leonmorlando Miembro de bronce

    Registro:
    21 Ene 2014
    Mensajes:
    1,578
    Likes:
    428
    Todo correcto. No hay errores y está bastante simple de entender.
    Al probarlo me continúa mostrando solo una linea y un miss como con los demás filtros. ¿Es normal?
     
  12. gnox

    gnox Miembro maestro

    Registro:
    3 Ene 2013
    Mensajes:
    794
    Likes:
    252
    Cual de los 2? ..

    Del primero con tus datos de ejemplo :
    Código:
    root@f6ff64ddd1ac:/# fail2ban-regex log.txt /etc/fail2ban/filter.d/nginx-400.conf
    
    Running tests
    =============
    
    Use  failregex file : /etc/fail2ban/filter.d/nginx-400.conf
    Use  log file : log.txt
    
    
    Results
    =======
    
    Failregex: 3 total
    |-  #) [# of hits] regular expression
    |  1) [3] ^<HOST> -.*"(GET|POST).*HTTP.*(?:400).*$
    `-
    
    Ignoreregex: 0 total
    
    Date template hits:
    |- [# of hits] date format
    |  [8] Day/MONTH/Year:Hour:Minute:Second
    `-
    
    Lines: 8 lines, 0 ignored, 3 matched, 5 missed
    |- Missed line(s):
    |  198.20.69.74 - - [09/Oct/2015:06:11:40 -0400] "" 400 0 "-" "-"
    |  198.20.69.74 - - [09/Oct/2015:06:11:40 -0400] "" 400 0 "-" "-"
    |  198.20.69.74 - - [09/Oct/2015:06:11:41 -0400] "" 400 0 "-" "-"
    |  198.20.69.74 - - [09/Oct/2015:06:11:44 -0400] "quit" 400 166 "-" "-"
    |  198.20.69.74 - - [09/Oct/2015:06:11:45 -0400] "" 400 0 "-" "-"
    `-
    
    Del segundo :
    Código:
    root@f6ff64ddd1ac:/# fail2ban-regex log.txt /etc/fail2ban/filter.d/nginx-400.conf
    
    Running tests
    =============
    
    Use  failregex file : /etc/fail2ban/filter.d/nginx-400.conf
    Use  log file : log.txt
    
    
    Results
    =======
    
    Failregex: 8 total
    |-  #) [# of hits] regular expression
    |  1) [8] ^<HOST> -.* (?:400) .*$
    `-
    
    Ignoreregex: 0 total
    
    Date template hits:
    |- [# of hits] date format
    |  [8] Day/MONTH/Year:Hour:Minute:Second
    `-
    Lines: 8 lines, 0 ignored, 8 matched, 0 missed
    
    Solo el woot
    Código:
    woot=w00tw00t\.at\.ISC\.SANS\.DFind
    failregex = ^<HOST> -.*(?:%(woot)s).*$
    
    Código:
    root@f6ff64ddd1ac:/# fail2ban-regex log.txt /etc/fail2ban/filter.d/nginx-400.conf
    
    Running tests
    =============
    
    Use  failregex file : /etc/fail2ban/filter.d/nginx-400.conf
    Use  log file : log.txt
    
    
    Results
    =======
    
    Failregex: 1 total
    |-  #) [# of hits] regular expression
    |  1) [1] ^<HOST> -.*(?:w00tw00t\.at\.ISC\.SANS\.DFind).*$
    `-
    
    Ignoreregex: 0 total
    
    Date template hits:
    |- [# of hits] date format
    |  [8] Day/MONTH/Year:Hour:Minute:Second
    `-
    
    Lines: 8 lines, 0 ignored, 1 matched, 7 missed
    |- Missed line(s):
    |  198.20.69.74 - - [09/Oct/2015:06:11:40 -0400] "" 400 0 "-" "-"
    |  198.20.69.74 - - [09/Oct/2015:06:11:40 -0400] "" 400 0 "-" "-"
    |  198.20.69.74 - - [09/Oct/2015:06:11:41 -0400] "" 400 0 "-" "-"
    |  198.20.69.74 - - [09/Oct/2015:06:11:44 -0400] "quit" 400 166 "-" "-"
    |  198.20.69.74 - - [09/Oct/2015:06:11:45 -0400] "" 400 0 "-" "-"
    |  24.254.129.157 - - [09/Oct/2015:13:11:41 -0400] "GET /tmUnblock.cgi HTTP/1.1" 400 166 "-" "-"
    |  24.254.129.157 - - [09/Oct/2015:13:11:44 -0400] "GET / HTTP/1.1" 400 166 "-" "-"
    `-
    
    
     
    A leonmorlando le gustó este mensaje.
  13. leonmorlando

    leonmorlando Miembro de bronce

    Registro:
    21 Ene 2014
    Mensajes:
    1,578
    Likes:
    428
    Olvidalo, no me hagas caso. Estaba haciendo fail2ban-regex sin elevar.
    Gracias miles por la ayuda, volveré a leer el manual de regex por puntos hasta que algo me quede.
     
  14. leonmorlando

    leonmorlando Miembro de bronce

    Registro:
    21 Ene 2014
    Mensajes:
    1,578
    Likes:
    428
    Solo para agregar: compilé naxsi para nginx, como para agregar una capa más a la protección web, y me va muy bien hasta ahora. Cualquier comentario es de gran ayuda, soy 90% nulo en el tema de servidores web y estoy aprendiendo.