Encrypted proxy killswitch + TUN optimization #1

Open
zenaku wants to merge 54 commits from feature/merge-encrypted-proxy into master
7 changed files with 98 additions and 202 deletions
Showing only changes of commit 5ef45ad6b4 - Show all commits

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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",

View file

@ -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

View file

@ -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 ""