#!/bin/sh # this script creates a restricted user # with access to only certain Binaries # and browser filters to pretect against # malware and adult content # run as root or with doas/sudo set -e printf "Enter a username for the restricted user: " read -r USER if [ -z "$USER" ]; then echo "Error: Username cannot be empty." exit 1 fi if id "$USER" >/dev/null 2>&1; then echo "Error: User '$USER' already exists." exit 1 fi echo "" echo "==========================================" echo " Select a shell for the restricted user" echo " (zsh recommended for best restrictions)" echo "==========================================" SHELL_LIST="" i=1 for shell in zsh bash fish ksh tcsh dash sh; do if command -v "$shell" >/dev/null 2>&1; then if [ "$shell" = "zsh" ]; then printf " [%d] %s (recommended)\n" "$i" "$shell" else printf " [%d] %s\n" "$i" "$shell" fi SHELL_LIST="$SHELL_LIST $shell" i=$((i + 1)) fi done echo "" printf "Enter the number of your choice (default: zsh): " read -r SHELL_CHOICE if [ -z "$SHELL_CHOICE" ]; then CHOSEN_SHELL=$(command -v zsh) else i=1 for shell in $SHELL_LIST; do if [ "$i" = "$SHELL_CHOICE" ]; then CHOSEN_SHELL=$(command -v "$shell") fi i=$((i + 1)) done fi if [ -z "$CHOSEN_SHELL" ]; then echo "Error: Could not resolve selected shell." exit 1 fi echo " Using shell: $CHOSEN_SHELL" echo "" HOME_DIR=/home/$USER BIN_DIR=$HOME_DIR/.local/bin CONFIG_DIR=$HOME_DIR/.config/zsh PROFILE_DIR=$HOME_DIR/.config/shell CANDIDATES_SAFE="firefox chromium firefox-esr chromium-browser google-chrome brave-browser \ vlc mpv mplayer celluloid haruna totem rhythmbox \ gimp inkscape krita darktable rawtherapee shotwell digikam \ libreoffice soffice abiword gnumeric scribus \ kdenlive obs shotcut openshot pitivi handbrake \ blender freecad openscad librecad \ audacity ardour lmms hydrogen musescore \ transmission qbittorrent deluge nicotine \ discord telegram-desktop signal-desktop element-desktop \ thunderbird evolution geary claws-mail \ steam lutris heroic bottles \ code vscodium gedit mousepad kate geany \ filezilla remmina vinagre \ nitrogen feh variety \ calibre foliate evince okular zathura mupdf \ spotify strawberry clementine \ keepassxc bitwarden \ gnome-calculator kcalc \ eog shotwell gthumb nomacs \ nemo nautilus thunar dolphin pcmanfm \ cheese webcamoid simplescreenrecorder flameshot scrot \ yt-dlp youtube-dl \ gparted gnome-disks baobab \ ls cat touch grep zip unzip neofetch screenfetch \ xrandr arandr pavucontrol alsamixer \ htop btop" CANDIDATES_RISKY="vim neovim emacs nano ed \ python3 python ruby perl lua node \ bash sh fish ksh \ screen tmux \ curl wget \ git \ ssh \ find \ awk sed \ tar gzip bzip2 \ gcc g++ make \ gdb strace \ nmap netcat socat \ rsync \ xterm alacritty kitty konsole tilix terminator \ at cron \ base64 xxd \ openssl gpg \ ranger nnn" BLOCK="su sudo doas pkexec polkit \ nsenter unshare chroot \ mount umount \ passwd chpasswd chsh \ newgrp sg \ insmod rmmod modprobe \ docker podman lxc \ systemctl service \ chmod chown chattr \ dd install \ ldconfig \ fdisk parted \ sv vsv svstat svok svc \ runsvdir runsv chpst \ runit runit-init \ halt poweroff reboot shutdown \ loginctl \ wall write mesg" echo "Scanning for installed programs..." echo "" INSTALLED_SAFE="" for bin in $CANDIDATES_SAFE; do if command -v "$bin" >/dev/null 2>&1; then INSTALLED_SAFE="$INSTALLED_SAFE $bin" fi done INSTALLED_RISKY="" for bin in $CANDIDATES_RISKY; do if command -v "$bin" >/dev/null 2>&1; then INSTALLED_RISKY="$INSTALLED_RISKY $bin" fi done echo "==========================================" echo " Safe Programs" echo "==========================================" i=1 for bin in $INSTALLED_SAFE; do printf " [%d] %s\n" "$i" "$bin" i=$((i + 1)) done echo "" echo "Enter the numbers of the programs to allow," echo "separated by spaces (e.g. 1 3 5):" printf "> " read -r CHOICES_SAFE SELECTED="" for choice in $CHOICES_SAFE; do i=1 for bin in $INSTALLED_SAFE; do if [ "$i" = "$choice" ]; then SELECTED="$SELECTED $bin" fi i=$((i + 1)) done done echo "" echo "==========================================" echo " Elevated Risk Programs" echo " WARNING: These programs have known shell" echo " escape vectors and could allow the user" echo " to bypass restrictions. Only allow if" echo " you understand and accept the risk." echo "==========================================" i=1 for bin in $INSTALLED_RISKY; do printf " [%d] %s\n" "$i" "$bin" i=$((i + 1)) done echo "" echo "Enter the numbers of the risky programs to allow," echo "or press Enter to skip all:" printf "> " read -r CHOICES_RISKY for choice in $CHOICES_RISKY; do i=1 for bin in $INSTALLED_RISKY; do if [ "$i" = "$choice" ]; then SELECTED="$SELECTED $bin" fi i=$((i + 1)) done done if [ -z "$SELECTED" ]; then echo "Error: No programs selected." exit 1 fi echo "" echo "Selected programs: $SELECTED" echo "" LOCK_FIREFOX=0 LOCK_CHROMIUM=0 for bin in $SELECTED; do if [ "$bin" = "firefox" ] || [ "$bin" = "firefox-esr" ]; then printf "Lock down Firefox with family-safe DNS and restricted settings? [y/N]: " read -r LOCK_FF case "$LOCK_FF" in y|Y) LOCK_FIREFOX=1 ;; esac fi if [ "$bin" = "chromium" ] || [ "$bin" = "chromium-browser" ] || [ "$bin" = "google-chrome" ] || [ "$bin" = "brave-browser" ]; then printf "Lock down Chromium/Chrome with family-safe DNS and restricted settings? [y/N]: " read -r LOCK_CH case "$LOCK_CH" in y|Y) LOCK_CHROMIUM=1 ;; esac fi done echo "Creating user '$USER'..." useradd -m -s "$CHOSEN_SHELL" "$USER" passwd "$USER" chown root:"$USER" "$HOME_DIR" chmod 750 "$HOME_DIR" mkdir -p "$BIN_DIR" "$CONFIG_DIR" "$PROFILE_DIR" mkdir -p "$HOME_DIR/Downloads" "$HOME_DIR/Documents" chown "$USER":"$USER" "$HOME_DIR/Downloads" "$HOME_DIR/Documents" chmod 700 "$HOME_DIR/Downloads" "$HOME_DIR/Documents" SHELL_NAME=$(basename "$CHOSEN_SHELL") case "$SHELL_NAME" in zsh) RCFILE="$CONFIG_DIR/.zshrc" cat > "$RCFILE" < "$RCFILE" < "$RCFILE" < "$RCFILE" </dev/null) if [ -n "$BIN_PATH" ]; then ln -s "$BIN_PATH" "$BIN_DIR/$bin" echo " Linked: $bin" fi done echo "" echo "Enforcing blocks..." for bin in $BLOCK; do rm -f "$BIN_DIR/$bin" done if [ -f /etc/doas.conf ]; then sed -i "1s/^/deny $USER\n/" /etc/doas.conf fi if [ -f /etc/pam.d/su ]; then sed -i '1s/^/auth required pam_wheel.so use_uid\n/' /etc/pam.d/su fi if [ "$LOCK_FIREFOX" = "1" ]; then echo "" echo "Applying Firefox lockdown policy..." mkdir -p /usr/lib/firefox/distribution cat > /usr/lib/firefox/distribution/policies.json < /etc/chromium/policies/managed/restricted.json <