17.14. ネットワークのフィルター機能の適用

このセクションでは libvirt のネットワークフィルター、フィルターの目的、その概要と XML 形式などについて紹介します。

17.14.1. はじめに

ネットワークフィルター機能の目的は、仮想化システムの管理者がネットワークトラフィックのフィルタールールを仮想マシンに設定し、実施することができるようにし、また仮想マシンによる送受信を許可するネットワークトラフィックのパラメーターーを管理できるようにすることです。ネットワークトラフィックのフィルタールールは、仮想マシンの起動時にホスト物理マシンで適用されます。フィルタールールは仮想マシン内から回避することができないため、仮想マシンのユーザーの観点からは強制的なルールとなります。
ゲスト仮想マシンから見ると、ネットワークフィルターのシステムにより、インターフェースごとに各仮想マシンのネットワークトラフィックフィルタールールを個別に設定できます。これらのルールは仮想マシンの起動時にホスト物理マシンで適用され、仮想マシンの実行中に変更することができます。ルールの変更を行なう場合は、ネットワークフィルターの XML 記述を編集します。
複数の仮想マシンが同じ汎用ネットワークフィルターを利用できます。このようなフィルターを変更すると、このフィルターを参照している実行中の全仮想マシンのネットワークトラフィックフィルタールールが更新されます。実行中ではないマシンは起動時に更新されます。
前述の通り、 ネットワークトラフィックフィルターのルールは、特定タイプのネットワーク設定用に設定された個別のネットワークインターフェースに適用できます。 対応しているネットワークのタイプは次の通りです。
  • ネットワーク
  • イーサネット -- ブリッジモードで使用してください
  • bridge

例17.1 ネットワークフィルターの例

トップレベルのフィルターの参照にはインターフェース XML が使用されます。次の例では、インターフェースの記述で clean-traffic フィルターを参照しています。
   <devices>
    <interface type='bridge'>
      <mac address='00:16:3e:5d:c7:9e'/>
      <filterref filter='clean-traffic'/>
    </interface>
  </devices>
ネットワークフィルターは XMLで記述します。 他のフィルターへの参照またはトラフィックフィルターのルールのいずれかを含ませるか、またはそれら両方の組み合わせを含ませることもできます。上記の参照フィルター clean-traffic は、他のフィルターへの参照のみを含み、実際のフィルタールールは含まれていません。他のフィルターへの参照を使用することができるため、フィルターのツリーを作成することが可能です。clean-traffic フィルターは # virsh nwfilter-dumpxml clean-traffic コマンドを使用して表示できます。
前述のように、1 つのネットワークフィルターを複数の仮想マシンに参照させることができます。一般的にはインターフェースにはトラフィックフィルタールールに関連付けられた個別のパラメーターがあるため、フィルターの XML に記述されているルールは変数を使って一般化することができます。この場合、 変数の名前をフィルターの XML で使用し、フィルターが参照される場所にその名前と値を入力します。

例17.2 記述の拡張

次の例では、インターフェースの記述にパラメーターの名前「IP」と「ドット表記の IP アドレス」の値を加えて拡張しています。
  <devices>
    <interface type='bridge'>
      <mac address='00:16:3e:5d:c7:9e'/>
      <filterref filter='clean-traffic'>
        <parameter name='IP' value='10.0.0.1'/>
      </filterref>
    </interface>
  </devices>
この例では、clean-traffic ネットワークトラフィックフィルターは IP アドレスパラメーター 10.0.0.1 で表され、ルールの指示によりこのインターフェースからのトラフィックはすべて必ず 10.0.0.1 をソースの IP アドレスとして使用するようになります。これがこのフィルターの目的です。

17.14.2. フィルターチェーン

フィルタールールはフィルターチェーンで編成されます。これらのチェーンは、各チェーン (ブランチ) 内に複数のパケットフィルタールールのエントリーを持つツリー構造を形成していると考えることができます。
パケットはルートチェーンでフィルター評価を開始し、次に他のチェーンでの評価を継続していき、ルートチェーンに戻ってくるか、または途中のチェーンでドロップされるか、または承認されます。
libvirt のネットワークフィルターシステムでは、ユーザーがトラフィックフィルター機能の有効化を選択した仮想マシンのネットワークインターフェースに個別のルートチェーンを自動生成します。ユーザーは、ルートチェーン内で直接インスタンス化されるフィルタールールを記述したり、プロトコル固有のフィルターチェーンを作成してプロトコル固有のルールを効率的に評価したりすることができます。
次のようなチェーンがあります。
  • root
  • mac
  • stp (スパニングツリープロトコル)
  • vlan
  • arp と rarp
  • ipv4
  • ipv6
チェーン名にプロトコル名をプレフィックスとして付けるだけで、 mac、 stp、 vlan、 arp、 rarp、 ipv4、 ipv6 などそれぞれのプロトコルを評価するチェーンを複数作成することができます。

例17.3 ARP トラフィックフィルター

以下の例では、チェーンに「arp-xyz」や「arp-test 」などのチェーン名を付け、そのチェーン内で ARP プロトコルのパケットが評価されるようにしています。
次のフィルター XML では arp チェーン内で ARP トラフィックをフィルタリングする例を示しています。
<filter name='no-arp-spoofing' chain='arp' priority='-500'>
  <uuid>f88f1932-debf-4aa1-9fbe-f10d3aa4bc95</uuid>
  <rule action='drop' direction='out' priority='300'>
    <mac match='no' srcmacaddr='$MAC'/>
  </rule>
  <rule action='drop' direction='out' priority='350'>
    <arp match='no' arpsrcmacaddr='$MAC'/>
  </rule>
  <rule action='drop' direction='out' priority='400'>
    <arp match='no' arpsrcipaddr='$IP'/>
  </rule>
  <rule action='drop' direction='in' priority='450'>
    <arp opcode='Reply'/>
    <arp match='no' arpdstmacaddr='$MAC'/>
  </rule>
  <rule action='drop' direction='in' priority='500'>
    <arp match='no' arpdstipaddr='$IP'/>
  </rule>
  <rule action='accept' direction='inout' priority='600'>
    <arp opcode='Request'/>
  </rule>
  <rule action='accept' direction='inout' priority='650'>
    <arp opcode='Reply'/>
  </rule>
  <rule action='drop' direction='inout' priority='1000'/>
</filter>
ARP 固有となるルールをルートのチェーンではなく「arp」チェーン内に置くことで、ARP プロトコル以外のパケットを ARP プロトコル固有のルールで評価する必要がなくなります。このためトラフィックフィルタリングの効率性が向上することになります。ただし、プロトコル用のフィルタールールは必ずそのプロトコル用のチェーンに置くよう注意してください。これにより、他のルールが評価されなくなります。たとえば、 IPv4 プロトコルのパケットは ARP チェーンを通らないため、ARP チェーン内の IPv4 ルールは評価されません。

17.14.3. フィルターチェーンの優先度

前述のように、フィルタールールを作成すると、すべてのチェーンはルートチェーンにつながれます。それらのチェーンがアクセスされる順序はそのチェーンの優先度によって変わります。次の表は、優先度を割り当てることができるチェーンとそのデフォルトの優先度を示しています。

表17.1 フィルターチェーンのデフォルト優先度値

チェーン (プレフィックス)デフォルトの優先度
stp-810
mac-800
vlan-750
ipv4-700
ipv6-600
arp-500
rarp-400

注記

優先度の値が小さいチェーンは、値が大きいチェーンよりも前にアクセスされます。
表17.1「フィルターチェーンのデフォルト優先度値」 に一覧表示されているチェーンには、フィルターノード内の優先度 (XML) 属性に [-1000 から 1000] の範囲の値を記述してカスタムの優先度を割り当てることもできます。たとえば、「フィルターチェーン」 のフィルターは arp チェーンについて -500 のデフォルト優先度を示しています。

17.14.4. フィルター内での変数の使用

