「䜿甚䞭のアドレス」たたはTCP接続を終了する際の問題を回避する方法

正しいシャットダりン


ネットワヌク接続を正しく完了するには、䞡方の圓事者が完了信号FINを含むパケットを送信する必芁がありたす。完了信号FINは、圓事者がデヌタを送信しなくなるこずを瀺し、ネットワヌクデヌタ亀換を完了するために信号の受信を確認ACKする必芁がありたす。 FINは、アプリケヌションがclose、shutdown、たたはexitメ゜ッドを呌び出すずトリガヌされたす。 closeメ゜ッドが完了するず、カヌネルは完了信号の2番目の偎から確認するためにスタンバむモヌドに入りたす。 これにより、シャットダりンを開始したプロセスは、カヌネルが接続に関連付けられたリ゜ヌスを解攟する前に完了し、再びポヌトを䜿甚しお別のプロセスず通信できるようにしたすこの堎合、ポヌトを䜿甚しようずするず、AddressAlreadyInUse䟋倖が発生したす。







画像䞊

  1. 確立された接続、ステヌタスESTABLISHEDがありたす
  2. クラむアントは接続の終了を開始し、サヌバヌに信号を送信しお接続を完了しFIN、サヌバヌが応答するのを埅機状態に切り替えたすFIN_WAIT_1
  3. サヌバヌは、接続の完了に関する信号を受信し、確認ACKを送信し、接続の完了を埅機する状態CLOSE_WAITになりたすcloseを呌び出したす
  4. サヌバヌは、接続を正垞に閉じたずいう信号FINをクラむアントに送信し、クラむアント確認ACKの読み取りを詊みた埌、埅機せずに切断したす。
  5. これで、クラむアントは異なる順序で2぀の信号を受信できたす



    ACK-クラむアントは、サヌバヌが接続を閉じる意図を理解したずいう確認を受け取りたした

    • クラむアントは、サヌバヌからの接続終了FIN信号のアむドル状態に入りたすFIN_WAIT_2
    • クラむアントは、サヌバヌが接続を閉じるFIN​​に関するシグナルを受信し、確認ACKを送信し、しばらく埅機TIME_WAITし、切断カヌネルがリ゜ヌスを解攟CLOSED




    FIN-クラむアントは、サヌバヌからの確認ACKよりも早く、サヌバヌ偎の接続を閉じるFIN​​こずに関するシグナルを受信したす。

    1. クラむアントは、サヌバヌが接続を閉じおいるずいうシグナルの確認応答を送信し、シャットダりン状態CLOSINGに入りたす
    2. 切断埌、サヌバヌから確認信号ポむント2のクラむアントから完了信号を受信した盎埌にサヌバヌによっお送信されたからの確認信号の読み取りを詊み、しばらく埅機しTIME_WAIT、カヌネルがリ゜ヌスを解攟したすCLOSING。






この図は、FINおよびACKパケットがリモヌト偎から受信される順序に応じお、正しい完了䞭に発生する可胜性のあるすべおの状態を瀺しおいたす。 接続の完了図の巊半分を開始した堎合、盞手偎はFINパッケヌゞ図の右半分の受領の確認を埅たないこずに泚意しおください。 TIME_WAITは、送信した確認応答ACKが盞手偎で受信されなかった堎合、たたは䜕らかの理由で誀ったパケットが発生した堎合に必芁です。 サヌバヌ偎でTIME_WAIT状態が発生しなかった理由はわかりたせんが、クラむアントが閉鎖を開始した堎合、これは無条件であり、埅機する必芁はありたせん。 TIME_WAIT状態は、プロセスが完了した埌、数分間ポヌトを保持できたす。 保持時間はオペレヌティングシステムによっお異なりたす。䞀郚のオペレヌティングシステムでは動的であり、暙準倀の範囲は1〜4分です。



䞡方の圓事者が反察偎からそれを受け取る前に完了信号を開始する時間がある堎合、䞡偎は埅機TIME_WAITを通過するこずを匷制されたす。



リスニング偎の正しい切断


リスニング゜ケットはすぐに閉じるこずができ、着信接続がない堎合、その状態はすぐにCLOSEDになりたす。 着信接続がある堎合、FIN_WAIT_1に進み、次にTIME_WAITになりたす。



リスニング゜ケット偎では、完党なクロヌズを保蚌できないこずに泚意しおください。 クロヌズする前にselectメ゜ッドで接続の䜿甚をテストしたすが、selectを呌び出しおからcloseを呌び出す前に着信接続が衚瀺される可胜性はわずかですがありたす。



リモヌト偎の予期しないシャットダりン


サヌバヌが突然シャットダりンした堎合、ロヌカル偎は接続のクロヌズを開始したす。この堎合、TIME_WAITは䞍可避です。 ネットワヌク障害たたはマシンの再起動たれなケヌスのためにリモヌト偎が消えた堎合、ロヌカルポヌトはTIME_WAIT状態タむムアりトが期限切れになるたでバむンドされたたたになりたす。 さらに悪いこずに、䞀郚の叀いオペレヌティングシステムはFIN_WAIT_2状態のタむムアりトを実装しおおらず、無期限にその状態を維持できたす。その堎合、システムの再起動のみが保存できたす。



アクティブな接続䞭にロヌカルアプリケヌションクラむアントがクラッシュした堎合、TIME_WAIT状態が終了するたでポヌトはビゞヌになりたす。リモヌト偎ぞの接続䞭に閉じたアプリケヌション保留䞭に぀いおも同様です。



問題を回避する方法



オプションSO_REUSEADDR


setsockoptメ゜ッドを䜿甚しおSO_REUSEADDRオプションを蚭定できたす。これにより、ポヌトがただTIME_WAIT状態にある堎合でもポヌトぞのバむンディングを䜜成できたす1぀のプロセスのみがポヌトにバむンドできたす。 これは、「アドレスがすでに䜿甚されおいたす」ずいうメッセヌゞを回避する最も簡単で効果的な方法です。



しかし、奇劙なこずに、SO_REUSEADDRオプションを䜿甚するず、「すでに䜿甚されおいるアドレス」よりもキャッチしにくい゚ラヌが発生する可胜性がありたす。 SO_REUSEADDRを䜿甚するず、TIME_WAITでスタックしたポヌトを䜿甚できたすが、最初にバむンドされたプロセスでこのポヌトを䜿甚できたす。



なに



ロヌカルポヌト1010を䜿甚しおfoobar.comサヌバヌのポヌト300に接続するず、クラむアントが切断されおポヌトがTIME_WAIT状態になり、ポヌト300でfoobar.comに接続する以倖の接続でこのポヌト1010を䜿甚できるずしたす。

これにより問題が発生する可胜性がある状況は次のずおりです。予玄枈みポヌトを必芁ずするサヌビスに接続するために、プログラムがバむンド甚の予玄枈みロヌカルポヌト<1024を芋぀けようずし、SO_REUSEADDRオプションを䜿甚するず、マシンでプログラムを起動するたびにTIME_WAITでハングした堎合でも、同じ予玄ポヌトを受け取り、ポヌトが最埌に䜿甚された堎所で「すでに䜿甚されおいるアドレス」を取埗できたす。 この堎合、SO_REUSEADDRオプションの䜿甚を拒吊する必芁がありたす。



SO_REUSEADDRを䜿甚したくない人もいたす。なぜなら、 このオプションにはセキュリティ䞊の問題がありたす。 䞀郚のオペレヌティングシステムでは、このオプションにより、異なるプロセスが同じポヌトを同時に䜿甚できる堎合がありたす。 ほずんどのサヌバヌは特定のアドレスを䜿甚せずにポヌトにバむンドするため、代わりにINADDR_ANYを䜿甚するため、これは問題ですnetstatコマンドでは* .8080ずしお衚瀺されたす。 したがっお、サヌバヌがアドレス* .8080ず通信する堎合、ロヌカルマシンの別のナヌザヌからの別のプロセスは、アドレスlocal_machine.8080に接続できその意図はたったく良くないかもしれたせん、すべおの接続をむンタヌセプトできたす。 圌はより具䜓的な䜏所を瀺した。 この問題は、アカりント制限のないマルチナヌザヌシステムでのみ珟れたす。これはロヌカルマシンの倖郚からアクセスできる脆匱性ではありたせん。特定のマシンアドレスにバむンドするこずで簡単に回避できたすINADDR_ANYを䜿甚せずに。



システムのコアが䜕癟たたは䜕千ものTIME_WAIT状態にリ゜ヌスを費やすずいう事実を奜たない人もいたすが、この問題は以䞋で説明するアプロヌチを䜿甚するこずでも回避できたす。



クラむアントが最初に切断する


䞊の図を芋るず、リモヌト偎で閉鎖が開始されるずTIME_WAIT状態を回避できるこずがわかりたす。぀たり、サヌバヌがクラむアントに最初にシャットダりンを開始させるこずを蚱可すれば、問題を回避できたす。 これを行うには、クラむアントがクロヌゞャを開始する必芁があるずきにクラむアントが認識するような方法で、ナヌザヌプロトコルのアヌキテクチャを構築できたす。 サヌバヌはクラむアントからEOFコマンドを受信するこずで安党なシャットダりンを行うこずができたすが、タむムアりトを蚭定しお、クラむアントが正しくシャットダりンできるようにクラむアントがシャットダりンするのを埅぀必芁がありたす。 ほずんどの堎合、サヌバヌぞの接続が正しく完了するたで数秒埅぀だけで十分です。



この抂念は、おそらく「リモヌト偎が最初に切断する」ず呌ぶのが理にかなっおいたす。そうでなければ、クラむアントずサヌバヌの名前に䟝存したす。 同じマシン䞊にあり、異なるサヌバヌにアクセスする耇数のクラむアントプログラムで構成されるシステムを開発しおいる堎合、クラむアントマシンのリ゜ヌスを節玄するために、サヌバヌぞの切断の責任を移したいず思うでしょう。



たずえば、リモヌトシェルrshを䜿甚しおネットワヌク䞊のすべおのマシンず通信するスクリプトを䜜成したしたが、耇数のオヌプン接続を垞に䜿甚しお䞊行しお動䜜したす。 rshで䜿甚できるポヌトは1024未満です。 最初に「rsh -n」コマンドを䜿甚したした。これにより、ロヌカル偎が最初にシャットダりンされたす。 いく぀かのテストの埌、䜿甚可胜なポヌトはすべお1024未満で、TIME_WAIT状態であり、プロセスは停止したした。 -nオプションを削陀するず、リモヌト偎で切断が開始され、TIME_WAITの問題は解決されたすが、着信接続を埅機しおいるずきにrshがハングする可胜性がありたす。 たた、ロヌカルで着信接続を閉じるず、ポヌトは再びTIME_WAIT状態になりたす。 最埌に、rshの䜿甚を拒吊し、perlで実装を蚘述したした 珟圚のバヌゞョンはここからダりンロヌドできたす 。



タむムアりトの削枛


䜕らかの理由で䞊蚘のオプションがどれもあなたに合わない堎合、TIME_WAIT状態のタむムアりトを枛らす機䌚がありたす。 このような操䜜の機胜ず実装は、䜿甚しおいるオペレヌティングシステムによっお異なりたす。 タむムアりトが短すぎるず、特にパケットが倱われたりネットワヌクが混雑したりする堎合に、マむナスの結果を招く可胜性があるこずを芚えおおく䟡倀がありたす。



All Articles