You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<p>Droidspaces supports three networking modes that determine whether a network namespace (<code>CLONE_NEWNET</code>) is used:</p>
418
+
<p>Droidspaces supports four networking modes that determine whether a network namespace (<code>CLONE_NEWNET</code>) is used:</p>
419
419
<ol>
420
420
<li><strong>Host Mode (<code>--net=host</code>) - Default</strong>: Droidspaces deliberately does <strong>not</strong> unshare the network namespace. The container shares the host's network stack. This greatly simplifies setup: containers get internet access immediately without virtual bridges, NAT, or firewall rules. On Android, where networking is already complex (cellular, Wi-Fi, VPN), this avoids a whole category of connectivity issues.
421
421
</li>
422
-
<li><strong>NAT Mode (<code>--net=nat</code>)</strong>: The container is placed in a private network namespace. It is connected to the host via a virtual bridge or veth pair, providing <strong>Pure Network Isolation</strong> while maintaining internet access through the host's active internet uplink, which is detected automatically. Compatible with the vast majority of Android devices.
422
+
<li><strong>NAT Mode (<code>--net=nat</code>)</strong>: The container is placed in a private network namespace. It is connected to the host via a virtual bridge or veth pair, providing <strong>Pure Network Isolation</strong> while maintaining internet access through the host's active internet uplink, which is detected automatically (or pinned manually with <code>--upstream</code>, see below). Compatible with the vast majority of Android devices.
423
423
</li>
424
424
<li><strong>None Mode (<code>--net=none</code>)</strong>: The container is placed in a private, air-gapped network namespace with only the loopback interface enabled for maximum security.
425
425
</li>
426
+
<li><strong>Gateway Mode (<code>--net=gateway</code>)</strong>: The container's LAN is delegated to <em>another</em> running container (typically OpenWRT). Droidspaces does only the L2 plumbing (bridge + veth pairs) and lets the gateway container own all policy - DHCP, DNS, firewall, routing, VPN. Ideal for VPN killswitches, segmented LANs, and traffic analysis. See the dedicated <ahref="networking-from-zero.html" rel="noopener noreferrer">Networking From Zero</a> guide for the full deep dive.
427
+
</li>
426
428
</ol>
427
429
<h3id="how-it-compares-to-chroot">How It Compares to Chroot</h3>
428
430
<p>A <code>chroot</code> only changes the apparent root directory for a process. It provides no process isolation, no mount isolation, no hostname isolation, and no IPC isolation. Any process inside a chroot shares the host's PID space, can see and signal other processes, and cannot run an init system like systemd.</p>
<p>Droidspaces validates bind mount targets with two protections: 1. <strong>Pre-mount:</strong> Uses <code>lstat()</code> to ensure the target inside the rootfs is not a symlink 2. <strong>Post-mount:</strong> Uses <code>realpath()</code> via the <code>is_subpath()</code> helper to verify the mounted path cannot escape the container root</p>
<p>The container shares the host's network namespace. - <strong>Pros</strong>: Zero configuration, instant internet access, works with all Android VPNs/hotspots. - <strong>Cons</strong>: No port isolation; services inside the container bind to host ports directly.</p>
<p>The container is placed in a private network namespace (<code>CLONE_NEWNET</code>) and connected to the host via a virtual bridge (<code>ds-br0</code>) or a direct veth pair. - <strong>Deterministic IP</strong>: Each container is assigned a unique IP in the <code>172.28.0.0/16</code> range, derived from its PID. - <strong>Embedded DHCP</strong>: Droidspaces includes a minimal, built-in DHCP server to automatically configure the container's <code>eth0</code>. - <strong>Pure Isolation</strong>: The container cannot see or interact with the host's network interfaces directly. - <strong>Automatic Uplink Detection</strong>: No configuration needed. Droidspaces reads the kernel's own ground truth to find the interface that provides internet access - on Android, the policy-routing rule netd installs for the active default network; on standard Linux, the main routing table's default route. CLAT (464xlat) interfaces on IPv6-only mobile networks are handled automatically.</p>
610
612
<divclass="callout callout-important"><strongclass="callout-title">IMPORTANT</strong> NAT mode is <strong>IPv4 only</strong>. If the host's uplink lacks an IPv4 address (IPv6-only network), internet access will not work. See <ahref="troubleshooting.html#ipv4-quirks" rel="noopener noreferrer">IPv4 NAT Quirks</a> for a workaround.</div>
<p>The container gets a private network namespace with only the loopback (<code>lo</code>) interface enabled. - <strong>Use Case</strong>: Maximum security for offline tasks.</p>
<p>The container is placed on an isolated L2 bridge whose <strong>policy is owned by another running container</strong> (typically OpenWRT) instead of by Droidspaces. Droidspaces does only the plumbing - it creates the bridge and the veth pairs and moves them into place; the gateway container provides DHCP, DNS, firewall, routing and VPN. - <strong>Required flag</strong>: <code>--gateway=NAME</code> names the running container that acts as the router. - <strong>Segments</strong>: <code>--gateway-net=NAME</code> (default <code>lan</code>) selects which bridge/segment the client lands on. Multiple clients sharing a <code>--gateway-net</code> share a LAN; different <code>--gateway-net</code> values are isolated segments through the same gateway. - <strong>Interface naming</strong>: <code>--gateway-iface=IFACE</code> (default <code>eth1</code>) controls what the LAN interface is called <em>inside</em> the gateway container, so it matches the gateway's own config. - <strong>Self-healing</strong>: wiring is driven entirely from the host side, so clients are (re)wired automatically when the gateway container starts or reboots - no client restart needed. - <strong>Use Cases</strong>: VPN killswitch for selected containers, VLAN-style segmented LANs, single-chokepoint traffic analysis, gateway-wide DNS filtering. See <ahref="networking-from-zero.html" rel="noopener noreferrer">Networking From Zero</a> for the complete walkthrough.</p>
<p>In NAT mode, you can expose container services to the host or local network using the <code>--port</code> flag. Supported formats:</p>
615
619
<divclass="code-block"><buttonclass="copy-btn" onclick="copyCode(this)"><iclass="fa-regular fa-copy"></i> Copy</button><pre><code># Forward host port 8080 to container port 80
<p>Forwarded ports are reachable from any network the host belongs to - including clients connected to the phone's own hotspot or USB tethering on Android.</p>
<p>On Android, the connection often hops between Wi-Fi and Mobile Data. Droidspaces includes a <strong>Route Monitor</strong> that subscribes to kernel routing events (FIB rules, routes, links, addresses). The moment Android switches its default network (e.g., you walk out of Wi-Fi range), the monitor updates the kernel's policy routing to keep the container connected - no configuration, no restart.</p>
633
+
<p>On Android, the connection often hops between Wi-Fi and Mobile Data. Droidspaces includes a <strong>Route Monitor</strong> that subscribes to kernel routing events (FIB rules, routes, links, addresses). The moment Android switches its default network (e.g., you walk out of Wi-Fi range), the monitor updates the kernel's policy routing to keep the container connected - no configuration, no restart. The same monitor works on desktop Linux (e.g. a Wi-Fi to ethernet handoff), where it follows the main routing table's default route.</p>
<p>By default the uplink is fully automatic. When you want the container's WAN to <strong>ignore the host's active network</strong> and go out through a specific interface instead, pin it with <code>--upstream</code>. This switches auto-detection off entirely - the listed interface(s) become the <em>only</em> WAN candidates.</p>
636
+
<divclass="code-block"><buttonclass="copy-btn" onclick="copyCode(this)"><iclass="fa-regular fa-copy"></i> Copy</button><pre><code># Single interface
637
+
--upstream=wlan0
638
+
639
+
# Priority-ordered list with wildcards (comma-separated)
640
+
--upstream=wlan0,rmnet*
641
+
</code></pre></div>
642
+
<ul>
643
+
<li><strong>Authoritative, not a fallback</strong>: traffic never hops to whatever <code>netd</code> marks active - only to interfaces you listed.
644
+
</li>
645
+
<li>**Priority failover <em>within</em> the list**: the Route Monitor re-resolves on every link/route change and uses the first listed interface that is up and has internet. <code>wlan0,rmnet*</code> prefers Wi-Fi and falls back to mobile data, then back to Wi-Fi when it returns.
646
+
</li>
647
+
<li><strong>Literals and wildcards</strong> (<code>*</code>, <code>?</code>): use <code>rmnet*</code> for mobile data, whose interface number is not stable across reconnects.
648
+
</li>
649
+
<li><strong>Disappear/reappear</strong> mid-session is handled: no WAN until a pinned interface is up, then it wires automatically.
650
+
</li>
651
+
<li><strong>Use cases</strong>: pin <code>tun0</code> to route the container exclusively through a phone-side VPN (a free killswitch), or pin <code>rmnet*</code> (with "Mobile data always active") to keep the container on cellular while the phone stays on Wi-Fi.
652
+
</li>
653
+
</ul>
654
+
<blockquote><p><code>--upstream</code> is only valid with <code>--net=nat</code>; it is ignored (with a warning) in other modes.</p></blockquote>
<tr><td><code>--net=MODE</code></td><td></td><td>Networking mode: <code>host</code> (default), <code>nat</code>, or <code>none</code>.</td></tr>
482
+
<tr><td><code>--net=MODE</code></td><td></td><td>Networking mode: <code>host</code> (default), <code>nat</code>, <code>none</code>, or <code>gateway</code>.</td></tr>
483
+
<tr><td><code>--upstream=IFACE</code></td><td></td><td>Pin the NAT WAN to specific interface(s); disables automatic uplink detection. Comma-separated, priority-ordered, supports wildcards. Example: <code>--upstream=wlan0,rmnet*</code>. NAT mode only.</td></tr>
483
484
<tr><td><code>--port HOST:CONT[/proto]</code></td><td></td><td>Forward host port to container (NAT mode). Supports TCP/UDP.</td></tr>
484
485
<tr><td><code>--dns=SERVERS</code></td><td><code>-d</code></td><td>Custom DNS servers, comma-separated. Example: <code>--dns=1.1.1.1,8.8.8.8</code></td></tr>
485
486
<tr><td><code>--disable-ipv6</code></td><td></td><td>Disable IPv6 networking support (Host mode only).</td></tr>
486
487
</tbody>
487
488
</table></div>
489
+
<h4id="gateway-mode">Gateway Mode</h4>
490
+
<p>Delegate a container's LAN to another running container (e.g. OpenWRT), which then owns DHCP, DNS, firewall and routing. Droidspaces only does the L2 plumbing. See <ahref="networking-from-zero.html" rel="noopener noreferrer">Networking From Zero</a> for the full guide.</p>
<tr><td><code>--gateway=NAME</code></td><td></td><td><strong>Required</strong> for <code>--net=gateway</code>. The running container that acts as the router.</td></tr>
497
+
<tr><td><code>--gateway-net=NAME</code></td><td></td><td>LAN segment name / host bridge suffix (default: <code>lan</code>). Clients sharing a value share a LAN; different values are isolated segments.</td></tr>
498
+
<tr><td><code>--gateway-iface=IFACE</code></td><td></td><td>Interface name as seen <em>inside</em> the gateway container (default: <code>eth1</code>). Each segment needs a unique name.</td></tr>
499
+
<tr><td><code>--gateway-bridge=BR</code></td><td></td><td>Override the host bridge name (default: <code>ds-{gateway-net}</code>).</td></tr>
500
+
</tbody>
501
+
</table></div>
488
502
<h3id="feature-flags">Feature Flags</h3>
489
503
<divclass="table-wrap"><table>
490
504
<thead>
@@ -596,6 +610,23 @@ <h3 id="nat-isolation-with-port-forwarding">NAT Isolation with Port Forwarding</
596
610
--port=8080:80 \
597
611
start
598
612
</code></pre></div>
613
+
<h3id="nat-with-a-pinned-uplink">NAT with a Pinned Uplink</h3>
614
+
<p>Force the container's internet out through a specific interface instead of following the host's active network. Pin a VPN tunnel (<code>tun0</code>) as a killswitch, or <code>rmnet*</code> to stay on mobile data while the phone uses Wi-Fi:</p>
0 commit comments