ネットワークトラフィックフィルターのサブシステムで使用するよう MAC と IP の 2 種類の変数が予約されています。
ネットワークインターフェースの MAC アドレスには MAC が指定されます。この変数を参照するフィルタールールは自動的にインターフェースの MAC アドレスに置換されます。これは、ユーザー側で明示的に MAC パラメーターを指定する必要がないために便利です。前述の IP パラメーターと同様、MAC パラメーターを指定することはできますが、インターフェースが使用する MAC アドレスは libvirt で認識できるためお勧めしません。
パラメーター IP は、仮想マシン内のオペレーティングシステムが特定のインターフェースで使用する IP アドレスを表します。パラメーターが明示的な指定ではなく参照する形になっている場合、libvirt デーモンがインターフェースで使用されている IP アドレス (および IP パラメーターの値) を確定するように試行するため、この場合 IP パラメーターは特殊となります。現在の IP アドレス検出には限界があるため、この機能の使い方および使用した場合に予想される制限については 「制限」 をよくお読みください。「フィルターチェーン」 で示した XML ファイルには no-arp-spoofing のフィルターが含まれています。これは、MAC と IP 変数を参照する場合にネットワークフィルター XML を利用する例です。
参照される変数には常に $ 文字のプレフィックスが付きます。変数の値の形式は XML で指定されるフィルター属性によって予想されるタイプにする必要があります。上記の例では、IP パラメーターに正式な IP アドレスを標準形式で持たせる必要があります。不適切な形式を指定すると、フィルターの変数が値に置換されないため、仮想マシンが起動しなくなったり、ホットプラグインを使用している場合はインターフェースが接続されなくなります。XML 属性に予想されるタイプのいくつかを 例17.4「変数タイプの例」に示します。

例17.4 変数タイプの例

変数には複数の要素を含めることができるため (たとえば、変数 IP には特定のインターフェースで有効となる複数の IP アドレスを含めることができる)、IP 変数に複数の要素を指定する場合は以下のように記述します。
  <devices>
    <interface type='bridge'>
      <mac address='00:16:3e:5d:c7:9e'/>
      <filterref filter='clean-traffic'>
        <parameter name='IP' value='10.0.0.1'/>
        <parameter name='IP' value='10.0.0.2'/>
        <parameter name='IP' value='10.0.0.3'/>
      </filterref>
    </interface>
  </devices>
この XML ファイルは、1 つのインターフェースに複数の IP アドレスを有効にするフィルターを作成します。各 IP アドレスが別個のフィルタールールになります。したがって、上記の XML と以下のルールを使用すると、3 種類の異なるフィルタールールが作成されます (IP アドレスごと 1 ルール)。
  <rule action='accept' direction='in' priority='500'>
    <tcp srpipaddr='$IP'/>
  </rule>
複数の要素を含む変数の各要素にアクセスすることができるため、以下のようなフィルタールールは DSTPORTS 変数の 2 番目の要素にアクセスします。
  <rule action='accept' direction='in' priority='500'>
    <udp dstportstart='$DSTPORTS[1]'/>
  </rule>

例17.5 各種変数の使用

$VARIABLE[@<iterator id="x">] の表記を使用すると、異なる一覧からの許容範囲内にあるルールのあらゆる組み合わせを表すことができるフィルタールールの作成が可能です。次のルールは、仮想マシンが DSTPORTS で指定されている複数のポート上で SRCIPADDRESSES に指定されている複数のソース IP アドレスからのトラフィックを受信できるよう許可します。このルールは、要素へのアクセスに 2 種類の独立した反復子を使って、変数 DSTPORTSSRCIPADDRESSES のあらゆる組み合わせを生成します。
  <rule action='accept' direction='in' priority='500'>
    <ip srcipaddr='$SRCIPADDRESSES[@1]' dstportstart='$DSTPORTS[@2]'/>
  </rule>
以下のように SRCIPADDRESSESDSTPORTS に具体的な値を割り当てます。
  SRCIPADDRESSES = [ 10.0.0.1, 11.1.2.3 ]
  DSTPORTS = [ 80, 8080 ]
$SRCIPADDRESSES[@1]$DSTPORTS[@2] を使って変数に値を割り当てると、以下のようにアドレスとポートのあらゆる組み合わせが作成されることになります。
  • 10.0.0.1, 80
  • 10.0.0.1, 8080
  • 11.1.2.3, 80
  • 11.1.2.3, 8080
$SRCIPADDRESSES[@1]$DSTPORTS[@1] の表記など、1 つの反復子を使って前述の変数にアクセスすると、両方の一覧に並列にアクセスされるため、次のような組み合わせになります。
  • 10.0.0.1, 80
  • 11.1.2.3, 8080

注記

$VARIABLE$VARIABLE[@0] の簡略形になります。このセクションの冒頭で示したように、先の表記は常に反復子の役割となる iterator id="0" が付くと仮定しています。

17.14.5. 自動 IP アドレス検出と DHCP スヌーピング

このセクションでは、自動 IP アドレス検出と DHCP スヌーピングについての情報を提供します。

17.14.5.1. はじめに

仮想マシンのインターフェースで使用される IP アドレスの検出は、変数の IP が参照されるものの、値が割り当てられていない場合に自動的に作動します。使用する IP アドレスラーニングメソッドを指定する場合に変数 CTRL_IP_LEARNING を使用します。anydhcpnone が有効な値になります。
any の値では、libvirt に対し、パケットを使って仮想マシンで使用しているアドレスを確定するよう指示します。これは、変数 CTRL_IP_LEARNING が設定されていない場合のデフォルトになります。このメソッドの場合、検出する IP アドレスはインターフェースごとに 1 つのみとなります。ゲスト仮想マシンの IP アドレスが検出されると、その IP ネットワークトラフィックがそのアドレスにロックされ、IP アドレスのなりすましなどがそのフィルターの 1 つで防止されます。この場合、IP アドレスのなりすましと見られるような、仮想マシンのユーザーによるゲスト仮想マシン内からのインターフェースの IP アドレスの変更は行なえなくなります。ゲスト仮想マシンを別のホスト物理マシンに移行したり、一時停止状態から再開させた場合、ゲスト仮想マシンが送信する最初のパケットによって特定のインターフェースで使用できる IP アドレスが再度確定されます。
dhcp の値では、libvirt に DHCP サーバーで割り当てられる有効なリースを持つアドレスしか受け取らないよう指示します。このメソッドは 1 つのインターフェースでの複数 IP アドレスの検出および使用に対応しています。ゲスト仮想マシンが一時停止状態から再開すると、有効な IP アドレスのリースがそのフィルターに適用されます。その他の場合、ゲスト仮想マシンは新しい IP アドレスを取得するために DHCP を使用します。ゲスト仮想マシンを別の物理的なホスト物理マシンに移行する場合には、ゲスト仮想マシンで DHCP プロトコルを再実行する必要があります。
CTRL_IP_LEARNING を none に設定すると、libvirt では IP アドレスラーニングは行なわれず、明示的な値を割り当てない IP の参照はエラーになります。

17.14.5.2. DHCP スヌーピング

CTRL_IP_LEARNING=dhcp (DHCP スヌーピング) により、とくに IP アドレスの割り当てを信頼できる DHCP サーバーに限るフィルターと併用したい場合に、なりすまし防止に対する安全性が強化されます。これを有効にするには、DHCPSERVER 変数を有効な DHCP サーバーの IP アドレスに設定し、 この変数を使って着信 DHCP の応答を処理するフィルターを指定します。
DHCP スヌーピングが有効にされており、DHCP リースの有効期限が切れた場合、ゲスト仮想マシンは DHCP サーバーから新しい有効なリースを取得するまで、その IP アドレスを使用できなくなります。ゲスト仮想マシンを移行する場合、IP アドレスを使用するために新しい有効な DHCP リースを取得する必要があります (たとえば、仮想マシンをいったんダウンさせてから再起動する必要があります)。

注記

