2011年9月17日土曜日

KVM/libvirt 隔離された2つの仮想ネットワーク間で通信する


このエントリーをはてなブックマークに追加


検証や勉強で仮想マシンを複数作って異なるネットワークセグメントに配置したい時に使う。

RHCE/RHCSA(RHCT)の勉強するときに便利。


libvirtの作る仮想ネットワーク

libvirt(virt-manager)は起動時にOSのルーティングを有効化するが、作成する仮想ネットワーク(virbrX)が他の仮想ネットワークとルーティングすることを禁止している。

# sysctl -a |grep ip_forward
net.ipv4.ip_forward = 1


隔離された2つのネットワークを以下のように作成する(virt-managerから作成)

virbr1
<network>
  <name>trust</name>
  <uuid>9929b191-4e3e-42e0-9dd4-00f1dea86715</uuid>
  <bridge name='virbr1' stp='on' delay='0' />
  <ip address='192.168.100.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.100.128' end='192.168.100.254' />
    </dhcp>
  </ip>
</network>

virbr2
<network>
  <name>untrust</name>
  <uuid>15994602-01fe-a1d5-da19-c89bbfc0a3cf</uuid>
  <bridge name='virbr2' stp='on' delay='0' />
  <ip address='192.168.101.1' netmask='255.255.255.0'>
    <dhcp>
      <range start='192.168.101.128' end='192.168.101.254' />
    </dhcp>
  </ip>
</network>


この仮想ネットワークを作成した場合、libvirtd起動時に以下のルールがiptablesへ追加される。

# iptables -nvL --line-numbers
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num  pkts bytes target  prot opt in     out     source       destination 
1       0     0 ACCEPT  all  --  virbr2 virbr2  0.0.0.0/0    0.0.0.0/0   
2       0     0 REJECT  all  --  *      virbr2  0.0.0.0/0    0.0.0.0/0   reject-with icmp-port-unreachable
3       0     0 REJECT  all  --  virbr2 *       0.0.0.0/0    0.0.0.0/0   reject-with icmp-port-unreachable
4       0     0 ACCEPT  all  --  virbr1 virbr1  0.0.0.0/0    0.0.0.0/0   
5      15  1260 REJECT  all  --  *      virbr1  0.0.0.0/0    0.0.0.0/0   reject-with icmp-port-unreachable
6       0     0 REJECT  all  --  virbr1 *       0.0.0.0/0    0.0.0.0/0   reject-with icmp-port-unreachable
7      38  3192 REJECT  all  --  *      *       0.0.0.0/0    0.0.0.0/0   reject-with icmp-host-prohibited
このルールを見ると、virbr1,2は他のネットワークとの通信をREJECTされていることがわかる。

これを解決する方法は以下。


1. iptables を無効にする

一番手っ取り早い。net.ipv4.ip_forward = 1 が指定されていれば全てのルーティングが許可される。

# /etc/init.d/iptables stop

ただし外部からのルーティングも受け付けてしまう上、他のiptablesルールも無効になるためセキュリティ的にはお勧めできない。

自宅や完全に隔離された物理マシン上で試すにはこれがお手軽。

*iptablesはプロセスでは無いので、無効(停止)してもルールが破棄されるだけでiptablesは動いている。そのためlibvirtの再起動等を行うと再度ルールが追加されてしまうので注意。


2. iptables にルールを追加する

virbr1,2間でのルーティングを許可するルールをiptablesに記載してやる。これがお手軽かつ安全な方法。

# iptables -I FORWARD 1 -i virbr1 -o virbr2 -j ACCEPT
# iptables -I FORWARD 1 -i virbr2 -o virbr1 -j ACCEPT

既に定義されたルールよりも上位に追加する。3つ以上の仮想ネットワークでルーティングする場合はそれぞれのIF間でのルールを作る必要がある。

# iptables -I FORWARD 1 -i virbr1 -o virbr2 -j ACCEPT
# iptables -I FORWARD 1 -i virbr1 -o virbr3 -j ACCEPT
# iptables -I FORWARD 1 -i virbr2 -o virbr1 -j ACCEPT
# iptables -I FORWARD 1 -i virbr2 -o virbr3 -j ACCEPT
# iptables -I FORWARD 1 -i virbr3 -o virbr1 -j ACCEPT
# iptables -I FORWARD 1 -i virbr3 -o virbr2 -j ACCEPT

これ以上の数の仮想ネットワークを作る場合も同様。全インターフェース間でのFORWARDを許可してやる。


設定を永続化する

上記設定は一時的なもの。無理に永続化する必要もないと思うけど、rc.local当たりに上記ルールの追加を書いておくか、libvirtを停止した状態で iptablesにルールを追加した上で /etc/init.d/iptables save でルールが保存される。

0 件のコメント:

コメントを投稿