RouterOSでSyslog停止中のカウンタを保存
MikroTikのDoH・VLAN設定と、NetwatchでSyslog送信先を切り替える実装記録です。小規模インフラ構築の監視として、5分カウンタ、NAND保存、復旧時の回収、取りこぼしの条件を扱います。
RouterOSの通信とログ収集
MikroTikのRouterOSでDoH、VLAN、DHCP、Firewallを設定しました。CRS304はMacとLinuxのローカル10GbE転送とルーティングに使います。インフラ構築の監視として、Syslogサーバー停止中はカウンタをNANDに残します。
Netwatchで送信先の状態を確認し、Syslog送信とローカル保存を切り替えます。
背景と目的
必要な条件です。
- セキュリティとプライバシー: DNSへの問い合わせを暗号化(DoH)し、平文のUDP/TCP 53番ポートでの通信を禁止する。
- ネットワークの分離: 用途に応じたVLAN(vlan10, vlan20, vlan30等)を作成し、互いに干渉しないようにルーティングを制御する。
- 確実な監視とログ収集: 不正アクセスやパケットドロップの統計を取得し、Linux Syslogサーバーに送信する。ただし、Syslogサーバーがダウンしている間はルーターの内部(NAND)にプールし、復旧後に回収できるようにする。
5分間隔の処理を1本だけ常時動かし、Netwatchは状態フラグだけを変えます。スケジューラの有効・無効は切り替えません。
この構成を置くネットワーク全体像
Port1はWAN、Port2はMac、Port3はLinux、Port4はWi-Fi AP、Port5はConsoleです。有線はローカル10GbE、外向き通信は別のWi-Fiセグメントで扱います。ISP側inboundは基本dropです。
RouterOSがVLAN境界と監視イベントの集約を担当し、Linux停止時も最低限の統計を保持します。
メイン設定:ネットワーク基盤の構築
ether1をWANにし、DHCPクライアントを動かしました。
/interface ethernet set ether1 name=WAN
/ip dhcp-client add interface=WAN disabled=no
1. DNS (DoH有効化)
DNSをDoH(DNS over HTTPS)で暗号化します。
/ip dns set allow-remote-requests=yes \
servers=1.1.1.1,1.0.0.1 \
use-doh-server=https://1.1.1.1/dns-query \
verify-doh-cert=yes
外向きUDP/TCP 53をFirewallで禁止し、ルーターはDoHを使います。クライアントのDNSは各VLANのゲートウェイIPです。
2. VLANとブリッジの設定
vlan10、vlan20、vlan30を作り、ether4、ether2、ether3へそれぞれ割り当てました。
/interface vlan
add name=vlan10 interface=bridge vlan-id=10
add name=vlan20 interface=bridge vlan-id=20
add name=vlan30 interface=bridge vlan-id=30
/interface bridge vlan
add bridge=bridge tagged=bridge,ether4 vlan-ids=10
add bridge=bridge tagged=bridge,ether2 vlan-ids=20
add bridge=bridge tagged=bridge,ether3 vlan-ids=30
/interface bridge port
set [find interface=ether4] pvid=10
set [find interface=ether2] pvid=20
set [find interface=ether3] pvid=30
/ip address
add address=192.168.10.1/24 interface=vlan10
add address=192.168.20.1/24 interface=vlan20
add address=192.168.30.1/24 interface=vlan30
3. DHCPサーバーの設定
この例ではvlan10だけでDHCP配布します。
/ip pool add name=pool10 ranges=192.168.10.100-192.168.10.200
/ip dhcp-server
add name=dhcp10 interface=vlan10 address-pool=pool10 disabled=no
/ip dhcp-server network
add address=192.168.10.0/24 gateway=192.168.10.1 dns-server=192.168.10.1
4. ファイアウォール(フィルタ)
VLAN分離、外部アクセス遮断、管理用vlan88の許可を設定します。forwardではvlan10とvlan20間をdropし、LANからWANへの新規接続を許可します。
/ip firewall filter
# input
add chain=input connection-state=invalid action=drop comment="Drop invalid input"
add chain=input connection-state=established,related action=accept comment="Allow est/rel input"
add chain=input protocol=udp in-interface=ether1 src-port=67 dst-port=68 action=accept comment="Allow DHCP from ISP"
add chain=input protocol=tcp src-address=192.168.88.2 dst-port=22,8291,8728,8729 action=accept comment="Mgmt from vlan88"
add chain=input protocol=udp src-address=192.168.88.2 dst-port=161 action=accept comment="SNMP from vlan88"
add chain=input protocol=tcp src-address=192.168.88.2 dst-port=80,443 action=accept comment="Web mgmt from vlan88"
add chain=input protocol=icmp src-address=192.168.88.2 action=accept comment="ICMP from vlan88"
add chain=input action=drop log=yes log-prefix="IN_DROP:"
# forward
add chain=forward connection-state=invalid action=drop comment="Drop invalid forward"
add chain=forward action=fasttrack-connection connection-state=established,related hw-offload=yes comment="FastTrack"
add chain=forward connection-state=established,related action=accept comment="Allow est/rel forward"
add chain=forward in-interface=vlan10 out-interface=vlan20 action=drop comment="Isolate vlan10->vlan20"
add chain=forward in-interface=vlan20 out-interface=vlan10 action=drop comment="Isolate vlan20->vlan10"
add chain=forward connection-state=new out-interface=ether1 action=accept comment="LAN->WAN new"
add chain=forward action=drop comment="Drop remaining forward"
# output
add chain=output connection-state=established,related action=accept comment="Allow est/rel output"
add chain=output protocol=udp out-interface=ether1 src-port=68 dst-port=67 action=accept comment="Allow DHCP client"
add chain=output protocol=udp out-interface=ether1 dst-port=123 action=accept comment="Allow NTP"
add chain=output protocol=icmp out-interface=ether1 action=accept comment="Allow ping"
add chain=output protocol=tcp out-interface=ether1 dst-port=80,443 action=accept comment="Allow HTTP/HTTPS"
add chain=output protocol=udp dst-address=192.168.88.2 dst-port=514 action=accept comment="Syslog"
add chain=output protocol=tcp dst-address=192.168.88.2 dst-port=3100 action=accept comment="Loki ingest"
add chain=output action=drop comment="Drop remaining output"
状態連動型のSyslog・5分カウンタ送信の実装
通常はLinuxへUDP Syslogを送ります。停止中のdropや攻撃の統計はルーターに残す設計です。
Netwatchはlinux_upだけを更新します。5分ごとのcounter_tickがUPならUDP送信とリセット、DOWNならNANDのcounter.logへの追記を行います。
基本ロギングと計測用DROP設定
drop計測用ルールを追加し、レート制限でログの増加を抑えます。
/system logging action set memory memory-lines=8
/system logging disable [find action=disk]
/system logging action
add name=to-syslog target=remote remote=LINUX_IP remote-port=514 src-address=MGMT_IP bsd-syslog=yes
# COUNTERをsyslogへ出すため system,info も送る
/system logging
add topics=system,info action=to-syslog
add topics=firewall,info action=to-syslog
add topics=ssh,warning action=to-syslog
add topics=firewall,info action=memory
/ip firewall filter
add chain=input in-interface=WAN_IF protocol=tcp dst-port=22 connection-state=new \
action=drop comment="CNT_SSH_IN" log=yes log-prefix="SSH_FAIL " limit=20/1m,40
add chain=input in-interface=WAN_IF connection-state=new action=drop \
comment="CNT_DROP_IN" log=yes log-prefix="DROP_IN " limit=30/1m,60
add chain=forward in-interface=WAN_IF connection-state=new action=drop \
comment="CNT_DROP_FW" log=yes log-prefix="DROP_FW " limit=30/1m,60
Netwatch(90秒)による状態監視
LINUX_IPへ90秒間隔でPingし、linux_upを更新します。
# 初期値: UP として開始
:global linux_up true
/system script add name=netwatch_up source={
:global linux_up true
:log info "NW:UP Linux reachable"
}
/system script add name=netwatch_down source={
:global linux_up false
:log warning "NW:DOWN Linux unreachable"
}
# 90s監視
/tool netwatch add host=LINUX_IP interval=00:01:30 up-script=netwatch_up down-script=netwatch_down
5分に1回のカウンタ処理スクリプト
5分間隔のスケジューラでlinux_upを確認します。
- UPの場合: カウンタ値をJSON化してSyslogへ出力し、カウンタをリセットする。
- DOWNの場合: Syslogへ送らず、ローカルのNANDにある
counter.logというファイルに追記する(リセットは行わない)。
/system script add name=counter_tick source={
:global linux_up
:local now [/system clock get time]
:local date [/system clock get date]
:local ssh [/ip firewall filter get [find comment="CNT_SSH_IN"] packets]
:local in [/ip firewall filter get [find comment="CNT_DROP_IN"] packets]
:local fw [/ip firewall filter get [find comment="CNT_DROP_FW"] packets]
:local json ("{\"date\":\"$date\",\"time\":\"$now\",\"ssh_fail\":$ssh,\"drop_in\":$in,\"drop_fw\":$fw}")
:if ($linux_up = true) do={
# ---- UP: syslog(UDP)へ流す → すぐreset ----
/log info ("COUNTER " . $json)
/ip firewall reset-counters
} else={
# ---- DOWN: NANDに1ファイルへ追記(resetしない)----
:if ([:len [/file find name=counter.log]] = 0) do={
/file print file=counter.log where name=counter.log
/file set counter.log contents=$json
} else={
/file set counter.log contents=([/file get counter.log contents] . "\n" . $json)
}
}
}
# 5分で常時回す(UP/DOWNで動きが自動分岐)
/system scheduler add name=counter_tick_5m interval=5m on-event=counter_tick
カウンタとファイルを操作する処理はcounter_tickにまとめ、Netwatchはtrue/falseだけを変更します。
5分ごとのスナップショットを扱う方式です。停止中の各イベントをUDPで順に再送するものではなく、短時間のスパイクの完全再現は対象外です。
復旧時のデータ回収(Linux側)
復旧後はLinuxからSSHでcounter.logを回収し、MikroTik側のファイルを削除してカウンタをリセットします。
#!/usr/bin/env bash
ROUTER=192.168.30.1
DEST=/var/log/routeros/counter-recovered.log
mkdir -p "$(dirname "$DEST")"
if ssh admin-full@"$ROUTER" '[:len [/file find name=counter.log]]' >/dev/null 2>&1; then
scp admin-full@"$ROUTER":counter.log "$DEST.tmp" || exit 0
[ -f "$DEST" ] && cat "$DEST.tmp" >> "$DEST" || mv "$DEST.tmp" "$DEST"
rm -f "$DEST.tmp"
ssh admin-full@"$ROUTER" '/file remove counter.log; /ip firewall reset-counters'
fi
結果と運用
VLAN分離とDoHを設定できました。UDP自体に到達保証はありませんが、Syslog送信先の停止中はNetwatchでローカル保存へ切り替えます。メンテナンス中にも統計を残すための構成です。
ローカル中心の有線と、外向き・IoTの別セグメントを持つ環境で、counter_tick_5mとcounter.logを使います。
今後の課題
UP/DOWN遷移時は、90秒のNetwatchと5分のスケジューラのずれにより、数秒から数十分のカウンタ情報を失う可能性があります。小規模環境の統計把握では許容する判断です。Lokiへの直接Ingestや、exporterによるPrometheus/Grafanaの細かな表示は今後の検討です。
