□KVMでゲストOSのネットワーク分離(隔離)化
http://libvirt.org/formatnwfilter.html
ホストもゲストも自分で管理しているのならいいけれど、ゲストOSを人に
使わせるとなった場合には、ヒューマンエラーを含めて変なIPアドレスを
設定されかねないので、元々のIP以外のパケットの場合はゲストOSからの
通信を制限したいよね、と言うことです。
まー簡単にできるだろうと思ったら、確かに「IPv4が1つ」だけにならOK
なのだけど、IPv4アドレスを複数とか、IPv6も、となるとちと面倒です。
●その一、IPv4アドレス一つだけの場合。
IPv4だけなら、ゲストOSのXML設定ファイルのインターフェースに、通過
させたいIPを
<filterref filter=’clean-traffic’>
<parameter name=’IP’ value=’192.168.0.200’/>
</filterref>
のように書くだけ。
ちなみにlibvirtのバージョンが0.9.8以上なら、という条件がつくが、
複数IPを通過させたい場合には
<filterref filter=’clean-traffic’>
<parameter name=’IP’ value=’192.168.0.202’/>
<parameter name=’IP’ value=’192.168.0.203’/>
</filterref>
とするだけでもOKらしい。(CentOS6.2は0.9.4、2012.06現在)
あとはゲストOSのXML設定ファイルのインターフェースのところに
> <interface type=’bridge’>
> <mac address=’52:54:00:30:fc:2d’/>
> <source bridge=’br0’/>
> <model type=’virtio’/>
> <address type=’pci’ domain=’0x0000′ bus=’0x00′ slot=’0x03′ function=’0x0’/>
> <filterref filter=’clean-traffic’>
> <parameter name=’IP’ value=’192.168.0.200’/>
> </filterref>
> </interface>
という感じで書けばOK。
●その二、IPv4をセグメントでとかIPv6も、とかの場合。
IPv6やセグメント指定をする場合には、ルールを別途作らないといけない。
例えばIPv4もIPv6も、と言う場合には、まぁIPv4の設定を拡張してあげれば
よい。
cat > /etc/libvirt/nwfilter/allow-incoming-ipv6.xml
<filter name=’allow-incoming-ipv6′ chain=’ipv6′>
<rule direction=’in’ action=’accept’/>
</filter>
cat > /etc/libvirt/nwfilter/no-ipv6-spoofing.xml
<filter name=’no-ipv6-spoofing’ chain=’ipv6′>
<!– drop if srcipaddr is not the IPv6 address of the guest –>
<rule action=’drop’ direction=’out’>
<ipv6 match=’no’ srcipaddr=’$IPV6′ />
</rule>
</filter>
として、IPv6用のフィルタを作って、「clean-traffic」フィルターにこの
二つのフィルターを追記してあげる。
emacs /etc/libvirt/nwfilter/clean-traffic.xml
> <!– preventing IP spoofing on outgoing, allow all IPv4 in incoming –>
> <filterref filter=’no-ip-spoofing’/>
> <filterref filter=’allow-incoming-ipv4’/>
>
> <!– preventing IP spoofing on outgoing, allow all IPv6 in incoming –>
> <filterref filter=’no-ipv6-spoofing’/>
> <filterref filter=’allow-incoming-ipv6’/>
>
あとは、ゲストOSのXML設定ファイルのインターフェースのところに
<filterref filter=’ip-address-filter’>
<parameter name=’IP’ value=’192.168.0.203’/>
<parameter name=’IPV6′ value=’fe80::203’/>
</filterref>
のように記述して、ルール定義ファイルを追加したらlibvirtdを再起動
しないといけない。事前にゲストOSは全て止めておいた方がよい。
/etc/init.d/libvirtd restart
とすると再起動してくれる。(autostartしていればゲストOSも連れて起動)
ここで、外部とゲストOSとやり取りできればOK。
意図的にゲストOSのIPアドレスを変えたりして、外部やゲストOS同士でも
通信できないことを確認して、ちゃんとフィルターが効いているか確認を
すること。
※セグメント指定の場合には、参考URLのマニュアル読めばわかるでしょ。
いやー、IPv6もとなるとちょっと苦労した。難しく考えて、あれこれ悩ん
じゃったけど、結局こんな感じで追加してフィルターできるようになった
ので一安心したけど。
でさ、つまるところ、デフォルトではIPv6についてのフィルターってのは
ちゃんとできないんだよね。ネット上にも情報がほとんどない。
rootのchainにIPv6関連を設定するとか言うのもあるけど、うまく動かな
かったんだよなー。みんなどうしているんだろう?
まさか、
性善説に基づいて他人のIPなんて設定しないだろう
なんていう運用はしていないよね?世の中のVPS屋さんは。
IPv4については少なくともフィルターしているよねぇ?
と言うことは、この情報は意外と飯の種的な価値があったのかな?
★補足、libvirtd-0.9.10の場合
新しいlibvirtdの場合、MACアドレスとかIPv6とか複数のIPアドレスの
フィルター設定も出来るのでちょっとフィルター設定の中身が変わって
いるので補足します。
IPv6のフィルター設定をしたい場合は以下のようにclean-traffic.xmlに
追加します。(IPv4の下にでも追記)
emacs /etc/libvirt/nwfilter/clean-traffic.xml
> <!– preventing IP spoofing on outgoing, allow all IPv6 in incoming –>
> <filterref filter=’no-ipv6-spoofing’/>
>
> <rule direction=’out’ action=’accept’ priority=’-650′>
> <mac protocolid=’ipv6’/>
> </rule>
>
> <filterref filter=’allow-incoming-ipv6’/>
>
・さらにno-ipv6-spoofing.xmlも修正
emacs /etc/libvirt/nwfilter/no-ipv6-spoofing.xml
<filter name=’no-ip-spoofing’ chain=’ipv6-ip’ priority=’-710′>
<!– allow UDP sent from 0::0 (DHCP); filter more exact later –>
<rule action=’return’ direction=’out’ priority=’100′>
<ip srcipaddr=’0::0′ protocol=’udp’/>
</rule>
<!– allow all known IPv6 addresses –>
<rule direction=’out’ action=’return’ priority=’500′>
<ip srcipaddr=’$IPV6’/>
</rule>
<!– drop everything else –>
<rule direction=’out’ action=’drop’ priority=’1000’/>
</filter>
と、IPv4のno-ip-spoofing.xmlを参考に修正。
(DHCPの設定についてはよく判ってないので間違っていると思う…笑)
・allow-incoming-ipv6.xmlは変更がありません。
で、上記のように修正したら
<interface type=’bridge’>
<filterref filter=’clean-traffic‘>
<parameter name=’MAC’ value=’00:16:3e:7b:05:e1’/>
<parameter name=’IP’ value=’192.168.73.201’/>
<parameter name=’IPV6′ value=’fe80:192:168:73:0:0:0:201’/>
</filterref>
<mac address=’00:16:3e:7b:05:e1’/>
<source bridge=’br0’/>
<address type=’pci’ domain=’0x0000′ bus=’0x00′ slot=’0x03′ function=’0x0’/>
</interface>
とか書いてあげると、IPv4もIPv6もMACアドレスでもフィルターできる。