容器安全拾遗 - Rootless Container初探
近期Docker 19.03中發(fā)布了一個重要的特性 “Rootless Container支持”。趁著五一假期,快速驗證一下。本文參考了Experimenting with Rootless Docker?一文的內(nèi)容,并且補(bǔ)充了更多的細(xì)節(jié)和上手內(nèi)容。
Rootless容器背景與架構(gòu)
Docker和Kubernetes已經(jīng)成為企業(yè)IT架構(gòu)的基礎(chǔ)設(shè)施,其自身安全越來越被關(guān)注。Docker基于Linux操作系統(tǒng)提供了應(yīng)用虛擬化能力,通過namespace, cgroup實現(xiàn)了資源的隔離和配額約束。Docker Engine是一個典型的 Client-Server 結(jié)構(gòu):
Docker Client (TCP/Unix Socket) -> Docker Daemon (Parent/Child Processes) -> Container
由于Linux需要特權(quán)用戶來創(chuàng)建namespace,掛載分層文件系統(tǒng)等,所以 Docker Daemon 一直以來是以root用戶來運(yùn)行的。這也導(dǎo)致了有Docker訪問權(quán)限的用戶可以通過連接Docker Engine獲取root權(quán)限,而且可以繞開系統(tǒng)的審計能力對系統(tǒng)進(jìn)行攻擊。這阻礙了容器在某些場景的應(yīng)用:比如在高性能計算領(lǐng)域,由于傳統(tǒng)的資源管理和調(diào)度系統(tǒng)需要非特權(quán)用戶來運(yùn)行容器,社區(qū)實現(xiàn)了另外的容器運(yùn)行時Singularity 。
Moby社區(qū)的 Akihiro Suda,為Docker Engine和Buildkit貢獻(xiàn)了rootless容器支持,讓Docker Engine以非特權(quán)用戶方式運(yùn)行,更好地復(fù)用Linux的安全體系。
注意:
Rootless容器有幾個核心技術(shù)
首先是利用 user namespaces 將容器中的root用戶uid/gid映射到宿主機(jī)的非特權(quán)用戶范圍內(nèi)。Docker Engine已經(jīng)提供了?--userns-remap?標(biāo)志支持了相關(guān)能力,提升了容器的安全隔離性。Rootless容器在此之上,讓Docker daemon也運(yùn)行在重映射的用戶名空間中。
其次,雖然Linux中的非特權(quán)用戶可以在用戶名空間中創(chuàng)建網(wǎng)絡(luò)名空間,并且執(zhí)行iptables規(guī)則管理和tcpdump等操作,然而非特權(quán)用戶無法在宿主機(jī)和容器之間創(chuàng)建veth pairs, 這也意味著容器沒有外網(wǎng)訪問能力。為了解決這個問題,Akihiro 利用用戶態(tài)的網(wǎng)絡(luò)“SLiRP”,通過一個TAP設(shè)備連接到非特權(quán)用戶名空間,為容器提供外網(wǎng)連接能力。其架構(gòu)如下
相關(guān)細(xì)節(jié)請參考,slirp4netns項目
環(huán)境準(zhǔn)備
本文在一臺 CentOS 7.6的虛擬機(jī)上進(jìn)行的驗證
創(chuàng)建用戶
$ useradd moby $ passwd moby將新建用戶添加到 sudoers 組
usermod -aG wheel moby切換到非特權(quán)用戶
$ su - moby $ id uid=1000(moby) gid=1000(moby) groups=1000(moby),10(wheel)進(jìn)行uid/gid映射配置
echo "moby:100000:65536" | sudo tee /etc/subuid echo "moby:100000:65536" | sudo tee /etc/subgid安裝Rootless Docker
curl -sSL https://get.docker.com/rootless | sh如果第一次安裝,需要安裝所需軟件包
$ curl -sSL https://get.docker.com/rootless | sh # Missing system requirements. Please run following commands to # install the requirements and run this installer again. # Alternatively iptables checks can be disabled with SKIP_IPTABLES=1cat <<EOF | sudo sh -x curl -o /etc/yum.repos.d/vbatts-shadow-utils-newxidmap-epel-7.repo https://copr.fedorainfracloud.org/coprs/vbatts/shadow-utils-newxidmap/repo/epel-7/vbatts-shadow-utils-newxidmap-epel-7.repo yum install -y shadow-utils46-newxidmap cat <<EOT > /etc/sysctl.d/51-rootless.conf user.max_user_namespaces = 28633 EOT sysctl --system EOF(可選)安裝用戶態(tài)網(wǎng)絡(luò)協(xié)議棧實現(xiàn) slirp4netns :由于yum 安裝的slirp4netns版本比較老無法執(zhí)行,需要從源碼構(gòu)建。
$ sudo yum install glib2-devel $ sudo yum group install "Development Tools" $ git clone https://github.com/rootless-containers/slirp4netns $ cd slirp4netns $ ./autogen.sh $ ./configure --prefix=/usr $ make $ sudo make install安裝 Rootless Docker成功之后,會出現(xiàn)如下提示
$ curl -sSL https://get.docker.com/rootless | sh # systemd not detected, dockerd daemon needs to be started manually/home/moby/bin/dockerd-rootless.sh --experimental --storage-driver vfs# Docker binaries are installed in /home/moby/bin # Make sure the following environment variables are set (or add them to ~/.bashrc):\n export XDG_RUNTIME_DIR=/tmp/docker-1000 export DOCKER_HOST=unix:///tmp/docker-1000/docker.sock驗證Rootless容器
執(zhí)行
$ export XDG_RUNTIME_DIR=/tmp/docker-1000 $ export DOCKER_HOST=unix:///tmp/docker-1000/docker.sock $ /home/moby/bin/dockerd-rootless.sh --experimental --storage-driver vfs然后在另外一個窗口執(zhí)行
$ export XDG_RUNTIME_DIR=/tmp/docker-1000 $ export DOCKER_HOST=unix:///tmp/docker-1000/docker.sock $ docker version Client:Version: master-dockerproject-2019-04-29API version: 1.40Go version: go1.12.4Git commit: 3273c2e2Built: Mon Apr 29 23:39:39 2019OS/Arch: linux/amd64Experimental: falseServer:Engine:Version: master-dockerproject-2019-04-29API version: 1.40 (minimum version 1.12)Go version: go1.12.4Git commit: 9a2c263Built: Mon Apr 29 23:46:23 2019OS/Arch: linux/amd64Experimental: truecontainerd:Version: v1.2.6GitCommit: 894b81a4b802e4eb2a91d1ce216b8817763c29fbrunc:Version: 1.0.0-rc7+devGitCommit: 029124da7af7360afa781a0234d1b083550f797cdocker-init:Version: 0.18.0GitCommit: fec3683 $ docker run -d -p 8080:80 nginx $ curl localhost:8080利用 iperf3 進(jìn)行網(wǎng)絡(luò)性能測試,啟動服務(wù)器端
$ docker run -it --rm --name=iperf3-server -p 5201:5201 networkstatic/iperf3 -s測試容器之間的網(wǎng)絡(luò)帶寬
$ SERVER_IP=$(docker inspect --format "{{ .NetworkSettings.IPAddress }}" iperf3-server) $ echo $SERVER_IP 172.17.0.2 $ docker run -it --rm networkstatic/iperf3 -c $SERVER_IP ... - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.03 sec 29.8 GBytes 25.5 Gbits/sec 0 sender [ 4] 0.00-10.03 sec 29.8 GBytes 25.5 Gbits/sec receiver測試容器到宿主機(jī)之間的網(wǎng)絡(luò)帶寬(外網(wǎng)訪問)
$ HOST_IP=$(hostname --ip-address) $ echo $HOST_IP 192.168.1.162 $ docker run -it --rm networkstatic/iperf3 -c $HOST_IP ... - - - - - - - - - - - - - - - - - - - - - - - - - [ ID] Interval Transfer Bandwidth Retr [ 4] 0.00-10.00 sec 1011 MBytes 848 Mbits/sec 0 sender [ 4] 0.00-10.00 sec 1008 MBytes 845 Mbits/sec receiver可以看到容器之間的通信帶寬還比較不錯,然而容器和宿主機(jī)不同網(wǎng)絡(luò)名空間之間的通信性能有較大的損耗。
總結(jié)
Rootless容器在提升Docker/Runc容器的安全隔離性和可管理性方面前進(jìn)了一大步,可以很好地復(fù)用Linux的安全體系,配合seccomp和SELinux等安全配置,可以減少攻擊面。社區(qū)還提供了無需特權(quán)用戶的Kubernetes實驗版本,可以從如下項目獲得?https://github.com/rootless-containers/usernetes
然而Rootless容器無法防范Linux內(nèi)核的安全風(fēng)險,目前其網(wǎng)絡(luò)、存儲的性能也有待優(yōu)化,需要在特定場景中進(jìn)行使用。也期待社區(qū)持續(xù)提升容器安全能力與效率,讓容器有更加廣闊的應(yīng)用場景。
原文鏈接
本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。
總結(jié)
以上是生活随笔為你收集整理的容器安全拾遗 - Rootless Container初探的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 重磅公开!阿里语音识别模型端核心技术,让
- 下一篇: 对话鲁直:蚂蚁金服中间件的开源头羊 |