Openobserve - Monitorización red

Openobserve - Monitorización red

Table of Contents

Configuracion en Mikrotik

Para que el Mikrotik mida y envíe los datos del tráfico (volumen,IPs, Protocolos…) se habilita Traffic Flow en todos los puertos y se configura el target para redirigir esta información al servidor

/ip traffic-flow set enabled=yes interfaces=all target-version=9

/ip traffic-flow target
add dst-address=xxx.xxx.xx.xxx port=X v9-template-refresh=20 v9-template-timeout=30m

Configuración en servidor

En la parte del servidor para gestionar el envío de la información hacia Otelcolector/Openobserve enviándolo mediante HTTP con la API:

[Unit]
Description=GoFlow2 Collector para MikroTik
After=network.target

[Service]
Type=simple
User=root
# Parámetros calcados de tu ejecución manual exitosa
ExecStart=/usr/local/bin/goflow2 \
  -transport=http \
  -transport.http.destination=http://xxx.xxx.xxx.xxx:xxx/api/default/netflow1/_json \
  -transport.http.batchSize=10 \
  -transport.http.auth.header=Authorization \
  -transport.http.auth.credentials="Basic aquipongoAPIKey"
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

De esta el servicio Openobserve ya está recibiendo la información del tráfico de red y se reciben los logs: alt text
En el Anexo I Dejo un ejemplo de log completo.

Con esta información ya se puede consultar información, crear dashboards y analizar flujos.

Dashboards

Gráfica de las direcciones a las que más consultas realizan y los paises dedse los que más conexiones se reciben. alt text

Puertos con más conexiones solicitadas: alt text

Otras de las gráficas creadas es el volumen de tráfico en general y las IPs que más consumen de la red. alt text Información de las direcciones que más tráfico y más datos generan así como distribución de los protocolos. alt text

Integración de mapas en OpenObserve

Para enriquecer aun más los datos se puede añadir información geográfica a los logs.

El proceso de instalación que tuve que seguir fue registrarme en MAXMIND, lo cual me facilitó una LICENSE_KEY que integré en mi configuración de OpenObserve del Docker-compose.yml:

  openobserve:
    image: openobserve/openobserve:latest
    container_name: openobserve
    restart: unless-stopped
    ports:
      - "5080:5080"  # <--- Esto mapea el puerto del host al contenedor
    environment:
      ZO_DATA_DIR: /data
      ZO_ROOT_USER_EMAIL: xxxxxxxxxx@xxxxx.xx
      ZO_ROOT_USER_PASSWORD: ************************
      ZO_GEOIP_DB_PATH: /var/lib/GeoIP/GeoLite2-City.mmdb
      ZO_MAXMIND_LICENSE_KEY: ********xxxxxxxxxxx********
    volumes:
      - ./openobserve/data:/data
      - /var/lib/GeoIP:/var/lib/GeoIP:ro
    networks:
      - proxy

Simplemente con la LicenseKey de MaxMind, Openobserve soporta la integración de este servicio, conecta con sus servidores y mantendrá los mapas actualizados de forma automática respecto a la BBDD que le indiqué en el path de la variable y que también descargará la primera vez de forma automática.

La segunda parte para que esto se haga efectivo será enriquecer ese log de tráfico de red con la información adicional de esta base de datos geográfica.
Para ello hay que crear un pipeline mediante una función. alt text

Aqui se ve la función creada. Esto fue una tarea un poco tediosa para dar con el código exacto por lo que en Anexo II dejaré el código por si alguien quiere ayudarse de esta. alt text

Ahora que ya está la función que añadirá al log la información geográfica, falta integrarlo en el flujo y esto se hace en el apartado pipelines donde se crea de forma gráfica el flujo. alt text

Hay dos tipos de maps a mostrar:

  • En base al nombre del país/ciudad alt text

  • En base a la latitud y longitud: alt text

Logs Mikrotik

También tengo configurado para recibir información de los logs de Mikrotik del sistema.

En este caso con el servicio fluentibt levantado con docker y redireccionando estas salidas hacia el puerto adecuado de mi docker, y de este, al fichero de configuracion del colector otel-config.yml

La configuracion de Mikrotiks consta de dos partes:

  • Primero crear la acción (enviar los logs en remoto)
[xx@xx] > /system/ logging/ action/print 
Flags: * - DEFAULT
[...] 
4    name="EnviarOpenobserveInfo" target=remote remote=xxx.xxx.xxx.xxx
     remote-port=xxx src-address=0.0.0.0 remote-log-format=syslog
     remote-protocol=udp syslog-time-format=iso8601 syslog-facility=daemon
     syslog-severity=info add-topics-string=no vrf=main
 
5    name="EnviarOpenobserveError" target=remote remote=xxx.xxx.xxx.xxx
     remote-port=xxx src-address=0.0.0.0 remote-log-format=syslog
     remote-protocol=udp syslog-time-format=iso8601 syslog-facility=daemon
     syslog-severity=error add-topics-string=no vrf=main
 
6    name="EnviarOpenobserveWarning" target=remote remote=xxx.xxx.xxx.xxx
     remote-port=xxx src-address=0.0.0.0 remote-log-format=syslog
     remote-protocol=udp syslog-time-format=iso8601 syslog-facility=daemon
     syslog-severity=warning add-topics-string=no vrf=main
 
