Syslog with Elasticsearch

本指南说明如何使用 Elasticsearch、Kibana 和 Fleet Server 配合 MikroTik RouterOS 设备配置 Syslog 数据收集与分析。内容涵盖先决条件、Elastic 和 RouterOS 组件的设置步骤,包括 agent policy 创建和 Custom UDP logs 集成配置。

将 Syslog 与 Elasticsearch 配合使用

简介

Elasticsearch 是一个流行的 NoSQL 数据库,可用于存储各种数据,包括 Syslog 数据。结合 Kibana,你可以创建一个强大的工具来分析来自 RouterOS 设备的 Syslog 数据。本指南依赖 Elasticsearch 集成,要使其正常工作,你需要一个可用的 Elasticsearch 环境。本指南不会涵盖 Elasticsearch 和 Kibana 的安装说明,但会涵盖设置 Syslog 数据收集与分析的相关步骤。

使用 Elasticsearch 可以进行许多可能的配置,但为了本指南的目的,我们将使用以下原则:

  • 一台 RouterOS (10.0.0.1) 设备将 Syslog 数据发送到运行 Custom UDP logs的服务器 (10.0.0.2)。
  • 运行 Custom UDP logs 集成的服务器 (10.0.0.2) 摄取 Syslog 数据、处理数据并将其发送到 Fleet Server (10.0.0.3)。
  • Fleet Server (10.0.0.3) 将数据存储在 Elasticsearch (10.0.0.4) 中。
  • Kibana (10.0.0.5) 从 Elasticsearch (10.0.0.4) 检索数据、分析数据并允许你搜索数据。

信息

本指南不会使用 Logstash 作为分析 Syslog 数据的一部分;它已被 Fleet Server 取代。

信息

可以将 Elasticsearch、Kibana、Fleet Server 和 Custom UDP logs 集成安装在同一台设备上。

先决条件

  • 设置 Elasticsearch。
    :::info Elasticsearch 在多个平台上得到广泛支持。建议设置一个 Elasticsearch 节点集群。 :::
  • 设置 Kibana。
    :::info Kibana 可以安装在安装 Elasticsearch 的同一台设备上,但出于性能考虑,也可以将其安装在单独的设备上。虽然不使用 Kibana 也可以分析 Syslog 数据,但需要编写自己的 API 请求,而 Kibana 非常易于使用,并具有广泛的功能。 :::
  • 设置 Fleet Server。
    :::info 可以在安装 Elasticsearch 和/或 Kibana 的同一台设备上设置 Fleet Server。建议将 Fleet Server 安装在不同的设备上。有关硬件和拓扑要求的建议,请参阅 Elasticsearch 手册。 :::

设置

设置说明分为两部分:Elastic(有关 Elasticsearch、Kibana 和 Fleet Server 的配置)和 RouterOS(与你的 RouterOS 设备相关的配置)。

Elastic

警告

某些步骤可能会随时间变化。请参阅 Elastic 的手册以查找最新的步骤。

  1. 登录你的 Kibana。

  2. 在主菜单下打开 Fleet 部分。

  3. 打开 "Agent policies" 部分。

  4. 按 "Create agent policy" 按钮以创建新的 Agent Policy。

  5. 为该策略命名,例如 "Syslog policy",根据需要调整高级设置,然后创建该策略。或者你可以使用下面的 API 请求:

    POST kbn:/api/fleet/agent_policies
    {
      "name": "Syslog policy",
      "description": "",
      "namespace": "default",
      "monitoring_enabled": [
        "logs",
        "metrics"
      ],
      "inactivity_timeout": 1209600,
      "is_protected": false
    }
    
  6. 通过点击名称打开你新创建的策略。

  7. 按 "Add integration"。

  8. 搜索 "Custom UDP logs" 并按 "Add Custom UDP logs"。

  9. 调整配置,并确保:

    • 将 "Listen Address" 设置为将要运行 Custom UDP logs 集成的服务器的 IP 地址,在此示例中该地址应为 "10.0.0.2"。
    • 将 "Listen Port" 设置为 "5514"。
    • 将 "Dataset name" 设置为 "routeros"。
    • 将 "Ingest Pipeline" 设置为 "logs-routeros@custom"。
    • 将 "Syslog Parsing" 设置为 "Yes"。
  10. 保存集成。

  11. 按 "Add Elastic Agent to your host" 按钮。

  12. 按照说明将 Elastic Agent 添加到你的主机。
    :::info 官方 Elastic 手册建议将 Elastic Agent 安装为 Fleet-managed。考虑遵循该建议,因为当 agent 由 Fleet 管理时更容易管理。 :::

  13. 转到主菜单上的 "Stack Management",然后打开 "Ingest Pipelines"。

  14. 通过按 "Create pipeline" 然后 "New pipeline" 来创建新的 Ingest Pipeline。

  15. 将 "Name" 设置为 "logs-routeros@custom"。

  16. 按 "Import processors" 并粘贴以下 processors:

    {
    	"processors": [
    		{
    			"grok": {
    			"field": "message",
    			"patterns": [
    				"^first L2TP UDP packet received from %{IP:source.ip}$",
    				"^login failure for user %{USERNAME:user.name} from %{IP:source.ip} via %{DATA:service.name}$",
    				"^%{USERNAME:user.name} logged in, %{IP:client.ip} from %{IP:source.ip}$",
    				"^dhcp alert on %{DATA}: discovered unknown dhcp server, mac %{MAC:source.mac}, ip %{IP:source.ip}$",
    				"in:%{DATA} out:%{DATA}, ?(connection-state:%{DATA},|)?(src-mac %{MAC:source.mac},|) proto %{DATA:network.transport} \\(%{DATA}\\), %{IP:source.ip}:?(%{INT:source.port}|)->%{IP:destination.ip}:?(%{INT:destination.port}|), len %{INT:network.bytes}$",
    				"in:%{DATA} out:%{DATA}, ?(connection-state:%{DATA},|)?(src-mac %{MAC:source.mac},|) proto %{DATA:network.transport}, %{IP:source.ip}:?(%{INT:source.port}|)->%{IP:destination.ip}:?(%{INT:destination.port}|), len %{INT:network.bytes}$",
    				"^%{DATA:network.name} (deassigned|assigned) %{IP:client.ip} for %{MAC:client.mac} %{DATA}$",
    				"^%{DATA:user.name} logged out, %{INT:event.duration} %{INT} %{INT} %{INT} %{INT} from %{IP:client.ip}$",
    				"^user %{DATA:user.name} logged out from %{IP:source.ip} via %{DATA:service.name}$",
    				"^user %{DATA:user.name} logged in from %{IP:source.ip} via %{DATA:service.name}$",
    				"^%{DATA:network.name} client %{MAC:client.mac} declines IP address %{IP:client.ip}$",
    				"^%{DATA:network.name} link up \\(speed %{DATA}\\)$",
    				"^%{DATA:network.name} link down$",
    				"^user %{DATA:user.name} authentication failed$",
    				"^%{DATA:network.name} fcs error on link$",
    				"^phase1 negotiation failed due to time up %{IP:source.ip}\\[%{INT:source.port}\\]<=>%{IP:destination.ip}\\[%{INT:destination.port}\\] %{DATA}:%{DATA}$",
    				"^%{DATA:network.name} (learning|forwarding)$",
    				"^user %{DATA:user.name} is already active$",
    				"^%{GREEDYDATA}$"
    			]
    			}
    		},
    		{
    			"lowercase": {
    			"field": "network.transport",
    			"ignore_missing": true
    			}
    		},
    		{
    			"append": {
    			"ignore_failure": true,
    			"field": "event.category",
    			"description": "Enrich logon events",
    			"allow_duplicates": false,
    			"value": [
    				"authentication"
    			],
    			"if": "ctx.message =~ /(login failure for user|logged in from|logged in,)/"
    			}
    		},
    		{
    			"append": {
    			"ignore_failure": true,
    			"field": "event.outcome",
    			"description": "Enrich successful login events",
    			"allow_duplicates": false,
    			"value": [
    				"success"
    			],
    			"if": "ctx.message =~ /(logged in from|logged in,)/"
    			}
    		},
    		{
    			"append": {
    			"ignore_failure": true,
    			"field": "event.outcome",
    			"description": "Enrich failed login events",
    			"allow_duplicates": false,
    			"value": [
    				"failure"
    			],
    			"if": "ctx.message =~ /(login failure for user)/"
    			}
    		},
    		{
    			"append": {
    			"ignore_failure": true,
    			"field": "event.category",
    			"description": "Enrich network events",
    			"allow_duplicates": false,
    			"value": [
    				"network"
    			],
    			"if": "ctx.message =~ /( fcs error on link| link down| link up)/"
    			}
    		},
    		{
    			"append": {
    			"ignore_failure": true,
    			"field": "event.outcome",
    			"description": "Enrich network failures",
    			"allow_duplicates": false,
    			"value": [
    				"failure"
    			],
    			"if": "ctx.message =~ /( fcs error on link)/"
    			}
    		},
    		{
    			"append": {
    			"ignore_failure": true,
    			"field": "event.category",
    			"allow_duplicates": false,
    			"value": [
    				"session"
    			],
    			"if": "ctx.message =~ /(logged out)/"
    			}
    		},
    		{
    			"append": {
    			"ignore_failure": true,
    			"field": "event.category",
    			"allow_duplicates": false,
    			"value": [
    				"threat"
    			],
    			"if": "ctx.message =~ /(from address that has not seen before)/"
    			}
    		},
    		{
    			"append": {
    			"ignore_failure": true,
    			"field": "service.name",
    			"value": [
    				"l2tp"
    			],
    			"if": "ctx.message =~ /(^L2TP\\/IPsec VPN)/"
    			}
    		},
    		{
    			"geoip": {
    			"ignore_failure": true,
    			"ignore_missing": true,
    			"field": "source.ip",
    			"target_field": "source.geo"
    			}
    		},
    		{
    			"geoip": {
    			"ignore_failure": true,
    			"ignore_missing": true,
    			"field": "destination.ip",
    			"target_field": "destination.geo"
    			}
    		},
    		{
    			"geoip": {
    			"ignore_failure": true,
    			"ignore_missing": true,
    			"field": "client.ip",
    			"target_field": "client.geo"
    			}
    		}
    	]
    }
    
  17. 按 "Save pipeline"。

  18. 转到主菜单上的 "Stack Management",然后选择 "Index Management",再选择 "Component templates"。

  19. 通过按 "Create component template" 创建新模板。

  20. 将 "Name" 设置为 "logs-routeros@custom"。

  21. 在 "Index settings" 部分下,粘贴以下内容:

    {
      "index": {
        "lifecycle": {
          "name": "logs"
        },
        "default_pipeline": "logs-routeros@custom"
      }
    }
    

    :::info 将 ILM policy 更改为你需要的策略名称。"logs" 策略是可能被其他日志使用的默认策略。 :::

  22. 在 "Mappings" 部分下,按 "Load JSON" 并粘贴以下内容:

    {
      "dynamic_templates": [],
      "properties": {
        "service": {
          "type": "object",
          "properties": {
            "name": {
              "type": "keyword"
            }
          }
        },
        "destination": {
          "type": "object",
          "properties": {
            "port": {
              "type": "long"
            },
            "ip": {
              "type": "ip"
            }
          }
        },
        "host": {
          "type": "object",
          "properties": {
            "ip": {
              "type": "ip"
            }
          }
        },
        "client": {
          "type": "object",
          "properties": {
            "ip": {
              "type": "ip"
            },
            "mac": {
              "type": "keyword"
            }
          }
        },
        "source": {
          "type": "object",
          "properties": {
            "geo": {
              "type": "object",
              "properties": {
                "continent_name": {
                  "ignore_above": 1024,
                  "type": "keyword"
                },
                "region_iso_code": {
                  "ignore_above": 1024,
                  "type": "keyword"
                },
                "city_name": {
                  "ignore_above": 1024,
                  "type": "keyword"
                },
                "country_iso_code": {
                  "ignore_above": 1024,
                  "type": "keyword"
                },
                "country_name": {
                  "ignore_above": 1024,
                  "type": "keyword"
                },
                "location": {
                  "type": "geo_point"
                },
                "region_name": {
                  "ignore_above": 1024,
                  "type": "keyword"
                }
              }
            },
            "as": {
              "type": "object",
              "properties": {
                "number": {
                  "type": "long"
                },
                "organization": {
                  "type": "object",
                  "properties": {
                    "name": {
                      "ignore_above": 1024,
                      "type": "keyword",
                      "fields": {
                        "text": {
                          "type": "match_only_text"
                        }
                      }
                    }
                  }
                }
              }
            },
            "address": {
              "ignore_above": 1024,
              "type": "keyword"
            },
            "port": {
              "type": "long"
            },
            "domain": {
              "ignore_above": 1024,
              "type": "keyword"
            },
            "ip": {
              "type": "ip"
            },
            "mac": {
              "type": "keyword"
            }
          }
        },
        "event": {
          "type": "object",
          "properties": {
            "duration": {
              "type": "long"
            },
            "category": {
              "type": "keyword"
            },
            "outcome": {
              "type": "keyword"
            }
          }
        },
        "message": {
          "type": "match_only_text"
        },
        "user": {
          "type": "object",
          "properties": {
            "name": {
              "type": "keyword"
            }
          }
        },
        "network": {
          "type": "object",
          "properties": {
            "bytes": {
              "type": "long"
            },
            "name": {
              "type": "keyword"
            },
            "transport": {
              "type": "keyword"
            }
          }
        },
        "tags": {
          "ignore_above": 1024,
          "type": "keyword"
        }
      }
    }
    
  23. 按 "Next",然后按 "Save component template"。
    :::warning 如果存在同名的 component template,则改为编辑现有的模板。 :::

  24. 转到主菜单上的 "Stack Management",然后选择 "Index Management",再选择 "Index templates"。

  25. 通过按 "Create template" 创建新模板。

  26. 将 "Name" 设置为 "logs-routeros"。

  27. 将 "Index patterns" 设置为 "logs-routeros-*"。

  28. 在 "Component templates" 部分下,将以下模板添加到你的新 Index template:

    logs@settings
    logs-routeros@custom
    ecs@mappings
    
  29. 按 "Next",然后按 "Save template"。

  30. 确保你已在主机上以及从 RouterOS 设备 (10.0.0.1) 路径中的其他位置打开 5514/UDP 端口。

  31. 你的 Elastic Agent 现在已准备好接收 Syslog 数据!

RouterOS

  1. 在你的 RouterOS 设备 (10.0.0.1) 上配置 Logging action 设置:

    /system/logging/action
    set [find where name="remote"] remote-log-format=syslog remote=10.0.0.2 remote-port=5514 syslog-facility=syslog
    
  2. 添加你希望从 RouterOS 设备 (10.0.0.1) 接收的主题,例如:

    /system/logging
    add action=remote topics=info
    add action=remote topics=error
    add action=remote topics=critical
    add action=remote topics=warning
    add action=remote topics=bridge,stp
    
  3. 你现在应该开始看到 Syslog 数据被摄取。

  4. 继续本指南以开始使用 Kibana。

使用 Kibana

Kibana 允许你搜索已摄取的 Syslog 数据。要查看已摄取的日志,请执行以下操作:

  1. 登录你的 Kibana。

  2. 从主菜单打开 "Discover"。

  3. 添加过滤器,并使用以下参数:

    Select a field: data_stream.dataset
    Select operator: IS
    Select a value: routeros
    
  4. 为简单起见,我们建议在 Discover 菜单中搜索字段,搜索 "message",然后将该字段添加到视图中。

  5. 我们还建议搜索 "log.syslog.hostname" 字段并将其也添加到视图中。

  6. 考虑保存搜索以便以后更容易访问。

  7. 完成。

提示

虽然搜索日志可能很有用,但你更可能想要为某些活动创建警报,并创建连接器以将警报发送到电子邮件、webhook、聊天和其他选项。考虑启用 Spike in failed logon events 规则,以对过多的失败登录尝试发出警报。你还可以创建一个阈值规则,并将其设置为在固定数量的失败登录后发出警报。