Skip to content

Commit 4ce93e3

Browse files
committed
feat: add -N flag to run inside an existing named network namespace
Adds a -N NAME option that launches the wrapped program inside a pre-existing Linux network namespace (e.g. one set up by the new netns-sandbox.sh, which routes all traffic through a WireGuard VPN). Unlike -n, which only unshares/shares the host net, -N keeps the target namespace's network so the sandboxed process inherits the namespace's routing, firewall, and VPN-provided DNS. To enter it, wrap prefixes the launch with 'sudo ip netns exec NAME sudo -u $USER', dropping back to the invoking user before exec'ing bwrap. Because the process lives in the namespace's net, -N must not unshare net: it sets unshare_all=0 and explicitly unshares everything else (ipc, pid, uts, plus user/cgroup best-effort), mirroring the default set minus net. It also implies the network binds (resolv.conf, ssl) so DNS and TLS work, relying on the kernel exposing /etc/netns/NAME/resolv.conf as /etc/resolv.conf inside the namespace. Documents the flag under ADVANCED OPTIONS in usage and README.
1 parent 335de9d commit 4ce93e3

2 files changed

Lines changed: 45 additions & 4 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ By default, Nixwrap will:
7676
#### Advanced Options
7777

7878
```
79+
-N NAME Run inside the existing named network namespace NAME. The namespace
80+
must already exist (e.g. created by netns-sandbox.sh). wrap enters it
81+
via 'sudo ip netns exec NAME' and drops back to the current user
82+
before launching. This keeps the namespace's network instead of
83+
unsharing net, and implies network access (-n) so DNS and TLS work.
7984
-p Do not share current working directory. By default wrap will share
8085
the current working directory as a write mount and cd into it
8186
before running the program. With this option, wrap will not share

wrap.sh

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,13 @@ OPTIONS:
140140
-v Verbose output for debugging.
141141
142142
ADVANCED OPTIONS:
143-
-p Do not share current working directory. By default wrap will share
144-
the current working directory as a write mount and cd into it
143+
-N NAME Run inside the existing named network namespace NAME. The namespace
144+
must already exist (e.g. created by netns-sandbox.sh). wrap enters it
145+
via 'sudo ip netns exec NAME' and drops back to the current user
146+
before launching. This keeps the namespace's network instead of
147+
unsharing net, and implies network access (-n) so DNS and TLS work.
148+
-p Do not share current working directory. By default wrap will share
149+
the current working directory as a write mount and cd into it
145150
before running the program. With this option, wrap will not share
146151
the directory and leave the current directory untouched.
147152
-f Force share current working directory. By default wrap will share
@@ -173,8 +178,9 @@ fi
173178
unshare_all=1
174179
share_cwd=1
175180
force_share_cwd=0
181+
netns=""
176182

177-
while getopts "r:w:e:abcdfhmnpuv" opt; do
183+
while getopts "r:w:e:N:abcdfhmnpuv" opt; do
178184
case "$opt" in
179185

180186
# bind / mount a path readonly in sandbox to the same path as host
@@ -270,6 +276,28 @@ while getopts "r:w:e:abcdfhmnpuv" opt; do
270276
bwrap_opts+=(--ro-bind /etc/static/ssl /etc/static/ssl)
271277
;;
272278

279+
# run inside an existing named network namespace (see netns-sandbox.sh).
280+
# the namespace must already exist; wrap will enter it via
281+
# `sudo ip netns exec NAME` before launching bwrap, dropping back to the
282+
# current user. this keeps the namespace's network (instead of unsharing
283+
# net) and implies network access (-n) so that DNS and TLS work.
284+
N)
285+
netns="$OPTARG"
286+
287+
# keep the netns' network instead of unsharing net, but still unshare
288+
# everything else (mirrors the explicit set documented for -m, minus net)
289+
unshare_all=0
290+
bwrap_opts+=(--unshare-ipc --unshare-pid --unshare-uts)
291+
bwrap_opts+=(--unshare-user-try --unshare-cgroup-try)
292+
bwrap_opts+=(--share-net)
293+
294+
# imply network access binds so resolv.conf / TLS work inside the netns.
295+
# the kernel exposes /etc/netns/NAME/resolv.conf as /etc/resolv.conf here.
296+
bwrap_opts+=(--ro-bind /etc/resolv.conf /etc/resolv.conf)
297+
bwrap_opts+=(--ro-bind /etc/ssl /etc/ssl)
298+
bwrap_opts+=(--ro-bind /etc/static/ssl /etc/static/ssl)
299+
;;
300+
273301
# grant audio access
274302
a)
275303
bwrap_opts+=(--bind-try "$XDG_RUNTIME_DIR/pulse/native" "$XDG_RUNTIME_DIR/pulse/native")
@@ -383,7 +411,15 @@ for e in "${env_vars[@]}"; do
383411
fi
384412
done
385413

386-
exec bwrap \
414+
# when running inside a named network namespace, enter it via
415+
# `sudo ip netns exec NAME` and drop back to the current user before bwrap.
416+
# otherwise the prefix is empty and bwrap runs directly as today.
417+
netns_prefix=()
418+
if [[ -n "$netns" ]]; then
419+
netns_prefix=(sudo ip netns exec "$netns" sudo -u "$USER")
420+
fi
421+
422+
exec "${netns_prefix[@]}" bwrap \
387423
--chdir "$bwrap_chdir" \
388424
--clearenv \
389425
--dev /dev \

0 commit comments

Comments
 (0)