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
になくされました.!client
はserver
が相手にしないため情緒が落ち込んでそれらの接続を放棄しますか?[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
プロトコルのRTT
とRTO
によって決定されています.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
はそれに対応する情報を受け取ることができて、それからclient
とServer
はまた楽しく遊ぶことができますclient
とserver
の真の愛を証明するのに大きな紙面を費やし、事実はそれらの専一が学ぶ価値があることを証明した.しかし多くの时、もし
client
とserver
冷戦、谁も相手にしないならば、これは私达にとても卵が痛くなって、もしこのように不必要なリンクならば、长い时间保存して、大量の资源を占有して、すぐに资源のボトルネックが现れて、だから私达は必ずこの行为を杀します!正しい姿勢
まず、私たちが理解しなければならないのは、一般的な再起動プログラム、再起動機械は、実際には
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番目の新聞のR
、reset
の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であり、主に以下のいくつかがある.上記の方法で使用されるのが最後のフラグです:
RST
したがって、iptables
のDROP
行為は、リンクの確立を阻止することができるが、すでに確立されたリンクについては、データの伝送を阻止するしかないが、リンクを切断することはできない.リンクの切断は以下のいくつかの可能性しかないはずだ.socket
のアクティブclose
、すなわちfin
メッセージ(アプリケーション層プログラムまたはカーネル)TCP
リンクのタイムアウト自動切断(このプロセスは比較的時間がかかる可能性がある)RST
場合によっては、たとえ相手が閉じても、自分では感知できない.
send
回、通信1回、socketのエラーをトリガーしなければならない.例えば、Connection reset by peer.
やBroken pipe
など、自分が閉じることができることを知ることができる.そうしないと、みんな通信しない.各位の大神の指点交流を歓迎して、QQ討論群:258498217、転載して出所を明記してください:https://segmentfault.com/a/11...