守护进程参数配置规则
限制容器间不受控的互相网络通信
由于Docker容器内核的共享性质,为了在多租户环境中更安全地实现责任分离。建议将容器运行在没有其它目的,且不用于敏感操作的宿主机上。可以考虑将所有服务迁移到Docker控制的容器中。同一主机上所有容器间默认不限制网络通信。因此,每个容器都可以读取同一主机上容器网络中的所有报文。这可能导致信息在无意中被泄露到其他容器。因此,应对容器间的通信进行限制。
建议修改方式:
- 在“/lib/systemd/system/docker.service”文件中的“ExecStart”项后面增加参数“--icc=false”(以下修改示例是HostOS为Ubuntu时)。
1 2
# vim /lib/systemd/system/docker.service ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock --selinux-enabled=false --icc=false
- 重启Docker服务。
1 2
# systemctl daemon-reload # systemctl restart docker
可执行以下命令查询上述修改是否成功。
1
# ps -ef|grep docker
确认回显中进程启动参数带“--icc=false”,则修改成功。
防止开启远程接口,将Docker守护进程暴露于外部网络
在默认情况下,Docker守护进程绑定到非网络Unix socket,并在root权限下运行,如unix:///var/run/docker.sock。
官方还提供一个Rustful api接口,允许通过TCP远程访问Docker,例如执行以下启动参数可以让docker侦听在本地所有地址的2375端口上:
1
|
dockerd -H=0.0.0.0:2375 -H unix:///var/run/docker.sock |
如果将默认的Docker守护进程绑定更改为TCP端口或其他Unix socket,开启这种没有任何访问控制的Docker remote Api服务是非常危险的,访问该端口或socket的任何人都有权限访问Docker守护进程,攻击者可以用Docker client或任意http客户端远程访问,进而访问主机系统,轻松地拿下整个服务器的权限。
因此:
- 不要将本地部署的Docker守护进程绑定到其他TCP端口或Unix socket,直接暴露于外部网络。
- 在不必需的情况下,不要启用Docker的remote api服务。
建议修改方式:
- 将“/lib/systemd/system/docker.service”文件中的“ExecStart”项参数“-H tcp://0.0.0.0:4243”删除,保留本地socket通信方式。
- 重启Docker服务。
1 2
# systemctl daemon-reload # systemctl restart docker
可执行以下命令查询上述修改是否成功。
1
# ps -ef | grep docker
确认回显中进程启动参数不带“-H tcp://0.0.0.0:4243”,则修改成功。
禁用用户空间代理
Docker引擎提供了两个从主机到容器的端口传输机制:hairpin网络地址转换(NAT)和用户空间代理。在大多数情况下,应优先采用hairpin NAT模式,这一模式能够提高性能,使用自身的网络过滤器功能,而不使用额外的组件。如果可以使用hairpin NAT模式,在启动时应禁用用户空间代理,减小设备的攻击面。
建议修改方式:
- 在“/lib/systemd/system/docker.service”文件中的“ExecStart”项后面增加参数“--userland-proxy=false”。
- 重启Docker服务。
1 2
# systemctl daemon-reload # systemctl restart docker
可执行以下命令查询上述修改是否成功。
1
# ps -ef | grep docker
确认回显中进程启动参数带“--userland-proxy=false”,则修改成功。
启用user namespace命名空间
user namespace为运行在host上的docker提供更加安全保障。它利用容器用户到主机的重映射机制,为容器用户和主机用户提供权限隔离。简单的说就是可以让容器拥有看起来和主机系统中不同的uid和gid。例如容器中的root用户,在主机系统里可能是一个非root用户。这允许进程在容器中以root权限运行,但容器在主机系统中却没有真正拥有root权限。如果所使用的容器在容器镜像里没有定义一个明确的容器用户,该建议会很有用,如果所使用的容器镜像已经有预定义的非root用户,则可跳过该建议。
Kbox未启用user namespace命名空间,该建议与为容器创建单独分区冲突,请根据实际业务需要自行配置。
开启守护进程的细粒度访问策略控制
Docker的授权模型默认是全部授予或者完全不授予。任何拥有权限的用户都能通过访问守护进程来运行Docker客户端命令,这对于使用远程API访问Docker的调用者也是一样。如果要加强访问控制,就需要创建一个授权插件(authorization plugin),开启细粒度的访问策略控制,有Docker管理员来对守护进程进行安全配置。授权插件(authorization plugin)默认是没有设置的。
Kbox当前未开启守护进程的细粒度访问策略控制,用户可按需参照以下步骤开启细粒度访问策略控制。
- 安装创建一个授权插件(authorization plugin)。
- 配置合适的授权策略。
- 用下面方式启动docker守护进程。
1
# dockerd --authorization-plugin=<PLUGIN_ID>
可执行以下命令查询上述修改是否成功。
1
# ps -ef | grep docker | grep '\-\-authorization-plugin'
确认回显非空,则修改成功。
配置集中式日志和远程日志
集中和远程日志记录确保所有重要日志记录尽管发生灾难性事件都是安全的。Docker现在支持各种日志驱动,可以选择一个对业务环境最合适的。
建议修改方式:
- 在“/lib/systemd/system/docker.service”文件中的“ExecStart”项后面增加参数“--log-driver=syslog”。
若“ExecStart”项后面存在参数“ --log-opt max-size=1g”,则需要先将参数“ --log-opt max-size=1g”删除,再添加参数“--log-driver=syslog”。
- 重启Docker服务。
1 2
# systemctl daemon-reload # systemctl restart docker
可执行以下命令查询上述修改是否成功。
1
# ps -ef | grep docker
确认回显中进程启动参数带“--log-driver=syslog”,则修改成功。
启用现场还原live-restore
“--live-restore”参数可以让容器减少对Docker守护进程的依赖。该参数可以不用停止或关闭容器的情况下而让容器在重启时能够自恢复和重新建立连接。同时它是一个重要的安全组策略,能够在守护进程没有正常服务的同时让容器正常运行,也就是说该参数可以让Docker守护进程放心执行安全升级和安全补丁了。该参数默认是没有设置的。
建议修改方式:
- 在“/lib/systemd/system/docker.service”文件中的“ExecStart”项后面增加启动参数“--live-restore”。
- 重启Docker服务。
1 2
# systemctl daemon-reload # systemctl restart docker
可执行以下命令查询上述修改是否成功。
1
# ps -ef | grep docker
确认回显中进程启动参数带“--live-restore”,则修改成功。
使用TCP远程访问时需开启TLS认证
默认情况下,Docker守护进程只绑定一个本地套接字。如果存在必须远程访问Docker daemon,则需开启TLS认证。
在生产环境中禁止启用实验功能
Docker的实验功能尚未经过充分测试,不能保证API的稳定性,不能用于生产环境。