四层结构
我们考虑四层的网络结构,如下图右侧:
image.png
由这个图,我们可以简单得到几个结论:
① 网卡层的转发,是靠MAC地址;
② 网络层的转发,是靠IP地址;
③ 传输层的转发,是靠端口;
⑤ Socket就是操作系统提供的,通过一个fd的占用,就可以屏蔽下面的工作,顺利读取数据,并做对应协议解析;
⑥ 对于输入的数据,从下到上解析;对于输出的数据,从上到下解析;当然也有可能是平级传输(在对等情况下,忽略上下过程);
⑦ 数据包转发过程中,IP地址是不会改变的,都是通过MAC地址改变来传递,除非做了NAT;
⑧ 网桥和交换机工作在第一层;NAT工作在第三层;
桥接与交换机[1]
桥接原理
image.png可以看到,网桥通过记录A、B两个端口的MAC地址,可以实现在第一层解包后,向另一个网段转发消息。
交换机原理
image.png可以知道,交换机上面是有N个插口的,所以他的表记录的内容是每一个插口的MAC地址。
此时如果某个插口对应的是交换机,就会进一步套娃:在外层交换机视角,记录可能被内存交换机反复刷新,触发“扩散”操作,即广播到内层;在内层交换机视角,有所记录,直接转发即可。
特征
① 网卡层;
② 集中式管理,即所有节点会先发送到网桥,再转发,即使是内网设备;
③ 能实现内网穿透,但是因为ip地址,不能在公网访问。
NAT
NAT不是特指一个设备,更多是指实现了一个功能。
原理
image.png可以看到,NAT实现了将一个“IP+Port”替换为另一个“IP+Port”的功能。
从IP角度,此时这个设备必须同时存在于“公网IP环”上和“内网IP环”上,同时也正是这个功能,使得数据能在两个环上跳转。
特征
① 传输层
② IP地址会发生变化
③ 两个环的交汇处
Docker的网络模式
常见的网络模式有5种,分别为
- bridge:实际上是NAT模式;Docker中默认的网络驱动模型,在启动容器时如果不指定则默认为此驱动类型;
- host:实际上是桥接模式;打破Docker容器与宿主机之间的网络隔离,直接使用宿主机的网络环境,该模型仅适用于Docker17.6及以上版本;
- overlay:可以连接多个docker守护进程或者满足集群服务之间的通信;适用于不同宿主机上的docker容器之间的通信;
- none:即禁用了网络驱动,需要自己手动自定义网络驱动配置;
- plugins:使用第三方网络驱动插件;
主要关注桥接(Bridge)模式
image.png
可以很明显看到,docker0作为一个虚拟网桥(拥有ip),和ens160这个物理网卡做了桥接(ip_forwad),然后Docker Container在连在虚拟网卡的环上。
此时两个环就出来了,只不过,内层环是在宿主机内部的。
无论这个模式叫什么名字,我们都要清楚,他的实现实际上是NAT,也就是说,container的网络是在宿主机的下层网络,即如果不通过宿主机,宿主机同级网络无法访问container网络。
为什么要叫桥接模式呢?
我个人更倾向于叫做NAT模式,除了满足NAT的一些特征,一些相关组件也能和NAT对应上,比如地址转换是通过iptables转换的(而不是通过一个表)
but 暂且认为是docker觉得自己docker0最精妙的地方就是网卡和veth-pair的设计,所以取名叫做桥接模式吧,同时它抽象了iptables的功能,让读者认为他就是简单能将container的流量转发到docker0上(忽略ip地址变化,甚至认为公网上就直接是指向container的ip),此时就满足了桥接的含义。
VMware的网络模式
一共有三种网络模式:桥接模式(VMnet0)、NAT(VMnet8)、仅主机模式(VMnet1)
桥接模式
image.png对于虚拟机的流量,会被物理网卡转发到虚拟交换机上再转发,所以可以认为路由器直接相连交换机,交换机再与这些网卡平等相连。
它桥接了物理网卡,这样物理网卡的消息就能转发到虚拟机上。
注意,VMnet0只是一个摆设,没有实际用处。
NAT模式
image.png图示中的NAT设备如同iptables一样,对发送过来的ip地址做转换;我们知道,NAT必须要主动向外界发消息,不然无法访问内部,即我们不能走"物理网卡-NAT设备"这条线相连,为了解决这个问题,于是引入了VMnet8,使得物理机网络与虚拟网络有一个重叠,这样通过VMnet8可以访问到虚拟机(如主机模式)。
主机模式
image.png图示很明显,我们在物理机想访问虚拟网络,只有通过VMnet8,但是VMnet8又与物理网卡隔离,这样整个虚拟网络都无法被外界访问。
Docker端口映射猜想
我们都知道,在启动一个container的时候,如果想要公网访问(即不在机器上直接访问),必须要做端口映射,如“-p 9980:80”。
- 从原理上,这个参数代表了iptables中增加了一条转换规则(这不就是NAT吗!),这样流量就能打到对应的container上了。
- (猜想)具体的数据流向
<1.14.46.100:8723, 1.14.46.101:12443>
,其中1.14.46.101
为宿主机路由器的公网IP,当数据到达路由器时,触发NAT,进入下一层网络:<1.14.46.100:8723, 192.168.1.10:9980>
,由路由器送到宿主机,iptables拦截下,转发到再下一层网络(下证):<1.14.46.100:8723, 172.18.0.2:80>
,此时就完成了从公网打到container的流程。 - 宿主机上一定有一个socket文件(可能在overlay中),在监听
172.18.0.2:80
这个端口,这样container中的应用就能从这里面取出数据进行应用层的处理了。
这个参数会带来一个iptables的增加,如下,作用是将主机9980的流量,转发到172.17.0.2:80上。
iptables -t nat -A DOCKER ! -i docker0 -p tcp -m tcp --dport 9980 -j DNAT --to-destination 172.17.0.2:80
[1](网络基础之网桥和交换机的工作原理及区别ugly_girl的博客-CSDN博客网桥和交换机的区别)
[2](VMware Workstation 的三种网络模式 - 知乎 (zhihu.com))
[3](iptables详解及docker的iptables规则_摩洛哥M的博客-CSDN博客_docker iptables)
网友评论