testsAndMisc/linux_configuration/features/lib/nc_remote.sh
Krzysztof kuhy Rudnicki 7581a904cd
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (mypy, mypy) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (pylint, pylint) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (rest, ) (push) Waiting to run
Pre-commit checks / pre-commit (${{ matrix.group }}) (shellcheck, shellcheck) (push) Waiting to run
Python tests / test (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
Shell tests / shell-tests (push) Waiting to run
Shell tests / lib-tests (push) Waiting to run
Shell tests / arch-tests (push) Waiting to run
feat(pi): rustscan instead of nmap
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-11-10 14:32:12 +01:00

130 lines
4.0 KiB
Bash
Executable File

#!/bin/bash
# Remote host discovery and connection setup.
#
# Sourced by setup_nextcloud_raspberry.sh; split out to keep it under the 250-line
# cap. Sourced rather than run, so it inherits the caller's strict mode
# and the variables defined above the source line.
discover_remote_laptop() {
log_info "Auto-discovering remote laptop on local network..."
# Ensure we have the tools we need
ensure_dependencies
# Get local IP to exclude ourselves (works on both Linux variants)
local my_ip
my_ip=$(ip -4 addr show | grep -oP '(?<=inet\s)(?!127\.)\d+(\.\d+){3}' | head -1)
# Get gateway
local gateway
gateway=$(ip route | grep default | awk '{print $3}' | head -1)
local network="${gateway%.*}.0/24"
log_info "Local IP: $my_ip, Gateway: $gateway, Network: $network"
# Use rustscan for fast parallel SSH port scanning
log_info "Scanning network for SSH-enabled devices (using rustscan)..."
local ssh_hosts
# Greppable output: one "IP -> [22]" line per host with the port open
ssh_hosts=$(rustscan -a "$network" -p 22 -g 2>/dev/null | awk '{print $1}' | grep -vw "$my_ip" | sort -u) || true
if [[ -z $ssh_hosts ]]; then
die "No SSH-enabled devices found on network"
fi
local host_count
host_count=$(echo "$ssh_hosts" | wc -l)
log_info "Found $host_count SSH-enabled device(s): $(echo "$ssh_hosts" | tr '\n' ' ')"
# Common usernames to try (in order of preference)
local common_users=("$REMOTE_LAPTOP_USER" "kuchy" "kuhy" "$(whoami)" "pi" "user" "admin")
# Remove duplicates while preserving order
local users=()
for u in "${common_users[@]}"; do
local is_dup=0
for existing in "${users[@]}"; do
if [[ $u == "$existing" ]]; then
is_dup=1
break
fi
done
if [[ $is_dup -eq 0 ]]; then
users+=("$u")
fi
done
log_info "Will try usernames: ${users[*]}"
# Find a device with passwordless SSH and SD card
local found_laptop=""
local found_user=""
local idx=0
for ip in $ssh_hosts; do
idx=$((idx + 1))
# Skip gateway
if [[ $ip == "$gateway" ]]; then
log_info "[$idx/$host_count] Skipping $ip (gateway)"
continue
fi
log_info "[$idx/$host_count] $ip - Trying SSH key access with common usernames..."
# Try each username
for try_user in "${users[@]}"; do
if ssh -o BatchMode=yes -o ConnectTimeout=2 -o StrictHostKeyChecking=accept-new "${try_user}@${ip}" "echo ok" 2>/dev/null | grep -q "ok"; then
log_success "[$idx/$host_count] $ip - SSH key access confirmed with user '$try_user'!"
found_user="$try_user"
# Check if there's a removable device (SD card)
log_info "[$idx/$host_count] $ip - Checking for SD card..."
local has_sd
has_sd=$(ssh -o BatchMode=yes -o ConnectTimeout=2 "${try_user}@${ip}" "lsblk -d -o NAME,RM,TRAN 2>/dev/null | grep -E '1.*(usb|mmc)' | head -1" 2>/dev/null || true)
if [[ -n $has_sd ]]; then
log_success "[$idx/$host_count] $ip - Found SD card: $has_sd"
found_laptop="$ip"
break 2 # Break out of both loops
else
log_warning "[$idx/$host_count] $ip - No SD card detected, saving as fallback..."
if [[ -z $found_laptop ]]; then
found_laptop="$ip"
fi
fi
break # Found working user, move to next IP if no SD card
fi
done
if [[ -z $found_user ]]; then
log_info "[$idx/$host_count] $ip - No SSH key access with any common username"
fi
done
# If no passwordless access found, prompt user for username
if [[ -z $found_laptop ]] || [[ -z $found_user ]]; then
log_warning "No device with passwordless SSH found using common usernames."
# Pick first available SSH host
found_laptop=$(echo "$ssh_hosts" | grep -vw "$gateway" | head -1)
if [[ -z $found_laptop ]]; then
die "Could not find any suitable SSH-enabled device"
fi
log_info "Found SSH host at $found_laptop but need credentials."
read -r -p "Enter username for $found_laptop: " found_user
if [[ -z $found_user ]]; then
die "No username provided"
fi
fi
REMOTE_LAPTOP_IP="$found_laptop"
REMOTE_LAPTOP_USER="$found_user"
log_success "Selected remote laptop: ${REMOTE_LAPTOP_USER}@${REMOTE_LAPTOP_IP}"
# Save to config file for future use
save_config
}