LinuxホストでVMware Workstation/Playerを動かすときのfirewall(iptables)について

Linuxホスト環境で、VMware Workstation 6.5.2/Player 2.5.2を使用している時のfirewallはどう設定すべきか、実際に試してみた。iptablesの設定はホストで行い、基本的にはNAT環境のゲストがガードできるかどうか。なお、私は主にDebian(現在はDebian5 lenny)を使用しているので、設定ファイルの配置はDebian5ディストリビューションに依存している。

Linuxiptablesには、自ホストへの入力/出力を制御するINPUT/OUTPUTチェイン、複数のネットワークインタフェース間のルーティングに関するパケットフィルタリングを制御するFORWARDチェインがある。

VMware Workstation/PlayerのゲストOSには、仮想NIC(ネットワークインターフェイス)ドライバとして、vmnetX(一般的にvmnet1はホストとゲストのみを接続、vmnet8はNATとして、これに接続した仮想マシンは全て同一のNATネットワーク内に属することになる)がある。また、ホストOSが動作している物理的なマシンと同じネットワークに、別のマシンとして接続されているように見えるブリッジ接続がある。

しかし、ゲストOSは(ドライバは存在するけれども)基本的にホストLinux OSのプロセスとして動作している。なので、恐らくホストオンリー、NATとして使用されるvmnetX(通常はvmnet1とvmnet8)はiptablesから見るとINPUT/OUTPUTチェインで制御でき、FORWARDチェインはDROPさせたままにしておいても良いと考えられる。また、実際VMwareは、Linuxホスト上で動作している時に、一般的にルーティングのために必要な設定/proc/sys/net/ipv4/ip_forwardは0のまま動作している。

ただし、VMwareゲストとの接続NICである(NAT接続の)vmnet8は、iptablesのINPUT/OUTPUTチェインをDROPしていいかどうか試して見たところ、DROPするとアクセスできなくなった。恐らく、ルーティング(FORWARDチェイン)に関する機能はVMwareが不要としているが、vmnetXの先のゲストとホストとの通信でのINPUT/OUTPUTチェインは仮想マシンをホストマシンとは"別のマシン"と意識する仕組みになっているのだろう。

これらのことを確認するためにiptablesを設定してみた。予想通り、FORWARDチェインのパケットは全て破棄(DROP)に設定しても、VMwareゲストは外部ネットワークと通信することが可能だった。また、ブリッジ接続の場合にはどうかも確認してみたが、やはりFORWARDチェインはDROPさせたままで外部ネットワークと通信することができた。

私はiptablesについてはほとんど初心者であるため、パケットフィルタリングにIPアドレスを指定する必然性が理解できなかった。また、使用しているVMwareホストのLinuxマシンがDynamic DNS(DNSDHCPが連携して、ホスト名をDHSPサーバに渡すと、LAN上の他のマシンからはDNSネームが見える)クライアントであり、またVMwareゲストも基本的にはNAT接続かつVMwareDHCPは使用せずdnsmasqを利用してDynamic DNSクライアントとして動作させる運用であるため、IPアドレス指定のパケットフィルタリングは行っていない。

さて、iptablesでのファイヤーウォール設定であるが、以下のようなポリシーで行った。

  • VMwareホストから外部に出たパケットに関連するパケット以外は、外部からのパケットは全てDROP。
  • VMwareゲストは全てNAT接続で構成しているので、vmnet8(ついでにvmnetX全て)で接続されているゲストとの相互パケットは全てACCEPT。

非常にシンプルであるが、以下のような設定スクリプトになった。スクリプト名はfirewall-startとした。外部との接続はeth0、VMwareゲストとの相互通信はvmnetXで行うとしている。

#!/bin/sh

# iptablesポリシーの初期化
# 基本的には、全てのチェインのパケットを通過させない。
# 以降の設定ルールにマッチした場合は、そちらが優先となる。

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

# このスクリプト実行前のiptables設定をクリア
# (現在このスクリプトではユーザ定義チェイン、パケットカウンタ、バイトカウンタは
# 使用していないが、他のスクリプトの考慮と、今後使用する可能性を考え、消去している。)

iptables -F # iptables内蔵チェイン内容を全て消去
iptables -X # ユーザ定義されていたチェイン内容を全て消去
iptables -Z # 全チェインのパケットカウンタ、バイトカウンタを全て消去

# loopbackインタフェース(このホスト内部での相互通信)の設定(全て許可)

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# vmnetで接続された仮想マシンVMwareホストとの相互通信設定(全て許可)
# (vmnet+はiptablesの仕様でvmnet[0-9]全て、というような意味を表す)

iptables -A INPUT -i vmnet+ -j ACCEPT
iptables -A OUTPUT -o vmnet+ -j ACCEPT

# このVMwareホストと外部(eth0インタフェース)との通信設定
# (外部へのアクセスは全て許可、そのアクセスに関する外部からのアクセスは許可)

iptables -A OUTPUT -o eth0 -j ACCEPT
iptables -A INPUT -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT

Debian5での設定として、ネットワーク初期化前にこのスクリプトを実行するため、firewall-startを/etc/network/if-pre-up.dに配置した。

また、停止スクリプトとして、大したことはしていないが、以下のfirewall-stopを作成。コメントはfirewall-startと同様なので省略。

#!/bin/sh

iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

iptables -F
iptables -X
iptables -Z

このスクリプトfirewall-stopを/etc/network/if-post-down.dに配置した。

このスクリプトにより、取り合えず単純な外部からのアクセスは完全に破棄(DROP)するので、通常使用には問題ないと思っている。

ただし、このVMwareホスト自身と、VMware内部の仮想マシンからのパケット流出を考慮するには、もう少し(firewall-startの最後から一つ前の行)の処理を検討する必要があると思われる。