自動 DHCP 検出では、ゲスト仮想マシンがインフラストラクチャーの DHCP サーバーと通信する DHCP トラフィックをリッスンします。libvirt でのサービス拒否攻撃を回避するには、パケット評価の速度制限を行います。つまり、ゲスト仮想マシンがインターフェース上で 1 秒間に大量の DHCP パケットを送信している場合には、そのパケットすべてには評価を行わないようにして、フィルターが適用されないようにします。通常の DHCP クライアントの動作の場合、1 秒に送信する DHCP パケット数は多くないことが想定されます。また、DHCP パケットが送信されないようにするためにインフラストラクチャー内の全ゲスト仮想マシンに適切なフィルターを設定することが重要になります。したがって、ポート 67 からポート 68 へのゲスト仮想マシンによる UDP および TCP トラフィック送信を防止するか、または DHCPSERVER 変数を全ゲスト仮想マシンで使用して DHCP サーバーのメッセージが信頼できる DHCP サーバーからしか送信できないよう制限する必要があります。同時に、なりすまし防止の対策をサブネット内の全ゲスト仮想マシンで有効にしておく必要があります。

例17.6 DHCP スヌーピング用に IP をアクティブ化

以下の XML は、DHCP スヌーピングメソッドを使って IP アドレスラーニングをアクティブにした例を示しています。
    <interface type='bridge'>
      <source bridge='virbr0'/>
      <filterref filter='clean-traffic'>
        <parameter name='CTRL_IP_LEARNING' value='dhcp'/>
      </filterref>
    </interface>

17.14.6. 予約済み変数

表17.2「予約済み変数」 は、予約済みとみなされ、libvirt によって使用される変数を示しています。

表17.2 予約済み変数

変数名定義
MACインターフェースの MAC アドレス
IPインターフェースで使用中の IP アドレス一覧
IPV6現在のところ実装されていません。インターフェースで使用中の IPV6 アドレスの一覧
DHCPSERVER信頼できる DHCP サーバーの IP アドレス一覧
DHCPSERVERV6現在のところ実装されていません。信頼できる DHCP サーバーの IPv6 アドレスの一覧
CTRL_IP_LEARNINGIP アドレス検出モードの選択

17.14.7. 要素と属性の概要

ネットワークフィルターすべてに必要なルート要素は 2 つの属性を持つ <filter> になります。name 属性は特定フィルターの固有名を指定します。chain 属性はオプションですが、基礎となるホスト物理マシンのファイアウォールサブシステムによってより効率的な処理を実現するために特定のフィルターを編成することができます。現在、システムで対応しているチェーンは、rootipv4ipv6arp、および rarp のみです。

17.14.8. 他のフィルターへの参照

いずれのフィルターにも他のフィルターへの参照を持たせることができます。フィルターツリー内の各フィルターは複数回参照できますが、フィルター間の参照がループとならないようにする必要があります。

例17.7 clean traffic フィルターの例

以下は、他のいくつかのフィルターを参照している clean-traffic ネットワークフィルターの XML です。
<filter name='clean-traffic'>
  <uuid>6ef53069-ba34-94a0-d33d-17751b9b8cb1</uuid>
  <filterref filter='no-mac-spoofing'/>
  <filterref filter='no-ip-spoofing'/>
  <filterref filter='allow-incoming-ipv4'/>
  <filterref filter='no-arp-spoofing'/>
  <filterref filter='no-other-l2-traffic'/>
  <filterref filter='qemu-announce-self'/>
</filter>
別のフィルターを参照させる場合、XML ノードの <filterref> をフィルターノード内に指定する必要があります。このノードには参照先のフィルター名を値として持つ属性フィルターを持たせる必要があります。
新しいネットワークフィルターはいつの時点で定義しても構いません。また、libvirt がまだ認識できないネットワークフィルターへの参照を含めることもできます。ただし、仮想マシンの起動後、またはフィルターを参照するネットワークインターフェースのホットプラグ後には、フィルターツリー内の全ネットワークフィルターが利用可能な状態になければなりません。 利用できないフィルターがある場合には仮想マシンが起動しなくなるか、またはネットワークインターフェースの接続が不可能になります。

17.14.9. フィルタールール

以下の XML は、発信 IP パケット内の IP アドレス (変数 IP の値から取得される) が期待したアドレスではない場合に、トラフィックをドロップするルールを実施するネットワークトラフィックフィルターの簡単な例を示しています。これにより仮想マシンからの IP アドレスのなりすましを防ぎます。

例17.8 ネットワークトラフィックフィルターの例

<filter name='no-ip-spoofing' chain='ipv4'>
  <uuid>fce8ae33-e69e-83bf-262e-30786c1f8072</uuid>
  <rule action='drop' direction='out' priority='500'>
    <ip match='no' srcipaddr='$IP'/>
  </rule>
</filter>
トラフィックフィルターのルールはルールノードで開始します。このノードには以下の属性を最大 3 つまで含めることができます。
  • action を mandatory にすると、次の値を取ることができます。
    • drop (ルールに一致すると、さらに分析することなくパケットを破棄し、メッセージは出力されません)
    • reject (ルールに一致すると、さらに分析することなく ICMP 拒否メッセージを生成します)
    • accept (ルールに一致すると、さらに分析することなくパケットを受け取ります)
    • return (ルールに一致すると、このフィルターを通過しますがさらに分析するため呼び出しフィルターに制御を戻します)
    • continue (ルールに一致すると、さらに分析するため次のルールに移動します)
  • direction を mandatory にすると、次の値を取ることができます。
    • in - 着信トラフィック
    • out - 発信トラフィック
    • inout - 着信と発信のトラフィック
  • priority はオプションです。ルールの優先度は、ルールが他のルールに対して相対的にインスタンス化される順序を制御します。小さい値のルールは大きい値のルールより先にインスタンス化されます。有効な値は -1000 から 1000 の範囲です。この属性が指定されないと、デフォルトでは優先度 500が指定されます。ルートチェーン内のフィルタールールは、その優先度に基づいて、ルートチェーンに接続されるフィルターで分類されます。これにより、フィルターチェーンへのアクセスを持たせながらフィルタールール同士を交互配置することができるようになります。詳細は「フィルターチェーンの優先度」を参照してください。
  • statematch はオプションです。「0」または「false」に設定すると、 基礎となる接続状態のマッチングをオフにします。デフォルト設定は「1」または「 true」です。
詳細は、「高度なフィルター設定について」 を参照してください。
前述の 例17.7「clean traffic フィルターの例」 では、type ip のトラフィックはチェーン ipv4 に関連付けられ、ルールは priority=500 になることを示しています。type ip のトラフィックがチェーン ipv4 に関連付けられる別のフィルターが参照される場合は、そのフィルターのルールは先のルールの priority=500 に基づいて順序付けられます。
ルールにはトラフィックのフィルターを行なう単一ルールを含めることができます。上記の例では、タイプ ip のトラフィックがフィルターされます。

17.14.10. サポート対象プロトコル

以下のセクションでは、ネットワークフィルターのサブシステムで対応しているプロトコルの詳細について示します。このタイプのトラフィックルールはネスト化されたノードとしてルールノードで指定されます。ルールがフィルターするトラフィックのタイプにより、属性は異なります。上記の例では、単一の srcipaddr 属性を示しています。この属性は ip トラフィックフィルターノード内で有効になります。次のセクションでは有効な属性と期待されるデータタイプについて示します。 次のようなデータタイプが使用可能です。
  • UINT8 : 8 ビットの整数; 0-255 の範囲
  • UINT16: 16 ビットの整数; 0-65535 の範囲
  • MAC_ADDR: ドット付き 10 進数形式の MAC アドレス (00:11:22:33:44:55 など)
  • MAC_MASK: MAC アドレス形式による MAC アドレスマスク (FF:FF:FF:FC:00:00 など)
  • IP_ADDR: ドット付き 10 進数形式の IP アドレス (10.1.2.3 など)
  • IP_MASK: ドット付き 10 進数形式 (255.255.248.0) または CIDR マスク (0-32) による IP アドレスマスク
  • IPV6_ADDR: 数値形式の IPv6 アドレス (FFFF::1)
  • IPV6_MASK: 数値形式 (FFFF:FFFF:FC00::) または CIDR マスク (0-128) による IPv6 マスク
  • STRING: 文字列
  • BOOLEAN: 'true'、'yes'、'1'、または 'false'、 'no'、 '0'
  • IPSETFLAGS: 最大 6 つの 'src' または 'dst' 要素で記述される ipset のソースフラグと宛先フラグで、パケットヘッダーのソース部分または宛先部分いずれかの機能を選択します (src,src,dst など)。ここに入力する 'selectors' の数は参照される ipset のタイプによって異なります。
