dotfiles/scripts/tunnel
rpriven 5b6af65def
Organize scripts and clean up dotfiles
Changes:
- Added 80+ scripts with organized structure
  - payloads/ for third-party pentesting tools
  - pentesting/ for custom security scripts
  - Daily drivers remain flat for fast access
- Converted wes() function to proper script
- Removed .sh extensions from pentesting scripts
- Cleaned up aliases (removed 31 redundant lines)
- Added kanata/, build artifacts to gitignore
- Removed old fre.sh scripts and empty a.out
- Updated configs: helix, tmux, zsh, ulauncher, redshift

Security: All sensitive data excluded via gitignore
2025-11-07 14:48:21 -07:00

348 lines
8.4 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
# Script Name: tunnel
# Description: SSH tunnel manager with saved configurations
# Usage: tunnel list # List saved tunnels
# tunnel add name user@host:port ... # Add new tunnel config
# tunnel start name # Start a saved tunnel
# tunnel stop name # Stop a running tunnel
# tunnel status # Show active tunnels
VERSION="1.0.0"
TUNNEL_DIR="$HOME/.tunnels"
TUNNEL_CONF="$TUNNEL_DIR/tunnels.conf"
PID_DIR="$TUNNEL_DIR/pids"
# Colors
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly CYAN='\033[0;36m'
readonly MAGENTA='\033[0;35m'
readonly BOLD='\033[1m'
readonly NC='\033[0m'
# Initialize tunnel directory
init_tunnel() {
if [[ ! -d "$TUNNEL_DIR" ]]; then
mkdir -p "$TUNNEL_DIR" "$PID_DIR"
touch "$TUNNEL_CONF"
fi
}
show_help() {
echo -e "${BOLD}tunnel${NC} - SSH Tunnel Manager v${VERSION}"
echo
echo -e "${BOLD}USAGE:${NC}"
echo " tunnel <COMMAND> [OPTIONS]"
echo
echo -e "${BOLD}COMMANDS:${NC}"
echo -e " ${CYAN}list${NC} List all saved tunnels"
echo -e " ${CYAN}add NAME SPEC${NC} Add new tunnel configuration"
echo -e " ${CYAN}start NAME${NC} Start a saved tunnel"
echo -e " ${CYAN}stop NAME${NC} Stop a running tunnel"
echo -e " ${CYAN}restart NAME${NC} Restart a tunnel"
echo -e " ${CYAN}status${NC} Show active tunnels"
echo -e " ${CYAN}delete NAME${NC} Delete saved tunnel"
echo -e " ${CYAN}edit NAME${NC} Edit tunnel configuration"
echo
echo -e "${BOLD}TUNNEL TYPES:${NC}"
echo -e " ${YELLOW}Local forward:${NC} -L local_port:remote_host:remote_port"
echo -e " ${YELLOW}Remote forward:${NC} -R remote_port:local_host:local_port"
echo -e " ${YELLOW}Dynamic (SOCKS):${NC} -D local_port"
echo
echo -e "${BOLD}EXAMPLES:${NC}"
echo " # Forward local port 3000 to remote port 80"
echo " tunnel add web user@server.com -L 3000:localhost:80"
echo
echo " # Expose local port 8080 on remote port 9000"
echo " tunnel add reverse user@server.com -R 9000:localhost:8080"
echo
echo " # SOCKS proxy on local port 1080"
echo " tunnel add socks user@server.com -D 1080"
echo
echo " # Multiple forwards"
echo " tunnel add multi user@server.com -L 3000:localhost:80 -L 5432:localhost:5432"
echo
echo " # Start/stop tunnels"
echo " tunnel start web"
echo " tunnel stop web"
echo " tunnel status"
}
# Add tunnel configuration
add_tunnel() {
local name="$1"
shift
local ssh_target="$1"
shift
local ssh_args="$*"
if grep -q "^$name|" "$TUNNEL_CONF" 2>/dev/null; then
echo -e "${RED}Error:${NC} Tunnel '$name' already exists"
echo "Use: tunnel delete $name (then re-add)"
return 1
fi
echo "$name|$ssh_target|$ssh_args" >> "$TUNNEL_CONF"
echo -e "${GREEN}${NC} Added tunnel: ${BOLD}$name${NC}"
echo -e " Target: $ssh_target"
echo -e " Args: $ssh_args"
}
# List tunnels
list_tunnels() {
if [[ ! -f "$TUNNEL_CONF" ]] || [[ ! -s "$TUNNEL_CONF" ]]; then
echo -e "${YELLOW}No tunnels configured${NC}"
echo "Add one with: tunnel add <name> <user@host> <args>"
return 0
fi
echo -e "${BOLD}${CYAN}Saved Tunnels:${NC}"
echo
while IFS='|' read -r name target args; do
# Check if running
pid_file="$PID_DIR/$name.pid"
if [[ -f "$pid_file" ]]; then
pid=$(cat "$pid_file")
if ps -p "$pid" &>/dev/null; then
status="${GREEN}${NC} running"
else
status="${RED}${NC} dead"
rm -f "$pid_file"
fi
else
status="${YELLOW}${NC} stopped"
fi
echo -e " [$status] ${BOLD}$name${NC}"
echo -e " Target: $target"
echo -e " Args: $args"
echo
done < "$TUNNEL_CONF"
}
# Get tunnel config
get_tunnel() {
local name="$1"
if [[ ! -f "$TUNNEL_CONF" ]]; then
echo -e "${RED}Error:${NC} No tunnels configured" >&2
return 1
fi
local line=$(grep "^$name|" "$TUNNEL_CONF")
if [[ -z "$line" ]]; then
echo -e "${RED}Error:${NC} Tunnel '$name' not found" >&2
return 1
fi
echo "$line"
}
# Start tunnel
start_tunnel() {
local name="$1"
local config=$(get_tunnel "$name")
IFS='|' read -r _ target args <<< "$config"
pid_file="$PID_DIR/$name.pid"
# Check if already running
if [[ -f "$pid_file" ]]; then
pid=$(cat "$pid_file")
if ps -p "$pid" &>/dev/null; then
echo -e "${YELLOW}${NC} Tunnel '$name' is already running (PID: $pid)"
return 0
else
rm -f "$pid_file"
fi
fi
echo -e "${CYAN}[*]${NC} Starting tunnel: ${BOLD}$name${NC}"
echo -e " Target: $target"
echo -e " Args: $args"
# Start SSH tunnel in background
ssh -f -N $args "$target" &
local pid=$!
echo "$pid" > "$pid_file"
echo -e "${GREEN}${NC} Tunnel started (PID: $pid)"
}
# Stop tunnel
stop_tunnel() {
local name="$1"
pid_file="$PID_DIR/$name.pid"
if [[ ! -f "$pid_file" ]]; then
echo -e "${YELLOW}${NC} Tunnel '$name' is not running"
return 0
fi
pid=$(cat "$pid_file")
if ! ps -p "$pid" &>/dev/null; then
echo -e "${YELLOW}${NC} Tunnel process not found (stale PID file)"
rm -f "$pid_file"
return 0
fi
echo -e "${CYAN}[*]${NC} Stopping tunnel: ${BOLD}$name${NC} (PID: $pid)"
kill "$pid" 2>/dev/null || true
# Wait a moment and verify
sleep 1
if ps -p "$pid" &>/dev/null; then
echo -e "${YELLOW}${NC} Process didn't stop gracefully, using SIGKILL"
kill -9 "$pid" 2>/dev/null || true
fi
rm -f "$pid_file"
echo -e "${GREEN}${NC} Tunnel stopped"
}
# Restart tunnel
restart_tunnel() {
local name="$1"
echo -e "${CYAN}[*]${NC} Restarting tunnel: ${BOLD}$name${NC}"
stop_tunnel "$name"
sleep 1
start_tunnel "$name"
}
# Show status of all tunnels
show_status() {
echo -e "${BOLD}${CYAN}Active SSH Tunnels:${NC}"
echo
local found_any=false
if [[ -f "$TUNNEL_CONF" ]]; then
while IFS='|' read -r name target args; do
pid_file="$PID_DIR/$name.pid"
if [[ -f "$pid_file" ]]; then
pid=$(cat "$pid_file")
if ps -p "$pid" &>/dev/null; then
found_any=true
echo -e " ${GREEN}${NC} ${BOLD}$name${NC} (PID: $pid)"
echo -e " $target $args"
echo
fi
fi
done < "$TUNNEL_CONF"
fi
if [[ "$found_any" == "false" ]]; then
echo -e " ${YELLOW}No active tunnels${NC}"
fi
}
# Delete tunnel
delete_tunnel() {
local name="$1"
if ! grep -q "^$name|" "$TUNNEL_CONF" 2>/dev/null; then
echo -e "${RED}Error:${NC} Tunnel '$name' not found"
return 1
fi
# Stop if running
pid_file="$PID_DIR/$name.pid"
if [[ -f "$pid_file" ]]; then
echo -e "${YELLOW}${NC} Stopping running tunnel first..."
stop_tunnel "$name"
fi
# Remove from config
sed -i "/^$name|/d" "$TUNNEL_CONF"
echo -e "${GREEN}${NC} Deleted tunnel: ${BOLD}$name${NC}"
}
# Edit tunnel
edit_tunnel() {
local name="$1"
if ! grep -q "^$name|" "$TUNNEL_CONF" 2>/dev/null; then
echo -e "${RED}Error:${NC} Tunnel '$name' not found"
return 1
fi
"${EDITOR:-vim}" "$TUNNEL_CONF"
echo -e "${GREEN}${NC} Configuration updated"
}
# Initialize
init_tunnel
# Parse command
if [[ $# -eq 0 ]] || [[ "$1" =~ ^(-h|--help|help)$ ]]; then
show_help
exit 0
fi
command="$1"
shift
case "$command" in
list|ls)
list_tunnels
;;
add|new)
if [[ $# -lt 2 ]]; then
echo -e "${RED}Error:${NC} Usage: tunnel add <name> <user@host> <args>"
exit 1
fi
add_tunnel "$@"
;;
start|up)
if [[ $# -lt 1 ]]; then
echo -e "${RED}Error:${NC} Usage: tunnel start <name>"
exit 1
fi
start_tunnel "$1"
;;
stop|down)
if [[ $# -lt 1 ]]; then
echo -e "${RED}Error:${NC} Usage: tunnel stop <name>"
exit 1
fi
stop_tunnel "$1"
;;
restart)
if [[ $# -lt 1 ]]; then
echo -e "${RED}Error:${NC} Usage: tunnel restart <name>"
exit 1
fi
restart_tunnel "$1"
;;
status|ps)
show_status
;;
delete|del|rm)
if [[ $# -lt 1 ]]; then
echo -e "${RED}Error:${NC} Usage: tunnel delete <name>"
exit 1
fi
delete_tunnel "$1"
;;
edit)
if [[ $# -lt 1 ]]; then
echo -e "${RED}Error:${NC} Usage: tunnel edit <name>"
exit 1
fi
edit_tunnel "$1"
;;
*)
echo -e "${RED}Error:${NC} Unknown command: $command"
echo "Run 'tunnel --help' for usage"
exit 1
;;
esac