mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-12 18:15:33 +00:00
fix: more artefact hardening
This commit is contained in:
1 parent
47cc0314af
commit
94a845aa82
37 files changed
+1233
-165
No files matched your search
@@ -11,31 +11,68 @@
|
||||
# (control plane to backend/worker) and `sandbox-egress` (its internet route).
|
||||
# This overlay flips `sandbox-egress` to `internal: true`, which removes the
|
||||
# runner's direct route to the internet / host / RFC1918 / metadata entirely --
|
||||
# so even raw sockets in arbitrary sandbox code have nowhere to go except the
|
||||
# proxy on `sandbox-net`. The proxy is the ONLY container with an internet route
|
||||
# so raw sockets in arbitrary sandbox code have no route OFF the host except the
|
||||
# deny-private proxy. The proxy is the ONLY container with an internet route
|
||||
# (on its own `sandbox-egress-out` network) and its ACL denies private
|
||||
# destinations. We flip a network's scalar property by KEY (a well-defined
|
||||
# Compose merge); we do NOT try to remove an item from the service's `networks`
|
||||
# LIST, which Compose cannot express (it unions lists) -- the reason a naive
|
||||
# `networks: [sandbox-net]` override silently leaves the runner on its old net.
|
||||
#
|
||||
# Two viable approaches; pick one:
|
||||
# WHAT THIS OVERLAY DOES NOT CONTAIN (read before enabling the sandbox):
|
||||
# The runner STILL shares `sandbox-net` with `backend` and `worker` -- that is
|
||||
# its control path and it cannot be removed without breaking code execution. A
|
||||
# shared Docker network is bidirectional and Compose cannot sever it
|
||||
# one-directionally, so arbitrary sandbox code can still open sockets to
|
||||
# `backend:7091` and reach the worker. The internal flip contains raw sockets to
|
||||
# the internet / host / RFC1918 / metadata, NOT to backend/worker on sandbox-net.
|
||||
# (The Kubernetes NetworkPolicy DOES block this, via its RFC1918 egress
|
||||
# carve-out; compose has no equivalent.)
|
||||
#
|
||||
# (1) Host / cloud firewall (simplest, belt-and-suspenders for single-host):
|
||||
# Also drop egress to RFC1918 (10/8, 172.16/12, 192.168/16), link-local
|
||||
# (169.254/16, incl. the 169.254.169.254 metadata IP), and ULA on the
|
||||
# docsgpt-sandbox container's interface using iptables/nftables on the
|
||||
# Docker host. Example (host root):
|
||||
# SBX=$(docker inspect -f '{{.NetworkSettings.Networks.docsgpt-oss_sandbox-egress.IPAddress}}' docsgpt-sandbox)
|
||||
# iptables -I DOCKER-USER -s "$SBX" -d 169.254.0.0/16 -j DROP
|
||||
# iptables -I DOCKER-USER -s "$SBX" -d 10.0.0.0/8 -j DROP
|
||||
# iptables -I DOCKER-USER -s "$SBX" -d 172.16.0.0/12 -j DROP
|
||||
# iptables -I DOCKER-USER -s "$SBX" -d 192.168.0.0/16 -j DROP
|
||||
# (Allow established/return traffic and DNS as needed for your setup.)
|
||||
# MITIGATION -- required when enabling the sandbox (do the first, ideally both):
|
||||
# - Run the backend with real authentication (`AUTH_TYPE` != none / a real auth
|
||||
# provider) so a reachable API rejects unauthenticated requests. Without it,
|
||||
# runner->backend reach is a free control-plane bypass.
|
||||
# - Add a host-firewall DROP for runner->backend/worker on sandbox-net
|
||||
# (approach (1) below).
|
||||
#
|
||||
# Two layers below: (2) is what this overlay wires up (internet egress via the
|
||||
# deny-private proxy); (1) is the host-firewall DROP that closes the
|
||||
# runner->backend/worker gap. Apply both for the strongest posture.
|
||||
#
|
||||
# (1) Host-firewall DROP for runner->backend/worker (closes the gap above). Run
|
||||
# as root on the Docker host AFTER `... up`. The project name is pinned to
|
||||
# `docsgpt-oss` (see `name:` in docker-compose.yaml), so the shared control
|
||||
# net is `docsgpt-oss_sandbox-net`. `docker compose ... ps -q` resolves each
|
||||
# container id regardless of its generated name (there is no fixed
|
||||
# `container_name`), and the `index` function is REQUIRED because a
|
||||
# Go-template dotted key cannot contain hyphens -- the old
|
||||
# `{{.NetworkSettings.Networks.docsgpt-oss_sandbox-egress.IPAddress}}` form
|
||||
# never parsed. Both IPs are read on sandbox-net so source+dest match the
|
||||
# shared path:
|
||||
# CF="-f deployment/docker-compose.yaml -f deployment/optional/docker-compose.optional.sandbox-egress.yaml --profile sandbox"
|
||||
# NET=docsgpt-oss_sandbox-net
|
||||
# SBX=$(docker inspect -f "{{(index .NetworkSettings.Networks \"$NET\").IPAddress}}" "$(docker compose $CF ps -q docsgpt-sandbox)")
|
||||
# BE=$( docker inspect -f "{{(index .NetworkSettings.Networks \"$NET\").IPAddress}}" "$(docker compose $CF ps -q backend)")
|
||||
# WK=$( docker inspect -f "{{(index .NetworkSettings.Networks \"$NET\").IPAddress}}" "$(docker compose $CF ps -q worker)")
|
||||
# iptables -I DOCKER-USER -s "$SBX" -d "$BE" -j DROP # runner -> backend (incl. :7091)
|
||||
# iptables -I DOCKER-USER -s "$SBX" -d "$WK" -j DROP # runner -> worker
|
||||
# (These container-to-container DROPs require the host's
|
||||
# `bridge-nf-call-iptables=1`, Docker's default, so bridged traffic
|
||||
# traverses DOCKER-USER.) If a lookup is empty (renamed project, or the
|
||||
# container is not up yet), resolve by hand instead of running a broken
|
||||
# command: `docker compose $CF ps` to list ids, then `docker inspect
|
||||
# <runner-id>` / `<backend-id>`, read the sandbox-net
|
||||
# `.NetworkSettings.Networks.*.IPAddress`, and add the same DROP rules.
|
||||
# Re-run after any recreate -- container IPs are not stable across `up`.
|
||||
# (Internet / RFC1918 / metadata egress is already gone via the internal
|
||||
# flip, so no separate SSRF drop is needed here.)
|
||||
#
|
||||
# (2) Egress-gateway sidecar (this overlay): the runner has NO direct internet
|
||||
# route (see above); its only path out is the deny-private forward proxy.
|
||||
# Point the runner's HTTP(S) client at the proxy via the env vars below.
|
||||
# This does NOT stop runner->backend/worker on sandbox-net -- pair it with
|
||||
# backend auth and/or approach (1).
|
||||
#
|
||||
# Apply alongside the base stack:
|
||||
# docker compose -f deployment/docker-compose.yaml \
|
||||
@@ -43,11 +80,14 @@
|
||||
# (also works layered on docker-compose-hub.yaml / docker-compose-azure.yaml,
|
||||
# which share the same service/network names).
|
||||
#
|
||||
# NOTE: because `sandbox-egress` is internal here, non-HTTP raw egress is blocked
|
||||
# at L3 regardless of what the code does (there is simply no route). HTTP(S) that
|
||||
# honors the proxy env is filtered by the proxy ACL. For belt-and-suspenders on a
|
||||
# multi-tenant or untrusted deployment, also apply approach (1) or the Kubernetes
|
||||
# NetworkPolicy.
|
||||
# NOTE: because `sandbox-egress` is internal here, non-HTTP raw egress TO THE
|
||||
# INTERNET / HOST / RFC1918 / METADATA is blocked at L3 regardless of what the
|
||||
# code does (there is simply no route). HTTP(S) that honors the proxy env is
|
||||
# filtered by the proxy ACL. This does NOT block raw egress to `backend:7091` /
|
||||
# the worker on the shared `sandbox-net` (see WHAT THIS OVERLAY DOES NOT CONTAIN
|
||||
# / MITIGATION above): enable backend auth and/or apply approach (1). On a
|
||||
# multi-tenant or untrusted deployment, prefer the Kubernetes NetworkPolicy,
|
||||
# which blocks the internal path too.
|
||||
|
||||
services:
|
||||
# Forward proxy that denies private/link-local/metadata destinations and
|
||||
|
||||
Reference in new issue
Block a user