Claude Codeが並列にSubAgentを起動した時に自宅ネットワークが死ぬ問題を解消した – $shibayu36->blog;

表題のとおり、Claude Codeが4~5並列にSubAgentを起動した時に自宅ネットワークが死ぬ問題が起きていた。その状況になると次のような現象が起きていた。

  • pingなども含めて一切外部との通信ができなくなる
  • Claude Codeを一旦止めて数分待つと復活する

この現象について知人に相談しながら対応を進めたところ解消できたので、ログとしてブログに残しておく。ただしネットワークについて専門分野ではないため、かなり間違ったことを書くかもしれない。その場合は指摘してもらえると嬉しい。

自宅ネットワークの構成

  • ISP: enひかり + v6プラスオプション
  • ルーター: Aterm 2600HP4

再現させる

まず再現はかなり簡単に取れた。Claudeを起動し、「どういう内容でもいいので、10並列で何かの調査を行なってみて」と指示を出すと、Explore SubAgentが一斉に起動する。この状態でしばらく経つと、外部との通信が全くできなくなる。

Wiresharkでパケットを見る

ここからどう調査しようかと考えたが、まずAterm 2600HP4にはログを出す機能がないことが分かった。普通に困る。

そこでClaude Code以外を閉じてWiresharkを起動し、パケットを確認してみることにした。知人からExpert Infoを見ると良いと言われたので、それも確認する。

さて悲しいかな、知識がなく、これを見ても全くわからんとなってしまった。ひとまずChatGPTにWiresharkのパケットキャプチャとExpert Infoのスクショを渡して分析をお願いした。するとNAT周りが怪しいかも?という情報が出てきた。知人も同じ見解であった。

一方、Claude Codeを起動して並列にSubAgent起動したとしても、多くてもTCP接続のESTABLISHED状態は100程度増えるくらいであった。ルーターのNATテーブルは、ポート数のことを考えるとおそらく6万セッションほどは作れるはずだし、このくらいで上限に達する?という疑問が出てきた。

MAP-E方式のポート数制限が原因かも?という予測が立つ

すると、さらに知人から、v6プラス(MAP-E方式)でのIPv4通信の場合、ISP側でポート数が240ほどに制限されており、そっちで詰まっているのではないかという指摘があった。

確かにありそう。ただv6プラスではあるけど、この記事とは違ってWiresharkで見るとClaude CodeがQUICなどでUDP通信をしているわけではないのに詰まるんだよな〜。またClaude Code以外にもnettopでUDP通信を見てみたが、大量に接続が起きているようにも見えない。ただこれ以外に調べるポイントがなかったため、この方向で調査を進めることにした。

まずISP側でのv6プラスのポート数制限に引っかかっているということは、もし別のISP環境ではネットワークが死ぬことはないはずだ。幸い別の場所でIPv4をPPPoE接続している環境があったのと、スマホでテザリングして試すことができたので、検証してみた。

  • PPPoE環境で試した場合 => ネットワークは死なない
  • テザリングで試した場合 => ネットワークは死なない

PPPoE環境だけでなく、通信がかなり不安定なテザリング環境でも死なないことが分かったのは結構収穫だ。

ISP側ポート数制限に対して対策する

ここで対策として二つの手段が考えられそう(というのも知人に教えてもらえた)。

  • ポートセービングIPマスカレードという機能でポート数をいい感じに節約してくれる新しめなルーターを購入する
    • この記事によると、安物ルーターでも最近のやつは大体入ってるみたい
  • ISP側のv6プラス(MAP-E方式)の契約から、仕組み的にポート数が多めにもらえやすいDS-Lite形式の契約に変更する
    • 通常DS-Liteでも1000個程度のポート制限があるらしいが、enひかりだと超transixというDS-Lite方式の契約で、12800ポートほど確保できる

enひかりの超transixは、v6プラス198円/month => 超transix 399円/monthと、月額200円増やすだけで良い。ISP側のポート数を一気に増やせると検証もしやすそうだということで、ISP契約切り替えを試すことにした。

