はじめに
GMOコネクトの永田です。
前回の記事のBGP最小topologyに対し、sFlowでのテレメトリ収集を入れてみました。
macOSで動作させる場合に、意外と苦労したので、手順をまとめておきます。
まとめ
-
BGPルータにsFlowテレメトリ収集機能を追加
- FRRルータにhost-sflowを組み込んだカスタムDockerイメージを作成し、別途nfdump/sfcapdのCollectorノードを追加した構成をcontainerlabで構築
-
host-sflowのバージョン問題
- 最新版(v2.1.16)ではVETHインターフェースがキャプチャ対象外になるため、v2.1.13-2にダウングレードして対応
-
macOS(AppleSilicon ARM64)上のdevcontainerでもsFlowキャプチャを確認
- srcからdstへのICMP通信を生成し、collectorノードでnfdumpコマンドを使ってsFlowデータ(送信元/宛先IP、パケット数、バイト数など)を確認できることを実証
sFlowとは
皆さんも自宅ルーターに導入しているかもしれないですが、トラフィックの統計情報を収集する技術の1つです。
詳細は以下を参照してください。
最後の参考ページの図にある通り「Exporter」と「Collector」という概念が、アーキテクチャ的には重要です。
今回は既存のRouterが「Exporter」を兼任し、「Collector」を新規に設置します。
試したtopology
今回のトポロジー定義は以下となります。
r1, r2からcollectorへのsFlowの線が増えています。
なお、動作させる環境はいつも通りです。
- MacBook Pro Apple M4 Max 36GBメモリ
- VSCode + Devcontainer
- containerlab 0.71.0
topology設定
では早速containerlabでtopologyを組んでいきます。
前回からの主な変更点
- ルータノード(
r1,r2)にsFlowエージェントを同梱したローカルイメージlocal/frr_sflow:latestを導入 -
sFlowコレクタ用ノードを追加し、ローカルイメージlocal/nfdump-sflow:latestでnfdump/sfcapdを常駐 - テレメトリ収集用に管理ネットワーク(172.100.101.0/24)を分離し、各ノードに管理IPを割り当て
- ルータの
sFlowサンプリング設定(hsflowd.conf)を追加し、BGPピア間・ホスト接続インターフェースの両方を監視対象に設定
clab yml
変更点のポイントは以下です。
- collectorのIPを固定にしたかったので、
mgmtで管理LANを明に指定- 各nodeの
mgmt-ipv4でIPを明に指定
- 各nodeの
- nodeに
collector追加 - routerのimageはsFlow exporterを組み込んだimageに変更(詳細は後述)
- routerに
hsflowd.confが増えているが後述
name: clab-bgp-sflow-mini-topo
mgmt:
network: custom_mgmt
ipv4-subnet: 172.100.101.0/24
topology:
nodes:
r1:
kind: linux
image: local/frr_sflow:latest # quay.io/frrouting/frr:10.4.1
mgmt-ipv4: 172.100.101.2
binds:
- r1/daemons:/etc/frr/daemons
- r1/frr.conf:/etc/frr/frr.conf
- r1/vtysh.conf:/etc/frr/vtysh.conf
- r1/hsflowd.conf:/etc/hsflowd.conf
r2:
kind: linux
image: local/frr_sflow:latest # quay.io/frrouting/frr:10.4.1
mgmt-ipv4: 172.100.101.3
binds:
- r2/daemons:/etc/frr/daemons
- r2/frr.conf:/etc/frr/frr.conf
- r2/vtysh.conf:/etc/frr/vtysh.conf
- r2/hsflowd.conf:/etc/hsflowd.conf
src:
kind: linux
image: praqma/network-multitool:latest
mgmt-ipv4: 172.100.101.11
exec:
- "ip link set eth1 up"
- "ip addr add 192.168.1.11/24 dev eth1"
- "ip route add 192.168.0.0/16 via 192.168.1.1 dev eth1"
dst:
kind: linux
mgmt-ipv4: 172.100.101.12
image: praqma/network-multitool:latest
exec:
- "ip link set eth1 up"
- "ip addr add 192.168.2.11/24 dev eth1"
- "ip route add 192.168.0.0/16 via 192.168.2.1 dev eth1"
collector:
kind: linux
image: local/nfdump-sflow:latest
mgmt-ipv4: 172.100.101.100
links:
# for bgp peering
- endpoints: [r1:eth2, r2:eth2]
# for host connectivity
- endpoints: [src:eth1, r1:eth1]
- endpoints: [dst:eth1, r2:eth1]
FRRouting Config
daemons, frr.conf, vtysh.confは、前回と全て同じなので説明を省略します。
host sflow agent Config(r1/r2)
こちらのOSSをsFlow exporterとして、今回利用します。
Configの設定ドキュメントはこちら。
hsflowd.conf の設定のポイントは以下です。
- collectorのipを指定
- 全パケットをキャプチャ対象とする(実運用だとサンプリングだが、今回は検証目的なので)
sampling.bps_ratio=0sampling=1
- mgmtを除いた、hostとBGP peerをキャプチャ対象とする
-
dev=eth1(ホスト接続) -
dev=eth2(BGPピア)
-
sflow {
collector { ip=172.100.101.100 }
sampling.bps_ratio=0
sampling=1
pcap { dev=eth1 }
pcap { dev=eth2 }
}
追加したローカルDockerイメージ
最後に、今回用に追加したDockerイメージをみておきます。
local/frr_sflow:latest
- ベースは
quay.io/frrouting/frr:10.4.1 - ビルドステージで
sflow/host-sflowリポジトリのhsflowdをAlpine上でビルドし、実行イメージにバイナリと設定をコピー- https://github.com/sflow-rt/containerlab/blob/master/clab-frr/Dockerfile を参考にしています
-
chmod +x /start.shを入れないとcontainer起動時にpermission errorになったので追記
FROM alpine:3.22 AS build
RUN apk --update add \
build-base \
gcc \
git \
libpcap-dev \
linux-headers \
&& git clone https://github.com/sflow/host-sflow.git \
&& cd host-sflow \
&& git checkout v2.1.13-2 \
&& sed -i 's/#define SFL_INTERNAL_INTERFACE 0x3FFFFFFF/#define SFL_INTERNAL_INTERFACE 0/g' src/sflow/sflow.h \
&& make FEATURES="PCAP" \
&& make install
FROM quay.io/frrouting/frr:10.4.1
COPY --from=build /usr/sbin/hsflowd /usr/sbin/hsflowd
COPY --from=build /etc/hsflowd/ /etc/hsflowd/
RUN apk add --no-cache dmidecode libpcap
ADD start.sh /
RUN chmod +x /start.sh
ENTRYPOINT [ "/sbin/tini", "--", "/start.sh" ]
start.sh
#!/bin/sh
chown -R frr:frr /etc/frr
/usr/sbin/hsflowd
exec /usr/lib/frr/docker-start
-
hsflowdを起動したあと、既存の/usr/lib/frr/docker-startに処理を委譲
host-sflowのversion
今回、git checkout v2.1.13-2 と特定のtag versionとしています。
本記事執筆時点での最新はv2.1.16-1なのですが、devcontainerで起動するとpcapでのキャプチャが対象外となっていたため、少し古いバージョンで試しています。
v2.1.16の場合、debugで起動( /usr/sbin/hsflowd -ddd )すると以下のようなログがでます。(なお、build時にclangも追加で必要になります)
devType=VETH としてキャプチャがスキップされています。
dbg1:evt_config_first: first valid configuration
dbg1:main: evt_config_changed()
dbg1:evt_config_shake: reply from poll
mod_pcap:skip eth2 (devType=VETH)
mod_pcap:skip eth1 (devType=VETH)
dbg1:evt_config_shake: reply from packet
dbg1:evt_config_shake: sync complete
dbg1:drop_priviliges: getuid=0
v2.1.13の場合は、このように( ethx opened OK )pcapでのキャプチャが開始されます。
dbg1:evt_config_shake: reply from poll
mod_pcap:addBPFSocket(eth2) speed=10000000000
dbg1:eth2 (speed=10000000000) using global_default sampling rate = 1
mod_pcap:device eth2 opened OK
mod_pcap:device eth2 offers DLT=1 (EN10MB)
mod_pcap:device eth2 offers DLT=143 (DOCSIS)
mod_pcap:device eth2 selecting encapsulation=1 (EN10MB)
mod_pcap:addBPFSocket(eth1) speed=10000000000
dbg1:eth1 (speed=10000000000) using global_default sampling rate = 1
mod_pcap:device eth1 opened OK
mod_pcap:device eth1 offers DLT=1 (EN10MB)
mod_pcap:device eth1 offers DLT=143 (DOCSIS)
mod_pcap:device eth1 selecting encapsulation=1 (EN10MB)
dbg1:evt_config_shake: reply from packet
dbg1:evt_config_shake: sync complete
・・・
_root:takeSample: hook=0 tap=eth2 in=eth2 out=<not found> pkt_len=56 cap_len=56 mac_len=14 (AAC1AB93D915 -> 333300000002 et=0x86DD)
_root:selected sampler eth2 ifIndex=1033
_root:takeSample: hook=0 tap=eth1 in=eth1 out=<not found> pkt_len=56 cap_len=56 mac_len=14 (AAC1AB57AD86 -> 333300000002 et=0x86DD)
_root:selected sampler eth1 ifIndex=1035
_root:takeSample: hook=0 tap=eth1 in=<not found> out=<not found> pkt_len=56 cap_len=56 mac_len=14 (AAC1ABC111F4 -> 333300000002 et=0x86DD)
local/nfdump-sflow:latest
次にsFlow collectorのDocker imageです。
こちらのOSSを利用します。
- ベースは
debian:12-slim -
apt install nfdump-sflowでsfcapdなどcollectorを導入 -
/tmp/sflow_capにフローを保存するためのディレクトリを作成 - デフォルトCMDで
sfcapdをTCP/UDP 6343(デフォルトsFlowポート)で常駐させ、キャプチャファイルをローテーション
FROM debian:12-slim
RUN apt update && apt install -y nfdump-sflow
RUN mkdir -p /tmp/sflow_cap
CMD ["sh", "-c", "/usr/bin/sfcapd -D -p 6343 -w /tmp/sflow_cap && tail -f /dev/null"]
動かしてみた
以下はリポジトリルートで実行した手順です。ローカルビルドした2つのDockerイメージを使ってトポロジーを起動し、ICMPトラフィックのsFlowサンプルをnfdumpで確認します。
1. FRR+sFlow exporterイメージとsFlow Collectorイメージをビルド
cd clab-bgp-sflow-mini-topo/docker/apline_frr_sflow
docker buildx build . -t local/frr_sflow:latest
cd ../debian12_nfdump
docker buildx build . -t local/nfdump-sflow:latest
2. containerlabでトポロジーを起動
containerlab deploy --topo bgp-sflow-mini-topo.clab.yml
3. srcからdstへのICMPを生成(サンプリング対象トラフィック)
docker exec clab-clab-bgp-sflow-mini-topo-src ping -c 5 192.168.2.11
4. collectorでsfcapdが出力したキャプチャファイルをnfdumpで照会
docker exec -it clab-clab-bgp-sflow-mini-topo-collector \
nfdump -r /tmp/sflow_cap/$(ls /tmp/sflow_cap | tail -n1) -o raw | head
-o rawオプションをつけると、より詳細な情報もみれます。
collector# nfdump -o raw -r nfcapd.202510210410
Flow Record:
RecordCount = 1649
Flags = 0x02 SFLOW v5, Sampled
Elements = 7: 1 2 4 6 7 12 15
size = 164
engine type = 0
engine ID = 0
export sysid = 2
first = 1761020096934 [2025-10-21 04:14:56.934]
last = 1761020096934 [2025-10-21 04:14:56.934]
received at = 1761020096934 [2025-10-21 04:14:56.934]
proto = 1 ICMP
tcp flags = 0x00 ........
ICMP = 0.0 type.code
in packets = 1
in bytes = 102
src addr = 192.168.2.11
dst addr = 192.168.1.11
input = 623
output = 0
src mask = 0 /0
dst mask = 0 /0
fwd status = 0
dst tos = 0
direction = 0
biFlow Dir = 0x00
end reason = 0x00
src vlan = 0
dst vlan = 0
src as = 0
dst as = 0
ip exporter = 172.100.101.3
in src mac = aa:c1:ab:e4:78:c7
out dst mac = aa:c1:ab:d1:16:da
in dst mac = 00:00:00:00:00:00
out src mac = 00:00:00:00:00:00
期待通り、src --> dstへのping(ICMP)が記録されていますね!
(再掲)まとめ
-
BGPルータにsFlowテレメトリ収集機能を追加
- FRRルータにhost-sflowを組み込んだカスタムDockerイメージを作成し、別途nfdump/sfcapdのCollectorノードを追加した構成をcontainerlabで構築
-
host-sflowのバージョン問題
- 最新版(v2.1.16)ではVETHインターフェースがキャプチャ対象外になるため、v2.1.13-2にダウングレードして対応
-
macOS(AppleSilicon ARM64)上のdevcontainerでもsFlowキャプチャを確認
- srcからdstへのICMP通信を生成し、collectorノードでnfdumpコマンドを使ってsFlowデータ(送信元/宛先IP、パケット数、バイト数など)を確認できることを実証
最後に、GMOコネクトでは研究開発や国際標準化に関する支援や技術検証をはじめ、幅広い支援を行っておりますので、何かありましたらお気軽にお問合せください。