lubiao

读大学时,宿舍每个人都买了电脑,为了节约网费,整个宿舍又从二手市场淘了台TP-LINK路由器。这样每个人的电脑就通过路由器连接到学校网管中心,再连接到外网。从路由器后台界面可以看到,路由器为每个人的电脑分配了一个IP地址。这看上去IP是属于主机的.

tplink

进入职场以后,公司的电脑都安装了两个物理网卡,通过两根网线分别接入了两个网络(10.X.X.X/8 和 192.X.X.X/24).

从适配器管理界面可以看到,两个网卡都有各自的IP地址.这样看上去,IP地址是属于网卡的。

那么,究竟哪种说法正确呢 ?

先上结论:IP地址属于主机,即使我们配置都是在网卡上配置IP地址。

IP地址与网络接口

Linux中, 我们可以通过ifconfig -a或者ip addr看到主机上的所有网络接口,它有两种来源,一种是物理网卡的驱动程序创建的,另一种是内核自己或者用户主动创建的虚拟接口。

举个栗子:

ipaddr1

ip addr命令一共输出了4项,其中ens33是物理网卡驱动程序创建的,而lo是内核启动时自己创建的环回网络接口,veth0veth1则是我们自己创建的veth peer虚拟网络接口。

我们可以将每个网络接口都视作一条管道,管道的一端连接到本机内核路由子系统,而另一端根据类型各有不同。物理网卡对应的网络接口另一端通向设备驱动程序;
veth peer类型的接口另一端通向对方;tun类型设备的另一端通向用户应用程序。

图:网络设备

另外,从上面的输出内容中还可以注意到的是:网络接口上并不是一定都有IP地址(本文提到的IP地址专指IPv4地址),比如veth0veth1后面都没有IP地址。

IP地址是网络层的概念,而网卡其实更多的是链路层的概念。

一个简化版的IP报文的接收处理流程如下:

IF  报文目标MAC == 网卡MAC
    对报文进行路由
	IF 报文目标IP匹配本机路由
        上送本机传输层
	ELSE IF 匹配其他路由
		根据路由进行转发
	END
END

在这个过程中,网卡只参加了链路层头部的检查,只要报文通过检查,就会上送给网络层进行路由,至于之后报文去哪,它才不会管。报文去哪儿完全是路由说了算

route

一般来说就两条路,如果匹配上了本机路由,则表示这个报文就是给自己的,那么就根据报文的protocol字段,上送给对应协议(比如TCP UDP ICMP)处理;如果匹配上其他路由,就表示这个报文只是将本机当作中转站,于是它会根据路由结果找到报文的出网络接口,从该网络接口(管道)的另一端发送出去.

那么问题来了,这些路由是哪里来的?

答案是:当你为网络接口配置IP地址时,内核会生成对应的主机路由、网段路由和广播路由!

还是上面那个栗子,我们为veth0上配置IP地址

ipaddr2

MAIN表里可以看到新添加的网段路由

图netroute

LOCAL表里可以看到新添加的主机路由和广播路由

图 localroute

现在我们做个实验,从PC2ping刚刚配置IPveth0

图

(我们需要先在PC2上为1.2.3.4配置一条静态路由,让其知道这个地址其实就在局域网上的主机上,而不会走默认网关)

PC2 add route

执行ping,果然能ping通!

ping

我们在PC1上对网卡的抓包结果如下:

pcap

这是是普通的局域网内的ping交互过程:PC2先通过ARP获得1.2.3.4对应的MAC地址,再是普通的ICMP requestICMP reply

稍微有点意思的是PC2得到的1.2.3.400:0c:29:d6:56:46,这不是veth0MAC地址,而是ens33MAC地址。这说明上面的交互过程压根没有veth0的参与!如果你用tcpdump去抓取veth0上的报文,得不到任何结果!

之所以会这样,这是因为Linux在收到ARP请求时,默认行为是只要ARP请求报文的目标IP地址能匹配本机路由,就会回复收到ARP请求报文的网络接口的MAC地址。

只有主机路由,没有IP地址

也就是说,如果没有为veth0配置IP,而只是配置了主机路由呢 ?

图

上面的操作中,我们删除了之前为veth0配置的IP地址,而是主动配置了一条本机路由

还是在PC2ping 1.2.3.4,也能ping通!

图2ping

结论

我们在网络接口上配置IP地址的本质是配置路由。说到底,IP地址还是属于主机的,而不是某个网络接口。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