VPN プロセスにはどの Linux ケイパビリティが必要か
インターフェースの設定、ルート、デバイスへのアクセス、通常のソケットは別々の権限です。CAP_NET_ADMIN を付与する前に、失敗した操作を特定してください。
VPN デーモンには特権的なネットワーク操作が必要ですが、通常のアプリケーションは何の特権もなく外向きのソケットを開けます。その隙間こそ、多くのケイパビリティの誤りの起点であり、誰かが権限エラーを見て一式を付与し、後から誰も説明できない理由でサービスが動いてしまいます。以下の手順は、失敗した操作から始まり、それを一つの権限に対応づけ、そのうえでプロセスが実際に動いている文脈を確認します。制限のない root として動かすのは一部の配備では妥当な答えですが、既定値ではなく判断であるべきです。
失敗した操作から始める
チュートリアルを読む前に、エラーを読んでください。インターフェース変更での「操作は許可されていません」、デバイスノードを開く際の拒否、低いポートでのバインド失敗は、それぞれ別の許可を必要とする三つの問題です。プロセスが起動して最初のルート変更でだけ失敗するなら、インターフェースの作成はすでに成功していることになり、答えはかなり絞られます。
サービスを止めた状態で失敗を再現し、実装が許すなら同じユーザーのままフォアグラウンドで起動してください。目に見えるエラーは推測しなければならないログ行より優れており、ケイパビリティの問題と SELinux や AppArmor による拒否の違いがはっきりします。
各操作を一つの権限に対応づける
この表は出発点の地図であり、実装のドキュメントの代わりではありません:
| Operation | Usual authority | Watch for |
|---|---|---|
| Create or configure tun/tap | CAP_NET_ADMIN in the relevant namespace | Creating the device and opening it are separate steps |
| Add routes, rules, firewall entries | CAP_NET_ADMIN | Same capability, different namespace than you think |
| Open /dev/net/tun | Device permissions, not a capability | Group membership or a udev rule may be enough |
| Raw sockets | CAP_NET_RAW | Needed by some user-space tunnel implementations |
| Bind a port below 1024 | CAP_NET_BIND_SERVICE | Irrelevant for most modern tunnel ports |
この表の二行こそ、人が混同しやすいところです。/dev/net/tun を開くのはファイル権限の問題であり、開いたものを設定するようカーネルに求めるのはケイパビリティの問題です。CAP_NET_ADMIN を付与しても、サービスのユーザーが読めないデバイスノードは直りませんし、ノードを直してもルートの権限は得られません。どちらかを変える前に、両方を確認してください。
カーネルの WireGuard とユーザー空間のトンネルプログラムも、要件は同じではありません。カーネルモジュールの経路は既存のインターフェースを netlink 経由で設定しますが、ユーザー空間の実装はデバイスも必要とすることがあり、一部のトランスポートでは生のソケットも要ります。
文脈を読む: サービス、コンテナ、シェル
ホストのネットワーク名前空間におけるケイパビリティは、意図的に分離されたスタック内の同じ操作よりはるかに大きな影響を与え得ます。コンテナランタイムは通常、縮小されたバウンディングセットで起動し、ホストのネットワークを共有するコンテナに NET_ADMIN を追加するのは、独自のネットワーク名前空間を持ちホストのマウントもないコンテナに追加するより、はるかに大きな許可です。
systemd ユニットでは、ユニットファイルが言っているように見えることではなく、実際に適用されるものを読んでください: systemctl show -p CapabilityBoundingSet -p AmbientCapabilities は有効な値を報告し、それは忘れていた drop-in によって設定されているかもしれません。求めるのは有効な値であり、意図した値ではありません。ambient ケイパビリティが重要なのは、root でないサービスはそれがないと exec をまたいでケイパビリティを失うからです。
パッケージやイメージがサポートする設定を基準にし、別のチュートリアルが別のツール向けに挙げていたからといって生のソケット権限や特権モードを追加しないでください。その推論は何も移さず、支払った分離を失わせます。迷ったら何も付与せず、必要な操作について実装の注意書きを読んでください。
特権が落ちた後に何が起きるかを見る
多くのデーモンは特権で起動し、インターフェースを設定したあと、非特権ユーザーに切り替えてトンネルを維持します。その時点からプロセスはルートを追加できず、ファイアウォール規則を書き換えることも、新しい特権デバイスを開くこともできませんが、再接続がまさにそれを必要とするまでは問題ありません。後からのファイル読み取りやフック実行も同じ理由で失敗することがあります。
最初の一秒ではなくライフサイクル全体を試してください: 起動、更新や再接続、停止時の後始末です。最初のインターフェース作成が成功しても、以降のすべての特権操作が動き続ける証拠にはならず、障害は通常、本番で数時間後に現れます。
ユーザー切り替えをまたいでトンネルを開いたままにする実装は、通常トンネルと鍵を保持するオプションと組み合わせます。systemd 側で同等の問いは、ユニットのケイパビリティ集合が設定したユーザー切り替えを生き延びるかどうかです。
付与とその理由を記録する
正確な付与、それが可能にする操作、それが直したエラーを書き留めてください。配備メモの一行 —「ユニットのネットワーク名前空間における CAP_NET_ADMIN、再接続後のルート変更に必要」— で、次の人が再び付与を広げるのを防げます。
その後、更新のたびに有効な集合を読み直してください。ベンダーは機能を追加し、イメージは既定値を変え、去年は不要だったケイパビリティが誰も気づかないうちに支えになることがあります。