Compare commits
No commits in common. "bae5bfe7f34882e44d0858d4ae5de65d74e606e1" and "28e0bba1d80bf6b2bd39549065da187b4fba991c" have entirely different histories.
bae5bfe7f3
...
28e0bba1d8
5 changed files with 3 additions and 312 deletions
|
|
@ -1,58 +0,0 @@
|
||||||
dns_script = """#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
if [[ "$EUID" -ne 0 ]]; then
|
|
||||||
echo "[killswitch] ERROR: must be run as root" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
ACTION="${1:-}"
|
|
||||||
IFACE="${2:-}"
|
|
||||||
DNS="${3:-}"
|
|
||||||
|
|
||||||
|
|
||||||
_check_prereqs() {
|
|
||||||
[[ -z "$DNS" ]] && { echo "Error: DNS IP required" >&2; exit 1; }
|
|
||||||
|
|
||||||
# ✓ Check it's a valid IPv4 address:
|
|
||||||
if ! [[ "$DNS" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ ]]; then
|
|
||||||
echo "Error: Invalid IP: $DNS" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# ✓ checks interface exists before configuring
|
|
||||||
if ! ip link show "$IFACE" &>/dev/null; then
|
|
||||||
echo "Error: Interface $IFACE not found" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_set_dns() {
|
|
||||||
resolvectl dns "$IFACE" "$DNS" || {
|
|
||||||
echo "ERROR: Failed to set DNS to $DNS" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
resolvectl domain "$IFACE" '~.' || {
|
|
||||||
echo "ERROR: Failed to set domain routing" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
resolvectl default-route "$IFACE" true || {
|
|
||||||
echo "ERROR: Failed to set default route" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "$ACTION" == "set" ]]; then
|
|
||||||
_check_prereqs
|
|
||||||
_set_dns
|
|
||||||
fi
|
|
||||||
|
|
||||||
# if [[ "$ACTION" == "revert" ]]; then
|
|
||||||
# resolvectl revert "$IFACE" 2>/dev/null || true
|
|
||||||
|
|
||||||
# fi
|
|
||||||
|
|
||||||
if [[ "$ACTION" == "revert" ]]; then
|
|
||||||
resolvectl revert "$IFACE" || true
|
|
||||||
fi
|
|
||||||
"""
|
|
||||||
|
|
@ -1,117 +0,0 @@
|
||||||
firewall_script = """#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
if [[ "$EUID" -ne 0 ]]; then
|
|
||||||
echo "[killswitch] ERROR: must be run as root" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
ACTION="${1:-}"
|
|
||||||
SERVER_IP="${2:-}"
|
|
||||||
TUNNEL_IF="${3:-}"
|
|
||||||
INTERNAL_SUBNET="${4:-}"
|
|
||||||
TABLE="hydraveil"
|
|
||||||
|
|
||||||
if [[ "$ACTION" != "arm" && "$ACTION" != "disarm" && "$ACTION" != "status" ]]; then
|
|
||||||
echo "[killswitch] ERROR: invalid action '$ACTION'. Usage: arm <server_ip> <tunnel_if> [internal_subnet] | disarm | status" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
_default_iface() {
|
|
||||||
ip route show default 2>/dev/null | awk 'NR==1{print $5}'
|
|
||||||
}
|
|
||||||
|
|
||||||
_log() {
|
|
||||||
local level="$1"; shift
|
|
||||||
echo "[killswitch] [$level] $* — $(date '+%Y-%m-%d %H:%M:%S')" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "$ACTION" == "status" ]]; then
|
|
||||||
if nft list table inet "$TABLE" &>/dev/null 2>&1; then
|
|
||||||
echo "armed"
|
|
||||||
else
|
|
||||||
echo "disarmed"
|
|
||||||
fi
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$ACTION" == "disarm" ]]; then
|
|
||||||
if nft list table inet "$TABLE" &>/dev/null 2>&1; then
|
|
||||||
nft delete table inet "$TABLE"
|
|
||||||
_log "INFO" "disarmed"
|
|
||||||
else
|
|
||||||
_log "INFO" "already disarmed"
|
|
||||||
fi
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ -z "$SERVER_IP" ]] && { _log "ERROR" "server_ip required for arm"; exit 1; }
|
|
||||||
[[ -z "$TUNNEL_IF" ]] && { _log "ERROR" "tunnel_if required for arm"; exit 1; }
|
|
||||||
|
|
||||||
if ! [[ "$SERVER_IP" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
|
|
||||||
_log "ERROR" "invalid IPv4: $SERVER_IP"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
IFS='.' read -r o1 o2 o3 o4 <<< "$SERVER_IP"
|
|
||||||
for oct in "$o1" "$o2" "$o3" "$o4"; do
|
|
||||||
if (( oct > 255 )); then
|
|
||||||
_log "ERROR" "invalid IPv4 octet ($oct) in $SERVER_IP"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
WAN_IFACE=$(_default_iface)
|
|
||||||
if [[ -z "$WAN_IFACE" ]]; then
|
|
||||||
_log "ERROR" "could not detect primary network interface"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
INTERNAL_RULE=""
|
|
||||||
if [[ -n "$INTERNAL_SUBNET" ]]; then
|
|
||||||
INTERNAL_RULE=" ip daddr ${INTERNAL_SUBNET} accept"
|
|
||||||
fi
|
|
||||||
|
|
||||||
nft list table inet "$TABLE" &>/dev/null 2>&1 && nft delete table inet "$TABLE" || true
|
|
||||||
|
|
||||||
nft -f - << NFTEOF
|
|
||||||
table inet ${TABLE} {
|
|
||||||
chain output {
|
|
||||||
type filter hook output priority filter; policy drop;
|
|
||||||
oifname "lo" accept
|
|
||||||
ether type arp drop
|
|
||||||
ip6 daddr != ::1 drop
|
|
||||||
ip daddr 224.0.0.0/4 drop
|
|
||||||
ip daddr 255.255.255.255 drop
|
|
||||||
ip daddr 192.168.1.0/24 drop
|
|
||||||
|
|
||||||
oifname "${WAN_IFACE}" ip daddr ${SERVER_IP} accept
|
|
||||||
oifname "${TUNNEL_IF}" accept
|
|
||||||
log prefix "hydraveil-drop " drop
|
|
||||||
}
|
|
||||||
|
|
||||||
chain input {
|
|
||||||
type filter hook input priority filter; policy drop;
|
|
||||||
iifname "lo" accept
|
|
||||||
|
|
||||||
ether type arp drop
|
|
||||||
ip6 saddr != ::1 drop
|
|
||||||
ip daddr 224.0.0.0/4 drop
|
|
||||||
ip daddr 255.255.255.255 drop
|
|
||||||
|
|
||||||
ct state established,related accept
|
|
||||||
iifname "${WAN_IFACE}" ip saddr ${SERVER_IP} accept
|
|
||||||
iifname "${TUNNEL_IF}" accept
|
|
||||||
|
|
||||||
log prefix "hydraveil-drop " drop
|
|
||||||
}
|
|
||||||
chain forward {
|
|
||||||
type filter hook forward priority filter; policy drop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NFTEOF
|
|
||||||
|
|
||||||
|
|
||||||
_log "INFO" "armed — wan=${WAN_IFACE} server=${SERVER_IP} tunnel=${TUNNEL_IF} internal=${INTERNAL_SUBNET:-none}"
|
|
||||||
exit 0
|
|
||||||
"""
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
setup_script = """
|
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
ORIGINAL_FOLDER="${ORIGINAL_FOLDER:-$(pwd)}"
|
|
||||||
TARGET_FOLDER="${TARGET_FOLDER:-/opt/hydra-veil}"
|
|
||||||
LINUX_USER="${LINUX_USER:-$SUDO_USER}"
|
|
||||||
|
|
||||||
add_sudoers_rule() {
|
|
||||||
sudo tee /etc/sudoers.d/zzzzzzzzzzzzzzzzzzz > /dev/null <<EOF
|
|
||||||
${LINUX_USER} ALL=(root) NOPASSWD: /opt/hydra-veil/firewall
|
|
||||||
${LINUX_USER} ALL=(root) NOPASSWD: /opt/hydra-veil/dns
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if running as root
|
|
||||||
if [[ $EUID -ne 0 ]]; then
|
|
||||||
echo "Error: This script must be run as root (use sudo)" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Validate environment variables
|
|
||||||
if [[ -z "$ORIGINAL_FOLDER" ]]; then
|
|
||||||
echo "Error: ORIGINAL_FOLDER environment variable not set" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$TARGET_FOLDER" ]]; then
|
|
||||||
echo "Error: TARGET_FOLDER environment variable not set" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Validate that source folder exists
|
|
||||||
if [[ ! -d "$ORIGINAL_FOLDER" ]]; then
|
|
||||||
echo "Error: ORIGINAL_FOLDER does not exist: $ORIGINAL_FOLDER" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create target folder if it doesn't exist
|
|
||||||
if [[ ! -d "$TARGET_FOLDER" ]]; then
|
|
||||||
echo "Creating target folder: $TARGET_FOLDER"
|
|
||||||
mkdir -p "$TARGET_FOLDER"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the setup script's own filename, because we'll exclude it from being copied,
|
|
||||||
SCRIPT_NAME="$(basename "$0")"
|
|
||||||
|
|
||||||
echo "Starting file copy from $ORIGINAL_FOLDER to $TARGET_FOLDER"
|
|
||||||
echo "Script name to exclude: $SCRIPT_NAME"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# Counter for tracking progress
|
|
||||||
COPIED=0
|
|
||||||
SKIPPED=0
|
|
||||||
|
|
||||||
# Loop through all files in source folder
|
|
||||||
while IFS= read -r -d '' file; do
|
|
||||||
filename="$(basename "$file")"
|
|
||||||
|
|
||||||
# Skip if this is the script itself
|
|
||||||
if [[ "$filename" == "$SCRIPT_NAME" ]]; then
|
|
||||||
echo "⊘ Skipping: $filename (this script)"
|
|
||||||
((SKIPPED++))
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Copy the file
|
|
||||||
if cp "$file" "$TARGET_FOLDER/"; then
|
|
||||||
echo "✓ Copied: $filename"
|
|
||||||
((COPIED++))
|
|
||||||
|
|
||||||
# Set permissions to 755
|
|
||||||
if chmod 755 "$TARGET_FOLDER/$filename"; then
|
|
||||||
echo " └─ chmod 755 applied"
|
|
||||||
else
|
|
||||||
echo " └─ WARNING: chmod 755 failed for $filename" >&2
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "✗ ERROR: Failed to copy $filename" >&2
|
|
||||||
((SKIPPED++))
|
|
||||||
fi
|
|
||||||
|
|
||||||
done < <(find "$ORIGINAL_FOLDER" -maxdepth 1 -type f -print0)
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "=========================================="
|
|
||||||
echo "Copy complete!"
|
|
||||||
echo "Files copied: $COPIED"
|
|
||||||
echo "Files skipped: $SKIPPED"
|
|
||||||
echo "Target folder: $TARGET_FOLDER"
|
|
||||||
echo "=========================================="
|
|
||||||
|
|
||||||
# Try to apply the rules, if not emit 1
|
|
||||||
if add_sudoers_rule; then
|
|
||||||
echo "Operation successful"
|
|
||||||
else
|
|
||||||
echo "Operation failed - sudoers rule not applied"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
"""
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
from core.Constants import Constants
|
from core.Constants import Constants
|
||||||
from core.errors.logger import logger
|
from core.errors.logger import logger
|
||||||
from core.services.helpers.assets_as_strings.sudo_scripts.dns import dns_script
|
|
||||||
from core.services.helpers.assets_as_strings.sudo_scripts.firewall import firewall_script
|
|
||||||
from core.services.helpers.assets_as_strings.sudo_scripts.setup_script import setup_script
|
|
||||||
|
|
||||||
# generic
|
# generic
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
@ -17,38 +14,12 @@ def assets_folder_setup():
|
||||||
return copy_folders(initial_appimage_assets, current_assets_folder)
|
return copy_folders(initial_appimage_assets, current_assets_folder)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def sudo_assets_folder_setup() -> bool:
|
def sudo_assets_folder_setup() -> bool:
|
||||||
|
initial_appimage_assets = f"{Constants.APPDIR_HOME}/assets/sudo_scripts"
|
||||||
current_assets_folder = f"{Constants.HOME}/Downloads/hydraveil_sudo_scripts"
|
current_assets_folder = f"{Constants.HOME}/Downloads/hydraveil_sudo_scripts"
|
||||||
|
return copy_folders(initial_appimage_assets, current_assets_folder)
|
||||||
|
|
||||||
data = {
|
|
||||||
"dns": dns_script,
|
|
||||||
"firewall": firewall_script,
|
|
||||||
"setup.sh": setup_script
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Create the folder (if it doesn't exist)
|
|
||||||
os.makedirs(current_assets_folder, exist_ok=True)
|
|
||||||
logger.info(f"[MANAGE ASSETS] Folder in Downloads is setup at {current_assets_folder}.")
|
|
||||||
|
|
||||||
# Iterate through the dictionary and write files
|
|
||||||
for filename, content in data.items():
|
|
||||||
file_path = os.path.join(current_assets_folder, filename)
|
|
||||||
|
|
||||||
logger.info(f"[MANAGE ASSETS] We are preparing {filename}.")
|
|
||||||
|
|
||||||
# Skip if file already exists
|
|
||||||
if os.path.exists(file_path):
|
|
||||||
continue
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(file_path, 'w') as f:
|
|
||||||
f.write(content.lstrip('\n'))
|
|
||||||
logger.info(f"[MANAGE ASSETS] File written for {filename}.")
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"[MANAGE ASSETS] Failed to write to file for {filename} at {file_path} because {e}.")
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
def copy_folders(initial_appimage_assets: str, current_assets_folder: str) -> bool:
|
def copy_folders(initial_appimage_assets: str, current_assets_folder: str) -> bool:
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,6 @@ def auto_install_sudo_script() -> Result:
|
||||||
copied = sudo_assets_folder_setup()
|
copied = sudo_assets_folder_setup()
|
||||||
if not copied:
|
if not copied:
|
||||||
return Result(valid=False, message="Could not copy scripts to begin.")
|
return Result(valid=False, message="Could not copy scripts to begin.")
|
||||||
else:
|
|
||||||
logger.info(f"Folder setup in download folder at {setup_dir}")
|
|
||||||
else:
|
|
||||||
logger.info(f"Folder already existed in the download folder at {setup_dir}")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue