Problem
How to kill an ESTABLISHED TCP connection in Linux.
Solution #1: passive mechanism
We can use a little tool called tcpkill that you can find desription and example usage here link
tcpkill -i eth0 { expression }
When started it first listens on a wire for any traffic matching your expression filter (that is compatible with tcpdump expressions). This is passive mechanism to learn about the TCP ACK and SEQ numbers. Once it knows the numbers it spoofs a TCP segments and try to reset the TCP session on both sides.
If the TCP session is idle or in generic there is no data being exchanged than this passive mechanism unfortunately is not going to work.
Solution #2: active mechanism
This killcx tool is taking a different approach and tries to generate traffic on the wire to discover what the ACK and SEQ numbers are. Once it forces the peer to replay to its spoofed traffic it kills the TCP session immediately after.
killcx.pl dest_ip:dest_port
Simple demonstration
- tcpkill (passive)
root@server:~# nc -v -l 7777 Connection from 164.177.146.87 port 7777 [tcp/*] accepted a
root@client:~# nc -D 5.79.21.166 7777 a b
Below are tcpdumps showing TCP handshaking and 1 byte exchange on both hosts.
root@server:~# tcpdump -i any -nn port 7777 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes 23:15:59.049739 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [S], seq 2946797440, win 14600, options [mss 1460,sackOK,TS val 726987371 ecr 0,nop,wscale 2], length 0 23:15:59.049803 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [S.], seq 2303834803, ack 2946797441, win 14480, options [mss 1460,sackOK,TS val 350774705 ecr 726987371,nop,wscale 3], length 0 23:15:59.051394 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [.], ack 1, win 3650, options [nop,nop,TS val 726987375 ecr 350774705], length 0 23:16:00.815434 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [P.], seq 1:3, ack 1, win 3650, options [nop,nop,TS val 726987816 ecr 350774705], length 2 23:16:00.815493 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [.], ack 3, win 1810, options [nop,nop,TS val 350775146 ecr 726987816], length 0
root@client:~# tcpdump -i any -nn port 7777 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes 23:20:38.159839 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [S], seq 2946797440, win 14600, options [mss 1460,sackOK,TS val 726987371 ecr 0,nop,wscale 2], length 0 23:20:38.174837 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [S.], seq 2303834803, ack 2946797441, win 14480, options [mss 1460,sackOK,TS val 350774705 ecr 726987371,nop,wscale 3], length 0 23:20:38.174880 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [.], ack 1, win 3650, options [nop,nop,TS val 726987375 ecr 350774705], length 0 23:20:39.938895 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [P.], seq 1:3, ack 1, win 3650, options [nop,nop,TS val 726987816 ecr 350774705], length 2 23:20:39.939313 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [.], ack 3, win 1810, options [nop,nop,TS val 350775146 ecr 726987816], length 0
At this point from another terminal on the server we can verify that the connection exists and start the tcpkill to try to kill it.
root@server:~# netstat -tulpan | grep 7777 tcp 0 0 0.0.0.0:7777 0.0.0.0:* LISTEN 1338/nc tcp 0 0 5.79.21.166:7777 164.177.146.87:50185 ESTABLISHED 1338/nc root@server:~# tcpkill -i eth0 -9 port 50185
At this stage nothing is going to happen because neither the client or server sending any data. The tcpkill simply hangs and waits. The open TCP session continue to exists. But as soon as we sent another byte from the client to the server these is being logged on the tcpdump sessions for the tcpkill, client and server.
tcpkill
root@server:~# tcpkill -i eth0 -9 port 50185 tcpkill: listening on eth0 [port 50185] 164.177.146.87:50185 > 5.79.21.166:7777: R 2303834804:2303834804(0) win 0 164.177.146.87:50185 > 5.79.21.166:7777: R 2303838454:2303838454(0) win 0 164.177.146.87:50185 > 5.79.21.166:7777: R 2303845754:2303845754(0) win 0 164.177.146.87:50185 > 5.79.21.166:7777: R 2303856704:2303856704(0) win 0 164.177.146.87:50185 > 5.79.21.166:7777: R 2303871304:2303871304(0) win 0 164.177.146.87:50185 > 5.79.21.166:7777: R 2303889554:2303889554(0) win 0 164.177.146.87:50185 > 5.79.21.166:7777: R 2303911454:2303911454(0) win 0 164.177.146.87:50185 > 5.79.21.166:7777: R 2303937004:2303937004(0) win 0 164.177.146.87:50185 > 5.79.21.166:7777: R 2303966204:2303966204(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946797445:2946797445(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946799255:2946799255(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946802875:2946802875(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946808305:2946808305(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946815545:2946815545(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946824595:2946824595(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946835455:2946835455(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946848125:2946848125(0) win 0 5.79.21.166:7777 > 164.177.146.87:50185: R 2946862605:2946862605(0) win 0
client
root@client:~# tcpdump -i any -nn port 7777 ... 23:21:03.938535 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [P.], seq 3:5, ack 1, win 3650, options [nop,nop,TS val 726993816 ecr 350775146], length 2 23:21:03.943047 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [.], ack 5, win 1810, options [nop,nop,TS val 350781146 ecr 726993816], length 0 23:21:03.943070 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303834804, win 0, length 0 23:21:03.943082 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303838454, win 0, length 0 23:21:03.943086 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303845754, win 0, length 0 23:21:03.943090 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303856704, win 0, length 0 23:21:03.943093 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303871304, win 0, length 0 23:21:03.943096 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303889554, win 0, length 0 23:21:03.943099 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303911454, win 0, length 0 23:21:03.943102 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303937004, win 0, length 0 23:21:03.943106 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303966204, win 0, length 0
Server
root@server:~# tcpdump -i any -nn port 7777 ... 23:16:24.815402 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [P.], seq 3:5, ack 1, win 3650, options [nop,nop,TS val 726993816 ecr 350775146], length 2 23:16:24.815449 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [.], ack 5, win 1810, options [nop,nop,TS val 350781146 ecr 726993816], length 0 23:16:24.816040 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303834804, win 0, length 0 23:16:24.816080 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303838454, win 0, length 0 23:16:24.816103 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303845754, win 0, length 0 23:16:24.816130 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303856704, win 0, length 0 23:16:24.816153 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303871304, win 0, length 0 23:16:24.816177 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303889554, win 0, length 0 23:16:24.816199 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303911454, win 0, length 0 23:16:24.816225 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303937004, win 0, length 0 23:16:24.816245 IP 5.79.21.166.7777 > 164.177.146.87.50185: Flags [R], seq 2303966204, win 0, length 0 23:16:24.816280 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946797445, win 0, length 0 23:16:24.816314 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946799255, win 0, length 0 23:16:24.816339 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946802875, win 0, length 0 23:16:24.816362 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946808305, win 0, length 0 23:16:24.816384 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946815545, win 0, length 0 23:16:24.816407 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946824595, win 0, length 0 23:16:24.816429 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946835455, win 0, length 0 23:16:24.816451 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946848125, win 0, length 0 23:16:24.816474 IP 164.177.146.87.50185 > 5.79.21.166.7777: Flags [R], seq 2946862605, win 0, length 0
We can see that as soon as the new byte generate 2 TCP segment the tcpkill learns about the SEQ and ACK numbers and generate its RST packet to desynchronize and kill the TCP session.
- killcx (active)
server
root@server:~# tcpdump -i any -nn port 7777 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes 23:46:06.228566 IP 164.177.146.87.50189 > 5.79.21.166.7777: Flags [S], seq 11257294, win 14600, options [mss 1460,sackOK,TS val 727439173 ecr 0,nop,wscale 2], length 0 23:46:06.228625 IP 5.79.21.166.7777 > 164.177.146.87.50189: Flags [S.], seq 1319656020, ack 11257295, win 14480, options [mss 1460,sackOK,TS val 351226499 ecr 727439173,nop,wscale 3], length 0 23:46:06.233328 IP 164.177.146.87.50189 > 5.79.21.166.7777: Flags [.], ack 1, win 3650, options [nop,nop,TS val 727439174 ecr 351226499], length 0 23:46:07.960259 IP 164.177.146.87.50189 > 5.79.21.166.7777: Flags [P.], seq 1:3, ack 1, win 3650, options [nop,nop,TS val 727439605 ecr 351226499], length 2 23:46:07.960322 IP 5.79.21.166.7777 > 164.177.146.87.50189: Flags [.], ack 3, win 1810, options [nop,nop,TS val 351226932 ecr 727439605], length 0 # at this moment the TCP is estabilished and the server received one byte # we see this as soon as the killcx is started 23:46:32.411167 IP 164.177.146.87.50189 > 5.79.21.166.7777: Flags [S], seq 10, win 65535, length 0 23:46:32.411194 IP 5.79.21.166.7777 > 164.177.146.87.50189: Flags [.], ack 3, win 1810, options [nop,nop,TS val 351233045 ecr 727439605,nop,nop,sack 1 {4283710012:4283710013}], length 0 23:46:32.413315 IP 164.177.146.87.50189 > 5.79.21.166.7777: Flags [R], seq 11257297, win 65535, length 0 23:46:32.414945 IP 5.79.21.166.7777 > 164.177.146.87.50189: Flags [R], seq 1319656021, win 65535, length 0
client
root@client:~# tcpdump -i any -nn port 7777 tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes 23:50:45.365610 IP 164.177.146.87.50189 > 5.79.21.166.7777: Flags [S], seq 11257294, win 14600, options [mss 1460,sackOK,TS val 727439173 ecr 0,nop,wscale 2], length 0 23:50:45.370015 IP 5.79.21.166.7777 > 164.177.146.87.50189: Flags [S.], seq 1319656020, ack 11257295, win 14480, options [mss 1460,sackOK,TS val 351226499 ecr 727439173,nop,wscale 3], length 0 23:50:45.370059 IP 164.177.146.87.50189 > 5.79.21.166.7777: Flags [.], ack 1, win 3650, options [nop,nop,TS val 727439174 ecr 351226499], length 0 23:50:47.097391 IP 164.177.146.87.50189 > 5.79.21.166.7777: Flags [P.], seq 1:3, ack 1, win 3650, options [nop,nop,TS val 727439605 ecr 351226499], length 2 23:50:47.098888 IP 5.79.21.166.7777 > 164.177.146.87.50189: Flags [.], ack 3, win 1810, options [nop,nop,TS val 35122693221:20:14439605], length 0 # at this moment the TCP is estabilished and the client sent one byte # we see this as soon as the killcx is started 23:51:11.550122 IP 5.79.21.166.7777 > 164.177.146.87.50189: Flags [.], ack 3, win 1810, options [nop,nop,TS val 351233045 ecr 727439605,nop,nop,sack 1 {4283710012:4283710013}], length 0 23:51:11.552854 IP 5.79.21.166.7777 > 164.177.146.87.50189: Flags [R], seq 1319656021, win 65535, length 0
killcx
root@server:~# netstat -tulpan | grep 7777 tcp 0 0 0.0.0.0:7777 0.0.0.0:* LISTEN 10568/nc tcp 0 0 5.79.21.166:7777 164.177.146.87:50189 ESTABLISHED 10568/nc root@manage2:~# ./killcx.pl 164.177.146.87:50189 killcx v1.0.3 - (c)2009-2011 Jerome Bruandet - http://killcx.sourceforge.net/ [PARENT] checking connection with [164.177.146.87:50189] [PARENT] found connection with [5.79.21.166:7777] (ESTABLISHED) [PARENT] forking child [CHILD] interface not defined, will use [eth0] [CHILD] setting up filter to sniff ACK on [eth0] for 5 seconds [PARENT] sending spoofed SYN to [5.79.21.166:7777] with bogus SeqNum [CHILD] hooked ACK from [5.79.21.166:7777] [CHILD] found AckNum [11257297] and SeqNum [1319656021] [CHILD] sending spoofed RST to [5.79.21.166:7777] with SeqNum [11257297] [CHILD] sending RST to remote host as well with SeqNum [1319656021] [CHILD] all done, sending USR1 signal to parent [10726] and exiting [PARENT] received child signal, checking results... => success : connection has been closed !
As before the TCP session is established and idle waiting. As soon as we start the killcx it successfully spoofs a SYN packet on behalf of the client and sent it to the server. The server than replays with a valid TCP packet revealing the ACK and SEQ numbers. As soon as this this is on a wire the killcx sniffs this up and sent RST to kill the active session.
References
- http://killcx.sourceforge.net/
- http://www.cyberciti.biz/howto/question/linux/kill-tcp-connection-using-linux-netstat.php
- http://serverfault.com/questions/179702/is-it-possible-to-close-a-socket-with-a-shell-command
- http://superuser.com/questions/127863/manually-closing-a-port-from-commandline
Further reading
No comments:
Post a Comment