reoring/botbox
GitHub: reoring/botbox
一个 Kubernetes 边车代理,通过 iptables 与允许列表为容器提供零信任网络隔离与安全审计。
Stars: 13 | Forks: 1
# BotBox
[](https://github.com/reoring/botbox/actions/workflows/ci.yml)
[](LICENSE)
[](https://www.rust-lang.org/)
English | [日本語](README.ja.md)
no credentials"] IPT[/"iptables
transparent
redirect"/] BotBox["🔒 BotBox
sidecar"] end Agent -- "curl http://api.openai.com" --> IPT IPT -- ":80 → :8080" --> BotBox BotBox -- "✅ Allowed + TLS + Key injected" --> API["api.openai.com"] BotBox -. "❌ Denied → 403" .-> Agent style Agent fill:#fef3c7,stroke:#d97706 style BotBox fill:#dbeafe,stroke:#2563eb style API fill:#d1fae5,stroke:#059669 ``` 这使得 BotBox 非常适合任何需要**运行不受信或半信任代码**并具备可控、可审计网络访问的场景。 ## 工作原理 ### 运行模式 BotBox 支持两种运行模式: 1. **仅 HTTP(默认)** — 拦截 80 端口的明文 HTTP,重写头部,并对上游发起 TLS。应用程序容器发起 `http://` 请求,BotBox 将其升级为 HTTPS。 2. **HTTPS 拦截** — 此外,通过 8443 端口上的 TLS 终止监听器拦截 443 端口的出站 HTTPS。BotBox 动态签发由本地 CA 签名的短期叶证书,解密流量,应用相同的允许列表和头部重写流水线,然后重新加密并转发到上游。这允许在不要求应用程序使用明文 HTTP 的情况下向 HTTPS 请求注入凭据。 ### 请求处理 ``` flowchart LR A["HTTP request"] --> B{"Allowlist"} B -- "deny" --> C["403"] B -- "allow" --> D["Rewrite headers\n+ inject secrets"] --> E["TLS → upstream"] style C fill:#fee2e2,stroke:#dc2626 style E fill:#d1fae5,stroke:#059669 ``` 请参阅 [架构](docs/architecture.md) 了解完整的请求处理流水线。 ### iptables 网络规则 ``` flowchart TD OUT["Outbound packet
OUTPUT chain"] --> FIL{"EGRESS_FILTER"} FIL -- "loopback" --> PASS1["✅ RETURN"] FIL -- "UID 1337
BotBox itself" --> PASS2["✅ RETURN"] FIL -- "DNS (53)" --> PASS3["✅ RETURN"] FIL -- "other TCP/UDP" --> DROP["🚫 DROP"] OUT --> NAT{"EGRESS_REDIRECT
NAT"} NAT -- "loopback" --> SKIP1["RETURN"] NAT -- "UID 1337" --> SKIP2["RETURN"] NAT -- "TCP :80" --> REDIR[":80 → :8080
REDIRECT to BotBox"] NAT -- "TCP :443" --> REDIR443[":443 → :8443
REDIRECT to HTTPS
interception"] style DROP fill:#fee2e2,stroke:#dc2626 style REDIR fill:#dbeafe,stroke:#2563eb style REDIR443 fill:#dbeafe,stroke:#2563eb ``` ## HTTPS 拦截模式 启用后,BotBox 会通过在边车中终止 TLS 并重新加密到上游来拦截出站 HTTPS 流量。这使 BotBox 能够检查并重写 HTTPS 请求中的头部——相同的允许列表、头部重写和凭据注入流水线均适用。 ### 工作原理 1. iptables 将出站 TCP 443 端口重定向到 BotBox 的 HTTPS 拦截监听端口 8443。 2. BotBox 使用动态颁发的叶证书(由本地 CA 签名)终止 TLS。 3. 解密后的 HTTP 请求通过标准代理流水线(允许列表检查、头部重写、密钥注入)。 4. BotBox 重新加密并转发请求到上游 TLS。 应用程序容器看到的是一个有效的 TLS 连接(由本地 CA 签名),无需任何代理配置。 ### 配置 在配置中添加一个 `https_interception` 块: ``` https_interception: enabled: true listen_addr: "127.0.0.1" listen_port: 8443 ca_cert_path: "/etc/botbox/https_interception/ca.crt" ca_key_path: "/etc/botbox/https_interception/ca.key" enforce_sni_host_match: true # default: true -- reject requests where Host header != SNI deny_handshake_on_disallowed_sni: false # default: false -- when true, refuse TLS handshake for non-allowlisted hosts cert_ttl_seconds: 86400 # default: 86400 (24h) -- leaf cert validity period cert_cache_size: 1024 # default: 1024 -- LRU cache capacity cert_cache_ttl_seconds: 3600 # default: 3600 (1h) -- cache entry TTL handshake_timeout_ms: 5000 # default: 5000 -- TLS handshake timeout ``` 环境变量覆盖: | 变量 | 描述 | |---|---| | `BOTBOX_ENABLE_HTTPS_INTERCEPTION` | 设置为 `1`,以便在 iptables 初始化容器中添加 443 端口的 NAT 重定向 | | `BOTBOX_HTTPS_INTERCEPTION_PORT` | 覆盖 HTTPS 拦截监听端口(默认:8443) | ### HTTPS 拦截的 iptables 规则 初始化容器必须添加针对 443 端口的 NAT 重定向, alongside 现有的 80 端口规则: ``` iptables -t nat -A EGRESS_REDIRECT -p tcp --dport 443 -j REDIRECT --to-port 8443 ``` ### 应用端 CA 信任 应用程序容器必须信任 BotBox CA 证书。挂载 CA 证书(**不是私钥**)到应用容器并配置运行时: | 运行时 / 库 | 环境变量或标志 | |---|---| | curl / OpenSSL | `CURL_CA_BUNDLE=/etc/botbox/https_interception/ca.crt` 或 `SSL_CERT_FILE=/etc/botbox/https_interception/ca.crt` | | Node.js | `NODE_EXTRA_CA_CERTS=/etc/botbox/https_interception/ca.crt` | | Python requests | `REQUESTS_CA_BUNDLE=/etc/botbox/https_interception/ca.crt` | | JVM(Java、Kotlin) | `-Djavax.net.ssl.trustStore=/path/to/truststore.jks`(将 CA 证书导入 JKS 信任库) | | Go(net/http) | `SSL_CERT_FILE=/etc/botbox/https_interception/ca.crt` | **安全说明:** CA **私钥** 不得挂载到应用容器中。只有 CA 证书(公钥)应当共享。私钥必须存放在仅限边车访问的独立卷中。 ### Kubernetes 注意事项(来自示例清单) - 仅监听回环的监听器与探针:BotBox 的指标服务器绑定到 `127.0.0.1`,且 `https_interception.listen_addr` 必须为回环地址。Kubernetes `httpGet` 探针会命中 Pod IP,因此如果将探针指向 `:9090/healthz`(或 `:8443`)而这些监听器绑定到回环地址,探针会超时。 - 对任何包含 HTTP 客户端(你的应用容器或小型 curl 边车)的容器使用 `exec` 探针,并从 Pod 网络命名空间探测 `http://127.0.0.1:9090/healthz`。默认 BotBox 镜像为 distroless,不包含 `/bin/sh` 或 `curl`。 示例 `exec` 就绪探针: ``` readinessProbe: exec: command: - /bin/sh - -c - curl -sf --connect-timeout 1 --max-time 1 http://127.0.0.1:9090/healthz >/dev/null initialDelaySeconds: 1 periodSeconds: 2 timeoutSeconds: 1 ``` - 开发阶段的临时 CA:示例会在初始化容器中生成一次性 CA 密钥对,并存储在 `emptyDir` 中。这对开发很方便,但生产环境你可能希望将稳定的 CA 存储在 Kubernetes Secret 中。 ## 快速开始 ### 先决条件 - Docker - [kind](https://kind.sigs.k8s.io/) - kubectl ### 1. 构建并加载镜像 ``` docker build -t botbox:test . docker build --target iptables-init -t botbox-iptables-init:test . kind load docker-image botbox:test botbox-iptables-init:test ``` ### 2. 编写出口策略 ``` # config.yaml allow_non_loopback: false # keep false unless intentionally exposing outside the pod egress_policy: default_action: deny rules: - host: api.openai.com action: allow header_rewrites: - name: Authorization value: "Bearer {value}" secret_ref: openai-api-key # reads from K8s Secret ``` ### 3. 添加边车到 Pod ``` initContainers: - name: iptables-init # installs the recommended iptables NAT+filter rules image: botbox-iptables-init:test env: - name: BOTBOX_ENABLE_IPV6 value: "1" # required — set to "0" if ip6tables or ip6table_nat is unavailable securityContext: capabilities: { add: [NET_ADMIN] } runAsUser: 0 runAsNonRoot: false - name: botbox # runs for the pod's lifetime image: botbox:test restartPolicy: Always args: ["--config", "/etc/botbox/config.yaml"] securityContext: runAsUser: 1337 runAsNonRoot: true # mount your ConfigMap and Secret here containers: - name: app # your application — no proxy config needed image: your-app:latest securityContext: runAsNonRoot: true runAsUser: 1000 # must NOT be 1337 (BotBox UID) or iptables owner-match can be bypassed ``` 或者尝试可直接应用的 Kubernetes 示例(启用 HTTPS 拦截): ``` kubectl apply -k examples/https_interception kubectl -n botbox-https-interception rollout status deploy/botbox-https-interception-demo kubectl -n botbox-https-interception exec -it deploy/botbox-https-interception-demo -c client -- sh ``` ### 4. 在 kind 上运行验收测试(自动化) ``` tests/e2e/run-kind-acceptance.sh ``` ### 5. 运行单个 E2E 测试(可选) ``` tests/e2e/run-egress-test.sh tests/e2e/run-https-interception-test.sh ``` ### 6. 运行单元测试 ``` cargo test ``` ## 为什么选择 BotBox | 问题 | BotBox 的解决方案 | |---|---| | API 密钥泄露到应用环境变量 | 密钥仅存在于 K8s Secrets 中,在网络边界注入 | | 应用程序必须配置 HTTP_PROXY | iptables 使拦截透明化——零应用变更 | | 未受控的出站流量 | 拒绝默认的允许列表;仅允许访问批准的主机 | | 密钥轮换需要重启 | Secrets 目录通过 inotify 监听;热重载,零停机 | ## 文档 - [架构](docs/architecture.md) — 模块结构、请求流程、iptables 规则、配置参考 - [安全性](docs/security.md) — 威胁模型、控制措施、加固清单、残留风险 - [BotBox 与 Deno 沙箱对比](docs/vs-deno-sandbox.md) — `allowNet`/`secrets` 对比、允许列表上游风险分析
no credentials"] IPT[/"iptables
transparent
redirect"/] BotBox["🔒 BotBox
sidecar"] end Agent -- "curl http://api.openai.com" --> IPT IPT -- ":80 → :8080" --> BotBox BotBox -- "✅ Allowed + TLS + Key injected" --> API["api.openai.com"] BotBox -. "❌ Denied → 403" .-> Agent style Agent fill:#fef3c7,stroke:#d97706 style BotBox fill:#dbeafe,stroke:#2563eb style API fill:#d1fae5,stroke:#059669 ``` 这使得 BotBox 非常适合任何需要**运行不受信或半信任代码**并具备可控、可审计网络访问的场景。 ## 工作原理 ### 运行模式 BotBox 支持两种运行模式: 1. **仅 HTTP(默认)** — 拦截 80 端口的明文 HTTP,重写头部,并对上游发起 TLS。应用程序容器发起 `http://` 请求,BotBox 将其升级为 HTTPS。 2. **HTTPS 拦截** — 此外,通过 8443 端口上的 TLS 终止监听器拦截 443 端口的出站 HTTPS。BotBox 动态签发由本地 CA 签名的短期叶证书,解密流量,应用相同的允许列表和头部重写流水线,然后重新加密并转发到上游。这允许在不要求应用程序使用明文 HTTP 的情况下向 HTTPS 请求注入凭据。 ### 请求处理 ``` flowchart LR A["HTTP request"] --> B{"Allowlist"} B -- "deny" --> C["403"] B -- "allow" --> D["Rewrite headers\n+ inject secrets"] --> E["TLS → upstream"] style C fill:#fee2e2,stroke:#dc2626 style E fill:#d1fae5,stroke:#059669 ``` 请参阅 [架构](docs/architecture.md) 了解完整的请求处理流水线。 ### iptables 网络规则 ``` flowchart TD OUT["Outbound packet
OUTPUT chain"] --> FIL{"EGRESS_FILTER"} FIL -- "loopback" --> PASS1["✅ RETURN"] FIL -- "UID 1337
BotBox itself" --> PASS2["✅ RETURN"] FIL -- "DNS (53)" --> PASS3["✅ RETURN"] FIL -- "other TCP/UDP" --> DROP["🚫 DROP"] OUT --> NAT{"EGRESS_REDIRECT
NAT"} NAT -- "loopback" --> SKIP1["RETURN"] NAT -- "UID 1337" --> SKIP2["RETURN"] NAT -- "TCP :80" --> REDIR[":80 → :8080
REDIRECT to BotBox"] NAT -- "TCP :443" --> REDIR443[":443 → :8443
REDIRECT to HTTPS
interception"] style DROP fill:#fee2e2,stroke:#dc2626 style REDIR fill:#dbeafe,stroke:#2563eb style REDIR443 fill:#dbeafe,stroke:#2563eb ``` ## HTTPS 拦截模式 启用后,BotBox 会通过在边车中终止 TLS 并重新加密到上游来拦截出站 HTTPS 流量。这使 BotBox 能够检查并重写 HTTPS 请求中的头部——相同的允许列表、头部重写和凭据注入流水线均适用。 ### 工作原理 1. iptables 将出站 TCP 443 端口重定向到 BotBox 的 HTTPS 拦截监听端口 8443。 2. BotBox 使用动态颁发的叶证书(由本地 CA 签名)终止 TLS。 3. 解密后的 HTTP 请求通过标准代理流水线(允许列表检查、头部重写、密钥注入)。 4. BotBox 重新加密并转发请求到上游 TLS。 应用程序容器看到的是一个有效的 TLS 连接(由本地 CA 签名),无需任何代理配置。 ### 配置 在配置中添加一个 `https_interception` 块: ``` https_interception: enabled: true listen_addr: "127.0.0.1" listen_port: 8443 ca_cert_path: "/etc/botbox/https_interception/ca.crt" ca_key_path: "/etc/botbox/https_interception/ca.key" enforce_sni_host_match: true # default: true -- reject requests where Host header != SNI deny_handshake_on_disallowed_sni: false # default: false -- when true, refuse TLS handshake for non-allowlisted hosts cert_ttl_seconds: 86400 # default: 86400 (24h) -- leaf cert validity period cert_cache_size: 1024 # default: 1024 -- LRU cache capacity cert_cache_ttl_seconds: 3600 # default: 3600 (1h) -- cache entry TTL handshake_timeout_ms: 5000 # default: 5000 -- TLS handshake timeout ``` 环境变量覆盖: | 变量 | 描述 | |---|---| | `BOTBOX_ENABLE_HTTPS_INTERCEPTION` | 设置为 `1`,以便在 iptables 初始化容器中添加 443 端口的 NAT 重定向 | | `BOTBOX_HTTPS_INTERCEPTION_PORT` | 覆盖 HTTPS 拦截监听端口(默认:8443) | ### HTTPS 拦截的 iptables 规则 初始化容器必须添加针对 443 端口的 NAT 重定向, alongside 现有的 80 端口规则: ``` iptables -t nat -A EGRESS_REDIRECT -p tcp --dport 443 -j REDIRECT --to-port 8443 ``` ### 应用端 CA 信任 应用程序容器必须信任 BotBox CA 证书。挂载 CA 证书(**不是私钥**)到应用容器并配置运行时: | 运行时 / 库 | 环境变量或标志 | |---|---| | curl / OpenSSL | `CURL_CA_BUNDLE=/etc/botbox/https_interception/ca.crt` 或 `SSL_CERT_FILE=/etc/botbox/https_interception/ca.crt` | | Node.js | `NODE_EXTRA_CA_CERTS=/etc/botbox/https_interception/ca.crt` | | Python requests | `REQUESTS_CA_BUNDLE=/etc/botbox/https_interception/ca.crt` | | JVM(Java、Kotlin) | `-Djavax.net.ssl.trustStore=/path/to/truststore.jks`(将 CA 证书导入 JKS 信任库) | | Go(net/http) | `SSL_CERT_FILE=/etc/botbox/https_interception/ca.crt` | **安全说明:** CA **私钥** 不得挂载到应用容器中。只有 CA 证书(公钥)应当共享。私钥必须存放在仅限边车访问的独立卷中。 ### Kubernetes 注意事项(来自示例清单) - 仅监听回环的监听器与探针:BotBox 的指标服务器绑定到 `127.0.0.1`,且 `https_interception.listen_addr` 必须为回环地址。Kubernetes `httpGet` 探针会命中 Pod IP,因此如果将探针指向 `:9090/healthz`(或 `:8443`)而这些监听器绑定到回环地址,探针会超时。 - 对任何包含 HTTP 客户端(你的应用容器或小型 curl 边车)的容器使用 `exec` 探针,并从 Pod 网络命名空间探测 `http://127.0.0.1:9090/healthz`。默认 BotBox 镜像为 distroless,不包含 `/bin/sh` 或 `curl`。 示例 `exec` 就绪探针: ``` readinessProbe: exec: command: - /bin/sh - -c - curl -sf --connect-timeout 1 --max-time 1 http://127.0.0.1:9090/healthz >/dev/null initialDelaySeconds: 1 periodSeconds: 2 timeoutSeconds: 1 ``` - 开发阶段的临时 CA:示例会在初始化容器中生成一次性 CA 密钥对,并存储在 `emptyDir` 中。这对开发很方便,但生产环境你可能希望将稳定的 CA 存储在 Kubernetes Secret 中。 ## 快速开始 ### 先决条件 - Docker - [kind](https://kind.sigs.k8s.io/) - kubectl ### 1. 构建并加载镜像 ``` docker build -t botbox:test . docker build --target iptables-init -t botbox-iptables-init:test . kind load docker-image botbox:test botbox-iptables-init:test ``` ### 2. 编写出口策略 ``` # config.yaml allow_non_loopback: false # keep false unless intentionally exposing outside the pod egress_policy: default_action: deny rules: - host: api.openai.com action: allow header_rewrites: - name: Authorization value: "Bearer {value}" secret_ref: openai-api-key # reads from K8s Secret ``` ### 3. 添加边车到 Pod ``` initContainers: - name: iptables-init # installs the recommended iptables NAT+filter rules image: botbox-iptables-init:test env: - name: BOTBOX_ENABLE_IPV6 value: "1" # required — set to "0" if ip6tables or ip6table_nat is unavailable securityContext: capabilities: { add: [NET_ADMIN] } runAsUser: 0 runAsNonRoot: false - name: botbox # runs for the pod's lifetime image: botbox:test restartPolicy: Always args: ["--config", "/etc/botbox/config.yaml"] securityContext: runAsUser: 1337 runAsNonRoot: true # mount your ConfigMap and Secret here containers: - name: app # your application — no proxy config needed image: your-app:latest securityContext: runAsNonRoot: true runAsUser: 1000 # must NOT be 1337 (BotBox UID) or iptables owner-match can be bypassed ``` 或者尝试可直接应用的 Kubernetes 示例(启用 HTTPS 拦截): ``` kubectl apply -k examples/https_interception kubectl -n botbox-https-interception rollout status deploy/botbox-https-interception-demo kubectl -n botbox-https-interception exec -it deploy/botbox-https-interception-demo -c client -- sh ``` ### 4. 在 kind 上运行验收测试(自动化) ``` tests/e2e/run-kind-acceptance.sh ``` ### 5. 运行单个 E2E 测试(可选) ``` tests/e2e/run-egress-test.sh tests/e2e/run-https-interception-test.sh ``` ### 6. 运行单元测试 ``` cargo test ``` ## 为什么选择 BotBox | 问题 | BotBox 的解决方案 | |---|---| | API 密钥泄露到应用环境变量 | 密钥仅存在于 K8s Secrets 中,在网络边界注入 | | 应用程序必须配置 HTTP_PROXY | iptables 使拦截透明化——零应用变更 | | 未受控的出站流量 | 拒绝默认的允许列表;仅允许访问批准的主机 | | 密钥轮换需要重启 | Secrets 目录通过 inotify 监听;热重载,零停机 | ## 文档 - [架构](docs/architecture.md) — 模块结构、请求流程、iptables 规则、配置参考 - [安全性](docs/security.md) — 威胁模型、控制措施、加固清单、残留风险 - [BotBox 与 Deno 沙箱对比](docs/vs-deno-sandbox.md) — `allowNet`/`secrets` 对比、允许列表上游风险分析
标签:AI代理, AI安全, allowlist, API密钥管理, Chat Copilot, deny-by-default, egress控制, iptables, LLM代理, Rust, sidecar, 凭证注入, 可视化界面, 子域名突变, 审计日志, 容器网络, 容器隔离, 密钥不落地, 底层编程, 数据防泄露, 无代理, 结构化查询, 结构化追踪, 网络沙箱, 网络流量审计, 网络边界, 自动化安全, 透明代理, 通知系统, 零配置代理