diff --git a/advanced_network/example.md b/advanced_network/example.md index 9606cc6..2379646 100644 --- a/advanced_network/example.md +++ b/advanced_network/example.md @@ -1,8 +1,8 @@ ##工具和示例 在介绍自定义网络拓扑之前,你可能会对一些外部工具和例子感兴趣: -https://github.com/jpetazzo/pipework +https://github.com/jpetazzo/pipework Jérôme Petazzoni 创建了一个叫pipework的shell脚本来帮助我们在复杂的场景中完成网络连接 -https://github.com/brandon-rhodes/fopnp/tree/m/playground +https://github.com/brandon-rhodes/fopnp/tree/m/playground Brandon Rhodes创建了一个完整的docker容器网络拓扑,包含 nat 防火墙,服务包括HTTP, SMTP, POP, IMAP, Telnet, SSH, and FTP: -工具使用的网络命令跟我们之前看到非常相似。 \ No newline at end of file +工具使用的网络命令跟之前看到非常相似。 diff --git a/advanced_network/ptp.md b/advanced_network/ptp.md index e6c45d2..8b77c3d 100644 --- a/advanced_network/ptp.md +++ b/advanced_network/ptp.md @@ -1,15 +1,15 @@ ##创建一个点到点连接 -默认docker会将所有容器连接到由docker0提供的虚拟子网,你也可以使用自己创建的网桥。但如果你想要2个特殊的容器之间可以直连通信,而不用去配置复杂的主机网卡桥接。 -解决办法很简单:创建一对接口,把2个容器放到这对接口中,配置成点到点链路类型。这2个容器就可以直接通信了。配置如下: +默认Docker会将所有容器连接到由docker0提供的虚拟子网,你也可以使用自己创建的网桥。但如果你想要2个特殊的容器之间可以直连通信,而不用去配置复杂的主机网卡桥接。 + +解决办法很简单:创建一对接口,把2个容器放到这对接口中,配置成点到点链路类型。这2个容器就可以直接通信了。首先启动2个容器: ``` -# 在2个终端中启动2个容器 $ sudo docker run -i -t --rm --net=none base /bin/bash root@1f1f4c1f931a:/# $ sudo docker run -i -t --rm --net=none base /bin/bash root@12e343489d2f:/# ``` -找到他们的process IDs ,然后创建他们的 namespace entries +找到他们的进程号,然后创建他们的 namespace entries ``` $ sudo docker inspect -f '{{.State.Pid}}' 1f1f4c1f931a 2989 @@ -34,7 +34,7 @@ $ sudo ip netns exec 3004 ip addr add 10.1.1.2/32 dev B $ sudo ip netns exec 3004 ip link set B up $ sudo ip netns exec 3004 ip route add 10.1.1.1/32 dev B ``` -现在这2个容器就可以相互ping通,并成功建立连接。点到点链路不需要子网和子网掩码,使用ip route 来连接单个ip地址到指定的网络接口。 -如果没有特殊需要你不需要指定--net=none来创建点到点链路。 +现在这2个容器就可以相互ping通,并成功建立连接。点到点链路不需要子网和子网掩码,使用`ip route`来连接单个ip地址到指定的网络接口。 +如果没有特殊需要你不需要指定`--net=none`来创建点到点链路。 -还有一个办法就是创建一个只跟主机通信的容器,除非有特殊需求,你可以仅用--icc=false来限制主机间的通信。 \ No newline at end of file +还有一个办法就是创建一个只跟主机通信的容器,除非有特殊需求,你可以仅用`--icc=false`来限制主机间的通信。 diff --git a/container_security/README.md b/container_security/README.md index 8f42d24..ae209e0 100644 --- a/container_security/README.md +++ b/container_security/README.md @@ -1,5 +1,5 @@ #容器安全 -评估docker的安全性时,主要考虑3个方面: -* 由内核中namespace和cgruoups提供的容器的内在安全 -* docker程序本身的抗攻击性 -加固内核安全性来影响容器的安全性 +评估Docker的安全性时,主要考虑3个方面: +* 由内核中名字空间和控制组提供的容器的内在安全 +* Docker程序本身的抗攻击性 +* 加固内核安全性来影响容器的安全性 diff --git a/container_security/control_group.md b/container_security/control_group.md index 815549c..c6aeee1 100644 --- a/container_security/control_group.md +++ b/container_security/control_group.md @@ -1,3 +1,4 @@ -##Control Groups -Control Groups 是LXC容器的另外一个关键组件,由它来实现资源的审计和限制。他们提供了很多有用的特性,还可以用来确保每个容器可以公平分享主机的内存、cpu、磁盘IO等资源,更重要的是,它可以保证当一个容器耗尽其中一个资源的时候不会连累主机宕机。 -尽管他们不阻止容器之间相互访问、处理数据和进程,但他们在防止拒绝服务攻击方面是必不可少的。在多用户的平台比如共有或则私有的paas上更加重要,当某些应用程序表现不好的时候,可以保证一直的uptime和性能。Control Groups 始于2006年,从2.6.24之后被引入。 \ No newline at end of file +##控制组 +控制组是LXC容器的另外一个关键组件,由它来实现资源的审计和限制。他们提供了很多有用的特性,还可以用来确保每个容器可以公平分享主机的内存、CPU、磁盘IO等资源,更重要的是,它可以保证当一个容器耗尽其中一个资源的时候不会连累主机宕机。 + +尽管他们不阻止容器之间相互访问、处理数据和进程,但他们在防止拒绝服务攻击方面是必不可少的。在多用户的平台比如共有或则私有的PaaS上更加重要,当某些应用程序表现不好的时候,可以保证一直的uptime和性能。控制组始于2006年,从2.6.24之后被引入。 diff --git a/container_security/daemon_sec.md b/container_security/daemon_sec.md index 5abf98c..73fed2b 100644 --- a/container_security/daemon_sec.md +++ b/container_security/daemon_sec.md @@ -1,11 +1,16 @@ ##Docker Daemon Attack Surface -运行一个容器或则应用程序意味着运行一个docker 服务。docker服务要求root权限,所以你需要了解一些重要的细节。 -首先,确保只有可信的用户可以访问docker服务,因为这会直接导致很严重的后果。因为,docker允许你在主机和容器之间共享文件夹,这就容易让容器突破资源限制。比如当你在启动容器的时候将主机的/映射到容器的/host目录中,那么容器就可以对主机做任何更改了。这听起来很疯狂?不过,你要知道几乎所有虚拟机系统都有在物理主机和虚拟机之间共享资源的限制,所以需要你自己来考虑这一层的安全性。 -比如,当你使用一个web api来提供容器创建服务时,要比平常更加注意参数的检查,防止恶意的用户用精心准备的参数来创建带有任意参数的容器 +运行一个容器或则应用程序意味着运行一个Docker 服务。Docker服务要求root权限,所以你需要了解一些重要的细节。 + +首先,确保只有可信的用户可以访问docker服务,因为这会直接导致很严重的后果。因为,Docker允许你在主机和容器之间共享文件夹,这就容易让容器突破资源限制。比如当你在启动容器的时候将主机的/映射到容器的/host目录中,那么容器就可以对主机做任何更改了。这听起来很疯狂?不过,你要知道几乎所有虚拟机系统都有在物理主机和虚拟机之间共享资源的限制,所以需要你自己来考虑这一层的安全性。 + +比如,当你使用一个web api来提供容器创建服务时,要比平常更加注意参数的检查,防止恶意的用户用精心准备的参数来创建带有任意参数的容器。 + 因此,REST API在docker0.5.2之后使用unix socket替代了绑定在127.0.0.1上的tcp socket(后者容易遭受跨站脚本攻击)。现在你可以使用增强的unix sockt权限来限制对控制socket的访问。 + 你依然可以将REST API发布到http服务上。不过一定要小心确认这里的安全机制,确保只有可信的网络或则vpn或则受保护的stunnel和ssl认证可以对REST API进行访问。还可以使用https和认证HTTPS and certificates. 最近改进的linux namespace将很快可以实现使用非root用户来运行全功能的容器。这解决了因在容器和主机共享文件系统而引起的安全问题。 -docker的终极目标是改进2个安全特性: + +Docker的终极目标是改进2个安全特性: * 将root用户的容器映射到主机上的非root用户,减轻容器和主机之间因权限提升而引起的安全问题 -* 允许docker服务在非root权限下运行,委派操作请求到那些经过良好审计的子进程,每个子进程拥有非常有限的权限:虚拟网络设定,文件系统管理、配置等等。 -最后,如果你在一个服务器上运行docker,建议去掉docker之外的其他服务,除了一些管理服务比如ssh 监控和进程管理工具nrpe clllectd等等。 \ No newline at end of file +* 允许Docker服务在非root权限下运行,委派操作请求到那些经过良好审计的子进程,每个子进程拥有非常有限的权限:虚拟网络设定,文件系统管理、配置等等。 +* 最后,如果你在一个服务器上运行Docker,建议去掉Docker之外的其他服务,除了一些管理服务比如ssh 监控和进程管理工具nrpe clllectd等等。 diff --git a/container_security/kernel_capability.md b/container_security/kernel_capability.md index 94da4c8..c46e564 100644 --- a/container_security/kernel_capability.md +++ b/container_security/kernel_capability.md @@ -1,6 +1,8 @@ -##Linux Kernel Capabilities -默认情况下,docker启动的容器只严格使用一部分内核capabilities。这代表什么呢? -这是一个root或非root 二分法粒度管理的访问控制系统。比如web服务进程只需要绑定一个低于1024的端口,不需要用root来允许:那么它只需要给它授权net_bind_service功能就可以了。还有很多其他的capabilities,几乎所有需要root权限的仅需要指定一个部分capabilities就可以了。 +##内核权限 +默认情况下,Docker启动的容器只严格使用一部分内核capabilities。这代表什么呢? + +这是一个root或非root二分法粒度管理的访问控制系统。比如web服务进程只需要绑定一个低于1024的端口,不需要用root来允许:那么它只需要给它授权net_bind_service功能就可以了。还有很多其他的capabilities,几乎所有需要root权限的仅需要指定一个部分capabilities就可以了。 + 这对容器的安全有很多好处,通常的服务器需要允许一大堆root进程,通常有ssh cron syslogd;模块和网络配置工具等等。容器则不同,因为大部分这种人物都被容器外面的基础设施处理了: * ssh可以被主机上ssh服务替代 * 硬件管理也无关紧要,容器中也就无需执行udevd或则其他类似的服务 @@ -14,4 +16,6 @@ * 还有一些其他的 就算攻击者在容器中取得了root权限,他能做的破坏也少了,也不能获得主机的更高权限。 -然而这不会影响普通的web apps,恶意的用户会想各种办法来对你!默认情况下,docker丢弃了它需要的功能之外的其余部分。这里有一个白名单和黑名单,在 Linux manpages可以看到完整的清单列表。当然,你还可以启用你需要的额外capabilities。默认docker容器仅使用白名单的内capabilities。 +然而这不会影响普通的web apps,恶意的用户会想各种办法来对你! + +默认情况下,docker丢弃了它需要的功能之外的其余部分。这里有一个白名单和黑名单,在 Linux manpages可以看到完整的清单列表。当然,你还可以启用你需要的额外权限。默认Docker容器仅使用白名单的内capabilities。 diff --git a/container_security/kernel_ns.md b/container_security/kernel_ns.md index fbba541..dfd6e2a 100644 --- a/container_security/kernel_ns.md +++ b/container_security/kernel_ns.md @@ -1,6 +1,10 @@ -##Kernel Namespaces -docker容器和lxc容器很相似,他们提供的安全特性也差不多。当你用docker run启动一个容器时,在后台docker 为容器创建了一个namespace和contril groups的集合。 -Namespaces提供了最初也是最直接的隔离,在容器中运行的进程不会被运行在主机上的进程和容器发现,他们之间相互影响也就小了。 +##内核名字空间 +Docker容器和LXC容器很相似,他们提供的安全特性也差不多。当你用`docker run`启动一个容器时,在后台Docker为容器创建了一个名字空间和控制组的集合。 + +名字空间提供了最初也是最直接的隔离,在容器中运行的进程不会被运行在主机上的进程和容器发现,他们之间相互影响也就小了。 + 每个容器都有自己的网络堆栈,他们不能访问其他容器的sockets接口。不过,如果在主机系统上做了相应的设置,他们还是可以像跟主机交互一样的和其他容器交互通信。当你指定公共端口或则使用links来连接2个容器时,他们就可以相互通信了。(相互ping、udp、tcp都没问题,也可以根据需要设定更严格的策略)从网络架构上来看,所有的容器通过主机的网桥接口相互通信,就像物理机器通过物理交换机通信一样。 -内核提供的namesapce和私有网络的代码有多成熟? -内核namesapce从内核2.6.15之后被引入,距今已经5年了,在很多大型生产系统中被验证。他们的设计和灵感提出的时间更早,openvz项目利用namespace重新封装他们的内核,并合并到主流内核中。openvz最早的版本在2005,所以他们的设计和实现都很成熟。 \ No newline at end of file + +内核提供的名字空间和私有网络的代码有多成熟? + +内核名字空间从内核2.6.15之后被引入,距今已经5年了,在很多大型生产系统中被验证。他们的设计和灵感提出的时间更早,openvz项目利用名字空间重新封装他们的内核,并合并到主流内核中。openvz最早的版本在2005,所以其设计和实现都很成熟。 diff --git a/container_security/other_feature.md b/container_security/other_feature.md index 8718a27..9c181bc 100644 --- a/container_security/other_feature.md +++ b/container_security/other_feature.md @@ -1,7 +1,9 @@ -##其它安全特性 -Capabilities是现代linux内核提供的诸多安全特性中的一个,docker可以利用现有的如TOMOYO, AppArmor, SELinux, GRSEC来增强安全性。为什么docker当前只启用capabilities,而不介入其他系统。 -因为这样他就还可以有很多方法来加固docker主机,下面是一些例子。 -*你可以在内核中加载GRSEC和PAX,这会增加很多安全检查。 -*你可以使用一些有增强安全特性的发行版的模板,比如带apparmor的模板和redhat系列带selinux dcoker策略,这些模板提供了额外的安全特性。 -*使用你自己喜欢的访问控制机制来定义你自己的安全策略。 -像其他添加到docker容器的第三方工具一样(比如网络拓扑和文件系统共享),有很多这样的工具,利用他们可以不用改变docker内核就可以加固现有的docker容器 \ No newline at end of file +##其它内核安全特性 +Capabilities是现代linux内核提供的诸多安全特性中的一个,Docker可以利用现有的如TOMOYO, AppArmor, SELinux, GRSEC来增强安全性。 + +为什么Docker当前只启用capabilities,而不介入其他系统。 +因为这样就可以有很多方法来加固Docker主机,下面是一些例子。 +* 可以在内核中加载GRSEC和PAX,这会增加很多安全检查。 +* 可以使用一些有增强安全特性的发行版的模板,比如带apparmor的模板和redhat系列带selinux dcoker策略,这些模板提供了额外的安全特性。 +* 使用你自己喜欢的访问控制机制来定义你自己的安全策略。 +像其他添加到docker容器的第三方工具一样(比如网络拓扑和文件系统共享),有很多这样的工具,利用他们可以不用改变docker内核就可以加固现有的docker容器 diff --git a/container_security/summary.md b/container_security/summary.md index ca0f897..589b4b4 100644 --- a/container_security/summary.md +++ b/container_security/summary.md @@ -1,2 +1,4 @@ ##结论 -docker容器默认还是比较安全的,特别是你如果注意在容器中使用非root权限来允许进程的话。你还可以添加额外的比如Apparmor, SELinux, GRSEC等你熟悉的加固方法。最后,如果你对其他容器系统中的安全特性感兴趣,你也可以在docker中实现它,毕竟,所有的东西都已经在内核中了。 +Docker容器默认还是比较安全的,特别是你如果注意在容器中使用非root权限来允许进程的话。你还可以添加额外的比如Apparmor, SELinux, GRSEC等你熟悉的加固方法。 + +最后,如果你对其他容器系统中的安全特性感兴趣,你也可以在Docker中实现它,毕竟,所有的东西都已经在内核中了。