详解 IP 命令 2023-04-09IP 命令是网络调试界的“瑞士军刀”,这篇文章详细介绍了 ip 命令的使用方法及其在网络调试中的应用。经典七层网络架构ip 这个命令属于 linux 中 ip-route 这个包。另一个非常常用的网络工具包叫做 net-tools ,这个包里包含了 arp / route / ifconfig 之类耳熟能详的很多工具。关于他们之间的渊源,ChatGPT 可以更好地回答,提问: should I use `net-tools` package or `ip-route` package? Which is better?回答:It is generally recommended to use the `iproute2` package instead of the `net-tools` package for managing network interfaces and routing in Linux.The `net-tools` package provides commands such as `ifconfig`, `route`, `arp`, etc. that have been used for many years to manage network interfaces and routing. However, these commands are considered deprecated and are no longer actively developed or maintained.On the other hand, the `iproute2` package provides the `ip` command, which is a modern and more powerful tool for managing network interfaces and routing. The `ip` command provides a more consistent and flexible interface for managing network settings and supports advanced features such as policy routing, traffic control, and network namespaces.So, it is recommended to use the `iproute2` package and the `ip` command instead of the deprecated `net-tools` commands.简单来说, net-tools (即 ifconfig 系列)“历史悠久”,而 ip-route 系列提供更加现代化的功能, ChatGPT 都推荐了,还不赶紧把电脑里的 ifconfig 卸载掉😏。下面列出了一些好用的命令,结果为树莓派(Debian 11)上的输出:显示 IP 地址信息 ip --detail --color addr show dev eth0显示网卡信息 ip --detail --color link show dev eth0网卡详情显示 IP 路由信息IP路由信息计算指定 IP 地址的路由信息这里测试了两个 IP,一个是公网 IP,一个是 docker 内部的 IP 地址。可以看到第一个 IP 地址走的是家用路由器的 IP,第二个走的是 Docker 自建的网卡。>>> ip --color --detail route get 211.69.129.86 unicast 213.59.119.76 via 192.168.31.1 dev wlan0 table main src 192.168.31.134 uid 1000 cache >>> ip --color --detail route get 10.96.25.31 unicast 10.96.25.31 via 192.168.49.2 dev br-e96c8a907727 table main src 192.168.49.1 uid 1000 cache 配置网卡 IP 地址在还没有 DHCP (Dynamic Host Configuration Protocol)之前,如果你买了一个新电脑并用网线连接到了家里的交换机(光猫)上以后,就需要主动给自己的电脑配置一个 IP 地址,否则交换机没法识别就上不了网。下面给我的树莓派 wlan0 也就是 Wifi 接口配置一个 IP 地址: sudo ip addr add 192.168.31.111/24 dev wlan0配置 IP 地址这个时候我的树莓派就有两个 IP 地址了。接下来通过我的 Apple Mac M1 电脑(下文简称 Apple)来访问这个新的 IP 地址:访问新 IP 地址因为我的树莓派上运行着 Grafana,所以这里尝试访问了 http://192.168.31.111:3000 ,可见已经可以成功访问了。那这里有一个问题:如果我给 wlan0 添加了一个新的 ip: 192.168.111.111/16 ,那还能够访问到吗?点击查看不能arp 协议会帮忙找到 192.168.111.111 对应的树莓派 IP 吗?点击查看可以,在 Apple 输入 arping -I en0 192.168.111.111 可以返回树莓派的 wlan0 口 MAC 地址。另一方面从设计角度讲,交换机只需关心 MAC 地址Apple 访问 http://192.168.111.111:80 时会发生什么?由于 192.168.111.111 不匹配任何路由规则,且不在本子网掩码中,所以 ip 层会将数据包前面的 MAC 地址填为路由器网关( 192.168.31.1 )的 MAC 地址,整个过程不涉及查 ARP table 或者发送 ARP 请求。下面是 Apple tcpdump 的输出,请求发送方式是: curl -XGET http://192.168.111.111/123/>>> sudo tcpdump -nXs 0 -i en0 'host 192.168.111.111' tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on en0, link-type EN10MB (Ethernet), snapshot length 524288 bytes 21:08:57.010879 IP 192.168.31.198.51810 > 192.168.111.111.80: Flags [S], seq 3334750323, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 3683895198 ecr 0,sackOK,eol], length 0 0x0000: 4500 0040 0000 4000 4006 2a32 c0a8 1fc6 E..@..@.@.*2.... 0x0010: c0a8 6f6f ca62 0050 c6c4 4073 0000 0000 ..oo.b.P..@s.... 0x0020: b002 ffff b158 0000 0204 05b4 0103 0306 .....X.......... 0x0030: 0101 080a db93 c79e 0000 0000 0402 0000 ................ 21:08:58.012016 IP 192.168.31.198.51810 > 192.168.111.111.80: Flags [S], seq 3334750323, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 3683896199 ecr 0,sackOK,eol], length 0 0x0000: 4500 0040 0000 4000 4006 2a32 c0a8 1fc6 E..@..@.@.*2.... 0x0010: c0a8 6f6f ca62 0050 c6c4 4073 0000 0000 ..oo.b.P..@s.... 0x0020: b002 ffff ad6f 0000 0204 05b4 0103 0306 .....o.......... 0x0030: 0101 080a db93 cb87 0000 0000 0402 0000 ................ 21:08:59.013140 IP 192.168.31.198.51810 > 192.168.111.111.80: Flags [S], seq 3334750323, win 65535, options [mss 1460,nop,wscale 6,nop,nop,TS val 3683897200 ecr 0,sackOK,eol], length 0 0x0000: 4500 0040 0000 4000 4006 2a32 c0a8 1fc6 E..@..@.@.*2.... 0x0010: c0a8 6f6f ca62 0050 c6c4 4073 0000 0000 ..oo.b.P..@s.... 0x0020: b002 ffff a986 0000 0204 05b4 0103 0306 ................ 0x0030: 0101 080a db93 cf70 0000 0000 0402 0000 .......p........ 为了方便,这里只截取前面三条数据。可以看到这是三个 SYN 请求,且有相同的序列号,证明 TCP 在进行重传。这就意味着 Apple 已经把请求发送到了路由器的 MAC 地址,而迟迟没有得到回复,触发了不断重传,直到最后达到 TCP Timeout 时间,curl 失败。这个时候其实路由器也没闲着,一直在把 Apple 发过来的请求发送到上一层网络,而当迟迟没有收到返回数据包的时候,要么是延迟太长,响应还没到,要么是这个 IP 地址不存在,请求包在公网不断漫游,直到达到 TTL 被丢弃。这里路由器和 Apple 都宁愿相信前者。所以这个时候用浏览器访问 http://192.168.111.111:3000 ,浏览器只会不断提示加载中,直到最终超时。如何修复 192.168.111.111 无法访问的问题?上节有提到:因为 192.168.111.111 无法匹配路由规则,导致数据包直接被发往路由器因为交换机只关心 MAC 地址,所以树莓派 wlan0 上的 192.168.111.111 是可被识别的简单来说,就是以太网层没有问题,IP 层因为路由规则匹配错误,出问题了。那只需要在 Apple 的路由规则上将 192.168.111.111 的数据流量发往 192.168.31.111 即可。sudo ip route add 192.168.111.111 via 192.168.31.111经过这样配置以后,关于 192.168.111.111 的数据包就会在以太网层加上 192.168.31.111 对应的 MAC 地址,即树莓派的地址。此时打开 http://192.168.111.111:30000/ 就能够成功访问 Grafana 了。如果是访问局域网不存在的 ip 地址,会发生什么?现在让 Apple 访问一个不存在的局域网 IP 地址: curl -XGET http://192.168.31.89/none/然后让树莓派监听局域网,看看会发生什么: sudo tcpdump -nX '(host 192.168.31.89 or src host 192.168.31.198) and (arp or tcp or udp)'这条命令监听了 Apple 和 Apple 要请求的 IP 地址,由于请求内容很多,所以我将其保存到了文件中,可以点击链接下载:request_non_exist_ip_address_under_LAN.pcap下面列出了文件中具体请求过程:>>> tcpdump -r request_non_exist_ip_address_under_LAN.pcap -nq reading from file request_non_exist_ip_address_under_LAN.pcap, link-type EN10MB (Ethernet), snapshot length 262144 21:39:49.324557 ARP, Request who-has 192.168.31.89 tell 192.168.31.198, length 28 21:39:50.352202 ARP, Request who-has 192.168.31.89 tell 192.168.31.198, length 28 21:39:50.469725 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:39:50.568694 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:39:51.372603 ARP, Request who-has 192.168.31.89 tell 192.168.31.198, length 28 21:39:52.397665 ARP, Request who-has 192.168.31.89 tell 192.168.31.198, length 28 21:39:53.319298 ARP, Request who-has 192.168.31.89 tell 192.168.31.198, length 28 21:39:55.690722 ARP, Reply 192.168.31.198 is-at a0:78:17:5e:8c:c4, length 28 21:40:05.577240 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:05.671259 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:11.552011 IP 192.168.31.198.5353 > 224.0.0.251.5353: UDP, length 337 21:40:20.672689 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:20.778594 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:24.345785 ARP, Request who-has 192.168.31.89 tell 192.168.31.198, length 28 21:40:35.788526 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:35.880446 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:50.132677 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:50.132853 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:50.135742 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 0 21:40:50.135990 IP 192.168.31.198.52690 > 192.168.31.134.9001: tcp 24 21:40:55.335923 ARP, Reply 192.168.31.198 is-at a0:78:17:5e:8c:c4, length 28 21:40:56.396894 ARP, Request who-has 192.168.31.89 tell 192.168.31.198, length 28 21:41:13.909238 IP 192.168.31.198.5353 > 224.0.0.251.5353: UDP, length 56 21:41:14.931763 IP 192.168.31.198.5353 > 224.0.0.251.5353: UDP, length 56 21:41:17.904960 IP 192.168.31.198.5353 > 224.0.0.251.5353: UDP, length 56 Apple 先后使用了 ARP / mDNS(Bonjour) 不断尝试找到 192.168.31.89 的 IP 地址,但可惜一直没有响应,而 curl 也乖乖地一直等到了 TCP 连接超时,即 RTT(round-trip time)。>>> curl -XGET http://192.168.31.89:8000/none/ curl: (28) Failed to connect to 192.168.31.89 port 8000 after 75007 ms: Couldn't connect to server 但第二次重新访问不存在的 IP 地址时, curl 快速返回了失败。下表列出了不同情况下访问不存在的 IP 地址, curl 的延迟结果:IP 范围是否首次访问Pingcurl 响应时间curl 返回值局域网 IP (192.168.31.89)✅arp 超时后报错75000mscurl: (28) Failed to connect to 192.168.31.89 port 8000 after 75007 ms: Couldn't connect to server局域网 IP (192.168.31.89)❌使用 arp 缓存,直接报错0mscurl: (7) Couldn't connect to server非本局域网 IP (192.168.111.111)✅不停发送 ICMP,无法察觉75000scurl: (28) Failed to connect to 192.168.111.111 port 8000 after 75007 ms: Couldn't connect to server非本局域网 IP (192.168.111.111)❌不停发送 ICMP,无法察觉75000scurl: (28) Failed to connect to 192.168.111.111 port 8000 after 75007 ms: Couldn't connect to server这里所有的 curl 请求失败都源于系统调用 connect ,在第一次 ARP 请求获取局域网 IP 失败后,Apple 保存了 ARP 请求的结果,所以在缓存过期之前, connect 系统调用获取 MAC 地址直接失败,导致 connect 快速失败,这是件好事。当 ping 失败后快速查看 ARP 表,可以看到这样一条记录:>>> ip neigh | grep 192.168.31.13 192.168.31.13 dev en0 INCOMPLETE 192.168.31.134 dev en0 lladdr e4:5f:1:a7:2a:86 REACHABLE INCOMPLETE 在这里的意思就是这个 IP 地址不存在,在该条 ARP 缓存到期之前不用发送新的 ARP 请求。这里有两个简单的问题:访问 192.168.111.111 时,Apple 会发送 ARP 请求吗?点击查看不会。Apple 通过子网掩码匹配路由规则,最终什么都没命中,于是就会走 default(路由器)网关。Apple 在哪些情况下会发送 ARP 请求?点击查看1⃣️ 命中路由规则,而对应 IP 地址的 MAC 地址未知。 2⃣️ 未命中路由规则,而路由器的 MAC 地址未知。ARP 请求属于以太层还是 IP 层?点击查看以太层。IP 层发送数据包时不会知道还执行了 ARP 请求这个操作,从耦合性 / 代码调用上讲,都属于以太层。MAC 地址如何构成的?和 IP 地址一样, MAC 地址也分为单播、多播、广播地址。参考这篇文章。6字节MAC地址=3字节从IEEE获得的OUI号+3字节厂商分配的唯一编号类型特点单播全球唯一,出厂自带组播前3 bytes 必须为 01-00-5E广播FFFF.FFFF.FFFF有的时候会在某些文档里看到 dynamic / static mac addr,这个其实是交换机的概念,交换机会将长时间没有数据包往来的 MAC 从缓存丢掉,同时也会存入新的 MAC 地址,这养的地址就是 dynamic mac address,与此相对比, static mac addr 就是手动在交换机上配置的写死的 MAC 地址。同样的还有 filter address,用来过滤 / 丢弃特定的 MAC 地址数据。如何监控整个电脑上的流量?简单点说就是可以通过创造 or 连接到一个虚拟网卡,并配置相应私有 IP。然后配置路由规则,将所有流量都发送到私有 IP 上,在该 IP 上运行有监控程序,一方面记录流量内容,另一方面根据分流策略直接将流量 MAC 头改为 default 网关地址。本来这篇是写这个主题的,不过经过查找资料后发现不是一两句就能说清楚的,还是在另一篇文章里写吧。Referencehttps://superuser.com/questions/1299022/creating-a-virtual-nic-that-connects-to-the-same-network-as-physical-nic#:~:text=Open%20Hyper%2DV%20Manager%20from,for%20that%20virtual%20network%20switch.https://unix.stackexchange.com/questions/21841/make-some-virtual-mac-address/156587#156587https://www.cisco.com/c/dam/en_us/training-events/le21/le34/downloads/689/academy/2008/sessions/BRK-134T_VPNs_Simplified.pdfhttps://www.cs.unh.edu/~it666/reading_list/Networking/firewall_concept_terms.pdfip link explain (macvlan explain)Red Hat ip command cheat sheetRed Hat arping doc大佬 dog250 的博客vlan 技术详解Question list:How MAC address assigned?like mentioned here