IP_MASK または IPV6_MASK のタイプを除き、すべての属性は no の値の match 属性を使って無効にすることができます。無効にした複数の属性を 1 つのまとめることもできます。次の XML の抜粋部分で抽象属性を使った一例を示します。
[...]
  <rule action='drop' direction='in'>
    <protocol match='no' attribute1='value1' attribute2='value2'/>
    <protocol attribute3='value3'/>
  </rule>
[...]
ルールの動作によりそのルールが評価されるとともに、特定のプロトコル属性の境界内でそのルールが論理的に調べられます。単一属性の値がルールで指定された値に一致しない場合、評価のプロセスではそのルール全体が省略されることになります。したがって、上記の例では、プロトコルプロパティの attribute1value1 に一致せず、プロトコルプロパティーの attribute2value2 に一致せず、かつプロトコルプロパティー attribute3value3 に一致する場合、 着信トラフィックのみがドロップされます。

17.14.10.1. MAC (イーサネット)

プロトコル ID: mac
このタイプのルールはルートチェーンに入ります。

表17.3 MAC プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcmacmaskMAC_MASK送信側の MAC アドレスに適用されるマスク
dstmacaddrMAC_ADDR宛先の MAC アドレス
dstmacmaskMAC_MASK宛先の MAC アドレスに適用されるマスク
protocolidUINT16 (0x600-0xffff), STRINGレイヤー 3 プロトコル ID、有効な文字列 [arp, rarp, ipv4, ipv6]
commentSTRING最長 256 文字のテキスト文字列
フィルターは以下のように記述できます。
[...]
<mac match='no' srcmacaddr='$MAC'/>
[...]

17.14.10.2. VLAN (802.1Q)

プロトコル ID: vlan
このタイプのルールはルートチェーンまたは vlan チェーンのいずれかに入ります。

表17.4 VLAN プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcmacmaskMAC_MASK送信側の MAC アドレスに適用されるマスク
dstmacaddrMAC_ADDR宛先の MAC アドレス
dstmacmaskMAC_MASK宛先の MAC アドレスに適用されるマスク
vlan-idUINT16 (0x0-0xfff, 0 - 4095)VLAN ID
encap-protocolUINT16 (0x03c-0xfff), Stringカプセル化されたレイヤー 3 プロトコル ID、有効な文字列 arp、ipv4、ipv6
commentSTRING最長 256 文字のテキスト文字列

17.14.10.3. STP (Spanning Tree Protocol)

プロトコル ID: stp
このタイプのルールはルートチェーンまたは stp チェーンのいずれかに入ります。

表17.5 STP プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcmacmaskMAC_MASK送信側の MAC アドレスに適用されるマスク
typeUINT8BPDU (Bridge Protocol Data Unit) タイプ
flagsUINT8BPDU flagdstmacmask
root-priorityUINT16ルート優先度範囲の始点
root-priority-hiUINT16 (0x0-0xfff, 0 - 4095)ルート優先度範囲の終点
root-addressMAC _ADDRESSルートの MAC アドレス
root-address-maskMAC _MASKルートの MAC アドレスマスク
roor-costUINT32ルートのパスコスト (範囲の始点)
root-cost-hiUINT32ルートのパスコスト (範囲の終点)
sender-priority-hiUINT16送信側優先度の範囲の終点
sender-addressMAC_ADDRESSBPDU 送信側 MAC アドレス
sender-address-maskMAC_MASKBPDU 送信側 MAC アドレスマスク
portUINT16ポート識別子 (範囲の始点)
port_hiUINT16ポート識別子 (範囲の終点)
msg-ageUINT16メッセージエイジタイマー (範囲の始点)
msg-age-hiUINT16メッセージエイジタイマー (範囲の終点)
max-age-hiUINT16最大エイジ時間の範囲の終点
hello-timeUINT16Hello タイムタイマー (範囲の始点)
hello-time-hiUINT16Hello タイムタイマー (範囲の終点)
forward-delayUINT16フォワード遅延 (範囲の始点)
forward-delay-hiUINT16フォワード遅延 (範囲の終点)
commentSTRING最長 256 文字のテキスト文字列

17.14.10.4. ARP/RARP

プロトコル ID: arp または rarp
このタイプのルールはルートチェーンまたは arp/rarp チェーンのいずれかに入ります。

表17.6 ARP と RARP のプロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcmacmaskMAC_MASK送信側の MAC アドレスに適用されるマスク
dstmacaddrMAC_ADDR宛先の MAC アドレス
dstmacmaskMAC_MASK宛先の MAC アドレスに適用されるマスク
hwtypeUINT16ハードウェアのタイプ
protocoltypeUINT16プロトコルのタイプ
opcodeUINT16, STRINGOpcode の有効な文字列: Request、Reply、Request_Reverse、Reply_Reverse、DRARP_Request、DRARP_Reply、DRARP_Error、InARP_Request、ARP_NAK
arpsrcmacaddrMAC_ADDRARP/RARP パケット内のソース MAC アドレス
arpdstmacaddrMAC _ADDRARP/RARP パケット内の宛先 MAC アドレス
arpsrcipaddrIP_ADDRARP/RARP パケット内のソース IP アドレス
arpdstipaddrIP_ADDRARP/RARP パケット内の宛先 IP アドレス
gratuitousBOOLEAN余計な ARP パケットをチェックするかどうかを指定するブール値
commentSTRING最長 256 文字のテキスト文字列

17.14.10.5. IPv4

プロトコル ID: ip
このタイプのルールはルートチェーンまたは ipv4 チェーンのいずれかに入ります。

表17.7 IPv4 プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcmacmaskMAC_MASK送信側の MAC アドレスに適用されるマスク
dstmacaddrMAC_ADDR宛先の MAC アドレス
dstmacmaskMAC_MASK宛先の MAC アドレスに適用されるマスク
srcipaddrIP_ADDRソース IP アドレス
srcipmaskIP_MASKソース IP アドレスに適用されるマスク
dstipaddrIP_ADDR宛先 IP アドレス
dstipmaskIP_MASK宛先 IP アドレスに適用されるマスク
protocolUINT8, STRINGレイヤー 4 プロトコルの識別子。protocol に有効な文字列: tcp、udp、udplite、esp、ah、icmp、igmp、sctp
srcportstartUINT16有効なソースポート範囲の開始点。プロトコルが必要。
srcportendUINT16有効なソースポート範囲の終了点。プロトコルが必要。
dstportstartUNIT16有効な宛先ポート範囲の開始点。プロトコルが必要。
dstportendUNIT16有効な宛先ポート範囲の終了点。プロトコルが必要。
commentSTRING最長 256 文字のテキスト文字列

17.14.10.6. IPv6

プロトコル ID: ipv6
このタイプのルールはルートチェーンまたは ipv6 チェーンのいずれかに入ります。

表17.8 IPv6 プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcmacmaskMAC_MASK送信側の MAC アドレスに適用されるマスク
dstmacaddrMAC_ADDR宛先の MAC アドレス
dstmacmaskMAC_MASK宛先の MAC アドレスに適用されるマスク
srcipaddrIP_ADDRソース IP アドレス
srcipmaskIP_MASKソース IP アドレスに適用されるマスク
dstipaddrIP_ADDR宛先 IP アドレス
dstipmaskIP_MASK宛先 IP アドレスに適用されるマスク
protocolUINT8, STRINGレイヤー 4 プロトコル識別子。protocol に有効な文字列: tcp、udp、udplite、esp、ah、icmpv6、sctp
scrportstartUNIT16有効なソースポート範囲の開始点。プロトコルが必要。
srcportendUINT16有効なソースポート範囲の終了点。プロトコルが必要。
dstportstartUNIT16有効な宛先ポート範囲の開始点。プロトコルが必要。
dstportendUNIT16有効な宛先ポート範囲の終了点。プロトコルが必要。
commentSTRING最長 256 文字のテキスト文字列

