当前位置: 首页 > 科技观察

使用Docker容器的20大安全提示

时间:2023-03-13 09:11:25 科技观察

本文包含帮助您安全使用Docker的提示。如果您是Docker新手,我建议您先阅读我之前关于Docker概念、Docker生态系统、Dockerfile、瘦镜像、Docker中的常用命令和数据的文章。您需要多关注Docker的安全性?这取决于Docker是否内置了合理的安全功能。如果您使用的是官方Docker镜像并且它不与其他机器通信,则无需担心。但是,如果您使用的是非官方图像、服务文件或在生产环境中运行您的应用程序,那么情况就不同了。在这种情况下,您需要了解更多有关Docker安全性的知识。您的主要安全目标是防止恶意用户获取有价值的信息或造成破坏。为此,我将在几个关键领域分享Docker安全最佳实践。到本文结束时,您将看到20多个Docker安全提示!在第一部分中,我们将重点关注三个方面:访问管理图像安全秘密管理考虑使用首字母缩略词AIM来帮助您记住它们。首先,让我们看看限制对容器的访问。访问管理——限制权限启动容器时,Docker会创建一组命名空间。命名空间可防止容器中的进程看到或影响主机(包括其他容器)中的进程。命名空间是Docker将一个容器与另一个容器隔离的主要方式。Docker还提供私有容器网络。这可以防止容器获得对同一主机上其他容器的网络接口的特权访问。所以Docker环境有些孤立,但对于您的用例来说可能还不够孤立。>看起来不安全良好的安全性意味着遵循最小特权原则。您的容器应该具有执行所需功能的能力,但没有其他能力。棘手的是,一旦您开始限制可以在容器内运行的进程,容器可能无法执行它合法需要执行的操作。有几种方法可以调整容器的权限。首先,避免以root身份运行(如果必须,您应该重新映射)。其次,使用--cap-drop和--cap-add调整功能。大多数人需要做的是避免root和调整功能以限制权限。更高级的用户可能想要调整默认的AppArmor和seccomp配置文件。我将在即将出版的有关Docker的书中讨论这些内容,但我将它们留在此处以防止本文出现预期的膨胀。避免以root身份运行Docker默认设置是让映像中的用户以root身份运行。许多人没有意识到这有多危险。这意味着攻击者更容易访问敏感信息和您的内核。作为一般的最佳实践,不要让容器以root身份运行。>Roots“防止来自容器内部的权限升级攻击的最佳方法是将容器的应用程序配置为以非特权用户身份运行。”—Docker文档。您可以在构建时指定root以外的用户名,如下所示:dockerrun-u1000my_image-user或-u标志可以指定用户名或用户ID。如果userid不存在也没关系。在上面的示例中,1000是任意的非特权用户ID。在Linux中,通常保留0到499之间的用户ID。选择一个超过500的用户ID,以避免以默认系统用户身份运行。最好从镜像的root用户更改用户,而不是从命令行设置用户。这样人们就不必记住在构建时进行更改。仅在需要root附带的功能的Dockerfile指令之后,才在映像中包含USERDockerfile指令。也就是说,先安装需要的包,再切换用户。例如:FROMalpine:latestRUNapkupdate&&apkadd--no-cachegitUSER1000...如果您必须以超级用户身份在容器中运行进程,请将该超级用户重新映射到Docker主机上的特权较低的用户。请参阅Docker文档。您可以通过更改功能授予用户所需的权限。能力函数是允许的过程包。使用--cap-drop和--cap-add通过命令行调整功能。最好的策略是使用--cap-dropall从容器中删除所有权限,然后使用--cap-add重新添加所需的权限。>Stoporgo您可以在运行时调整容器的功能。例如,要放弃使用kill停止容器的能力,您可以删除该默认能力,如下所示:dockerrun--cap-drop=Killmy_image避免给进程SYS_ADMIN和SETUID特权,因为它们具有广泛的权力。将此功能添加到用户类似于授予root特权(避免这种结果是不使用root的全部意义)。更安全的做法是禁止容器使用1到1023之间的端口号,因为大多数网络服务都在这个范围内运行。未经授权的用户可以侦听诸如登录之类的事情并运行未经授权的服务器应用程序。这些编号较小的端口需要以root身份运行或明确赋予CAP_NET_BIND_SERVICE能力。要了解容器是否具有特权端口访问等信息,您可以使用inspect。使用dockercontainerinspectmy_container_name将向您显示有关容器分配的资源和安全配置文件的许多详细信息。这是Docker参考,有关特权的更多信息。与Docker中的大多数内容一样,最好在自动化的自文档文件中配置容器。使用DockerCompose,您可以像这样在服务配置中指定功能:cap_drop:ALL或者,您可以在Kubernetes文件中调整它们,如此处所述。Linux功能的完整列表在这里。要对容器权限进行更细粒度的控制,请查看我在即将出版的书中对AppArmor和seccomp的讨论。订阅我的电子邮件时事通讯,以便在可用时得到通知。>闭路访问管理——限制资源最好限制容器对内存、CPU等系统资源的访问。没有资源限制,容器可以用完所有可用内存。如果发生这种情况,Linux主机内核将抛出“内存不足”异常并终止内核进程。这可能会导致整个系统崩溃。您可以想象攻击者如何利用这些知识来尝试关闭应用程序。如果您在同一台机器上运行多个容器,明智的做法是限制任何一个容器可以使用的内存和CPU。如果您的容器内存不足,它将关闭。关闭容器可能会使应用程序崩溃,这很不好玩。但是,这种隔离可以防止主机内存不足,并防止主机上的所有容器崩溃。这是好事。>Wind资源DockerDesktopCEforMacv2.1.0有默认的资源限制。您可以在Docker图标->首选项下访问它们。然后单击“资源”选项卡。您可以使用滑块调整资源限制。>Mac上的资源设置或者,您可以通过指定--memory标志(或简称-m,后跟数字和度量单位)来限制命令行上的资源。4m表示4兆字节,是最小的容器内存分配。兆字节(MiB)略大于兆字节(1MiB=1.048576MB)。该文档目前不正确,但希望维护者在您阅读本文时已经接受了我的PR更改。要查看您的容器正在使用哪些资源,请在新的终端窗口中输入命令dockerstats。您会看到定期刷新的运行容器统计信息。>Stats在后台,Docker使用Linux控制组(cgroups)来实施资源限制。该技术已经过实战测试。在此处了解有关Docker资源限制的更多信息。图像安全从DockerHub抓取图像就像邀请某人进入您的家。你可能想阐明这一点。>某人的家使用值得信赖的镜子镜子安全的规则之一是只使用您信任的镜子。你怎么知道哪些镜像值得信赖?可以肯定的是,流行的官方镜像是相对安全的。此类镜像包括alpine、ubuntu、python、golang、redis、busybox和node。每个都有超过1000万的下载量,并且有很多人关注他们。Docker解释说:Docker赞助了一个专门的团队,负责审查和发布官方镜像中的所有内容。该团队与上游软件维护人员、安全专家和更广泛的Docker社区合作,以确保这些图像的安全。减少攻击面与使用官方基础镜像有关,这是您可以使用的最小基础镜像。由于内部代码较少,安全漏洞的可能性较小。较小、不太复杂的基础图像更透明。在Alpine镜像中查看发生了什么比在你朋友的镜像中要容易得多(这取决于朋友的镜像,而朋友的镜像又依赖于另一个基础镜像)。短线更容易解开。>TangledAgain,只安装你真正需要的包。这减少了攻击面并加快了图像下载和图像构建。需要签名的图像图像您可以使用DockerContentTrust来确保图像已签名。DockerContentTrust阻止用户使用标记图像,除非它们包含签名。可信来源包括来自DockerHub的官方Docker镜像和来自用户可信来源的签名镜像。>Signed默认禁用内容信任。要启用它,请将DOCKER_CONTENT_TRUST环境变量设置为1。从命令行运行以下命令:exportDOCKER_CONTENT_TRUST=1现在,当我尝试从DockerHub拉下我自己的未签名图像时,它被阻止了。错误:remotetrustdatadoesnotexistfordocker.io/discdiver/frames:notary.docker.iodoesnothavetrustdatafordocker.io/discdiver/frames内容信任是防止重复的一种方法。在此处了解有关内容信任的更多信息。Docker通过图像内容的加密校验和来存储和访问图像。这可以防止攻击者创建图像冲突。这是一个很酷的内置安全功能。管理密码您的访问受限并且镜像是安全的,现在是时候管理您的密码了。“管理敏感信息的规则1:不要将其添加到您的镜像中。在代码存储库、日志和其他地方不难找到未加密的敏感信息。规则2:也不要将环境变量用于敏感信息......任何可以在容器中运行dockerinspect或exec的人都可以找到你的密码。任何以root身份运行的人都可以。希望我们已经配置了一些东西,这样用户就不会以root身份运行,但是多余的Yu是良好安全性的一部分。通常也会记录日志转储环境变量值。你不希望你的敏感信息泄露给任何人。Docker卷更好。建议使用它们来访问Docker文档中的敏感信息。你可以使用卷作为临时文件系统保存在内存。卷消除了dockerinspect和日志记录风险。但是,root用户仍然可以看到秘密,任何可以在容器中执行的人都可以看到它们。总体而言,卷是一个很好的解决方案。比卷更好,使用DockerS秘密。机密已加密。>Secrets一些Docker文档指出您只能在DockerSwarm中使用秘密。但是,您可以在没有Swarm的情况下使用它们,以防万一。如果只需要镜像中的secret,可以使用BuildKit。与目前用于构建Docker镜像的构建工具相比,BuildKit是一个更好的后端。它大大减少了构建时间并具有其他不错的功能,包括支持构建时秘密。BuildKit相对较新——DockerEngine18.09是第一个支持BuildKit的版本。可以通过三种方式指定BuildKit后端,因此您可以开箱即用地使用其功能。将来,它将成为默认后端。使用exportDOCKER_BUILDKIT=1将其设置为环境变量。使用DOCKER_BUILDKIT=1开始构建或运行命令。默认情况下启用BuildKit。使用以下命令将/etc/docker/daemon.json中的配置设置为true:{"features":{"buildkit":true}}。然后重新启动Docker。然后,您可以在构建时使用--secret标志使用秘密,如下所示:dockerbuild--secretmy_key=my_value,src=path/to/my_secret_file。文件将您的Secret指定为键值对的位置。这些秘密不会存储在最终图像中。它们也被排除在图像构建缓存之外。安全第一!如果您需要在容器中运行Secrets,而不仅仅是在构建镜像时,请使用DockerCompose或Kubernetes。使用DockerCompose,将机密键值对添加到服务并指定机密文件。提示改编自关于DockerCompose秘密的StackExchange回答,用于以下示例。示例docker-compose.ymlwithSecret:version:"3.7"services:my_service:image:centos:7entrypoint:"cat/run/secrets/my_secret"secrets:-my_secretsecrets:my_secret:file:./my_secret_file.txt然后开始撰写像往常一样使用docker-composeup--buildmy_service。如果您使用的是Kubernetes,它支持秘密。Helm-Secrets可以帮助简化K8s中的秘密管理。此外,与DockerEnterprise一样,K8s具有基于角色的访问控制(RBAC)。RBAC使管理团队的访问秘密变得更易于管理和安全。Secret的最佳实践是使用诸如Vault之类的秘密管理服务。Vault是HashiCorp的一项服务,用于管理对秘密的访问。它还限制了秘密的时间。您可以在此处找到有关Vault的Docker映像的更多信息。AWSSecretsManager和其他云提供商的类似产品也可以帮助您管理云中的秘密。>密钥请记住,管理秘密的关键是保守秘密。绝对不要将它们添加到您的图像或将它们变成环境变量。更新与任何代码一样,使镜像中的语言和库保持最新,以便从最新的安全修复中获益。>希望您的安全性比这个锁更新如果您在图像中引用特定版本的基础图像,请确保也将其保持在最新状态。相关地,您应该使您的Docker版本保持最新以修复错误和增强功能,以允许您实施新的安全功能。最后,让您的主机服务器软件保持最新。如果您使用的是托管服务,这应该为您完成。更好的安全性意味着保持更新。考虑DockerEnterprise如果您的组织有一群人和一堆Docker容器,那么您可以从DockerEnterprise中受益。管理员可以为所有用户设置策略限制。提供的RBAC、监视和日志记录功能可以使您的团队更轻松地进行安全管理。使用Enterprise,您还可以在DockerTrustedRegistry中私下托管您自己的图像。Docker提供了一个内置的安全扫描功能,以确保您的镜像中没有已知的漏洞。Kubernetes免费提供其中一些功能,但DockerEnterprise为容器和图像提供额外的安全功能。最重要的是,DockerEnterprise3.0于2019年7月发布。它包括具有“合理的安全默认值”的DockerKubernetes服务。其他提示除非您有特定需要,例如在Docker容器内运行Docker,并且您知道自己在做什么,否则永远不要以特权方式运行容器。在Dockerfile中,建议使用COPY而不是ADD。ADD自动提取压缩文件并可以从URL复制文件。COPY没有这些功能。尽可能避免添加,这样您就不容易受到来自远程URL和Zip文件的攻击。如果您在同一台服务器上运行任何其他进程,请在Docker容器中运行它们。如果您使用Web服务器和API创建容器,请仔细检查参数,以免创建您不想要的新容器。如果公开RESTAPI,请使用HTTPS或SSH保护API端点。考虑使用DockerBenchforSecurity检查您的容器是否符合其安全准则。仅将敏感数据存储在卷中,而不是容器中。如果使用带网络的单主机应用程序,请不要使用默认的桥接网络。它存在技术缺陷,不建议用于生产。如果端口已发布,则可以访问桥接网络上的所有容器。将LetsEncrypt用于HTTPS证书以进行服务。请在此处查看有关NGINX的示例。仅当需要读取卷时才将卷挂载为只读。在这里查看几种方法。总结您已经看到了许多使Docker容器更安全的方法。安全不是静态的。需要保持警惕以确保图像和容器的安全。>密钥在考虑安全性时,请牢记AIM:(1)访问管理避免以超级用户身份运行。如果必须使用root,请重新映射。删除所有功能并重新添加您需要的功能。如果您需要细粒度的权限调整,请进入AppArmor。限制资源。(2)镜像安全使用官方镜像、流行镜像、最小基础镜像。不要安装你不需要的东西。需要对图像进行签名。保持Docker、Docker映像和其他与Docker相关的软件更新。(3)Secret秘密管理使用Secret或Volume。考虑一个秘密管理器,例如保险库。>靶心!保持Docker容器安全意味着实现安全目标。不要忘记保持Docker、您的语言和库、您的图像以及您的主机软件的更新。最后,如果您作为团队的一部分运行Docker,请考虑DockerEnterprise。希望本文对Docker安全性有所帮助。如果您这样做了,请在您最喜欢的论坛或社交媒体频道上与他人分享,以便您的朋友也能找到它!