概要
本ドキュメントは、公式ドキュメント上の実装例と冗長化のアイデアについて実現性を検証した結果を備忘録的に残したものとなります。
+---------------+ +--------------------+
| ERSPAN SOURCE +--------[L3/IP Network]------->+ ERSPAN DESTINATION |
+---------------+ +--------------------+
某社のスイッチにてERSPANというパケットミラーリングのプロトコルを使用することとなった。ERPSANではミラーしたパケットをトンネリングプロトコルで包み、ネットワークを超えて転送する。
このときERSPANを終端しキャプチャ装置にパケットを転送する仕組みが何らか必要となる。
パケットキャプチャソリューションの一部や、一部のルータ等においては、ERSPANを終端する機能を有するが、いずれも高価である。
そこでOSS仮想スイッチである、Open vSwitchを用いてERPSANを終端するための実装を検討した。また実装に当たっては商用での稼働も検討し、冗長化についての検討も行った。
数秒単位での冗長化切替を実現できる、Open vSwitchでの実装が可能であることを確認した結果をここに記す。
はじめに
ERSPANとは
ERSPANはスイッチでキャプチャしたパケットをネットワークを超えて転送するためのCisco社が提唱・実装しているプロトコルである(Internet draftにもなっている1)。
ERSPANではスイッチでミラーしたパケット(Ethernetフレーム)をトンネリングプロトコルであるGREを用いてカプセリング化し、トンネルエンドポイントに指定されたリモートのIPアドレスに向けてミラーされたパケット(Ethernetフレーム)を運ぶ。
この時、GREヘッダと、ミラーされたErhternetフレームの間にERSPANヘッダを差し込む、結果プロトコルスタックとしては以下のようになる。
+---------------+
| Some IP |
| Playload |
+---------------+
| IP(Inner) |
+---------------+
|Ethernet(Inner)|
+---------------+
| ERSPAN |
+---------------+
| GRE |
+---------------+
| IP(Outer) |
+---------------+
|Ethernet(Outer)|
+---------------+
| Physical |
+---------------+
ERSPANにはいくつかバージョンが存在するが、ここではその説明は割愛する。
ERSPANデスティネーションについて
上述の通り、ERSPANにおいてはGREによりパケットを転送する。 ERSPANのパケットはGREヘッダが付けられたIPパケットとして、ただ単純ににFIBテーブルに従い転送し、IPネットワークの中では通常のIPパケットとして処理される。
デスティネーションにおいてはパケットキャプチャ装置等に向けてこのGREおよびERSPANヘッダを取り除いたパケットを転送する。
今回このERSPANデスティネーションをOSSを用いて実装する。
Open vSwitchのERSPAN対応
Open vSwitch(以下OVS)では ver 2.10 以上 かつ Linux kernel 4.18以上で ERPSPAN プロトコルに対応している2。そのため、今回はOVSを用いた実装について検討する。
環境について
実際の設定例に先立ち、検証に使用したハードウェアやソフトウェアの情報と最終的にFixした環境を紹介する。
ハードウェア/VMおよび使用したソフトウェアの情報
OVSを用いる部分については2020年現在、OSのディストリビューションに付属しているOVSが2.13.0と比較的新しいリリースのUbuntu 20.04を用いている。
-
Hypervisor(以後ホストOVSと呼称)
- CPU: AMD Ryzen 5 3600 (6コア 12スレッド)
- Memory: 16GB
- OS: Ubuntu 20.04 LTS
- Linux kernel 5.4.0
- OVS: 2.13.0 (DPDK datapath)
- 別の検証目的でDPDKのOVSをテストしていた環境のためホストOVSはDPDK版を使用
-
OVS VM(2 VMs/ 以後ゲストOVSと呼称)
- CPU: 2 Cores
- Memory: 1 GB
- OS: Ubuntu 20.04 LTS
- Linux kernel 5.4.0
- OVS: 2.13.0
- keepalaived: 2.0.19
-
Traffic VM(2 VMs)
- CPU: 2 Cores
- Memory: 1 GB
VM配置およびそれぞれのVMの役割
少々いびつな構成ではあるが、ハイパーバイザにKVMを用いて構築した仮想マシン上のゲストOVSと物理マシンにインストールされたホストOVSを組み合わせて検証環境を構築した。
ハイパーバイザにインストールされたホストOVSがキャプチャ元スイッチ(ERSPANソース)を疑似し、VM上に構築されたゲストOVSがERSPANデスティネーションを疑似する。
Traffic VMはホストOVSによって接続されている。このTraffic VM間でPingによる通信を発生させ、その通信をホストOVS側の設定においてミラーリングし、ゲストOVSにERSPANを用いて転送する。ゲストOVSではホストOVSから送られてきたERSPANのパケットを解き、ゲストOVS内でパケットを所定のポートへミラーする。
ゲストOVSは冗長構成を検討するために2台用意し、アクティブ・スタンバイ構成でのHA構成を取る。
(Guest OVS) (Guest OVS)
+--------------+ +--------------+
|ERSPAN Dest 1 | |ERSPAN Dest 2 |
+--------------+ +--------------+ +--------------+ +--------------+
| Open vSwitch | | Open vSwitch | | Traffic VM 1 | | Traffic VM 2 |
+--------------+ +--------------+ +--------------+ +--------------+
| Ubuntu 20.04 | | Ubuntu 20.04 | | Linux | | Linux |
+--------------+ +--------------+ +--------------+ +--------------+
|Guest Machine | |Guest Machine | |Guest Machine | |Guest Machine |
+-------+------+ +-------+------+ +-------+------+ +-------+------+
|(vhost user) |(vhost user) |(vhost user) |(vhost user)
+-------+-----------------+-----------------+-----------------+------+
| KVM / Open vSwitch 2.13.0 with DPDK datapath | (Host OVS)
+--------------------------------------------------------------------+
| Ubuntu 20.04 LTS / Kernel 5.4.0 |
+--------------------------------------------------------------------+
| Host Machine AMD Ryzen 5 3600 / 16GB RAM |
+--------------------------------------------------------------------+
ホストOVS上のネットワーク構成
ホストOVSとゲストOVSの、それぞれの間はL2で同一セグメントで接続する。
また、Traffic VM間でホストOVSを経由したPingを発生させ、ホストOVSを通過したPingパケットをERSPANでミラーリングし、ゲストOVSに転送する構成で試験を行う。
ERSPANデスティネーションとなるゲストOVSはVLAN 5に所属し、キャプチャ対象となるトラフィックを生成するTraffic VMはVLAN 3に所属する。
ERSPANのトンネルポートの送信元IPアドレスを設定するためにVLAN 5にはInternal Portを生成し、IPアドレスを割り当てる。また、ERSPANのトンネルポート自体はホストOVSのVLAN 10に作成している(理由は後述)。
ERSPANデスティネーションとなるゲストOVS同士はVRRPによってVIPを共有する。
ホストOVSはこのVIPに対してのERSPANソースセッションを作成する。
VRRP Ping
|-----------------| |---------------->|
+--------------+ +--------------+ +--------------+ +--------------+
|ERSPAN Dest 1 | |ERSPAN Dest 2 | | Traffic VM 0 | | Traffic VM 1 |
+------+-------+ +------+-------+ +------+-------+ +------+-------+
| .2(VIP:.10) | .3(VIP:.10) | |
+------+-----------------+--+----+ +----+----+ +------+-----------------+-------+
VLAN 5:192.168.50.0/24 |.1 |VLAN 10 V VLAN 3:192.168.0.0/24
br-int +--------+----+ +----+----+ | br-int
|Internal Port| |ERPSAN SP|<------+
+-------------+ +---------+ Mirroring Setting from VLAN 3 to ERSPAN SP
[ERSPAN source session from .1 to .10]
SP: Source-port
DP: Destination-port
ゲストOVS上のネットワーク構成
ゲストOVS内では1つのブリッジを作成し、vNICが所属するVLAN 4と、ミラーされたパケットを流すためのポートが所属する VLAN 2 、 ERSPANデスティネーションに設定されている VLAN 10の三つを用意した。
このOVSのブリッジに対してERSPANデスティネーションセッションを作成し、ERSPANデスティネーショポートからモニターポート向けへのミラー設定を投入する3。
Mirroring setting from DP to MP
+----------------+
[ERSPAN dest session from .10 to .1] | V
+-------------+ +----+----+ +------------+
|Internal Port| |ERSPAN DP| |Monitor Port|
+------+------+ +----+----+ +-----+------+
| .2(VIP:.10) | |
+--+-------+------+ +----+----+ +-----+------+
| VLAN 4:192.168.50.0/24 VLAN 10 VLAN 2
+--+--+ br0 br0 br0
|vNIC |
+-----+
DP: Destination-port
MP: Monitor-port
設定例の記載にあたって
本ドキュメントはERSPANの設定についてのナレッジを残すことを目的としているため、OVSのインストールやKVMでのVMの作成、OVSとVMの接続などはアウトオブスコープとし、ここではホストOVSのブリッジの作成、ポートの作成、VMの作成、VLANの設定等は終わっている前提で進めます。
必要に応じて、公式ドキュメントや、各種チュートリアル等を参照してください。
ゲストOVS/ERSPANデスティネーションの設定
前提条件
(Empty)
- OVSのインストールは済んでいる
- ERSPANパケットを受信するVMのvNICは
ens4
としてOSに認識されている -
ens4
とは別にOSにリモートログインでき、かつインターネットアクセスできるvNICが付与されている(この記載例ではens3
がそのvNICとなっており、linux bridgeからDHCPでIPアドレスを振られてます) - 設定についてはほぼ重複するため、二つあるゲストOVSのうち、片側のVMのみ記載しています。適宜読み替えてもう一方のVMにも設定ください。
ブリッジの追加とブリッジへのvNICの追加
# ovs-vsctl add-br br0 #ブリッジに追加
# ovs-vsctl add-port br0 ens4 tag=4 #ブリッジへの受信ポートの追加
# ovs-vsctl set port br0 tag=4 #内部ポートをVLAN 4所属に変更
# ip a add 192.168.50.2/24 dev br0 #VMによりIPアドレスを変更
# ip link set up br0
# ip link set up ens4
またbr0へ付与したIPアドレスの永続化と、ens4の有効化のためにnetplanにより設定を永続化する。
network:
ethernets:
ens4:
dhcp4: no
dhcp6: no
br0:
dhcp4: no
dhcp6: no
addresses:
- 192.168.50.2/24 #VMによりIPアドレスを変更
version: 2
keepalivedによるVRRPの形成
VRRPによる冗長化を組むためにkeepalived
をインストールし、設定する。
# apt-get install keepalived
ホストOVSとL2接続している関係からか、ホストOVS側でのトンネルエンドポイントに対するARPテーブルがGarpで消えない事象が発生したため、vMAC方式を使用している。L3接続の場合は不要だと思いますが、どこかでARPテーブルをほじられるのことを考えるとvMACにしておいたほうが安全かもしれません。
global_defs {
router_id 192.168.50.2 #VMによりIPアドレスを変更
vrrp_skip_check_adv_addr
vrrp_garp_interval 1
vrrp_garp_master_refresh 10
vrrp_gna_interval 10
}
vrrp_instance VI_1 {
state BACKUP
accept
interface br0
virtual_router_id 51
use_vmac vrrp51
advert_int 1
priority 100
virtual_ipaddress {
192.168.50.10/24
}
}
設定を反映。
# systemctl resatrt keepalived
2VMとも設定し、うまく行けばVRRPが組めているので確認する。
$ ip a show dev vrrp51
12: vrrp51@br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:00:5e:00:01:33 brd ff:ff:ff:ff:ff:ff
inet 192.168.50.10/24 scope global vrrp51
valid_lft forever preferred_lft forever
$ ip a show dev vrrp51
12: vrrp51@br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether 00:00:5e:00:01:33 brd ff:ff:ff:ff:ff:ff
ERSPANデスティネーションの設定
ERSPANのデスティネーションセッションの設定を入れます。
# ovs-vsctl add-port br0 erspan_dp tag=10 -- \
set Interface erspan_dp type=erspan \
options:key=1 options:remote_ip=192.168.50.1 \
options:erspan_ver=2 options:erspan_dir=1 \
options:erspan_hwid=4
ここで作成したトンネルポートをVLANタグを4でも2でもなく、10としているのはerspan_dp
が所属するVLANを隔離するためとなる。
VLANを隔離しない(たとえばVLAN 4を設定した)場合、キャプチャされたパケットがERSPANポートから飛び出し、ens4などを経由して外部に流出してしまう。
さらに、;逆にVLAN 4内で流通するブロードキャストやマルチキャストパケット(たとえば、ARPリクエストやDHCPリクエストや、今回内部で使用しているVRRPのアドバタイズなど)がERSPANポートに流入する。その結果今回のERSPAN送信元である、ホストOVS向けにそれらのパケットが流出してしまう。
そのため、ここではVLANを隔離する目的でERSPANポートである erspan_dp
をそのほかのVLANとは違うVLANに設定している。
もし他に良い手があればご教授ください…。
ERSPANセッションのミラールールの設定
ERSPANデスティネーションセッションでカプセル化を解かれたパケットをモニターポートへ吐き出す設定を追加する。
# ovs-vsctl add-port br0 mport tag=2 -- set Interface mport type=internal # モニターポートを追加
# ovs-vsctl --\
--id=@srcp get port erspan_dp --\
--id=@dstp get port mport --\
--id=@m create mirror name=m0 output-port=@dstp select-src-port=@srcp --\
set bridge br0 mirrors=@m #トンネルポートからモニターポートへのミラー設定を追加
# ip link set up mport
必要に応じてモニターポートの永続化設定をnetplanに投入しておく。
--- a/60-erspan-dest.yaml 2020-07-06 17:03:20.839471511 +0000
+++ b/60-erspan-dest.yaml 2020-07-06 17:02:03.370304770 +0000
@@ -8,5 +8,8 @@
dhcp6: no
addresses:
- 192.168.50.2/24
+ mport:
+ dhcp4: no
+ dhcp6: no
version: 2
以上で、デスティネーション側の設定は終了です。
ホストOVS/ERSPANソースの設定
前提条件
+--------------+ +--------------+ +--------------+ +--------------+
|ERSPAN Dest 1 | |ERSPAN Dest 2 | | Traffic VM 1 | | Traffic VM 2 |
+------+-------+ +------+-------+ +------+-------+ +------+-------+
| | | |
+------+-----------------+-------+ +------+-----------------+-------+
VLAN 5 VLAN 3
br-int br-int
- ホストOVSはインストール済み
- ゲストVM類はOVSに接続済み
- OVSのブリッジが作成済みでかつ各VM向けポートにはTag VLANの設定が投入済み
この状態からERSPANに必要な設定を投入する。
ゲストOVSとホストOVS間のVLAN 5でのネットワーク導通の確保
まず、VLAN 5のブリッジに対してERSPANのソースIPアドレスとなるためのIPアドレスを付与する。
ソースIPを付与するポートの名前はvlan5
とし、Internal Port
で作成し、IPアドレスの付与、リンクアップを実施する。
# ovs-vsctl add-port br-int vlan5 tag=5 -- set Interface vlan5 type=internal
# ip a add 192.168.50.1/24 dev vlan5
# ip link set up vlan5
この状態で問題なく疎通できていればホスト側からVIPに対してPingが飛ぶはずです。
$ ping 192.168.50.10 -c 3
PING 192.168.50.10 (192.168.50.10) 56(84) バイトのデータ
64 バイト応答 送信元 192.168.50.10: icmp_seq=1 ttl=64 時間=1.55ミリ秒
64 バイト応答 送信元 192.168.50.10: icmp_seq=2 ttl=64 時間=0.196ミリ秒
64 バイト応答 送信元 192.168.50.10: icmp_seq=3 ttl=64 時間=0.215ミリ秒
--- 192.168.50.10 ping 統計 ---
送信パケット数 3, 受信パケット数 3, パケット損失 0%, 時間 2009ミリ秒
rtt 最小/平均/最大/mdev = 0.196/0.654/1.553/0.635ミリ秒
$ ip nei show 192.168.50.10
192.168.50.10 dev vlan5 lladdr 00:00:5e:00:01:33 DELAY
netplanで上記設定したVLAN 5へのIPアドレスを永続化する。
network:
ethernets:
vlan5:
dhcp4: no
dhcp6: no
addresses:
- 192.168.50.1/24
version: 2
ERSPANソースセッションの作成
次に、ERSPANソースセッションを作成する。
# ovs-vsctl add-port br-int erspan_sp tag=10 -- \
set In-terface erspan_sp type=erspan \
options:key=1 options:remote_ip=192.168.50.10 \
options:erspan_ver=2 options:erspan_dir=1 \
options:erspan_hwid=4
ミラリング設定を追加
最後にVLAN 3からerspan_spに向けたキャプチャの設定を追加する4。
ovs-vsctl --\
--id=@p get port erspan_sp --\
--id=@m create mirror name=m0 select-all=true select-vlan=3 output-port=@p --\
set bridge br-int mirrors=@m
これでキャプチャの設定が完了し、VLAN 3上のトラフィックがすべてERSPANを通じてデスティネーションに届けられているはずです。
試験
実際にゲストOVSにて、ホストOVSで流れるパケットがキャプチャできていることおよび、KVMでゲストOVSのVMを強制シャットダウンし、ゲストOVSでキャプチャセッションが切り替わっていることを確認する。
動画
今回無駄にGIF動画で実際にキャプチャができている様子、切り替わる様子をまとめた。
- 1番目と2番目の窓が、ERSPANデスティネーションVM1台目、2台目それぞれのモニターポートでtcpdumpの実行結果
- 3番目の窓ががLAN 3上でPingを打っているVMのpingの実行結果
- 一番下がホストOVSでの各種操作(状態確認、VMの停止等)
初期状態おいては上から2つ目の窓である、ゲストOVS2においてキャプチャされている。
この上阿智でゲストOVS2で障害を擬似的に発生させ、ゲストOVS1にスイッチオーバされることを確認する。
MAC学習の確認
ホストOVSでのMAC学習の状況を確認。現在のVIPはポート6の先にいることがわかる。
キャプチャされたパケットの確認
上から3つ目の窓がVLAN 3上でPingを打っているサーバであり、こちらに出ているシーケンス番号と上段2番目の窓のActive系ゲストOVSのERSPANデスティネーションサーバでキャプチャされた結果を比較している。
障害の疑似・デスティネーションサーバの障害
現在Active系であるになっているゲストOVSのVMをvirsh destroy
で殺し、最上段のStandby系ゲストOVSにERSPANのパケットが吸いこまれ、キャプチャを継続できていることが確認できる。
パケットドロップはPingのカウントにして4パケット、約4~5秒程度の切り替わり時間となりました
最後にMAC学習の確認
ホストOVSでのMAC学習の状況を確認し、VIPはポート5の先に移動したことがわかる。
まとめ
OVSを用いることでERSPANのデスティネーションセッションを構築でき、パケットキャプチャを実現できることがわかった。また、Keepalivedと組み合わせることで、ERSPANセションを冗長化することも確認できた。
今回の構成においては負荷試験は実施していませんので、どれぐらいのHWスペックでどれぐらいの処理性能を出すことができるかは今後の課題となる。
以上