"""Sandbox Docker network 管理。 `zcbot-sandbox-net` 是 `--internal` bridge: - 默认无 outbound(Docker bridge 移除 host NAT 路由) - 同网络下容器之间默认隔离(Docker bridge 默认行为,internal 也成立) Step 2 起即用 `--internal`,iptables OUTPUT blocklist(init.sh 里的)作为 defense-in-depth (网络层已堵死,iptables 仍按 §7.5 #1 协议加规则,任一缺失视为部署未完成)。 Step 4 引入 egress proxy 时:proxy 容器同接 `zcbot-sandbox-net`(从内部网到 proxy 容器 保持联通),proxy 容器再走 host 默认网出网。sandbox 容器 env `HTTP_PROXY` 指向 proxy 容器名 + iptables 加 ACCEPT 例外,实现"默认 deny + 仅经 proxy"。 操作幂等:create 前 inspect 探测,已存在直接返。 """ from __future__ import annotations import subprocess NETWORK_NAME = "zcbot-sandbox-net" def ensure_network() -> None: """创建 `zcbot-sandbox-net`(若不存在)。失败 raise。""" inspect = subprocess.run( ["docker", "network", "inspect", NETWORK_NAME], capture_output=True, text=True, ) if inspect.returncode == 0: return r = subprocess.run( ["docker", "network", "create", "--internal", NETWORK_NAME], capture_output=True, text=True, ) if r.returncode != 0: raise RuntimeError( f"docker network create {NETWORK_NAME} failed: {r.stderr.strip()}" )