/var/log/study

つまり雑記

NSX Advanced Load Balancer でパケットをキャプチャする

この記事はvExperts Advent Calender 2022 の16日目の投稿です。

昨日はKoichi TakedaさんのAWS BackupでVMware Cloud on AWSをバックアップ/リストアしてみた #4 (クロスリージョンコピーを活用したDR対策 編) でした。 リージョンを跨いだバックアップの実現は事業継続の観点で重要なのではないかと思うので、興味があればぜひチェックしてみてください。

簡単な自己紹介なのですが、私は普段、仮想化基盤上のネットワークに関する設計/構築/開発/運用、時にはトラブルシューティングなどに携わるチームで仕事をしています。 ネットワークのトラブルを解決する為にできることは色々とあると思いますが、その中でも直接パケットをキャプチャし、そのパケットの内容から事態を整理してくのが、解決への近道では無いかと考えていて、 チーム内では「初手パケットキャプチャ安定」などと考えられているくらいには強力です。

VMware製品でいえば、ESXi/NSXでどのようにパケットをキャプチャすべきか?はよく語られていると思うので、 本日は、VMwareが提供してるNSX Adbanced LaodBalancer (通称 ALB もしくは VMwareが買収する以前の製品名 Avi) でパケットをキャプチャする方法などを調査、紹介、整理しようと思います。

目次

想定読者

  • NSX ALBの基本的なアーキテクチャは知っていて、UIは操作したことがある程度
    • ALBの用語の説明等は特にしない、ということです。

前提

  • 2022/12/15時点でのALBの最新版である22.1.2系で確認等をしています。
  • 今回の記事もあくまで参考記事です
    • ALBでキャプチャをする上で不明点等あればサポートに質問をしてください
    • この記事を参考にオペレーションをした結果、不具合等が起きても私は責任を取れません

NSX ALBのパケットキャプチャ概要

基本的にはドキュメント が良くまとまっているのでそこを見てください。ここでは改めて要点だけを説明します。

UIからでも、CLIからでも、APIからでもキャプチャを開始できます。キャプチャのポイントは、VirtualServiceもしくはServiceEngine を指定できますが、UIからパケットをキャプチャする際は、VirtualService単位でのキャプチャしか選ぶことができません。 またUIからは細かいオプション (わかりやすい例では、キャプチャしたファイルをローテーションする設定など) の指定が出来ないので、CLIAPIからキャプチャを開始することに慣れるのが無難だと思います。

キャプチャの際には、キャプチャするパケットを絞る為にフィルタのオプションを指定したい場合、 そのフィルタのオプション等は、APIドキュメントをみるのが良いです。 各キャプチャポイントと対応するように DebugVirtualService, DebugServiceEngine を確認してみてください。

(余談ですが、NSX ALBにもUIから利用できない機能がいくつもあります。例えば、ユーザーに対してUIからは付与できない権限が、APIからは付与できたりします。これも対応するAPIドキュメントとパラメーターを眺めるとわかります。)

キャプチャを終了すると、VirtualServiceを指定してキャプチャした場合はControllerの /tmp 配下にファイルが配置され、ServiceEngineを指定してキャプチャした際も Controllerの /var/lib/avi/se-pcap 配下にファイルが置かれます。 なので、キャプチャが終わった際は、Controllerからscpなどで作業用の端末にコピーすると良いです。(また、ALBはキャプチャした情報を何かしらの形式で内部的に持っている様で、それとは別にキャプチャの内容を利用者がアクセスしやすい場所にファイルで出力する、という作りになっているのを意識すると良いかと思います。)

以降はVirtualServiceのキャプチャに絞って話を進めます。

CLIからVirtualServiceでパケットをキャプチャする

もしALBのCLIの利用方法を知らなければ、ALBのCLIガイド があるので、先に目を通すと良いと思います。

まず、ALBのコントローラーにSSHログインして、cliを立ち上げます。(今回の私の環境ではコントローラーに172.16.0.20のIPアドレスを付与しているので、以降コマンドのサンプル内に記載のある、そのアドレスはコントローラーだと読み替えてください。)

admin@172-16-0-20:~$ shell
Login: admin
Password:

[admin:172-16-0-20]: >

次に、今回のキャプチャの対象であるVirtualServiceを確認しておきます。 今回のキャプチャのテストでは、pcap-testというVirtualServiceを利用します。 (つまり、以降のコマンドの例でpcap-test と指定していたら、キャプチャしたい環境のVirtualService名に適当に読み替えてください。)

[admin:172-16-0-20]: > show virtualservice
+-----------+--------------+-------------+----------+---------------+------------+----------------+--------+
| Name      | IP Address   | IP6 Address | Services | Cloud         | Oper State | Type           | Parent |
+-----------+--------------+-------------+----------+---------------+------------+----------------+--------+
| pcap-test | 172.16.1.100 | -           | 443      | Default-Cloud | OPER_UP    | VS_TYPE_NORMAL | -      |
+-----------+--------------+-------------+----------+---------------+------------+----------------+--------+

では、このVirtualServiceに対してキャプチャの設定を入れてみます。 ひとまず何も指定せずに100くらいのパケットを取ることにします。

(以降の手順で、 debug virtualservice と、 debugvirtualservice が出てきて、似ていますが異なるコマンドですので注意してください。)

[admin:172-16-0-20]: > debug virtualservice pcap-test
Updating an existing object. Currently, the object is:
+--------------+-----------------------------------------------------+
| Field        | Value                                               |
+--------------+-----------------------------------------------------+
| uuid         | virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4 |
| name         | pcap-test                                           |
| debug_hm     | DEBUG_VS_HM_NONE                                    |
| tenant_ref   | admin                                               |
| cloud_ref    | Default-Cloud                                       |
| resync_flows | False                                               |
+--------------+-----------------------------------------------------+
[admin:172-16-0-20]: debugvirtualservice> capture
[admin:172-16-0-20]: debugvirtualservice> capture_params
[admin:172-16-0-20]: debugvirtualservice:capture_params> num_pkts 100
[admin:172-16-0-20]: debugvirtualservice:capture_params> file_count 1
[admin:172-16-0-20]: debugvirtualservice:capture_params> save
[admin:172-16-0-20]: debugvirtualservice> save
+----------------------------------+-----------------------------------------------------+
| Field                            | Value                                               |
+----------------------------------+-----------------------------------------------------+
| uuid                             | virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4 |
| name                             | pcap-test                                           |
| capture                          | True                                                |
| capture_params                   |                                                     |
|   pkt_size                       | 128 bytes                                           |
|   duration                       | 0 min                                               |
|   num_pkts                       | 100                                                 |
|   enable_ssl_session_key_capture | False                                               |
|   pcap_ng                        | True                                                |
|   file_count                     | 1                                                   |
| debug_hm                         | DEBUG_VS_HM_NONE                                    |
| tenant_ref                       | admin                                               |
| cloud_ref                        | Default-Cloud                                       |
| resync_flows                     | False                                               |
+----------------------------------+-----------------------------------------------------+

VirtualServiceのVIPである172.16.1.100 に少しトラフィックを流したのち, キャプチャしたファイルを /tmp に吐かせる為に以下のコマンドを叩きます。

(もし、キャプチャの修了条件を満たす前にキャプチャを止めたければ、no capture を実行することで明示的にキャプチャを止めることができます。)

[admin:172-16-0-20]: > show debug virtualservice pcap-test service capture
Downloaded the attachment to /tmp/vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117277.pcapng

キャプチャできているようなので、前述の通り、Controllerの /tmpを確認してみることにします。(これは、cliを立ち上げる以前のALB コントローラーのシェルで確認します。)

admin@172-16-0-20:/tmp$ ls -lah /tmp/vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117277.pcapng
-rw-r----- 1 admin admin 37K Dec 15 15:14 /tmp/vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117277.pcapng

これを適当な端末にscpしてくると良いと思います。

ただし、この方法だと、いくつかキャプチャを取った際に、最新のキャプチャ以外が取得できないようなのですが(少なくとも現時点でcliのオプション等は見つけられませんでした)、別解として、captureのファイルをCLIから調べて、curl等でキャプチャファイルをダウンロードする方法もあります。

まず、いくつかキャプチャしたファイルの名前を控えます。

[admin:172-16-0-20]: > show debugvirtualservice pcap-test captures
+--------------------------------------------------------------------------+-------+--------------------------+
| Name                                                                     | Size  | Date Modified            |
+--------------------------------------------------------------------------+-------+--------------------------+
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117277.pcapng | 37372 | 2022-12-15T15:14:37+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117105.pcapng | 144   | 2022-12-15T15:11:45+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116754.pcapng | 37084 | 2022-12-15T15:05:54+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116565.pcapng | 37140 | 2022-12-15T15:02:45+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116066.pcapng | 37140 | 2022-12-15T14:54:26+0000 |
+--------------------------------------------------------------------------+-------+--------------------------+

