Claude Codeのネットワーク制御をコンテナ外部で行うサンドボックス環境
#Claude_Code
意図せず加害者になるリスク
rmコマンドで自分の環境が壊れるならまだ自分だけの被害に止まる可能性が高いが、ネットワークを通じて外部のサーバーへアクセスできることは意図しない攻撃になる可能性がある。
Claude Codeにファイル書き込みと一定のコマンドが許可れていれば、その他のコマンド実行を防ごうしても、以下のような経路でコマンドは実行できる。
大抵のビルドツールはコマンド実行があるので、ファイルを書き換えてビルド時に任意のコマンド実行。
system()、popen、subprocessなど各言語の標準ライブラリを使う方法にコードを書き換えて実行。
find ... -exec 任意のコマンド \;のような抜け道。
上記のような実行はしないようにシステムプロンプトか学習なのかで制御しているようだが、ネットの情報をもとにClaude Codeが試行錯誤する過程で実行されるかもしれない。コマンド以外にも大体の言語にはHTTP通信やTCP通信するライブラリがあるからそれを使ったコードを書いて意図せず攻撃するかもしれない。
コンテナ内のファイアウォール
ネットワークを制限するためにコンテナ内のiptablesを設定例をよく見かける。
例えば、Claude Codeのdevcontainersも以下を読む限りコンテナ内にファイアウォール設定がある。
https://github.com/anthropics/claude-code/blob/55219b8b4e612b5fc6a85f7dc4eb4382ec4134eb/.devcontainer/Dockerfile
新しいツールを導入しやすくするためにroot権限が欲しくなるが、root権限があるとファイアウォール設定を書き換えられてしまうので、root権限を与えるわけにはいかない。
解決策:コンテナ外部でアクセス制御
根本的な解決のためのアプローチはネットワーク制御をClaude Codeが動くコンテナ外部ですること。
技術的にはdocker run --network noneをというネットワークから遮断されたコンテナにClaude Codeを置いて、-vオプションでHTTPプロキシ経由でネットワークにアクセスできるようにする。
この発想自体はClaude Codeに限らず利用できる。
以下のような構成。
code:t
+------------------ Host machine -------------------+
| |
| Internet <--> Squid <--> socat |
| (:13128) (Relay) |
+---------------------------------------------------+
^
| (Volume Mount)
| (Unix domain socket)
| /tmp/squid_for_claude.sock
v
+------------ Container (network=none) -------------+
| |
| socat <--> Claude Code App |
| (Relay) (via HTTP_PROXY) |
+---------------------------------------------------+
以下のリポジトリコードの全体がある。
https://github.com/nwtgck/claude-code-isonet
以下のようにClaude Codeの入ったコンテナをdocker runする。
code:bash
docker run -it --network none -v /HTTPプロキシ.sock:/HTTPプロキシ.sock <Claude Code入りのDockerイメージ>
/HTTPプロキシ.sockはUnix domain socketで、雑に説明するとポートをファイルのように使える。例えばDockerのdocker.sockにcurlでアクセスすると以下のようにHTTPサーバのように機能する。
code:console
$ curl --unix-socket /run/docker.sock http://localhost/info | jq
{
"ID": "...",
...
Claude Codeのコンテナ内で以下のようにsocatコマンドを使えばlocalhost:3128がHTTPプロキシになる。
code:bash
socat TCP-LISTEN:3128,reuseaddr,fork UNIX-CONNECT:/HTTPプロキシ.sock
(先述のリポジトリではこれは自動で実行されるようになっている。)
そのためClaude Codeのコンテナで環境変数HTTP_PROXY=http://127.0.0.1:3128やALL_PROXY=http://127.0.1:3128を設定すればHTTPプロキシ経由でネットワークにアクセスできる。繰り返しになるがdocker run --network noneをしているためこのプロキシ以外のネットワークへのアクセス手段がない。
HTTPプロキシはSquidを使っていてドメインを指定して許可するサーバーを決められる。
(Claude Codeのdevcontainersは頑張ってIPアドレスを取得して許可している。)
code:squid.conf
http_port 3128
acl allowed_domains dstdomain .github.com .registry.npmjs.org .api.anthropic.com .console.anthropic.com .sentry.io .statsig.anthropic.com .statsig.com .ubuntu.com
acl allowed_ports port 80 443
http_access allow allowed_domains allowed_ports
http_access deny all
以下のようにgithub.comにはアクセスできるが、example.comはブロックできている。
https://gyazo.com/1609406d71c55f011bb156990a16994a
sudoが使えるのでClaude Codeがaptコマンドをインストールできる。
https://gyazo.com/a31906238ad845b80d98b5d49d816ab9
リポジトリについて
https://github.com/nwtgck/claude-code-isonet
README.mdの手順にしたがってclaude_isonet.shを実行するとカレントワーキングディレクトリに以下のような構成でコンテナのファイルが共有される。
$PWD/container_share/.claude:コンテナの~/.claude。
$PWD/container_share/ws:コンテナ内の~/wsのワークスペース。
他のツールを既存でインストールしたい場合はリポジトリのDockerfileを修正してbuild_claude_isonet.shすると良い。
この方法の限界と今後
HTTPプロキシに対応している必要がある。aptやcurlやClaude CodeはHTTPプロキシに対応しているが対応していないソフトウェアもあるはず。今後のこととして、SOCKSプロキシにしてproxychainsかtsocksを使ってコンテナのentrypointのbash自体からSOCKSプロキシを使うようにすればあらゆコマンドがプロキシ経由になって汎用的なのではと考えている。