• Publicidad

Monitorizar correo

¿Eres administrador de sistemas? Este foro es para todos aquellos temas relacionados con el uso de Perl para administración de sistemas.

Monitorizar correo

Notapor ElCidJJ » 2019-02-08 09:09 @422

Buenas tardes.

Hace muchísimo que no me pasaba por aquí y estoy retomando el tema de programación Perl y todo iba bien y feliz hasta que me he topado con un problemilla que no me deja avanzar y llevo tardes investigando sobre el tema y no doy con ello.

Resulta que básicamente tengo un sistema con varios servicios instalados de postfix, dovecot, ssh... corriendo en un servidor montado en Debian 9.

Me gustaría como administrador del sistema hacer un script que monitorice o guarde un aviso o algo de información de cuando a un usuario concreto del sistema recibe un correo.

He intentado al extremo manipulando los ficheros /var/mail/user y analizando el contenido del fichero si es igual o no al anterior, pero lo veo bastante bruto y seguro que hay herramientas más útiles que lo que pienso hacer.

Necesitaría algo de información y ayuda porque por más que leo más dudas me surgen.

Muchas gracias.
ElCidJJ
Perlero nuevo
Perlero nuevo
 
Mensajes: 10
Registrado: 2008-08-19 07:38 @360

Publicidad

Re: Monitorizar correo

Notapor explorer » 2019-02-08 11:23 @516

Bienvenido de nuevo de ElCidJJ.

La respuesta depende de, exactamente, qué es lo que necesitas.

Quiero decir, que no es lo mismo enterarte inmediatamente de cuando llega un correo, o al contrario, recibir el aviso con 5 minutos de retraso (de media).

En el primer caso, se podría poner un sistema basado en inotify para vigilar el archivo del buzón que quieres vigilar.

En el segundo caso, se podría poner un script que mirase los registros de actividad (logs) del correo electrónico, para ver los últimos 5 minutos y buscar por algo interesante.

