mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 07:17:26 +00:00
docs(security): document Docker UFW hardening via DOCKER-USER (#27613)
Merged via squash.
Prepared head SHA: 31ddd43326
Co-authored-by: dorukardahan <35905596+dorukardahan@users.noreply.github.com>
Co-authored-by: grp06 <1573959+grp06@users.noreply.github.com>
Reviewed-by: @grp06
This commit is contained in:
@@ -13,6 +13,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
- Docs/security hardening guidance: document Docker `DOCKER-USER` + UFW policy and add cross-linking from Docker install docs for VPS/public-host setups. (#27613) thanks @dorukardahan.
|
||||||
- Docs/tool-loop detection config keys: align `docs/tools/loop-detection.md` examples and field names with the current `tools.loopDetection` schema to prevent copy-paste validation failures from outdated keys. (#33182) Thanks @Mylszd.
|
- Docs/tool-loop detection config keys: align `docs/tools/loop-detection.md` examples and field names with the current `tools.loopDetection` schema to prevent copy-paste validation failures from outdated keys. (#33182) Thanks @Mylszd.
|
||||||
- Discord/inbound debouncer: skip bot-own MESSAGE_CREATE events before they reach the debounce queue to avoid self-triggered slowdowns in busy servers. Thanks @thewilloftheshadow.
|
- Discord/inbound debouncer: skip bot-own MESSAGE_CREATE events before they reach the debounce queue to avoid self-triggered slowdowns in busy servers. Thanks @thewilloftheshadow.
|
||||||
- Discord/Agent-scoped media roots: pass `mediaLocalRoots` through Discord monitor reply delivery (message + component interaction paths) so local media attachments honor per-agent workspace roots instead of falling back to default global roots. Thanks @thewilloftheshadow.
|
- Discord/Agent-scoped media roots: pass `mediaLocalRoots` through Discord monitor reply delivery (message + component interaction paths) so local media attachments honor per-agent workspace roots instead of falling back to default global roots. Thanks @thewilloftheshadow.
|
||||||
|
|||||||
@@ -630,7 +630,56 @@ Rules of thumb:
|
|||||||
- If you must bind to LAN, firewall the port to a tight allowlist of source IPs; do not port-forward it broadly.
|
- If you must bind to LAN, firewall the port to a tight allowlist of source IPs; do not port-forward it broadly.
|
||||||
- Never expose the Gateway unauthenticated on `0.0.0.0`.
|
- Never expose the Gateway unauthenticated on `0.0.0.0`.
|
||||||
|
|
||||||
### 0.4.1) mDNS/Bonjour discovery (information disclosure)
|
### 0.4.1) Docker port publishing + UFW (`DOCKER-USER`)
|
||||||
|
|
||||||
|
If you run OpenClaw with Docker on a VPS, remember that published container ports
|
||||||
|
(`-p HOST:CONTAINER` or Compose `ports:`) are routed through Docker's forwarding
|
||||||
|
chains, not only host `INPUT` rules.
|
||||||
|
|
||||||
|
To keep Docker traffic aligned with your firewall policy, enforce rules in
|
||||||
|
`DOCKER-USER` (this chain is evaluated before Docker's own accept rules).
|
||||||
|
On many modern distros, `iptables`/`ip6tables` use the `iptables-nft` frontend
|
||||||
|
and still apply these rules to the nftables backend.
|
||||||
|
|
||||||
|
Minimal allowlist example (IPv4):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# /etc/ufw/after.rules (append as its own *filter section)
|
||||||
|
*filter
|
||||||
|
:DOCKER-USER - [0:0]
|
||||||
|
-A DOCKER-USER -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
|
||||||
|
-A DOCKER-USER -s 127.0.0.0/8 -j RETURN
|
||||||
|
-A DOCKER-USER -s 10.0.0.0/8 -j RETURN
|
||||||
|
-A DOCKER-USER -s 172.16.0.0/12 -j RETURN
|
||||||
|
-A DOCKER-USER -s 192.168.0.0/16 -j RETURN
|
||||||
|
-A DOCKER-USER -s 100.64.0.0/10 -j RETURN
|
||||||
|
-A DOCKER-USER -p tcp --dport 80 -j RETURN
|
||||||
|
-A DOCKER-USER -p tcp --dport 443 -j RETURN
|
||||||
|
-A DOCKER-USER -m conntrack --ctstate NEW -j DROP
|
||||||
|
-A DOCKER-USER -j RETURN
|
||||||
|
COMMIT
|
||||||
|
```
|
||||||
|
|
||||||
|
IPv6 has separate tables. Add a matching policy in `/etc/ufw/after6.rules` if
|
||||||
|
Docker IPv6 is enabled.
|
||||||
|
|
||||||
|
Avoid hardcoding interface names like `eth0` in docs snippets. Interface names
|
||||||
|
vary across VPS images (`ens3`, `enp*`, etc.) and mismatches can accidentally
|
||||||
|
skip your deny rule.
|
||||||
|
|
||||||
|
Quick validation after reload:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ufw reload
|
||||||
|
iptables -S DOCKER-USER
|
||||||
|
ip6tables -S DOCKER-USER
|
||||||
|
nmap -sT -p 1-65535 <public-ip> --open
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected external ports should be only what you intentionally expose (for most
|
||||||
|
setups: SSH + your reverse proxy ports).
|
||||||
|
|
||||||
|
### 0.4.2) mDNS/Bonjour discovery (information disclosure)
|
||||||
|
|
||||||
The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353) for local device discovery. In full mode, this includes TXT records that may expose operational details:
|
The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353) for local device discovery. In full mode, this includes TXT records that may expose operational details:
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ Sandboxing details: [Sandboxing](/gateway/sandboxing)
|
|||||||
- Docker Desktop (or Docker Engine) + Docker Compose v2
|
- Docker Desktop (or Docker Engine) + Docker Compose v2
|
||||||
- At least 2 GB RAM for image build (`pnpm install` may be OOM-killed on 1 GB hosts with exit 137)
|
- At least 2 GB RAM for image build (`pnpm install` may be OOM-killed on 1 GB hosts with exit 137)
|
||||||
- Enough disk for images + logs
|
- Enough disk for images + logs
|
||||||
|
- If running on a VPS/public host, review
|
||||||
|
[Security hardening for network exposure](/gateway/security#04-network-exposure-bind--port--firewall),
|
||||||
|
especially Docker `DOCKER-USER` firewall policy.
|
||||||
|
|
||||||
## Containerized Gateway (Docker Compose)
|
## Containerized Gateway (Docker Compose)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user