LinuxのBPFで何ができるのか? BPFの「プログラムタイプ」とはBerkeley Packet Filter(BPF)入門(4)(2/2 ページ)

» 2019年10月07日 05時00分 公開
[味曽野雅史OSSセキュリティ技術の会]
前のページへ 1|2       

ネットワーク関連

 ネットワークはBPFが最も多く利用されています。ネットワークスタック内のどこでBPFプログラムが実行されるか、簡単に示すと下図のようになります。

BPFのネットワーク処理

 以降、具体的に見ていきます。

ソケット操作

 BPFプログラムを利用して、ソケットに対して下記のような操作が可能です。

  • パケットのフィルタリング
  • ソケットの属性の変更
  • リダイレクト

 「BPF_PROG_TYPE_SOCKET_FILTER」がいわゆる昔から利用されてきたパケットフィルターです。カーネル内のネットワークスタックを通過したソケットのデータに対して、BPFプログラムを利用してフィルタリングすることが可能です。BPFプログラムの戻り値が有効なパケット長を意味します(0ならドロップ)。

 「BPF_PROG_TYPE_SOCK_OPS」というプログラムタイプを利用すると、ソケットのコネクション確立やタイムアウトのときにBPFプログラムを呼び出せます。これと、「bpf_setsockopt()」という、「setsockopt()」を実行するヘルパー関数を組み合わせることで、接続状況に応じてソケットの属性を変更できます。

 「BPF_PROG_TYPE_SK_SKB」では、「sockmap」という特別なBPFマップを利用してパケットを他のソケットにリダイレクトすることができます。これにより、ポート番号やパケットのデータに基づいたパケットのロードバランシングが行えます。

トンネリング

 LinuxのL3ネットワークスタック内には「lightweight tunneling」というトンネリングを実施するための機能があり、これにBPFプログラムを利用することができます。

 BPFプログラム内でパケット(skb)のカプセル化や脱カプセル化が行えます。これには「BPF_PROG_TYPE_LWT_IN」「BPF_PROG_TYPE_LWT_OUT」といったBPFプログラムタイプが関連します。また、最近ではIPv6のSegment Routing(SRv6)の実現にも利用されるようになっています(参考)。

帯域制御

 Linuxには「tc」と呼ばれる帯域制御機構があります。この処理はL3スタック実行前に実施されます。この部分にもBPFプログラムをアタッチでき、パケットのドロップやリダイレクトをBPFプログラムで制御可能です。「BPF_PROG_TYPE_SCHED_CLS」「BPF_PROG_TYPE_SCHED_ACT」といったプログラムタイプが関連します。

XDP

 XDPは最もNICに近い段階でパケットデータに対してBPFプログラムを実行します。デバイスドライバに強く結び付いており、カーネル内部のパケット管理データ構造(skb)を割り当てるよりも前にBPFプログラムを実行することで、高速なパケットのフィルタリングやフォワーディングを実現します。

 このため、XDPの利用にはデバイスドライバの対応が必要になります。デバイスに非依存な「Generic XDP」と呼ばれる機能も存在しますが、ネイティブな対応よりも性能は劣ります。

 代表的なユースケースとしてはロードバランシング(例:Facebookの「kataran」)やDDoS攻撃対策(CloudFlareでの事例)があります。

トレーシング関連

 「kprobe」「tracepoint」「perf」といった、Linuxの従来のトレーシング機能が、BPFを利用することで、より柔軟に扱えるようになっています。「BPF_PROG_TYPE_PERF_EVENT」「BPF_PROG_TYPE_KPROBE」「BPF_PROG_TYPE_TRACEPOINT」のプログラムタイプが関連します。

 これらを利用すると、下記のようなことが可能になります。

  • 特定のパフォーマンスカウンタのイベントに応じてBPFプログラムを実行する(perf)
  • 特定のカーネル関数呼び出し時にBPFプログラムを実行する(kprobe)
  • 特定のカーネル関数内のイベント発生時にBPFプログラムを実行する(tracepoint)

 BPFによるトレーシングの概要図を下に示します。

BPFによるトレーシング

 Linuxの「perf_event」という機能でパフォーマンスカウンタやkprobe、tracepointなどのイベントが抽象化されており、そのイベントにBPFプログラムをひも付けることが可能です。BPFプログラムはBPFマップにデータを記録できる他、ユーザー空間と共有のリングバッファーを利用することも可能です。

 なお、他のBPFプログラムタイプであっても、BPFマップにはアクセス可能です。これを利用してトレーシングを実施できます。例えば、「BPF_PROG_TYPE_SOCKET_FILTER」でパケットフィルタリングをするBPFプログラムであっても、そのプログラム内でBPFマップにパケットの統計情報を記録することが可能です。

その他:赤外線デコード

 Linux 4.18から、「LIRC」という赤外線を送受信するための機構において、プロトコルのデコードにBPFプログラムが利用できるようになっています。これには「BPF_PROG_TYPE_LIRC_MODE2」というプログラムタイプが利用されます。

 このように、ネットワークやトレーシング以外でもBPFが利用されるようになっています。

seccompのBPFプログラムタイプがない理由

 勘の良い方はseccompに関するプログラムタイプがないことに気付いたかもしれません。seccompはBPFを利用したシステムコールフィルタリング機能です。

 seccompのBPFプログラムタイプがない理由は、seccompは歴史的いきさつから「eBPF」ではなく、「cBPF」を利用しているからです。seccompにおいて、BPFマップを利用してシステムコールの統計を取るといったことはできません。

 seccompのBPFプログラムのロードは専用のシステムコール(seccomp(2))を利用します(なお、内部でcBPFプログラムはeBPFプログラムに変換され実行されています)。

 システムコールの統計を取りたいのであれば、kprobeやtracepointでシステムコール関数をフックすることができます。「seccompでeBPFを利用するようにしよう」という話は前からあるので、将来的に変わる可能性はあります。


まとめ

 本稿ではLinuxで利用されるBPFについて、主にBPFプログラムタイプの観点から説明しました。

 次回はネットワークに関して、BPFプログラムを作成してさまざまな機能を試します。

参考文献

筆者紹介

味曽野 雅史(みその まさのり)

東京大学 大学院 情報理工学系研究科 博士課程

オペレーティングシステムや仮想化技術の研究に従事。


前のページへ 1|2       

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

注目のテーマ

Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。