feat(deployer): warn when userland-proxy masks attacker source IPs
MazeNET publishes gateway ports on the host via Docker. With the default userland-proxy enabled, attacker connections appear to originate from the bridge gateway instead of the real remote IP. Log a soft warning at deploy time when the topology publishes any ports and docker info reports UserlandProxy=true, pointing the operator at the daemon.json toggle. Best-effort: daemon talk failures silently no-op.
This commit is contained in:
@@ -311,6 +311,33 @@ def _topology_compose_path(topology_id: str) -> Path:
|
||||
return Path(f"decnet-topology-{topology_id[:8]}-compose.yml")
|
||||
|
||||
|
||||
def _warn_if_userland_proxy_enabled(hydrated: dict) -> None:
|
||||
"""Soft warning: docker-proxy masks attacker source IPs.
|
||||
|
||||
Only log if the topology will publish ports (gateway deckies with
|
||||
``forwards_l3=True``) — no point scaring operators on port-less
|
||||
topologies. Best-effort: any failure talking to the daemon is
|
||||
silently ignored.
|
||||
"""
|
||||
publishes = any(
|
||||
(d.get("decky_config") or {}).get("forwards_l3")
|
||||
for d in hydrated.get("deckies", [])
|
||||
)
|
||||
if not publishes:
|
||||
return
|
||||
try:
|
||||
info = docker.from_env().info()
|
||||
except Exception:
|
||||
return
|
||||
if info.get("UserlandProxy") or info.get("Userland Proxy"):
|
||||
log.warning(
|
||||
"[USERLAND_PROXY] docker-proxy is enabled; attacker source IPs "
|
||||
"will appear as the bridge gateway. Set "
|
||||
'"userland-proxy": false in /etc/docker/daemon.json to preserve '
|
||||
"real source IPs."
|
||||
)
|
||||
|
||||
|
||||
@_traced("engine.deploy_topology")
|
||||
async def deploy_topology(repo, topology_id: str, *, dry_run: bool = False) -> None:
|
||||
"""Deploy a persisted MazeNET topology.
|
||||
@@ -349,6 +376,8 @@ async def deploy_topology(repo, topology_id: str, *, dry_run: bool = False) -> N
|
||||
for w in check_no_host_port_collision(hydrated):
|
||||
log.warning("[%s] %s", w.code, w.message)
|
||||
|
||||
_warn_if_userland_proxy_enabled(hydrated)
|
||||
|
||||
await transition_status(repo, topology_id, TopologyStatus.DEPLOYING)
|
||||
|
||||
client = docker.from_env()
|
||||
|
||||
Reference in New Issue
Block a user