netstat命令你真的理解吗?

前言

虽然草稿箱堆满了很大篇,就是没有动力继续写 ,回想起前几天被问到的问题《关于netstat的原理》,我确实未能回答到点子上,原来一直在用的命令仅仅就是适用,它的底层实现原理是什么,没有认真全面的想过。

早上都想到这里了,捻转反侧,不会就学,来吧,让我一起重新认识一下netstat这个命令的巨大威力。

首先看下netstat怎么使用

~$ netstat --help
usage: netstat [-vWeenNcCF] [<Af>] -r         netstat {-V|--version|-h|--help}
       netstat [-vWnNcaeol] [<Socket> ...]
       netstat { [-vWeenNac] -i | [-cnNe] -M | -s [-6tuw] }

        -r, --route              display routing table
        -i, --interfaces         display interface table
        -g, --groups             display multicast group memberships
        -s, --statistics         display networking statistics (like SNMP)
        -M, --masquerade         display masqueraded connections

        -v, --verbose            be verbose
        -W, --wide               don't truncate IP addresses
        -n, --numeric            don't resolve names
        --numeric-hosts          don't resolve host names
        --numeric-ports          don't resolve port names
        --numeric-users          don't resolve user names
        -N, --symbolic           resolve hardware names
        -e, --extend             display other/more information
        -p, --programs           display PID/Program name for sockets
        -o, --timers             display timers
        -c, --continuous         continuous listing

        -l, --listening          display listening server sockets
        -a, --all                display all sockets (default: connected)
        -F, --fib                display Forwarding Information Base (default)
        -C, --cache              display routing cache instead of FIB
        -Z, --context            display SELinux security context for sockets

  <Socket>={-t|--tcp} {-u|--udp} {-U|--udplite} {-S|--sctp} {-w|--raw}
           {-x|--unix} --ax25 --ipx --netrom
  <AF>=Use '-6|-4' or '-A <af>' or '--<af>'; default: inet
  List of possible address families (which support routing):
    inet (DARPA Internet) inet6 (IPv6) ax25 (AMPR AX.25) 
    netrom (AMPR NET/ROM) ipx (Novell IPX) ddp (Appletalk DDP) 
    x25 (CCITT X.25) 

上面命令我就不一一讲解了,相信你和我一样,一定要自己去看帮助命令,每个参数认真看,总能找到你需要的命令搭配,下面我们看几个常用的参数:

列出所有当前的连接,使用 -a 选项

$ netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 localhost:16062         0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:amanda          0.0.0.0:*               LISTEN  
tcp6       0      0 [::]:amanda             [::]:*                  LISTEN     
tcp6       0      0 [::]:kamanda            [::]:*                  LISTEN  
udp        0      0 0.0.0.0:44351           0.0.0.0:*                          
udp        0      0 0.0.0.0:48504           0.0.0.0:*                          
udp        0      0 0.0.0.0:36463           0.0.0.0:*   
udp6       0      0 user2:dhcpv6-client  [::]:*                             
raw6       0      0 [::]:ipv6-icmp          [::]:*                  7                           
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ]         DGRAM                    526672   /run/user/1000/systemd/notify
unix  2      [ ]         DGRAM                    37904    /run/user/1001/systemd/notify
unix  2      [ ACC ]     SEQPACKET  LISTENING     16633    /run/udev/control
unix  2      [ ACC ]     STREAM     LISTENING     9177922  /run/containerd/s/bae34f9f78b9a1a630d503c177996bc38cc08d8386a2e1e6a23d17a8325e0953
unix  2      [ ACC ]     STREAM     LISTENING     526675   /run/user/1000/systemd/private

上述命令列出 tcp, udp 和 unix 协议下所有套接字的所有连接。然而这些信息还不够详细,管理员往往需要查看某个协议或端口的具体连接情况。

-t(只列出tcp协议连接) 和 -u(只列出udp协议连接)

注意: 命令展示结果不全,不便于全部展示,请谅解。

使用 -t 和 -u 选项列出 TCP和UDP 协议的连接:

$ netstat -atu
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 localhost:16062         0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:amanda          0.0.0.0:*               LISTEN     
udp        0      0 0.0.0.0:44351           0.0.0.0:*                                                 
udp        0      0 localhost:domain        0.0.0.0:*                               

上面展示了tcp和udp协议连接,如果想只查看tcp,那就只使用-t就可以了,udp亦然。

禁用反向域名解析,加快查询速度

有时候,你使用netstat命令的时候,很快会弹出一些信息,但是就卡在一个地方,等待有一会儿才会有刷出很多结果,那么,默认情况下 netstat 会通过反向域名解析技术查找每个 IP 地址对应的主机名。这会降低查找速度。如果你觉得 IP 地址已经足够,而没有必要知道主机名,就使用 -n 选项禁用域名解析功能。

$ netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.1:16062         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:11011         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:7400          0.0.0.0:*               LISTEN   
tcp6       0      0 :::22                   :::*                    LISTEN  

上述命令列出所有 TCP 协议的连接,没有使用域名解析技术,命令结果信息秒出。

只列出监听中的连接

任何网络服务的后台进程都会打开一个端口,用于监听接入的请求。这些正在监听的套接字也和连接的套接字一样,也能被 netstat 列出来。使用 -l 选项列出正在监听的套接字。

$ netstat -tnl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.1:16062         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:11011         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:7400          0.0.0.0:*               LISTEN     
tcp        0      0 172.17.0.1:9998         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:6010          0.0.0.0:*               LISTEN     
tcp6       0      0 :::10080                :::*                    LISTEN     

现在我们可以看到处于监听状态的 TCP 端口和连接。如果你查看所有监听端口,去掉 -t 选项。如果你只想查看 UDP 端口,使用 -u 选项,代替 -t 选项。

注意:不要使用 -a 选项,否则 netstat 会列出所有连接,而不仅仅是监听端口。

获取进程名、进程号以及用户 ID

查看端口和连接的信息时,能查看到它们对应的进程名和进程号对系统管理员来说是非常有帮助的。举个栗子,Apache 的 httpd 服务开启80端口,如果你要查看 http 服务是否已经启动,或者 http 服务是由 apache 还是 nginx 启动的,这时候你可以看看进程名。

使用 -p 选项查看进程信息。

$ netstat -nlpt
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:16062         0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:10080           0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:11011         0.0.0.0:*               LISTEN      -      

使用 -p 选项时,netstat 必须运行在 root 权限之下,不然它就不能得到运行在 root 权限下的进程名,而很多服务包括 http 和 ftp 都运行在 root 权限之下。

相比进程名和进程号而言,查看进程的拥有者会更有用。使用 -ep 选项可以同时查看进程名和用户名。


$ netstat -ltpe
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode      PID/Program name    
tcp        0      0 localhost:16062         0.0.0.0:*               LISTEN      root       10566246   -                   
tcp        0      0 0.0.0.0:amanda          0.0.0.0:*               LISTEN      root       30719      -                   
tcp        0      0 localhost:11011         0.0.0.0:*               LISTEN      root       21277      -              

面列出 TCP 协议下的监听套接字,同时显示进程信息和一些额外信息。

这些额外的信息包括用户名和进程的索引节点号。这个命令对网管来说很有用。

注意 - 假如你将 -n 和 -e 选项一起使用,User 列的属性就是用户的 ID 号,而不是用户名。

打印统计数据

netstat 可以打印出网络统计数据,包括某个协议下的收发包数量。

$ netstat -s
Ip:
    Forwarding: 1
    17451809 total packets received
    2 with invalid addresses
    5121043 forwarded
    0 incoming packets discarded
    12330737 incoming packets delivered
    25927983 requests sent out
    20 outgoing packets dropped
    204 dropped because of missing route
Icmp:
    175 ICMP messages received
    24 input ICMP message failed
    ICMP input histogram:
        destination unreachable: 140
        echo replies: 35
    168 ICMP messages sent
    0 ICMP messages failed
    ICMP output histogram:
        destination unreachable: 127
        echo requests: 41
IcmpMsg:
        InType0: 35
        InType3: 140
        OutType3: 127
        OutType8: 41
Tcp:
    40469 active connection openings
    14455 passive connection openings
    8122 failed connection attempts
    2372 connection resets received
    11 connections established
    11816562 segments received
    13416691 segments sent out
    9802 segments retransmitted
    0 bad segments received
    26609 resets sent
Udp:
    517142 packets received
    57 packets to unknown port received
    0 packet receive errors
    7584388 packets sent
    0 receive buffer errors
    0 send buffer errors
    IgnoredMulti: 1964
...
...
...

如果想只打印出 TCP 或 UDP 协议的统计数据,只要加上对应的选项(-t 和 -u)即可。

显示内核路由信息

使用 -r 选项打印内核路由信息。打印出来的信息与 route 命令输出的信息一样。我们也可以使用 -n 选项禁止域名解析。

$ netstat -rn
Kernel IP routing table
Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
0.0.0.0         192.168.31.1    0.0.0.0         UG        0 0          0 eno1
172.17.0.0      0.0.0.0         255.255.0.0     U         0 0          0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U         0 0          0 br-01f307435ee5
192.100.0.0     0.0.0.0         255.255.0.0     U         0 0          0 br-eff40b05b181
192.168.31.0    0.0.0.0         255.255.255.0   U         0 0          0 eno1
192.168.31.1    0.0.0.0         255.255.255.255 UH        0 0          0 eno1

打印网络接口

netstat 也能打印网络接口信息,-i 选项就是为这个功能而生。

