我是从 4.0 版本开始使用 mosdns,经历了 4.1 和 4.2 不稳定的功能更新和今年 1 月份发布 5.x 大版本重构后貌似已经稳定下来。

托 @river_leaves 的福利用 mosdns 自带的 prometheus metrics 接口实时查看 DNS 解析情况。

配置中的规则是灵活且有时候很难调试,为了验证配置规则是否有效以及可视化看到域名访问频次,我从 mosdns 日志本身下手,需要的工具有 vector、prometheus、loki 和 grafana。

实时监控 mosdns 规则解析 Grafana 看板

当前教程仅适用于 mosdns 5.0 ~ 5.1.3 版本(后续版本没有发布可能存在配置变化,依据实际情况调整)

mosdns

mosdns 5 版本采用了新数据源解包格式,配置我实在懒得调整了,直接在采用了 luci-app-mosdns 插件配置微调。配置中各个 plugins 名称请确保不要修改和变动,否则会导致 vector 转换规则无法正常工作。

看不到下面配置文件的,送上直达电梯

配置定义了 mosdns 日志的文件路径为 /var/log/mosdns.log,输出日志等级只需要是 INFO 即可。如果 mosdns 服务所在磁盘空间较小建议使用 logrotate 来切割日志并控制归档日志数量,以免出现空间不足的情况。

1/var/log/mosdns.log {
2  daily
3  rotate 2
4  compress
5  missingok
6  notifempty
7  copytruncate
8}

copytruncate 的意思是将旧日志文件的内容复制到新日志文件,默认是直接改名原文件会造成 mosdns 运行日志记录出现问题,设置好后确保 logrotate 定时运行:

1# crontab -e
20 1 * * * /bin/sh -c "/usr/sbin/logrotate -l=syslog -d /etc/logrotate.d"

vector

vector 是一个日志收集工具,能够从多个源(Source)收集、转换(Transform)并推送到下一个接收器(Sinks)。

vector 需要能够直接访问到 mosdns 的日志文件。这里有两种方式可以实现:一种是两个服务都在一台机器上运行,另外一种是通过容器化共享 volume 让 vector 可以读取 mosdns 日志。

工具本身是 Go 语言开发从 Github 直接下载好对应的包解压缩就能够使用或者使用一键安装脚本:

1curl --proto '=https' --tlsv1.2 -sSf https://sh.vector.dev | bash

Openwrt/Immortalwrt 用户可使用我个人维护的仓库 icyleaf/openwrt-dist 添加后即可安装(支持 amd64、armv8 平台的 snapshot 和 23.05.0-rc3 两个分支):

添加仓库密钥

1wget http://cdn.jsdelivr.net/gh/icyleaf/openwrt-dist@master/key-build.pub
2opkg-key add key-build.pub

根据 openwrt 平台不同修改源地址

1# 源规则
2# src/gz icyleaf https://icyleaf-openwrt-repo.vercel.app/{{{target}}/packages/{{arch}}
3
4# 添加 snapshot 分支 amd64 (x86/64) 平台的源
5echo "src/gz icyleaf https://icyleaf-openwrt-repo.vercel.app/snapshosts/packages/x86/64" >> /etc/opkg/customfeeds.conf

安装 vector

1opkg update
2opkg install vector

修改 /etc/vector/config.yml 的配置文件如下

 1data_dir: /tmp/vector
 2
 3sources:
 4  mosdns-log-file:
 5    type: file
 6    include:
 7      - /var/log/mosdns.log
 8    read_from: beginning
 9
10transforms:
11  mosdns-input:
12    type: filter
13    inputs:
14      - mosdns-log-file
15    condition: |
16      .file == "/var/log/mosdns.log"      
17
18  mosdns-data:
19    type: remap
20    inputs:
21      - mosdns-input
22    drop_on_error: true
23    source: |
24      .type = "mosdns"
25      .app = "mosdns"
26      del(.host)
27      del(.file)
28      del(.source_type)
29
30      message_parts = split!(.message, r'\t')
31
32      .timestamp = parse_timestamp!(message_parts[0], format: "%FT%T%.9fZ")
33      .level = message_parts[1]
34
35      if (length(message_parts) == 6) {
36        .plugin = message_parts[2]
37        .processor = message_parts[3]
38        .message = message_parts[4]
39
40        if (exists(message_parts[5])) {
41          .metadata = parse_json!(message_parts[5])
42          . = merge!(., .metadata)
43          del(.metadata)
44        }
45      } else {
46        .processor = message_parts[2]
47        .message = message_parts[3]
48
49        if (exists(message_parts[4])) {
50          .metadata = parse_json!(message_parts[4])
51          . = merge!(., .metadata)
52          del(.metadata)
53        }
54      }
55
56      if (exists(.query)) {
57        query_parts = split!(.query, r'\s')
58        .domain = query_parts[0]
59        .record = query_parts[2]
60        .address = query_parts[5]
61      }      
62
63sinks:
64  # 同步到 loki,根据实际情况修改 endpoint 的值
65  loki:
66    type: loki
67    inputs:
68      - mosdns-data
69    endpoint: 'http://10.10.10.2:3100'
70    encoding:
71      codec: json
72    labels:
73      app: '{{ app }}'
74      type: '{{ type }}'
75    healthcheck:
76      enabled: true
77
78  # 临时输出转换数据到 vector 控制台(生产环境请禁用)
79  debug_mosdns:
80    type: console
81    inputs:
82      - mosdns-data
83    encoding:
84      codec: json

运行 vector 服务(部署好 loki 后再运行)

非 openwrt 用户使用

1vector --config /etc/vector/config.yml --watch-config --verbose

openwrt 用户使用

1$ /etc/init.d/vector start
2
3Loaded with warnings ["/etc/vector/config.yml"]
4-----------------------------------------------
5√ Component configuration
6√ Health check "loki"
7√ Health check "vector"
8-----------------------------------------------
9                                      Validated

使用 openwrt 插件的 vector 服务本身是会监控配置文件变化并重载,后面再调整的时候也不需要反复重启服务。

prometheus

prometheus 是一个监控数据服务,可以作为 Grafana 数据源使用。安装参考官方教程,配置文件需要把 mosdns metrics 地址(比如是 10.10.10.1:8338)加到 prometheus.yml 文件中:

 1global:
 2  scrape_interval:     1m
 3  evaluation_interval: 1m
 4
 5scrape_configs:
 6+  - job_name: mosdns
 7+    scrape_interval: 5s
 8+    # scrape_timeout: 10s
 9+
10+    # metrics_path: /metrics
11+    static_configs:
12+      - targets:
13+        - 10.10.10.1:8338

loki

loki 是一个日志聚合服务,本身也是 Grafana 研发的,可以作为 Grafana 数据源使用。参照官方文档就能部署好 loki 和 Grafana,唯一需要注意的是要提前下载好 loki 配置文件。部署好之后把 loki 地址更新到上面 vector 配置。

grafana

grafana 是一个数据可视化工具,安装见 loki 部分,已有服务直接跳过。

Dashboard 看板的配置就非常简单了,先添加好 prometheus 和 loki 的数据源后,导入 mosdns v5 看板,按照图示配置即可。

Grafana 导入 Dashboard 看板

Grafana 配置数据源

结语

感谢 mosdns 长达几个月的配置稳定之前挖的坑填上了,撒花!