基于 NeuVector 发现和管理 Docker macvlan 网络安全
概述
NeuVector 是 SUSE 开源的专为 Kubernetes 等容器环境设计的零信任安全平台,Docker 环境也是原生支持 。本章主要讲解如何基于 NeuVector 的网络防护能力,自动发现和管理 Docker macvlan 网络安全。
环境
版本:
| Env | Version |
|---|---|
| Ubuntu | 22.04.5 |
| Docker | 29.3.1/29.6.0 |
| Neuvector | 5.4.9/5.6.1 |
虚拟机环境:
| 节点 | IP 地址 |
|---|---|
| u69 | 192.168.2.69 |
| u71 | 192.168.2.71 |
额外准备:
虚拟机要多一张网卡,为 Macvlan 网络提供接口。这里我的环境中两张网卡名称分别是 enp1s0 和 enp2s0
前置准备
检查 macvlan 模块是否加载:
1 | lsmod | grep macvlan |
如果没有加载,可以通过该命令加载:
1 | modprobe macvlan |
如果 enp2s0 网卡未启用,需要先启用:
1 | ip link set dev enp2s0 up |
某些环境下,需要开启网卡的混杂模式,我的是 Harvester 虚拟机,不开启也可以使用。
1 | ip link set dev eth0 promisc on |
创建 macvlan 网桥
默认情况下,macvlan 的一个内核级限制是宿主机无法通过同一个物理接口与 macvlan 容器直接通信。直接 ping 容器 IP 会失败,为了让本机和外部服务能够访问 macvlan 网络,可以在宿主机上创建一个 macvlan 虚拟接口作为“桥接”。
在 u69 节点上执行:
1 | ip link add macvlan-br link enp2s0 type macvlan mode bridge |
在 u71 节点上执行:
1 | ip link add macvlan-br link enp2s0 type macvlan mode bridge |
Docker macvlan 环境搭建
分别在 u69 和 u71 节点上,使用 Docker 命令创建 macvlan 的容器网络:
1 | docker network create --scope global --driver macvlan \ |
参数说明:
scope:默认是 local,但是这种模式无法让 NeuVector 发现跨主机网络,需要设置为 global 或者 swarm。其中 swarm 与 macvlan 兼容性不好,创建容器时无法通过--ip参数设置 IP,所以这里设置为 global。deiver:默认是 bridge,这里需要设置为 macvlan。o:设置驱动参数,这里parent设置 macvlan 设备对接的网卡名称。subnet:子网范围。gateway:网关地址。
验证网络连通性
在 u69 节点创建 macvlan 容器 m-11 和 m-12:
1 | docker run -itd \ |
参数说明:
io.neuvector.service.name:默认 Docker 环境,NeuVector 会识别镜像名称作为 Group 名称,可以通过这个 label 实现自定义 Group 名称。
确认 IP 是否生效:
1 | docker exec -it m-11 ip a |
在 u71 节点创建 macvlan 容器 m-21 和 m-22:
1 | docker run -itd \ |
确认 IP 是否生效:
1 | docker exec -it m-21 ip a |
在 u69 上测试是否与 u71 的 macvlan 容器网络连通:
1 | docker exec -it m-11 ping 192.168.3.21 |
生成 NeuVector Internal 证书
从 5.4.2 版本开始,这些内置的证书不会自动生成,需要手动生成。
- 创建证书目录
1 | cd && mkdir -p neuvector/cert && cd neuvector/cert |
- 创建一个
ca.cfg文件
1 | [req] |
- 生成
ca.crt,tls.key,tls.crt
1 | openssl genrsa -out ca.key 2048 |
搭建 NeuVector 容器安全平台
这里以单点架构为例,生产环境建议使用高可用架构。
在 Docker 环境中,controller 和 enforcer 不支持部署在一个节点上,NeuVector 提供了 allinone 镜像来提供一体化部署。
首先在 u69 节点上部署 NeuVector 的 allinone 容器:
1 | docker run -d --name allinone \ |
部分参数说明:
CLUSTER_JOIN_ADDR:Controller IP 地址,如果有多个需要都写进去,用,隔开。NV_PLATFORM_INFO: 设置本地识别 Docker 环境。CONTAINER_NET_TYPE:识别 macvlan 网络设备。
u71 节点部署 enforcer 容器:
1 | docker run -d --name enforcer \ |
浏览器访问 https://192.168.2.69:8443 ,初始账号密码是 admin/admin。
容器发现和网络学习
查看 Policy - Groups,可以看到已经自动识别到容器。
在容器里,例如从 m-11 分别去访问 m-12 m-21 m-22:
1 | docker exec -it m-11 curl 192.168.3.12 -o /dev/null -s -v | grep HTTP |
进入 UI 查看是否学习到网络规则:
自此已验证容器发现和网络规则学习都正常运行。
已知问题
根据 SetIPAddrScope 和 connectToLocal 两部分代码的逻辑,如果 docker network 的 scope 是 local,则会将 IP 映射到 CLUSIPAddrScopeLocalhost,从而容器只能学习到同一个宿主机的其他容器的网络规则,无法学习到跨主机网络规则,需要将 scope 设置为 global 实现跨主机网络规则的学习。
Docker 环境下默认通过镜像名称自动识别为 Group 名称,如果启动的容器无法正确识别,需要通过
io.neuvector.service.namelabel 设置 Group 名称。如果发现无法创建 global scope 的 macvlan 网络,可以检查一下 Docker 版本是不是太低了,实测发现 Docker 20.10.24 版本无法创建 global scope 的 macvlan 网络,提示需要 swarm 环境。我验证的环境的 Docker 版本是 29.xx 版本,可以直接创建 global scope 的 macvlan 网络。
根据官方文档说明,从 v5.5.0 版本开始,Allinone 支持已被弃用。后面新版本可能需要采用 controller + enforcer 方式部署,或者考虑后续迁移至 Kubernetes 环境。