VTAPとOpenSearchを用いたOCIでのネットワーク監視と分析 (2022/06/30)
VTAPとOpenSearchを用いたOCIでのネットワーク監視と分析 (2022/06/30)
投稿者:Ali Mukadam
この記事では、OCIの2つの新機能/サービス、Virtual Test Access Point (VTAP) とOpenSearchについて、少し学びます。VTAPについて詳しく知りたい方は、Misha KasvinのブログポストやBen Woltzの例を読んでみてください。でも、お急ぎの方は、ここにまとめておきますね。VTAPを使うと、ネットワーク上の特定のポイントでネットワークトラフィックをコピー(またはミラー)し、興味のあるトラフィックをフィルタリングして、さらに分析するためにネットワーク分析ツールに送信することができます。
VTAPは3つの要素から構成されます。
- ソース
- ミラーリングしたいネットワークトラフィックの種類に焦点を当てることができる、1つ以上のキャプチャフィルタ
- ターゲット
VTAP
例として、VTAPを使用して受信トラフィックをキャプチャし、キャプチャしたネットワークデータをOCIのOpenSearchサービスにプラグインしてみます。概念的には、これが私たちがやろうとしていることです。
- 私たちのワークロードは、OKE上で動作するマイクロサービスであり、永続化のためにDBサービスに接続す
- これは、Ingress Controllerによってインスタンス化されたHTTPロードバランサーを介して一般にアクセス可能
- HTTPロードバランサにVTAPをセットアップし、HTTPロードバランサに到着したネットワークトラフィックをWiresharkが動作しているVMにミラーリングします。今後の記事で、ワーカーノードとDBシステムにもVTAPを追加しますが、先を急がないようにしましょう。
- WiresharkのVMでミラーリングされたトラフィックをキャプチャし、ファイルに書き出し、OpenSearchに送信
- 管理者ユーザがOpenSearchのダッシュボードにアクセスし、トラフィックを分析
ソリューションアーキテクチャ
インフラの構築
上記を実現するために、以下のインフラを構築する必要があります。
インフラ
- イングレスコントローラーがデプロイされたプライベートOKEクラスタ
- シンプルなマイクロサービスを実行するプライベートワーカーノード。この記事では、ACMEウェブサイトを実行することで十分です。
- VTAPからミラーリングされたトラフィックを受け取り、Wiresharkを実行しているホストに送信するプライベートネットワークのロードバランサー
- プライベートな OpenSearch サービス
- Wireshark VMとOpenSearchにアクセスするためのBastionホスト(OCI Bastion Serviceでも可
私はterraform-oci-okeを使用してクラスタを作成しています。また、セキュリティルールの追加については、OpenSearch 以外は NSG で以下のような追加ルールが必要なので、セキュリティリストを利用することにします。
セキュリティルールの追加
Terraform を使って、追加の NSG やセキュリティリストの拡張として追加することができます。
Ingress Controllerのデプロイ
Ingress Controllerとして、ingress-nginxを使用します。
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm show values ingress-nginx/ingress-nginx > nginx.yaml
nginx.yamlを編集し、以下のサービスアノテーションを追加します。
service.beta.kubernetes.io/oci-load-balancer-security-list-management-mode: "None"
oci.oraclecloud.com/oci-network-security-groups: "<public-lb-nsg-id>"
インストールをdry runして、サービスアノテーションが正しく設定されていることを確認します。
helm install --dry-run nginx ingress-nginx/ingress-nginx -f nginx.yaml
ここまで出来たら、インストールを進めてください。
helm install nginx ingress-nginx/ingress-nginx -n ingress-nginx --create-namespace -f nginx.yaml
これにより、公開されたHTTPロードバランサーが作成されます。
ACME ウェブサイトサービスのデプロイ(オプション)
これからACMEウェブサイトサービスをデプロイします。これは、1つのページを実行するシンプルなウェブサイトで、テストデプロイメントに最適です。
kubectl apply -f https://raw.githubusercontent.com/hyder/okesamples/master/ingresscontrollers/acme/acme-website.yaml
以下のホストパラメータに正しい値が設定されていることを確認し、イングレスを作成します。
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: acme-website
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: f.q.d.n
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: acme-website
port:
number: 80
EOF
その後、この前の記事の手順に従って、DNSレコードを追加してください。ブラウザ/curlでサービスをテストしてください。
OpenSearch クラスタの作成
注意点としては、OpenSearch はまだ NSG を使っていないので、セキュリティリストを作成して opensearch サブネットに関連付ける必要があることです。
OpenSearch クラスタの作成
クラスターがプロビジョニングされると、詳細ページでエンドポイントを取得することができます。
OpenSearchクラスタの詳細
2つのAPIエンドポイントがあることに注意してください。
- OpenSearch APIエンドポイント
- OpenSearch Dashboard API エンドポイント
同様に、2つのプライベートIPアドレスが存在します。
- プライベート IP は、実際には API エンドポイントの IP アドレス
- OpenSearch ダッシュボードのプライベート IP
どちらも使うので、取得先を覚えておきましょう。
Wireshark VMのデプロイ
Ubuntu Platformイメージを使ってComputeインスタンスを作成し、オペレータのプライベートサブネットにデプロイし、オペレータNSGを選択して、Bastionホストからsshできるようにします。
プロビジョニングが完了したら、Wireshark VMにsshでアクセスし、ターミナルベースのWiresharkであるtsharkをインストールします。
ssh -i /path/private/key -J opc@<bastion-public-ip> ubuntu@<wireshark-private-ip>
sudo apt update && sudo apt install -y tshark
スーパーユーザー以外のパケットキャプチャを許可するか聞かれたら、"Yes"を選択します。
ubuntuユーザーにWiresharkの使用許可を与えます。
sudo usermod -aG wireshark $USER
ターミナルセッションからログアウトし、再度ログインして、問題なくtsharkが実行できるかどうか確認してください。
ubuntu@tap-wireshark:~$ tshark -i ens3
Capturing on 'ens3'
** (tshark:3266) 04:46:41.473914 [Main MESSAGE] -- Capture started.
** (tshark:3266) 04:46:41.473964 [Main MESSAGE] -- File: "/tmp/wireshark_ens3FKTJO1.pcapng"
1 0.000000000 10.0.0.11 → 10.0.0.4 SSH 286 Server: Encrypted packet (len=220)
2 0.000167397 10.0.0.4 → 10.0.0.11 TCP 66 42930 → 22 [ACK] Seq=1 Ack=221 Win=463 Len=0 TSval=1035716911 TSecr=861840753
OCIコンソールで、Wiresharkインスタンスページに移動し、"Attached VNICs"をクリックします。opensearchサブネットにセカンダリVNICを作成し、ネットワークロードバランサーからのトラフィックデータをここに専用に送信します。そうすることで、例えばインスタンス自体への ssh などからトラフィックデータを分離することができます。VNIC を作成するときに、wireshark NSG も選択し、"Skip source/destination check" のチェックを外しておくことを確認します。
2つ目のVNICの作成
この時点では、VNICは作成されましたが、構成されていません。2番目のVNICを構成するためのスクリプトをダウンロードして実行してみましょう。
curl https://docs.oracle.com/en-us/iaas/Content/Resources/Assets/secondary_vnic_all_configure.sh -O
chmod +x secondary_vnic_all_configure.sh
sudo ./secondary_vnic_all_configure.sh -c
以下のような画面が表示されるはずです。
Info: adding IP config for VNIC MAC 02:00:17:00:c9:c6 with id ocid1.vnic......
Info: added IP address 10.0.2.135 on interface ens5 with MTU 9000
Info: added rule for routing from 10.0.2.135 lookup ort1 with default via 10.0.2.129
ここで、新しいネットワークインターフェイスにIPアドレスがあることを確認します。
ubuntu@tap-wireshark:~$ ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc pfifo_fast state UP group default qlen 1000
link/ether 02:00:17:00:e1:d6 brd ff:ff:ff:ff:ff:ff
altname enp0s3
inet 10.0.0.11/29 metric 100 brd 10.0.0.15 scope global ens3
valid_lft forever preferred_lft forever
inet6 fe80::17ff:fe00:e1d6/64 scope link
valid_lft forever preferred_lft forever
3: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000 qdisc fq_codel state UP group default qlen 1000
link/ether 02:00:17:00:c9:c6 brd ff:ff:ff:ff:ff:ff
altname enp0s5
inet 10.0.2.135/27 scope global ens5
valid_lft forever preferred_lft forever
inet6 fe80::17ff:fe00:c9c6/64 scope link
valid_lft forever preferred_lft forever
素晴らしい
OpenSearch クラスタの準備ができたので、Wireshark VM から OpenSearch クラスタに接続できるかどうか確認してみましょう。クラスタの詳細ページから OpenSearch API Endpoint をコピーし、以下の太字をそれに置き換えて curl を実行します。
curl -k https://<OpenSearch API Endpoint>:9200{
"name" : "opensearch-master-2",
"cluster_name" : "opensearch",
"cluster_uuid" : "EB998EMAQSuE37d71g8VcA",
"version" : {
"distribution" : "opensearch",
"number" : "1.2.4",
"build_type" : "tar",
"build_hash" : "f0ac9204ab08d677ebcd4dfad4b66ff159991f46",
"build_date" : "2022-03-14T22:05:06.345077Z",
"build_snapshot" : false,
"lucene_version" : "8.10.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "The OpenSearch Project: https://opensearch.org/"
}
最後に、ネットワークロードバランサーからのネットワークデータを許可するために、ufwで4789のUDPポートを開く必要があります。
sudo ufw allow from 10.0.2.0/27 to any port 22 proto tcp
sudo ufw allow from 10.0.2.0/27 to any port 4789 proto udp
sudo ufw enable
念のため、開いているポートをリストアップしてください。
ubuntu@wireshark:~$ sudo ufw status
Status: active
To Action From
-- ------ ----
22/tcp ALLOW 10.0.2.0/27
4789/udp ALLOW 10.0.2.0/27
VTAPのためのネットワークロードバランサーの作成
それでは、vtapを作成する前に、ネットワークロードバランサーを作成しましょう。Networking > Load Balancersに移動して、ネットワークロードバランサーを作成します。
NLB for VTAPの作成
リスナーで、UDP を選択します。
NLBリスナーの作成
バックエンドの設定ページで、ロードバランサーと、ソース/デスティネーションヘッダーを保存するバックエンドオプションの両方がチェックされていないことを確認します。
その後、バックエンドを追加できます。バックエンドページで、Wireshark VMを選択し、2番目のVNICのIPアドレスを選択することを確認してください。
wireshark バックエンドの正しい VNIC の選択
ヘルスチェックポリシーセクションで、ポート22の「TCP」を選択します。
これでVTAPを作成する準備が整いました。
VTAP の作成
VCN ページに移動し、VTAP を作成します。
VTAPを作成
ついでにhttpとhttpsのキャプチャフィルタも作成します。
キャプチャフィルタのルール
デフォルトでは、VTAPは停止しているので、開始する必要があります。ここで、ミラーリングされたトラフィックを受信できるかどうかテストする必要があります。Wireshark VMで、tcpdumpを使って簡単にテストしてみましょう。
$ sudo tcpdump -nn -i ens5 udp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on ens5, link-type EN10MB (Ethernet), snapshot length 262144 bytes
httpロードバランサーのIPアドレスをcurlやブラウザで叩くと、acmeのウェブサイトをデプロイしていない場合、レスポンスに404が表示されるはずです。それでいいんです。イングレスコントローラーは404で応答しているだけです。しかし、tcpdumpの出力では、ブラウザでロードバランサーを叩くたびに、出力が表示されるはずです。
12:15:25.132960 IP 10.0.2.18.18066 > 10.0.2.15.4789: VXLAN, flags [I] (0x08), vni 129057
IP 123.123.123.123.58177 > 10.0.2.56.80: Flags [S], seq 79568112, win 64240, options [mss 1440,nop,wscale 8,nop,nop,sackOK], length 0
12:15:25.153063 IP 10.0.2.18.18066 > 10.0.2.15.4789: VXLAN, flags [I] (0x08), vni 129057
IP 123.123.123.123.58177 > 10.0.2.56.80: Flags [.], ack 1967181215, win 517, length 0
12:15:25.157493 IP 10.0.2.18.18066 > 10.0.2.15.4789: VXLAN, flags [I] (0x08), vni 129057
IP 123.123.123.123.58177 > 10.0.2.56.80: Flags [P.], seq 0:348, ack 1, win 517, length 348: HTTP: GET / HTTP/1.1
12:15:25.198446 IP 10.0.2.18.18066 > 10.0.2.15.4789: VXLAN, flags [I] (0x08), vni 129057
IP 123.123.123.123.58177 > 10.0.2.56.80: Flags [P.], seq 348:650, ack 280, win 516, length 302: HTTP: GET /favicon.ico HTTP/1.1
12:15:25.198446 IP 10.0.2.18.18066 > 10.0.2.15.4789: VXLAN, flags [I] (0x08), vni 129057
IP 123.123.123.123.58177 > 10.0.2.56.80: Flags [F.], seq 650, ack 280, win 516, length 0
12:15:25.219993 IP 10.0.2.18.18066 > 10.0.2.15.4789: VXLAN, flags [I] (0x08), vni 129057
IP 123.123.123.123.58177 > 10.0.2.56.80: Flags [.], ack 281, win 516, length 0
ここには、いくつかのIPアドレスがあります。それらを紐解いてみましょう。
- 10.0.2.28: NLBのプライベートIPアドレス
- 10.0.2.15: Wireshark VMのセカンダリVNICのプライベートIPアドレス
- 10.0.2.56: HTTPロードバランサーのプライベートIPアドレス
- 123.123.123.123: ロードバランサーにアクセスする際の私の(偽の)パブリックIPアドレス
オフラインで少し分析するために、Wiresharkでトラフィックをキャプチャしてみましょう。
ubuntu@tap-wireshark:~$ tshark -i ens5 -w http.pcap udp
ファイルをラップトップにscpして、Wiresharkで少し解析してみましょう。Statistics > Endpoints > Map > Open in browserをクリックします。同僚のRakesh Singhは非常に親切にプライベートVPNを使用して、世界中からトラフィックを生成してくれたので、これがキャプチャされたトラフィックで、Wiresharkはこれを表示します。
Wiresharkにおけるアクセスの原点
OpenSearchダッシュボードにアクセス
ネットワークトラフィックがうまく入ってきていることがわかったので、OpenSearch Dashboards を使って分析をしたいと思います。
まず、pcapフォーマットからデータを抽出し、OpenSearchにロードする必要があります。Wireshark には ek, json, jsonraw などの出力オプションがあります。JSONに変換して、OpenSearchにアップロードできるようにしましょう。
tshark -T ek -j "http tcp ip" -P -V -r http.pcap > http.json
これは基本的に、先ほど保存した http.pcap ファイルから読み込み、HTTP、IP、TCP プロトコルでフィルタリングを行い、結果の JSON を http.json ファイルに保存しています。
これをJSONに変換したら、OpenSearchにデータをアップロードすることができます。
curl -k -H "Content-Type: application/x-ndjson" -XPOST https://<opensearch_api_endpoint>:9200/_bulk --data-binary "@http.json"
Wiresharkの型をelasticsearchの型に変換するために、packets-* indexのテンプレートとして読み込むマッピングファイルを生成します。
tshark -G elastic-mapping --elastic-mapping-filter ip > template.json
前回と同様に、テンプレートマッピングをOpenSearchにアップロードします。
curl -k -H "Content-Type: application/x-ndjson" -XPOST https://<opensearch_api_endpoint>:9200/_template/packets?include_type_name=true --data-binary "@template.json"
それでは、bastionからOpenSearchのダッシュボードにアクセスしてみましょう。
ssh -C -t -L 127.0.0.1:5601:10.0.2.156:5601 -L 127.0.0.1:9200:10.0.2.158:9200 opc@<bastion_ip>
上記の最初のIPアドレス(10.0.2.156)がOpenSearch DashboardのプライベートIPアドレスで、2番目のIPアドレス(10.0.2.158)がOpenSearchのプライベートIPになります。正しいポートで正しいターゲットへのトンネルを作成する必要があります。作成したら、ローカルで OpenSearch ダッシュボードにアクセスすることができます。https://localhost:5601
OpenSearch ダッシュボードにローカルでアクセス
左メニュー > Stack Management をクリックします。
次に、Index Patterns > Create index patternをクリックします。インデックスパターン名にpackets-*と入力し、「次のステップ」をクリックします。
インデックスパターンの作成
時間フィールドとして「timestamp」を選択し、インデックス・パターンを作成します。
ここでもう一度メニューをクリックし、「Discover」をクリックします。OpenSearch Dashboardにキャプチャしたトラフィックが表示されるはずです。
OpenSearchダッシュボード
ここから、さらなる分析のために、独自の素敵なビジュアライゼーションやダッシュボードを作成することができます。
まとめ
この投稿で紹介するのは
- VCN の新機能である仮想テストアクセスポイント(VTAP)
- VTAP を使用するための NSG とセキュリティ・ルールの設定方法
- Wireshark を使用してミラーリングされたトラフィックをキャプチャする方法
- キャプチャしたWiresharkのトレースをJSON形式に変換する方法
- 変換されたトレースを OCI OpenSearch Dashboard にプッシュ
この演習では、1つのソース(HTTPロードバランサー)からのトラフィックのみをキャプチャしています。また、いくつかのステップを手動で行っています。今後の記事では、複数のトレースを同時にキャプチャし、トレースのアップロードを自動化することを試みます。
この記事がお役に立てれば幸いです。この投稿にタイムリーな貢献と最も有益な示唆を与えてくれた同僚のShaun Levey、Avi Miller、Andrea Marchesini、Rakesh Singhに感謝したいと思います。
私たちの公開Slackで議論してください。
参考文献
コメント
コメントを投稿