
Openobserve - Monitorización red
- Monitorización , Openobserve
- August 12, 2026
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:

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.

Puertos con más conexiones solicitadas:

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

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.

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.

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.

Hay dos tipos de maps a mostrar:
En base al nombre del país/ciudad

En base a la latitud y longitud:

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)
}
}
}
.