#!/usr/bin/env bash # Copyright (c) 2025. LUXIM d.o.o., Slovenia - Matjaž Mozetič. # backtunnel-share: Share a folder using reverse SSH for a limited duration # Syntax: backtunnel-share /path/to/folder with remoteuser:remotehost for 2h # Options: -p|--tunnel-port -l|--local-ssh-port -h|--help set -euo pipefail TUNNEL_PORT=2222 # remote-side port exposed via -R LOCAL_SSH_PORT=22 # local sshd port to forward to DURATION="" # required: e.g. 30m, 2h, 1d usage() { cat >&2 < [options] Positional (required, in order): /path/to/folder Informational only (the actual folder is mounted by backtunnel-access) with Literal keyword remoteuser:remotehost Or remoteuser@remotehost for Literal keyword e.g. 30m, 2h, 1d (passed to 'timeout') Options: -p, --tunnel-port N Remote tunnel port (default: ${TUNNEL_PORT}) -l, --local-ssh-port N Local sshd port to expose (default: ${LOCAL_SSH_PORT}) -h, --help Show this help Examples: $(basename "$0") ~/projects with alice:vps.example.com for 2h $(basename "$0") ~/projects with alice@vps.example.com for 1d -p 4422 -l 2222 EOF exit 1 } # --- basic positional parsing --- [[ $# -lt 5 ]] && usage FOLDER=$1 KW1=$2 REMOTE=$3 KW2=$4 DURATION=$5 shift 5 || true [[ "$KW1" != "with" ]] && usage [[ "$KW2" != "for" ]] && usage # --- optional flags --- while [[ $# -gt 0 ]]; do case "$1" in -p|--tunnel-port) [[ $# -lt 2 ]] && usage TUNNEL_PORT=$2 shift 2 ;; -l|--local-ssh-port) [[ $# -lt 2 ]] && usage LOCAL_SSH_PORT=$2 shift 2 ;; -h|--help) usage ;; *) echo "Unknown option: $1" >&2 usage ;; esac done # --- validate duration (timeout supports s,m,h,d) --- if [[ ! "$DURATION" =~ ^[0-9]+[smhd]$ ]]; then echo "Invalid duration '$DURATION' (use forms like 30m, 2h, 1d)." >&2 exit 1 fi # --- split remote user/host --- REMOTE_USER="" REMOTE_HOST="" if [[ "$REMOTE" == *:* ]]; then REMOTE_USER=${REMOTE%%:*} REMOTE_HOST=${REMOTE#*:} elif [[ "$REMOTE" == *"@"* ]]; then REMOTE_USER=${REMOTE%%@*} REMOTE_HOST=${REMOTE#*@} else echo "Invalid remote format. Use remoteuser:remotehost or remoteuser@remotehost" >&2 exit 1 fi # --- deps check --- command -v ssh >/dev/null 2>&1 || { echo "ssh not found."; exit 1; } command -v timeout >/dev/null 2>&1 || { echo "timeout not found."; exit 1; } echo "⏳ Sharing '${FOLDER}' via reverse SSH:" echo " local sshd port : ${LOCAL_SSH_PORT}" echo " remote bind port : ${TUNNEL_PORT} (on ${REMOTE_HOST})" echo " remote user : ${REMOTE_USER}" echo " duration : ${DURATION}" echo echo "Tip: On the remote side, mount with:" echo " backtunnel-access '${FOLDER}' from ${REMOTE_USER}@${REMOTE_HOST} -p ${TUNNEL_PORT}" timeout "$DURATION" ssh -N \ -R "${TUNNEL_PORT}:localhost:${LOCAL_SSH_PORT}" \ -- "${REMOTE_USER}@${REMOTE_HOST}" rc=$? if [[ $rc -eq 124 ]]; then echo "⏹️ Sharing ended: reached duration (${DURATION})." exit 0 fi exit "$rc"