diff --git a/tunnel.sh b/tunnel.sh new file mode 100644 index 0000000..bfd8ace --- /dev/null +++ b/tunnel.sh @@ -0,0 +1,187 @@ +#!/bin/bash + +# SSH Tunneling Management Script +# This script sets up bi-directional SSH tunnels for remote access through NAT + +# Configuration Variables +SSHD_ADDRESS="user@example.com" # Public SSH server address +REMOTE_ADDRESS="192.168.1.100" # Remote computer's internal IP +LOCAL_RDP_PORT="3389" # Local RDP port +REMOTE_RDP_PORT="3389" # Remote RDP port +TUNNEL_PORT="2222" # Tunnel port on public server +SOCKS_PORT="8765" # Local SOCKS proxy port +LOG_FILE="/var/log/ssh-tunnel.log" # Log file location +KEEP_ALIVE="60" # SSH keepalive interval in seconds +MAX_RETRIES=3 # Maximum number of connection retries + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Logging function +log() { + local level=$1 + local message=$2 + local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + echo -e "${timestamp} [${level}] ${message}" >> "$LOG_FILE" + + case $level in + "INFO") + echo -e "${GREEN}${message}${NC}" + ;; + "WARNING") + echo -e "${YELLOW}${message}${NC}" + ;; + "ERROR") + echo -e "${RED}${message}${NC}" + ;; + esac +} + +# Check if required commands exist +check_requirements() { + local requirements=("ssh" "nc") + for cmd in "${requirements[@]}"; do + if ! command -v "$cmd" &> /dev/null; then + log "ERROR" "Required command '$cmd' not found. Please install it." + exit 1 + fi + done +} + +# Test SSH connection +test_ssh_connection() { + log "INFO" "Testing SSH connection to $SSHD_ADDRESS..." + if ! ssh -q -o BatchMode=yes -o ConnectTimeout=5 "$SSHD_ADDRESS" exit; then + log "ERROR" "Cannot connect to SSH server. Check your credentials and connection." + return 1 + fi + return 0 +} + +# Check if port is available +check_port() { + local port=$1 + if nc -z localhost "$port" 2>/dev/null; then + log "WARNING" "Port $port is already in use" + return 1 + fi + return 0 +} + +# Setup reverse tunnel and SOCKS proxy +setup_reverse_tunnel() { + log "INFO" "Setting up reverse tunnel and SOCKS proxy..." + ssh -R "0.0.0.0:${TUNNEL_PORT}:127.0.0.1:${LOCAL_RDP_PORT}" \ + -D "$SOCKS_PORT" \ + -o "ServerAliveInterval=${KEEP_ALIVE}" \ + -o "ServerAliveCountMax=3" \ + -o "ExitOnForwardFailure=yes" \ + -N "$SSHD_ADDRESS" & + REVERSE_PID=$! + + # Check if tunnel is established + sleep 2 + if kill -0 "$REVERSE_PID" 2>/dev/null; then + log "INFO" "Reverse tunnel established (PID: $REVERSE_PID)" + else + log "ERROR" "Failed to establish reverse tunnel" + return 1 + fi +} + +# Setup local tunnel +setup_local_tunnel() { + log "INFO" "Setting up local tunnel..." + ssh -L "${TUNNEL_PORT}:${REMOTE_ADDRESS}:${REMOTE_RDP_PORT}" \ + -o "ServerAliveInterval=${KEEP_ALIVE}" \ + -o "ServerAliveCountMax=3" \ + -o "ExitOnForwardFailure=yes" \ + -N "$SSHD_ADDRESS" & + LOCAL_PID=$! + + # Check if tunnel is established + sleep 2 + if kill -0 "$LOCAL_PID" 2>/dev/null; then + log "INFO" "Local tunnel established (PID: $LOCAL_PID)" + else + log "ERROR" "Failed to establish local tunnel" + return 1 + fi +} + +# Cleanup function +cleanup() { + log "INFO" "Cleaning up tunnels..." + [[ -n $REVERSE_PID ]] && kill "$REVERSE_PID" 2>/dev/null + [[ -n $LOCAL_PID ]] && kill "$LOCAL_PID" 2>/dev/null + exit 0 +} + +# Handle signals +trap cleanup SIGINT SIGTERM + +# Main function +main() { + local tunnel_type=$1 + local retry_count=0 + + # Create log directory if it doesn't exist + mkdir -p "$(dirname "$LOG_FILE")" + + # Check requirements + check_requirements + + # Test SSH connection + test_ssh_connection || exit 1 + + # Check ports + check_port "$TUNNEL_PORT" || exit 1 + [[ "$tunnel_type" == "reverse" ]] && check_port "$SOCKS_PORT" || exit 1 + + # Main loop with retry logic + while true; do + case $tunnel_type in + "reverse") + setup_reverse_tunnel + ;; + "local") + setup_local_tunnel + ;; + *) + log "ERROR" "Invalid tunnel type. Use 'reverse' or 'local'" + exit 1 + ;; + esac + + if [[ $? -ne 0 ]]; then + ((retry_count++)) + if [[ $retry_count -ge $MAX_RETRIES ]]; then + log "ERROR" "Maximum retry attempts reached. Exiting." + exit 1 + fi + log "WARNING" "Tunnel failed. Retrying in 10 seconds... (Attempt $retry_count/$MAX_RETRIES)" + sleep 10 + continue + fi + + retry_count=0 + wait + done +} + +# Display usage information +usage() { + echo "Usage: $0 [reverse|local]" + echo " reverse - Setup reverse tunnel and SOCKS proxy" + echo " local - Setup local tunnel for remote access" + exit 1 +} + +# Check command line arguments +[[ $# -ne 1 ]] && usage + +# Start the script +main "$1" \ No newline at end of file