今回は前回紹介できなかったセキュリティ、ネットワーク系の設定を説明していきたいと思います。
セキュリティ機能
ケーパビリティ
コンテナがrootで実行されている場合でも、コンテナ内では一部の特権を認めたくない場合はあるでしょう。このような場合、Linuxカーネルの持つケーパビリティの機能を使ってコンテナの特権を制御できます。
ケーパビリティはcapabilities(7)にあるようにCAP_SYS_MODULE
というようなCAP_
で始まる大文字で表されます。LXCではこの冒頭のCAP_
を除いた文字列を小文字で指定します。たとえばCAP_SYS_MODULE
の場合はsys_module
と指定します。
ケーパビリティの指定は以下のどちらかで行います。各設定ともに、スペース区切りで一行に複数の値を指定できます。
- lxc.cap.drop
- コンテナ内で削除したいケーパビリティを指定します。
- lxc.cap.keep
- コンテナ内で保持したいケーパビリティを指定します。指定したケーパビリティ以外は全て削除されます。
lxc-create
でコンテナを作成する際にincludeされる各ディストリビューションの標準設定ファイルでは、lxc.cap.drop
でコンテナに与えると問題になることの多いケーパビリティを削除しています。たとえばUbuntuコンテナ用の設定ファイルでは以下のように設定されています。
セキュリティ系の機能とはいえ、コンテナを実用的に使えるようにしながら、ケーパビリティの指定でセキュリティを確保するのは難しいため、どちらかというとコンテナを運用する際に起こる問題を解消するためにケーパビリティを指定する方が多いでしょう。
AppArmor
ホストOSでAppArmorが利用できる環境では、コンテナで使うAppArmorプロファイルが指定できます。設定は使用したいプロファイルをlxc.aa_profile
に指定するだけです。
ホストOS環境がUbuntuの場合、LXCパッケージをインストールするとAppArmor関連のファイルも同時にインストールされ、以下のプロファイルが使用できるようになります。
- lxc-container-default
- lxc.aa_profileでプロファイルを指定しない場合はこのプロファイルが使われます
- lxc-container-default-with-nesting
- lxc-container-defaultに、コンテナ内でコンテナを動作させる場合に必要な権限が追加されます
- lxc-container-default-with-mounting
- lxc-container-defaultに、ファイルシステムをマウントするための権限が追加されます
- unconfined
- デフォルトで指定されるlxc-container-defaultを無効にしたい場合に指定します
もちろん自分で作成した独自のプロファイルも使えます。
SELinux
ホストOSでSELinuxが利用できる環境では、AppArmorと同様にコンテナが使うSELinuxのコンテキストが指定できます。
今のところ、多くのディストリビューションでSELinuxを有効にしてLXCのパッケージを作成しているようです。しかしコンテナに対してSELinuxを使うように設定しているディストリビューションは今のところないようです。
Seccomp
SeccompはLinuxカーネルに実装されている、実行できるシステムコールを設定できるフィルタリング機能です。
LXCではlxc.seccomp
にフィルタリングを記述したファイルを指定して利用します。1.0.5からlxc-create
でコンテナを作成する際にincludeされる、各ディストリビューションの標準設定ファイルでLXCが標準で準備するフィルタリングが適用されるようになりました。
このcommon.seccomp
ファイルは以下のような内容です。
このファイルの1行目はバージョン番号を表しており、現在は1か2が指定できます。
2行目はポリシーのタイプを指定します。
バージョン1の場合はSeccompのポリシーはホワイトリストのみとなるので、whitelist
のみが指定できます。そして3行目以降に実行可能なシステムコールの番号を書きます。
たとえば以下のように書くと、コンテナ内では103番のシステムコール(syslog)のみが実行可能になります。
バージョン2の場合は先にあげたcommon.seccomp
のようにblacklist
を指定して、ポリシーとしてブラックリストの指定ができます。
そしてアーキテクチャをブラケット"[]"で指定し、その後の行の一行にシステムコール名をテキストで書くとともに、そのシステムコールが呼ばれた際の処理を記述します。
先にあげたcommon.seccomp
の場合は、"[all]
"で全てのアーキテクチャを指定し、システムコールのkexec_load
, open_by_handle_at
, init_module
, finit_module
, delete_module
が呼ばれた場合は全てエラー番号1を返しています。
LXCのマニュアルにはこれ以上の情報がなく、アーキテクチャや処理として何が書けるかがわかりません。
LXCのソースコードを見る限り、以下が指定できるようです。
処理はlibseccompのマニュアルであるseccomp_rule_add(3)の説明で挙げられている有効なアクションに対応しているようです。カーネル付属文書のprctl/seccomp_filter.txtにも解説があります。
ネットワーク
LXCのネットワーク設定の基本的な設定項目を説明した後、いろいろな設定を行った場合の実例を紹介します。
インターフェースの指定 ~lxc.network.link
コンテナにはホストの物理的なインターフェースを割り当てることもできますし、vethやmacvlanのような仮想的なインターフェースを割り当てることもできま
す。
このときにコンテナが使うホスト上のインターフェースを指定します。
このように設定すると、コンテナはホストのeth0経由で通信を行います。
UbuntuのLXCパッケージの/etc/lxc/default.conf
では以下のように設定されており、コンテナはLXC用に作られたブリッジlxcbr0
に接続されます。
コンテナ起動時のインターフェースの動作 ~lxc.network.flags
lxc.network.flags
にup
と指定すると、コンテナ起動時にコンテナのネットワークインターフェースを起動させます。
コンテナでネットワークを使う場合は通常行う設定ですね。
仮想インターフェースのMACアドレス ~lxc.network.hwaddr
コンテナに仮想インターフェースを割り当てる際の、仮想インターフェースのMACアドレスを指定したい場合に行う設定です。設定しない場合は自動的にランダムなMACアドレスが設定されます。
このように設定するとそのままの値が設定されますし、x
という文字を使うとその部分はランダムな値となります。
UbuntuのLXCパッケージの/etc/lxc/default.conf
には以上のようなx
を使った値が設定されています。これを使うとテンプレートにMACアドレスを指定して、コンテナ作成時に固定値が割り当てできます。
ネットワークタイプの設定 ~lxc.network.type
コンテナに対して設定するネットワークインターフェースのタイプをlxc.network.type
で設定します。この設定には以下の6つの値が設定できます。
none
この値を設定するとコンテナ用に新しいネットワーク名前空間を作成しません。つまりホストのネットワークをそのまま使います。
ただしシステムコンテナの場合で、ホストでもコンテナ内でもUpstartのようなUNIXドメインソケット経由で命令を受け取るようなプログラムを使っている場合、ホストと名前空間が分離していないと正常に動作しません。
アプリケーションコンテナでホストのネットワークインターフェースを使いたいような場合に使えるでしょう。
empty
コンテナ内にループバックインターフェースのみを作成します。
以上のように設定して起動したコンテナ内のネットワークインターフェースは以下のようにloのみとなります。
veth
第6回で紹介したvethを使ってペアのインターフェースを作り、片方をホストに、もう片方をコンテナに割り当てます。
vethペアのホスト側のインターフェース名は自動的に付与されます。lxc.network.veth.pair
を使うと、このホスト側のインターフェース名を指定できます。
UbuntuでLXCパッケージを入れてデフォルトのまま使用するとコンテナは以下のように設定されます。
lxc.network.hwaddr
は/etc/lxc/default.conf
で
と設定されており、lxc-create
時に"x"が置き換えられます。
このように設定してコンテナを起動すると、コンテナ内のネットワークインターフェースは以下のようになります。
このとき、ホスト側のvethインターフェースは以下のような名前になっています。
ここでlxc.network.veth.pair
を使って名前を指定してみます。
以上のように指定した名前でホスト側のvethインターフェースが作成されています。
macvlan
第6回で紹介したmacvlanインターフェースをlxc.network.link
に指定したネットワークインターフェースに作成し、コンテナに割り当てます。
第6回で説明したようにmacvlanにはモードが存在しますので、どのモードを使用するかをlxc.network.macvlan.mode
で指定します。
macvlanのモードを使った実例はあとで紹介します。
vlan
Linuxカーネルの持つVLANを扱う機能を使い、lxc.network.link
で指定されたネットワークインターフェース上にVLANインターフェースを作成し、コンテナに割り当てます。
タグVLANのIDはlxc.network.vlan.id
で指定します。
phys
lxc.network.link
で指定したネットワークインターフェースを直接コンテナに割り当てます。指定したインターフェースはコンテナのネットワーク名前空間に割り当てられますので、当然ホスト上では見えなくなります。
ホスト上や他のコンテナで使っていないネットワークインターフェースの場合に指定できます。
コンテナのIPアドレスの指定
システムコンテナを起動する場合は、LXCの設定ファイルでは最低限の設定だけ行い、UbuntuやDebianの/etc/network/interfaces
や、CentOSやFedoraの/etc/sysconfig/network-scripts
以下の設定ファイルなどで、各ディストリビューションのネットワークの設定方法に従ってコンテナ内で設定を行えば、コンテナにIPアドレスやデフォルトゲートウェイを設定できます。
しかし、アプリケーションコンテナの場合は直接アプリケーションが起動しますので、システムコンテナの起動時のようにネットワークの設定を行うところがありません。
このような場合はコンテナの設定ファイルにアドレスの指定を行います。
たとえば、Apacheを起動するアプリケーションコンテナで以下のような設定を行います。
以上のようにlxc.network.ipv4
で"アドレス/ネットマスク"とブロードキャストアドレスをスペース区切りで指定し、lxc.network.ipv4.gateway
でゲートウェイのアドレスを指定します。
lxc.network.ipv4.gateway
には"auto"という値も設定できます。このときは、lxc.network.link
で指定したインターフェースの最初のアドレスを使います。
この設定を行って、アプリケーションコンテナを起動してみます。
以上のようにlxc.network.ipv4
で設定した10.0.3.200でapacheが起動し、正常にアクセスできるのが確認できました。
ここで紹介したIPv4の例と同様にlxc.network.ipv6
, lxc.network.ipv6.gateway
でIPv6のアドレスも設定できます。
macvlanを使ったコンテナ
第6回でmacvlanの各モードについて説明をしました。そのときはそれぞれのモードを実際に設定したときにどのような動きになるかの紹介はしませんでしたので、今回コンテナの設定とあわせて紹介します。
第6回で説明した通り、macvlanはホストOSのネットワークと同じネットワークに属するアドレスをコンテナで使用するときに使います。
macvlanをコンテナで使用するには先に説明した通り、lxc.network.type
でmacvlan
を指定します。
では、macvlanインターフェースをホストOS上のeth0に作成し、コンテナを起動してみましょう。
ここの例では、ホストOSのeth0は以下のように192.168.122.0/24に属しており、このネットワークではDHCPサーバが動いています。
コンテナの設定は以下のようになります。
ではコンテナを起動してみましょう。
ご覧のように、DHCPサーバからアドレスをもらってホストOSと同じネットワークに接続されたコンテナが起動しています。ではコンテナのインターフェースを確認してみましょう。
確かに192.168.122.224が割り当たっています。
コンテナから外部への通信も問題なく行えています。
第6回のmacvlanの説明では、macvlanに設定できるいくつかのモードを紹介しました。そのうち、privateモードとbridgeモードを紹介しましょう。
privateモード
先ほどの例の環境でもう1つコンテナを起動してみましょう。ネットワークの設定を、lxc.network.hwaddr
以外は同じにしたct02
という名前のコンテナを起動してみます。
お互いに向けてpingを実行します。
お互いに通信ができません。そうです、第6回で説明したように、macvlanインターフェースがprivateモードに設定されていると同じインターフェースに属するmacvlanインターフェース同士の通信ができません。
ここで起動した2つのコンテナct01
とct02
は両方ともprivateモードに設定されているのです。lxc.network.type
でmacvlan
を指定した場合のデフォルトのモードはprivateとなります。
もちろん、以下のように明示的にも指定できます。
第6回で説明したように、macvlanインターフェースとmacvlanインターフェースを割り当てたインターフェースの間は通信できないことも確認しておきましょう。
bridgeモード
ホストOS上の同じインターフェースに属するmacvlanインターフェースを持つコンテナ同士の通信を行いたい場合はbridgeモードに設定します。
上記の設定を行ってコンテナを起動します。
pingを実行してみましょう。
以上のようにct01
とct02
の間で通信ができます。各コンテナとホスト間の通信はprivateモードと同じくできません。
複数のネットワークインターフェースの割り当て
コンテナには複数のネットワークインターフェースを割り当てることができます。
ホストOSにlxcbr0
(10.0.3.1)というブリッジとeth0
(192.168.122.26)というインターフェースがある場合に以下のような設定を行ってみます。
複数のインターフェースを定義する場合は、上記のように同じインターフェースに対する定義を固めて書かないと予期しない結果になる可能性がありますので注意しましょう。
コンテナ内にも複数のインターフェースが起動するような設定を行います。ここではct01
はUbuntuコンテナでしたので、/var/lib/lxc/ct01/rootfs/etc/network/interfaces
(コンテナ内では/etc/network/interfaces
)に以下のような設定を追加しました。
そしてコンテナを起動すると、以下のように2つアドレスが割り当たっています。
図で示すと図1のようになります。コンテナ用の隔離したネットワークを構成したりするのに使えますね。
コンテナ内でインターフェースの情報を見ると以下のようになります。設定ファイルに書いた順にeth0
がvethインターフェース、eth1
がmacvlanインターフェースになっています。
まとめ
今回はセキュリティとネットワークに関する主な設定を紹介し、ネットワークについては実際に設定したときの動きもいくつか見てみました。
ネットワーク関係の設定で紹介できていない設定項目についてはman lxc.container.conf
をご参照ください。
前回と今回でLXCでコンテナを起動する際の基本的な設定を紹介しました。もう少し進んだ使いかたをする際の設定については、この連載の後の回で紹介する予定です。
さて、今回まででLXCでコンテナを使う場合の基本的な使い方や設定が紹介できました。LXCを使う場合の代表的なディストリビューションであるUbuntuでの紹介もあわせて行いましたので、次回以降は他のディストリビューション特有のLXCの使い方を紹介していきます。
次回は筆者と同じくPlamo Linuxのメンテナをつとめており、LXCに付属するPlamo Linux用テンプレートのメンテナンスだけでなく、LXCの開発にも参加されている田向さんにPlamo特有の使い方やPlamoならではの進んだ使い方の紹介をしていただく予定です。
その後も田向さんにRPM系の代表的なディストリビューションであるFedoraでのLXCの使いかたの紹介をしていただく予定です。
お楽しみに。