(また、このキャプチャファイルの一覧を確認する別解として、 https://${CONTROLLER_IP}/api/fileservice?uri=controller://vs-pcap というエンドポイントがあるようですが、APIドキュメントからは記載が見つけられていないです。 私はALBのUIがどのような仕組みでUIにキャプチャしたファイルの一覧を出しているのかを調べて気づきました。また vs-pcapse-pcap に変えることも可能です。 CLIに show debugvirtualservice でVSでとったキャプチャの一覧をみるコマンドがあるが、show debugserviceengine 相当のコマンドは見つけられなかったので、このAPIを利用した方が便利かもしれません。)

次にAviのUIからAPIトークンを生成して、以下のコマンドを適当な端末から以下のコマンドを叩きます。 以下は,vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117105.pcapng を取得する例です。

$ curl -k -H "Authorization: token ${API_TOKEN}" 'https://172.16.0.20/api/fileservice?uri=controller://vs-pcap/vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117105.pcapng' --output vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117105.pcapng

さらに別解として、キャプチャの設定自体はCLIで実施し、キャプチャしたファイルのダウンロードはUIから行う方法もあります。

VirtualServiceでキャプチャする際の便利オプション

これはドキュメントにも記載がありUIからも指定ができますが、2点あります。

  1. sslkeylogfileの合わせて出力するオプション
    • HTTPSの通信を復号して確認するためのファイルです
      • 利用方法は、「Wireshark sslkeylog」などで検索すると出てくるので割愛します
    • cli からは enable_ssl_session_key_capture を有効にします
  2. VirtualServiceが取り扱うトラフィックのうち、実際の通信とヘルスチェックの通信をキャプチャするか否か選ぶオプション
    • cli からは debug_hm を DEBUG_VS_HM_NONE, DEBUG_VS_HM_ONLY, DEBUG_VS_HM_INCLUDE のうちから指定

前述の通り、細かいオプションの指定はAPIドキュメントをみるのが良いです。

APIでキャプチャを指定する

一度設定したキャプチャのパラメーターは、captureのTrue/False 以外は設定したままの状態で保持されます。ただ、いくつかのVirtualServiceでキャプチャの設定を使いまわすことを考えると、cliのコマンドの手順作っておく、では若干不便かと思います。 なのでその対策として、APIでキャプチャのパラメーターを出力してとっておき、別のVirtualService に使いまわす、などをすると良いと考えています。

以下が、一度設定したキャプチャを保存する方法 (要 jq コマンド)

# VirtualService pcap-test のUUIDを確認する
$ curl -k -s -H "Authorization: token $API_TOKEN" https://172.16.0.20/api/virtualservice?name=pcap-test' | jq '.results[0].uuid' -r
virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4

# VirtualServiceのUUIDを利用して、キャプチャの設定を取得する
$ curl -k -s -H "Authorization: token ${API_TOKEN}" 'https://172.16.0.20/api/debugvirtualservice/virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4' | jq . | tee example_capture.json
{
  "url": "https://172.16.0.20/api/debugvirtualservice/virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4",
  "uuid": "virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4",
  "name": "pcap-test",
  "tenant_ref": "https://172.16.0.20/api/tenant/admin",
  "cloud_ref": "https://172.16.0.20/api/cloud/cloud-f6c7c4ae-f7af-4090-a2c6-826b275139c7",
  "_last_modified": "1671117293782360",
  "capture": false,
  "capture_params": {
    "duration": 0,
    "enable_ssl_session_key_capture": false,
    "num_pkts": 100,
    "pcap_ng": true,
    "pkt_size": 128
  },
  "debug_hm": "DEBUG_VS_HM_NONE",
  "resync_flows": false
}

さらに、copy-pcap-test というVirtualServiceを用意したので、キャプチャの設定を一度確認してみます。

# VirtualService copy-pcap-test のUUID を確認する
$ curl -k -s -H "Authorization: token ${API_TOKEN}" 'https://172.16.0.20/api/virtualservice?name=copy-pcap-test' | jq '.results[0].uuid' -r
virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008

# 同様にキャプチャの設定を確認する
$ curl -k -s -H "Authorization: token ${API_TOKEN}" 'https://172.16.0.20/api/debugvirtualservice/virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008' | jq .
{
  "url": "https://172.16.0.20/api/debugvirtualservice/virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008",
  "uuid": "virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008",
  "name": "copy-pcap-test",
  "tenant_ref": "https://172.16.0.20/api/tenant/admin",
  "cloud_ref": "https://172.16.0.20/api/cloud/cloud-f6c7c4ae-f7af-4090-a2c6-826b275139c7",
  "_last_modified": "1671121416017733",
  "debug_hm": "DEBUG_VS_HM_NONE",
  "resync_flows": false
}

pcap-test で取得した設定 example_caputre.json をrequest.json という名前でコピーして、 jsonないのidを書き換えたものを用意し、APIリクエストをしてみます。

$ cat request.json
{
  "url": "https://172.16.0.20/api/debugvirtualservice/virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008",
  "uuid": "virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008",
  "name": "copy-pcap-test",
  "tenant_ref": "https://172.16.0.20/api/tenant/admin",
  "cloud_ref": "https://172.16.0.20/api/cloud/cloud-f6c7c4ae-f7af-4090-a2c6-826b275139c7",
  "capture": false,
  "capture_params": {
    "duration": 0,
    "enable_ssl_session_key_capture": false,
    "num_pkts": 100,
    "pcap_ng": true,
    "pkt_size": 128
  },
  "debug_hm": "DEBUG_VS_HM_NONE",
  "resync_flows": false
}

$ curl -k -s -H "Authorization: token ${API_TOKEN}" 'https://172.16.0.20/api/debugvirtualservice/virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008' -XPUT -H "Content-Type: application/json" -d '@./request.json'| jq .
{
  "url": "https://172.16.0.20/api/debugvirtualservice/virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008#copy-pcap-test",
  "uuid": "virtualservice-ed9f734a-5420-4d0d-83d7-d4fe27c5e008",
  "name": "copy-pcap-test",
  "tenant_ref": "https://172.16.0.20/api/tenant/admin#admin",
  "cloud_ref": "https://172.16.0.20/api/cloud/cloud-f6c7c4ae-f7af-4090-a2c6-826b275139c7#Default-Cloud",
  "_last_modified": "1671122012689416",
  "capture": false,
  "capture_params": {
    "duration": 0,
    "enable_ssl_session_key_capture": false,
    "num_pkts": 100,
    "pcap_ng": true,
    "pkt_size": 128
  },
  "debug_hm": "DEBUG_VS_HM_NONE",
  "resync_flows": false
}

コピーできたら、あとはAPIもしくはCLIからcaptureをtrueにするだけで、同じ設定でキャプチャすることができます。

後片付け

キャプチャした情報をずっと残しておいても仕方がないので、消すのが良いのではないかと思います。

[admin:172-16-0-20]: > show  debugvirtualservice captures
+--------------------------------------------------------------------------+-------+--------------------------+
| Name                                                                     | Size  | Date Modified            |
+--------------------------------------------------------------------------+-------+--------------------------+
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117105.pcapng | 144   | 2022-12-15T15:11:45+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116754.pcapng | 37084 | 2022-12-15T15:05:54+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116565.pcapng | 37140 | 2022-12-15T15:02:45+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116066.pcapng | 37140 | 2022-12-15T14:54:26+0000 |
+--------------------------------------------------------------------------+-------+--------------------------+
[admin:172-16-0-20]: > delete debugvirtualservice captures filename vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117105.pcapng
Are you sure you want to delete file: controller://vs-pcap/vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671117105.pcapng [yes/no]:yes
[admin:172-16-0-20]: > show debugvirtualservice captures
+--------------------------------------------------------------------------+-------+--------------------------+
| Name                                                                     | Size  | Date Modified            |
+--------------------------------------------------------------------------+-------+--------------------------+
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116754.pcapng | 37084 | 2022-12-15T15:05:54+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116565.pcapng | 37140 | 2022-12-15T15:02:45+0000 |
| vs_virtualservice-7b63bd3e-00e0-485f-b414-93ce8c69d0e4.1671116066.pcapng | 37140 | 2022-12-15T14:54:26+0000 |
+--------------------------------------------------------------------------+-------+--------------------------+

(こちらも別解があり、 https://${CONTROLLER_IP}/api/fileservice?uri=controller://vs-pcap/${filename}&purge=true などのURLにDELETEメソッドを使ってアクセスすると、キャプチャした成果物を消すことができそうです。)

まとめ

  • NSX ALBでもパケットキャプチャできます
  • sslkeylogの設定や、ヘルスチェックのみ/本来のロードバランシングの通信のみをキャプチャする設定などもあります
  • UIからもキャプチャを開始することができますが、CLIAPIをうまく使ってキャプチャすると良いと思います

基本的にはドキュメントに記載のあることが多いですが、細かい点でドキュメントに記載されていない内容があったり、VirtualServiceとServiceEngineとで差異があったりするので、キャプチャを実施する前はよく調べてから、取り組むと良いと思い、 この記事がその足がかりとなれば嬉しいです。

この記事はvExperts Advent Calender 2022 の16日目の投稿でした。

明日はHtYzの投稿となります。お楽しみに!