LINUX:それぞれのsocketプログラムを再起動しない場合、ESTABのTCPリンクを切り離す


TCPといえば、何が3回握手して、4回手を振ったのですか.今回議論したいのは
      socket     ,  ESTABLED     ???

シナリオシミュレーション
簡単に、同じマシンでncでserverとclientを実現しましょう
# Server
nc -l -p 5555
# Client
nc localhost 5555 -p 6666

サーバ側は5555ポートで傍受し、clientは6666ポートで接続する
流量をより明確に見るために、tcpdumpで観察します.
tcpdump -i lo  -xnn -S  #      ,   lo    
08:32:01.063394 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [S], seq 1812097880, win 43690, options [mss 65495,sackOK,TS val 2762998 ecr 2761788,nop,wscale 7], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  003c 43ae 4000 4006 f90b 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 6c02 6b58 0000 0000 a002
    0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 002a
    0x0040:  28f6 002a 243c 0103 0307
08:32:01.063416 IP 127.0.0.1.5555 > 127.0.0.1.6666: Flags [S.], seq 1320008227, ack 1812097881, win 43690, options [mss 65495,sackOK,TS val 2762998 ecr 2762998,nop,wscale 7], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  003c 0000 4000 4006 3cba 7f00 0001 7f00
    0x0020:  0001 15b3 1a0a 4ead ba23 6c02 6b59 a012
    0x0030:  aaaa fe30 0000 0204 ffd7 0402 080a 002a
    0x0040:  28f6 002a 28f6 0103 0307
08:32:01.063431 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [.], ack 1320008228, win 342, options [nop,nop,TS val 2762998 ecr 2762998], length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0034 43af 4000 4006 f912 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 6c02 6b59 4ead ba24 8010
    0x0030:  0156 fe28 0000 0101 080a 002a 28f6 002a
    0x0040:  28f6
ssの結果は、リンクが確立されたことを証明しています.
[root@5464f8622628 /]# ss -ant
State      Recv-Q Send-Q Local Address:Port               Peer Address:Port
ESTAB      0      0      172.17.0.3:6666               172.17.0.3:5555
ESTAB      0      0      172.17.0.3:5555               172.17.0.3:6666

リンクができて、お互いに通信できるようになりました
では、どうやってこのリンクを切りますか?
ポーズを間違える
伝統的な方法を試してみましょう.一般的にはiptablesに行きます.
[root@6913388a8a1e /]# iptables -A INPUT -p tcp --dport 5555 -j DROP
[root@6913388a8a1e /]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
DROP       tcp  --  anywhere             anywhere             tcp dpt:personal-agent

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

上記のルールは、宛先ポートが5555である要求を破棄することを意味します.クライアントから5555ポートに送信できるため、クライアントから情報を送信する必要があります.
ここでは、情報が送信されなくなり、tcpdumpを通じてclientから送信されたメッセージが表示されます.
08:43:44.459584 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [P.], seq 327893533:327893535, ack 3568222208, win 342, options [nop,nop,TS val 2833338 ecr 2832362], length 2
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0036 75f8 4000 4006 c6c7 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 138b 421d d4ae c000 8018
    0x0030:  0156 fe2a 0000 0101 080a 002b 3bba 002b
    0x0040:  37ea 330a
08:43:44.670096 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [P.], seq 327893533:327893535, ack 3568222208, win 342, options [nop,nop,TS val 2833359 ecr 2832362], length 2
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0036 75f9 4000 4006 c6c6 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 138b 421d d4ae c000 8018
    0x0030:  0156 fe2a 0000 0101 080a 002b 3bcf 002b
    0x0040:  37ea 330a
08:43:44.881782 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [P.], seq 327893533:327893535, ack 3568222208, win 342, options [nop,nop,TS val 2833380 ecr 2832362], length 2
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0036 75fa 4000 4006 c6c5 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 138b 421d d4ae c000 8018
    0x0030:  0156 fe2a 0000 0101 080a 002b 3be4 002b
    0x0040:  37ea 330a
.... (       8    )
tcpdumpの出力は私たちにclientが本当に努力していることを教えてくれましたが、serverは応答していません.これは本当にserverが情けないのではなく、本当に受け取っていません.すべてあの憎らしいiptablesになくされました.!clientserverが相手にしないため情緒が落ち込んでそれらの接続を放棄しますか?
[root@6913388a8a1e /]# ss -ant
State       Recv-Q Send-Q  Local Address:Port                 Peer Address:Port
ESTAB       0      2           127.0.0.1:6666                    127.0.0.1:5555
ESTAB       0      0           127.0.0.1:5555                    127.0.0.1:6666

明らかに、それらの間は真の愛であり、serverは相手にしないにもかかわらず、clientも簡単に諦めない.
そして興味深いことに、tcpdumpはまだ出力を続けています.
.....(       )
08:53:28.844326 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [P.], seq 327893533:327893535, ack 3568222208, win 342, options [nop,nop,TS val 2891776 ecr 2832362], length 2
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0036 7606 4000 4006 c6b9 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 138b 421d d4ae c000 8018
    0x0030:  0156 fe2a 0000 0101 080a 002c 2000 002b
    0x0040:  37ea 330a
08:55:31.721921 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [P.], seq 327893533:327893535, ack 3568222208, win 342, options [nop,nop,TS val 2904064 ecr 2832362], length 2
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0036 7607 4000 4006 c6b8 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 138b 421d d4ae c000 8018
    0x0030:  0156 fe2a 0000 0101 080a 002c 5000 002b
    0x0040:  37ea 330a

注意深い学生は、通信の時間が、最初から数ミリ秒、今までの2分間増加していることに気づくかもしれません.これはTCPプロトコルのRTTRTOによって決定されています.
RTT (round trip time)
TCPタイムスタンプがオンになった後に、Aは時間t 1を記録してBにパケットを送り、Bはパケットを受け取った後に時間t 2を記録してAにパケットを返し、この過程の中でt 2-t 1はRTTである
RTO(Retransmission TimeOut)すなわち再送タイムアウト時間
だから性能を節約するために、clientの再試行の時間は、このアルゴリズムに従って、絶えず増加します~しかし彼らのリンクは、すでに長く保存されています...どのくらい長く残るかは、keepalived など、多くの要因によって異なります.ここでは、ncは13分ほどでは見られません.
では、まだそんなに長くないのにiptablesの良心が発見され、妨害を放棄したらどうなるのでしょうか.
[root@6913388a8a1e /]# iptables -F
[root@6913388a8a1e /]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

次のRTOが終わると、serverはそれに対応する情報を受け取ることができて、それからclientServerはまた楽しく遊ぶことができますclientserverの真の愛を証明するのに大きな紙面を費やし、事実はそれらの専一が学ぶ価値があることを証明した.
しかし多くの时、もしclientserver冷戦、谁も相手にしないならば、これは私达にとても卵が痛くなって、もしこのように不必要なリンクならば、长い时间保存して、大量の资源を占有して、すぐに资源のボトルネックが现れて、だから私达は必ずこの行为を杀します!
正しい姿勢
まず、私たちが理解しなければならないのは、一般的な再起動プログラム、再起動機械は、実際にはfinの標識を送信して両端に行って の発生をトリガしたので、罪の縁に対して、やはり規則に従って、内部から攻め破らなければならないことです.
方法1
さっきの実験では、iptablsは邪魔できませんでしたが、姿勢が間違っているだけで、姿勢を変えて分に分けました.
[root@6913388a8a1e /]# iptables -A INPUT -p tcp --dport 5555 -j REJECT --reject-with tcp-reset
[root@6913388a8a1e /]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:5555 reject-with tcp-reset

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

これを加えると、clientのメッセージはもう待つのではなく、iptablesに耳かきを打たれた.
[root@6913388a8a1e /]# nc localhost 5555 -p 6666
p
Ncat: Connection reset by peer.
ssの結果は
[root@6913388a8a1e /]# ss -ant
State       Recv-Q Send-Q  Local Address:Port                 Peer Address:Port
ESTAB       0      0           127.0.0.1:5555                    127.0.0.1:6666
tcpdumpは更にこの電光火石の瞬間を目撃して、2番目の新聞のRresetのflagsで、このようにclientのあちらのリンクが直接リセットして切れます.
09:59:55.472340 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [P.], seq 3009865367:3009865369, ack 1955226254, win 342, options [nop,nop,TS val 3290439 ecr 3289331], length 2
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0036 d667 4000 4006 6658 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 b366 e697 748a 628e 8018
    0x0030:  0156 fe2a 0000 0101 080a 0032 3547 0032
    0x0040:  30f3 700a
09:59:55.472362 IP 127.0.0.1.5555 > 127.0.0.1.6666: Flags [R], seq 1955226254, win 0, length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0028 0000 4000 4006 3cce 7f00 0001 7f00
    0x0020:  0001 15b3 1a0a 748a 628e 0000 0000 5004
    0x0030:  0000 fe1c 0000

しかし、TCPの全二重ですね.さっき切れたのは、clientからserverまで、serverからclientまでです.さっきの方法で、逆にやります.
PS:先のINPUTを削除することに注意してください.そうしないとresetは自分で禁止され、5555に送信できません.
root@6913388a8a1e /]# iptables -F
[root@6913388a8a1e /]# iptables -A OUTPUT -p tcp --dport 6666 -j REJECT --reject-with tcp-reset
[root@6913388a8a1e /]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
REJECT     tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:6666 reject-with tcp-reset
serverからメッセージが届くと、すぐに切りました.
[root@6913388a8a1e /]# nc -l -p  5555
p
[root@6913388a8a1e /]#

ssの結果:
[root@6913388a8a1e /]# ss -nat
State       Recv-Q Send-Q  Local Address:Port                 Peer Address:Port

瓜を食べながら芝居を见るtcpdump..
14:54:59.045584 IP 127.0.0.1.6666 > 127.0.0.1.5555: Flags [R], seq 379940499, win 0, length 0
    0x0000:  0000 0000 0000 0000 0000 0000 0800 4500
    0x0010:  0028 0000 4000 4006 3cce 7f00 0001 7f00
    0x0020:  0001 1a0a 15b3 16a5 6e93 0000 0000 5004
    0x0030:  0000 fe1c 0000


#          ,     server 5555          ,              tcpdump    iptables        ..

そこでこの友达はこのようにそれぞれ物を走って、江湖に忘れました.
方法2
この方法は使いやすいですが、操作すると本当に気持ち悪いです.しかも誤傷しやすいので、2つ目の方法があります.簡単で優雅です.tcpkill直接:
tcpkill -1 -i eth0 port 5555

お互いにメッセージを送ると、直接乾くことができます.tcpkillの原理はさっきのiptablesと似ていて、リンクリセットのRフラグメッセージを送信して、相手に接続をオフにさせますが、相対的にスマートです.メッセージを自動的に構築して送信するからです.詳細は以下を参照してください.https://github.com/stanzgy/wi...
まとめ
実はここまで来て、みんなはいくつかの印象があるべきで、第1の方法にしても、第2の方法にしても、その不思議なRから離れられませんが、これらは何ですか?
これらは、TCP通信中に決定的な役割を果たすフラグビットflagsであり、主に以下のいくつかがある.
  • SYN:接続の確立を示す
  • FIN:接続を閉じることを示し、
  • ACK:応答を示す
  • PSH:DATAデータ伝送があることを示し、
  • RST:接続リセットを示します.

  • 上記の方法で使用されるのが最後のフラグです:RST したがって、iptablesDROP行為は、リンクの確立を阻止することができるが、すでに確立されたリンクについては、データの伝送を阻止するしかないが、リンクを切断することはできない.リンクの切断は以下のいくつかの可能性しかないはずだ.
  • socketのアクティブclose、すなわちfinメッセージ(アプリケーション層プログラムまたはカーネル)
  • を送信する.
  • TCPリンクのタイムアウト自動切断(このプロセスは比較的時間がかかる可能性がある)
  • 偽造メッセージ送信RST
  • 上の条件のほかに、もう一つ注意しなければならないことがあります.それは:
    場合によっては、たとえ相手が閉じても、自分では感知できない.send回、通信1回、socketのエラーをトリガーしなければならない.例えば、Connection reset by peer.Broken pipeなど、自分が閉じることができることを知ることができる.そうしないと、みんな通信しない.
    各位の大神の指点交流を歓迎して、QQ討論群:258498217、転載して出所を明記してください:https://segmentfault.com/a/11...