Encrypted proxy killswitch + TUN optimization #1
7 changed files with 98 additions and 202 deletions
11
lib/steps.sh
11
lib/steps.sh
|
|
@ -3,20 +3,15 @@
|
|||
|
||||
TOTAL_STEPS=6
|
||||
|
||||
# ─── Variables globales ───────────────────────────────────────────────────────
|
||||
# Directorio base de hydra-veil
|
||||
HV_BASE="$HOME/.local/share/hydra-veil"
|
||||
|
||||
# Componentes
|
||||
HV_CORE="$HV_BASE/core"
|
||||
HV_CLI="$HV_BASE/cli"
|
||||
HV_GUI="$HV_BASE/gui"
|
||||
HV_ESSENTIALS="$HV_BASE/essentials"
|
||||
|
||||
# Venv — siempre en el core
|
||||
HV_VENV="$HV_CORE/.venv"
|
||||
|
||||
# XDG — INSTALL_DIR es $HOME, no el repo
|
||||
INSTALL_DIR="$HOME"
|
||||
HV_DATA_DIR="$HOME/data/hydra-veil"
|
||||
HV_CONFIG_DIR="$HOME/.config/hydra-veil"
|
||||
|
|
@ -31,12 +26,10 @@ SINGBOX_CONFIG_DIR="$HV_DATA_DIR/configs"
|
|||
SINGBOX_PID_FILE="$HV_DATA_DIR/runtime/singbox.pid"
|
||||
SINGBOX_LOG_FILE="$HV_DATA_DIR/runtime/singbox.log"
|
||||
|
||||
# sudoers
|
||||
SUDOERS_PATH="/etc/sudoers.d/hydraveil"
|
||||
|
||||
# Repos
|
||||
declare -A REPO_URLS=(
|
||||
["core"]="https://git.simplifiedprivacy.com/Support/sp-hydra-veil-core "
|
||||
["core"]="https://git.simplifiedprivacy.com/Support/sp-hydra-veil-core"
|
||||
["cli"]="https://git.simplifiedprivacy.com/Support/sp-hydra-veil-cli"
|
||||
["essentials"]="https://git.simplifiedprivacy.com/Support/sp-essentials"
|
||||
["gui"]="https://git.simplifiedprivacy.com/Support/sp-hydra-veil-gui"
|
||||
|
|
@ -54,8 +47,6 @@ declare -A REPO_DIRS=(
|
|||
["essentials"]="$HV_ESSENTIALS"
|
||||
["gui"]="$HV_GUI"
|
||||
)
|
||||
|
||||
# ─── Importar steps atómicos ──────────────────────────────────────────────────
|
||||
_STEPS_DIR="$SCRIPT_DIR/lib/steps"
|
||||
|
||||
for _step in preflight repos python_env singbox wrapper sudoers; do
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
#!/bin/bash
|
||||
# lib/steps/preflight.sh — verificaciones previas
|
||||
|
||||
step_preflight() {
|
||||
print_section "Pre-flight"
|
||||
log_step "System checks" 1 $TOTAL_STEPS
|
||||
|
|
|
|||
|
|
@ -35,13 +35,11 @@ _create_venv() {
|
|||
_pip_install() {
|
||||
source "$HV_VENV/bin/activate"
|
||||
|
||||
# Fix: la GUI puede pedir core==2.3.4 pero core puede ser 2.3.x
|
||||
if [ -f "$HV_GUI/pyproject.toml" ]; then
|
||||
sed -i 's/sp-hydra-veil-core == [0-9.]*/sp-hydra-veil-core >= 2.3.0/' \
|
||||
"$HV_GUI/pyproject.toml" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Orden de instalación: dependencias primero
|
||||
for name in essentials core cli gui; do
|
||||
local dir
|
||||
case "$name" in
|
||||
|
|
|
|||
|
|
@ -70,13 +70,11 @@ _setup_env() {
|
|||
*) _app_env="production" ;;
|
||||
esac
|
||||
|
||||
# SP_API_BASE_URL_PRODUCTION
|
||||
echo ""
|
||||
printf " ${BCYAN}┌─${RESET} ${BWHITE}SP_API_BASE_URL_PRODUCTION${RESET} ${DIM}e.g. https://fake.simplifiedprivacy.org/api/v1${RESET}\n"
|
||||
printf " ${BCYAN}›${RESET} "
|
||||
read -r _api_url < /dev/tty
|
||||
|
||||
# Escribir .env
|
||||
cat > "$env_file" << EOF
|
||||
APP_ENV=${_app_env}
|
||||
SP_API_BASE_URL_LOCAL=http://simplifiedprivacy.test/api/v1
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ classifiers = [
|
|||
]
|
||||
dependencies = [
|
||||
"cryptography ~= 46.0.3",
|
||||
"python-dotenv ~= 1.0.0",
|
||||
"dataclasses-json ~= 0.6.7",
|
||||
"marshmallow ~= 3.26.1",
|
||||
"pysocks ~= 1.7.1",
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
python-dotenv
|
||||
cryptography~=46.0.3
|
||||
dataclasses-json~=0.6.7
|
||||
marshmallow~=3.26.1
|
||||
psutil~=7.1.3
|
||||
pysocks~=1.7.1
|
||||
python-dateutil~=2.9.0.post0
|
||||
requests~=2.32.5
|
||||
annotated-types==0.7.0
|
||||
certifi==2026.4.22
|
||||
charset-normalizer==3.4.7
|
||||
click==8.3.3
|
||||
cytoolz==1.1.0
|
||||
eth-hash==0.8.0
|
||||
eth-typing==6.0.0
|
||||
eth-utils==6.0.0
|
||||
idna==3.13
|
||||
packaging==26.2
|
||||
pathspec==1.1.1
|
||||
platformdirs==4.9.6
|
||||
py-ecc==8.0.0
|
||||
pydantic==2.13.3
|
||||
pydantic_core==2.46.3
|
||||
pydeps==3.0.6
|
||||
pytokens==0.4.1
|
||||
stdlib-list==0.12.0
|
||||
toolz==1.1.0
|
||||
typing-inspect==0.9.0
|
||||
typing-inspection==0.4.2
|
||||
typing_extensions==4.15.0
|
||||
urllib3==2.6.3
|
||||
252
uninstall.sh
252
uninstall.sh
|
|
@ -1,113 +1,93 @@
|
|||
#!/bin/bash
|
||||
# hv-clean.sh — Limpieza completa de hydra-veil para reinstalación limpia
|
||||
# Elimina: wrapper, sudoers, dirs de runtime (logs/run/pid)
|
||||
# Conserva: repo, venv, configs (a menos que se pase --full)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ─── Colores ──────────────────────────────────────────────────────────────────
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
CYAN='\033[0;36m'
|
||||
DIM='\033[2m'
|
||||
BOLD='\033[1m'
|
||||
RESET='\033[0m'
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
LIB_DIR="$SCRIPT_DIR/lib"
|
||||
|
||||
ok() { printf " ${GREEN}✔${RESET} %s\n" "$*"; }
|
||||
warn() { printf " ${YELLOW}⚠${RESET} %s\n" "$*"; }
|
||||
info() { printf " ${CYAN}→${RESET} %s\n" "$*"; }
|
||||
err() { printf " ${RED}✖${RESET} %s\n" "$*" >&2; }
|
||||
hdr() { echo ""; printf "${BOLD}${CYAN}── %s ${RESET}\n" "$*"; echo ""; }
|
||||
for _lib in ui log input steps; do
|
||||
_path="$LIB_DIR/${_lib}.sh"
|
||||
if [ ! -f "$_path" ]; then
|
||||
echo "[ERROR] Missing lib: $_path" >&2
|
||||
exit 1
|
||||
fi
|
||||
source "$_path"
|
||||
done
|
||||
|
||||
# ─── Paths (deben coincidir con steps.sh) ────────────────────────────────────
|
||||
HV_CORE_HOME="$HOME/.local/share/hydra-veil/core"
|
||||
HV_LOG_DIR="$HV_CORE_HOME/logs/hydra-veil"
|
||||
HV_RUN_DIR="$HV_CORE_HOME/run"
|
||||
HV_DATA_DIR="$HV_CORE_HOME/data/hydra-veil"
|
||||
HV_CONFIG_DIR="$HV_DATA_DIR/configs"
|
||||
HV_VENV_DIR="$HV_CORE_HOME/.venv"
|
||||
|
||||
SINGBOX_BIN="/usr/bin/sing-box"
|
||||
SINGBOX_PID_FILE="$HV_RUN_DIR/singbox.pid"
|
||||
SINGBOX_LOG_FILE="$HV_LOG_DIR/singbox.log"
|
||||
|
||||
WRAPPER_PATH="/usr/local/bin/hydraveil-singbox"
|
||||
SUDOERS_PATH="/etc/sudoers.d/hydraveil"
|
||||
|
||||
# ─── Flags ────────────────────────────────────────────────────────────────────
|
||||
FULL=false
|
||||
YES=false
|
||||
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--full|-f) FULL=true ;;
|
||||
--yes|-y) YES=true ;;
|
||||
--full|-f) FULL=true ;;
|
||||
--yes|-y) YES=true ;;
|
||||
--help|-h)
|
||||
echo ""
|
||||
echo " Uso: $0 [opciones]"
|
||||
echo " Usage: $0 [options]"
|
||||
echo ""
|
||||
echo " Sin flags — elimina wrapper, sudoers, logs, pid, run"
|
||||
echo " conserva repo, venv y configs"
|
||||
echo " No flags — removes wrapper, sudoers, runtime"
|
||||
echo " keeps repos, venv, configs and data"
|
||||
echo ""
|
||||
echo " --full — todo lo anterior + repo completo, venv y configs"
|
||||
echo " --yes — no pide confirmación"
|
||||
echo " --full — everything above + repos, venv, configs and data"
|
||||
echo " --yes — skip confirmation prompt"
|
||||
echo ""
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
err "Flag desconocido: $arg"
|
||||
log_error "Unknown flag: $arg"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# ─── Banner ───────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
printf "${BOLD}${RED} hydra-veil — limpieza para reinstalación${RESET}\n"
|
||||
echo ""
|
||||
clear
|
||||
print_header "HYDRA-VEIL UNINSTALLER" "v2.0.0"
|
||||
printf " ${DIM}%s${RESET}\n" "$(date '+%Y-%m-%d %H:%M:%S') — $(uname -n)"
|
||||
print_divider
|
||||
|
||||
if $FULL; then
|
||||
warn "Modo --full: se eliminará TODO incluyendo repo, venv y configs"
|
||||
label_warn "Mode --full: everything will be removed (repos, venv, configs, data)"
|
||||
else
|
||||
info "Modo normal: conserva repo, venv y configs"
|
||||
label_info "Normal mode: repos, venv, configs and data will be kept"
|
||||
label_info "Use --full to remove everything"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ─── Confirmación ─────────────────────────────────────────────────────────────
|
||||
if ! $YES; then
|
||||
printf " ${YELLOW}¿Continuar?${RESET} ${DIM}[s/N]:${RESET} "
|
||||
read -r _confirm < /dev/tty
|
||||
case "$_confirm" in
|
||||
s|S|y|Y) : ;;
|
||||
*)
|
||||
echo ""
|
||||
info "Cancelado."
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
echo ""
|
||||
if ! ask_confirm "Continue with uninstall?"; then
|
||||
log_warn "Uninstall cancelled."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─── 1. Detener sing-box si está corriendo ────────────────────────────────────
|
||||
hdr "1. Proceso sing-box"
|
||||
print_divider
|
||||
|
||||
_rm() {
|
||||
local target="$1"
|
||||
if [ -e "$target" ]; then
|
||||
rm -rf "$target"
|
||||
label_ok "Removed: $target"
|
||||
else
|
||||
label_info "Not found: $target"
|
||||
fi
|
||||
}
|
||||
|
||||
print_section "1. sing-box process"
|
||||
|
||||
_stop_singbox() {
|
||||
local pid=""
|
||||
|
||||
# Intentar via pidfile primero
|
||||
if [ -f "$SINGBOX_PID_FILE" ]; then
|
||||
pid=$(cat "$SINGBOX_PID_FILE" 2>/dev/null || echo "")
|
||||
fi
|
||||
|
||||
# Si no hay pidfile, buscar por nombre
|
||||
if [[ -z "$pid" || ! "$pid" =~ ^[0-9]+$ ]]; then
|
||||
pid=$(pgrep -x sing-box 2>/dev/null | head -1 || echo "")
|
||||
fi
|
||||
|
||||
if [[ -n "$pid" && "$pid" =~ ^[0-9]+$ ]] && kill -0 "$pid" 2>/dev/null; then
|
||||
info "Deteniendo sing-box PID $pid..."
|
||||
log_info "Stopping sing-box PID $pid..."
|
||||
kill -TERM "$pid" 2>/dev/null || true
|
||||
local elapsed=0
|
||||
while kill -0 "$pid" 2>/dev/null && (( elapsed < 16 )); do
|
||||
|
|
@ -117,149 +97,109 @@ _stop_singbox() {
|
|||
if kill -0 "$pid" 2>/dev/null; then
|
||||
kill -KILL "$pid" 2>/dev/null || true
|
||||
sleep 0.3
|
||||
ok "sing-box eliminado (SIGKILL)"
|
||||
label_ok "sing-box killed (SIGKILL)"
|
||||
else
|
||||
ok "sing-box detenido (SIGTERM)"
|
||||
label_ok "sing-box stopped (SIGTERM)"
|
||||
fi
|
||||
else
|
||||
info "sing-box no está corriendo"
|
||||
label_info "sing-box is not running"
|
||||
fi
|
||||
}
|
||||
|
||||
# Intentar via wrapper si existe, sino directo
|
||||
if [ -x "$WRAPPER_PATH" ]; then
|
||||
sudo "$WRAPPER_PATH" "" stop 2>/dev/null && ok "Detenido via wrapper" || _stop_singbox
|
||||
if [ -x "$SINGBOX_WRAPPER" ]; then
|
||||
sudo "$SINGBOX_WRAPPER" "" stop 2>/dev/null && label_ok "Stopped via wrapper" || _stop_singbox
|
||||
else
|
||||
_stop_singbox
|
||||
fi
|
||||
|
||||
# Eliminar interfaz tun0 si existe
|
||||
if ip link show tun0 &>/dev/null 2>&1; then
|
||||
sudo ip link delete tun0 2>/dev/null && ok "tun0 eliminada" || warn "No se pudo eliminar tun0"
|
||||
sudo ip link delete tun0 2>/dev/null && label_ok "tun0 removed" || label_warn "Could not remove tun0"
|
||||
else
|
||||
info "tun0 no existe"
|
||||
label_info "tun0 not found"
|
||||
fi
|
||||
|
||||
# ─── 2. Wrapper ───────────────────────────────────────────────────────────────
|
||||
hdr "2. Wrapper"
|
||||
print_divider
|
||||
print_section "2. Wrapper"
|
||||
|
||||
if [ -f "$WRAPPER_PATH" ]; then
|
||||
sudo rm -f "$WRAPPER_PATH"
|
||||
ok "Eliminado: $WRAPPER_PATH"
|
||||
if [ -f "$SINGBOX_WRAPPER" ]; then
|
||||
sudo rm -f "$SINGBOX_WRAPPER"
|
||||
label_ok "Removed: $SINGBOX_WRAPPER"
|
||||
else
|
||||
info "No existe: $WRAPPER_PATH"
|
||||
label_info "Not found: $SINGBOX_WRAPPER"
|
||||
fi
|
||||
|
||||
# ─── 3. Sudoers ───────────────────────────────────────────────────────────────
|
||||
hdr "3. Sudoers"
|
||||
print_divider
|
||||
print_section "3. Sudoers"
|
||||
|
||||
if [ -f "$SUDOERS_PATH" ]; then
|
||||
sudo rm -f "$SUDOERS_PATH"
|
||||
ok "Eliminado: $SUDOERS_PATH"
|
||||
label_ok "Removed: $SUDOERS_PATH"
|
||||
else
|
||||
info "No existe: $SUDOERS_PATH"
|
||||
label_info "Not found: $SUDOERS_PATH"
|
||||
fi
|
||||
|
||||
# Verificar que no haya entradas huérfanas en sudoers.d
|
||||
_orphans=$(sudo grep -rl "hydraveil" /etc/sudoers.d/ 2>/dev/null || true)
|
||||
if [ -n "$_orphans" ]; then
|
||||
warn "Entradas huérfanas de hydraveil encontradas:"
|
||||
label_warn "Orphaned sudoers entries found:"
|
||||
echo "$_orphans" | while read -r f; do
|
||||
warn " $f"
|
||||
sudo rm -f "$f" && ok " Eliminado: $f"
|
||||
sudo rm -f "$f" && label_ok " Removed: $f"
|
||||
done
|
||||
else
|
||||
info "Sin entradas huérfanas en sudoers.d"
|
||||
label_info "No orphaned entries in sudoers.d"
|
||||
fi
|
||||
|
||||
# ─── 4. PID file y runtime ────────────────────────────────────────────────────
|
||||
hdr "4. Runtime (pid / run)"
|
||||
print_divider
|
||||
print_section "4. Runtime"
|
||||
|
||||
if [ -f "$SINGBOX_PID_FILE" ]; then
|
||||
rm -f "$SINGBOX_PID_FILE"
|
||||
ok "Eliminado PID file: $SINGBOX_PID_FILE"
|
||||
else
|
||||
info "Sin PID file"
|
||||
fi
|
||||
_rm "$SINGBOX_PID_FILE"
|
||||
_rm "$SINGBOX_LOG_FILE"
|
||||
_rm "$HV_DATA_DIR/runtime"
|
||||
|
||||
if [ -d "$HV_RUN_DIR" ]; then
|
||||
rm -rf "$HV_RUN_DIR"
|
||||
ok "Eliminado: $HV_RUN_DIR"
|
||||
else
|
||||
info "No existe: $HV_RUN_DIR"
|
||||
fi
|
||||
print_divider
|
||||
|
||||
# ─── 5. Logs ──────────────────────────────────────────────────────────────────
|
||||
hdr "5. Logs"
|
||||
|
||||
if [ -d "$HV_LOG_DIR" ]; then
|
||||
rm -rf "$HV_LOG_DIR"
|
||||
ok "Eliminado: $HV_LOG_DIR"
|
||||
else
|
||||
info "No existe: $HV_LOG_DIR"
|
||||
fi
|
||||
|
||||
# ─── 6. Limpieza completa (--full) ────────────────────────────────────────────
|
||||
if $FULL; then
|
||||
hdr "6. Limpieza completa (--full)"
|
||||
print_section "5. Data"
|
||||
_rm "$HV_DATA_DIR"
|
||||
|
||||
# Configs
|
||||
if [ -d "$HV_CONFIG_DIR" ]; then
|
||||
rm -rf "$HV_CONFIG_DIR"
|
||||
ok "Eliminado: $HV_CONFIG_DIR"
|
||||
else
|
||||
info "No existe: $HV_CONFIG_DIR"
|
||||
print_section "6. Configs"
|
||||
_rm "$HV_CONFIG_DIR"
|
||||
_rm "$HV_CACHE_DIR"
|
||||
_rm "$HV_STATE_DIR"
|
||||
|
||||
print_section "7. Venv"
|
||||
_rm "$HV_VENV"
|
||||
|
||||
print_section "8. Repos"
|
||||
for _dir in "$HV_CORE" "$HV_CLI" "$HV_GUI" "$HV_ESSENTIALS"; do
|
||||
_rm "$_dir"
|
||||
done
|
||||
|
||||
if [ -d "$HV_BASE" ] && [ -z "$(ls -A "$HV_BASE" 2>/dev/null)" ]; then
|
||||
rmdir "$HV_BASE"
|
||||
label_ok "Empty base directory removed: $HV_BASE"
|
||||
fi
|
||||
|
||||
# Data dir completo
|
||||
if [ -d "$HV_DATA_DIR" ]; then
|
||||
rm -rf "$HV_DATA_DIR"
|
||||
ok "Eliminado: $HV_DATA_DIR"
|
||||
else
|
||||
info "No existe: $HV_DATA_DIR"
|
||||
fi
|
||||
|
||||
# Venv
|
||||
if [ -d "$HV_VENV_DIR" ]; then
|
||||
rm -rf "$HV_VENV_DIR"
|
||||
ok "Eliminado venv: $HV_VENV_DIR"
|
||||
else
|
||||
info "No existe: $HV_VENV_DIR"
|
||||
fi
|
||||
|
||||
# Repo completo
|
||||
if [ -d "$HV_CORE_HOME/.git" ]; then
|
||||
rm -rf "$HV_CORE_HOME"
|
||||
ok "Eliminado repo: $HV_CORE_HOME"
|
||||
elif [ -d "$HV_CORE_HOME" ]; then
|
||||
rm -rf "$HV_CORE_HOME"
|
||||
ok "Eliminado directorio: $HV_CORE_HOME"
|
||||
else
|
||||
info "No existe: $HV_CORE_HOME"
|
||||
fi
|
||||
|
||||
# sing-box binary (solo si se instaló por el installer, no si era preexistente)
|
||||
if [ -L "$SINGBOX_BIN" ]; then
|
||||
sudo rm -f "$SINGBOX_BIN"
|
||||
ok "Eliminado symlink sing-box: $SINGBOX_BIN"
|
||||
label_ok "sing-box symlink removed: $SINGBOX_BIN"
|
||||
else
|
||||
info "sing-box no es symlink — conservado: $SINGBOX_BIN"
|
||||
label_info "sing-box is not a symlink — kept: $SINGBOX_BIN"
|
||||
fi
|
||||
|
||||
print_divider
|
||||
fi
|
||||
|
||||
# ─── Resumen ──────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
printf "${BOLD}${GREEN} ✔ Limpieza completa.${RESET}"
|
||||
label_ok "Uninstall complete"
|
||||
|
||||
if $FULL; then
|
||||
printf " ${DIM}(modo --full)${RESET}\n"
|
||||
label_ok "Mode --full: everything removed"
|
||||
else
|
||||
printf "\n"
|
||||
echo ""
|
||||
printf " ${DIM}Conservados: repo, venv, configs${RESET}\n"
|
||||
printf " ${DIM}Para eliminar todo: %s --full${RESET}\n" "$0"
|
||||
label_info "Kept: repos, venv, configs, data"
|
||||
label_info "To remove everything: $0 --full"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
info "Podés correr el installer nuevamente sin conflictos."
|
||||
print_divider
|
||||
echo ""
|
||||
|
|
|
|||
Loading…
Reference in a new issue