Buenas tardes
Quiero decirle cuán fácil y naturalmente puede configurar un servidor de recopilación de metadatos de tráfico de red para enrutadores Mikrotik.
Propósito: El objetivo será almacenar los registros de firewall "masticados" en una base de datos para su posterior análisis.
Medios: cualquier distribución fresca de Linux con rsyslogd v8 y superior es adecuada para la implementación, tal vez la sintaxis propuesta también funcione en v7. También necesitamos un DBMS, elegí mariadb. El crecimiento de la base de datos variará dependiendo del número de reglas registradas, porque el tamaño de la unidad es a su discreción, en mi caso, se registran 30-40 reglas, que son aproximadamente 1200 mil líneas por día. Durante el mes de uso de la base de datos, incluidos los índices, creció a 3,8 GB.
Mecánica: el enrutador envía un registro al servidor remoto a través de UDP. Usando expresiones regulares, el servidor rsyslog limpia cadenas de información innecesaria, genera un inserto SQL y lo envía al DBMS. El DBMS, utilizando un disparador antes de la inserción, realiza una limpieza y separación adicional de los campos que no se pudieron analizar en rsyslog.
Configurar RSYSLOG
Edición del archivo /etc/rsyslog.conf
Agregue las siguientes líneas allí:
module(load="ommysql") module(load="imudp") input(type="imudp" port="514")
Por lo tanto, cargamos los módulos necesarios y abrimos el puerto UDP 514.
La línea de registro de Mikrotik se ve así:
20180927155341 BLOCKSMKNETS forward: in:ether6 - LocalTORF out:VLAN55 - RT_INET, src-mac 00:15:17:31:b8:d7, proto TCP (SYN), 192.168.0.234:2457->192.168.6.14:65535, len 60
Como puede ver, será mucho más extra para el almacenamiento en la base de datos y una selección clara.
En teoría, necesito agregar tales datos:
20180927155341 ether6 VLAN5 192.168.0.234 2457 192.168.6.14 65535 00:15:17:31:b8:d7 TCP SYN forward BLOCKSMKNETS 60
No pude obtener esa línea usando solo un rsyslog. Los clientes habituales de Rsyslog utilizan POSIX ERE / BRE, por lo que no hay forma de aplicar funciones como mirar hacia adelante o hacia atrás.
Hay una herramienta que le permite depurar los clientes habituales, probarlo, tal vez pueda separar el puerto de la dirección, así como el nombre de la interfaz de in: y out:. Solo tenga en cuenta que faltan algunos de los protocolos de deporte y dport.
En general, mi salida fue la siguiente:
20180927155341 in:ether6 out:VLAN5 192.168.0.234:2457 192.168.6.14:65535 00:15:17:31:b8:d7 TCP (SYN) forward BLOCKSMKNETS 60
Existe documentación sobre cómo cocinar los clientes habituales de rsyslog.
En la forma final, el archivo de configuración para recibir el registro de Mikrotik /etc/rsyslog.d/20-remote.conf se verá así:
$template tpl_traflog,"insert into traflog.traffic (datetime, inif, outif, src, dst, smac, proto, flags, chain, logpref, len) values ('%timereported:::date-mysql%', '%msg:R,ERE,0,DFLT,0:in:[a-zA-Z]+[0-9]+|in:<[a-zA-Z]+-[a-zA-Z]+>--end%', '%msg:R,ERE,0,BLANK,0:out:[a-zA-Z]+[0-9]+|out:<[a-zA-Z]+-[a-zA-Z]+>--end%', '%msg:R,ERE,0,DFLT,0:([0-9]+\.){3}[0-9]+[:]?([0-9]+)?--end%', '%msg:R,ERE,0,DFLT,1:([0-9]+\.){3}[0-9]+[:]?([0-9]+)?--end%', '%msg:R,ERE,0,BLANK:([0-f]+:){5}[0-f]+--end%', '%msg:R,ERE,0,BLANK:\b[AX]{3,4}\b--end%', '%msg:R,ERE,0,BLANK:\([AZ]+\)|\(([AZ]+\,){1,3}[AZ]+\)--end%', '%msg:R,ERE,0,DFLT:[ax]+--end%', '%msg:F,32:2%', '%msg:R,ERE,0,DFLT:[0-9]+$--end%' )",SQL if ($fromhost-ip == '192.168.0.230') and ($syslogtag contains "firewall") then {action(type="ommysql" server="localhost" serverport="3306" db="traflog" uid="rsyslogger" pwd="rsyslogger" template="tpl_traflog") stop}
En la primera línea, la descripción de la plantilla (plantilla) es una línea de código SQL para transferirla al DBMS.
La segunda línea es la condición cuando se producirá la acción, es decir, el registro en el DBMS.
La condición se ve así: si la fuente de registro = 192.168.0.230 (
if ($fromhost-ip == '192.168.0.230')
) Y si la línea msg contiene "firewall" (y ($ syslogtag contiene "firewall"), entonces usar el módulo ommysql con parámetros de conexión (
then {action(type="ommysql" server="localhost" serverport="3306" db="traflog" uid="rsyslogger" pwd="..."
) llamamos a la plantilla tpl_traflog (
template="tpl_traflog")
), y después de eso detenemos el procesamiento posterior de la línea (
stop}
).
Es posible que en su caso algo salga mal, puede deberse a los nombres de las interfaces o prefijos de registro, tal vez algo más. Para la depuración, haremos lo siguiente, comentaremos en la segunda línea, agregaremos una nueva plantilla y dos condiciones nuevas:
$template tpl_traflog_test,"%timereported:::date-mysql% %msg:R,ERE,0,DFLT,0:in:[a-zA-Z]+[0-9]+|in:<[a-zA-Z]+-[a-zA-Z]+>--end% %msg:R,ERE,0,BLANK,0:out:[a-zA-Z]+[0-9]+|out:<[a-zA-Z]+-[a-zA-Z]+>--end% %msg:R,ERE,0,DFLT,0:([0-9]+\.){3}[0-9]+[:]?([0-9]+)?--end% %msg:R,ERE,0,DFLT,1:([0-9]+\.){3}[0-9]+[:]?([0-9]+)?--end% %msg:R,ERE,0,BLANK:([0-f]+:){5}[0-f]+--end% %msg:R,ERE,0,BLANK:\b[AX]{3,4}\b--end% %msg:R,ERE,0,BLANK:\([AZ]+\)|\(([AZ]+\,){1,3}[AZ]+\)--end% %msg:R,ERE,0,DFLT:[ax]+--end% %msg:F,32:2% %msg:R,ERE,0,DFLT:[0-9]+$--end%\n" if ($fromhost-ip == '192.168.0.230') then {action(type="omfile" file="/var/log/remote/192.168.0.230.log" )} if ($fromhost-ip == '192.168.0.230') then {action(type="omfile" file="/var/log/remote/192.168.0.230.log" template="tpl_traflog_test" ) stop}
Reinicie el registrador.
La plantilla tpl_traflog_test es similar a tpl_traflog, pero sin SQL INSERT.
La primera condición agrega la línea no procesada% msg% al archivo /var/log/remote/192.168.0.230.log, porque la plantilla no está especificada.
La segunda condición agrega la línea procesada al mismo archivo.
Por lo tanto, será más conveniente comparar.
A continuación, prepare la base de datos.
Preparamos un DB
Bajaremos la configuración de DBMS, aquí todo es estándar.
Iniciamos la consola mysql y ejecutamos el siguiente código:
La mesa está lista, el usuario sí.
Ahora agregue un disparador, hará lo que el registrador no logró separar la dirección del puerto, limpiará los nombres de las interfaces, eliminará los corchetes de la bandera:
REGEXP_REPLACE busca el segundo parámetro después del punto decimal (temporada regular) y lo reemplaza con el tercer parámetro, en nuestro caso no hay nada entre comillas, por lo tanto, simplemente elimina lo que encuentra.
Hagamos un inserto de prueba, similar a cómo lo hará el registrador:
Veamos que pasó:
select * from tarffic;
Si todo está correcto, entonces sigue adelante. Si no, busque el error.
Agregue al menos un índice. No soy un maestro en la creación de índices, pero según tengo entendido, en mysql es más correcto usar índices con diferentes campos de unión para diferentes consultas, ya que una consulta puede usar solo un índice (¿o me equivoco?). Si lo comprende, hágalo a su discreción.
A menudo tengo que hacer solicitudes con un prefijo específico, así que agregué este índice:
Listo
Ahora debe comenzar a enviar en el enrutador, agregar la configuración y la acción del servidor de registro remoto, agregar la opción de registro a una de las reglas del firewall, agregar un prefijo de no más de 24 caracteres.
En la consola Mikrotik, se ve más o menos así:
/system logging action set 3 remote=192.168.0.94 src-address=192.168.0.230 add name=remote2 remote=192.168.0.19 syslog-facility=local6 target=remote /system logging add action=remote topics=error,account,critical,event,info add action=remote2 topics=firewall /ip firewall filter ... add action=drop chain=input comment="drop ssh brute forcers" dst-port=22,8291 log=yes log-prefix=DROP_SSH_BRUTE protocol=tcp src-address-list=ssh_blacklist ...
Donde 192.168.0.230 es la dirección del enrutador, 192.168.0.19 es la dirección del servidor de registro para los registros del firewall y 192.168.0.94 es otro servidor de registro, tengo registros del sistema Mikrotik allí, no lo necesitamos ahora. Nuestra configuración es remota2.
A continuación, vea lo que cae en el archivo:
tail -f /var/log/remote/192.168.0.230.log
Las líneas del enrutador deben guardarse en el archivo, a menos que, por supuesto, su regla se active con bastante frecuencia.
Si faltan algunos campos, es decir, no se sigue la secuencia datetime, inif, outif, src, dst, smac, proto, flags, chain, logpref, len, puede intentar cambiar el parámetro en las plantillas de depuración del registrador, reemplazar BLANK con DLFT. Luego, en lugar del vacío de cualquier campo, aparecerán algunas letras, ya no recuerdo cuáles. Si esto sucede, entonces algo está mal con el horario regular y necesita arreglarlo.
Si todo salió como debería, apague las condiciones de prueba y la plantilla.
También necesita ejecutar la configuración predeterminada en /etc/rsyslog.d/ a continuación, le cambié el nombre a 50-default.conf para que los registros remotos no se viertan en el registro del sistema / var / log / message
Reinicie el registrador.
Esperemos un poco hasta que nuestra base de datos esté llena. Entonces podemos comenzar la selección.
Algunas consultas para un ejemplo:Para ver el tamaño de la base de datos y el número de filas: MariaDB [traflog]> select table_schema as "database", round(sum(data_length + index_length)/1024/1024,2) as "size Mb", TABLE_ROWS as "count rows" from information_schema.tables group by table_schema; +
Casi 4 GB han crecido en un mes, pero depende del número y las propiedades de las reglas de firewall registradas
Número de prefijos registradosEl número de prefijos registrados no es igual al número de reglas, algunas reglas funcionan con un prefijo, pero ¿cuántos prefijos totales hay? y cuántas reglas se han elaborado para ellos?
MariaDB [traflog]> select logpref,count(logpref) from traffic group by logpref order by count(logpref) desc; +
ACCEPT_TORF_INET es el líder, con este prefijo puede encontrar a todos los que ingresaron a Internet desde nuestra red local, se registran protocolos y puertos, llegará el momento y se cerrará el acceso para algunos. Hay datos de referencia para futuros trabajos sobre errores.
Smtp lanza líderVeamos quién trató hoy de llegar al servidor smtp:
MariaDB [traflog]> select src,count(dport) from traffic where logpref='SMTP_DNAT' and datetime > '2018101600000000' group by src order by count(dport) desc limit 10; +
Claramente, el nodo 191.96.249.92 es el ganador hoy. Veamos en qué reglas registradas todavía apareció:
MariaDB [traflog]> select src,dport,count(dport),logpref from traffic where src='191.96.249.92' group by logpref order by count(dport) desc; +
Este se especializa solo en smtp, ~ 1% de aciertos por tratar de adivinar la contraseña o intentar enviar algo de basura, el resto fue a la casa de baños.
La solicitud tardó 10 minutos, esto es mucho, los índices actuales no son adecuados para ello, o puede reformular la solicitud, pero ahora no hablaremos de eso.
En el futuro, está previsto atornillar la interfaz web con consultas y formularios estándar.
El vector está dado, espero que este artículo sea útil.
Gracias a todos!
ReferenciasDocumentación de RsyslogDocumentación de MySQLDocumentación de registro de MikrotikGracias a la comunidad LOR por los
consejos.UPD.1Se agregó el campo de banderas a la base de datos, ahora puede rastrear la duración de la conexión capturando SYN, FIN.
Se corrigieron algunos errores en los regulares de rsyslog, así como también en los desencadenantes de mysql.
Curiosamente, la regla predeterminada defconf: drop invalid deja todos los paquetes finales de conexiones TCP, como resultado, todos los nodos que intentan cerrar la conexión en ciencia fallan, enviando varios FIN. ¿Es esto correcto?
Agregué una regla que permite el recorrido TCP con ACK, banderas FIN.
Bajo el spoiler de SQL, un procedimiento que muestra el tiempo de las conexiones TCP en los últimos cinco minutos
connections_list () DROP PROCEDURE IF EXISTS connections_list; DELIMITER // CREATE PROCEDURE connections_list() BEGIN DECLARE logid BIGINT UNSIGNED; DECLARE done INT DEFAULT FALSE; DECLARE datefin DATETIME; DECLARE datesyn DATETIME; DECLARE conntime TIME; DECLARE connsport INT; DECLARE conndport INT; DECLARE connsrc VARCHAR(21); DECLARE conndst VARCHAR(21); DECLARE cur CURSOR FOR SELECT id,datetime,src,sport,dst,dport FROM conn_syn_fin WHERE flags='SYN'; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done=TRUE; DROP TABLE IF EXISTS conn_syn_fin; DROP TABLE IF EXISTS connless; CREATE temporary TABLE connless(datestart DATETIME,dateend DATETIME,duration TIME,src VARCHAR(21),sport INT,dst VARCHAR(21),dport INT); CREATE temporary TABLE conn_syn_fin (SELECT * from traffic WHERE datetime > now() - interval 5 minute and src in (select src from traffic where datetime > now() - interval 5 minute and logpref='TCP_FIN' and flags like '%FIN%') and (flags like '%SYN%' or flags like '%FIN%') order by id); OPEN cur; read_loop: LOOP FETCH cur INTO logid,datesyn,connsrc,connsport,conndst,conndport; IF done THEN LEAVE read_loop; END IF; set datefin=(SELECT datetime FROM conn_syn_fin WHERE id>logid and src=connsrc and sport=connsport and flags like '%FIN%' and dst=conndst and dport=conndport limit 1); set conntime=(SELECT timediff(datefin,datesyn)); INSERT INTO connless (datestart,dateend,duration,src,sport,dst,dport) value (datesyn,datefin,conntime,connsrc,connsport,conndst,conndport); END LOOP; CLOSE cur; select * from connless; END; // DELIMITER ;
Como resultado del procedimiento, se crearán dos tablas temporales.
La tabla
conn_syn_fin contiene entradas de registro con los indicadores SYN y FIN, luego se realiza una búsqueda utilizando el cursor en esta tabla.
La tabla
sinn contiene una lista de conexiones, abiertas y completadas, completadas tienen una duración de abierto, respectivamente, no.
Tenga en cuenta el tiempo de muestreo menos cinco minutos desde la hora actual. Mi pedido es lento Lentamente busca a través del cursor, procesa alrededor de 10 registros por segundo, intenta acelerarlo en todos los sentidos, pero el tiempo de ejecución es siempre el mismo.
También tenga en cuenta que este procedimiento es solo para fines de demostración. Si necesita hacer una selección para un src / sport / dst / dport específico, es mejor hacer un procedimiento separado similar a este. Si eres un maestro SQL, entonces puedes escribir mejor tu consulta.
llamar a connections_list (); MariaDB [traflog]> call connections_list(); +
Una vez completado el procedimiento, las tablas temporales
conn_syn_fin y
connless permanecen, puede verlas con más detalle si encuentra algo sospechoso o no confiable. Después de comenzar el procedimiento, se eliminan las tablas antiguas y aparecen las nuevas. Escribe si encuentras un error.