本文主要介绍Docker和iptables,以及在桥接模式下实现网络隔离和通信 *** 作,具有很好的参考价值。希望对大家有帮助。来和边肖一起看看吧。
Docker提供网桥、主机、覆盖和其他网络。同一个Docker主机上有很多不同类型的网络,不同网络中的容器无法相互通信。
Docker容器的跨网络隔离和通信是基于iptables的机制。
iptables的过滤表默认分为三个链:输入、转发、输出。
Docker处于转发链(forwardtouser-definedchain),额外提供自己的链,实现桥接网络之间的隔离和通信。
Docker的基本网络配置
Docker启动时会自动在主机上创建一个docker0虚拟桥,实际上是Linux的一个桥,可以理解为软件交换机。它将在安装到它的端口之间转发。
同时,Docker在本地未被占用的私有网段中随机分配一个地址给docker0接口。例如,典型的172.17.0.1掩码是255.255.0.0。之后,启动的容器中的网络端口会自动分配一个相同网段的地址(172.17.0.0/16)。
创建Docker容器时,会同时创建一对vethpair接口(当一个数据包发送到一个接口时,另一个接口也可以接收到相同的数据包)。
接口的一端在容器中,即eth0;另一端是本地的,挂载到docker0桥,名字以veth开头(比如veth1)。这样,主机可以与容器通信,容器之间也可以相互通信。
Docker在主机和所有容器之间创建一个虚拟共享网络。
1。iptables过滤表中的Docker链
在Docker18.05.0(2018.5)和更高版本中,提供了以下四个链:
码头工人
对接-隔离-第一阶段
对接-隔离-第二阶段
码头工人-用户
目前Docker有一个完整的默认情况下主机的iptables设置规则列表,在/etc/sysconfig/iptables文件中。
##地址转发表nat中的规则链及默认 *nat #PREROUTING规则链默认策略是ACCEPT :PREROUTINGACCEPT[0:0] #INPUT规则链默认策略是ACCEPT :INPUTACCEPT[0:0] #OUTPUT规则链默认策略是ACCEPT :OUTPUTACCEPT[4:272] #POSTROUTING规则链默认策略是ACCEPT :POSTROUTINGACCEPT[4:272] #DOCKER规则链默认策略是ACCEPT :DOCKER-[0:0] #######################在PREROUTING规则链中添加的规则########################### ##-m表示使用扩展模块进行数据包匹配,到达本机的数据包,如果目标地址类型是本地局域网,则指定到DOCKER链 -APREROUTING-maddrtype--dst-typeLOCAL-jDOCKER #######################在OUTPUT规则链中添加的规则########################### -AOUTPUT!-d127.0.0.0/8-maddrtype--dst-typeLOCAL-jDOCKER #######################在POSTROUTING规则链中添加的规则########################### ##这条规则是为了使容器和外部网络通信 #将源地址为192.168.0.0/20的包(也就是从Docker容器产生的包),并且不是从docker0网卡发出的 #进行源地址转换,转换成主机网卡的地址。 -APOSTROUTING-s192.168.0.0/20!-odocker0-jMASQUERADE ############################在DOCKER规则链中添加的规则########################### #由docker0接口输入的数据包,返回到调用链;-i指定了要处理来自哪个接口的数据包 -ADOCKER-idocker0-jRETURN ############################################################################### ##规则表中的链及默认策略 *filter :INPUTDROP[4:160] :FORWARDACCEPT[0:0] :OUTPUTACCEPT[59:48132] :DOCKER-[0:0] :DOCKER-ISOLATION-STAGE-1-[0:0] :DOCKER-ISOLATION-STAGE-2-[0:0] :DOCKER-USER-[0:0] ############################在FORWARD规则链中添加的规则########################### ##数据包全部指定到DOCKER-USER链 -AFORWARD-jDOCKER-USER ##数据包全部指定到DOCKER-ISOLATION-STAGE-1链 -AFORWARD-jDOCKER-ISOLATION-STAGE-1 -AFORWARD-odocker0-mconntrack--ctstateRELATED,ESTABLISHED-jACCEPT ##由docker0接口输出的数据包,指定到DOCKER链 -AFORWARD-odocker0-jDOCKER ##由docker0接口输入的数据包,且不是由docker0接口输出的数据包,允许通过 -AFORWARD-idocker0!-odocker0-jACCEPT ##由docker0接口输入的数据包,且由docker0接口输出的数据包,允许通过 -AFORWARD-idocker0-odocker0-jACCEPT ####################在DOCKER-ISOLATION-STAGE-1规则链中添加的规则################# ##由docker0接口输入的数据包,且不是由docker0接口输出的数据包,指定到DOCKER-ISOLATION-STAGE-2链 ##也就是要处理来自docker0的数据包,但是不是由docker0输出的数据包 -ADOCKER-ISOLATION-STAGE-1-idocker0!-odocker0-jDOCKER-ISOLATION-STAGE-2 ##数据包直接返回到调用链 -ADOCKER-ISOLATION-STAGE-1-jRETURN ####################在DOCKER-ISOLATION-STAGE-2规则链中添加的规则################# ##由docker0接口输出的数据包,丢弃掉 -ADOCKER-ISOLATION-STAGE-2-odocker0-jDROP ##数据包直接返回到调用链 -ADOCKER-ISOLATION-STAGE-2-jRETURN ############################在DOCKER-USER规则链中添加的规则########################### ##直接返回到调用链 -ADOCKER-USER-jRETURN2。Docker的DOCKER链
仅处理从主机到停靠站0的IP数据包。
3。DOCKER-DOCKER的隔离链(隔离不同桥接网络之间的通信)
如您所见,为了隔离不同桥接网络之间的通信,Docker提供了两个DOCKER-ISOLATION阶段实现。
DOCKER-ISOLATION-STAGE-1链过滤源地址为网桥网络(默认docker0)的数据包,匹配的数据包进入DOCKER-ISOLATION-STAGE-2链进行处理;
如果不匹配,就向前返回父链。
在DOCKER-ISOLATION-STAGE-2链中,进一步处理目的地址为网桥网络(默认为docker0)的数据包,匹配的数据包表示该数据包从一个网桥网络的网桥发送到另一个网桥网络的网桥。此类数据包来自其他桥接网络,将被直接丢弃;
不匹配的数据包将被返回到父链进行进一步处理。
4。DOCKER-DOCKER的用户链
当Docker启动时,DOCKER链和DOCKER-ISOLATION(现为DOCKER-ISOLATION-STAGE-1)链中的过滤规则将被加载并生效。这里绝对禁止修改过滤规则。
如果用户想补充Docker的过滤规则,强烈建议追加到DOCKER-USERchain。
Docker-USER链中的过滤规则会在DOCKER默认创建的规则之前加载(在上面的规则列表中,DOCKER_USER链是最早追加到规则链中的),从而能够覆盖DOCKER链和DOCKER-ISOLATION链中DOCKER的默认过滤规则。
例如,在Docker启动后,默认情况下,任何外部源IP都被允许转发,因此能够从该源IP连接到主机上的任何Docker容器实例。如果仅允许一个指定的IP访问容器实例,则可以将路由规则插入到对接者-用户链中,从而可以在对接者链之前加载该路由规则。
例子如下:
#只允许192.168.1.1访问容器 iptables-ADOCKER-USER-idocker0!-s192.168.1.1-jDROP #只允许192.168.1.0/24网段中的IP访问容器 iptables-ADOCKER-USER-idocker0!-s192.168.1.0/24-jDROP #只允许192.168.1.1-192.168.1.3网段中的IP访问容器(需要借助于iprange模块) iptables-ADOCKER-USER-miprange-idocker0!--src-range192.168.1.1-192.168.1.3-jDROP5。iptables的nat表中的Docker规则
为了能够从容器访问其他Docker主机,Docker需要在iptables的nat表中的POSTROUTING链中插入转发规则。示例如下:
iptables-tNAT-Apostrouting-s172.18.0.0/16-j伪装
上述配置进一步限制了容器实例的IP范围,这是为了区分Docker主机上有多个桥接网络的情况。
6。Docker中禁止修改iptables过滤表
dockerd启动时,参数-iptables默认设置为true,这意味着允许修改iptables路由表。
要禁用此功能,有两个选项:
设置启动参数-iptables=false
修改配置文件/etc/docker/daemon.json,设置“iptables”:“false”;";然后执行systemctlreloaddockerreload。
附加知识:Docker网络模式的默认桥接模式
如上所述,docker有五种网络模式,分别是birdge、host、overlay、nacvlan、none和Networkplugin。这里主要介绍默认的桥接模式。
一、导言
在网络的概念中,桥接网络是在网段之间转发通信的链路层设备。网桥是运行在主机内核上的硬件设备或软件设备。在docker中,桥接网络由软件桥接。连接到同一个桥接网络的容器可以直接相互通信,并且是全端口的,与没有连接到桥接网络的容器直接隔离。这样,桥接网络管理同一主机上所有容器的连接和隔离。Docker的桥驱动自动在主机上安装规则。同一网桥上的网络可以相互通信,不同网桥的网络容器相互隔离。
该网络适用于由同一主机docker守护程序生成的容器。对于不同主机之间的容器交互,要么使用 *** 作系统级的路由 *** 作,要么使用覆盖网络驱动器。
当我们启动docker时,systemctl启动docker,并且会自动创建一个默认的桥接网络(birbr0),将docker守护进程与主机相连,同时创建一个网络docker0,后续的生产容器会自动连接到这个桥接网络(docker0)。我们可以检查当地的桥梁。每次创建容器时,都会创建一个新的网桥,将容器与默认网桥网络连接起来。
[root@localhosthadoop]#brctlshow bridgenamebridgeidSTPenabledinterfaces docker08000.0242b47b550dno virbr08000.52540092a4f4yesvirbr0-nic [root@localhosthadoop]#网桥virbr0连接docker0和主机,在网桥上创建接口virbr0-nic,接收docker0网络的数据。生成每个容器,在docker0上新建一个接口,docker0的地址设置为容器的网关。
[root@localhosthadoop]#dockerrun--rm-tdinvidia/cuda:9.0-base [root@localhosthadoop]#dockerps CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 9f9c2b80062fnvidia/cuda:9.0-base"/bin/bash"15secondsagoUp14secondsquizzical_mcnulty [root@localhosthadoop]#brctlshow bridgenamebridgeidSTPenabledinterfaces docker08000.0242b47b550dnovethabef17b virbr08000.52540092a4f4yesvirbr0-nic [root@localhosthadoop]#检查本地网络信息ifconfig-a
[root@localhosthadoop]#ifconfig-a docker0:flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu1500 inet192.168.0.1netmask255.255.240.0broadcast192.168.15.255 inet6fe80::42:b4ff:fe7b:550dprefixlen64scopeid0x20<link> ether02:42:b4:7b:55:0dtxqueuelen0(Ethernet) RXpackets37018bytes2626776(2.5MiB) RXerrors0dropped0overruns0frame0 TXpackets46634bytes89269512(85.1MiB) TXerrors0dropped0overruns0carrier0collisions0 eno1:flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu1500 inet192.168.252.130netmask255.255.255.0broadcast192.168.252.255 ether00:25:90:e5:7f:20txqueuelen1000(Ethernet) RXpackets14326014bytes17040043512(15.8GiB) RXerrors0dropped34overruns0frame0 TXpackets10096394bytes3038002364(2.8GiB) TXerrors0dropped0overruns0carrier0collisions0 devicememory0xfb120000-fb13ffff eth1:flags=4099<UP,BROADCAST,MULTICAST>mtu1500 ether00:25:90:e5:7f:21txqueuelen1000(Ethernet) RXpackets0bytes0(0.0B) RXerrors0dropped0overruns0frame0 TXpackets0bytes0(0.0B) TXerrors0dropped0overruns0carrier0collisions0 devicememory0xfb100000-fb11ffff lo:flags=73<UP,LOOPBACK,RUNNING>mtu65536 inet127.0.0.1netmask255.0.0.0 inet6::1prefixlen128scopeid0x10<host> looptxqueuelen0(LocalLoopback) RXpackets3304bytes6908445(6.5MiB) RXerrors0dropped0overruns0frame0 TXpackets3304bytes6908445(6.5MiB) TXerrors0dropped0overruns0carrier0collisions0 oray_vnc:flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu1200 inet172.1.225.211netmask255.0.0.0broadcast172.255.255.255 ether00:25:d2:e1:01:00txqueuelen500(Ethernet) RXpackets1944668bytes227190815(216.6MiB) RXerrors0dropped0overruns0frame0 TXpackets2092320bytes2232228527(2.0GiB) TXerrors0dropped0overruns0carrier0collisions0 vethabef17b:flags=4163<UP,BROADCAST,RUNNING,MULTICAST>mtu1500 inet6fe80::e47d:4eff:fe87:39d3prefixlen64scopeid0x20<link> ethere6:7d:4e:87:39:d3txqueuelen0(Ethernet) RXpackets0bytes0(0.0B) RXerrors0dropped0overruns0frame0 TXpackets8bytes648(648.0B) TXerrors0dropped0overruns0carrier0collisions0 virbr0:flags=4099<UP,BROADCAST,MULTICAST>mtu1500 inet192.168.122.1netmask255.255.255.0broadcast192.168.122.255 ether52:54:00:92:a4:f4txqueuelen0(Ethernet) RXpackets0bytes0(0.0B) RXerrors0dropped0overruns0frame0 TXpackets0bytes0(0.0B) TXerrors0dropped0overruns0carrier0collisions0 virbr0-nic:flags=4098<BROADCAST,MULTICAST>mtu1500 ether52:54:00:92:a4:f4txqueuelen500(Ethernet) RXpackets0bytes0(0.0B) RXerrors0dropped0overruns0frame0 TXpackets0bytes0(0.0B) TXerrors0dropped0overruns0carrier0collisions0Docker结合了桥和路由规则来设置同一主机中容器之间的交互。在docker容器桥接网络的驱动下,网络访问方式如下图所示:
如果容器启动时指定了端口映射,内部端口80映射到主机端口8080,或者网卡可以用0.0.0:8080的方式指定,如下
dockerrun-RM-ti-p8080:80NVIDIA/cuda:9.0-base
然后检查路由表,
iptables-tnat-vnL
您可以看到已经添加了路由和转发规则:
[root@localhosthadoop]#iptables-tnat-vnL ChainPREROUTING(policyACCEPT55packets,2470bytes) pktsbytestargetprotoptinoutsourcedestination 161K8056KPREROUTING_directall--**0.0.0.0/00.0.0.0/0 161K8056KPREROUTING_ZONES_SOURCEall--**0.0.0.0/00.0.0.0/0 161K8056KPREROUTING_ZONESall--**0.0.0.0/00.0.0.0/0 00DOCKERall--**0.0.0.0/00.0.0.0/0ADDRTYPEmatchdst-typeLOCAL ChainINPUT(policyACCEPT0packets,0bytes) pktsbytestargetprotoptinoutsourcedestination ChainOUTPUT(policyACCEPT0packets,0bytes) pktsbytestargetprotoptinoutsourcedestination 3442258KOUTPUT_directall--**0.0.0.0/00.0.0.0/0 00DOCKERall--**0.0.0.0/0!127.0.0.0/8ADDRTYPEmatchdst-typeLOCAL ChainPOSTROUTING(policyACCEPT0packets,0bytes) pktsbytestargetprotoptinoutsourcedestination 00MASQUERADEall--*!docker0192.168.0.0/200.0.0.0/0 00RETURNall--**192.168.122.0/24224.0.0.0/24 00RETURNall--**192.168.122.0/24255.255.255.255 00MASQUERADEtcp--**192.168.122.0/24!192.168.122.0/24masqports:1024-65535 00MASQUERADEudp--**192.168.122.0/24!192.168.122.0/24masqports:1024-65535 00MASQUERADEall--**192.168.122.0/24!192.168.122.0/24 3442258KPOSTROUTING_directall--**0.0.0.0/00.0.0.0/0 3442258KPOSTROUTING_ZONES_SOURCEall--**0.0.0.0/00.0.0.0/0 3442258KPOSTROUTING_ZONESall--**0.0.0.0/00.0.0.0/0 00MASQUERADEtcp--**192.168.0.3192.168.0.3tcpdpt:80 ChainDOCKER(2references) pktsbytestargetprotoptinoutsourcedestination 00RETURNall--docker0*0.0.0.0/00.0.0.0/0 00DNATtcp--!docker0*0.0.0.0/00.0.0.0/0tcpdpt:8080to:192.168.0.3:80的默认端口类型是TCP。
二。容器间访问配置
首先启动两个容器,然后进入容器,检查每个容器的IP信息。
[root@localhosthadoop]#dockerps CONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES 462751a70444nvidia/cuda:9.0-base"/bin/bash"17minutesagoUp17minutes0.0.0.0:8080->80/tcpsad_heyrovsky 9f9c2b80062fnvidia/cuda:9.0-base"/bin/bash"41minutesagoUp41minutesquizzical_mcnulty [root@localhosthadoop]#我在这里启动两个容器,然后调用dockerinspect容器ID来检查容器IP。
dockinspect-f{{.networksettings.IPaddress}}容器ID
我们的两个集装箱是192.168.0.2192.168.0.3。
当你进入其中一个容器ping另一台机器时,你会发现只有使用地址模式才能ping通192.168.0.3。
dockerexec-ti9F9C2b80062f/bin/bash
如果将别名附加到/etc/hosts,然后ping该名称,则无法ping它。
节点1
至于原因,下一篇文章会继续讲解解决这个问题的自定义桥接网络。
以上Docker和iptables以及桥接网络隔离和通信的实现都是边肖分享的内容。希望给大家一个参考,支持我们。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)