一个请求是如何从实体机传递到我们的应用的
iptables -> docker deamon -> docker bridge network -> docker container -> app
##从iptables开始
参考:https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/4/html/Security_Guide/s1-firewall-ipt-fwd.html
维基百科:iptables,一个运行在用户空间的应用软件,通过控制Linux内核netfilter模块,来管理网络数据包的流动与转送。
因为公网IP的稀有与昂贵,公司一般只有一个公网IP,使用局域网与私有IP是访问公网资源的常用方式.防火墙与路由器可以将请求转发到内网机器上,也可以将传入路由到对应内网节点.这样的转发很危险,特别是攻击者伪装成内网节点.为了防止这种情况,iptables提供了可以实现的路由和转发策略,以防止网络资源的异常使用。
####iptables的FORWARD策略
控制经过本节点的数据包路由的位置,例如转发到所有节点
如果这样设置,在这个防火墙之后的所有节点都可以接收到数据包,相当于创建了一个路由规则,发送到这个路由的数据包都可以达到数据包内包含的预期节点,且都通过eth1设备
1 | iptables -A FORWARD -i eth1 -j ACCEPT |
此时内网节点还不能正常访问外网,需要将内网IP伪装成路由IP来访问外网资源
1 | iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE |
如果你想让一个内网节点成为外部可用的服务器,使用DNAT转发策略,将外部请求转发到改内网节点,Docker就是使用这个策略将请求转发到对应container中
1 | iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to 172.31.0.23:80 |
##iptables结合docker deamon转发
参考:https://wiki.archlinux.org/index.php/Network_bridge_(简体中文) <Docker进阶与实战>
####iptables -> docker deamon
Docker deamon在启动container时会在主机上采用iptables的DNAT策略,将iptables接受到的请求转发给改container所属的内网节点
1 | root@ip-172-31-18-147:/home/ubuntu# docker run -itd -p 80:80 nginx |
####docker deamon -> docker bridge network
Docker deamon启动时会在主机创建一个Linux网桥(网桥:网桥是一种软件配置,用于连结两个或更多个不同网段。网桥的行为就像是一台虚拟的网络交换机,工作于透明模式(即其他机器不必关注网桥的存在与否)。任意的真实物理设备(例如 eth0)和虚拟设备(例如 tap0)都可以连接到网桥。)(默认为docker0).
容器启动时会创建一对veth pair,docker将一端挂在docker0网桥上,另一端放到容器的Network Namespace内,从而实现容器与主机通信的目的.
####docker bridge network -> docker container
当前没有容器运行,网桥上没有网络接口,但默认分配了172.17.0.1/16的子网
1 | root@ip-172-31-18-147:/home/ubuntu# ip addr show docker0 |
然后启动一个container测试,container会自动加入到该子网中
1 | root@ip-172-31-18-147:/home/ubuntu# docker run -it ubuntu:14.04 |
综上所述,Docker会为我们创建一个iptables转发规则,将从外界接收到的请求转发到Docker在启动container时创建的子网中的对应节点
号外号外
最近在总结一些针对Java面试相关的知识点,感兴趣的朋友可以一起维护~
地址:https://github.com/xbox1994/2018-Java-Interview