Skip to content

34.2 沙箱隔离配置

学习如何配置和使用 Claude Code 的沙箱隔离功能,为企业环境提供更安全的代理执行环境。

34.2.1 沙箱隔离概述

什么是沙箱隔离

沙箱隔离是 Claude Code 提供的一种安全机制,通过操作系统级原语强制执行文件系统和网络隔离。它允许 Claude Code 在预定义的安全边界内自主运行,减少对持续权限提示的依赖。

沙箱隔离的优势

  • 减少批准疲劳 :安全命令无需逐个批准
  • 提高生产力 :减少工作流中断
  • 增强安全性 :定义清晰的访问边界
  • 启用自主性 :Claude Code 可以更独立地工作
  • 全面保护 :文件系统和网络双重隔离

沙箱隔离的适用场景

  • 企业开发环境
  • 处理敏感数据的项目
  • 需要高安全性的生产环境
  • 自动化 CI/CD 流程
  • 多租户开发环境

34.2.2 沙箱隔离工作原理

文件系统隔离

沙箱化 bash 工具通过以下方式限制文件系统访问:

python
# 沙箱文件系统访问规则示例
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 配置
    ]
}

网络隔离

网络访问通过代理服务器控制:

python
# 沙箱网络访问规则示例
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"
    }
}

操作系统级强制执行

不同平台的实现方式:

bash
# 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
# 测试文件系统隔离 - 应该成功
echo "test" > /workspace/test.txt

# 测试文件系统隔离 - 应该失败
echo "test" > /etc/test.txt

# 测试网络隔离 - 应该成功
curl https://api.anthropic.com

# 测试网络隔离 - 应该失败
curl https://example.com

34.2.4 基础配置

settings.json 配置

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
# 启用沙箱
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 企业级配置

多环境沙箱配置

开发环境配置:

json
{
  "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
{
  "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):

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
{
  "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",
        "*.db.company.com"
      ]
    },
    "excludedCommands": [
      "docker",
      "systemctl",
      "service"
    ]
  }
}

34.2.6 高级配置

自定义代理配置

python
# 自定义代理服务器实现
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
{
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "allowedWritePaths": ["${workspaceFolder}"],
      "allowedUnixSockets": [
        "/var/run/docker.sock",
        "/tmp/vscode-git.sock"
      ]
    },
    "network": {
      "allowedDomains": ["api.anthropic.com", "code.claude.com"]
    }
  }
}

嵌套沙箱配置

json
{
  "sandbox": {
    "enabled": true,
    "enableWeakerNestedSandbox": true,
    "filesystem": {
      "allowedWritePaths": ["${workspaceFolder}"]
    },
    "network": {
      "allowedDomains": ["api.anthropic.com", "code.claude.com"]
    }
  }
}

34.2.7 安全最佳实践

1. 最小权限原则

从最严格的配置开始,根据需要逐步放宽:

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. 审计和监控

实现全面的审计日志记录:

python
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
#!/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. 环境隔离

为不同的环境使用不同的沙箱配置:

python
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
# 查看沙箱日志
tail -f /var/log/claude-sandbox/sandbox-$(date +%Y-%m-%d).log

# 临时禁用沙箱
/sandbox disable

# 添加允许的路径或域名
# 在 settings.json 中更新配置

问题 2:命令执行被拒绝

bash
# 检查命令是否在排除列表中
/sandbox config

# 将命令添加到排除列表
# 在 settings.json 中添加到 "excludedCommands"

问题 3:网络连接问题

bash
# 测试 DNS 解析
dig api.anthropic.com

# 检查代理配置
echo $HTTP_PROXY
echo $HTTPS_PROXY

# 测试网络连接
curl -v https://api.anthropic.com

问题 4:文件权限问题

bash
# 检查文件权限
ls -la /workspace

# 修复权限
chmod 755 /workspace
chown developer:developer /workspace

34.2.9 与其他安全功能集成

与 IAM 策略集成

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"]
    }
  }
}

与开发容器集成

json
{
  "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"
}

基于 MIT 许可发布 | 永久导航