Docker容器:网络以及容器安全

发布于 2017-03-15 · 本文总共 2843 字 · 阅读大约需要 9 分钟

通过Namespace和Cgroups技术实现了容器进程的隔离,通过AUFS让容器拥有自己的“文件系统”;

网络相关背景知识

协议、接口和端口

网络、NAT和端口转发

网络虚拟化技术

Linux虚拟网络设备

Linux支持创建出虚拟化的设备,可以通过虚拟化设备的组合实现多种多样的功能和网络拓扑;

常见的虚拟化设备有Veth、Bridge、802.1q VLAN device、TAP;

Linux Veth

Veth是成对出现的虚拟网络设备,发送到Veth一端虚拟设备的请求会从另一端的虚拟设备中发出; 在容器的虚拟化场景中,经常会使用Veth连接不同的网络Namespace;

Linux Bridge

Bridge虚拟设备是用来桥接的网络设备,相当于现实世界中的交换机,可以连接不同的网络设备, 当请求到达Bridge时,可以通过报文中的Mac地址进行广播或转发;

sudo ip netns add ns1
sudo ip link add vth0 type veth peer name veth1
sudo ip link veth1 setns ns1
# 创建网桥
sudo brctl addbr br0
# 挂载网络设备
sudo brctl addif br0 eth0
sudo brctl addif br0 veth0

Linux路由表

路由表是Linux内核的一个模块,通过定义路由表来决定在某个网络Namespace中包的流向,从而定义请求会到那个网络设备上;

通过设置路由,对IP地址的请求就能正确的路由到对应的网络设备上,从而实现通信;

Linux iptables

iptables是对Linux内核的netfilter模块进行操作和展示的工具,用来管理包的流动和转送;

iptables定义了一套链式处理的结构,在网络包传输的各个阶段可以使用不同的策略对包进行加工、传送或者丢弃;

在容器虚拟化的技术中,经常会用到两种策略MASQUERADE和DNAT,用于容器和宿主机外部的网络通信;

MASQUERADE

iptables中的MASQUERADE策略可以将请求包中的源地址转换成一个网络设备的地址;

# 打开IP转发
sudo sysctl -w net.ipv4.conf.all.forwarding=1
# 对namespace中发出的包添加网络地址转换
sudo iptables -t nat -A POSTROUTING -s 172.18.0.0./24 -o eth0 -j MASQUERADE

在namespace中请求宿主机外部地址时,将namespace中的源地址转换成宿主机的地址作为源地址,就可以在namespace中访问宿主机外的网络了;

DNAT

DNAT策略也是做网络地址的转换,不过它是更换目标地址,经常用于将内部网络地址的端口映射到外部去;

sudo iptables -t nat -A PREROUTING -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.2:80

这样就可以把宿主机上80端口的TCP请求转发到namespace中的地址172.18.0.2:80,从而实现外部的应用调用;

Docker网络基础

Docker本身的技术依赖于近年Linux内核虚拟化技术的发展,Docker对Linux内核的特性有很强的依赖;

Docker使用到的与Linux网络有关的主要技术包括:

  • Network Namespace

  • Veth设备对

  • Iptables/Netfilter

  • 网桥

  • 路由

network namespace网络命名空间

原理

为了支持网络协议栈的多个实例,Linux在网络栈中引入了network namespace, 这些独立的协议栈被隔离到不同的命名空间。

在Linux的network namespace内可以有自己独立的路由表及独立的Iptables/Netfilter设置来提供包转发 以及NAT、IP包过滤等功能;

Linux支持7种namespace:

  1. cgroup用于隔离cgroup根目录;

  2. IPC用于隔离系统消息队列;

  3. Network隔离网络;

  4. Mount隔离挂载点;

  5. PID隔离进程;

  6. User隔离用户和用户组;

  7. UTS隔离主机名nis域名。

实践

创建一个network namespace:

ip netns add <name>

在命名空间执行命令:

ip netns exec <name> <command>
ip netns exec <name> bash

Veth设备对

网络命名空间代表的是一个独立的协议栈,相互隔离无法通信;通过Veth设备对可以打通;

veth设备都是成对出现,很像一对以太网卡

操作命令:

给两个network namespace配置“网线”:

创建对:
ip link add veth0 type veth peer name veth1
ip link show
把另外一个给到其他network namespace:
ip link set veth1 netns netns1

加上IP:

ip netns exec netns1 ip addr add 10.1.1.1/24 dev veth1
ip addr add 10.1.1.2/24 dev veth0

启动:

ip netns exec netns1 ip link set dev veth1 up
ip link set dev veth0 up

网桥

brctl addbr xxxx
brctl addif xxxx ethx
ifconfig ethx 0.0.0.0
ifconfig brxxxx xx.xx.xx.xx

iptables/netfilter

iptables-save
iptables-vnL

路由

ip route show table local type local
ip route list
netstat -rn

Docker网络的局限

没有考虑多主机互联的网络解决方案

容器跨主机网络

Linux Bridge没有办法路由到宿主机外部,所以不同宿主机Bridge上的容器还是得通过映射到端口的方式来实现互相访问;

跨主机容器网络通信的常见方式

封包

可以把容器之间的请求外面包装上宿主机的地址发送,这样跨主机的容器之间的通信就转换成了宿主机之间的通信,到达另外一个容器所在 的宿主机后再解开外面的包装,拿到真正的容器请求,就能实现跨主机的容器间通信了;

常见的封包技术有VxLan、Ipip-tunnel、GRE,或者自己的封包格式等,通过这些技术就可以将容器间的请求封装成宿主机间的请求;

对基础设施要求低,只需要宿主机之间能联通即可;但是性能损耗较大(带宽、资源);

路由

让宿主机的网络“知道”容器的地址要怎么路由、路由到哪台机器,这种方式一般要网络设备的支持,比如修改路由器的路由表, 将容器IP的地址的下一跳修改到这个容器所在的宿主机上;

常见的路由技术有路由器路由表、Vlan、各大云服务厂商的VPC路由表等;

无封包、性能好;但是对基础网络设施有要求,需要支持一些路由的配置或者特定的网络协议;

Docker的安全机制

Docker daemon安全

镜像安全

内核安全

容器之间的网络安全




本博客所有文章采用的授权方式为 自由转载-非商用-非衍生-保持署名 ,转载请务必注明出处,谢谢。
声明:
本博客欢迎转发,但请保留原作者信息!
博客地址:邱文奇(qiuwenqi)的博客;
内容系本人学习、研究和总结,如有雷同,实属荣幸!
阅读次数:

文章评论

comments powered by Disqus


章节列表