Recopilant els LOGs d'Ubiquiti UniFi a Elasticsearch i visualitzant-los a Grafana

I seguim amb més coses rares… avui de primer una de recopilar Logs a l'entorn d'Ubiquiti Unifi, dels nostres APs, Switches… de segon parseiem, tractem els Logs amb Logstash i de postres l'emmagatzemem a Elasticsearch, i ja la guinda del pastís serà visualitzar-lo amb Grafana. Tot això per controlar en temps real què succeeix en la nostra infraestructura de comunicacions, qui intenta accedir al Wisfis…

Bueno pues lo dicho, si tenemos unos Ubiquiti por ahí prestando algún servicio y queremos conocer qué está pasando ahí, quién comunica con quiéna mí me dio más la curiosidad por la parte WiFi, ver intentos de conexiones, salud de los clientescada uno visualizará lo que más le interese. Así que empezaremos indicando a la consola de UniFi que almacene los logs en un syslog, a nuestro Logstash le mandará los logs y os dejaré un fichero de ejemplo para filtrar y poder separar en campos interesantes los datos recopilados, ese mismo fichero de configuración indicará que se almacene en un índice de Elasticsearch la información ya separada en distintos campos. Y acabaremos con Kibana o Grafana visualizando en un Dashboard la info que nos interese y en el formato que nos interese.

Primero obviamente tenemos que tener la parte de Elastic Stack instalada, el que ve sent Logstash, Elasticsearch y Kibana; Luego ya habilitamos el remote syslog desde la consola de UniFi Controller > “Settings” > “System Settings” > “Controller Configuration” > “Remote Logging”, y con habilitar únicamente la parte de Syslog nos vale, sin Netconsole. Indicamos la dirección IP de nuestro Logstash y un puerto aleatorio no usado donde mandará los Logs.

input {
        udp {
                type => "UniFi"
                port => "1601"
                tags => ["UniFi"]
        }
}

