コンテナがトンネルを開かなかったので特権フラグを入れたら、動くようになった。この手順が示したのは、少なくとも一つの権限が欠けていたということであり、どれが欠けていたかは何も語らない。特権モードは、トンネルインターフェースが必要とするよりはるかに広い権限の集合とデバイスアクセスを与える。

フラグが実際に変えるもの

特権コンテナは広範な権限とホストのデバイスへのアクセスを受け取るが、これはネットワーク経路が必要とするよりはるかに大きな許可である。正確な集合は言い伝えではなく実行環境が文書化しており、Docker のコンテナ実行に関する文書が利用できる特権オプションを説明している。一度読めば、トンネルが全体のごく一部であることが分かる。

より狭い二つの要件がほとんどの VPN コンテナを覆う。インターフェースの設定にはネットワーク管理の権限が必要であり、トンネルデバイスを開くにはその特定のデバイスノードへのアクセスが必要である。これらは別々の許可であり、両方を与えても包括的なオプションよりは狭い。特権集合の残りはトンネルとは何の関係もない。ホストレベルのアクセスを本当に必要とするワークロードのために存在し、VPN コンテナは通常その一つではない。

各エラーを一つの前提条件に対応させる

エラーメッセージは、抑え込む前に読めば、どの前提条件が欠けているかを教えてくれる。デバイスノードに関するメッセージはデバイスを名指しし、許可されていない操作に関するメッセージは権限を名指しし、モジュールや sysctl に関するメッセージはカーネルサポートを名指しする。それぞれ修正方法が異なり、そのうち権限なのは一つだけである。

欠けている設定ファイルは、すべての権限を与えた後も欠けたままであり、だから特権モードが何も変えないこともある。コンテナは起動し、トンネルは依然として失敗し、本当のエラーは権限の話ではなかった。カーネルサポートは第三のケースであり、最も読み違えやすい。ホストに読み込まれていないモジュールは非特権コンテナの中から読み込むことはできず、コンテナ内で権限を増やしてもホストの状態は変わらない。

症状ではなく要件を確認する

イメージが文書化している最小の呼び出しから始め、実行し、失敗の正確なテキストを残す。次に許可を一つずつ追加し、どの追加で結果が変わったかを記録する。

ls -l /dev/net/tun
docker run --rm --cap-add NET_ADMIN --device /dev/net/tun image:tag
ip -br link show type tun

デバイスが見え、権限も持っているのに失敗するコンテナは、問題が別の場所にあると告げている。それは有用な結果であり、特権モードはそれを隠していただろう。

正しく与えられたデバイスノードでもグループ所有権が誤っていると許可が欠けているのと同じエラーになるため、ホスト側のデバイス権限も確認すること。

機能する最小の許可を記録する

配備に必要なデバイスと権限を、それを正当化したエラーとともに書き留める。その記録があれば次の人が安全に何かを外せ、コンテナが特権付きとして報告されたときに監査人が求めるのもそれである。

ホストネットワーク、ホストのマウント、実行環境のオプションはそれぞれ許可の影響を広げうるため、周囲の文脈も見直すこと。それらをすべて組み合わせた隔離された実験環境の呼び出しは、どれほどうまく動いても本番構成ではない。配備を完了と呼ぶ前に、アプリケーション、その DNS の挙動、トンネルの失敗を試すこと。インターフェースを作る許可は外向きのポリシーではなく、完璧にトンネルを張れるコンテナでもアプリケーションが送るものはすべて経路に乗る。

関連記事