Linux 网络分析
灵活的使用各种网络分析工具,可以有效地快速定位问题。
Linux | 描述 |
---|---|
nslookup/dig | 查询本机域名解析情况 |
netstat | 多种网络栈和接口统计信息 |
ifconfig | 网络接口配置 |
ping | 测试网络连通性 |
traceroute | 测试网络路由 |
tcpdump | 网络数据包嗅探器 |
nslookup & dig
nslookup
常用来查询本机域名解析情况,dig
(domain information groper) 相较前者提供更多的信息,包括 NS 记录、A 记录、MX 记录等相关信息。
Fedora / Centos系统:
1 | $ sudo yum -y install bind-utils |
Debian / Ubuntu系统:
1 | $ sudo apt-get -y install dnsutils |
nslookup
简单介绍使用nslookup检查DNS信息的方法。
1、终端中输入命令:$ nslookup
2、设置 nslookup 使用的 DNS 服务器,输入 > server DNS_server_ip
并回车;
3、检查某个 DNS 域名的 MX 记录,先输入 > set q=mx
,回车后输入想要检查的 DNS 域名,例如nuzar.top;
4、显示其他记录,先输入 > set q=any
,回车后输入想要查询的记录的名称。
1 | $ nslookup |
dig
dig 默认查询
对 dig
默认查询的各个部分进行解析。
1 | $ dig www.baidu.com |
分段解释获取的信息
1
2 >; <<>> DiG 9.11.3-1ubuntu1.12-Ubuntu <<>> www.baidu.com
>;; global options: +cmd
DiG 默认版本号,查询的域名,默认的全局参数为 +cmd
1
2
3 ;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50658
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1
opcode 操作码为 QUERY
查询,status 表示查询操作状态为 NOERROR
无错误。
flags 标志位的解释如下:
qr
: 表示 query ,查询操作;rd
: 表示 recursion desired ,指希望通过递归查询操作;ra
: 表示 recursion available ,DNS 服务器支持递归查询操作;aa
: 表示 authoritative answer ,权威回复,即查询结果为域名服务器提供,而不是缓存服务器提供;QUERY
: 查询数,对应下面 QUESTION SECTION 中的记录数;ANSWER
: 结果数,对应下方 ANSWER SECTION 中的记录数;AUTHORITY
: 权威域名服务器记录数,代表该域名有 0 个权威域名服务器可供域名解析用;ADDITIONAL
: 额外记录数,当使用+comments
参数时不显示该部分。
继续看其他部分:
1
2 ;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
这里是有关 DNS 扩展机制 (EDNS) 的信息。
1
2 ;; QUESTION SECTION:
;www.baidu.com. IN A
QUESTION 部分为所查询域名的输出信息,默认为 A 记录
,+noquestion
参数可以不显示该部分
1
2
3
4 ;; ANSWER SECTION:
www.baidu.com. 81 IN CNAME www.a.shifen.com.
www.a.shifen.com. 80 IN A 180.101.49.11
www.a.shifen.com. 80 IN A 180.101.49.12
ANSWER 部分信息解释如下表所示:
域名 | TTL (缓存时间/sec) | 查询类别 | 解析地址 |
---|---|---|---|
www.a.shifen.com. | 80 | IN A | 180.1010.49.11 |
查询类别:A
为 A 记录
, CNAME
为别名记录。
最后一部分的内容:
1
2
3
4 ;; Query time: 49 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: Mon Jun 08 02:43:46 UTC 2020
;; MSG SIZE rcvd: 101其中:
Query time
: 查询耗时;
SERVER
: 查询使用的服务器地址和端口,这里显示的127.0.0.53
为本地回环地址,表示使用的是本地的 DNS 缓存,在kubernetes
中使用本地缓存作为解析地址可能会导致CoreDNS
出现一下问题可在
/etc/resolv.conf
中修改 DNS 服务器的地址,$ sudo service systemd-networkd restart
或$ netplan apply
,通过$ systemd-resolve --status enp0s25
查看 (enp0s25 为连接对应网卡)
WHEN
: 查询的时间
MSG SIZE rcvd
: 回复的大小,101 字节
命令以 +nostats
作为参数,可以不显示该部分。
如可用 $ dig www.google.com +noall +answer
只返回查询结果。
常用查询
精简查询
1 | $ dig www.google.com +short |
查询路径
1 | $ dig www.google.com +trace |
指定DNS服务器
1 | $ dig @8.8.8.8 www.google.com |
指定查询类型
1 | # 查询A记录(默认) |
反向查询
查询与特定 IP 地址关联的域名
1 | $ dig -x 8.8.8.8 +noall +answer |
批量查询
将待查询域名写入文本文件
1 | $ dig -f searchlist +noall +answer |
netstat
netstat
主要用于对网络接口 (interface) 中的数据进行统计、查询,通常使用的命令参数如下:
Options | Descriptions |
---|---|
-a |
列出所有端口的连接,包括 TCP 和 UDP ; |
-at |
仅列出 TCP 端口的连接; |
-au |
仅列出 UDP 端口的连接; |
-l |
所有活跃的套接字; |
-s |
网络统计数据,按照协议分类; |
-p |
同时列出进程 PID; |
-i |
同时列出网卡 interface ; |
-r |
列出路由表,类似 route ; |
-n |
默认下 netstat 会反向解析每个 IP 对应的主机名,-n 禁用反向域名解析,加快查询速度; |
-e |
显示更多信息 (用户等); |
-c |
持续输出信息; |
-g |
输出 IPv4 和 IPv6 的多播组信息。 |
ifconfig
ifconfig
主要用于网络接口相关的操作,一般直接使用 $ ifconfig
就会输出目前已经被启动的网卡,不管改接口有没有被配置地址。
参数解析
1 | $ ifconfig |
enp0s25
: 网卡名,注意lo
为loopback
;mtu
: 最大传输单元 (Maximum Transmission Unit, MTU) 数据链路层,规定作能接受数据服务单元的最大尺寸,是包或帧的最大长度,如果 MTU 过大,路由器会拒绝转发;inet addr
: IPv4 的 IP 地址。inet6 addr
: 是 IPv6 的版本的 IP。ether
: 网卡地址txqueuelen
: 代表用来传输数据的缓冲区的储存长度。RX
: 那一行代表的是网络由启动到目前为止的数据包接收情况
bytes
: 接收的字节总量;packets
代表数据包数;errors
代表数据包发生错误的数量;dropped
代表数据包由于有问题而遭丢弃的数量等;overruns
表示 fifo 队列中 ring-buffer 缓冲溢出,接受包的数量超出了内核的 IO 上限;frame
表示接收的帧未对齐。TX
: 与 RX 相反,为网络由启动到目前为止的发送情况。
carrier
: 由传输链路引起的错误 (存疑);collisions
: 代表数据包碰撞的情况。Interrupt
Memory
: 网卡硬件的数据,IRQ 岔断与内存地址。
常用命令
启动或关闭制定网卡
1 | $ ifconfig eth0 up # 启动 <br>ifcfg etho up # 启动 |
为网卡配置和删除 IPv4/IPv6 地址 (临时生效,永久修改需要更改配置文件)
1 | $ ifconfig eth0 192.168.25.166 netmask 255.255.255.0 up |
修改 MAC 地址
1 | $ ifconfig eth0 down //关闭网卡 |
启用或关闭 ARP 协议
1 | $ ifconfig eth0 down //关闭网卡 |
设置最大传输单元
1 | $ ifconfig eth0 mtu 1500 |
ping
ping
命令用来测试主机之间的网络连通性,执行 ping
指令会使用 ICMP 传输协议。
ICMP
由于 IP 协议并不提供可靠传输,并不能在丢包发生时通知传输层是否丢包以及丢包的原因。ICMP (Internet Control Message Protocol) 基于 IP 协议工作,可以把它归为网络层协议,ICMP 协议可以确认 IP 包是否成功到达目标地址,以及通知在发送过程中 IP 包被丢弃的原因 (需要注意,ICMP 只能搭配 IPv4 使用,如果是 IPv6 的情况,需要使用 ICMPv6)
ICMP 报文格式
在讲到 ICMP 报文格式之前,我们先来回忆一下 IP 报文的格式:
IPv4 数据报分为部首与数据两部分,部首中包含 IP 数据报的一些基本信息。ICMP 报文是包含在 IP 数据报的数据部分中的,当 IP 数据报首部的协议字段为 1时,说明这是一个 ICMP 报文。
IP 数据报的协议部分指示了其数据部分应该交给哪个特定的运输层协议,例如
6 -> TCP
17 -> UDP
,具体参见 IANA Protocol Numbers 。协议号所起的作用,类似运输层报文段中的 “端口号” 字段,协议号将网络层和运输层结合,而端口号则将运输层和应用层结合。
下面是 ICMP 的报文:
类型 | 说明 |
---|---|
type | 占一字节,标识ICMP报文的类型,从类型值来看ICMP报文可以分为两大类。第一类是取值为1~127的差错报文,第2类是取值128以上的信息报文 |
code | 占一字节,标识对应ICMP报文的代码。它与类型字段一起共同标识了ICMP报文的详细类型 |
checksum | 这是对包括 ICMP 报文数据部分在内的整个 ICMP 数据报的校验和,以检验报文在传输过程中是否出现了差错(其计算方法与 IP 报头中的校验和计算方法是一样的) |
常见的 type
类型,注意这一部分,涉及 ping
与 traceroute
的实现原理:
类型(十进制) | 内容 |
---|---|
0 | 回送应答 |
3 | 目标不可达 |
4 | 原点抑制 |
5 | 重定向或改变路由 |
8 | 回送请求 |
9 | 路由器公告 |
10 | 路由器请求 |
11 | 超时 |
13 | 时间戳请求 |
14 | 时间戳应答 |
ping
操作中就用到了类型为 0
与 8
的 ICMP 报文。
使用参数
ping
的详细参数见此文
Options | Descriptions |
---|---|
-a |
当 ping 通时发出蜂鸣; |
-A |
自适应 ping,根据 ping 包往返时间确定 ping 的速度; |
-b |
允许 ping 一个广播地址; |
-B |
Use this option if you do not want to allow the ping to change the source address of the probe |
-c |
-c <Count> ping 指定次数为 Count; |
-d |
使用 Socket 的 SO_DEBUG 功能; |
-f |
洪泛检测,以每秒100次甚至更高的速度 ping 一台主机; |
-i |
-i <Interval> 间隔 Interval 发送 ping 包,默认为1秒; |
-I |
-I <Interface Address> 指定网卡接口或者指定本机地址发送数据包,主要用于 ping 本地的 IPv6 地址; |
-l |
-l <Preload> 不需要等待回应,直接发出 Preload 个包,对于超出三个的需要 root 权限执行; |
-m |
-m <Mark> 设置 mark; |
-M |
-M <HINT> 设置 MTU 的分片策略:do 禁止分片,即使包被丢弃;want 当包过大时分片;dont 不设置分片标志 (DF Flag); |
-n |
不将 ip 地址转换为主机名; |
-p |
-p <Pattern> 指定填充 ping 数据包的十六进制内容,在诊断与数据相关的网络错误时这个选项会很有用,如 -p ff ; |
-q |
静默输出,不显示任何封包的信息,只显示最后的结果; |
-r |
忽略路由表直接送到连接的网络上的主机上。如果 主机 不在一个直接连接的网络上,ping 命令将产生一个错误消息, 这个选项可以被用来通过一个不再有路由经过的接口去 ping 一个本地主机; |
-Q |
-Q <Tos> 设置 QoS (Quality of Service),它是ICMP数据报相关位;可以是十进制或十六进制数,详见 rfc1349 和 rfc2474 文档; |
-R |
记录 ping 的路由过程 (IPv4 only);(注: IP 头仅仅大到适合 9 个这样的路由。而且,许多主机和网关忽略这个选项。) |
-s |
-s <Size> 指定发送数据的字节数,默认为56字节,与8字节的 ICMP 头数据合并为 64 字节的 ICMP 数据; |
-S |
-S <Host/IP addr> 将 IP 地址用作发出的 ping 信息包中的源地址。在具有不止一个 IP 地址的主机上,可以使用 -S 标志来强制源地址为除了软件包在其上发送的接口的 IP 地址外的任何地址。如果 IP 地址不是以下机器接口地址之一,则返回错误并且不进行任何发送; |
-T |
-T <TTL> 设置 TTL (Time to Live),指定 IP 包被路由器丢弃之前的生存时间; |
-v |
使 ping 处于 verbose 方式,它要 ping 命令除了打印 ECHO-RESPONSE 数据包之外,还打印其它所有返回的 ICMP 数据包; |
-V |
显示版本并退出; |
-w |
-w <Deadline> 设置截止时间(秒),在 ping 退出之前,查看有多少包成功地发送接收; |
-W |
设置等待超时时间。 |
有人会问 telnet 是
23
端口,ssh 是22
端口,那 ping 是什么端口吖?其实要是仔细阅读上文,就会知道 ping 基于 ICMP,处于网络层,而端口号是传输层的内容,在 ICMP 中根本没有端口号这个概念。
traceroute
原理
traceroute
指令可以让你追踪网络数据包的路由路径,预设数据包大小为 40 Bytes。同样也是基于 ICMP 协议实现的,其工作原理是利用 type 11
设置一个超时返回的类型,这样当路由主机超时时会向源主机发送一个超时报文。
那么如何利用超时的机制来获取沿途路由的地址呢?
traceroute
会封装一些分组,第一个分组的 TTL (IP 部首中的 Time To Live) 为1,第二个分组中 TTL 为2 …… 依此类推,第一跳接收第一个分组,并将 TTL 减1,TTL 变为0,超时并返回一个 ICMP 超时数据包,得到第一跳地址;第二跳超时返回下一个路由地址,直到到达目标主机,目标主机返回一个 ICMP "port unreachable"
,traceroute
结束。
由于有些路由器会隐藏自己的位置,不让 ICMP Timeout 的消息通过,在那一跳上就会显示
* * *
此外服务器也是可以伪造 traceroute 路径的,不过一般应用服务器没有理由这么做。
命令详解
Options | Descriptions |
---|---|
-d |
启用 Socket 级的调试; |
-f |
设置第一个检测数据包的 TTL 大小; |
-F |
设置禁止分包; |
-g |
在发出包中添加一个 IP 源路由的选项,告诉网络将数据包通过指定的网关进行路由 (大多数路由器出于安全考虑都禁用了源路由); |
-i |
设置数据包发出所经的网口,默认情况下,使用路由表中的网口; |
-I |
使用 ICMP ECHO 作为探测手段; |
-m |
设置探测数据包的最大跳数 (TTL) ,默认为30; |
-n |
同前几条指令,这里 -n 也是禁止将 IP 地址转换为主机名; |
-p |
对于 UDP 追踪,指定探测的目标端口 (目标端口号会随探测次数递增);对于 ICMP 追踪,指定初始的 ICMP 序列值 (同样随探测次数递增);对于 TCP,指定恒定的端口进行连接; |
-r |
忽略路由表,通过所连网络直接向主机发送数据包,如果主机不在直连网络中,会返回 error ;(可用于通过一个没有配置路由表的网口 ping 一个本地主机) |
-s |
设置本地主机送出数据包的源 IP 地址; |
-t |
设置检测数据包的 ToS (Type of Service) 数值,如 16 (low delay) 8 (high throughput) ; |
-T |
使用 TCP SYN 作为探测手段; |
-v |
详细显示指令的执行过程; |
-w |
设置等待远端主机回报的时间; |
-x |
开启或关闭数据包的正确性校验。 |
tcpdump
tcpdump
能够根据用户自定义条件截取数据包,支持 and
or
not
等逻辑语句,对网络层、协议、主机、网络或端口的数据包进行过滤。
由于网络流量通常很大,不加分辨收集所有数据包的量太大,不利于找出目标数据包,因此往往需要通过一些参数来更好地查找数据包。
Options | Most -used | Descriptions |
---|---|---|
-i |
* | 指定网络接口 |
-w |
将结果输出到文件中,通常文件以 .pcap 作为后缀,可以结合 WireShark 分析数据 |
|
-n |
* | 不把网络地址换成名字(不进行域名解析,速度更快) |
-nn |
不进行端口名称的转换,直接以ip和端口显示 | |
-v |
输出一个稍微详细的信息(例如在 ip 包中可以包括 ttl 和服务类型的信息) | |
-vv |
输出详细的报文信息 | |
-c |
在收到指定的包的数目后,tcpdump 就会停止,默认tcpdump需要 crtl+c 结束 |
|
-C |
后接 file_size,指定 -w 写入文件的大小,如果超过了指定大小,则关闭当前文件,然后在打开一个新的文件, file_size 的单位是兆字节 |
|
-a |
将网络地址和广播地址转变成名字 | |
-A |
* | 以ASCII格式打印出所有分组,并将链路层头最小化,方便去收集 web 页面内容 |
-d |
将匹配信息包的代码以人们能够理解的汇编格式给出 | |
-dd |
将匹配信息包的代码以c语言程序段的格式给出 | |
-ddd |
将匹配信息包的代码以十进制的形式给出 | |
-D |
* | 打印出系统中所有可以用 tcpdump 分析的网络接口 |
-q |
快速输出,只输出较少信息 | |
-e |
在输出行打印出数据链路层的头部信息 | |
-f |
将外部的 Internet 地址以数字的形式打印出来 | |
-l |
使标准输出变为缓冲行形式 | |
-t |
在输出的每一行不打印时间戳 | |
-tt |
在每一行中输出非格式化的时间戳 | |
-ttt |
输出本行和前面一行之间的时间差 | |
-F |
从指定的文件中读取表达式,忽略其它的表达式 | |
-r |
* | 从指定的文件中读取包(这些包一般通过 -w 选项产生) |
-w |
* | 直接将包写入文件中,并不分析和打印出来 $ tcpdump -w 0001.pcap -i eth0 |
-T |
将监听到的包直接解释为指定的类型的报文,常见的类型有 rpc (远程过程调用)和snmp(简单网络管理协议) | |
当然仅仅知道参数,还无法最大程度发挥 tcpdump 的能力,了解 tcpdump 的使用范式: |
tcpdump
+ [option]
+ 协议
+ 传输方向
+ 类型
+ 具体值
- 协议:包括 IP、ARP、RARP、TCP、UDP、ICMP、HTTP 等,默认监听所有协议的数据包;
- 传输方向:包括 src、dst、dst or src、dst and src,默认为 src or dst ;
- 类型:包括 host、net、port、ip proto、protochain,指定收集的主机或网段,默认为 host;
- 其他关键字:gateway、broadcast、less、greater;三种逻辑运算符
not
!
(非),and
&&
(与),or
||
(或)。
另外需要注意,tcpdump
命令只有具备 root 权限才能执行。
举个例子,我们需要截获
源 IP 是 192.168.0.19 且端口是22,或 源 IP 是192.168.0.19且目的端口是80,协议是 tcp ,包长度大于50,小于100的十个数据包,并保存到 traffic.cap 文件中
1 | $ sudo tcpdump -i eth0 -nnvv -c 10 \(less 100 and greater 50 and src host 192.168.0.19 and port 22\) or \(less 100 and greater 50 adn src host 192.168.0.19 and dst port 80\) -w traffic.cap |
当然还有更多的用法,可以参见说明的 Examples 部分。