root権限もコンテナも不要 LandlockでLinuxのプロセスを安全にサンドボックス化できるLandrunがマジですごい
引用元:https://news.ycombinator.com/item?id=43445662
Linux Landlockは、特権のないプロセスが自分自身をサンドボックス化できるカーネルネイティブなセキュリティモジュールだけど、APIが難しすぎて誰も使ってないんだよね。だからlandrun
っていうGo製のCLIツールを作ったんだ。これを使えば、ファイルシステムやネットワークへのアクセス制御を細かく設定して、どんなコマンドでもサンドボックス化できるよ。rootもコンテナもSELinux/AppArmorの設定もいらない。軽量で監査可能だし、Landlock v5の機能(ファイルアクセスとTCP制限)をラップしてるんだ。READMEにデモと使用例があるから、みんなからのフィードバックが欲しいな!
READMEの例を試してみたけど、うまくいかなかったんだよね。
># rm -f /tmp/foo; ./landrun-linux-amd64 –log-level debug –ro /usr/bin –ro /lib –ro /lib64 –rw /tmp touch /tmp/foo
>[landrun] 2025/03/22 10:28:02 Sandbox config: {ReadOnlyPaths:[/usr/bin /lib /lib64] ReadWritePaths:[/tmp] AllowExec:false BindTCPPorts:[] ConnectTCPPorts:[] BestEffort:true}
>[landrun:debug] 2025/03/22 10:28:02 Adding read-only path: /usr/bin
>[landrun:debug] 2025/03/22 10:28:02 Adding read-only path: /lib
>[landrun:debug] 2025/03/22 10:28:02 Adding read-only path: /lib64
>[landrun:debug] 2025/03/22 10:28:02 Adding read-write path: /tmp
>[landrun:debug] 2025/03/22 10:28:02 Applying Landlock restrictions
>[landrun] 2025/03/22 10:28:02 Landlock restrictions applied successfully
>[landrun] 2025/03/22 10:28:02 Executing: [touch /tmp/foo]
>touch: cannot touch ‘/tmp/foo’: Permission denied
すごく興味深いね。Dockerで同じようなことをしてて、ボリュームをroでマウントしてるんだけど、Landlockをサーバープロセスに追加するユースケースは絶対にあると思う。
ああ、--exec
がないね。指定しなきゃいけないのはちょっと面倒だけど、明示的な方が好きだし、LSMの機能をフルに使いたいんだ。cat
みたいに--exec
がいらないケースもあると思うし。最新リリースを見てみて。ちょっときれいになってるよ。
このtouch
の例で、なんでexec
が必要なのか教えてくれませんか?実際にtouch
バイナリを起動する必要があるんですか?それともtouch
自体が何か他のものをexec()
してるんですか?
これを動かすために必要な最小限のオプションはこれだよ:landrun --log-level debug --exec --ro /usr/bin --ro /usr/lib --rw /tmp touch /tmp/foo
個人的には--exec
で/tmp
にあるバイナリも実行できるようになるのが嫌だな…
landrun --ro /usr/bin --ro /lib --ro /lib64 --rw /path/to/dir touch /path/to/dir/newfile
vslandrun --ro /usr/bin --ro /lib --ro /lib64 --exec /usr/bin/bash
ってことは、--exec
は実行するコマンドが内部でexec
コールを使う場合にだけ必要ってことみたいだね。bash
はforkするために必要だけど。だからtouch
は--exec
はいらないけど、bash
は読み込めるもの(許可された/tmp
を含む)なら何でも実行できるはず。
前者はうまくいかないよ。--exec
を追加する必要がある。touch
が/usr/bin
にあるから、そこから実行する権限が必要なんだと思う。--ro
か--rw
を使うと、--exec
も必須になるみたい。
まあ、バイナリを実行したいなら--exec
が必要だよね(cat
と違って)。Landlockが--exec
をディレクトリにバインドするのをサポートしてくれたら面白いのに!
>you’ll need –exec when you want to run binaries
え、それっていつそうじゃないの?バイナリを実行する必要がない場合、このツールをどうやって使うの?
cat
の実行は--exec
じゃないよね。
この場合、どこにあろうと”a”にアクセスできないんだね…
$ landrun –ro /usr cat /usr/bin/ls | wc -l
400
ls(実際のバイナリ実行のように)を実行するには、–execが必要だよ
$ landrun –ro /usr ls /usr/bin/
ls: ディレクトリ ‘/usr/bin/’ を開けません: 許可されません
$ landrun –ro /usr –exec ls /usr/bin/
何十億ものファイルのリスト
–exec はマジで好きじゃないんだよね。デフォルトで”オン”じゃないなら、明示的にするためだけ。
アップデート: ”ファイルアクセス”を制限するバグがあるから、すぐに修正するね。
アップデート2: 実行ファイルを制限するために–exec-pathを追加するのは、グローバルな–execを持つより良い考えではなかった。
アップデート3: V0.1.4を見てくれ、今はずっとクリーンだと思う。
–ro /usr は /usr/bin には適用されないよ。–ro /usr/bin に変更すれば、cat は実行を拒否するはず。
デフォルトで再帰的だよ。
一時的な回避策として、noexecフラグ付きの/tmp_noexecのようなtmpfsデバイスを作成して、通常の/tmpの代わりにマウントできるよ。でも、landrunは(まだ?)ディレクトリオプションの名前変更を許可してないんだよね :(
セキュリティを強化するために、landlockの呼び出しごとに一時的なtmpfsディスクを作成したいな。明らかに、実行しているプログラムは他のプロセスが/tmpに置いたものを見るべきじゃない。
>一時的なtmpfsディスクをlandlockの呼び出しごとに作るって?
それって、firejail を発明しただけじゃん。
OCI/コンテナランドで landlock を使うのは可能?意味ある?
Syd[0] は、アプリケーションをコンテナ化するために (他の多くのメカニズムの中でも) landlock を使用し、OCI互換インターフェースを提供するよ。
[0]:
https://gitlab.exherbo.org/sydbox/sydbox
リンクありがとう、Sydbox は超クールなプロジェクトみたいだけど、なんか変なところがある:README にリンクが多すぎる。GitHub にはないし、GitHub にある似た名前のプロジェクトは16年間コミットがないけど、同じ人?
もし彼らがプロジェクトのパブリックな面を磨き上げることができれば、より信頼感を植え付けられると思う。
>README のリンクが多すぎる
他のドキュメントもそう。
そして、すごい繰り返す。
PoC が使われるたびに Wikipedia へのリンクは要らないよ。strace(1) が言及されるたびにオンラインマニュアルページへのリンクもね。
ドキュメントには複数の”エントリーポイント”があり、すべての出現箇所をハイパーリンクすることでそれを解決できることは理解してる。
でも、特定の読者を想定することで、より効果的なドキュメントになると私は思ってる。小学校の子供のために、大学レベルの教科書で足し算を説明したりはしない。
この製品は strace を初めて聞く人向けではないよ。
Wikipediaの記事って、記事内のありとあらゆる単語にリンク貼ってるとこあるよね。テキスト選択しようとするとリンクが邪魔でマジで冒険だよ。昔、内部リンク全部剥がすuserscript作ったもん。([citation needed]とかのノイズ除去スクリプトに追加して)。Wikipediaには、テキスト選択時とかグローバル設定でON/OFFできる「おすすめリンク」みたいな機能が必要だよね。そしたら作者は好きなだけリンク貼れるじゃん。
>which makes trying to simply highlight a section of text a fun adventure” マジかよ知らなかった。乗り換えてよかったー。 まあね。個人的にはリンク少なすぎるより多すぎる方が嬉しいかな。足し算の説明とか、一番良い説明へのリンク貼れば済むし。 めっちゃクールだけど、サンプルもドキュメントへのリンクもないから、タブ閉じて忘れちゃうな…多くの人がそう思うんじゃないかな。 // ルールがない場合は、そのままreturn それな。新しいバージョンでそうしてほしい。 いいね。Linux Kernelのlandlock APIを直接使ってるんだ(OpenBSDのpledgeみたいに)。yamlで設定記述できると嬉しいな。コマンドをあらかじめ設定して実行できるみたいな。好みの問題か。試してみるよ。 まだ初期段階だけど、landlockの作者Mickaël Salaünがこれに取り組んでるよ。 試してみるけど、最初に聞きたいのは、これってbubblewrapと比べてどうなの? >誰も使わないのは、APIが…難しいから! OpenBSDは確かに優れてるけど、リリース間の後方互換性に対する姿勢も違うよね。Linuxの厳格なABI互換性は問題を複雑にするけど、適切なライブラリがあれば耐えられると思うよ。Readmeの例を見て!Landlockをpledgeみたいに使ってほしいな。 pledgeとunveilのABIってリリースから変わってないよね?Linuxが使いやすい新しいセキュリティプリミティブを作れない理由は何?Wireguardみたいにさ。実装者のセンス次第で、使いやすさを犠牲にせずに作れるはず。 BSDはカーネルとユーザー空間を一緒に提供するから、色々シンプルなんだよね。Linuxは柔軟だけど、その分コストがかかる。Landlockは新しいセキュリティプリミティブの一つで、進化してるよ。インターフェースが変わると古いアプリが動かなくなるから、難しいんだよね。 LinuxとBSDの仕組みは理解してるつもりだよ。でも、LinuxがWireguardみたいな便利なセキュリティプリミティブを作れない理由が分からないんだよね。pledgeとunveilは単純なsyscallでしょ?複雑なユーザーインターフェースが必要な理由がわからない。 Linuxのlibc関数って、カーネルのsyscallが変更されたり、状況によって変わったりするよね。Landlockとかseccompのフィルタはカーネルレベルだから、libcしか使ってないプログラムが動かなくなるんだ。 (抽象)unixソケットはサポートされてる?外部依存なしで動くウェブサーバーを実行しようとしてるんだけど、デーモンとワーカー間の通信(unixソケット経由)がうまくいかないみたい。bubblewrapとかdockerコンテナの中なら動くんだ。 抽象ソケットって、ネットワーク名前空間を使わないとjailから出られないんじゃない?Xorgソケットへのアクセスを防ぐには、–share-netを除外する必要があると思う。 えーと、動くべきなの?別の理由があるってこと?分からないなぁ。 macOSみたいな「ターミナルにドキュメントフォルダへのアクセスを許可しますか?」みたいな権限管理がLinuxにもあったら最高じゃん? マジでWindowsとかLinuxでそれがなくて困ってるんだよね。Chrome入れたからって、パソコンのファイル全部スキャンしていいわけじゃないのに、止められないのがマジでセキュリティとプライバシー的に大問題だと思うんだよね! Flatpakって知ってる? ちゃんとパッケージされたアプリは、最初はファイルシステムへのアクセスが制限されてるんだ。例えばFirefoxでfile:///を開いても、すべてのファイルが見えるわけじゃない。でも、「ファイルを開く」メニューを使うと、ファイルシステムへのアクセスが許可されるんだよ。macOSとはちょっと違うけど、心配してる無制限のシステムアクセスは防げるよ。 Flatpakは知ってるけど、デメリットもあるんだよね。使うと色々壊れるし。アプリの挙動がおかしくなったり、テーマが崩れたり、起動しなくなったり。それに、ネットが遅い人にとっては、Flatpakのせいでアプリのダウンロードにめっちゃ時間かかるし。Flatpakが良いのはわかるけど、Linuxはいつも開発者向けって感じで、一般ユーザーには頭痛の種だよね。 それってxdg-portalsのことだよね。ちゃんと動くよ。ただ、アプリが対応する必要があるから、普及が遅れてるんだ。 Linuxの最大の問題は、プロセスごとのファイアウォール設定がないことだと思う。AppArmorとか、アプリごとにユーザーを作ってルールを割り当てることで回避できるかもしれないけど。Linuxを10年以上使ってるけど、まだ知らないことが多いから、何か見落としてるかもしれない。GitHubのページにはTCPネットワークアクセス制御とかUDPの制限について書いてあるから、これで簡単にプロセスをファイアウォールできるかな? Linuxのネットワーク名前空間を使って、プロセスを別々のネットワークスタックで実行するのはどう? nftablesのルールはネットワーク名前空間ごとだから、高度な設定ができるし、実質的にプロセスごとのファイアウォールを実現できるよ。Systemdには 他の人の意図はわからないけど、デスクトップでは、すべてのプログラムが制限されたネットワーク名前空間で起動してほしいな。デフォルトではすべての送受信接続をブロックする代わりに、ユーザーの許可をインタラクティブに要求して、それに応じてアクセスを調整するみたいな。 Linuxでは、デフォルトのネットワーク名前空間からすべてのインターフェースを移動させて、iptablesルールで全部ブロックするのが一番近いかな。そして、物理的なインターフェースとかVPNとか、目的のネットワーク名前空間で明示的にアプリケーションを起動する必要がある。そうすれば、間違って起動したアプリとかデスクトップ環境はネットワークに接続できなくなるよ。 opensnitchがそれをするよ。 例の「ユーザーの許可をインタラクティブに要求して、それに応じてアクセスを調整する」ってやつね。それならできるよ。eBPF使ってるけど。 namespaces使う上での一番の問題は、ホストのメインファイアウォールを完全にバイパスしちゃうことなんだよね。 それは設定次第だよ。「メインホスト」のファイアウォールをバイパスする必要はないんだ。 俺は防御セキュリティの観点から話してて、トラフィックをルーティングしようとするサーバーの話じゃないんだ。 ネットワーク分離にはfirejailが使えるよ。新しいネットワークnamespaceでアプリケーションを実行できる[1]。俺はこれをTor経由でアプリケーションを実行するために使ってて、何も漏れないようにしてる。 nft meta expressionsの中にcgroupをマッチさせるオプションがあるみたい(試したことはないけど)。プロセスごとのファイアウォールルールを追加したいだけなら十分かもしれないけど、関連するインターフェースやルーティング/NATを含む追加のnamespaceを構成する必要はないね。 うん。usernameとかSELinuxラベルに基づいてパケットをマッチさせることもできるよ。 >Linuxの最大の問題は、プロセスごとのファイアウォール設定がないことだ。 cgroup2を使った例ってある? https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html プロセスごとにファイアウォールルールを設定するのはちょっと重いかもね。ネットワーク名前空間を使えば、プロセスのグループごとにネットワークルール(ファイアウォール含む)を設定できるよ。 Androidのファイアウォールアプリはみんなそうしてるよ。アプリごとにユーザー名前空間があって、ファイアウォールルールでマッチできるんだ。プログラムのPIDごとにnet名前空間があれば同じようなことができるかも。もし週末が手に入れば、GUIでファイアウォールを管理できるパッチを作りたいな。 みんな、応援ありがとう!こんなに盛り上がるとは思わなかったよ!プロジェクトはまだ2日目だから、いろいろ問題があると思うけど、もし見つけたらGitHubで報告してね! 去年のOpen Source Europe Summit EuropeでLandlockに関する良いプレゼンがあったよ。[1] Linux Sandboxing with Landlock - Mickaël Salaün, Microsoft [video]: めっちゃクールなプロジェクトだね。Justine Tunneyが数年前にLandlockをラップする NixはLandlockの恩恵を十分に受けられると思うな。なぜなら、どのプロセスがどのパスにアクセスする必要があるかを(ある程度)把握しているから。 Landlock APIは、Dockerコンテナで使われているmount/network名前空間とどう違うの?名前空間は隔離のためで、Landlockはアクセス許可みたいなものって理解で合ってる? (Landlockのレビュー担当者です) upstream kernel LSMでは、プロセスが権限を持っている場合に子名前空間を作成するのを防ぐ唯一の方法は? user.max_user_namespaces sysctl自体は名前空間を認識しており、bubblewrapの–disable-usernsオプションで使用されている。 へー、知らなかった。child processがuserns作れないようにブロックできるんだ。ちょっと強引な気もするけど、95%のケースでは問題なさそう?capabilitiesのinherit maskみたいなのがchild namespaceに欲しいよね。誰かがupstreamに提案してた気がするけど、patchは見てないな。 NO_NEW_PRIVSって結構イラつく場面多いんだよね。pingとか使えなくなっちゃうから、debuggingが大変になるじゃん! >For example, you can’t run いい答えだね、ありがとう! Namespace(コンテナが使ってるやつ)は強力だけど、攻撃されやすいんだよね。https://lwn.net/Articles/673597/ を見てみて。Landlockはアクセス制御システムだけど、信用できないprocessでも使えるように設計されてるから、どんなappにも合うんだ。seccompと相性も良いよ。 –roのoは“only”の意味だってのはわかるけど、なんかclunkyじゃない?–roxとか自己矛盾してるし。long optionはちゃんと長くて、short optionでバックアップされてるのが好みだな。-r, –read, -w, –write, -x, –execを用意して、short optionを組み合わせられるようにしたらいいと思う(-rwxとか)。 ROXは自己矛盾してないよ。read()とexecve()は許可するけど、write()とtruncate()は禁止するってのは、安全な実行環境ではよくあること。directory traverseがあると面倒だけどね。だから、–roxは意味的にはOK。見た目が悪いだけ。:D parent posterはaccessの組み合わせが無効だって言ってるんじゃなくて、read-ONLYなのにreadだけじゃないからおかしいって言ってるんだよ。 executableなら“read-only”じゃないよね。 –execの意味がいまいちわからない。example 3で–execを省略したら、bashが他のprogramを実行できなくなるってこと? ああ、あれは最良の判断じゃなかったかもね。v0.1.4を見てみてよ。今はもっと良くなってると思うよ! めっちゃクールじゃん!でももっとコメントを表示(1)
FirefoxならAltキー押しながらドラッグすればリンク踏まずにテキスト選択できるよ。
仕事ではまだChrome使ってるけどね。FFのプロファイル管理マジ無理。firefox -ProfileManager
とかコンテナじゃダメなの?
問題はリンクが自動生成っぽいとこ。しかもちょっと雑。「Syd」のリンクはPink Floydのオリジナルフロントマンじゃなくて、sandboxing技術にリンクすべきでしょ。
if len(rules) == 0 {
log.Info(”No sandbox rules to apply”)
return nil
}
めっちゃクールでよく書けてるけど、この選択には反対。ルールなし=すべて拒否であるべき。
もっと細かいファイル/ディレクトリ権限のサポートがあると嬉しいなー。もう計画されてるみたいでよかった。
https://github.com/landlock-lsm/landlockconfig
関連が出てきたらGoのbinding書く予定。
OpenBSDはpledgeとunveilで本当に良い仕事をしたよね。もっとコメントを表示(2)
NetworkNamespacePath
っていうディレクティブもあるから、新しい名前空間でサービスを起動することもできるよ。
0.追加のnetwork namespacesを設定しない場合でも、デフォルトのnetwork namespaceが存在する。これが「メインホスト」と呼ばれるもの。
1.デフォルトのnet nsに、サーバーがトラフィックを受信するデバイスeth0があるとする。
2.デフォルトのnet nsにvethペアveth0とveth1を作成する。
3.新しいnet nsを作成し、veth1を新しいnet nsに移動する。veth0とeth0のみがデフォルトのnet nsに残る。
4.通常どおり、デフォルトのnet nsにルートとnftableルールを設定する。新しいネットにルーティングしたい特定のトラフィックは、ネクストホップveth0を経由するようにする(veth0をネクストホップとして使用して、veth1のIPにルーティングする必要がある)。
5.新しいnet nsに追加のnftableルールなどを設定すると、これはデフォルトのnet nsから分離される。
エンドツーエンドのフロー:パケットはeth0に到着し、netfilter(nftables/iptables)とルート検索を経由してveth0経由で「新しいネットワーク」にルーティングされる。パケットはveth0を介してデフォルトのネットスタックから「送信」され、新しいnet nsネットワークスタック内のveth1(ペアであるため)に到着する。そこで、パケットは分離されたnetfilterとルーティングテーブルを経由し、ソケットはサービスなどをリッスンできる。応答は逆方向に同じように続く。新しいnet nsでveth1から送信され、デフォルトのnet nsのveth0に到着し、eth0を介してそのスタックを終了する
ローカルユーザーがホストのファイアウォールをバイパスするnamespacesを簡単に作成できるってことは、マジで危険だと思う。
[1]https://firejail.wordpress.com/documentation-2/basic-usage/#…
>”A network namespace is a new、 independent TCP/IP stack attached to the sandbox. The stack has its own routing table、 firewall and set of interfaces.”
コンテナごとにパケットに特別なマークを設定して、それに基づいてフィルタリングすることもできる。インターネット上にはnftのリソースが驚くほど少ないんだよね。俺は数週間かけて書き方を学んだよ。間違いなく、一般消費者向けではないね。
あるよ。cgroupsを使えばね。https://www.kernel.org/doc/Documentation/cgroup-v1/net_cls.txtもっとコメントを表示(3)
https://youtu.be/d85TDpv8L9Upledge
cli [1]をリリースしたよ。[1]:
https://justine.lol/pledge/
Landlock APIを使って、アプリによる許可されていないネットワーク/ファイルシステムアクセスをキャッチして、macOSみたいに許可を求めるポップアップを表示できるかな?
名前空間もサンドボックス化に使えるけど、いろいろ問題があるんだよね。一番の問題は、プログラムに大幅な変更が必要になること。Landlockを使えば、プログラムは起動時にLandlockポリシーをインストールするだけで済むから楽だよ。
別のプロセスからルールを制御することはまだできないけど、kernel mailing listsで提案されているよ:
https://lore.kernel.org/all/cover.1741047969.git.m@maowtm.or…
例えば、制限された名前空間内でCAP_NET_ADMINをcatできる場合、大量の欠陥のあるカーネルコードにアクセスできる。そこから権限をエスカレートするのは簡単(カーネルのバグを悪用する方法を知っている人にとっては)。
Distroにはこの問題に対する独自の修正があるので、名前空間はサンドボックス化に役立たないわけではない。しかし、基本的なメカニズムはそれほど適していない。
しかし、prctlのようなNO_NEW_PRIVSの方が良いだろう。namespace-aware sysctlに必要な中間名前空間を回避できるから。ping
, so good luck debugging your networking!
>例えば、pingが実行できないから、ネットワークのdebugging頑張ってね!”ってことだけど、Linuxならuserspaceで(UDP経由で)ICMP Echo送れるし。経験上、public InternetだとTLS connectの方がTCPとかUDP、ICMPよりも確実だよ(IPとかTransport repliesをmiddlewareが邪魔しないように)。
“色は黒なら何色でも良い”みたいな。--best-effort
がデフォルトで有効になってるのはちょっと反対かな。これってサンドボックスでセキュリティ境界なんだから、セキュリティを下げるのはオプトインであるべきで、オプトアウトであるべきじゃないと思うんだ。