Update default mount point to $HOME/remote-rssh for consistency, and introduce backtunnel-auth-setup script for restricted SFTP-only key management. Update docs, scripts, and uninstall/install logic to reflect changes. Ensure robust handling of user-specified mount points in backtunnel-access.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
PORT=2222
|
||||
MOUNTPOINT="/mnt/remote-rssh"
|
||||
MOUNTPOINT="$HOME/remote-rssh"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 /path/to/folder from remoteuser:remotehost [-p PORT] [-m MOUNTPOINT]" >&2
|
||||
@@ -47,6 +47,32 @@ while [[ $# -gt 0 ]]; do
|
||||
esac
|
||||
done
|
||||
|
||||
# --- normalize and prepare mount point ---
|
||||
# Expand leading '~' even if quoted or passed via GUI
|
||||
# Note: default uses $HOME; still expand '~' if passed via CLI/GUI
|
||||
if [[ "${MOUNTPOINT:-}" == "~"* ]]; then
|
||||
MOUNTPOINT="${MOUNTPOINT/#\~/$HOME}"
|
||||
fi
|
||||
# Make absolute if realpath exists (doesn't fail if missing)
|
||||
if command -v realpath >/dev/null 2>&1; then
|
||||
MOUNTPOINT="$(realpath -m -- "$MOUNTPOINT")"
|
||||
fi
|
||||
# Create if missing, with restrictive perms
|
||||
if [[ ! -d "$MOUNTPOINT" ]]; then
|
||||
mkdir -p -- "$MOUNTPOINT"
|
||||
chmod 700 -- "$MOUNTPOINT" 2>/dev/null || true
|
||||
fi
|
||||
# Must be user-writable and empty (warn if non-empty to avoid masking files)
|
||||
if [[ ! -w "$MOUNTPOINT" ]]; then
|
||||
echo "Mount point '$MOUNTPOINT' is not writable by $(id -un)." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Warn if non-empty to avoid masking existing files
|
||||
if [[ -n "$(ls -A -- "$MOUNTPOINT" 2>/dev/null || true)" ]]; then
|
||||
echo "⚠️ Mount point '$MOUNTPOINT' is not empty; its contents will be hidden while mounted." >&2
|
||||
fi
|
||||
|
||||
# --- split remote user/host (supports user:host or user@host) ---
|
||||
REMOTE_USER=""
|
||||
REMOTE_HOST=""
|
||||
@@ -66,10 +92,7 @@ fi
|
||||
command -v sshfs >/dev/null 2>&1 || { echo "sshfs not found. Install sshfs first."; exit 1; }
|
||||
command -v mountpoint >/dev/null 2>&1 || { echo "mountpoint utility not found."; exit 1; }
|
||||
|
||||
# --- prepare mountpoint ---
|
||||
if [[ ! -d "$MOUNTPOINT" ]]; then
|
||||
mkdir -p -- "$MOUNTPOINT"
|
||||
fi
|
||||
command -v sftp >/dev/null 2>&1 || { echo "sftp not found (usually provided by openssh)."; exit 1; }
|
||||
|
||||
# Avoid double-mount
|
||||
if mountpoint -q -- "$MOUNTPOINT"; then
|
||||
@@ -79,13 +102,51 @@ fi
|
||||
|
||||
echo "🔗 Mounting '$FOLDER' from '$REMOTE_USER@$REMOTE_HOST' via reverse-tunnel localhost:$PORT → '$MOUNTPOINT' ..."
|
||||
|
||||
# --- ensure passwordless auth via tunnel (optional but user-friendly) ---
|
||||
SSH_IDENTITY_OPTS=()
|
||||
if [[ -f "$HOME/.ssh/id_ed25519_backtunnel" ]]; then
|
||||
SSH_IDENTITY_OPTS+=( -o IdentityFile="$HOME/.ssh/id_ed25519_backtunnel" -o IdentitiesOnly=yes )
|
||||
fi
|
||||
|
||||
SFTP_ID_OPTS=()
|
||||
if [[ -f "$HOME/.ssh/id_ed25519_backtunnel" ]]; then
|
||||
SFTP_ID_OPTS+=( -o IdentityFile="$HOME/.ssh/id_ed25519_backtunnel" -o IdentitiesOnly=yes )
|
||||
fi
|
||||
|
||||
if ! ssh -o BatchMode=yes -o StrictHostKeyChecking=accept-new \
|
||||
-p "$PORT" "${SSH_IDENTITY_OPTS[@]}" "$REMOTE_USER@localhost" true 2>/dev/null; then cat >&2 <<EOF
|
||||
⚠️ Passwordless auth not set for $REMOTE_USER@localhost:$PORT.
|
||||
You can initialize a tunnel-only, SFTP-only key with:
|
||||
backtunnel-auth-setup -p $PORT $REMOTE_USER@localhost
|
||||
(It will ask once for the server password to install and restrict the key.)
|
||||
EOF
|
||||
# continue anyway; sshfs may prompt for password
|
||||
fi
|
||||
|
||||
echo "Checking remote path visibility via SFTP ..."
|
||||
|
||||
if ! sftp -q -P "$PORT" -o StrictHostKeyChecking=accept-new "${SFTP_ID_OPTS[@]}" \
|
||||
"$REMOTE_USER@localhost" <<< "ls -1 \"$FOLDER\"" >/dev/null 2>&1; then
|
||||
echo "⚠️ Remote path '$FOLDER' not listable via SFTP. It may not exist or permissions deny access." >&2
|
||||
echo " Proceeding to mount; sshfs may fail if the path is invalid." >&2
|
||||
fi
|
||||
|
||||
SSH_CMD="ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new"
|
||||
# If identity options are present, append them to SSH_CMD
|
||||
if [[ ${#SSH_IDENTITY_OPTS[@]} -gt 0 ]]; then
|
||||
# Join array safely
|
||||
for opt in "${SSH_IDENTITY_OPTS[@]}"; do
|
||||
SSH_CMD+=" $opt"
|
||||
done
|
||||
fi
|
||||
|
||||
sshfs \
|
||||
-p "$PORT" \
|
||||
-o reconnect \
|
||||
-o ServerAliveInterval=15 \
|
||||
-o ServerAliveCountMax=3 \
|
||||
-o ssh_command="ssh -o ConnectTimeout=10" \
|
||||
-o ssh_command="$SSH_CMD" \
|
||||
-- "$REMOTE_USER@localhost:$FOLDER" "$MOUNTPOINT"
|
||||
|
||||
echo "✅ Mounted at: $MOUNTPOINT"
|
||||
echo "To unmount: fusermount -u \"$MOUNTPOINT\""
|
||||
echo "To unmount: fusermount -u \"$MOUNTPOINT\" || fusermount3 -u \"$MOUNTPOINT\""
|
||||
|
||||
44
scripts/backtunnel-auth-setup
Normal file
44
scripts/backtunnel-auth-setup
Normal file
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
# Initialize tunnel-only SSH auth for BackTunnel (Option A)
|
||||
# Usage: backtunnel-auth-setup [-p PORT] user@localhost
|
||||
set -euo pipefail
|
||||
|
||||
PORT=2222
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
-p|--port) PORT="$2"; shift 2;;
|
||||
-h|--help)
|
||||
echo "Usage: backtunnel-auth-setup [-p PORT] user@localhost"
|
||||
exit 0;;
|
||||
*) break;;
|
||||
esac
|
||||
done
|
||||
|
||||
DEST="${1:-}"
|
||||
[[ -n "$DEST" ]] || { echo "Missing destination (e.g., user@localhost)."; exit 1; }
|
||||
|
||||
KEY="$HOME/.ssh/id_ed25519_backtunnel"
|
||||
PUB="$KEY.pub"
|
||||
|
||||
# 1) Create a dedicated key if missing
|
||||
if [[ ! -f "$KEY" ]]; then
|
||||
echo "Generating dedicated key at $KEY ..."
|
||||
ssh-keygen -t ed25519 -f "$KEY" -N "" -C "backtunnel"
|
||||
fi
|
||||
|
||||
# 2) Append restricted key only (idempotent): tunnel-only + SFTP-only
|
||||
echo "Installing restricted key (tunnel-only, SFTP-only) via port $PORT ..."
|
||||
RESTRICTED_LINE="$(printf 'from="127.0.0.1",command="internal-sftp",restrict '; cat "$PUB")"
|
||||
ssh -p "$PORT" "$DEST" bash -lc '
|
||||
set -euo pipefail
|
||||
umask 077
|
||||
mkdir -p ~/.ssh
|
||||
touch ~/.ssh/authorized_keys
|
||||
chmod 600 ~/.ssh/authorized_keys
|
||||
# Only append if not already present
|
||||
if ! grep -Fqx -- "$RESTRICTED_LINE" ~/.ssh/authorized_keys 2>/dev/null; then
|
||||
printf "%s\n" "$RESTRICTED_LINE" >> ~/.ssh/authorized_keys
|
||||
fi
|
||||
' _ RESTRICTED_LINE="$RESTRICTED_LINE"
|
||||
|
||||
echo "Done. This key will only work via the reverse tunnel (127.0.0.1) and only for SFTP."
|
||||
@@ -64,7 +64,7 @@ profile_apply_defaults() { # set globals if unset; named overrides default
|
||||
# defaults
|
||||
v="$(ini_get default tunnel_port)"; [[ -n "$v" && "${TUNNEL_PORT}" == "2222" ]] && TUNNEL_PORT="$v"
|
||||
v="$(ini_get default local_ssh_port)"; [[ -n "$v" && "${LOCAL_SSH_PORT}" == "22" ]] && LOCAL_SSH_PORT="$v"
|
||||
v="$(ini_get default invite_mount)"; [[ -n "$v" && "${INVITE_MOUNT}" == "/mnt/remote-rssh" ]] && INVITE_MOUNT="$v"
|
||||
v="$(ini_get default invite_mount)"; [[ -n "$v" && "${INVITE_MOUNT}" == "$HOME/remote-rssh" ]] && INVITE_MOUNT="$v"
|
||||
v="$(ini_get default invite)"; [[ "${v,,}" == "true" ]] && INVITE=true
|
||||
v="$(ini_get default qr)"; [[ "${v,,}" == "true" ]] && QR=true
|
||||
if [[ -z "$DURATION" ]]; then
|
||||
@@ -84,7 +84,7 @@ LOCAL_SSH_PORT=22 # local sshd port to forward to
|
||||
DURATION="" # required: e.g. 30m, 2h, 1d
|
||||
|
||||
INVITE=false # print a ready-to-copy access command
|
||||
INVITE_MOUNT="/mnt/remote-rssh"
|
||||
INVITE_MOUNT="$HOME/remote-rssh"
|
||||
INVITE_FILE=""
|
||||
QR=false # render invite as terminal QR (requires qrencode)
|
||||
|
||||
@@ -214,19 +214,30 @@ echo
|
||||
# --- print invite (optional) ---
|
||||
if $INVITE; then
|
||||
INVITE_CMD="backtunnel-access '${FOLDER}' from ${REMOTE_USER}@${REMOTE_HOST} -p ${TUNNEL_PORT} -m '${INVITE_MOUNT}'"
|
||||
# Also provide a one-time auth bootstrap that installs a restricted, tunnel-only SFTP key
|
||||
AUTH_CMD="backtunnel-auth-setup -p ${TUNNEL_PORT} ${REMOTE_USER}@localhost"
|
||||
|
||||
INVITE_TEXT=$(
|
||||
cat <<EOT
|
||||
# Paste this on the REMOTE host (or SSH there first, then paste):
|
||||
cat <<EOT
|
||||
|
||||
# 1) (one-time) install a tunnel-only, SFTP-only key via the reverse tunnel:
|
||||
${AUTH_CMD}
|
||||
|
||||
# 2) mount the share:
|
||||
${INVITE_CMD}
|
||||
|
||||
# Unmount when done:
|
||||
# (use the one available on your system)
|
||||
fusermount -u '${INVITE_MOUNT}' || fusermount3 -u '${INVITE_MOUNT}'
|
||||
|
||||
EOT
|
||||
)
|
||||
)
|
||||
|
||||
echo "🔗 Invite (copy to chat):"
|
||||
echo "------------------------------------------------------------"
|
||||
echo "${AUTH_CMD}"
|
||||
echo "${INVITE_CMD}"
|
||||
echo "------------------------------------------------------------"
|
||||
|
||||
if [[ -n "${INVITE_FILE}" ]]; then
|
||||
printf "%s\n" "${INVITE_TEXT}" > "${INVITE_FILE}"
|
||||
echo "Saved invite to: ${INVITE_FILE}"
|
||||
|
||||
@@ -22,7 +22,7 @@ REMOTE_DEFAULT="user@vps.example.com"
|
||||
DURATION_DEFAULT="2h"
|
||||
TPORT_DEFAULT="2222"
|
||||
LPORT_DEFAULT="22"
|
||||
INVITE_MOUNT_DEFAULT="/mnt/remote-rssh"
|
||||
INVITE_MOUNT_DEFAULT="$HOME/remote-rssh"
|
||||
|
||||
# Profiles (search order: user -> system -> packaged fallback)
|
||||
PROFILES_USER="${XDG_CONFIG_HOME:-$HOME/.config}/backtunnel/profiles.ini"
|
||||
|
||||
@@ -20,6 +20,7 @@ say "Installing to PREFIX=${PREFIX} DESTDIR=${DESTDIR}"
|
||||
# --- Binaries (CLI) ---
|
||||
install -Dm755 "scripts/backtunnel-share" "$BINDIR/backtunnel-share"
|
||||
install -Dm755 "scripts/backtunnel-access" "$BINDIR/backtunnel-access"
|
||||
install -Dm755 "scripts/backtunnel-auth-setup" "$BINDIR/backtunnel-auth-setup"
|
||||
|
||||
# --- GUI wrappers (optional) ---
|
||||
install -Dm755 "scripts/backtunnel-share-gui" "$BINDIR/backtunnel-share-gui"
|
||||
|
||||
@@ -38,6 +38,7 @@ say "Uninstalling from PREFIX=${PREFIX} DESTDIR=${DESTDIR} (PURGE=${PURGE})"
|
||||
# --- Remove binaries ---
|
||||
rm -f "$BINDIR/backtunnel-share" \
|
||||
"$BINDIR/backtunnel-access" \
|
||||
"$BINDIR/backtunnel-auth-setup" \
|
||||
"$BINDIR/backtunnel-share-gui" \
|
||||
"$BINDIR/backtunnel-access-gui" \
|
||||
"$BINDIR/backtunnel-open-term" \
|
||||
|
||||
Reference in New Issue
Block a user