Docker 安全和日志管理
容器安全问题的根本原因是容器和主机共享内核。
容器中的应用程序导致Linux内核崩溃,那么整个系统可能会崩溃。
虚拟机不与主机共享内核,虚拟机崩溃一般不会导致主机崩溃。
Docker容器与虚拟机的区别
隔离与共享:虚拟机在此基础上通过添加Hypervisor层(虚拟化中间层)虚拟硬件来构建虚拟机。每个虚拟机都有自己的系统内核。 Docker容器利用隔离的方式隔离文件系统、进程、设备、网络等资源,进而控制权限、CPU资源等,使容器之间互不影响。容器和主机共享内核、文件系统和硬件等资源。
性能与消耗 与虚拟机相比,容器消耗的资源更少。在同一主机下,可以创建比虚拟机更多的容器。虚拟机的安全性比容器稍好一些。要从虚拟机侵入主机或其他虚拟机,需要先突破Hypervisor层,这是极其困难的。 Docker容器与主机共享内核、文件系统等资源,更容易对其他容器和主机产生影响。
差异 Docker容器 出去 启动速度快,慢几秒,几分钟
译运行性能接近本机(直接在内核中运行)并且在Hypervisor上运行大约50%。磁盘使用情况 小,甚至几十 KB,甚至几十 KB(取决于图像层) 级 系统级隔离进程级(更彻底)
操作系统主要支持linux几乎所有 打包程度仅打包项目代码和依赖项,共享主机内核的完整操作系统,与主机隔离。Docker 的安全问题
1。 Docker自身的漏洞和代码缺陷。
2。 Docker源码问题 Docker提供了Docker hub,允许用户上传创建的镜像供其他用户下载并快速搭建环境。但它也带来了一些安全问题。例如以下三种方法:
(1) 黑客上传恶意图片。如果黑客在生成的镜像中植入木马、后门等恶意软件,那么环境从一开始就不安全,以后就更没有安全可言了。
(2) 该镜像使用了易受攻击的软件。 DockerHub上可下载的镜像中,75%的镜像安装了易受攻击的软件。因此,下载镜像后,需要检查里面软件的版本信息,看看对应版本是否存在漏洞,并及时更新、打补丁。
(3) 中间人攻击篡改图像。图像在传输过程中可能会被篡改。目前新版本的Docker已经提供了相应的验证机制来防止这个问题。
Docker架构缺陷和安全机制 Docker本身的架构和机制可能会带来问题。例如,在攻击场景中,黑客控制了主机上的某些容器,或者通过将容器建立在公有云上来获取对容器的访问权限。 ,然后对主机或其他容器发起攻击。
1。容器间的局域网攻击 主机上的容器可以组成一个局域网,可以利用ARP欺骗、端口扫描、广播风暴等方式对局域网进行攻击。
解决方案:需要正确配置网络安全,例如设置iptables规则。
2。 DDoS 攻击耗尽资源。 DoS(DenialofService)攻击,DDos的前身,意思是拒绝服务攻击。这种攻击行为向网站服务器发送大量需要回复的消息,消耗网络带宽或系统资源,导致网络或系统不堪重负,停止提供正常的网络服务。 DDoS分布式拒绝服务主要是利用互联网上现有机器和系统的漏洞,捕获大量互联网主机,使之成为攻击者的代理人。当受控机器数量达到一定数量时,攻击者通过发送指令控制这些攻击机器,同时对目标主机或网络发起DoS攻击,消耗大量其网络带宽和系统资源,导致网络或系统瘫痪。坍塌。或者停止提供正常的网络服务。
解决方案:Cgroups的安全机制就是为了防止此类攻击。不要为单个容器分配太多资源,以避免此类问题。
3。存在漏洞的系统调用 Docker 与虚拟机的一个重要区别在于,Docker 与主机共享相同的操作系统内核。一旦主机内核存在允许权限越权或升级的漏洞,即使以普通用户执行Docker,当容器被攻破时,攻击者也可以利用内核漏洞跳转到主机执行更多操作事物。
4。共享root用户权限如果以root用户权限运行容器(docker run --privileged),容器中的root用户也将拥有主机的root权限。
Docker 安全基线标准
内核级别
(1)及时更新内核。
(2)User NameSpace(容器内的root权限在容器外处于非高权限状态)。
(3)Cgroups(资源配额和度量),通过设置CPU、内存、磁盘IO等资源限制,可以有效避免DDos攻击。
(4) 通过启用 SELinux/AppArmor/GRSEC(控制文件访问权限)来适当强化系统,增加额外的安全性。
(5)能力(权限划分),例如给容器分配指定的CPU。
(6)Seccomp(限制系统调用),限制不必要的系统调用。
(7) 禁止与宿主机进程的命名空间共享容器的命名空间,例如宿主机网络模式。
主机级别
(1) 为容器创建独立分区,例如在分布式文件系统上。
(2) 只运行必要的服务,尽量避免在容器中运行ssh服务。
(3) 禁止将主机上的敏感目录映射到容器。使用-v创建数据卷时需要注意。
(4)审计Docker daemon进程、相关文件和目录,防止病毒或木马文件的产生。
(5) 设置适当的默认文件描述符数量。 (文件描述符:简称fd,当应用程序请求内核打开/创建文件时,内核会返回一个与打开/创建的文件对应的文件描述符。文件描述符本质上是一个非负整数,可读写文件也需要通过这个文件描述符来指定要读写的文件,文件描述符是重要的系统资源,理论上系统内存应该能打开多少个文件描述符,但实际情况是即内核会通过系统级的限制,以及用户级的限制,阻止某个应用进程消耗所有文件资源。可以使用 ulimit -n 查看)
(6) root用户权限的Docker相关文件的访问权限应为644或更低。
(7)定期检查各主机的容器列表,清理不需要的容器。
网络层面
(1) 使用 iptables 设置规则来禁止或允许容器之间的网络流量。
(2) 允许Docker修改iptables。
(3) 禁止将 Docker 绑定到其他已使用的 IP/端口或 Unix Socket。
(4) 禁止在容器上映射特权端口。
(5) 仅在容器上打开所需的端口。
(6) 容器上禁止使用主机网络模式。
(7) 如果主机有多个网卡,则将容器传入流量绑定到特定的主机网卡。
docker网络创建--subnet=172.16.10.0/24--opt
“www.sychzs.cn”=“docker1”mynetwork
docker run -itd --net mynetwork --ip 172.16.10.100 centos:7 /bin/bash
iptables -t nat -A POSTROUTING -s 172.16.10.100 -o ens36 -j SNAT --to-source 192.168.100.10
镜像水平
(1) 创建本地私有镜像仓库服务器。
(2) 图中的软件为最新版本。建议根据实际情况使用对应的版本。业务稳定优先。
(3) 使用受信任的图像文件并通过安全渠道下载。
(4) 重建镜像而不是给容器和镜像打补丁,销毁异常容器并重建。
(5)合理管理图片标签,及时删除不再使用的图片。
(6) 使用镜像扫描。
(7) 使用镜像签名。
集装箱液位
(1) 容器最小化,最小的操作系统镜像集。
(2) 容器作为单个主进程运行。
(3) 禁用 --privileged 标志以使用特权容器。
(4) 容器上禁止运行ssh服务。尝试使用 docker exec 进入容器。
(5)以只读方式挂载容器的根目录系统,-v 主机目录:容器目录:ro。
(6) 明确定义属于容器的数据盘符。
(7) 通过设置 on-failure 来限制容器尝试重新启动的次数。容器反复重启容易导致数据丢失,--restart=on-failure:3。
(8)限制容器中可用的进程数量,docker run -m 限制内存使用,防止fork炸弹。 (fork炸弹,子进程快速增长,耗尽系统进程数)
其他设置
(1)定期对主机系统和容器进行安全审计。
(2) 使用最少的资源和最少的权限运行容器。这就是Docker容器安全的核心思想。
(3) 避免在同一主机上部署大量容器并保持可管理的数量。
(4)监控Docker容器(如zabbix)的使用情况、性能等指标。
(5)添加实时威胁检测和事件报警响应功能,如zabbix。
(6) 使用中央和远程日志收集服务,例如ELK。
容器相关的常见安全配置方法
容器最小化如果容器中只运行必要的服务,则无法轻易打开SSH等服务来连接容器。
进入容器的正确方式:docker exec -it a661258f6bfe bash
Docker远程API访问控制 Docker的远程调用API接口存在未授权访问漏洞,至少应该限制外部网络访问。推荐使用Socket方式访问。
(1)在docker服务配置文件中指定监听内网ip
vim /usr/lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://192.168.100.10:2375
(2)重启Docker
systemctl 守护进程重新加载
systemctl 重启docker
netstat -natp |
netstat -natp | grep 2375
(3) 对主机的firewalld进行IP访问控制。源地址指定客户端地址
firewall-cmd --permanent --add-rich-rule="规则系列="ipv4"源地址="192.168.100.20"
端口协议=“tcp”端口=“2375”接受”
firewall-cmd --reload 或 iptables -t filter -A INPUT -s 192.168.100.20 -p tcp --dport 2375 -j ACCEPT
(4)在客户端实现远程授权访问
docker -H tcp://192.168.100.10 镜像
限制交通流量
使用防火墙过滤器来限制 Docker 容器的源 IP 地址范围与外界通信。
firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" 源
地址=“192.168.80.0/24”拒绝“
iptables -t 过滤器 -A 输入 -s 192.168.80.0/24 -j 拒绝
生产环境中的大量问题都是由于暴露Docker容器端口导致的漏洞造成的。除了操作系统账户权限控制的问题外,Docker Daemon的进程管理也存在隐患。
目前常用的Docker版本都支持Docker Daemon来管理主机iptables。
一旦使用-p host_port:guest_port的端口映射启动进程,Docker Daemon将直接添加相应的FORWARD Chain和-j ACCEPT。
默认的DROP规则是在INPUT链上制定的,无法对docker进行限制,存在严重的安全隐患。
建议:
(1) 不要在有外网IP的机器上使用Docker服务。
(2) 使用k8s等docker编排系统来管理Docker容器。
(3) 在主机上的Docker daemon启动命令中添加--iptables=false,然后将常用的iptables规则写入文件中,然后使用iptables-restore重定向输入刷新规则。
镜像安全 一般情况下,为了保证镜像只从可信的仓库获取,建议使用harbor私有仓库。
如果公司没有使用自己的镜像源,则需要使用Docker镜像安全扫描工具Clair对下载的镜像进行检查。
与CVE数据库同步扫描图像,验证图像的md5等特征值,确认一致性后基于图像进一步构建。
一旦发现漏洞,将通知用户处理,否则直接阻止镜像继续构建。
Docker Client 与 DockerDaemon 之间的通信安全 为了防止链路劫持、会话劫持等问题导致 Docker 通信受到中间人攻击,c/s 两端应通过 TLS 加密进行通信。
通过在服务器上创建TLS密钥证书,然后颁发给客户端,客户端通过私钥访问容器,从而保证docker通信的安全。使用证书访问的工作流程:
(1) 客户端发起HTTPS请求,连接服务器的443端口。
(2) 服务器首先要申请一套数字证书(证书内容包括公钥、证书颁发机构、有效期等)。
(3) 服务器将自己的数字证书发送给客户端(公钥在证书中,私钥由服务器持有)。
(4) 客户端收到数字证书后,首先会验证证书的有效性。如果证书验证通过,将使用伪随机数生成器(/dev/random)随机生成【对称密钥】,并使用证书的公钥对【对称密钥】进行加密。
(5) 客户端将加密后的公钥【对称密钥】发送给服务器。
(6) 服务器收到客户端发来的密文密钥后,使用之前保留的私钥进行非对称解密。解密后,获得客户端的【对称密钥】,然后使用客户端的【对称密钥】对返回的数据进行加密,使得传输的数据为密文。
(7) 服务器端将加密后的密文数据返回给客户端。
(8) 客户端收到后,使用自己的【对称密钥】对称解密,得到服务器返回的数据。
首先创建ca证书,这只是官方认证的证书。接下来,为服务器和客户端节点创建证书。
此时创建证书分为三个步骤:
(1) 设置私钥,确保安全加密
(2)使用私钥签名保证身份的真实性和不可否认性
(3)使用ca证书制作证书
证书创建过程
1.环境准备
服务器 .Master 192.168.100.10 Docker-CE2客户端192.168.100.20 Docker-CE首先创建存储目录 mkdir /tls cd /tls/
生成ca证书
(1) 创建 ca 私钥
openssl genrsa -aes256 -out ca-key.pem 4096 #输入123123
genrsa:使用RSA算法生成私钥 -aes256:使用256位密钥的AES算法对私钥进行加密,这样每次使用私钥文件时都会输入密码,即可以省略 -out:输出文件的路径,如果不指定输出文件,则为标准输出
4096:指定私钥长度,默认1024。此项必须是命令行最后一个参数
(2) 创建 ca 证书
openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -subj "/CN=*" -out ca.pem #输入 123123
req:执行证书颁发命令
-新:新的证书颁发请求
-x509:生成x509格式证书,专门在创建私有CA时使用
-天:证书的有效期,单位为天
-key:指定私钥路径
-sha256:证书摘要使用sha256算法
-subj:证书相关的用户信息(subject的缩写)
-out:输出文件的路径
用ca证书颁发服务器端证书
(3) 创建服务器私钥
openssl genrsa -out 服务器密钥.pem 4096
(4) 生成证书签名请求文件(csr文件)
openssl req -new -key server-key.pem -sha256 -subj "/CN=*" -out server.csr
(5)使用ca证书和私钥证书颁发服务器签名证书,输入123123
openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem
x509:生成x509格式证书 -req:输入csr文件 -in:要输入的csr文件 -CA:指定ca证书的路径 -CAkey:指定ca证书的私钥路径
-CAcreateserial:创建证书序列号文件。创建的序列号文件默认名称为www.sychzs.cn
使用ca证书颁发客户端证书
(6) 生成客户端私钥
openssl genrsa -out 客户端密钥.pem 4096
(7) 生成证书签名请求文件
openssl req -new -key client-key.pem -subj "/CN=client" -out client.csr
(8) 创建扩展配置文件,使密钥适合客户端认证
echo ExtendedKeyUsage=clientAuth > extfile.cnf
(9) 使用ca证书颁发客户端签名证书,输入123123
openssl x509 -req -days 1000 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -extfile extfile.cnf
删除两个证书签名请求文件和扩展配置文件
rm -rf www.sychzs.cn 客户端.csr extfile.cnf 服务器.csr
配置docker服务配置文件
vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd --tlsverify --tlscacert=/tls/ca.pem --tlscert=/tls/server-cert.pem --tlskey=/tls/server-key.pem -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock #13 行
重启docker服务
systemctl 守护进程重新加载
systemctl 重启docker
netstat -natp |
netstat -natp | grep 2376 setenforce 0
将 /tls 目录下的 ca.pem、client-cert.pem、client-key.pem 三个文件复制到另一台主机
scp ca.pem root@192.168.100.10:/etc/docker/
scp cert.pem root@192.168.100.10:/etc/docker/
scp key.pem root@192.168.100.10:/etc/docker/
修改服务器的主机名和IP映射
hostnamectl 设置主机名主机
苏
vim /etc/hosts
127.0.0.1主
本地验证,使用证书访问时使用主机名连接
docker --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H tcp://master:2376 个镜像
客户端操作
hostnamectl 设置主机名客户端
苏
vim /etc/hosts
192.168.100.10主
cd /etc/docker/
docker --tlsverify --tlscacert=ca.pem --tlscert=client-cert.pem --tlskey=client-key.pem -H tcp://master:2376 个镜像
注:由于20.10.9 docker客户端使用的go版本是go1.16.8,而go1.15及以后版本不支持私有CA生成的证书,所以这里的docker客户端仍然使用docker-ce-cli -20.10.5-3.el7.x86_64安装版本。
避免Docker容器中的信息泄露。近年来,Github 上发生了大量个人或企业账户密码泄露事件。出现此类问题时,一般会使用dockerfile或者docker-compose文件来创建容器。
如果这些文件中存在账号、密码等认证信息,一旦Docker容器对外开放,这些主机上的敏感信息也会被泄露。
可以通过以下方式检查容器创建模板的内容。
检查创建的用户
grepauthorized_keys $dockerfile
检查操作系统用户
grep“etc/group”$dockerfile
检查 sudo 用户
grep“etc/sudoers.d”$dockerfile
检查 ssh 密钥对
grep“.ssh/.*id_rsa”$dockerfile
-->