在开发中,经常会查看当前服务器开启的端口,比如查看某些软件启动后默认的开放端口、端口是否支持外网访问、当前网络连接数如何,等等。

在Internet RFC标准中,Netstat的定义是: Netstat是在内核中访问网络连接状态及其相关信息的程序,它能提供TCP连接,TCP和UDP监听,进程内存管理的相关报告。

Netstat是控制台命令,是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。Netstat用于显示与IP、TCP、UDP和ICMP协议相关的统计数据,一般用于检验本机各端口的网络连接情况。

常见参数

指令 含义
-a (all) 显示所有选项,默认不显示LISTEN相关
-t (tcp) 仅显示tcp相关选项
-u (udp) 仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化成数字。
-l 仅列出有在 Listen (监听) 的服务状态
-p 显示建立相关链接的程序名
-r 显示路由信息,路由表
-e 显示扩展信息,例如uid等
-s 按各个协议进行统计
-c 每隔一个固定时间,执行该netstat命令。

指令操作

列出所有的tcp协议的端口,结果如下:

root [~] netstat -t
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State      
tcp        0     52 192.168.3.82:ssh            192.168.17.98:miles-apart   ESTABLISHED
tcp        0      0 ::ffff:192.168.3.82:mysql   ::ffff:192.168.3.83:43000   ESTABLISHED

显示所有tcp建立的连接详细信息:

root [~] netstat -anpt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name  
tcp        0      0 127.0.0.1:9000              0.0.0.0:*                   LISTEN      1637/php-fpm        
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      1814/nginx          
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1271/sshd          
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      1613/master        
tcp        0     52 192.168.3.82:22             192.168.17.98:2621          ESTABLISHED 26257/sshd          
tcp        0      0 :::3306                     :::*                        LISTEN      11078/mysqld        
tcp        0      0 :::22                       :::*                        LISTEN      1271/sshd          
tcp        0      0 ::1:25                      :::*                        LISTEN      1613/master        
tcp        0      0 ::ffff:192.168.3.82:3306    ::ffff:192.168.3.83:43000   ESTABLISHED 11078/mysqld

和上面指令类似,但是我们把n参数去掉。如果没有带n选项,会将套接字所对应的域名解析出来,如果加上n选项,那么就不会显示,即禁止域名解析的功能,这样做有助于提高查询速度,因为减少了对主机域名的查询:

root [~] netstat -apt
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name  
tcp        0      0 localhost:cslistener        *:*                         LISTEN      1637/php-fpm        
tcp        0      0 *:http                      *:*                         LISTEN      1814/nginx          
tcp        0      0 *:ssh                       *:*                         LISTEN      1271/sshd          
tcp        0      0 localhost:smtp              *:*                         LISTEN      1613/master        
tcp        0     52 192.168.3.82:ssh            192.168.17.98:miles-apart   ESTABLISHED 26257/sshd          
tcp        0      0 *:mysql                     *:*                         LISTEN      11078/mysqld        
tcp        0      0 *:ssh                       *:*                         LISTEN      1271/sshd          
tcp        0      0 localhost:smtp              *:*                         LISTEN      1613/master        
tcp        0      0 ::ffff:192.168.3.82:mysql   ::ffff:192.168.3.83:43000   ESTABLISHED 11078/mysqld

显示路由表:

root [~] netstat -r
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
192.168.3.0     *               255.255.255.0   U         0 0          0 eth1
link-local      *               255.255.0.0     U         0 0          0 eth1
default         192.168.3.1     0.0.0.0         UG        0 0          0 eth1

仅列举出监听(listen)的服务:

root [~] netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State      
tcp        0      0 127.0.0.1:9000              0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN      
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      
tcp        0      0 :::3306                     :::*                        LISTEN      
tcp        0      0 :::22                       :::*                        LISTEN      
tcp        0      0 ::1:25                      :::*                        LISTEN

local address

在查看网络详细信息的时候,Local Address有几种显示,编程中也对应了不同的实现方式。

代码或程序中有以下四种方式:
Listen *:80
Listen 0.0.0.0:80
Listen 127.0.0.1:80
Listen 192.168.0.3:80

在netstat中对应显示:
:::80
0.0.0.0:80
127.0.0.1:80
192.168.0.3:80

含义分别是:
Listen on any IP address (IPv4 or IPv6),支持任意IPv4和IPv6。
Listen on any IPv4 address on that server,支持任意IPv4.
Listen on IPv4 localhost only,仅支持本地访问。
Listen on external IPv4 address 192.168.0.3,绑定具体IP地址192.168.0.3。

State状态

netstat有多种状态,主要是因为TCP有三次握手和四次挥手。

握手过程:
1. 主动连接端发送一个SYN包给被动连接端;
2. 被动连接端收到SYN包后,发送一个带ACK和SYN标志的包给主动连接端;
3. 主动连接端发送一个带ACK标志的包给被动连接端,握手动作完成。

挥手过程:
1. 主动关闭端发送一个FIN包给被动关闭端;
2. 被动关闭端收到FIN包后,发送一个ACK包给主动关闭端;
3. 被动关闭端发送了ACK包后,再发送一个FIN包给主动关闭端;
4. 主动关闭端收到FIN包后,发送一个ACK包,当被动关闭端收到ACK包后,四次挥手动作完成,连接断开。

状态名 含义
CLOSED 初始(无连接)状态。
LISTEN 侦听状态,等待远程机器的连接请求。
SYN_SEND 在TCP三次握手期间,主动连接端发送了SYN包后,进入SYN_SEND状态,等待对方的ACK包。
SYN_RECV 在TCP三次握手期间,主动连接端收到SYN包后,进入SYN_RECV状态。
ESTABLISHED 完成TCP三次握手后,主动连接端进入ESTABLISHED状态。此时,TCP连接已经建立,可以进行通信。
FIN_WAIT_1 在TCP四次挥手时,主动关闭端发送FIN包后,进入FIN_WAIT_1状态。
FIN_WAIT_2 在TCP四次挥手时,主动关闭端收到ACK包后,进入FIN_WAIT_2状态。
TIME_WAIT 在TCP四次挥手时,主动关闭端发送了ACK包之后,进入TIME_WAIT状态,等待最多MSL时间,让被动关闭端收到ACK包。
CLOSING 在TCP四次挥手期间,主动关闭端发送了FIN包后,没有收到对应的ACK包,却收到对方的FIN包,此时,进入CLOSING状态。
CLOSE_WAIT 在TCP四次挥手期间,被动关闭端收到FIN包后,进入CLOSE_WAIT状态。
LAST_ACK 在TCP四次挥手时,被动关闭端发送FIN包后,进入LAST_ACK状态,等待对方的ACK包。

另外,对于linux-time-wait过多的优化,可以参考这篇文章:
https://love.ranshy.com/linux-time-wait%e8%bf%87%e5%a4%9a%e4%bc%98%e5%8c%96/