Last active
April 17, 2016 10:29
-
-
Save kriswebdev/de1fc97a508d04563d7a to your computer and use it in GitHub Desktop.
Vuze Private Profile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# === INFO === | |
# Vuze Private Profile (LINUX) | |
# Author: KrisWebDev | |
# Version: 1.1.1 | |
# Description: Switch Vuze to a private profile, where downloaded files and settings are stored in a password-protected encrypted directory. | |
# Warnings: This app only provides PARTIAL LOCAL security, and DOESN'T provide anonymity over the network! It does NOT replace a proxy/VPN/ToR! | |
# Encrypted filesystem (encfs) is easy to use but it DOESN'T provide "plausible deniability". | |
# It is recommended to manually disable Vuze UPnP plugin in the private profile. | |
# Requirements: Linux (only tested on Ubuntu with bash) | |
# encfs (sudo apt-get install encfs) | |
# Vuze 5.7.1.0 and above (bugfix to open .torrent files) | |
# Uninstall Vuze | |
# Reinstall Vuze manually: | |
# https://wiki.vuze.com/w/Initial_Setup_Guide#Manual_install_from_Vuze_website | |
# Then go in Vuze > Help > "Join Beta Program" then "Check for Updates" | |
# Additional Requirements for hidden mode: | |
# screen, mkpasswd (sudo apt-get install screen whois) | |
# Vuze must be able to find log4j.jar & commons-cli.jar. For manual install, put these in Azureus2.jar folder: http://svn.vuze.com/public/client/trunk/uis/lib/ | |
# === LICENSE === | |
# This program is free software: you can redistribute it and/or modify | |
# it under the terms of the GNU General Public License as published by | |
# the Free Software Foundation, either version 3 of the License, or | |
# (at your option) any later version. | |
# | |
# This program is distributed in the hope that it will be useful, | |
# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
# GNU General Public License for more details. | |
# | |
# You should have received a copy of the GNU General Public License | |
# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
# === CONFIGURATION === | |
# Crypted dir (download content, torrent files and private settings): | |
CRYPTED_DIR=$(xdg-user-dir DOWNLOAD)"/vuze-crypt" | |
# Virtual mount point (unencrypted view of crypted dir): | |
# Note: It is recommended to use a leading dot for the mount name, | |
# to consider it as hidden by the system. | |
# Don't change this after initial run! If you do, use a new empty CRYPTED_DIR or manually change all Vuze Options > Files > * path. | |
MOUNT_DIR=$(xdg-user-dir DOWNLOAD)"/.vuze-private" | |
# Optional *SUB*directory for the complete files, with trailing slash. | |
MOUNT_COMPLETE_SUBDIR="/complete" | |
# Where is your Vuze startup script? | |
# It's the "azureus" or "vuze" executable file, the *REAL* one with java or run_java statement inside, not a redirect | |
VUZE_STARTUP_SCRIPT="/usr/bin/azureus" | |
# Accelerate Vuze damn slow UI (true/false) | |
OPENGL_ACCELERATION=true | |
# Advanced configuration, avoid changing this. | |
# Path to existing Vuze public configuration: | |
VUZE_PUBLIC_CONF=~/".azureus" | |
# If anything ain't working, enable this | |
DEBUG=false | |
# === CODE === | |
me=`basename "$0"` | |
# DON'T move it outside $MOUNT_DIR ! | |
VUZE_PRIVATE_CONF="$MOUNT_DIR/.azureus-private" | |
VUZE_X_JAVA_ARGS="" | |
VUZE_X_JAVA_ARGS_COMP="" | |
RUN_VUZE_BACKGROUND=true | |
start_vuze_private() { | |
if [ "$OPENGL_ACCELERATION" = true ]; then | |
VUZE_X_JAVA_ARGS="-Dsun.java2d.opengl=true" | |
fi | |
# As the startup script pass arguments to Vuze and not Java, we need to rewrite it | |
launcher_script_public=$(< "$VUZE_STARTUP_SCRIPT") | |
cd "$(dirname "$VUZE_STARTUP_SCRIPT")" | |
# Script is maybe a redirect. Let's try to find the real vuze launch script | |
if [[ "$launcher_script_public" != *"-Dazureus.install.path"* ]]; then | |
real_script_path=$(sed -n -e 's/^\s*["'\'']\?\(.\+\(vuze\|azureus\)\)["'\'']\?\s*"\?\$@\?"\?\s*$/\1/p' -e '//q' "$VUZE_STARTUP_SCRIPT") | |
if [ -z "$real_script_path" ]; then | |
real_script_path=$(sed -n -e 's/^\s*["'\'']\?\(.\+\(vuze\|azureus\)\)["'\'']\?\s*"\?\$@\?"\?\s*$/\1/p' -e '//q' /usr/bin/vuze) | |
VUZE_STARTUP_SCRIPT="/usr/bin/vuze" | |
fi | |
if [ -z "$real_script_path" ]; then | |
real_script_path=$(sed -n -e 's/^\s*["'\'']\?\(.\+\(vuze\|azureus\)\)["'\'']\?\s*"\?\$@\?"\?\s*$/\1/p' -e '//q' /usr/bin/azureus) | |
VUZE_STARTUP_SCRIPT="/usr/bin/azureus" | |
fi | |
if [ ! -z "$real_script_path" ]; then | |
# Unescape | |
real_script_path=$(echo "$real_script_path" | sed -r 's/\\(.)/\1/g') | |
echo "VUZE_STARTUP_SCRIPT (${VUZE_STARTUP_SCRIPT}) is a redirect." | |
echo "Real Vuze launch script found at: \"${real_script_path}\"" | |
launcher_script_public=$(< "${real_script_path}") | |
cd "$(dirname "${real_script_path}")" | |
fi | |
fi | |
if [[ "$launcher_script_public" == *"-Dazureus.install.path"* ]]; then | |
# Append java args | |
launcher_script_private=${launcher_script_public//-Dazureus.install.path/-Dazureus.config.path=\"\$\{VUZE_PRIVATE_CONF\}\" "\$VUZE_X_JAVA_ARGS" "\$VUZE_X_JAVA_ARGS_COMP" -Dazureus.install.path} | |
if [[ "$@" == *"--ui=console"* ]]; then | |
echo "Using console UI in foreground." | |
launcher_script_private=${launcher_script_private//org.gudy.azureus2.ui.swt.Main/org.gudy.azureus2.ui.common.Main} | |
eval "$launcher_script_private" | |
fusermount -u "$MOUNT_DIR" # Soft unmount after Vuze closure | |
else | |
# Debug: | |
# eval "$launcher_script_private" & | |
if [ "$RUN_VUZE_BACKGROUND" = true ]; then | |
if [ "$DEBUG" = false ]; then | |
eval "$launcher_script_private" > /dev/null 2>&1 & | |
else | |
eval "$launcher_script_private" & | |
fi | |
else # Avoid closing the screen until Vuze has closed | |
if [ "$DEBUG" = false ]; then | |
eval "$launcher_script_private" > /dev/null 2>&1 | |
else | |
eval "$launcher_script_private" | |
fi | |
# TODO: Auto-close the mount when Vuze closes ("start" mode) | |
fi | |
fi | |
sleep 2 | |
else | |
echo "ERROR: You need to properly reference the configuration variable VUZE_STARTUP_SCRIPT. Aborting." | |
sleep 20 | |
exit 1 | |
fi | |
} | |
# close_app GREP_STATEMENT SIGNAL | |
# GREP_STATEMENT must not match itself! | |
close_app() { | |
APP_PID=$(ps -x | grep "$1" | grep -oP '^\s*\K[0-9]+' --color=never) | |
if [ ! -z "$APP_PID" ]; then | |
echo "Vuze (PID $APP_PID) is open. Trying to close Vuze (SIGNAL $2). Max $3sec." | |
kill $2 "$APP_PID" | |
WAIT_LOOP=0 | |
while ps -p "$APP_PID" > /dev/null 2>&1; do | |
sleep 1 | |
WAIT_LOOP=$((WAIT_LOOP+1)) | |
if [ "$WAIT_LOOP" = "$3" ]; then | |
break | |
fi | |
done | |
fi | |
APP_PID=$(ps -x | grep "$1" | grep -oP '^\s*\K[0-9]+' --color=never) | |
if [ -z "$APP_PID" ]; then return 0; else return 1; fi | |
} | |
close_vuze() { | |
close_app "java .*[A]zureus2.jar" "-HUP" "60" | |
close_app "java .*[A]zureus2.jar" "-TERM" "60" | |
close_app "java .*[A]zureus2.jar" "-SIGINT" "60" | |
close_app "java .*[A]zureus2.jar" "-KILL" "60" | |
return $? | |
} | |
find_screen() { | |
if screen -ls "$1" | grep -o "^\s*[0-9]*\.$1[ "$'\t'"](" --color=NEVER -m 1 | grep -oh "[0-9]*\.$1" --color=NEVER -m 1 -q >/dev/null; then | |
screen -ls "$1" | grep -o "^\s*[0-9]*\.$1[ "$'\t'"](" --color=NEVER -m 1 | grep -oh "[0-9]*\.$1" --color=NEVER -m 1 2>/dev/null | |
return 0 | |
else | |
echo "$1" | |
return 1 | |
fi | |
} | |
unmount_encfs() { | |
ENCFS_MOUNTED=$(mount -l | grep "encfs" | grep "$MOUNT_DIR") | |
if [ ! -z "$ENCFS_MOUNTED" ]; then | |
echo "Unmounting encfs gracefully" | |
fusermount -u "$MOUNT_DIR" | |
else | |
echo "INFO: No encfs mount to unmount." | |
fi | |
ENCFS_MOUNTED=$(mount -l | grep "encfs" | grep "$MOUNT_DIR") | |
if [ ! -z "$ENCFS_MOUNTED" ]; then | |
echo "Failed. Forcing encfs unmount (fusermount -z)" | |
fusermount -u -z "$MOUNT_DIR" | |
sleep 3 | |
if ! find "$MOUNT_DIR" -maxdepth 0 -empty | read v; then | |
echo -e "\e[31m\e[1mBROKEN: Virtual mount point \"$MOUNT_DIR\" may be in a broken state. Please empty it manually.\e[0m" | |
sleep 3 | |
fi | |
fi | |
} | |
concat_n_escape() { printf "%q"" " "$@"; } | |
# === START ==== | |
# Mount encfs crypted dir to clear view. | |
# Load a private Vuze profile | |
if [ "$1" = "start" ] || [ "$1" = "start-screened" ]; then | |
if [ "$1" = "start-screened" ]; then | |
# Unmount encfs... TODO test if necessary (not already mounted properly) and fail condition | |
#sudo fusermount -u "$MOUNT_DIR" | |
# Preparing to make mount private | |
RUN_VUZE_BACKGROUND=false | |
echo "Hi, you're in the screen matrix, or not." | |
fi | |
ENCFS_MOUNTED=$(mount -l | grep "encfs" | grep "$MOUNT_DIR") | |
if [ -z "$ENCFS_MOUNTED" ]; then | |
if [ -d "$VUZE_PRIVATE_CONF" ]; then | |
echo "Resuming from crash. Trying to empty $MOUNT_DIR." | |
rm -f -R "$VUZE_PRIVATE_CONF" | |
fi | |
echo "Mouting decrypted EncFS view:" | |
encfs "$CRYPTED_DIR" "$MOUNT_DIR" | |
ENCFS_RETURN=$? | |
else | |
echo "EncFS directory already mounted" | |
fi | |
ENCFS_MOUNTED=$(mount -l | grep "encfs" | grep "$MOUNT_DIR") | |
# Encfs mounted | |
if [ ! -z "$ENCFS_MOUNTED" ]; then | |
echo "Encfs mount point ready." | |
# Private profile doesn't exist in crypted dir | |
if [ ! -d "$VUZE_PRIVATE_CONF" ]; then | |
echo "Private Vuze conf not found (first start ever?)." | |
echo "Copying current Vuze conf to crypted private conf, without torrents." | |
cp -R "$VUZE_PUBLIC_CONF" "$VUZE_PRIVATE_CONF" | |
rm -R -f "$VUZE_PRIVATE_CONF/active" | |
mkdir -p "$VUZE_PRIVATE_CONF/active" | |
rm -f "$VUZE_PRIVATE_CONF/downloads.config" | |
rm -f "$VUZE_PRIVATE_CONF/downloads.config.bak" | |
echo "Adapting private settings: Download directories will point to mount dir." | |
echo "Please check that everyting's OK on your Vuze settings > Files." | |
mkdir -p "$VUZE_PRIVATE_CONF/custom" | |
/bin/cat >"$VUZE_PRIVATE_CONF/custom/private.config" <<EOF | |
Default\ save\ path=string:${MOUNT_DIR}/incomplete | |
Completed\ Files\ Directory=string:${MOUNT_DIR}${MOUNT_COMPLETE_SUBDIR} | |
General_sDefaultTorrent_Directory=string:${MOUNT_DIR}/incomplete | |
Move\ Completed\ When\ Done=bool:true | |
Move\ Torrent\ When\ Done=bool:true | |
File.move.download.removed.enabled=bool:false | |
EOF | |
fi | |
echo "Starting Vuze with private conf." | |
start_vuze_args=2 | |
count_java_args=0 | |
for arg in "${@:2}"; do | |
if [[ "$arg" == "-D"* ]]; then | |
start_vuze_args=$(( $start_vuze_args + 1 )) | |
count_java_args=$(( $count_java_args + 1 )) | |
else | |
break | |
fi | |
done | |
echo "start_vuze_args=$start_vuze_args " | |
VUZE_X_JAVA_ARGS_COMP="${@:2:$count_java_args}" | |
start_vuze_private "${@:$start_vuze_args}" | |
else | |
echo "ERROR: EncFS mounting failed. Aborting." | |
echo "Possible causes: Encfs not installed, bad password or need to manually empty $VUZE_PRIVATE_CONF" | |
exit 1 | |
fi | |
# === START IN HIDDEN MODE ==== | |
# Same as start but inside a different Linux namespace | |
# Vuze will be started in a password-protected GNU screen | |
# Encfs mount will be visible only to Vuze (so you can download/upload but not view files) | |
elif [ "$1" = "hidden" ]; then | |
# Prefer RAM to store the temporary screen conf file containing the encrypted screen password | |
if [ -d "/run/shm" ]; then | |
tmpscreendir="/run/shm" | |
else | |
tmpscreendir="/tmp" | |
fi | |
if find_screen "VZX" >/dev/null; then | |
echo "Screen already exist. Reattaching screen." | |
target_screen=$(find_screen "VZX") | |
screen -d -r "$target_screen" | |
else | |
echo "Creating password-protected screen and namespace." | |
echo -e "(Screen can be detached with \e[1mCtrl+A, D\e[0m and reattached with \e[1m$0 hidden\e[0m)" | |
tmpscreenfile="$(mktemp "$tmpscreendir"/.screenrc-XXXXXX)" | |
echo -e "Define password to protect the screen session (enter to skip):" | |
read -s -p "Screen password: " SCREEN_PWD | |
echo | |
if [ ! -z "$SCREEN_PWD" ]; then | |
(echo -n "password "; mkpasswd -m des -S SO "$SCREEN_PWD") >> "$tmpscreenfile" | |
fi | |
unset SCREEN_PWD | |
RUN_CMD="mount --bind \"$MOUNT_DIR\" \"$MOUNT_DIR\"; \ | |
mount --make-private \"$MOUNT_DIR\";\ | |
sudo -u \"#\$SUDO_UID\" -g \"#\$SUDO_GID\" bash -c \"sudo -K; rm \"$tmpscreenfile\"; "`concat_n_escape "$0"`" \\\"\\\$@\\\"; "`concat_n_escape "$0"`" stop\" - \"\$@\"; \ | |
umount \"$MOUNT_DIR\"" | |
# Unfortunately, encfs can't be mounted inside non-sudoed "unshare -m -r" | |
# due to permissions issues to access /etc/fuse.conf | |
# However, it runs well in "unshare -m" even after root permissions removal. | |
# Permissions are removed through "sudo -K" in RUN_CMD before running Vuze | |
echo "Script will ask for temporary root permissions to hide the mount." | |
sleep 3 | |
# Make the virtual mount point invisible to processes from other namespaces, by using unshare, in a password-protected screen | |
screen -mS "VZX" -c "$tmpscreenfile" \ | |
sudo unshare -m \ | |
bash -c \ | |
"$RUN_CMD" "$0" "start-screened" "${@:2}" | |
rm "$tmpscreenfile" 2>/dev/null | |
fi | |
exit 0 | |
# === STOP ==== | |
# Restore usual ("public") Vuze settings. | |
# Unmount encfs clear view. | |
elif [ "$1" = "stop" ]; then | |
close_vuze | |
VUZE_PID=$(ps -x | grep "java .*[A]zureus2.jar" | grep -oP '^\s*\K[0-9]+' --color=never) | |
if [ -n "$VUZE_PID" ]; then | |
echo "VUZE_PID = $VUZE_PID" | |
echo -e "\e[31m\e[1mBROKEN: Vuze is immortal." | |
echo -e "Unmounting encfs may screw up your Vuze public settings directory." | |
echo -e "Please close Vuze yourself and try again." | |
echo -e "Aborting in a dirty state.\e[0m" | |
exit 1 | |
fi | |
unmount_encfs | |
echo -e "\nStatus:" | |
echo -n "Vuze closed ? " | |
if [ -z "$VUZE_PID" ]; then echo "Yes, OK."; else echo "No, FAILED!"; fi | |
echo -n "Encfs unmounted ? " | |
ENCFS_MOUNTED=$(mount -l | grep "encfs" | grep "$MOUNT_DIR") | |
if [ -z "$ENCFS_MOUNTED" ]; then echo "Yes, OK."; else echo "No, FAILED!"; fi | |
# === VIEW ==== | |
# Just mount encfs clear view. | |
elif [ "$1" = "view" ]; then | |
ENCFS_MOUNTED=$(mount -l | grep "encfs" | grep "$MOUNT_DIR") | |
if [ -z "$ENCFS_MOUNTED" ]; then | |
echo "Mouting EncFS directory" | |
encfs "$CRYPTED_DIR" "$MOUNT_DIR" | |
else | |
echo "EncFS directory already mounted" | |
fi | |
ENCFS_MOUNTED=$(mount -l | grep "encfs" | grep "$MOUNT_DIR") | |
# Encfs mounted | |
if [ -z "$ENCFS_MOUNTED" ]; then | |
echo "ERROR: EncFS mounting failed. Aborting." | |
exit 1 | |
fi | |
echo "Opening File Explorer." | |
xdg-open "$MOUNT_DIR" > /dev/null 2>&1 & | |
exit 0 | |
else | |
echo "Usage:" | |
echo "$me start [-DJAVA ARGUMENTS] [VUZE ARGUMENTS] [TORRENT FILE]" | |
echo -e "\tMount crypted dir and change Vuze configuration" | |
echo -e "\tto the encrypted \"private\" profile." | |
echo "$me hidden [-DJAVA ARGUMENTS] [VUZE ARGUMENTS] [TORRENT FILE]" | |
echo -e "\tSame as start but inside a different Linux namespace." | |
echo -e "\tVuze will be started in a password-protected GNU screen." | |
echo -e "\tEncfs mount will be visible only to Vuze and programs opened through Vuze." | |
echo -e "\tOnly really useful with the --ui=console argument (you can't hide the GUI)." | |
echo "$me stop" | |
echo -e "\tUnmount crypted dir and restore Vuze configuration" | |
echo -e "\tto the unencrypted \"public\" profile." | |
echo "$me view" | |
echo -e "\tMount & browse encfs clear view directory." | |
fi | |
echo | |
echo "NOTE: Check your security settings after swaping profiles" | |
echo " (proxy, ToR, forced interface bindings...)" | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment