netstat查看tcp状态,通常看到的是 ESTABLISHED 和 TIME_WAIT,那么其他状态呢?下面用几个简单的命令来做几个实验,尝试看看能否显示出其他状态。
这里用到两台虚拟机:
192.168.136.133 是 server 端
192.168.136.134 是 client 端
(1) iptables过滤,netstat查看三次握手状态
① client = SYN_SENT
client 去 connect 一个不存在的 ip 地址即可
$ ssh 192.168.136.131 &
[1] 9129
$ netstat -nt |egrep "SYN_SENT|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 1 192.168.136.134:53910 192.168.136.131:22 SYN_SENT
$ ssh: connect to host 192.168.136.131 port 22: No route to host
[1]+ Exit 255 ssh 192.168.136.131
② server = SYN_RECV
server 把所有带 ACK 的包都丢弃,也就是只允许第一个 SYN通过,
所以可以看到服务器的 SYN_RECV 状态
server:
sudo iptables -A INPUT -p tcp -s 192.168.136.134 -m tcp --tcp-flags ACK ACK -j DROP
client:
$ ssh 192.168.136.133 &
[1] 9135
$ kill -9 9135
server:
$ netstat -nt |egrep "SYN_RECV|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 192.168.136.133:22 192.168.136.134:42404 SYN_RECV
$ sudo iptables -D INPUT 1
③ client = ESTABLISHED
正常通信即可看到:
server:
$ nc -l 8888 &
[1] 10371
client:
$ curl 192.168.136.133:8888 &
$ netstat -nt |egrep "8888|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 192.168.136.134:56368 192.168.136.133:8888 ESTABLISHED
server:
$ netstat -nt |egrep "8888|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 192.168.136.133:8888 192.168.136.134:56368 ESTABLISHED
$ kill -9 10371
(2) iptables过滤,netstat查看四次挥手状态
⑤ client = FIN_WAIT1
server:
$ sudo iptables -A INPUT -p tcp -s 192.168.136.134 -m tcp --tcp-flags FIN FIN -j DROP
client:
$ ssh 192.168.136.133 &
[1] 9074
oo2@uu2:/mnt/hgfs/ex/27.go.tcp$ kill -9 9074
[1]+ Stopped ssh 192.168.136.133
$ netstat -nt |egrep "22|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 1 192.168.136.134:42380 192.168.136.133:22 FIN_WAIT1
server:
$ sudo iptables -D INPUT 1
⑥ server = CLOSE_WAIT
因为 CLOSE_WAIT
是等待应用层关闭套接字,如果不关闭,就会处于这个状态,所以在 server 端发现 client 端关闭后,不关闭套接字,即可看到该状态:
server.py:
import socket
def tcplink(sock, addr):
print ('Accept new connection from %s:%s...' % addr)
while True:
data = sock.recv(1024)
if data:
print ('recv from',addr,":",data.decode())
else:
pass
if __name__ == '__main__':
my_address = ('192.168.136.133', 8888)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(my_address)
s.listen(5)
sock,addr = s.accept()
tcplink(sock, addr)
s.close()
client.py:
import socket
if __name__ == '__main__':
server_address = ('192.168.136.133', 8888)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(server_address)
s.send("hello world".encode())
s.close()
server:
$ python3 server.py &
[1] 33280
client:
$ python3 client.py
server:
$ netstat -nt |egrep "8888|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 192.168.136.133:8888 192.168.136.134:53182 CLOSE_WAIT
$ kill -9 33280
⑦ client = FIN_WAIT2
server = LAST_ACK
server.py:
import socket
def tcplink(sock, addr):
print ('Accept new connection from %s:%s...' % addr)
#sock.send('Welcome!')
while True:
data = sock.recv(1024)
if data:
print ('recv from',addr,":",data.decode())
else:
print ('recv null')
sock.send("hello world".encode())
sock.close()
break
print ('%s:%s closed.'%addr)
if __name__ == '__main__':
my_address = ('192.168.136.133', 8888)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(my_address)
s.listen(5)
sock,addr = s.accept()
tcplink(sock, addr)
s.close()
client.py:
import socket
if __name__ == '__main__':
server_address = ('192.168.136.133', 8888)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(server_address)
s.send("hello world".encode())
s.shutdown(socket.SHUT_WR)
#s.close()
while True:
pass
server:
$ sudo iptables -A OUTPUT -p tcp -d 192.168.136.134 -m tcp --tcp-flags FIN,ACK FIN,ACK -j DROP
$ python3 server.py
client:
$ python3 client.py &
[1] 8994
$ netstat -nt |egrep "8888|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 11 0 192.168.136.134:56310 192.168.136.133:8888 FIN_WAIT2
$ ss -t |egrep "8888|State"
State Recv-Q Send-Q Local Address:Port Peer Address:Port
FIN-WAIT-2 11 0 192.168.136.134:56310 192.168.136.133:8888
$ kill -9 8994
server:
$ netstat -nt |egrep "8888|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 1 192.168.136.133:8888 192.168.136.134:56310 LAST_ACK
ss -t |egrep "8888|State"
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LAST-ACK 0 1 192.168.136.133:8888 192.168.136.134:56310
$ sudo iptables -D INPUT 1
⑧ client = TIME_WAIT
TIME_WAIT 是最常见的:
$ curl 1.1.1.1
$ netstat -nt |egrep "1.1.1.1|State"
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 192.168.136.134:35168 1.1.1.1:80 TIME_WAIT
网友评论