17.14.10.7. TCP/UDP/SCTP

プロトコル ID: tcp、udp、sctp
このタイプのトラフィックについてはチェーンパラメーターは無視されるため、省略するかまたはルートに設定します。

表17.9 TCP/UDP/SCTP プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcipaddrIP_ADDRソース IP アドレス
srcipmaskIP_MASKソース IP アドレスに適用されるマスク
dstipaddrIP_ADDR宛先 IP アドレス
dstipmaskIP_MASK宛先 IP アドレスに適用されるマスク
scriptoIP_ADDRソース IP アドレス範囲の開始点
srcipfromIP_ADDRソース IP アドレス範囲の終了点
dstipfromIP_ADDR宛先 IP アドレス範囲の開始点
dstiptoIP_ADDR宛先 IP アドレス範囲の終了点
scrportstartUNIT16有効なソースポート範囲の開始点。プロトコルが必要。
srcportendUINT16有効なソースポート範囲の終了点。プロトコルが必要。
dstportstartUNIT16有効な宛先ポート範囲の開始点。プロトコルが必要。
dstportendUNIT16有効な宛先ポート範囲の終了点。プロトコルが必要。
commentSTRING最長 256 文字のテキスト文字列
stateSTRINGNEW、ESTABLISHED、RELATED、INVALID または NONE のコンマで区切った一覧
flagsSTRINGTCP のみ: マスク/フラグの形式。マスクおよびフラグを SYN、ACK、URG、PSH、FIN、RST または NONE か ALL のコンマで区切った一覧
ipsetSTRINGlibvirt の外側で管理されている IPSet の名前
ipsetflagsIPSETFLAGSIPSet のフラグ。ipset 属性が必要。

17.14.10.8. ICMP

プロトコル ID: icmp
注意: このタイプのトラフィックについてはチェーンパラメーターは無視されるため、省略するかまたはルートに設定します。

表17.10 ICMP プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcmacmaskMAC_MASK送信側の MAC アドレスに適用されるマスク
dstmacaddrMAD_ADDR宛先 MAC アドレス
dstmacmaskMAC_MASK宛先 MAC アドレスに適用されるマスク
srcipaddrIP_ADDRソース IP アドレス
srcipmaskIP_MASKソース IP アドレスに適用されるマスク
dstipaddrIP_ADDR宛先 IP アドレス
dstipmaskIP_MASK宛先 IP アドレスに適用されるマスク
srcipfromIP_ADDRソース IP アドレス範囲の開始点
scriptoIP_ADDRソース IP アドレス範囲の終了点
dstipfromIP_ADDR宛先 IP アドレス範囲の開始点
dstiptoIP_ADDR宛先 IP アドレス範囲の終了点
typeUNIT16ICMP タイプ
codeUNIT16ICMP コード
commentSTRING最長 256 文字のテキスト文字列
stateSTRINGNEW、ESTABLISHED、RELATED、INVALID または NONE のコンマで区切った一覧
ipsetSTRINGlibvirt の外側で管理されている IPSet の名前
ipsetflagsIPSETFLAGSIPSet のフラグ。ipset 属性が必要。

17.14.10.9. IGMP、ESP、AH、UDPLITE、'ALL'

プロトコル ID: igmp、esp、ah、udplite、all
このタイプのトラフィックについてはチェーンパラメーターは無視されるため、省略するかまたはルートに設定します。

表17.11 IGMP、ESP、AH、UDPLITE、'ALL'

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcmacmaskMAC_MASK送信側の MAC アドレスに適用されるマスク
dstmacaddrMAD_ADDR宛先 MAC アドレス
dstmacmaskMAC_MASK宛先 MAC アドレスに適用されるマスク
srcipaddrIP_ADDRソース IP アドレス
srcipmaskIP_MASKソース IP アドレスに適用されるマスク
dstipaddrIP_ADDR宛先 IP アドレス
dstipmaskIP_MASK宛先 IP アドレスに適用されるマスク
srcipfromIP_ADDRソース IP アドレス範囲の開始点
scriptoIP_ADDRソース IP アドレス範囲の終了点
dstipfromIP_ADDR宛先 IP アドレス範囲の開始点
dstiptoIP_ADDR宛先 IP アドレス範囲の終了点
commentSTRING最長 256 文字のテキスト文字列
stateSTRINGNEW、ESTABLISHED、RELATED、INVALID または NONE のコンマで区切った一覧
ipsetSTRINGlibvirt の外側で管理されている IPSet の名前
ipsetflagsIPSETFLAGSIPSet のフラグ。ipset 属性が必要。

17.14.10.10. IPV6 経由の TCP/UDP/SCTP

プロトコル ID: tcp-ipv6、udp-ipv6、sctp-ipv6
このタイプのトラフィックについてはチェーンパラメーターは無視されるため、省略するかまたはルートに設定します。

表17.12 IPv6 経由の TCP、UDP、SCTP プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcipaddrIP_ADDRソース IP アドレス
srcipmaskIP_MASKソース IP アドレスに適用されるマスク
dstipaddrIP_ADDR宛先 IP アドレス
dstipmaskIP_MASK宛先 IP アドレスに適用されるマスク
srcipfromIP_ADDRソース IP アドレス範囲の開始点
scriptoIP_ADDRソース IP アドレス範囲の終了点
dstipfromIP_ADDR宛先 IP アドレス範囲の開始点
dstiptoIP_ADDR宛先 IP アドレス範囲の終了点
srcportstartUINT16有効なソースポート範囲の開始点
srcportendUINT16有効なソースポート範囲の終了点
dstportstartUINT16有効な宛先ポート範囲の開始点
dstportendUINT16有効な宛先ポート範囲の終了点
commentSTRING最長 256 文字のテキスト文字列
stateSTRINGNEW、ESTABLISHED、RELATED、INVALID または NONE のコンマで区切った一覧
ipsetSTRINGlibvirt の外側で管理されている IPSet の名前
ipsetflagsIPSETFLAGSIPSet のフラグ。ipset 属性が必要。

17.14.10.11. ICMPv6

プロトコル ID: icmpv6
このタイプのトラフィックについてはチェーンパラメーターは無視されるため、省略するかまたはルートに設定します。

表17.13 ICMPv6 プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcipaddrIP_ADDRソース IP アドレス
srcipmaskIP_MASKソース IP アドレスに適用されるマスク
dstipaddrIP_ADDR宛先 IP アドレス
dstipmaskIP_MASK宛先 IP アドレスに適用されるマスク
srcipfromIP_ADDRソース IP アドレス範囲の開始点
scriptoIP_ADDRソース IP アドレス範囲の終了点
dstipfromIP_ADDR宛先 IP アドレス範囲の開始点
dstiptoIP_ADDR宛先 IP アドレス範囲の終了点
typeUINT16ICMPv6 タイプ
codeUINT16ICMPv6 コード
commentSTRING最長 256 文字のテキスト文字列
stateSTRINGNEW、ESTABLISHED、RELATED、INVALID または NONE のコンマで区切った一覧
ipsetSTRINGlibvirt の外側で管理されている IPSet の名前
ipsetflagsIPSETFLAGSIPSet のフラグ。ipset 属性が必要。

17.14.10.12. IPv6 経由の IGMP、ESP、AH、UDPLITE、'ALL'

プロトコル ID: igmp-ipv6、esp-ipv6、ah-ipv6、udplite-ipv6、all-ipv6
このタイプのトラフィックについてはチェーンパラメーターは無視されるため、省略するかまたはルートに設定します。

表17.14 IPv6 経由の IGMP、ESP、AH、UDPLITE、'ALL' プロトコルタイプ

