学习如何配置和使用 Claude Code 的沙箱隔离功能,为企业环境提供更安全的代理执行环境。
34.2.1 沙箱隔离概述#
什么是沙箱隔离#
沙箱隔离是 Claude Code 提供的一种安全机制,通过操作系统级原语强制执行文件系统和网络隔离。它允许 Claude Code 在预定义的安全边界内自主运行,减少对持续权限提示的依赖。
沙箱隔离的优势#
- 减少批准疲劳:安全命令无需逐个批准
- 提高生产力:减少工作流中断
- 增强安全性:定义清晰的访问边界
- 启用自主性:Claude Code 可以更独立地工作
- 全面保护:文件系统和网络双重隔离
沙箱隔离的适用场景#
- 企业开发环境
- 处理敏感数据的项目
- 需要高安全性的生产环境
- 自动化 CI/CD 流程
- 多租户开发环境
34.2.2 沙箱隔离工作原理#
文件系统隔离#
沙箱化 bash 工具通过以下方式限制文件系统访问:
沙箱文件系统访问规则示例
SANDBOX_FILESYSTEM_RULES = { "allowed_write_paths": [ "/workspace", # 当前工作目录 "/tmp", # 临时目录 "/home/developer/.cache" # 缓存目录 ], "allowed_read_paths": [ "/", # 整个系统(默认) "/usr/local/bin", # 系统工具 "/opt/tools" # 企业工具 ], "denied_paths": [ "/etc", # 系统配置 "/root", # root 用户目录 "/home/developer/.ssh", # SSH 密钥 "/home/developer/.aws", # AWS 凭证 "~/.config/claude-code" # Claude Code 配置 ] }
网络隔离#
网络访问通过代理服务器控制:
bashpython # 沙箱网络访问规则示例 SANDBOX_NETWORK_RULES = { "allowed_domains": [ "api.anthropic.com", "code.claude.com", "github.com", "npmjs.org", "*.company.com" ], "denied_domains": [ "*", "malicious-site.com" ], "proxy_settings": { "http_proxy": "http://proxy.company.com:8080", "https_proxy": "http://proxy.comany.com:8080", "no_proxy": "localhost,127.0.0.1,.company.com" } } ### 操作系统级强制执行 不同平台的实现方式: # Linux: 使用 bubblewrap bwrap \ --ro-bind /usr /usr \ --ro-bind /lib /lib \ --bind /workspace /workspace \ --bind /tmp /tmp \ --dev /dev \ --proc /proc \ --unshare-net \ --setenv PATH /usr/bin:/bin \ /bin/bash # macOS: 使用 Seatbelt sandbox-exec \ -f /path/to/sandbox.profile \ /bin/bash
34.2.3 快速入门#
启用沙箱隔离#
在 Claude Code 中运行斜杠命令:
bash/sandbox
这将使用默认设置激活沙箱化 bash 工具。
验证沙箱状态#
检查沙箱是否启用
bash/sandbox status # 查看当前沙箱配置 /sandbox config
测试沙箱隔离#
bash```bash # 测试文件系统隔离 - 应该成功 echo "test" > /workspace/test.txt # 测试文件系统隔离 - 应该失败 echo "test" > /etc/test.txt # 测试网络隔离 - 应该成功 curl https://api.anthropic.com # 测试网络隔离 - 应该失败 curl https://example.com ```## 34.2.4 基础配置 ### settings.json 配置 { "sandbox": { "enabled": true, "filesystem": { "allowedWritePaths": [ "${workspaceFolder}", "/tmp" ], "deniedPaths": [ "/etc", "/root", "~/.ssh", "~/.aws" ] }, "network": { "allowedDomains": [ "api.anthropic.com", "code.claude.com", "github.com", "npmjs.org" ], "httpProxy": "http://proxy.company.com:8080", "httpsProxy": "http://proxy.company.com:8080" }, "excludedCommands": [ "docker", "systemctl" ], "allowUnsandboxedCommands": false } }
环境变量配置#
bash```bash # 启用沙箱 export CLAUDE_SANDBOX_ENABLED=true # 配置文件系统路径 export CLAUDE_SANDBOX_WRITE_PATHS="/workspace,/tmp" export CLAUDE_SANDBOX_DENY_PATHS="/etc,/root,~/.ssh" # 配置网络 export CLAUDE_SANDBOX_ALLOWED_DOMAINS="api.anthropic.com,code.claude.com,github.com" export CLAUDE_SANDBOX_HTTP_PROXY="http://proxy.company.com:8080" export CLAUDE_SANDBOX_HTTPS_PROXY="http://proxy.company.com:8080" ```## 34.2.5 企业级配置 ### 多环境沙箱配置 > **开发环境配置:** { "sandbox": { "enabled": true, "filesystem": { "allowedWritePaths": [ "${workspaceFolder}", "/tmp", "/home/developer/.cache" ], "deniedPaths": [ "/etc", "/root", "~/.ssh", "~/.aws", "~/.config/claude-code" ] }, "network": { "allowedDomains": [ "api.anthropic.com", "code.claude.com", "github.com", "npmjs.org", "*.dev.company.com" ], "httpProxy": "http://proxy-dev.company.com:8080", "httpsProxy": "http://proxy-dev.company.com:8080" }, "excludedCommands": [ "docker", "kubectl" ], "allowUnsandboxedCommands": true } }
生产环境配置:
json```json { "sandbox": { "enabled": true, "filesystem": { "allowedWritePaths": [ "${workspaceFolder}/build", "${workspaceFolder}/dist", "/tmp" ], "deniedPaths": [ "/etc", "/root", "~/.ssh", "~/.aws", "~/.config", "${workspaceFolder}/src" ] }, "network": { "allowedDomains": [ "api.anthropic.com", "code.claude.com", "*.prod.company.com" ], "httpProxy": "http://proxy-prod.company.com:8080", "httpsProxy": "http://proxy-prod.company.com:8080" }, "excludedCommands": [], "allowUnsandboxedCommands": false, "enableWeakerNestedSandbox": false } } ```### 项目级配置 为不同类型的项目创建专门的沙箱配置: > **前端项目配置 (frontend-sandbox.json):** { "name": "Frontend Sandbox", "sandbox": { "filesystem": { "allowedWritePaths": [ "${workspaceFolder}", "/tmp", "/home/developer/.npm" ], "deniedPaths": [ "/etc", "/root", "~/.ssh", "~/.aws" ] }, "network": { "allowedDomains": [ "api.anthropic.com", "code.claude.com", "github.com", "npmjs.org", "registry.npmjs.org", "*.api.company.com" ] }, "excludedCommands": [ "docker" ] } }
后端项目配置 (backend-sandbox.json):
json```json { "name": "Backend Sandbox", "sandbox": { "filesystem": { "allowedWritePaths": [ "${workspaceFolder}", "/tmp", "/var/log/app" ], "deniedPaths": [ "/etc", "/root", "~/.ssh", "~/.aws", "/var/lib" ] }, "network": { "allowedDomains": [ "api.anthropic.com", "code.claude.com", "github.com", "*.api.company.com",
bash"*.db.company.com" ] }, "excludedCommands": [ "docker", "systemctl", "service" ]
} }
bash### 自定义代理配置 # 自定义代理服务器实现 import asyncio from aiohttp import web class SandboxProxy: def __init__(self, allowed_domains, audit_log_path): self.allowed_domains = set(allowed_domains) self.audit_log_path = audit_log_path async def proxy_handler(self, request): target_url = request.headers.get('X-Target-URL') # 检查域名是否在白名单中 from urllib.parse import urlparse parsed = urlparse(target_url) domain = parsed.netloc if domain not in self.allowed_domains: # 记录拒绝的访问 self.log_access(request, target_url, allowed=False) return web.Response(status=403, text="Domain not allowed") # 转发请求 async with aiohttp.ClientSession() as session: async with session.request( request.method, target_url, headers=request.headers, data=await request.read() ) as response: # 记录允许的访问 self.log_access(request, target_url, allowed=True) return web.Response( status=response.status, body=await response.read() ) def log_access(self, request, url, allowed): import json from datetime import datetime log_entry = { "timestamp": datetime.now().isoformat(), "client_ip": request.remote, "url": url, "allowed": allowed, "method": request.method } with open(self.audit_log_path, 'a') as f: f.write(json.dumps(log_entry) + '\n') def start(self, host='0.0.0.0', port=8080): app = web.Application() app.router.add_route('*', '/{path:.*}', self.proxy_handler) web.run_app(app, host=host, port=port) # 使用示例 if __name__ == '__main__': proxy = SandboxProxy( allowed_domains=[ 'api.anthropic.com', 'code.claude.com', 'github.com' ], audit_log_path='/var/log/sandbox-proxy.log' ) proxy.start()
Unix Socket 配置#
json```json { "sandbox": { "enabled": true, "filesystem": { "allowedWritePaths": ["${workspaceFolder}"], "allowedUnixSockets": [ "/var/run/docker.sock", # 警告:这可能授予主机访问权限 "/tmp/vscode-git.sock" ] }, "network": { "allowedDomains": ["api.anthropic.com", "code.claude.com"] } } } ```### 嵌套沙箱配置 { "sandbox": { "enabled": true, "enableWeakerNestedSandbox": true, "filesystem": { "allowedWritePaths": ["${workspaceFolder}"] }, "network": { "allowedDomains": ["api.anthropic.com", "code.claude.com"] } } }
34.2.7 安全最佳实践#
1. 最小权限原则#
从最严格的配置开始,根据需要逐步放宽:
json```json { "sandbox": { "enabled": true, "filesystem": { "allowedWritePaths": ["${workspaceFolder}"], "deniedPaths": [ "/etc", "/root", "~/.ssh", "~/.aws", "~/.config", "/usr/local/bin", "/opt" ] }, "network": { "allowedDomains": ["api.anthropic.com", "code.claude.com"] }, "excludedCommands": [], "allowUnsandboxedCommands": false } } ```### 2. 审计和监控 实现全面的审计日志记录: import json from datetime import datetime from pathlib import Path class SandboxAuditor: def __init__(self, log_dir='/var/log/claude-sandbox'): self.log_dir = Path(log_dir) self.log_dir.mkdir(parents=True, exist_ok=True) def log_filesystem_access(self, operation, path, allowed, user): log_entry = { "timestamp": datetime.now().isoformat(), "type": "filesystem", "operation": operation, "path": path, "allowed": allowed, "user": user } self._write_log(log_entry) def log_network_access(self, url, domain, allowed, user): log_entry = { "timestamp": datetime.now().isoformat(), "type": "network", "url": url, "domain": domain, "allowed": allowed, "user": user } self._write_log(log_entry) def log_command_execution(self, command, sandboxed, allowed, user): log_entry = { "timestamp": datetime.now().isoformat(), "type": "command", "command": command, "sandboxed": sandboxed, "allowed": allowed, "user": user } self._write_log(log_entry) def _write_log(self, log_entry): log_file = self.log_dir / f"sandbox-{datetime.now().strftime('%Y-%m-%d')}.log" with open(log_file, 'a') as f: f.write(json.dumps(log_entry) + '\n') def analyze_violations(self, days=7): violations = [] for i in range(days): date = (datetime.now() - timedelta(days=i)).strftime('%Y-%m-%d') log_file = self.log_dir / f"sandbox-{date}.log" if log_file.exists(): with open(log_file, 'r') as f: for line in f: entry = json.loads(line) if not entry.get('allowed', True): violations.append(entry) return violations # 使用示例 auditor = SandboxAuditor() # 记录文件系统访问 auditor.log_filesystem_access('write', '/etc/config', False, 'developer') # 记录网络访问 auditor.log_network_access('https://malicious.com', 'malicious.com', False, 'developer') # 分析违规 violations = auditor.analyze_violations(days=7) print(f"发现 {len(violations)} 个违规")
3. 定期审查#
建立定期审查流程:
bash```bash #!/bin/bash # sandbox-audit.sh LOG_DIR="/var/log/claude-sandbox" REPORT_DIR="/var/reports/sandbox" DATE=$(date +%Y-%m-%d) # 创建报告目录 mkdir -p "$REPORT_DIR" # 生成每日报告 echo "=== 沙箱审计报告 - $DATE ===" > "$REPORT_DIR/daily-$DATE.txt" # 统计违规次数 VIOLATIONS=$(grep -r '"allowed": false' "$LOG_DIR" | wc -l) echo "总违规次数: $VIOLATIONS" >> "$REPORT_DIR/daily-$DATE.txt" # 统计文件系统违规 FS_VIOLATIONS=$(grep -r '"type": "filesystem"' "$LOG_DIR" | grep '"allowed": false' | wc -l) echo "文件系统违规: $FS_VIOLATIONS" >> "$REPORT_DIR/daily-$DATE.txt" # 统计网络违规 NET_VIOLATIONS=$(grep -r '"type": "network"' "$LOG_DIR" | grep '"allowed": false' | wc -l) echo "网络违规: $NET_VIOLATIONS" >> "$REPORT_DIR/daily-$DATE.txt" # 列出最活跃的用户 echo -e "\n最活跃的用户:" >> "$REPORT_DIR/daily-$DATE.txt" grep -r '"user"' "$LOG_DIR" | jq -r '.user' | sort | uniq -c | sort -rn | head -10 >> "$REPORT_DIR/daily-$DATE.txt" # 列出最常见的违规 echo -e "\n最常见的违规:" >> "$REPORT_DIR/daily-$DATE.txt" grep -r '"allowed": false' "$LOG_DIR" | jq -r '.path // .domain // .command' | sort | uniq -c | sort -rn | head -10 >> "$REPORT_DIR/daily-$DATE.txt" echo "报告已生成: $REPORT_DIR/daily-$DATE.txt" ```### 4. 环境隔离 为不同的环境使用不同的沙箱配置: import json from pathlib import Path class SandboxConfigManager: def __init__(self, config_dir='/etc/claude-sandbox'): self.config_dir = Path(config_dir) self.config_dir.mkdir(parents=True, exist_ok=True) def create_config(self, environment, config): config_file = self.config_dir / f"{environment}.json" with open(config_file, 'w') as f: json.dump(config, f, indent=2) def get_config(self, environment): config_file = self.config_dir / f"{environment}.json" if config_file.exists(): with open(config_file, 'r') as f: return json.load(f) return None def create_development_config(self): return { "sandbox": { "enabled": True, "filesystem": { "allowedWritePaths": ["${workspaceFolder}", "/tmp"], "deniedPaths": ["/etc", "/root", "~/.ssh", "~/.aws"] }, "network": { "allowedDomains": [ "api.anthropic.com", "code.claude.com", "github.com", "npmjs.org", "*.dev.company.com" ] }, "allowUnsandboxedCommands": True } } def create_production_config(self): return { "sandbox": { "enabled": True, "filesystem": { "allowedWritePaths": ["${workspaceFolder}/build", "/tmp"], "deniedPaths": [ "/etc", "/root", "~/.ssh", "~/.aws", "~/.config", "${workspaceFolder}/src" ] }, "network": { "allowedDomains": [ "api.anthropic.com", "code.claude.com", "*.prod.company.com" ] }, "allowUnsandboxedCommands": False, "enableWeakerNestedSandbox": False } } # 使用示例 manager = SandboxConfigManager() # 创建开发环境配置 manager.create_config('development', manager.create_development_config()) # 创建生产环境配置 manager.create_config('production', manager.create_production_config())
34.2.8 故障排查#
常见问题#
问题 1:沙箱阻止了合法操作
bash```bash # 查看沙箱日志 tail -f /var/log/claude-sandbox/sandbox-$(date +%Y-%m-%d).log # 临时禁用沙箱
/sandbox disable
添加允许的路径或域名
在 settings.json 中更新配置
bash# 检查命令是否在排除列表中
/sandbox config
将命令添加到排除列表
在 settings.json 中添加到 "excludedCommands"
bash> **问题 3:网络连接问题** ```bash ```bash # 测试 DNS 解析 dig api.anthropic.com # 检查代理配置 echo $HTTP_PROXY echo $HTTPS_PROXY # 测试网络连接 curl -v https://api.anthropic.com ```> **问题 4:文件权限问题** # 检查文件权限 ls -la /workspace # 修复权限 chmod 755 /workspace chown developer:developer /workspace
34.2.9 与其他安全功能集成#
与 IAM 策略集成#
json```json { "sandbox": { "enabled": true, "filesystem": { "allowedWritePaths": ["${workspaceFolder}"], "deniedPaths": ["/etc", "/root", "~/.ssh", "~/.aws"] }, "network": { "allowedDomains": ["api.anthropic.com", "code.claude.com"] } }, "permissions": { "fileAccess": { "allowedPaths": ["${workspaceFolder}"], "deniedPaths": ["/etc", "/root", "~/.ssh", "~/.aws"] }, "networkAccess": { "allowedDomains": ["api.anthropic.com", "code.claude.com"] } } } ```### 与开发容器集成 { "name": "Claude Code Enterprise Dev Container", "dockerFile": "Dockerfile", "customizations": { "vscode": { "settings": { "claude-code.sandbox.enabled": true, "claude-code.sandbox.filesystem.allowedWritePaths": [ "${workspaceFolder}", "/tmp" ], "claude-code.sandbox.network.allowedDomains": [ "api.anthropic.com", "code.claude.com", "github.com" ] } } }, "postCreateCommand": "bash .devcontainer/init-sandbox.sh" }