隔離的本質(zhì)區(qū)別:跨平臺隔離方案與實(shí)操指南)
1. 沙箱到底隔離了什么沒隔離什么先把一個(gè)容易混淆的概念掰開沙箱和主機(jī)隔離壓根不是同一個(gè)層面的東西。沙箱解決的是“這段代碼跑起來別把我主進(jìn)程搞崩、別亂讀我的環(huán)境變量、別偷偷往外發(fā)請求”它是一層運(yùn)行時(shí)的約束。而跨平臺主機(jī)隔離解決的是“這臺機(jī)器上的東西跟那臺機(jī)器上的東西在網(wǎng)絡(luò)、文件系統(tǒng)、進(jìn)程空間上到底能不能互相看見、互相影響”。我見過太多團(tuán)隊(duì)在 Linux 上裝了個(gè) Docker跑了個(gè)容器就對外說“我們做了沙箱隔離”。結(jié)果一問容器網(wǎng)絡(luò)是不是 host 模式掛載卷是不是把宿主機(jī)根目錄映射進(jìn)去了容器里是不是還留著宿主機(jī)的 SSH 密鑰三個(gè)問題下來全中。這就是典型的“開了沙箱但主機(jī)隔離根本沒做”。沙箱的本質(zhì)是限制行為主機(jī)隔離的本質(zhì)是切斷通道。你可以在一個(gè)完全沒做主機(jī)隔離的環(huán)境里開一個(gè)很嚴(yán)格的沙箱代碼確實(shí)跑不出這個(gè)進(jìn)程但它照樣能通過共享的網(wǎng)絡(luò)命名空間掃到內(nèi)網(wǎng)其他機(jī)器。反過來你也可以做了很強(qiáng)的主機(jī)隔離但沙箱策略很松代碼在里面把磁盤寫滿。這兩件事必須分開評估不能互相替代。注意判斷一個(gè)環(huán)境是否真正隔離不要看它“用了什么技術(shù)”要看它“還能訪問到什么”。能 ping 通宿主機(jī)、能讀到宿主機(jī)掛載目錄、能復(fù)用宿主機(jī)的網(wǎng)絡(luò)棧那隔離就是沒做完。1.1 沙箱的三種常見形態(tài)與各自的隔離邊界市面上說的沙箱大致分三類每類的隔離邊界完全不同。第一類是語言級沙箱比如 Java 的 SecurityManager現(xiàn)在基本廢棄了、Node.js 的 vm 模塊、Python 的 RestrictedPython。這類沙箱跑在同一個(gè)進(jìn)程里共享同一個(gè)文件系統(tǒng)和網(wǎng)絡(luò)棧。它的隔離能力最弱只能防一些“手滑”級別的誤操作防不住任何有意的越權(quán)。你在這種沙箱里讀/etc/passwd只要權(quán)限夠照樣讀得到。第二類是進(jìn)程級沙箱比如 Linux 的 seccomp、AppArmor、SELinux或者 macOS 的 sandbox-exec。這類沙箱通過系統(tǒng)調(diào)用過濾和強(qiáng)制訪問控制限制進(jìn)程能做什么。它比語言級強(qiáng)很多但依然共享內(nèi)核和網(wǎng)絡(luò)命名空間。一個(gè)被 seccomp 限制的進(jìn)程如果允許socket調(diào)用它照樣能連外網(wǎng)。第三類是系統(tǒng)級沙箱也就是容器Docker、containerd和虛擬機(jī)KVM、VirtualBox。容器通過 namespace 和 cgroup 做隔離虛擬機(jī)通過硬件虛擬化做隔離。這兩類的隔離強(qiáng)度差異也很大容器共享宿主內(nèi)核虛擬機(jī)不共享。所以容器逃逸漏洞年年有虛擬機(jī)逃逸漏洞相對少得多。沙箱類型隔離邊界能否防住有意越權(quán)典型代表語言級進(jìn)程內(nèi)基本不能Node vm、RestrictedPython進(jìn)程級系統(tǒng)調(diào)用層部分能seccomp、SELinux容器級命名空間層大部分能Docker、containerd虛擬機(jī)級硬件層能KVM、VirtualBox這張表的關(guān)鍵結(jié)論是你開的沙箱屬于哪一類決定了它的隔離上限。如果你只開了語言級沙箱卻以為自己在做主機(jī)隔離那后面的所有安全假設(shè)都是空中樓閣。1.2 跨平臺主機(jī)隔離的真正含義跨平臺主機(jī)隔離重點(diǎn)在“跨平臺”和“主機(jī)”兩個(gè)詞??缙脚_意味著你的方案要在 Linux、Windows、macOS 上都能落地而不是只在 Linux 上跑通就完事。主機(jī)意味著隔離的對象是整臺機(jī)器包括它的網(wǎng)絡(luò)、存儲、外設(shè)、進(jìn)程空間。在 Linux 上主機(jī)隔離主要靠 namespace網(wǎng)絡(luò)、掛載、PID、IPC、UTS、用戶加 cgroup 加 seccomp 組合實(shí)現(xiàn)。Docker 默認(rèn)幫你做了大部分但默認(rèn)配置里有幾個(gè)坑默認(rèn)網(wǎng)絡(luò)是 bridge容器能通過 NAT 訪問外網(wǎng)默認(rèn)掛載了/etc/hosts、/etc/resolv.conf默認(rèn)以 root 運(yùn)行。這些默認(rèn)值在開發(fā)環(huán)境無所謂在生產(chǎn)隔離環(huán)境里全是漏洞。在 Windows 上主機(jī)隔離靠的是 Job Object、AppContainer、Windows Sandbox、Hyper-V 容器。Windows 的容器分兩種Process Isolation 和 Hyper-V Isolation。前者共享宿主內(nèi)核后者每個(gè)容器一個(gè)輕量虛擬機(jī)。很多團(tuán)隊(duì)在 Windows 上直接用 Process Isolation然后發(fā)現(xiàn)容器里的進(jìn)程能看到宿主機(jī)的注冊表和部分系統(tǒng)目錄這就是沒做干凈。在 macOS 上主機(jī)隔離最麻煩。macOS 沒有 Linux 那樣的 namespace也沒有 Windows 那樣的 Job Object。它靠的是 sandbox-exec 的 profile 文件加 Seatbelt 機(jī)制。Docker Desktop for Mac 實(shí)際上是跑在一個(gè) Linux 虛擬機(jī)里的所以你在 macOS 上用的容器隔離本質(zhì)是虛擬機(jī)里的容器隔離多了一層。這層虛擬機(jī)如果配置不當(dāng)比如共享了宿主機(jī)目錄、開了端口轉(zhuǎn)發(fā)隔離就被削弱了。提示跨平臺隔離方案的設(shè)計(jì)原則是“取交集”也就是找到三個(gè)平臺都能實(shí)現(xiàn)的隔離能力而不是在某個(gè)平臺上堆最強(qiáng)配置。否則你的方案在另外兩個(gè)平臺上會直接失效。2. 為什么“已經(jīng)開了沙箱”會給人虛假的安全感這個(gè)問題的核心在于沙箱的默認(rèn)配置和隔離的默認(rèn)配置方向是相反的。沙箱的默認(rèn)配置傾向于“能用”隔離的默認(rèn)配置傾向于“不能用”。你裝完 Docker默認(rèn)網(wǎng)絡(luò)是通的默認(rèn)掛載是有的默認(rèn)用戶是 root。這些默認(rèn)值是為了讓你快速跑起來不是為了讓你安全隔離。我踩過最典型的一個(gè)坑在某次內(nèi)部演練里我們在 Linux 上跑了一個(gè) Docker 容器容器里跑一段不可信代碼。代碼里寫了一句curl http://169.254.169.254/latest/meta-data/直接拿到了云主機(jī)的臨時(shí)憑證。為什么因?yàn)槿萜骶W(wǎng)絡(luò)是 bridge 模式能訪問到宿主機(jī)的元數(shù)據(jù)服務(wù)而元數(shù)據(jù)服務(wù)沒有做任何訪問控制。沙箱確實(shí)開了代碼確實(shí)被限制在容器里了但主機(jī)隔離沒做憑證照樣泄露。2.1 默認(rèn)配置里的五個(gè)隔離缺口第一個(gè)缺口是網(wǎng)絡(luò)命名空間共享。Docker 的--network host會讓容器直接用宿主機(jī)的網(wǎng)絡(luò)棧容器里的進(jìn)程能監(jiān)聽宿主機(jī)端口也能訪問宿主機(jī)能訪問的一切。即使不用 host 模式默認(rèn)的 bridge 模式也會通過 NAT 讓容器訪問外網(wǎng)同時(shí)容器之間默認(rèn)可以互相通信。第二個(gè)缺口是掛載卷過度暴露。很多人為了圖方便直接-v /:/host把宿主機(jī)根目錄掛進(jìn)去。這一掛容器里的進(jìn)程就能讀寫宿主機(jī)的任何文件包括 SSH 密鑰、配置文件、數(shù)據(jù)庫文件。沙箱再嚴(yán)也擋不住文件系統(tǒng)層面的直接訪問。第三個(gè)缺口是用戶權(quán)限過高。Docker 默認(rèn)以 root 運(yùn)行容器內(nèi)進(jìn)程。如果容器逃逸成功攻擊者直接拿到宿主機(jī) root。即使沒逃逸容器內(nèi) root 也能通過掛載的 docker socket 控制宿主機(jī) Docker等于間接拿到宿主機(jī) root。第四個(gè)缺口是能力集過大。Linux 的 capability 機(jī)制把 root 權(quán)限拆成了幾十個(gè)細(xì)粒度能力。Docker 默認(rèn)給容器保留了CAP_CHOWN、CAP_NET_RAW、CAP_SYS_CHROOT等十幾個(gè)能力。其中CAP_NET_RAW允許容器內(nèi)進(jìn)程構(gòu)造原始數(shù)據(jù)包可以做 ARP 欺騙、DNS 欺騙。CAP_SYS_CHROOT允許改變根目錄可能被用于逃逸。第五個(gè)缺口是內(nèi)核共享。容器共享宿主內(nèi)核內(nèi)核漏洞就是容器逃逸漏洞。CVE-2019-5736runc 逃逸、CVE-2022-0492cgroup 逃逸都是這類。你沒法在容器層面修復(fù)內(nèi)核漏洞只能靠升級宿主內(nèi)核。這也是為什么高安全場景更傾向虛擬機(jī)隔離。2.2 沙箱策略與隔離策略的沖突點(diǎn)沙箱策略通常關(guān)注“代碼能做什么”比如能不能讀文件、能不能發(fā)網(wǎng)絡(luò)請求、能不能創(chuàng)建子進(jìn)程。隔離策略關(guān)注“環(huán)境能看見什么”比如能不能看見宿主機(jī)網(wǎng)絡(luò)、能不能看見其他容器、能不能看見宿主機(jī)文件系統(tǒng)。這兩套策略在實(shí)現(xiàn)上經(jīng)常打架。舉個(gè)例子你為了讓沙箱里的代碼能正常跑給它開了文件讀寫權(quán)限。但隔離策略要求文件系統(tǒng)只讀。結(jié)果就是沙箱策略覆蓋了隔離策略代碼能寫文件了隔離目標(biāo)沒達(dá)成。反過來你為了隔離把網(wǎng)絡(luò)完全切斷。但沙箱里的代碼需要下載依賴跑不起來。于是你又把網(wǎng)絡(luò)打開隔離目標(biāo)又沒達(dá)成。解決這個(gè)沖突的辦法是分層設(shè)計(jì)隔離層負(fù)責(zé)切斷通道沙箱層負(fù)責(zé)限制行為。隔離層先做把不該看見的東西全部藏起來。沙箱層后做在可見范圍內(nèi)限制行為。兩層獨(dú)立配置互不覆蓋。注意不要試圖用一套配置同時(shí)滿足沙箱和隔離兩個(gè)目標(biāo)。它們的默認(rèn)方向相反混在一起配最后一定是某一方妥協(xié)。3. Linux 上的主機(jī)隔離實(shí)操從默認(rèn) Docker 到真正隔離Linux 是三個(gè)平臺里隔離能力最完整的也是坑最多的。下面這套配置是我在實(shí)際項(xiàng)目里反復(fù)調(diào)整后沉淀下來的可以直接抄。3.1 網(wǎng)絡(luò)隔離從 bridge 到 none 加按需放行默認(rèn)的 bridge 網(wǎng)絡(luò)讓容器能訪問外網(wǎng)也能被外網(wǎng)訪問。真正的隔離環(huán)境應(yīng)該用none網(wǎng)絡(luò)然后按需放行。# 創(chuàng)建無網(wǎng)絡(luò)容器 docker run --network none -d --name isolated_env my_image # 如果需要訪問特定服務(wù)用自定義網(wǎng)絡(luò)加防火墻規(guī)則 docker network create --internal isolated_net docker run --network isolated_net -d --name isolated_env my_image--internal參數(shù)創(chuàng)建的網(wǎng)橋不允許外部路由容器之間可以通信但出不了這個(gè)網(wǎng)橋。如果容器需要訪問某個(gè)特定外部服務(wù)用 iptables 在宿主機(jī)上做精確放行而不是直接給容器開外網(wǎng)。# 只允許容器訪問 10.0.0.5 的 443 端口 iptables -I FORWARD -s 172.18.0.0/16 -d 10.0.0.5 -p tcp --dport 443 -j ACCEPT iptables -I FORWARD -s 172.18.0.0/16 -j DROP這套配置的邏輯是默認(rèn)拒絕所有出站只放行明確需要的目標(biāo)。比默認(rèn)允許所有出站安全得多。3.2 文件系統(tǒng)隔離只讀根加臨時(shí)可寫層容器根文件系統(tǒng)應(yīng)該只讀需要寫入的目錄用 tmpfs 掛載。docker run \ --read-only \ --tmpfs /tmp:rw,noexec,nosuid,size64m \ --tmpfs /run:rw,noexec,nosuid,size16m \ --mount typebind,src/data/input,dst/input,readonly \ -d --name isolated_env my_image--read-only讓根文件系統(tǒng)只讀--tmpfs給臨時(shí)目錄分配內(nèi)存文件系統(tǒng)noexec禁止執(zhí)行其中的二進(jìn)制nosuid忽略 setuid 位。/data/input以只讀方式掛載容器只能讀不能寫。這套配置的關(guān)鍵是最小掛載原則只掛載容器真正需要的目錄且盡量只讀。不要掛載宿主機(jī)根目錄、不要掛載 docker socket、不要掛載 SSH 目錄。3.3 權(quán)限隔離非 root 用戶加能力裁剪容器內(nèi)進(jìn)程不應(yīng)該以 root 運(yùn)行也不應(yīng)該保留多余能力。docker run \ --user 1000:1000 \ --cap-drop ALL \ --cap-add NET_BIND_SERVICE \ --security-opt no-new-privileges \ -d --name isolated_env my_image--user 1000:1000以普通用戶運(yùn)行--cap-drop ALL丟棄所有能力--cap-add NET_BIND_SERVICE只加回綁定低端口的能力如果確實(shí)需要no-new-privileges禁止通過 setuid 提權(quán)。如果容器內(nèi)進(jìn)程需要寫文件提前在鏡像里把對應(yīng)目錄的屬主改成 1000:1000。不要用--privileged這個(gè)參數(shù)等于把容器變成宿主機(jī) root隔離完全失效。3.4 內(nèi)核隔離seccomp 加 AppArmor 雙保險(xiǎn)Docker 默認(rèn)的 seccomp profile 已經(jīng)屏蔽了 44 個(gè)危險(xiǎn)系統(tǒng)調(diào)用但還不夠??梢宰远x profile 進(jìn)一步收緊。{ defaultAction: SCMP_ACT_ERRNO, architectures: [SCMP_ARCH_X86_64], syscalls: [ { names: [read, write, open, close, stat, fstat, mmap, mprotect, munmap, brk, exit, exit_group], action: SCMP_ACT_ALLOW } ] }這個(gè) profile 只允許最基本的文件讀寫和內(nèi)存管理調(diào)用其他全部返回錯(cuò)誤。實(shí)際使用時(shí)需要根據(jù)程序行為逐步放行否則程序跑不起來。建議先用SCMP_ACT_LOG模式記錄程序?qū)嶋H用到的系統(tǒng)調(diào)用再根據(jù)日志生成白名單。AppArmor 則從另一個(gè)維度限制文件訪問和網(wǎng)絡(luò)訪問。Docker 默認(rèn)的docker-defaultprofile 已經(jīng)不錯(cuò)可以在此基礎(chǔ)上收緊。docker run --security-opt apparmordocker-default -d --name isolated_env my_image提示seccomp 和 AppArmor 是互補(bǔ)的不是二選一。seccomp 管系統(tǒng)調(diào)用AppArmor 管文件路徑和網(wǎng)絡(luò)地址。兩個(gè)都開隔離強(qiáng)度才夠。4. Windows 和 macOS 上的隔離差異與適配方案Linux 那套 namespace 加 cgroup 的方案在 Windows 和 macOS 上不能直接照搬。這兩個(gè)平臺的隔離機(jī)制完全不同需要單獨(dú)設(shè)計(jì)。4.1 WindowsProcess Isolation 與 Hyper-V Isolation 的選擇Windows 容器有兩種隔離模式。Process Isolation 共享宿主內(nèi)核啟動快、開銷小但隔離弱。Hyper-V Isolation 每個(gè)容器跑在一個(gè)輕量虛擬機(jī)里隔離強(qiáng)但啟動慢、開銷大。# 創(chuàng)建 Hyper-V 隔離的容器 docker run --isolationhyperv -d --name isolated_env my_image # 創(chuàng)建 Process 隔離的容器 docker run --isolationprocess -d --name isolated_env my_image如果安全要求高選 Hyper-V Isolation。如果只是開發(fā)測試Process Isolation 夠用。但要注意Process Isolation 下容器能看到宿主機(jī)的注冊表和部分系統(tǒng)目錄不能用于運(yùn)行不可信代碼。Windows 上還有一個(gè)容易被忽略的點(diǎn)Windows Sandbox。這是 Windows 10/11 專業(yè)版自帶的功能基于 Hyper-V啟動一個(gè)臨時(shí)桌面環(huán)境關(guān)閉后所有內(nèi)容銷毀。適合做一次性測試不適合做長期隔離環(huán)境。# 啟用 Windows Sandbox Enable-WindowsOptionalFeature -FeatureName Containers-DisposableClientVM -All -Online啟用后在開始菜單搜“Windows Sandbox”就能打開。它的隔離強(qiáng)度比 Process Isolation 容器高但比獨(dú)立虛擬機(jī)低。適合跑一些來源不明的安裝包或腳本。4.2 macOSsandbox-exec 加虛擬機(jī)雙層隔離macOS 沒有 Linux 的 namespace也沒有 Windows 的 Job Object。它的原生隔離靠 sandbox-exec 加 Seatbelt profile。# 用 sandbox-exec 運(yùn)行一個(gè)受限進(jìn)程 sandbox-exec -p (version 1)(deny default)(allow file-read* (subpath /usr/lib))(allow process-exec (subpath /bin)) /bin/ls這個(gè) profile 默認(rèn)拒絕所有操作只允許讀/usr/lib和執(zhí)行/bin下的程序。實(shí)際使用時(shí)需要根據(jù)程序行為逐步放行。sandbox-exec 的 profile 語法比較晦澀建議從系統(tǒng)自帶的 profile 文件改起位置在/System/Library/Sandbox/Profiles/。但 sandbox-exec 只能限制單個(gè)進(jìn)程不能做主機(jī)級隔離。macOS 上真正的主機(jī)隔離要靠虛擬機(jī)。Docker Desktop for Mac 實(shí)際上就是跑了一個(gè) Linux 虛擬機(jī)容器跑在虛擬機(jī)里。這層虛擬機(jī)如果配置不當(dāng)隔離會被削弱。# 檢查 Docker Desktop 的虛擬機(jī)配置 docker context ls docker info | grep -i operating system如果輸出顯示Operating System: Docker Desktop說明容器跑在虛擬機(jī)里。如果顯示Operating System: 你的 macOS 版本說明用了某種共享內(nèi)核的方案隔離強(qiáng)度會低很多。macOS 上還有一個(gè)選擇是 UTM 或 Parallels 跑獨(dú)立虛擬機(jī)隔離強(qiáng)度最高但資源開銷也最大。適合對隔離要求極高的場景。4.3 三平臺隔離能力對照與統(tǒng)一方案設(shè)計(jì)隔離維度LinuxWindowsmacOS網(wǎng)絡(luò)隔離network namespaceHyper-V vSwitch虛擬機(jī)網(wǎng)絡(luò)文件隔離mount namespace容器文件系統(tǒng)虛擬機(jī)磁盤進(jìn)程隔離PID namespaceJob Object虛擬機(jī)邊界權(quán)限隔離capabilityAppContainersandbox-exec內(nèi)核隔離共享宿主內(nèi)核Hyper-V 不共享虛擬機(jī)不共享從這張表可以看出Linux 的隔離能力最細(xì)粒度Windows 和 macOS 更依賴虛擬機(jī)做粗粒度隔離。統(tǒng)一方案的設(shè)計(jì)思路是在 Linux 上用容器加 namespace 做細(xì)粒度隔離在 Windows 和 macOS 上用虛擬機(jī)做粗粒度隔離上層用同一套編排接口管理。具體做法是Linux 上跑 Docker 加自定義 seccomp/AppArmor profileWindows 上跑 Hyper-V Isolation 容器macOS 上跑 Docker Desktop 加獨(dú)立虛擬機(jī)。三套環(huán)境通過同一個(gè) CI/CD 流水線管理但隔離配置各自獨(dú)立。注意不要試圖在三平臺上用完全相同的隔離配置。Linux 的 namespace 參數(shù)在 Windows 和 macOS 上不存在強(qiáng)行統(tǒng)一只會導(dǎo)致某一平臺隔離失效。5. 常見問題與排查技巧實(shí)錄這一節(jié)整理的是我在實(shí)際項(xiàng)目里踩過的坑和對應(yīng)的排查方法。每個(gè)問題都附了排查命令和解決思路可以直接對照使用。5.1 容器里還能 ping 通宿主機(jī)怎么排查這是最常見的隔離缺口。排查步驟# 進(jìn)入容器 docker exec -it isolated_env sh # 查看網(wǎng)絡(luò)接口 ip addr show # 查看路由表 ip route show # 嘗試 ping 宿主機(jī)網(wǎng)關(guān) ping -c 1 172.17.0.1如果容器里有eth0且路由表有默認(rèn)網(wǎng)關(guān)說明網(wǎng)絡(luò)沒隔離干凈。解決方法是改用--network none或--network internal或者在宿主機(jī) iptables 里加 DROP 規(guī)則。5.2 容器里能讀到宿主機(jī)的環(huán)境變量Docker 默認(rèn)不會把宿主機(jī)環(huán)境變量傳進(jìn)容器但如果你用了--env-file或-e傳了敏感變量容器里就能讀到。排查docker exec -it isolated_env env | grep -i key\|token\|secret\|password如果輸出里有敏感信息說明環(huán)境變量傳多了。解決方法是只傳必要的非敏感變量敏感信息用 secret 管理工具注入。5.3 容器逃逸的早期信號容器逃逸通常有幾個(gè)早期信號容器內(nèi)出現(xiàn)異常的系統(tǒng)調(diào)用、容器內(nèi)進(jìn)程試圖訪問/proc/sys或/sys下的敏感文件、容器內(nèi)出現(xiàn)未知的 setuid 程序。排查# 查看容器內(nèi)進(jìn)程 docker exec -it isolated_env ps aux # 查看容器內(nèi) setuid 程序 docker exec -it isolated_env find / -perm -4000 -type f 2/dev/null # 查看容器內(nèi)異常文件 docker exec -it isolated_env ls -la /proc/sys/如果發(fā)現(xiàn)異常立即停止容器并檢查宿主機(jī)的審計(jì)日志。5.4 常見問題速查表問題現(xiàn)象可能原因排查命令解決方法容器能訪問外網(wǎng)網(wǎng)絡(luò)未隔離ip route改用 none 網(wǎng)絡(luò)容器能讀宿主機(jī)文件掛載過度mount減少掛載點(diǎn)容器內(nèi)是 root用戶未指定whoami加 --user容器有額外能力能力未裁剪capsh --print加 --cap-drop ALL容器能提權(quán)setuid 未禁find / -perm -4000加 no-new-privileges容器共享宿主內(nèi)核隔離模式不對uname -a改用虛擬機(jī)隔離這張表里的每一行都是實(shí)際踩過的坑。特別是最后一行容器共享宿主內(nèi)核是架構(gòu)層面的限制沒法通過配置解決只能換隔離方案。5.5 隔離效果驗(yàn)證的自動化腳本手動排查效率低建議寫一個(gè)自動化驗(yàn)證腳本每次部署后跑一遍。#!/bin/bash # isolation_check.sh CONTAINER$1 FAIL0 # 檢查網(wǎng)絡(luò)隔離 if docker exec $CONTAINER ping -c 1 -W 1 8.8.8.8 /dev/null 21; then echo FAIL: 容器能訪問外網(wǎng) FAIL1 fi # 檢查用戶權(quán)限 USER$(docker exec $CONTAINER whoami) if [ $USER root ]; then echo FAIL: 容器內(nèi)以 root 運(yùn)行 FAIL1 fi # 檢查能力集 CAPS$(docker exec $CONTAINER capsh --print 2/dev/null | grep Current: | wc -l) if [ $CAPS -gt 0 ]; then echo WARN: 容器保留了能力集 fi # 檢查掛載點(diǎn) MOUNTS$(docker exec $CONTAINER mount | grep -c host) if [ $MOUNTS -gt 0 ]; then echo FAIL: 容器掛載了宿主機(jī)目錄 FAIL1 fi if [ $FAIL -eq 0 ]; then echo PASS: 隔離檢查通過 else echo 隔離檢查未通過請修復(fù)上述問題 fi這個(gè)腳本覆蓋了網(wǎng)絡(luò)、用戶、能力、掛載四個(gè)維度每次部署后跑一遍能擋住大部分低級配置錯(cuò)誤。6. 隔離方案選型的決策框架最后聊一下選型。隔離方案沒有銀彈不同場景需要不同強(qiáng)度的隔離。我一般用三個(gè)維度來決策威脅模型、性能預(yù)算、運(yùn)維成本。威脅模型決定隔離強(qiáng)度。如果只是防手滑語言級沙箱夠用。如果要跑不可信代碼至少容器級加嚴(yán)格配置。如果要跑惡意代碼必須虛擬機(jī)級。性能預(yù)算決定隔離開銷。容器啟動毫秒級虛擬機(jī)啟動秒級。如果業(yè)務(wù)對延遲敏感容器優(yōu)先。運(yùn)維成本決定方案復(fù)雜度。虛擬機(jī)需要管理鏡像、網(wǎng)絡(luò)、存儲運(yùn)維成本比容器高一個(gè)量級。場景推薦隔離方案理由內(nèi)部開發(fā)測試容器加基礎(chǔ)配置成本低夠用多租戶 SaaS容器加強(qiáng)隔離或輕量虛擬機(jī)平衡隔離與成本不可信代碼執(zhí)行虛擬機(jī)加容器雙層隔離強(qiáng)度優(yōu)先惡意代碼分析獨(dú)立物理機(jī)或?qū)S锰摂M機(jī)最高隔離強(qiáng)度這張表的核心邏輯是隔離強(qiáng)度與成本成正比按需選擇不要過度設(shè)計(jì)也不要偷懶。我見過為了省成本在不可信代碼場景用容器的也見過為了安全在開發(fā)環(huán)境用獨(dú)立物理機(jī)的。前者風(fēng)險(xiǎn)高后者浪費(fèi)大。提示無論選哪種方案都要定期做隔離驗(yàn)證。配置會漂移漏洞會出現(xiàn)今天的隔離不代表明天的隔離。把隔離檢查腳本接入 CI/CD每次部署自動跑是最省心的做法。我個(gè)人在實(shí)際操作中的體會是隔離這件事最怕的不是技術(shù)難而是“以為做了”。開了沙箱就以為隔離好了配了容器就以為安全了這種心態(tài)比不配還危險(xiǎn)。每次部署后跑一遍驗(yàn)證腳本把“以為”變成“確認(rèn)”才是靠譜的做法。