7    name="EnviarOpenobserveCritical" target=remote remote=xxx.xxx.xxx.xxx
     remote-port=xxx src-address=0.0.0.0 remote-log-format=syslog
     remote-protocol=udp syslog-time-format=iso8601 syslog-facility=daemon
     syslog-severity=critical add-topics-string=no vrf=main
  • La segunda decir qué logs van a hacer esa acción:
[xx@xx] > /system/ logging/ print 

#    TOPICS    ACTION                     PREFIX  
0  * info      memory                             
1  * error     memory                             
2  * warning   memory                             
3  * critical  echo                               
4    info      EnviarOpenobserveInfo      Mikrotik
5    error     EnviarOpenobserveError     Mikrotik
6    critical  EnviarOpenobserveCritical  Mikrotik
7    warning   EnviarOpenobserveWarning   Mikrotik

Una vez que los recibe fluentbit en el servidor, este tiene la configuración para parsearlos y mandarlos vía http/API a Openobserve. El fichero que muestro a continación es la configuración del servicio y se guarda en un volumen persistente de docker para que cada vez que se tenga que levantar “machaque” el que lleve por defecto el docker de fluentbit:

[SERVICE]
    Flush        1
    Log_Level    info
    Parsers_File /fluent-bit/etc/parsers.conf

[INPUT]
    Name   syslog
    Mode   udp
    Listen 0.0.0.0
    Port   xxxx
    # Aquí le digo qué formato usar para entender el texto del MikroTik
    Parser syslog-rfc3164
    Tag    mikrotik.logs

[OUTPUT]
    Name  http
    Match mikrotik.logs
    Host  openobserve
    Port  xxx
    URI   /api/default/mikrotik_syslog/_json
    Header Authorization Basic xxxxxxxxxxxxxxxxxxxx=
    Format json
    json_date_key _timestamp
    json_date_format iso8601

En este punto aun tengo pendiente de crear los dashboard, así que queda pendiente para futuras entradas o actualizaciones.

Y con esto termino la entrada de hoy, si has llegado hasta aquí espero que lo hayas disfrutado y gracias por tu tiempo.

ANEXO I “log generado por Mikrotik”

{
_timestamp: 1787798786954424,
bgp_next_hop: ,
bytes: 651,
dst_addr: xxx.xxx.xxx.xxx,
dst_as: 0,
dst_mac: xx:xx:xx:xx:xx:xx,
dst_net: 0.0.0.0/0,
dst_port: 52792,
dst_vlan: 0,
etype: IPv4,
forwarding_status: 0,
fragment_id: 0,
fragment_offset: 0,
geo_src_city_name: Madrid,
geo_src_country_code: ES,
geo_src_country_name: Spain,
geo_src_latitude: 40.4153,
geo_src_longitude: -3.694,
icmp_code: 0,
icmp_type: 0,
in_if: 4,
ip_flags: 0,
ip_tos: 0,
ip_ttl: 0,
ipv6_flow_label: 0,
next_hop: 0.0.0.0,
next_hop_as: 0,
observation_domain_id: 0,
observation_point_id: 0,
out_if: 9,
packets: 7,
proto: TCP,
sampler_address: xxx.xxx.xxx.xxx,
sampling_rate: 0,
sequence_num: 242500,
src_addr: xx.xx.xx.xx,
src_as: 0,
src_mac: 04:f4:1c:e9:8c:dc,
src_net: 0.0.0.0/0,
src_port: xx,
src_vlan: 0,
tcp_flags: 24,
time_flow_end_ns: 1787783124000000000,
time_flow_start_ns: 1787722824000000000,
time_received_ns: 1787798784864848400,
type: NETFLOW_V9,
vlan_id: 0
}

ANEXO II “Código de la función de integración de mapas”

# Enriquecer IP de Origen (src_addr)
if exists(.src_addr) {
    geo_src, err_src = get_enrichment_table_record("maxmind_city", { "ip": .src_addr })
    if err_src == null {
        .geo_src_country_code = geo_src.country_code
        .geo_src_country_name = geo_src.country_name
        .geo_src_city_name = geo_src.city_name
        
        # Convertir explícitamente a Float para que el Map Widget los detecte
        if exists(geo_src.latitude) {
            .geo_src_latitude = to_float!(geo_src.latitude)
        }
        if exists(geo_src.longitude) {
            .geo_src_longitude = to_float!(geo_src.longitude)
        }
    }
}

# Enriquecer IP de Destino (dst_addr)
if exists(.dst_addr) {
    geo_dst, err_dst = get_enrichment_table_record("maxmind_city", { "ip": .dst_addr })
    if err_dst == null {
        .geo_dst_country_code = geo_dst.country_code
        .geo_dst_country_name = geo_dst.country_name
        .geo_dst_city_name = geo_dst.city_name
        
        # Convertir explícitamente a Float para que el Map Widget los detecte
        if exists(geo_dst.latitude) {
            .geo_dst_latitude = to_float!(geo_dst.latitude)
        }
        if exists(geo_dst.longitude) {
            .geo_dst_longitude = to_float!(geo_dst.longitude)
        }
    }
} 
 .
Share :