Всем привет, хочу поделиться своим опытом по реализации сбора syslog с устройств Juniper и Cisco. Изначально хотел использовать под эту задачу zabbix так, как он уже используется в рабочей сети как основная система мониторинга, но после анализа различных источников на эту тему, понял, что он просто не справится с такой нагрузкой. Исходя из этого, было принято решения использовать инструменты заточенные под сбор логов. Первое что пришло в голову, это связка promtail-loki-grafana так, как она достаточно быстро и просто реализуема. Всё бы ничего, но в процессе отладки, promtail не удавалось распарсить syslog с маршрутизаторов. Погуглив ошибку, выяснилось, что устройства Cisco отправляют syslog с небольшим отклонением от формата RFC 3164, и вообще его нужно преобразовывать к RFC 5424. Таким образом, новая задача состояла в преобразовании syslog к надлежащему виду, с помощью какого-либо инструмента, и таким инструментом стал Syslog-ng и Vector. Vector отлично подходит для работы с логами сетевых устройств Juniper, но его недостаточно для работы с логами устройств Cisco.
Поэтому модель сбора syslog стала выглядеть следующим образом:

Наиболее быстрым и удобным решением для развертывания такой модели, является использование docker-compose.
Docker-compose.yml
services:
syslog-ng:
image: lscr.io/linuxserver/syslog-ng:latest
container_name: syslog-ng
environment:
- PUID=1000
- PGID=1000
- TZ=Etc/UTC
- LOG_TO_STDOUT= #optional
volumes:
- ./syslog-ng/config:/config
- ./log:/var/log #optional
ports:
- 515:5514/udp # Порт приема syslog cisco
restart: unless-stopped
vector:
image: timberio/vector:latest-alpine
container_name: vector
restart: unless-stopped
ports:
- "514:514/udp" # Порт для syslog juniper
- "516:516/udp" # Порт для syslog-ng
volumes:
- ./vector.toml:/etc/vector/vector.toml # Подключение конфигурации
environment:
- VECTOR_CONFIG=/etc/vector/vector.toml # Указание конфигурационного файла
network_mode: host
loki:
image: grafana/loki:3.2.1
container_name: loki
ports:
- "3100:3100"
volumes:
- ./:/mnt/config
command: -config.file=/mnt/config/loki-config.yaml
restart: unless-stopped
grafana:
environment:
- GF_PATHS_PROVISIONING=/etc/grafana/provisioning
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
- GF_FEATURE_TOGGLES_ENABLE=alertingSimplifiedRouting,alertingQueryAndExpressionsStepMode
entrypoint:
- sh
- -euc
- |
mkdir -p /etc/grafana/provisioning/datasources
cat <<EOF > /etc/grafana/provisioning/datasources/ds.yaml
apiVersion: 1
datasources:
- name: Loki
type: loki
access: proxy
orgId: 1
url: http://<ip-адрес>:3100
basicAuth: false
isDefault: true
version: 1
editable: false
EOF
/run.sh
image: grafana/grafana:latest
ports:
- "3000:3000"
Перед применением необходимо изменить в файле ip-адреса и volumes под свою топологию.
Инициализация запуска контейнеров с помощью команды: "docker-compose up -d", из директории в которой располагается конфигурационный файл docker-compose.yml. После того как, все контейнеры подгрузились, можно проверить их состояние: "docker ps -a".
После определения новой связки: syslog-ng, vector, loki-grafana, loki, я приступил к созданию(редактированию) конфигурационных файлов для syslog-ng, vector и loki:
syslog-ng.conf:
#############################################################################
# Default syslog-ng.conf file which collects all local logs into a
# single file called /var/log/messages tailored to container usage.
@version: 4.2
@include "scl.conf"
source s_network_udp {
syslog(transport(udp) port(5514));
};
#destination d_local {
# file("/var/log/messages");
# file("/var/log/messages-kv.log" template("$ISODATE $HOST $(format-welf --scope all-nv-pairs)\n") frac-digits(3));
#};
destination d_vector {
network("10.36.1.52" port(516) transport("udp"));
};
#log {
# source(s_network_udp);
# destination(d_local);
#};
log {
source(s_network_udp);
destination(d_vector);
};
В конфиге закомментированы строки для записи syslog в файлы messages-kv.log и messages, необходимые для отладки принимаемых syslog-ng сообщений от сетевых устройств.
vector.toml
data_dir = "/var/lib/vector"
[sources.syslog_514] # прием логов juniper
type = "syslog"
address = "0.0.0.0:514"
mode = "udp"
[sources.syslog_516] # прием логов cisco
type = "syslog"
address = "0.0.0.0:516"
mode = "udp"
[transforms.fix_hostname]
type = "remap"
inputs = ["syslog_516"]
source = '''
.host = .appname # замена ip на hostname
'''
[sinks.juniper_loki]
type = "loki"
inputs = [ "syslog_514" ]
endpoint = "http://<ip-loki>:3100"
[sinks.juniper_loki.encoding]
codec = "json"
[sinks.juniper_loki.labels]
host = "{{ host }}"
severity = "{{ severity }}"
vendor = "juniper" # Метка для Juniper
log_type = "network_logs"
[sinks.cisco_loki]
type = "loki"
inputs = [ "fix_hostname" ]
endpoint = "http://<ip-loki>:3100"
[sinks.cisco_loki.encoding]
codec = "json"
[sinks.cisco_loki.labels]
host = "{{ host }}"
severity = "{{ severity }}"
vendor = "cisco" # Метка для Cisco
log_type = "network_logs"
[sinks.file_syslog]
type = "file"
inputs = [ "syslog_514", "fix_hostname" ]
healthcheck = true
path = "/var/log/vector/vector-%Y-%m-%d.log"
[sinks.file_syslog.encoding]
codec = "text"
В данном конфиге необходимо указать ip-адрес сервера Loki в двух sinks.
loki-config.yaml
auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
common:
instance_addr: 127.0.0.1
path_prefix: /tmp/loki
storage:
filesystem:
chunks_directory: /tmp/loki/chunks
rules_directory: /tmp/loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
ruler:
alertmanager_url: http://localhost:9093
# By default, Loki will send anonymous, but uniquely-identifiable usage and configuration
# analytics to Grafana Labs. These statistics are sent to https://stats.grafana.org/
#
# Statistics help us better understand how Loki is used, and they show us performance
# levels for most users. This helps us prioritize features and documentation.
# For more information on what's sent, look at
# https://github.com/grafana/loki/blob/main/pkg/analytics/stats.go
# Refer to the buildReport method to see what goes into a report.
#
# If you would like to disable reporting, uncomment the following lines:
#analytics:
# reporting_enabled: false
После развертывания можно убедится в корректности функционирования каждого сервиса. Работоспособность grafana, проверяется по адресу: "http://localhost:3100/". Проверка loki осуществляется с помощью выполнения HTTP-запроса к API Loki: http://localhost:3100/ready.
Ожидаемый ответ: ready
Syslog-ng можно проверить и отладить с помощью файла в который записываются принимаемые syslog в режиме real time (для его подключения раскомментируйте поля в конфиге syslog-ng.conf) об этом указано выше.
Проверку работы vector, я осуществлял посредством анализа логов контейнера: "docker logs vector".
Теперь, когда все необходимые инструменты развернуты, остается произвести конфигурацию сетевых устройств, для отправки их syslog на сокет vector и syslog-ng. В сетевых устройствах juniper достаточно прописать следующие команды:
set system syslog host <ip-адрес vector> any any
set system syslog host <ip-адрес vector> port 514
set system syslog host <ip-адрес vector> facility-override local7
set system syslog host <ip-адрес vector> structured-data
set system syslog source-address <ip-порта управления>
Команды для устройств cisco:
logging origin-id string " <hostname>"
logging source-interface <порт управления>
logging host <ip-адрес syslog-ng> transport udp port 515
logging facility local7
service timestamps log datetime msec
logging on
logging trap debugging
Изменить конфигурацию можно двумя способами:
1) Подключиться к устройству и прописать вручную
2) Написать playbook, и с помощью Ansible изменить конфигурацию
Я выбрал второй вариант, так как изменять конфигурацию на каждом устройстве вручную, достаточно долгое занятие, особенно в крупных сетях.
Примерный вариант используемого мной playbook для juniper:
---
- name: "logs"
hosts: junos
connection: local
gather_facts: no
collections: juniper.device
tasks:
- name: "logs"
junipernetworks.junos.junos_config:
lines:
- "set system syslog host <ip-сервера> any any"
- "set system syslog host <ip-сервера> port 514"
- "set system syslog host <ip-сервера> facility-override local7"
- "set system syslog host <ip-сервера> structured-data"
commit: yes
В целях проверки, отправляемых сетевыми узлами syslog, можно на стороне сервера с помощью команды: "sudo tcpdump -i any port 514" осуществить прослушивание порта.
В целом, система уже собирает логи, остается только решить задачу визуализации данных , посредством создания dashboard в Grafana, но тут как говорится: "на вкус и цвет товарищей нет". Поэтому, я покажу какие варианты панелей на мой взгляд имеют место быть. Но для начала, необходимо подключить Loki к Grafana, как новый источник данных. Заходим в Grafana по адресу http://<ip-сервера>:3000, переходим в вкладку "Connections" и выбираем "Data sources" - "+ Add new data source". Далее, с помощью поисковой строки находим и выбираем "Loki", в случае если grafana и loki располагаются на одном устройстве, достаточно указать указать в разделе Connection url: http://localhost:3100, в противном случае указать ip-сервера на котором развернут Loki. После чего сохраняем новый источник данных "save & test".
Panel №1. Вывод Logs
Переходим в "Dashboards" - "New" - "New dashboard" - "Add Visualization" - "Loki"