属性名データタイプ定義
srcmacaddrMAC_ADDR送信側の MAC アドレス
srcipaddrIP_ADDRソース IP アドレス
srcipmaskIP_MASKソース IP アドレスに適用されるマスク
dstipaddrIP_ADDR宛先 IP アドレス
dstipmaskIP_MASK宛先 IP アドレスに適用されるマスク
srcipfromIP_ADDRソース IP アドレス範囲の開始点
scriptoIP_ADDRソース IP アドレス範囲の終了点
dstipfromIP_ADDR宛先 IP アドレス範囲の開始点
dstiptoIP_ADDR宛先 IP アドレス範囲の終了点
commentSTRING最長 256 文字のテキスト文字列
stateSTRINGNEW、ESTABLISHED、RELATED、INVALID または NONE のコンマで区切った一覧
ipsetSTRINGlibvirt の外側で管理されている IPSet の名前
ipsetflagsIPSETFLAGSIPSet のフラグ。ipset 属性が必要。

17.14.11. 高度なフィルター設定について

次のセクションでは高度なフィルター設定について解説します。

17.14.11.1. 接続の追跡

ネットワークフィルターのサブシステム (Linux 上) では、IP テーブルの接続追跡のサポートを使用します。ネットワークトラフィックの方向性を強制する (状態一致) ほか、ゲスト仮想マシンに対する同時接続数をカウントし、制限するのに役立ちます。たとえば、ゲスト仮想マシン側で TCP ポート 8080 をサーバーとして開くと、クライアントはポート 8080 でゲスト仮想マシンに接続することができます。接続の追跡と方向性の強制により、逆方向となるポート 8080 から (TCP クライアントから) ホスト物理マシンへの接続の開始は妨げられます。さらに重要な点は、追跡を行うことにより、リモート操作によりゲスト仮想マシンへの接続を確立するような攻撃を防ぐことができます。たとえば、ゲスト仮想マシン内のユーザーが攻撃者のサイトでポート 80 への接続を確立した場合でも、攻撃者は逆方向となる TCP ポート 80 からこのゲスト仮想マシンへの接続は開始できません。デフォルトでは、接続の追跡およびトラフィックの方向性の強制を有効にする接続状態一致はオンに設定されます。

例17.9 TCP ポートへの接続をオフにする XML 例

以下の XML の抜粋例では、TCP ポート 12345 への着信接続に対してこの機能をオフにしています。
   [...]
    <rule direction='in' action='accept' statematch='false'>
      <cp dstportstart='12345'/>
    </rule>
   [...]
これにより、TCP ポート 12345 への着信トラフィックが許可されますが、仮想マシン内の TCP ポート 12345 (クライアント) からの接続開始も有効になります。これは状況に適する場合もありますが、 適さない場合もあります。

17.14.11.2. 接続数の制限

ゲスト仮想マシンで確立できる接続数を制限する場合、特定タイプのトラフィックに対して接続数の制限を設けるルールを指定する必要があります。たとえば、仮想マシンに同時に ping を許可するのは 1 つの IP アドレスのみに制限したり、同時に許可されるアクティブな着信 SSH 接続を 1 つに制限する場合などにこの設定が必要になります。

例17.10 接続数に制限を設定した XML サンプル

次の XML の抜粋例を使って接続数を制限することができます。
  [...]
  <rule action='drop' direction='in' priority='400'>
    <tcp connlimit-above='1'/>
  </rule>
  <rule action='accept' direction='in' priority='500'>
    <tcp dstportstart='22'/>
  </rule>
  <rule action='drop' direction='out' priority='400'>
    <icmp connlimit-above='1'/>
  </rule>
  <rule action='accept' direction='out' priority='500'>
    <icmp/>
  </rule>
  <rule action='accept' direction='out' priority='500'>
    <udp dstportstart='53'/>
  </rule>
  <rule action='drop' direction='inout' priority='1000'>
    <all/>
  </rule>
  [...]

注記

制限ルールは、トラフィックを許可するルールの前に XML に記載する必要があります。例17.10「接続数に制限を設定した XML サンプル」 の XML ファイルでは、ポート 22 へ送信される DNS トラフィックがゲスト仮想マシンに到着するのを許可するルールが追加され、SSH デーモンによる DNS ルックアップの失敗に関連する理由で SSH セッションが確立されなくなることを防ぐようにされています。このルールを省くと、SSH クライアントが接続を試行する際に予期しないハングを招く可能性があります。トラフィックの追跡に関連するタイムアウトを扱う場合は十分な注意が必要です。ユーザーがゲスト仮想マシン内で終了させた可能性のある ICMP ping でホスト物理マシンの接続追跡システムに長期のタイムアウトが設定されていると、別の ICMP ping を通過させないことがあります。
最適なソリューションとしては、ホスト物理マシンの sysfs 内のタイムアウトをコマンド「# echo 3 > /proc/sys/net/netfilter/nf_conntrack_icmp_timeout」で調整する方法です。このコマンドにより、ICMP 接続の追跡タイムアウトが 3 秒に設定されます。1 つの ping が終了すると、別の ping が 3 秒後に開始されます。
何らかの理由でゲスト仮想マシンにより TCP 接続が正しく閉じられなかった場合、とくにホスト物理マシンでの TCP のタイムアウト値が長時間設定されている場合などは、接続が長い期間、開いたままになります。また、アイドル接続により接続追跡システム内でタイムアウトが生じ、パケットが交換されると接続が再度アクティブになる場合があります。
ただし、制限が低すぎると新たに開始された接続がアイドル接続を TCP バックオフに強制することがあります。したがって、接続の制限は高目に設定し、新しい TCP 接続での変動がアイドル接続に関連した異常なトラフィック動作の原因にならないようにします。

17.14.11.3. コマンドラインツール

virsh はネットワークフィルターのライフサイクルサポートで拡張されています。ネットワークフィルターサブシステムに関連するコマンドはすべて nwfilter のプレフィックスで開始されます。使用できるコマンドは次の通りです。
  • nwfilter-list : 全ネットワークフィルターの UUID と名前を一覧表示します。
  • nwfilter-define : 新しいネットワークフィルターを定義するか、または既存のフィルターを更新します (フィルター名の入力要)。
  • nwfilter-undefine : 指定したネットワークフィルターを削除します (フィルター名の入力要)。現在使用中のネットワークフィルターは削除しません。
  • nwfilter-dumpxml : 指定したネットワークフィルターを表示します (フィルター名の入力要)。
  • nwfilter-edit : 指定したネットワークフィルターを編集します (フィルター名の入力要)。

17.14.11.4. 既存のネットワークフィルター

以下は、libvirt で自動的にインストールされるサンプルのネットワークフィルターの一覧です。

表17.15 ICMPv6 プロトコルタイプ

プロトコル名説明
allow-arpゲスト仮想マシンに対するすべての着信および発信アドレス解決プロトコル (ARP) トラフィックを許可します。
no-arp-spoofingno-arp-mac-spoofingand no-arp-ip-spoofingこれらのフィルターは、ゲスト仮想マシンによる ARP トラフィックのなりすましを防ぎます。さらに、ARP 要求と返信メッセージだけを許可し、パケットに以下の項目が含まれるよう強制します。
  • no-arp-spoofing - ゲストの MAC および IP アドレス
  • no-arp-mac-spoofing - ゲストの MAC アドレス
  • no-arp-ip-spoofing - ゲストの IP アドレス
