bubblewrap is a wonderful tool for creating sandboxes as an unprivileged user. Here’s some useful sandboxes that I regularly use.
Reading Mail in Isolation
#!/bin/sh
exec bwrap --unshare-user --unshare-ipc --unshare-pid --unshare-uts --unshare-cgroup \
--ro-bind /bin /bin \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--ro-bind /usr/bin /usr/bin \
--ro-bind /usr/lib /usr/lib \
--ro-bind /usr/share/terminfo /usr/share/terminfo \
--ro-bind /etc/passwd /etc/passwd \
--ro-bind $HOME/.muttrc $HOME/.muttrc \
--bind $HOME/.mutt_certificates $HOME/.mutt_certificates \
--bind $MAIL $MAIL \
--tmpfs /tmp \
mutt "$@"
Text-mode Web Browsing without Distractions
#!/bin/bash
exec bwrap --unshare-user --unshare-ipc --unshare-pid --unshare-uts --unshare-cgroup \
--ro-bind /bin /bin \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--ro-bind /usr/bin /usr/bin \
--ro-bind /usr/lib /usr/lib \
--ro-bind /usr/share/terminfo /usr/share/terminfo \
--ro-bind /etc/passwd /etc/passwd \
--ro-bind /etc/lynx /etc/lynx \
--ro-bind /etc/ssl/certs /etc/ssl/certs \
--ro-bind /usr/share/ca-certificates /usr/share/ca-certificates \
--bind $HOME/Downloads $HOME/Downloads \
--tmpfs /tmp \
lynx "$@"
Just Reading a PDF
#!/bin/sh
for last; do true; done
exec bwrap --unshare-all \
--ro-bind /lib /lib \
--ro-bind /bin /bin \
--ro-bind /lib64 /lib64 \
--ro-bind /usr/bin /usr/bin \
--ro-bind /usr/lib /usr/lib \
--ro-bind "$last" "$last" \
--bind /tmp /tmp \
--dev /dev \
--proc /proc \
--chdir / \
/usr/bin/mupdf "$@"
Sandboxing ssh Clients
#!/bin/bash
ssh=/usr/bin/ssh
ssh_auth_dir=$(dirname $SSH_AUTH_SOCK)
exec bwrap --unshare-user --unshare-ipc --unshare-pid --unshare-uts --unshare-cgroup \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--ro-bind /usr/lib /usr/lib \
--bind $HOME/.ssh/ $HOME/.ssh/ \
--ro-bind /etc/passwd /etc/passwd \
--ro-bind /bin/bash /bin/bash \
--bind $ssh_auth_dir $ssh_auth_dir \
--bind $ssh $ssh \
--dev /dev \
$ssh "$@"
The Private Crypto Vault
#!/bin/bash
NAME=vault
function cleanup {
echo closing the $NAME..
sudo /sbin/cryptsetup close $NAME
}
trap cleanup EXIT
sudo /sbin/cryptsetup open /root/$NAME.fs $NAME && \
sudo fsck /dev/mapper/$NAME && \
sudo unshare --mount --ipc --net sudo /bin/sh -c "mount $HOME/mnt && sudo -u $USER $SHELL"
The Development Idyll
Name the script dev, then usage:
$ dev go
$ go get evilscript # this will fail, no network
#!/bin/bash
CMD=$SHELL
NET="--unshare-net --ro-bind /etc/resolv.conf /etc/resolv.conf"
EXTRA=""
CONFIGS=".bashrc .tmux.conf .vimrc .vim .ipython .jupyter .gitconfig"
HOST=dev
for opt in "$@"; do
case $opt in
net)
NET=""
EXTRA="$EXTRA --bind /etc/ssl/certs /etc/ssl/certs"
HOST="$HOST-net"
;;
ssh*)
NET=""
key=$(echo $opt | sed -e 's/ssh.//')
EXTRA="$EXTRA --bind $SSH_AUTH_SOCK $SSH_AUTH_SOCK"
EXTRA="$EXTRA --bind $HOME/.ssh/config $HOME/.ssh/config"
EXTRA="$EXTRA --bind $HOME/.ssh/known_hosts $HOME/.ssh/known_hosts"
if [ -n "$key" ]; then
EXTRA="$EXTRA --bind $HOME/.ssh/id_$key $HOME/.ssh/id_$key"
EXTRA="$EXTRA --bind $HOME/.ssh/id_$key.pub $HOME/.ssh/id_$key.pub"
HOST="$HOST-ssh2$key"
else
HOST="$HOST-ssh"
fi
;;
web)
EXTRA="$EXTRA --bind $HOME/web $HOME/web"
CONFIGS="$CONFIGS .linkchecker"
HOST="$HOST-web"
;;
src)
EXTRA="$EXTRA --bind $HOME/src $HOME/src"
HOST="$HOST-src"
;;
cwd)
EXTRA="$EXTRA --bind $PWD $PWD"
;;
py)
EXTRA="$EXTRA --bind $HOME/.local $HOME/.local"
HOST="$HOST-py"
;;
go)
EXTRA="$EXTRA --bind $GOPATH $GOPATH"
HOST="$HOST-go"
;;
*)
cat <<EOF 2>&1
usage: $0 mode1 mode2 ... modeN
mode is one of:
* net
enable network + share public ssl certs
* web
share web directory
* src
share src directory
* cwd
share current working directory
* py
share python stuff
* ssh=keyname
where keyname exists as .ssh/id_keyname*
implies enabling network
EOF
exit 1
;;
esac
done
for config in $CONFIGS; do
CONFIG="$CONFIG --ro-bind $HOME/$config $HOME/$config"
done
exec bwrap \
--unshare-user \
--unshare-ipc \
--unshare-pid \
$NET \
--unshare-uts \
--unshare-cgroup \
--hostname $HOST.home \
--proc /proc \
--dev /dev \
--tmpfs /tmp \
--ro-bind /bin /bin \
--ro-bind /usr /usr \
--ro-bind /lib /lib \
--ro-bind /lib64 /lib64 \
--ro-bind /sbin /sbin \
--ro-bind /etc/passwd /etc/passwd \
--ro-bind /etc/group /etc/group \
--ro-bind /etc/alternatives /etc/alternatives \
$CONFIG \
$EXTRA \
$CMD