1 - Выбираем тип Logs; 2 - Задаем название panel; 3 - Включаем временные метки; 4 - Создаем запрос. Результатом запроса будет вывод всех syslog со всех устройств. После чего обновляем значение "Run query", получаем вывод syslog и сохраняем.
Далее добавляем средства поиска и фильтрации, выводимых syslog.

Переходим в выделенную красным цветом, вкладку - "Dashboard settings" - "Variables" - "Add variable" и действуем как показано ниже.

Проделываем аналогичные действия по созданию поля метки "Severity". После этого добовляем filter, как показано на рисунке ниже.

В результате проделанных действий, получается панель с выводом syslog и поисковой системой с фильтрацией.

Panel №2. Bar gauge and Pie chart
Панель отображения статистики хоста создается согласно следующего изображения.

Пример запроса:
sum by(severity) (
count_over_time({host="RLIK-Krasnoyrsk-Olive"} [$__range])
)
Точное имя хоста можно взять при выборе метки в режиме "Builder"
С аналогичной информативностью представляется возможным, построить и круговую диаграмму "Pie chart"

Пример запроса аналогичный, отличаться будет только имя хоста или использование метки для анализа всех syslog. На основе информации представленной выше вы можете собрать dashboard как на изображении ниже, исходя из своих интересов.

Заключение
Таким образом, используя инструменты Vector, Loki и Grafana, посредством не сложных манипуляций можно собрать достаточно хорошую систему сбора и анализа логов с сетевых устройств. Благодаря грамотной конфигурации Vector и правильно составленного dashboard в Grafana вы сможете: своевременно выявлять сетевые сбои и проблемы, отслеживать производительность, обнаруживать атаки и многое другое, что поможет вам успешно заниматься администрированием сети.