その結果、同じようにSubAgentが一斉起動したとしても、ネットワークが死ななくなった!!!ようやく解消してめでたい。

ただし原因に対しては疑問が残る…

ただ原因を完全に理解した状態になってないのは悲しい。自分の自宅環境だと契約切り替え前はかなり簡単に再現してしまっていて、

  • Claude Code以外のほとんど全ての通信をしているアプリケーションを落とし、Wireshark上でもあまりパケットが流れない状態にしておく
  • その状態でClaude Codeで5並列くらいでSubAgentを起動する

程度でもネットワークが死んでいた。前述したとおり、この時のTCPの同時接続数は100も行っておらず、240ポート数の制限にも達してない。またAnthropic APIへの接続はv6で行われていたので、そっちはポート数制限はそもそも関係ない。以下はその状況下でのnettopのスクショ。

そのため、何かもう一つの要因が重なって起きてたんだろうな〜と思う。たとえばこういうことが考えられそう。ただ全く検証できなかったので実際のところは分からない。

  • MAP-E方式は、ISP側はポート範囲を割り当てるだけで、NATテーブルの管理は自宅のルーター側に任されている。つまり、NATテーブルをどのように管理するかは、ルーター側の実装依存である
  • UDPだとタイムアウトまでNATセッションを維持してしまう問題は有名だが、ルーターによってはTCPも接続が切れた後もNATセッションをある程度維持してしまうのかもしれない
  • 結果として短期間に大量接続をしていると、TCPコネクションを切ってもしばらくはNATセッションを占有し、同時接続数が240に到達しなくても上限に引っかかってしまう

まとめ

v6プラスでのIPv4通信のネットワーク環境の場合、Claude Codeが一定並列にSubAgentなどを起動しているとネットワークが死んでしまうということが分かった。これに対して、ISP側の契約変更をしてDS-Lite形式にすると解消できた。結構困っていたので解消できて良かった!

知人に教えてもらわないと絶対解消できなかったので助かりました🙏

そのほか調べたことメモ

今回、調べる際に前提知識が無さすぎたので、一つずつ調べていくことをした。その時の調査のメモを最後に残す。

  • IPv6での通信の場合、クライアント側とサーバー側もIPが一意に決まるため、そもそもNATが不要。NATテーブルでの問題はIPv4通信の場合で起きる
  • PPPoEでのIPv4通信なら、IPv4アドレスが契約につき1つ割り当てられるのでほとんどのポート(60000個ほど?)が使える
  • MAP-EやDS-LiteなどIPv4 over IPv6の場合は、複数の契約でIPv4アドレスが共有されて、ポートで分割されている。そのため、ポート数を全て使えるわけではない
  • MAP-E方式の場合、ISP側は契約に対して静的にポート範囲を決めている。自宅のルーター側ではそのポート範囲を使って、自宅のルーター側でNATをすることになる。つまり自宅ルーター側のNAT実装が関係する
  • DS-Lite方式の場合、ルーターはIPv4パケットをカプセル化して送るだけになる。その後ISP側のAFTR(Address Family Transition Router)でNATされる。この時ISP側が動的に決められるようになるので、MAP-E方式と比較するとポート数を柔軟に使える。逆に言えばISP側のNAT実装は触れないので、そちらの制限にかかると手は出せない
  • ルーターにはポートセービングIPマスカレードという機能があり、これを使うと利用するポート数を節約してくれる。イメージとしては、ルーターが扱うポートごとに、送信元IP・送信元ポート・プロトコル・送信先IP・送信先ポートを保持しておけば、ルーター側送信ポートは同じものを使っていても、戻りパケットの送信先情報から送信元情報に逆変換できるよねってイメージ?送信先はIP(+ポート?)単位なので、かなり節約できるイメージは持つ。

参考記事




元の記事を確認する

関連記事