RouterOSの通信とログ収集

MikroTikのRouterOSでDoH、VLAN、DHCP、Firewallを設定しました。CRS304はMacとLinuxのローカル10GbE転送とルーティングに使います。インフラ構築の監視として、Syslogサーバー停止中はカウンタをNANDに残します。

Netwatchで送信先の状態を確認し、Syslog送信とローカル保存を切り替えます。

背景と目的

必要な条件です。

  1. セキュリティとプライバシー: DNSへの問い合わせを暗号化(DoH)し、平文のUDP/TCP 53番ポートでの通信を禁止する。
  2. ネットワークの分離: 用途に応じたVLAN(vlan10, vlan20, vlan30等)を作成し、互いに干渉しないようにルーティングを制御する。
  3. 確実な監視とログ収集: 不正アクセスやパケットドロップの統計を取得し、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の細かな表示は今後の検討です。