filter {

        if [type] == "UniFi" {
                        grok {
                            match => { "message" => [
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: %{PROG:Proceso_nombre}: \[%{NUMBER:Proceso_pid}\] \[%{DATA:Proceso_tarea}\] DNS request timed out; \[STA: %{COMMONMAC:Cliente_MAC}\]\[QUERY: %{GREEDYDATA:Cliente_consulta}\] \[DNS_SERVER :%{IPV4}\] \[TXN_ID %{DATA:Txn_id}\] \[SRCPORT %{NUMBER:Cliente_puerto_origen}\]",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: %{PROG:Proceso_nombre}: \[%{NUMBER:Proceso_pid}\] \[%{DATA:Proceso_tarea}\] %{GREEDYDATA:Mensaje}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: wireless_agg_stats.log_sta_anomalies\(\): bssid=%{COMMONMAC:BSSID_MAC} radio=%{WORD:BSSID_radio} vap=%{WORD:vap} sta=%{COMMONMAC:Cliente_MAC} satisfaction_now=%{NUMBER:Cliente_satisfaccion} anomalies=%{GREEDYDATA:Cliente_anomalia}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: \[%{DATA:Proceso_tarea}\].stahtd_dump_event\(\): \{\"query_%{NUMBER:Consulta_id}\":\"%{HOSTNAME:Consulta_FQDN}\",\"mac\":\"%{COMMONMAC:Cliente_MAC}\",\"message_type\":\"%{DATA:Mensaje_tipo}\",\"query_server_%{NUMBER:Consulta_id}\":\"%{IPV4:IP_servidor}\",\"assoc_status\":\"%{NUMBER:Asociacion_estado}\",\"vap\":\"%{WORD:vap}\",\"event_type\":\"%{DATA:Evento_tipo}\"\}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: \[%{DATA:Proceso_tarea}\].stahtd_dump_event\(\): \{\"dns_resp_seen\":\"%{WORD:DNS_resp_seen}\",\"message_type\":\"%{DATA:Mensaje_tipo}\",\"mac\":\"%{COMMONMAC:Cliente_MAC}\",\"vap\":\"%{WORD:vap}\",\"assoc_status\":\"%{NUMBER:Asociacion_estado}\",\"event_type\":\"%{DATA:Evento_tipo}\",\"event_id\":\"%{NUMBER:Evento_id}\",\"arp_reply_gw_seen\":\"%{WORD:ARP_resp_seen}\",\"auth_ts\":\"%{NUMBER:Auth_ts}\"\}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: \[%{DATA:Proceso_tarea}\].stahtd_dump_event\(\): \{\"query_server_%{NUMBER:Consulta_id}\":\"%{IPV4}\",\"query_%{NUMBER:Consulta_id}\":\"%{HOSTNAME:Consulta_FQDN}\",\"mac\":\"%{COMMONMAC:Cliente_MAC}\",\"message_type\":\"%{DATA:Mensaje_tipo}\",\"assoc_status\":\"%{NUMBER:Asociacion_estado}\",\"vap\":\"%{WORD:vap}\",\"event_type\":\"%{DATA:Evento_tipo}\"\}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: \[%{DATA:Proceso_tarea}\].stahtd_dump_event\(\): \{\"query_server_%{NUMBER:Consulta_id}\":\"%{IPV4}\",\"mac\":\"%{COMMONMAC:Cliente_MAC}\",\"message_type\":\"%{DATA:Mensaje_tipo}\",\"vap\":\"%{WORD:vap}\",\"%{DATA:Evento_tipo}\",\"query_%{NUMBER:Consulta_id}\":\"%{HOSTNAME:Consulta_FQDN}\",\"assoc_status\":\"%{NUMBER:Asociacion_estado}\"\}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: \[%{DATA:Proceso_tarea}\].stahtd_dump_event\(\): \{\"mac\":\"%{COMMONMAC:Cliente_MAC}\",\"message_type\":\"%{DATA:Mensaje_tipo}\",\"assoc_status\":\"%{NUMBER:Asociacion_estado}\",\"vap\":\"%{WORD:vap}\",\"event_type\":\"%{DATA:Evento_tipo}\":\"%{NUMBER:Evento_id}\"\}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: \[%{DATA:Proceso_tarea}\].stahtd_dump_event\(\): \{\"mac\":\"%{COMMONMAC:Cliente_MAC}\",\"message_type\":\"%{DATA:Mensaje_tipo}\",\"vap\":\"%{WORD:vap}\",\"query_server_%{NUMBER:Consulta_id}\":\"%{IPV4}\",\"event_type\":\"%{DATA:Evento_tipo}\",\"assoc_status\":\"%{NUMBER:Asociacion_estado}\",\"query_%{NUMBER:Consulta_id}\":\"%{HOSTNAME:Consulta_FQDN}\"\}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: \[%{DATA:Proceso_tarea}\].stahtd_dump_event\(\): \{\"dns_resp_seen\":\"%{WORD:DNS_resp_seen}\",\"mac\":\"%{COMMONMAC:Cliente_MAC}\",\"message_type\":\"%{DATA:Mensaje_tipo}\",\"assoc_status\":\"%{NUMBER:Asociacion_estado}\",\"vap\":\"%{WORD:vap}\",\"event_type\":\"%{DATA:Evento_tipo}\",\"event_id\":\"%{NUMBER:Evento_id}\",\"auth_ts\":\"%{NUMBER:Auth_ts}\"\}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: \[%{DATA:Proceso_tarea}\].stahtd_dump_event\(\): \{\"dns_resp_seen\":\"%{WORD:DNS_resp_seen}\",\"message_type\":\"%{DATA:Mensaje_tipo}\",\"mac\":\"%{COMMONMAC:Cliente_MAC}\",\"ip_assign_type\":\"%{DATA:Tipo_asignacion_ip}\",\"vap\":\"%{WORD:vap}\",\"assoc_status\":\"%{NUMBER:Asociacion_estado}\",\"event_type\":\"%{DATA:Evento_tipo}\",\"auth_ts\":\"%{NUMBER:Auth_ts}\",\"wpa_auth_delta\":\"%{NUMBER:WPA_auth_delta}\",\"assoc_delta\":\"%{NUMBER:Assoc_delta}\",\"auth_delta\":\"%{NUMBER:Auth_delta}\",\"event_id\":\"%{NUMBER:Evento_id}\"\}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: %{PROG:Proceso_nombre}: %{WORD:vap}: STA %{COMMONMAC:Cliente_MAC} %{DATA:Proceso_tarea}: %{GREEDYDATA:Mensaje}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: wevent.ubnt_custom_event\(\): %{DATA:Evento_tipo} %{WORD:vap}: %{COMMONMAC:Cliente_MAC} / %{IPV4:Cliente_ip}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: wevent.ubnt_custom_event\(\): %{DATA:Evento_tipo} %{WORD:vap}: %{COMMONMAC:Cliente_MAC} / %{NUMBER:Evento_id}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: : %{PROG:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: %{GREEDYDATA:Mensaje}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: %{PROG:Proceso_nombre}: %{DATA:Proceso_tarea}\[%{NUMBER:Proceso_pid}\]: %{GREEDYDATA:Tarea}: %{GREEDYDATA:Mensaje}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: %{PROG:Proceso_nombre}: %{DATA:Proceso_tarea} %{COMMONMAC:Cliente_MAC} %{WORD:vap} \(%{GREEDYDATA:Mensaje}\)",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: %{UNIXPATH:Proceso_nombre}\[%{NUMBER:Proceso_pid}\]: %{GREEDYDATA:Mensaje}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: %{PROG:Proceso_nombre}: \[%{NUMBER:Proceso_pid}\] %{GREEDYDATA:Mensaje}",
                              "^<%{POSINT:syslog_pri}>%{SYSLOGTIMESTAMP:syslog_timestamp} %{WORD:UniFi_MAC},%{GREEDYDATA:UniFi_Firmware}: %{PROG:Proceso_nombre}: %{DATA:Proceso_tarea}: %{GREEDYDATA:Mensaje}"
                                       ]
                            }
                        }

                        mutate {
                          convert => {
                            "Cliente_satisfaccion" => "integer"
                          }
                        }
        }
}

