ssh-tunneling/tunnel.sh
2024-12-06 18:33:02 +05:30

187 lines
No EOL
5 KiB
Bash

#!/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"