读大学时,宿舍每个人都买了电脑,为了节约网费,整个宿舍又从二手市场淘了台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
地址还是属于主机的,而不是某个网络接口。