low-dhcpゲスト仮想マシンによる DHCP 経由の IP アドレスの要求を許可します (すべての DHCP サーバーから)。
low-dhcp-serverゲスト仮想マシンによる指定 DHCP サーバーからの IP アドレスの要求を許可します。DHCP サーバーのドット付き 10 進数 IP アドレスをこのフィルターへの参照内に指定する必要があります。変数名は DHCPSERVER にしてください。
low-ipv4仮想マシンに対するすべての着信および発信 IPv4 トラフィックを許可します。
low-incoming-ipv4仮想マシンへの着信 IPv4 トラフィックだけを許可します。このフィルターは、clean-traffic フィルターの一部です。
no-ip-spoofingゲスト仮想マシンが、パケット内部のアドレスとは異なるソース IP アドレスを持つ IP パケットを送信することを防ぎます。このフィルターは、clean-traffic フィルターの一部です。
no-ip-multicastゲスト仮想マシンが IP マルチキャストパケットを送信することを防ぎます。
no-mac-broadcast特定の MAC アドレスへの発信 IPv4 トラフィックを拒否します。このフィルターは、clean-traffic フィルターの一部です。
no-other-l2-trafficネットワークで使用される他のフィルターで指定したトラフィックを除き、すべての第 2 層ネットワークトラフィックを拒否します。このフィルターは、clean-traffic フィルターの一部です。
no-other-rarp-trafficqemu-announce-selfqemu-announce-self-rarpこれらのフィルターは、QEMU の自己アナウンス型逆アドレス解決プロトコル (RARP) パケットは許可しますが、他の RARP トラフィックはすべて拒否します。これらのフィルターも、すべて clean-traffic フィルターに含まれています。
clean-trafficMAC、IP および ARP のなりすましを防ぎます。このフィルターはビルディングブロックとして他の複数のフィルターを参照します。
これらのフィルターはビルディングブロックに過ぎないため、ネットワークトラフィックフィルターの機能を果たすためには他のフィルターと組み合わせて使用する必要があります。上記の一覧で最もよく使用されるフィルターは clean-traffic フィルターです。たとえば、このフィルター自体を no-ip-multicast フィルターと組み合わせ、パケットのなりすまし防止に加え、仮想マシンによる IP マルチキャストトラフィックの送信も防ぎます。

17.14.11.5. 独自のフィルターの記述

libvirt で提供されるのは数種類のサンプルネットワークフィルターのみとなるため、独自のフィルターの記述を検討するのもよいでしょう。独自のフィルターを記述する場合、ネットワークフィルターサブシステムについて、またこのシステムが内部でどのように機能するのかを知っておく必要があるかもしれません。また、意図するトラフィック以外のトラフィックは通過できず、意図するトラフィックのみが確実に通過できるようフィルターを行うプロトコルについて十分な知識と理解が必要になります。
ネットワークフィルターサブシステムは、現在 Linux のホスト物理マシン上でのみ利用できるため、QEMU および KVM タイプの仮想マシンでのみ機能します。Linux では、これは ebtables、iptables、ip6tables のサポートに基づいて構築され、これらの機能が使用されます。「サポート対象プロトコル」 の一覧を参照してください。以下のプロトコルは ebtables を使って実装できます。
  • mac
  • stp (スパニングツリープロトコル)
  • vlan (802.1Q)
  • arp、 rarp
  • ipv4
  • ipv6
IPv4 経由で実行されるプロトコルはすべて iptables を使ってサポートされます。IPv6 経由で実行されるプロトコルは ip6tables を使って実装されます。
Linux ホスト物理マシンを使用すると、libvirt のネットワークフィルターサブシステムで作成されたトラフィックフィルタールールはすべて ebtables で実装したフィルターサポートを最初に通過してから、iptables または ip6tables フィルターに移行します。フィルターツリーに mac、stp、vlan arp、rarp、ipv4、ipv6 などのいずれかのプロトコルのルールがある場合、まず etable のルールと一覧表示されている値が自動的に使用されます。
同じプロトコルの複数のチェーンを作成することができます。チェーン名には、以前にエミュレートされたプロトコルのいずれかのプレフィックスを含める必要があります。ARP トラフィックの処理用に追加のチェーンを作成するには、arp-test などの名前を持つチェーンを指定することができます。
たとえば、ip プロトコルフィルターを使用し、許可される UDP パケットのポート、ソースと宛先の IP アドレス、プロトコルの属性を指定して、ソースと宛先のポートごとに UDP トラフィック上でフィルターをかけることが可能です。これにより、ebtables を使った早期の UDP トラフィックのフィルターが可能になります。ただし、UDP パケットなどの IP または IPv6 パケットが ebtables 層を通過した後に、iptables または ip6tables ルールをインスタンス化する 1 つ以上のルールがフィルターツリーにある場合は、UDP パケットを通過させるルールをこれらのフィルター層にも指定する必要があります。これは、適切な udp または udp-ipv6 のトラフィックフィルターノードを含むルールで実行できます。

例17.11 カスタムフィルターの作成

以下の要件を満たすフィルターが必要であると仮定します。
  • 仮想マシンのインターフェースでの MAC、 IP、 ARP のなりすましを防ぐ
  • 仮想マシンのインターフェースの TCP ポート 22 と 80 のみを開く
  • 仮想マシンによるインターフェースからの ping トラフィック送信を許可する。ただしインターフェース上での仮想マシンに対する ping には応答させない
  • 仮想マシンによる DNS ルックアップを許可する (ポート 53 への UDP)
なりすまし防止の要件は既存の clean-traffic フィルターで満たすことができるため、カスタムフィルターからこのフィルターを参照させることで防止することができます。
TCP ポート 22 と 80 のトラフィックを許可するため、2 種類のルールを追加します。ゲスト仮想マシンによる ping トラフィックの送信を許可するために ICMP トラフィックにルールを 1 つ追加します。単純にするため、ゲスト仮想マシンからの一般的な ICMP トラフィックの開始を許可し、ICMP echo の要求および応答メッセージに対する ICMP トラフィックの指定を行ないません。他のすべてのトラフィックについては、ゲスト仮想マシンからの発信および着信すべてが遮断されます。これを実行するには、他のすべてのトラフィックをドロップするルールを追加します。ゲスト仮想マシン名は test、フィルターを関連付けるインターフェースは eth0 とし、作成するフィルターには test-eth0 という名前を付けるとします。
上記をネットワークフィルターの XML に反映させると以下のようになります。
<filter name='test-eth0'>
  <!- - This rule references the clean traffic filter to prevent MAC, IP and ARP spoofing. By not providing an IP address parameter, libvirt will detect the IP address the guest virtual machine is using. - ->
  <filterref filter='clean-traffic'/>

  <!- - This rule enables TCP ports 22 (ssh) and 80 (http) to be reachable - ->
  <rule action='accept' direction='in'>
    <tcp dstportstart='22'/>
  </rule>

  <rule action='accept' direction='in'>
    <tcp dstportstart='80'/>
  </rule>

  <!- - This rule enables general ICMP traffic to be initiated by the guest virtual machine including ping traffic - ->
  <rule action='accept' direction='out'>
    <icmp/>
  </rule>>

  <!- - This rule enables outgoing DNS lookups using UDP - ->
  <rule action='accept' direction='out'>
    <udp dstportstart='53'/>
  </rule>

  <!- - This rule drops all other traffic - ->
  <rule action='drop' direction='inout'>
    <all/>
  </rule>

</filter>

17.14.11.6. カスタムフィルターのサンプル

上記の XML 内のルールの 1 つにはゲスト仮想マシンのソースまたは宛先アドレスとなるいずれかの IP アドレスが含まれていますが、トラフィックのフィルターは正しく動作します。これは、ルールの評価はインターフェースごとに内部的に発生しますが、ルールがソースや宛先の IP アドレスではなく、パケットを送信したか、または受信するインターフェース (tap) に基づいて追加で評価されるためです。

例17.12 ネットワークインターフェースの詳細部分のサンプル XML

以下の XML の抜粋は、test ゲスト仮想マシンのドメイン XML 内にあるネットワークインターフェースの記述例を示しています。
   [...]
    <interface type='bridge'>
      <source bridge='mybridge'/>
      <filterref filter='test-eth0'/>
    </interface>
   [...]
ICMP トラフィックをさらに厳密に制御し、ICM echo の要求はゲスト仮想マシンからしか送信できないようにすると共に、ICMP echo の応答もゲスト仮想マシンでしか受信できないようにするには、上記の ICMP ルールを次の 2 つのルールに置き換えます。
  <!- - enable outgoing ICMP echo requests- ->
  <rule action='accept' direction='out'>
    <icmp type='8'/>
  </rule>
  <!- - enable incoming ICMP echo replies- ->
  <rule action='accept' direction='in'>
    <icmp type='0'/>
  </rule>

