深入了解 Linux netstat 命令
Linux 的 netstat 命令就像一个网络侦探,它能揭示关于网络连接、端口使用情况以及背后运行的进程的丰富信息。 掌握这个命令,你就能更好地理解系统上的网络活动。
端口、进程与协议
在网络通信中,网络套接字扮演着至关重要的角色,它们是连接的端点,可以是活跃的通信通道,也可以是等待连接的监听点。 连接的建立依赖于网络协议,如 传输控制协议 (TCP) 和 用户数据报协议 (UDP)。 这些协议通过 互联网协议 (IP) 地址和 网络端口来确保数据在网络中的正确传输。
虽然“套接字”这个词可能会让人联想到物理连接点,但实际上,它是一种软件结构,负责处理网络连接的一端。它就像一个连接器,让应用程序可以发送和接收数据。
套接字主要有两种状态:一种是已连接并进行中的网络通信,另一种是等待传入连接。 当然,还有其他中间状态,比如套接字正在尝试建立连接的时候。 但总的来说,你可以把套接字看作是连接状态或等待(也称监听)状态。
处于监听状态的套接字被称为服务器,而发起连接请求的套接字则被称为客户端。 这种命名与计算机的硬件或功能无关,它们仅仅描述了连接两端各自的角色。
netstat 命令允许你查看哪些套接字已建立连接,哪些正在监听。 这意味着,它可以告诉你哪些端口正在被使用,以及哪些进程在使用这些端口。 此外,netstat 还可以显示路由表的信息,以及 网络接口和 多播连接的统计数据。
随着时间的推移,netstat 的一些功能被其他 Linux 工具所取代,例如 ip 和 ss。 然而,netstat 仍然是网络分析命令的先驱,值得学习,因为它在所有 Linux 和类 Unix 系统(包括 Windows 和 Mac)上都适用。
接下来,我们将通过一些示例命令来介绍如何使用 netstat。
列出所有套接字
使用 -a
(全部)选项,netstat 会显示所有已连接和正在监听的套接字。 这通常会产生一个很长的列表,因此我们可以将其通过管道传递给 less
命令,以便分页查看。
netstat -a | less
输出列表包括 TCP (IP)、TCP6 (IPv6) 和 UDP 套接字。
由于终端窗口的自动换行,输出内容可能难以阅读。 下面是该列表的一些重要部分:
Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 localhost:domain 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN tcp 0 0 localhost:ipp 0.0.0.0:* LISTEN tcp 0 0 localhost:smtp 0.0.0.0:* LISTEN tcp6 0 0 [::]:ssh [::]:* LISTEN tcp6 0 0 ip6-localhost:ipp [::]:* LISTEN . . . Active UNIX domain sockets (servers and established) Proto RefCnt Flags Type State I-Node Path unix 24 [ ] DGRAM 12831 /run/systemd/journal/dev-log unix 2 [ ACC ] STREAM LISTENING 24747 @/tmp/dbus-zH6clYmvw8 unix 2 [ ] DGRAM 26372 /run/user/1000/systemd/notify unix 2 [ ] DGRAM 23382 /run/user/121/systemd/notify unix 2 [ ACC ] SEQPACKET LISTENING 12839 /run/udev/control
“Active Internet”部分列出了已建立的外部连接,以及监听远程连接请求的本地套接字。 换句话说,它显示了与外部设备之间的网络连接情况。
“UNIX 域”部分列出了已连接和正在监听的内部连接。 这些是计算机内部不同应用程序、进程和操作系统组件之间的连接。
在“Active Internet”部分,各列的含义如下:
Proto: 套接字使用的协议(例如,TCP 或 UDP)。
Recv-Q: 接收队列。 这是已接收并缓冲的传入字节,等待使用此连接的本地进程读取和使用。
Send-Q: 发送队列。 这表示准备从发送队列发送的字节。
Local Address: 连接本地端的地址详细信息。 默认情况下,netstat 显示地址的本地主机名和端口的服务名称。
Foreign Address: 连接远程端的地址和端口号。
State: 本地套接字的状态。 对于 UDP 套接字,这通常是空白的。 请参考下面的状态表。
对于 TCP 连接,状态值可以是以下之一:
LISTEN | 仅限服务器端。 套接字正在等待连接请求。 |
SYN-SENT | 仅限客户端。 此套接字已发出连接请求,正在等待是否被接受。 |
SYN-RECEIVED | 仅限服务器端。 此套接字在接受连接请求后正在等待连接确认。 |
ESTABLISHED | 服务器和客户端。 服务器和客户端之间已经建立了工作连接,允许在两者之间传输数据。 |
FIN-WAIT-1 | 服务器和客户端。 此套接字正在等待来自远程套接字的连接终止请求,或等待先前从该套接字发送的连接终止请求的确认。 |
FIN-WAIT-2 | 服务器和客户端。 此套接字正在等待来自远程套接字的连接终止请求。 |
CLOSE-WAIT | 服务器和客户端。 此套接字正在等待来自本地用户的连接终止请求。 |
CLOSING | 服务器和客户端。 此套接字正在等待来自远程套接字的连接终止请求确认。 |
LAST-ACK | 服务器和客户端。 这个套接字正在等待它发送到远程套接字的连接终止请求的确认。 |
TIME-WAIT | 服务器和客户端。 这个套接字向远程套接字发送了一个确认,让它知道它收到了远程套接字的终止请求。 现在正在等待以确保收到确认。 |
CLOSED | 没有连接,所以套接字已经终止。 |
“Unix 域”部分各列的含义如下:
Proto:此套接字使用的协议。 它将是“unix”。
RefCnt:参考计数。 连接到此套接字的附加进程数。
Flags:这通常设置为 ACC
,代表 SO_ACCEPTON
,表示套接字正在等待连接请求。 SO_WAITDATA
,显示为 W
,表示有数据等待读取。 SO_NOSPACE
,显示为 N
,表示没有空间可以将数据写入套接字(即发送缓冲区已满)。
Type:套接字类型。 请参阅下面的类型表。
State:套接字的状态。 请参阅下面的状态表。
I-Node:与此套接字关联的文件系统 inode。
Path:套接字的文件系统路径。
Unix 域套接字类型可以是以下之一:
DGRAM | 套接字正在数据报模式下使用,使用固定长度的消息。 数据报既不保证可靠、有序也不重复。 |
STREAM | 这个套接字是一个流套接字。 这是常见的“正常”类型的套接字连接。 这些套接字旨在提供可靠的有序(有序)数据包传递。 |
RAW | 此套接字用作原始套接字。 原始套接字在 OSI 模型中较低层级运行,不涉及 TCP 和 UDP 标头。 |
RDM | 此套接字位于可靠传递的消息连接的一端。 |
SEQPACKET | 此套接字作为顺序数据包套接字运行,这是提供可靠、有序和不重复的数据包传递的另一种方式。 |
PACKET | 原始接口访问套接字。 数据包套接字用于在 OSI 模型的设备驱动程序(即数据链路层)级别接收或发送原始数据包。 |
Unix 域套接字状态可以是以下之一:
FREE | 此套接字未分配。 |
LISTENING | 此套接字正在侦听传入的连接请求。 |
CONNECTING | 此套接字正在连接中。 |
CONNECTED | 连接已经建立,套接字可以接收和传输数据。 |
DISCONNECTING | 连接正在被终止。 |
这些信息非常丰富! netstat 提供了很多选项来优化结果,但它们不会大幅改变内容。 接下来,我们将了解一些常用选项。
按类型列出套接字
netstat -a
命令可能会输出比你需要的更多信息。 如果你只想查看 TCP 套接字,可以使用 -t
(TCP) 选项来限制显示,只显示 TCP 套接字。
netstat -at | less
输出结果明显减少。 列出的所有套接字都是 TCP 套接字。
-u
(UDP) 和 -x
(UNIX) 选项的行为类似,它们会将结果限制为命令行上指定的套接字类型。 这是使用 -u
(UDP) 选项的示例:
netstat -au | less
此时,输出结果只显示 UDP 套接字。
按状态列出套接字
要查看处于监听或等待状态的套接字,请使用 -l
(监听)选项。
netstat -l | less
此时,列出的套接字都是处于监听状态的套接字。
这个选项可以与 -t
(TCP)、-u
(UDP) 和 -x
(UNIX) 选项结合使用,以便更精确地筛选出感兴趣的套接字。 例如,让我们查找正在监听的 TCP 套接字:
netstat -lt | less
现在,我们只看到 TCP 监听套接字。
按协议划分的网络统计信息
要查看协议的统计信息,请使用 -s
(统计)选项,并同时使用 -t
(TCP)、-u
(UDP) 或 -x
(UNIX) 选项。 如果只单独使用 -s
(统计)选项,你将看到所有协议的统计信息。 例如,让我们查看 TCP 协议的统计信息。
netstat -st | less
less 命令显示了关于 TCP 连接的统计信息。
显示进程名称和 PID
你可以通过 -p
(程序)选项查看使用套接字的进程的 进程号 (PID) 以及该进程的名称。 让我们查看使用处于监听状态的 TCP 套接字的进程的 PID 和名称。 我们使用 sudo
来确保我们获取所有可用的信息,包括通常需要 root 权限的信息。
sudo netstat -p -at
下面是格式化后的表格输出:
Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 localhost:domain 0.0.0.0:* LISTEN 6927/systemd-resolv tcp 0 0 0.0.0.0:ssh 0.0.0.0:* LISTEN 751/sshd tcp 0 0 localhost:ipp 0.0.0.0:* LISTEN 7687/cupsd tcp 0 0 localhost:smtp 0.0.0.0:* LISTEN 1176/master tcp6 0 0 [::]:ssh [::]:* LISTEN 751/sshd tcp6 0 0 ip6-localhost:ipp [::]:* LISTEN 7687/cupsd tcp6 0 0 ip6-localhost:smtp [::]:* LISTEN 1176/master
我们增加了一列名为“PID/程序名称”的列。 此列显示了使用每个套接字的进程的 PID 和名称。
列出数字地址
为了更清楚地显示地址信息,我们可以将本地和远程地址显示为 IP 地址,而不是它们解析的域名和主机名。 使用 -n
(数字)选项,IPv4 地址将以点分十进制格式显示:
sudo netstat -an | less
此时,IP 地址显示为数值形式。 端口号也会显示,并用冒号 “:” 与 IP 地址分隔开。
IP 地址 127.0.0.1
表示套接字绑定到 本地计算机的回环地址。 可以把 IP 地址 0.0.0.0
看作是本地地址的“默认路由”,以及外部地址的“任何 IP 地址”。 显示为“::
”的 IPv6 地址也都是零地址。
列出的端口可以方便地通过 查找来确定它们的常见用途:
22:安全外壳 (SSH) 的监听端口。
25:简单邮件传输协议 (SMTP) 的监听端口。
53:域名系统 (DNS) 的监听端口。
68:动态主机配置协议 (DHCP) 的监听端口。
631:通用 UNIX 打印系统 (CUPS) 的监听端口。
显示路由表
-r
(路由)选项显示内核的路由表。
sudo netstat -r
下面是清晰的表格输出:
Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface default Vigor.router 0.0.0.0 UG 0 0 0 enp0s3 link-local 0.0.0.0 255.255.0.0 U 0 0 0 enp0s3 192.168.4.0 0.0.0.0 255.255.255.0 U 0 0 0 enp0s3
下面是这些列的含义:
Destination: 目标网络或目标主机设备(如果目标不是网络)。
Gateway: 网关地址。 如果未设置网关地址,此处将显示星号“*”。
Genmask: 路由的子网掩码。
Flags: 请参考下面的标志表。
MSS: 默认最大分段大小,用于通过此路由的 TCP 连接。它是 TCP 段中可以接收的最大数据量。
Window: 默认窗口大小,用于通过此路由的 TCP 连接,表示在接收缓冲区满之前可以传输和接收的数据包数。 实际数据包由接收应用程序使用。
irtt: 初始 往返时间。 内核使用此值来动态调整对响应缓慢的远程连接的 TCP 参数。
Iface: 通过此路由发送的数据包从中传输的网络接口。
标志值可以是以下之一:
U | 路由已启用。 |
H | 目标是一个主机,也是此路由上唯一可能的目的地。 |
G | 使用网关。 |
R | 恢复动态路由的路由。 |
D | 由路由守护进程动态安装。 |
M | 由路由守护进程在收到一个 互联网控制消息协议 (ICMP) 数据包后安装。 |
A | 由自动 DNS 和 DHCP 配置文件生成器 addrconf 安装。 |
C | 缓存条目。 |
! | 拒绝路由。 |
查找进程使用的端口
通过将 netstat
的输出通过管道传递给 grep
,我们可以按名称搜索进程,并识别它正在使用的端口。 我们使用之前提到的 -a
(全部)、-n
(数字)和 -p
(程序)选项,然后搜索 “sshd”。
sudo netstat -anp | grep "sshd"
grep 找到了目标字符串,我们看到 sshd 守护进程正在使用端口 22。
当然,我们也可以反过来操作。 如果搜索 “:22”,我们可以查找哪个进程正在使用此端口(如果有的话)。
sudo netstat -anp | grep ":22"
此时,grep 找到了 “:22” 的目标字符串,我们看到使用此端口的进程是 sshd 守护进程,其进程 ID 为 751。
列出网络接口
-i
(接口)选项会显示 netstat
可以检测到的网络接口表。
sudo netstat -i
下面是清晰的输出:
Kernel Interface table Iface MTU RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg enp0s3 1500 4520671 0 0 0 4779773 0 0 0 BMRU lo 65536 30175 0 0 0 30175 0 0 0 LRU
下面是这些列的含义:
iface:接口的名称。 enp0s3
接口是外部网络接口,而 lo
接口是回环接口。 回环接口使进程能够使用网络协议在计算机内相互通信,即使计算机没有连接到网络。
MTU:最大传输单元 (MTU)。 这是可以发送的最大“数据包”。 它由包含路由和协议标志、其他元数据以及实际传输的数据的标头组成。
RX-OK:接收到的数据包数量,没有错误。
RX-ERR:接收到的有错误的数据包数量。 我们希望这个值尽可能低。
RX-DRP:丢弃(即丢失)的数据包数量。 我们也希望这个值尽可能低。
RX-OVR:接收时由于溢出而丢失的数据包数量。 这通常意味着接收缓冲区已满,无法接收更多数据,但接收到更多数据,因此必须丢弃。 这个数字越低越好,零是理想的。
TX-OK:传输的数据包数量,没有错误。
TX-ERR:传输的有错误的数据包数量。 我们希望这个值为零。
TX-DRP:传输时被丢弃的数据包数量。 理想情况下,这个值应为零。
TX-OVR:传输时由于溢出而丢失的数据包数量。 这通常意味着发送缓冲区已满,无法接收更多数据,但更多数据准备好发送,因此必须丢弃。
Flg:标志。 请参考下面的标志表。
标志代表以下含义:
B | 正在使用广播地址。 |
L | 此接口是回环设备。 |
M | 正在接收所有数据包(即处于混杂模式)。 没有任何数据包被过滤或丢弃。 |
O | 地址解析协议 (ARP) 已针对此接口关闭。 |
P | 这是一个 点对点 (PPP) 连接。 |
R | 接口正在运行。 |
U | 接口已启动。 |
列出多播组成员资格
简单来说,多播传输 允许将数据包只发送一次,而不管接收者的数量。 对于视频流等服务来说,这大大提高了发送方的效率。
-g
(组)选项使 netstat
列出每个接口上套接字的多播组成员资格。
sudo netstat -g
这些列非常简单:
接口: 套接字传输所使用的接口名称。
RefCnt: 参考计数,即连接到套接字的进程数量。
组: 多播组的名称或标识符。
新一代网络工具
route
, ip
, ifconfig
和 ss
命令可以提供很多与 netstat
相似的功能。它们都是值得探索的优秀工具。
我们重点介绍了 netstat
,因为它具有普遍的可用性,无论你使用的是哪种类 Unix 操作系统,甚至是较少见的操作系统。