Aquí te pongo un ejemplo propio. Este script analiza el log cada 5 minutos para ver las conexiones externas de Dovecot para ver si hay usuarios locales que se están conectando desde IP localizadas fuera de España. Y en ese caso, reportarlas por correo al administrador.

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use v5.14.2;
  3. use autodie;
  4. use Geo::IP;
  5. use Cache::FileCache;
  6.  
  7. # Leer puntero anterior
  8. my $archivo_puntero = '/tmp/dovecot_mainlog.txt';
  9. my $puntero = 0;
  10.  
  11. if (-f $archivo_puntero) {
  12.     open my $ARCHIVO, $archivo_puntero;
  13.     $puntero = 0+ <$ARCHIVO>;
  14.     close $ARCHIVO;
  15. }
  16.  
  17. # Analizar registro de actividad smtp
  18. my $archivo_log = '/var/log/mail.log';
  19.  
  20. $puntero = 0 if $puntero  > -s $archivo_log;
  21. exit         if $puntero == -s $archivo_log;
  22.  
  23. my $gi      = Geo::IP->open("/usr/share/GeoIP/GeoIP.dat", GEOIP_STANDARD);
  24. my $gi_city = Geo::IP->open("/usr/share/GeoIP/GeoIPCity.dat", GEOIP_STANDARD);
  25. my $gi_as   = Geo::IP->open("/usr/share/GeoIP/GeoIPASNum.dat", GEOIP_STANDARD);
  26.  
  27. my %ip_mias = ( '37.187.72.99' => 1, '127.0.0.1' => 1 );
  28. my %isp_legales = map { $_ => 1 }
  29. (
  30.     'AS15169 Google LLC',
  31.     'AS15169 Google Inc.',
  32.     'AS18705 BlackBerry Limited',
  33.     'AS12479 France Telecom Espana SA',
  34.     'AS3215 Orange S.A.',
  35.     'AS60476 MRG Hosting B.V.',
  36.     'AS14618 Amazon.com, Inc.',
  37.     'AS47764 Mail.Ru',
  38. );
  39. my %ya_visto;
  40. my $listado;
  41.  
  42. my $cache = Cache::FileCache->new({
  43.                 'namespace'             => 'Dovecot',
  44.                 'default_expires_in'    => '30 day',
  45.                 'auto_purge_on_get'     => 1,
  46. });
  47.  
  48. open my $DOVECOT,  '<', $archivo_log;
  49. seek    $DOVECOT, $puntero, 0;
  50.  
  51. while (my $linea = <$DOVECOT>) {
  52.     next if $linea !~ /^(?<time>.+?) ns3369693 dovecot: (?:imap|pop3)-login: Login: user=<(?<email>.+?@(?<dominio>.+?))>, .+? rip=(?<IP>.+?),/;
  53.     next if exists $ip_mias{ $+{IP} };
  54.     next if $ya_visto{"$+{IP}|$+{email}"}++;
  55.  
  56.     my $pais = $gi->country_code_by_addr($+{IP});
  57.     next if $pais eq 'ES';
  58.  
  59.  
  60.     # casos especiales
  61.     next if $pais eq 'GB'  and  $+{email} eq '[email protected]';
  62.     #next if $+{email} eq '[email protected]'             and $pais eq 'US';
  63.     #next if $+{email} eq '[email protected]'       and $pais eq 'PT';
  64.  
  65.     my $record = $gi_city->record_by_addr($+{IP});
  66.     my $isp    = $gi_as->name_by_addr($+{IP});
  67.     my $whois;
  68.  
  69.     if (defined $record) {
  70.         $pais = $record->country_name;
  71.     }
  72.     else {
  73.         $whois = join('' => qx(whois $+{IP}));
  74.         ($pais) = $whois =~ /country:\s+(\S+)/;
  75.     }
  76.     if (not defined $isp) {
  77.         $whois = join('' => qx(whois $+{IP})) if not $whois;
  78.         ($isp)  = $whois =~ /origin:\s+(\S+)/;
  79.     }
  80.     defined $isp or warn "ERROR al sacar registro de IP [$+{IP}]" and next;
  81.  
  82.     next if exists $isp_legales{$isp};
  83.  
  84.     my $clave = "$+{IP}|$+{email}";
  85.     my $en_cache = $cache->get($clave);
  86.     next if $en_cache;
  87.  
  88.     $listado .= sprintf "$+{time} %-15s %36s %-20s %s\n", $+{IP}, $+{email}, $pais, $isp;
  89.    
  90.     $cache->set($clave, 1);
  91. }
  92.  
  93. $puntero = tell;
  94.  
  95. close $DOVECOT;
  96.  
  97. if ($listado) {
  98.     require Mail::Send;
  99.    
  100.     my $msg = Mail::Send->new(
  101.         To      => '[email protected]',
  102.         Subject => 'Conexiones dovecot sospechosas',
  103.     );
  104.    
  105.     $msg->add('From', 'administrador <[email protected]>');
  106.     $msg->add('Content-Type', 'text/plain; charset=UTF-8');
  107.    
  108.     my $fh = $msg->open;
  109.     print $fh $listado;
  110.     $fh->close;
  111. }
  112.  
  113. open my $ARCHIVO, '>', $archivo_puntero;
  114. print   $ARCHIVO $puntero;
  115. close   $ARCHIVO;
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4

El funcionamiento de la parte interesante es el siguiente:
  • 8: uso un archivo en /tmp/ para guardar la posición de última lectura del registro
  • 11: leo el archivo, que contiene esa posición (un número entero, nada más)
  • 20: reposiciono la posición, en caso de que el registro se haya reducido (caso de renovación del registro)
  • 21: salgo si no hubo actividad (!)
  • 42: uso un objeto Cache::FileCache para recordar qué IP ya he analizado en el pasado. De esta manera, no envío informes duplicados
  • 48: abrimos el registro y
  • 49: colocamos el puntero de lectura
  • 51: para todas las líneas del registro (hasta el final del archivo)
  • 52: salto las líneas que no me interesan, y aprovecho para capturar los datos que necesito (la línea dice "salta a la siguiente línea si no coincide con esto", pero si es "esto" entonces los paréntesis de captura me atrapan lo que quiero)
  • 53: salto a la línea siguiente si es una IP local mía
  • 54: salto a la línea siguiente si es una IP asociada a un determinado buzón de correo que ya he analizado en este informe
  • el resto del script analiza la localización de la IP (país, proveedor) y genera un informe que envía por correo al root.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14485
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Monitorizar correo

Notapor ElCidJJ » 2019-02-09 19:08 @839

Muchísimas gracias por tu pronta respuesta. No es justamente lo que buscaba pero sí que me has dado una idea interesante para conseguir monitorizar el correo entrante de un usuario en concreto. Ejecuto bien tu script sin problemas, pero no tengo formas de probarlo, a menos de que me vaya al extranjero. De nuevo, muchas gracias por el aporte y seguiré investigando respecto a lo que quiero hacer.

Un saludo.
ElCidJJ
Perlero nuevo
Perlero nuevo
 
Mensajes: 10
Registrado: 2008-08-19 07:38 @360


Volver a Administración

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados