必须牢记
网络状态
状态 |
说明 |
LISTEN | 首先服务器需要打开一个socket进行监听,监听来自远方TCP端口的连接请求 |
SYN_SENT | 表示主动连接,客户端能通过应用程序调用connect()函数进行active open。于是客户端TCP发送一个SYN以请求建立一个连接,之后状态为SYN_SEND,表示已发送一个SYN到服务器端,等待SYN 1+ACK 0响应。 |
SYN_RECV | 服务器端收到客户端的SYN 1+ACK 0,然后状态变为SYN_RECV。表示服务器收到了客户端发来的SYN,然后自己也响应了给客户端一个SYN 1+ACK 1,然后等待客户端确认。 这时候客户端过来的连接(属于半连接状态)被放在一个SYN队列里面,SYN泛洪***也是这样的,就是服务器响应了SYN+ACK之后,客户端就不在发送ACK了,然后继续发送SYN,直到把服务器的最大连接数量耗尽。 半连接队列长度是由内核参数tcp_max_syn_backlog来决定的。 |
ESTABLISHED | 代表一个打开的连接,客户端收到服务器发送的SYN 1+ACK 1,就变为这个状态,然后向服务器发送ACK,如果服务器收到这个ACK,那么它也变为这个状态。这个状态就是表示连接以及建立,正在或即将传输数据。服务器收到ACK以后就会把半连接从上面提到的SYN队列中删除,然后放到ACCEPT队列中,这时这个半连接的状态就变成了ESTABLISHED。 |
FIN_WAIT1 | 主动关闭端(可以是服务器也可以是客户端)应用程序调用了close,于是其TCP发出FIN主动关闭请求,也就是四次断开的第一次,之后就进入了FIN_WAIT1状态,等待远程主机的ACK请求。 |
CLOSE_WAIT | 被动关闭端(可以是服务器有可以是客户端)收到了对方发来的FIN后,进入该状态,然后发出ACK+1以回应FIN请求(它的接收也作为文件结束符传递给上层应用程序)。这个状态实际上是说客户端告诉服务器我没有请求或者数据要发送了,等待看看服务器或者说是进程还有没有数据要发送,如果有则继续发送,如果没有的话,就发送反向关闭指令。 如果服务器大量连接是这个状态就要去查看程序,很有可能是程序设计的问题。 |
FIN_WAIT2 | 主动关闭端收到ACK+1后,就进入的FIN_WAIT2状态,也就等服务器是否还有数据发来,如果服务器没有数据了,那么服务器就发送的反向关闭指令。也就是反向关闭连接指令FIN1+ACK1。实际上是告诉客户端我的数据发送完了,可以关闭连接了。 |
LAST_ACK | 被动关闭端,发送反向结束连接请求FIN 1+ACK 1,然后进入LAST_ACK状态,等待主动关闭端发送ACK。 |
TIME_WAIT | 主动关闭端收到FIN 1 +ACK 1后,并进入TIME_WAIT状态,然后发送ACK+1,等待一段时间(2MSL)以确保服务器收到了ACK+1,然后自己进入CLOSED状态。这个阶段主要是客户端为了再次确认一下服务器是否可以关闭连接,因为网络毕竟是不可靠的。 对于服务器有大量TIME_WAIT这个问题通常调整sysctl来解决。 |
CLOSING | 比较少见,表示等待远程TCP对连接中断的确认。 |
CLOSED | 被动关闭端在收到ACK包以后,就进入closed状态,连接结束。 |
三次握手
四次断开
为什么TIME_WAIT要等2MSL时长?
服务器发送FIN给客户端,之后自己进入LAST_ACK阶段,客户端收到FIN之后会发送ACK并进入TIMW_WAIT阶段,如果服务器没有收到客户端最后的ACK,那么它将会重发FIN,所以一个包的最大生存时间就是1MSL,客户端等2倍就是为了防止这种情况发生,这样就有时间来接收服务器重发的FIN信号。
古老的netstat命令
说它古老是因为它的确很古老目前已经被ss命令所替换,虽然在目前的CetnOS中还可以使用,但是它执行效率比ss命令要低。
参数和输出说明
不加任何参数将会输出2部分内容:
-
Active Internet connections 活动的internet连接,包含TCP和UDP。
-
Active UNIX domain sockets 活动UNIX本地套接字连接
参数 | 说明 |
-a | 显示所有选项 |
-t | 仅显示TCP相关选项 |
-u | 仅显示UDP相关选项 |
-n | 尽量不显示名称,而用数字代替,比如主机名换成IP显示 |
-l | 仅列出在Listen监听的服务状态 |
-p | 显示建立相关网络的程序名和进程号,也就是本机哪个进程开启的这个网络链接 |
-r | 显示路由表,作用和 route -n一样 |
-e | 显示扩展信息 |
-s | 按不同协议输出统计信息,因为协议不同,所以输出的统计选项也不同 |
-c | 每隔固定时间刷新 |
# 这里只显示了TCP的连接信息
netstat -anetp
列 |
说明 |
Proto | 协议 |
Recv-Q | 数据已经接收到本地套接字,但是还有多少没有被程序取走的字节,从2.6.18内核开始这里包含了半连接队列数据也就是对方发过来的SYN请求数据 |
Send-Q | 远程主机未确认的字节数,从2.6.18内核开始这里包含了半连接队列数据也就是服务器发送了SYN+ACK的数据量。 |
Local Address | 套接字在本地IP地址和端口 |
Foreign Address | 套接字远程的IP地址,也就是客户端或者上层代理的IP和端口 |
State | 网络连接状态 |
User | 运行该进程的账户,也就是该服务器网络套接字属于谁 |
Inode | |
PID/Progam name | 服务器端监听或者处理该端口请求的程序 |
常用命令组合
# 查看当前正在监听的TCP端口有哪些 netstat -alnt # 查看当前所有TCP端口的状态 netstat -nat # 查看当前所有的TCP端口状态并列出进程ID netstat -natp # 查看特定进程的网络连接状态 netstat -natp | grep PID
查看源IP中处于TIME_WAIT状态数量最多的前20名IP
netstat -nat | grep TIME_WAIT | awk '{print $5}' | sort | uniq -c | sort -rn | head -n 20
# sort排序,默认正向排序
# uniq -c 取出重复项 -c 统计个数
# sort -rn 再次排序反向,同时以数字进行,默认是纯文本
# head -n 20 显示前20个
查看访问80端口最多的前20个IP,其实道理和上面的类似
netstat -natp | grep 8080 | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -rn | head -n 20
查看连接状态统计信息
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
查看已经建立连接和正在监听的,你想查看其它状态也是类似的
netstat -natl | egrep "ESTABLISHED|LISTEN"
查看指定端口且状态为ESTABLISHED的连接数量
# grep -i 表示忽略大小写 est 表示 ESTABLISHED
netstat -nlap | grep -i est | grep -i 2181 | wc -l
SS命令
参数 | 说明 |
-a | 显示所有选项 |
-t | 仅显示TCP相关选项 |
-u | 仅显示UDP相关选项 |
-n | 尽量不显示名称,而用数字代替,比如主机名换成IP显示 |
-l | 仅列出在Listen监听的服务状态 |
-p | 显示建立相关网络的程序名和进程号,也就是本机哪个进程开启的这个网络链接 |
-s | 显示连接状态统计信息 |
-r | 解析服务的名称,ssh变成22这种。端口名称和端口号的解析,IP和机器名的解析 |
-x | 显示UNIX套接字 |
-m | 显示套接字内存使用 |
-e | 显示扩展信息 |
其实可以看到这里很多参数和netstat相似,所以使用也很方便,我们这里直接通过场景来说明
统计当前连接状态信息
ss -s
显示TCP或者UDP连接信息
# 加a就是所有的tcp连接信息
ss -at
查看所有TCP打开的端口
显示连接到指定目标端口所有的连接,这里的目的或者源相对于本机来说,下面的命令含义是本机连接远程443或者80的
ss -nt '( dst :443 or dst :80 )'
显示所有源端口或目的端口是ssh
ss -at '( dport = :ssh or sport = :ssh )'
查看所有连接到本机22端口的连接
ss -nt sport = :ssh
显示所有TCP建立连接的
ss -t4 state established
# 可用状态 time-wait syn-sent syn-recv fin-wait-1 fin-wait-2 time-wait last-ack connected closed close-wait
说明
在ss命令和netstat命令都有下面的字段但是其含义不同
即使在ss命令中不同场景其含义也不同
如果State是LISTEN状态:这里的含义就是上面说的Recv-Q是当前全连接队列使用量;Send-Q是当前对应进程SOCKET套接字最大blacklog的数量,也就是全连接队列最大长度
如果State不是LISTEN状态:
Recv-Q:数据已经接收到本地缓存,还有多少没有被程序取走,单位bytes
Send-Q:要发送的数据有多少还在本地缓冲区远程主机未确认,如果不是0可能是本地发送数据过快或者对方接收数据过慢,单位bytes
其他网络监控命令
iftop
# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 需要设置源
yum -y install iftop
# 安装完执行下面的命令
iftop -nP
=> 代表发送 <= 代表接收
最右边rates的三列数字,表示2秒、10秒和40秒的平均流量
cum表示从运行iftop开始到目前时间的总流量,peak流量峰值
TX:表示发送总量
RX:表示接收总量
TOTAL:表示全部总量
注意:在显示过程中按下列键可以切换模式
T:是否显示每个连接的总流量
B:分别显示2秒、10秒和40秒的平均流量
P:暂停显示/继续显示
nethogs
# rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 需要设置源 yum -y install nethogs # 安装完执行下面的命令
nethogs
当运行时按:
q:退出
s:对SENT列进行排序
r:对REVEIVE进行排序
m:切换显示单位