$ netstat -i
Kernel Interface table
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
br-01f30  1500    10234      0      0 0         11313      0      0      0 BMRU
br-eff40  1500  3293872      0      0 0       3423177      0      0      0 BMRU
docker0   1500        0      0      0 0             0      0      0      0 BMU
eno1      1500  7098937      0    680 0      14895913      0      0      0 BMRU
lo       65536  7966356      0      0 0       7966356      0      0      0 LRU

上面输出的信息比较原始。我们将 -e 选项和 -i 选项搭配使用,可以输出用户友好的信息。

$ netstat -ie
Kernel Interface table
br-01f307435ee5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.1  netmask 255.255.0.0  broadcast 172.18.255.255
        inet6 fe80::42:c9ff:fe5c:bcc5  prefixlen 64  scopeid 0x20<link>
        ether 02:42:c9:5c:bc:c5  txqueuelen 0  (Ethernet)
        RX packets 10234  bytes 28656523 (28.6 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 11313  bytes 3360701 (3.3 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

br-eff40b05b181: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.100.1.1  netmask 255.255.0.0  broadcast 192.100.255.255
        inet6 fe80::42:76ff:fec5:2040  prefixlen 64  scopeid 0x20<link>
        ether 02:42:76:c5:20:40  txqueuelen 0  (Ethernet)
        RX packets 3293945  bytes 513112406 (513.1 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 3423262  bytes 1552580439 (1.5 GB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:f9:17:cf:a1  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

上面的输出信息与 ifconfig 输出的信息一样。

netstat 持续输出

$ netstat -ct
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 localhost:43468         localhost:kamanda       ESTABLISHED
tcp        0      0 localhost:kamanda       localhost:43468         ESTABLISHED
tcp        0      0 localhost:43466         localhost:kamanda       ESTABLISHED
tcp        0      0 localhost:kamanda       localhost:43466         ESTABLISHED
tcp        0      0 localhost:56506         localhost:ssh           ESTABLISHED
tcp        0      0 localhost:ssh           localhost:56506         ESTABLISHED
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 localhost:43468         localhost:kamanda       ESTABLISHED
tcp        0      0 localhost:kamanda       localhost:43468         ESTABLISHED
tcp        0      0 localhost:43466         localhost:kamanda       ESTABLISHED
tcp        0      0 localhost:kamanda       localhost:43466         ESTABLISHED
tcp      444      0 localhost:56506         localhost:ssh           ESTABLISHED
tcp        0    116 localhost:ssh           localhost:56506         ESTABLISHED
Active Internet connections (w/o servers)

使用上面这个命令可以持续观察tcp连接的状态信息。

其它命令

当然,目前我介绍的这些命令已经足够用了,然后netstat展示的结果信息足够多,所以搭配 | grep来用,效果更有针对性:

$ netstat -ct | grep ESTABLISHED
tcp        0      0 localhost:43468         localhost:kamanda       ESTABLISHED
tcp        0      0 localhost:kamanda       localhost:43468         ESTABLISHED

这样,你就可以看到持续的输出你关注的信息了。
配合 watch 命令监视 active 状态的连接:

$ watch -d -n0 "netstat -atnp | grep ESTA"

-d: 意思是高亮显示变化的状态信息
-n0:其实是刷新的间隔的时间,0代表是0s

关于watch其他的命令请查看watch --h

state的含义

tcp连接有哪些state

  • LISTEN:侦听来自远方的TCP端口的连接请求。
  • SYN_SENT:在发送连接请求后等待匹配的连接请求。
  • SYN_RECEIVED:在收到和发送一个连接请求后等待对方对连接请求的确认。
  • ESTABLISHED:代表一个打开的连接,我们常用此作并发连接数。
  • FIN_WAIT1:等待远程TCP连接中断请求,或先前的连接中断请求的确认。
  • FIN_WAIT2:从远程TCP等待连接中断请求。
  • CLOSE_WAIT:等待从本地用户发来的连接中断请求。
  • CLOSING:等待远程TCP对连接中断的确认。
  • LAST_ACK:等待原来发向远程TCP的连接中断请求的确认。
  • TIME_WAIT:等待足够的时间以确保远程TCP接收到连接中断请求的确认。
  • CLOSED:没有任何连接状态。

先来干一杯tcp协议原理

TCP协议是端到端的传输控制协议,之所以是“端到端”的协议,是因为”路由“是由IP协议负责的,TCP协议负责为两个通信端点提供可靠性保证,这个可靠性不是指一个端点发送的数据,另一个端点肯定能收到(这显然是不可能的),而是指,数据的可靠投递或者故障的可靠通知。

TCP的可靠性通过以下方式来保证:
1.超时重传:TCP每发送出一个报文段后,都会启动一个定时器,对目的端传回的确认信息进行确认计时,超时后便重传。
2.确认信号:当TCP收到一个来自TCP的报文段后,便会发送回一个确认信号。
3.检验和:TCP将始终保持首部和数据的检验和,如果收到的报文段的检验和有差错,便将其丢弃,希望发送端超时重传。
4.重新排序:由于IP数据报的达到可能失序,因此TCP将会数据进行重新排序,以正确的顺序交给应用层。
5.丢弃重复:由于IP数据报有可能重复,因此TCP将会丢弃重复的数据。
6.流量控制:TCP连接的两端都有固定大小的缓冲区空间,TCP接受端只允许对端发送本端缓冲区能容纳的数据。

TCP提供流量控制。在双方进行交互时,会彼此通知自己目前接收缓冲区最多可以接收的数据量(通告窗口),以此确保发送方发送的数据不会溢出接收缓冲区。

TCP数据包主要包括:

  1. SYN包:请求建立连接的数据包
  2. ACK包:回应数据包,表示接收到了对方的某个数据包
  3. PSH包:正常数据包
  4. FIN包:通讯结束包
  5. RST包: 重置连接
    导致TCP协议发送RST包的原因:
    1)SYN 数据段指定的目的端口处没有接收进程在等待。
    2)TCP协议想放弃一个已经存在的连接。
    3)TCP接收到一个数据段,但是这个数据段所标识的连接不存在。
    接收到RST数据段的TCP协议立即将这条连接非正常地断开,并向应用程序报告错误。
  6. URG包: 紧急指针

一次完整的TCP通讯包括:建立连接、数据传输、关闭连接
建立连接(三次握手):
1.客户端通过向服务器端发送一个SYN来建立一个主动打开,作为三路握手的一部分。
2.服务器端应当为一个合法的SYN回送一个SYN/ACK。
3.最后,客户端再发送一个ACK。这样就完成了三路握手,并进入了连接建立状态。
数据传输:
1.发送数据端传输PSH数据包
2.接收数据端回复ACK数据包
关闭连接(四次分手):

  1. 一端主动关闭连接。向另一端发送FIN包。
  2. 接收到FIN包的另一端回应一个ACK数据包。
  3. 另一端发送一个FIN包。
  4. 接收到FIN包的原发送方发送ACK对它进行确认。

三次握手,四次分手:
在这里插入图片描述
TCP状态转换图:
在这里插入图片描述
说明(netstat可查看状态):

CLOSED: 初始状态。

LISTEN: 服务器端的某个SOCKET处于监听状态,可以接受连接了。

SYN_RCVD: 服务器接受到了SYN报文。

SYN_SENT: 客户端已发送SYN报文。

ESTABLISHED:连接已经建立了。

FIN_WAIT_1:当SOCKET在ESTABLISHED状态时,它想主动关闭连接,向对方发送了FIN报文, 此时该SOCKET即进入到FIN_WAIT_1状态。而当对方回应ACK报文后,则进入到FIN_WAIT_2状态,当然在实际的正常情况下,无论对方 何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。

FIN_WAIT_2:上面已经详细解释了这种状态,实际上FIN_WAIT_2状态下的SOCKET,表示半连接,也即有一方要求close连接,但另外还告诉对方,我暂时还有点数据需要传送给你,稍后再关闭连接。

TIME_WAIT: 表示收到了对方的FIN报文,并发送出了ACK报文,就等2个MSL(最大生存时间)值(RFC建议2分钟,Berkeley传统使用30s)后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。
TIME_WAIT状态存在两个理由:
1.可靠地实现TCP连接的终止
2.允许老的重复分解在网络中消逝
执行主动关闭的一端都会进入TIME_WAIT状态,Linux下高并发的Squid服务器,TCP TIME_WAIT套接字数量经常达到数万,服务器很容易被拖死。通过修改Linux内核参数,可以减少服务器的TIME_WAIT套接字数量。

CLOSING: 这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送 FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收 到对方的ACK报文,反而却也收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close 一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也即会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

CLOSE_WAIT: 这种状态的含义其实是表示在等待关闭。怎么理解呢?当对方close一个SOCKET后发送 FIN报文给自己,你系统毫无疑问地会回应一个ACK报文给对方,此时则进入到CLOSE_WAIT状态。接下来呢,实际上你真正需要考虑的事情是察看你是否还有数据发送给对方,如果没有的话,那么你也就可以close这个SOCKET,发送FIN报文给对方,也即关闭连接。所以你在CLOSE_WAIT 状态下,需要完成的事情是等待你去关闭连接。

LAST_ACK: 被动关闭一方在发送FIN报文后,最后等待对方的ACK报文。当收到ACK报文后,也即可以进入到CLOSED可用状态了。

感谢

Linux 常用命令之 netstat 的10个基本用法
TCP协议实现原理
Netstat command in Linux
THE TCP/IP GUIDE

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

京河小蚁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值