例17.13 カスタムフィルターのサンプル 2

この例では、前述の例と同じようなフィルターを構築していますが、ゲスト仮想マシン内にある ftp サーバーに関連して要件の一覧を拡張しています。このフィルターの要件は次の通りです。
  • ゲスト仮想マシンのインターフェースでの MAC、IP、ARP のなりすましを防ぐ
  • ゲスト仮想マシンのインターフェースの TCP ポート 22 と 80 のみを開く
  • ゲスト仮想マシンによるインターフェースからの ping トラフィック送信を許可するが、インターフェース上でのゲスト仮想マシンに対する ping には応答させない
  • ゲスト仮想マシンによる DNS ルックアップを許可する (ポート 53 への UDP)
  • ftp サーバーを有効にして (アクティブモード)、ゲスト仮想マシンの内側で実行できるようにする
ゲスト仮想マシン内で FTP サーバーを実行できるようにする追加要件は、FTP 制御トラフィックに対してポート 21 をアクセス可能にし、ゲスト仮想マシンによるゲスト仮想マシンの TCP ポート 20 から FTP クライアント (FTP アクティブモード) へ向けて発信する TCP 接続の確立を許可することになります。このフィルターは複数の方法で記述することができますが、以下の例では 2 種類のソリューションを示します。
1 つ目のソリューションでは、Linux ホスト物理マシンの接続追跡フレームワークとのつながりを提供する TCP プロトコルの状態属性を利用します。ゲスト仮想マシンが開始した FTP データ接続の場合 (FTP アクティブモード)、RELATED 状態を使ってゲスト仮想マシンによって開始された FTP データ接続が既存の FTP 制御接続の結果である (または関連性がある) ことを検出することができます。これにより、パケットがファイアウォールを通過できるようになります。ただし、RELATED 状態は、FTP データパスの TCP 発信接続の 1 番目のパケットにのみ有効になります。以後、状態は ESTABLISHED になり、この状態が着信と発信の両方向に一律に適用されます。これはすべてゲスト仮想マシンの TCP ポート 20から発信された FTP データトラフィックに関連します。これが次のソリューションにつながります。
<filter name='test-eth0'>
  <!- - This filter (eth0) references the clean traffic filter to prevent MAC, IP, and ARP spoofing. By not providing an IP address parameter, libvirt will detect the IP address the guest virtual machine is using. - ->
  <filterref filter='clean-traffic'/>

  <!- - This rule enables TCP port 21 (FTP-control) to be reachable - ->
  <rule action='accept' direction='in'>
    <tcp dstportstart='21'/>
  </rule>

  <!- - This rule enables TCP port 20 for guest virtual machine-initiated FTP data connection related to an existing FTP control connection - ->
  <rule action='accept' direction='out'>
    <tcp srcportstart='20' state='RELATED,ESTABLISHED'/>
  </rule>

  <!- - This rule accepts all packets from a client on the FTP data connection - ->
  <rule action='accept' direction='in'>
    <tcp dstportstart='20' state='ESTABLISHED'/>
  </rule>

  <!- - This rule enables TCP port 22 (SSH) to be reachable - ->
  <rule action='accept' direction='in'>
    <tcp dstportstart='22'/>
  </rule>

  <!- -This rule enables TCP port 80 (HTTP) to be reachable - ->
  <rule action='accept' direction='in'>
    <tcp dstportstart='80'/>
  </rule>

  <!- - This rule enables general ICMP traffic to be initiated by the guest virtual machine, including ping traffic - ->
  <rule action='accept' direction='out'>
    <icmp/>
  </rule>

  <!- - This rule enables outgoing DNS lookups using UDP - ->
  <rule action='accept' direction='out'>
    <udp dstportstart='53'/>
  </rule>

  <!- - This rule drops all other traffic - ->
  <rule action='drop' direction='inout'>
    <all/>
  </rule>

</filter>
RELATED 状態を使ってフィルターを試す前に、適切な接続追跡モジュールがホスト物理マシンのカーネルにロードされていることを確認する必要があります。カーネルのバージョンによっては、ゲスト仮想マシンで FTP 接続が確立される前に次の 2 つのコマンドのいずれかを実行する必要があります。
  • # modprobe nf_conntrack_ftp - where available OR
  • # modprobe ip_conntrack_ftp if above is not available
FTP 以外のプロトコルを RELATED 状態と併用する場合は、該当するモジュールをロードする必要があります。各プロトコルに使用できるモジュールは、ftp、tftp、irc、sip、sctp および amanda です。
2 つ目のソリューションでは、前述のソリューションより多くの接続状態フラグを利用します。このソリューションでは、トラフィックの一番最初のパケットが検出されると接続の NEW 状態が有効になる点を利用しています。続いて、最初のパケットのフローが許可されると、そのフローは接続とみなされ、ESTABLISHED 状態に移行します。したがって、ESTABLISHED 接続のパケットのゲスト仮想マシンへの着信、またゲスト仮想マシンからの発信を許可する汎用ルールを記述することができます。NEW 状態で識別できる一番最初のパケットについての特定ルールを記述し、データを受け取ることができるポートを指定して実行できます。明示的に許可されていないポートに向けたパケットはすべてドロップされるため、ESTABLISHED 状態にはなりません。そのポートから送信される後続パケットもすべてドロップされます。
<filter name='test-eth0'>
  <!- - This filter references the clean traffic filter to prevent MAC, IP and ARP spoofing. By not providing and IP address parameter, libvirt will detect the IP address the VM is using. - ->
  <filterref filter='clean-traffic'/>

  <!- - This rule allows the packets of all previously accepted connections to reach the guest virtual machine - ->
  <rule action='accept' direction='in'>
    <all state='ESTABLISHED'/>
  </rule>

  <!- - This rule allows the packets of all previously accepted and related connections be sent from the guest virtual machine - ->
  <rule action='accept' direction='out'>
    <all state='ESTABLISHED,RELATED'/>
  </rule>

  <!- - This rule enables traffic towards port 21 (FTP) and port 22 (SSH)- ->
  <rule action='accept' direction='in'>
    <tcp dstportstart='21' dstportend='22' state='NEW'/>
  </rule>

  <!- - This rule enables traffic towards port 80 (HTTP) - ->
  <rule action='accept' direction='in'>
    <tcp dstportstart='80' state='NEW'/>
  </rule>

  <!- - This rule enables general ICMP traffic to be initiated by the guest virtual machine, including ping traffic - ->
  <rule action='accept' direction='out'>
    <icmp state='NEW'/>
  </rule>

  <!- - This rule enables outgoing DNS lookups using UDP - ->
  <rule action='accept' direction='out'>
    <udp dstportstart='53' state='NEW'/>
  </rule>

  <!- - This rule drops all other traffic - ->
  <rule action='drop' direction='inout'>
    <all/>
  </rule>

</filter>

17.14.12. 制限

以下は、ネットワークフィルターサブシステムについての既知の制限の一覧です。
  • 仮想マシンの移行サポートは、ゲスト仮想マシンのトップレベルのフィルターで参照されるフィルターツリー全体がターゲットのホスト物理マシンでも使用できる場合に限られます。たとえば、ネットワークフィルター clean-traffic はすべての libvirt インストールで使用できる状態でなければなりません。これにより、このフィルターを参照するゲスト仮想マシンの移行が可能になります。バージョンの互換性が問題とならないよう、定期的にパッケージの更新を行い、常に最新の libvirt バージョンを使用するようにしてください。
  • インターフェースに関連しているネットワークトラフィックフィルターを失わないよう、 移行はバージョン 0.8.1 またはそれ以降の libvirt インストール間で行うようにしてください。
  • VLAN (802.1Q) パケットがゲスト仮想マシンによって送信された場合、プロトコル ID が arp、rarp、ipv4、ipv6 のルールではフィルターを行うことができません。このようなパケットをフィルターできるのは、プロトコル ID が MAC か VLAN の場合のみです。したがって、clean-traffic フィルターの例である 例17.1「ネットワークフィルターの例」 は期待通りには機能しません。