读大学时,宿舍每个人都买了电脑,为了节约网费,整个宿舍又从二手市场淘了台 TP-LINK 路由器。这样每个人的电脑就通过路由器连接到学校网管中心,再连接到外网。从路由器后台界面可以看到,路由器为每个人的电脑分配了一个 IP
地址。这看上去 IP
是属于 主机 的.
进入职场以后,公司的电脑都安装了两个物理网卡,通过两根网线分别接入了两个网络(10.X.X.X/8 和 192.X.X.X/24).
从适配器管理界面可以看到, 两个网卡都有各自的 IP 地址. 这样看上去,IP
地址是属于 网卡 的。
那么,究竟哪种说法正确呢?
先上结论:IP 地址属于主机 ,即使我们配置都是在 网卡 上配置 IP 地址。
IP 地址与网络接口
在 Linux
中, 我们可以通过 ifconfig -a
或者 ip addr
看到主机上的所有 网络接口
,它有两种来源,一种是物理网卡的驱动程序创建的,另一种是内核自己或者用户主动创建的虚拟接口。
举个栗子:
ip addr
命令一共输出了 4
项,其中 ens33
是物理网卡驱动程序创建的,而 lo
是内核启动时自己创建的环回网络接口,veth0
和 veth1
则是我们自己创建的 veth peer
虚拟网络接口。
我们可以将每个网络接口都视作一条管道,管道的一端连接到本机内核路由子系统,而另一端根据类型各有不同。物理网卡对应的网络接口另一端通向设备驱动程序;veth peer
类型的接口另一端通向对方;tun
类型设备的另一端通向用户应用程序。
另外,从上面的输出内容中还可以注意到的是:网络接口上并不是一定都有 IP
地址 (本文提到的 IP 地址专指 IPv4 地址),比如veth0
和veth1
后面都没有 IP
地址。
IP 地址
是网络层的概念,而网卡其实更多的是链路层的概念。
一个简化版的 IP
报文的接收处理流程如下:
IF 报文目标 MAC == 网卡 MAC
对报文进行路由
IF 报文目标 IP 匹配本机路由
上送本机传输层
ELSE IF 匹配其他路由
根据路由进行转发
END
END
在这个过程中,网卡只参加了链路层头部的检查,只要报文通过检查,就会上送给网络层进行路由,至于之后报文去哪,它才不会管。报文去哪儿完全是路由说了算!
一般来说就两条路,如果匹配上了 本机路由
,则表示这个报文就是给自己的,那么就根据报文的protocol
字段,上送给对应协议 (比如TCP
UDP
ICMP
) 处理;如果匹配上 其他路由
, 就表示这个报文只是将本机当作中转站,于是它会根据路由结果找到报文的 出网络接口 ,从该网络接口(管道) 的另一端发送出去.
那么问题来了,这些路由是哪里来的?
答案是:当你为网络接口配置 IP
地址时,内核会生成对应的主机路由、网段路由和广播路由!
还是上面那个栗子,我们为 veth0
上配置 IP
地址
在 MAIN
表里可以看到新添加的网段路由
在 LOCAL
表里可以看到新添加的主机路由和广播路由
现在我们做个实验,从 PC2
上ping
刚刚配置 IP
的veth0
(我们需要先在 PC2
上为 1.2.3.4
配置一条静态路由,让其知道这个地址其实就在局域网上的主机上,而不会走默认网关)
执行 ping
, 果然能ping
通!
我们在 PC1
上对网卡的抓包结果如下:
这是是普通的局域网内的 ping
交互过程:PC2
先通过 ARP
获得 1.2.3.4
对应的 MAC
地址,再是普通的 ICMP request
和ICMP reply
。
稍微有点意思的是 PC2
得到的 1.2.3.4
的00:0c:29:d6:56:46
,这不是 veth0
的MAC
地址,而是 ens33
的MAC
地址。这说明上面的交互过程压根没有 veth0
的参与!如果你用 tcpdump
去抓取 veth0
上的报文,得不到任何结果!
之所以会这样,这是因为 Linux
在收到 ARP
请求时,默认行为是只要 ARP
请求报文的目标 IP
地址能匹配 本机路由 ,就会回复收到ARP
请求报文的网络接口的 MAC
地址。
只有主机路由,没有 IP
地址
也就是说,如果没有为 veth0
配置IP
,而只是配置了主机路由呢?
上面的操作中,我们删除了之前为 veth0
配置的 IP
地址,而是主动配置了一条 本机路由
还是在 PC2
上ping
1.2.3.4
, 也能 ping
通!
结论
我们在网络接口上配置 IP
地址的本质是配置路由。说到底,IP
地址还是属于主机的,而不是某个网络接口。