output {

        if ([type]=="UniFi"){

                elasticsearch {
                   index => "unifi-%{+YYYY.MM.dd}"
                   hosts => "DIRECCION_IP_ELASTICSEARCH:9200"
                }

        }
}

Continuamos, necesitamos crear un fichero en Logstash para ingestar, transformar y enviar los datos. Primero escucharemos en el puerto TCP indicado en UniFi que vimos en el paso anterior; segon, tratar los logs que recibe y separarlos en distintos campos para ser por último almacenados en nuestro Elasticsearch. Así que creamos por ejemplo el fichero de configuración ‘/etc/logstash/conf.d/unifi.conf’, Seguiremos con los filtros, yo hice mis grok como pude, pido perdón a los sabios del tema, pero totalmente válido para recopilar los Logs del Ubiquiti UniFi con versión 6.2.x. Al final, en el output le daremos salida a nuestro Elasticsearch, recordar poner username & password que lo mío es un LAB y me encantan las worst practicesY de verdad perdonar los verdaderos gurús mis groks, sigo en 1ro de filtros.

Un cop creat el fitxer de configuració, acordaros de reiniciar el servicio de Logstash para recargar la nueva config. Después como siempre, anirem a Kibana i un cop les dades estiguin entrant ja podrem anar a "Management" > "Stack management" > "Kibana" > "Index Patterns" > "Crea't index pattern" per crear el patró de l'índex, el que s' ha dit, com habitualment (en aquest cas i sense les cometes) ‘unifi-*’ y tendremos los datos ya en Elasticsearch almacenados de manera correcta. Ahora podríamos conectarnos desde “Discover” a nuestro índice de Ubiquiti UniFi visualizar que está recogiendo datos.

Y acabamos como siempre en Grafana! Tras crear el índice en Kibana, ahora en nuestro amado Grafana deberíamos crear un “Data Source” que apunte contra nuestro Elasticsearch y el índice de UniFi. Després ja és deixar volar la imaginació, fer un Dashboard amb diferents Panells, amb diferents dades a visualitzar, gráficas con satisfacción/calidad de la conexión de los clientes, un mapamundi con las conexiones entrantes/salientes, uno de estilo Sankey para ver IPs clientes/APs, en formato columnas, en taules para ver datos concretos de por ejemplo los accesos correctos, incorrectes, las conexiones…

Com sempre, intentando que pueda inspirar o ayudar, si lo mejoráis me lo pasáis 😉 Con esto podremos ver qué pasa en nuestro(s) dispositivos de Ubiquiti, en los Puntos de Acceso, en los Switches, en temps real, posant un refresc automàtic cada 10 segundos queda muy impresionante, también nos servirá para analizar el resumen de las últimas 24h, o conocer cuando algo extraño sucede… como el vecino intentando conectarse.. Com sempre, gracias a todos y muchísimo más a los que movéis este tipo de contenidos en redes sociales 😉 jeje ¡Abrazos!

Posts recomanats

Autor

nheobug@bujarra.com
Autor del blog Bujarra.com Cualquier necesidad que tengas, no dubtis a contactar amb mi, us intentareu ajudar sempre que pugui, compartir és viure ;) . Gaudir dels documents!!!