Add reverse SSH tunnel (autossh) as VPN option in operator wizard

Generates a dedicated tunnel keypair during setup, prints public key
for operator to pre-stage on server, writes private key to SD card.
On first boot: installs autossh, writes bb-tunnel.service with
correct RemoteForward and reconnect settings. Zero network traffic
until operator initiates connection through the tunnel port.
This commit is contained in:
Cobra
2026-04-07 14:30:10 -04:00
parent ae79d64913
commit 2b00b28de6
+94 -2
View File
@@ -316,11 +316,18 @@ step "VPN Tunnel"
echo " [1] None" echo " [1] None"
echo " [2] Tailscale" echo " [2] Tailscale"
echo " [3] WireGuard" echo " [3] WireGuard"
prompt_default vpn_opt "Select VPN (1-3)" "1" echo " [4] Reverse SSH Tunnel (autossh) — no traffic until operator connects"
prompt_default vpn_opt "Select VPN (1-4)" "1"
BB_VPN="none" BB_VPN="none"
TAILSCALE_KEY="" TAILSCALE_KEY=""
WG_CONFIG="" WG_CONFIG=""
AUTOSSH_SERVER=""
AUTOSSH_USER="root"
AUTOSSH_PORT="22"
AUTOSSH_REMOTE_PORT=""
AUTOSSH_PRIVKEY=""
AUTOSSH_PUBKEY=""
if [[ "$vpn_opt" == "1" ]]; then if [[ "$vpn_opt" == "1" ]]; then
BB_VPN="none" BB_VPN="none"
@@ -333,6 +340,29 @@ elif [[ "$vpn_opt" == "3" ]]; then
prompt_default wg_config_path "Path to WireGuard config (wg0.conf)" "" prompt_default wg_config_path "Path to WireGuard config (wg0.conf)" ""
[[ -f "$wg_config_path" ]] || error "File not found: $wg_config_path" [[ -f "$wg_config_path" ]] || error "File not found: $wg_config_path"
WG_CONFIG=$(cat "$wg_config_path") WG_CONFIG=$(cat "$wg_config_path")
elif [[ "$vpn_opt" == "4" ]]; then
BB_VPN="autossh"
prompt_default AUTOSSH_SERVER "Operator SSH server (host or IP)" ""
[[ -n "$AUTOSSH_SERVER" ]] || error "Server address required"
prompt_default AUTOSSH_USER "SSH user on server" "root"
prompt_default AUTOSSH_PORT "SSH port on server" "22"
DEFAULT_REMOTE_PORT=$(( 20000 + RANDOM % 10000 ))
prompt_default AUTOSSH_REMOTE_PORT "Remote tunnel port (device SSH appears here on server)" "$DEFAULT_REMOTE_PORT"
# Generate dedicated tunnel keypair — keeps it separate from device management key
_TMP_TKEY=$(mktemp)
ssh-keygen -t ed25519 -N "" -C "bb-tunnel-${DEVICE_ID}" -f "$_TMP_TKEY" -q
AUTOSSH_PRIVKEY=$(cat "$_TMP_TKEY")
AUTOSSH_PUBKEY=$(cat "${_TMP_TKEY}.pub")
rm -f "$_TMP_TKEY" "${_TMP_TKEY}.pub"
echo ""
echo -e " ${YELLOW}Add this public key to ${AUTOSSH_USER}@${AUTOSSH_SERVER}:~/.ssh/authorized_keys before powering on:${NC}"
echo ""
echo -e " ${BOLD}${AUTOSSH_PUBKEY}${NC}"
echo ""
echo -n -e "${CYAN} Press Enter once the key is on the server:${NC} "
read -r
else else
error "Invalid VPN option" error "Invalid VPN option"
fi fi
@@ -365,7 +395,11 @@ fi
echo "WiFi: ${BOLD}$([ -n "$WIFI_SSID" ] && echo "$WIFI_SSID" || echo "disabled")${NC}" echo "WiFi: ${BOLD}$([ -n "$WIFI_SSID" ] && echo "$WIFI_SSID" || echo "disabled")${NC}"
echo "SSH Mode: ${BOLD}${SSH_MODE}${NC}" echo "SSH Mode: ${BOLD}${SSH_MODE}${NC}"
echo "Auto-start: ${BOLD}${BB_MODE}${NC}" echo "Auto-start: ${BOLD}${BB_MODE}${NC}"
echo "VPN: ${BOLD}${BB_VPN}${NC}" if [[ "$BB_VPN" == "autossh" ]]; then
echo "VPN: ${BOLD}autossh → ${AUTOSSH_USER}@${AUTOSSH_SERVER}:${AUTOSSH_PORT} (remote port ${AUTOSSH_REMOTE_PORT})${NC}"
else
echo "VPN: ${BOLD}${BB_VPN}${NC}"
fi
echo "Alerter: ${BOLD}$([ -n "$BB_ALERTER_WEBHOOK" ] && echo "enabled" || echo "disabled")${NC}" echo "Alerter: ${BOLD}$([ -n "$BB_ALERTER_WEBHOOK" ] && echo "enabled" || echo "disabled")${NC}"
echo "" echo ""
@@ -526,6 +560,21 @@ if [[ "$BB_VPN" == "wireguard" && -n "$WG_CONFIG" ]]; then
chmod 600 "${MOUNT_POINT}/etc/wireguard/wg0.conf" chmod 600 "${MOUNT_POINT}/etc/wireguard/wg0.conf"
fi fi
# Store autossh config if needed
if [[ "$BB_VPN" == "autossh" ]]; then
echo "BB_AUTOSSH_SERVER=\"${AUTOSSH_SERVER}\"" >> "${MOUNT_POINT}/root/bb-config.env"
echo "BB_AUTOSSH_USER=\"${AUTOSSH_USER}\"" >> "${MOUNT_POINT}/root/bb-config.env"
echo "BB_AUTOSSH_PORT=\"${AUTOSSH_PORT}\"" >> "${MOUNT_POINT}/root/bb-config.env"
echo "BB_AUTOSSH_REMOTE_PORT=\"${AUTOSSH_REMOTE_PORT}\"" >> "${MOUNT_POINT}/root/bb-config.env"
# Write tunnel private key — separate from device management key
mkdir -p "${MOUNT_POINT}/root/.ssh"
echo "$AUTOSSH_PRIVKEY" > "${MOUNT_POINT}/root/.ssh/bb-tunnel-key"
chmod 600 "${MOUNT_POINT}/root/.ssh/bb-tunnel-key"
info "Tunnel key written to /root/.ssh/bb-tunnel-key"
unset AUTOSSH_PRIVKEY
fi
chmod 600 "${MOUNT_POINT}/root/bb-config.env" chmod 600 "${MOUNT_POINT}/root/bb-config.env"
info "Configuration written" info "Configuration written"
@@ -573,6 +622,40 @@ elif [[ "${BB_VPN:-}" == "wireguard" ]]; then
apt-get update >/dev/null 2>&1 apt-get update >/dev/null 2>&1
apt-get install -y wireguard >/dev/null 2>&1 apt-get install -y wireguard >/dev/null 2>&1
systemctl enable --now wg-quick@wg0 || echo "[-] WireGuard startup failed" systemctl enable --now wg-quick@wg0 || echo "[-] WireGuard startup failed"
elif [[ "${BB_VPN:-}" == "autossh" ]]; then
echo "[*] Installing autossh..."
apt-get update >/dev/null 2>&1
apt-get install -y autossh >/dev/null 2>&1
chmod 600 /root/.ssh/bb-tunnel-key 2>/dev/null || true
cat > /etc/systemd/system/bb-tunnel.service << SVCEOF
[Unit]
Description=BigBrother reverse SSH tunnel
After=network-online.target
Wants=network-online.target
[Service]
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -N \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-o StrictHostKeyChecking=no \
-o ExitOnForwardFailure=yes \
-i /root/.ssh/bb-tunnel-key \
-p ${BB_AUTOSSH_PORT} \
-R ${BB_AUTOSSH_REMOTE_PORT}:localhost:22 \
${BB_AUTOSSH_USER}@${BB_AUTOSSH_SERVER}
Restart=always
RestartSec=30
User=root
[Install]
WantedBy=multi-user.target
SVCEOF
systemctl daemon-reload
systemctl enable --now bb-tunnel.service || echo "[-] Tunnel service startup failed"
echo "[+] Reverse SSH tunnel configured (remote port ${BB_AUTOSSH_REMOTE_PORT})"
fi fi
# Network alerter # Network alerter
@@ -661,6 +744,15 @@ else
echo " ssh -i $(dirname $ssh_pubkey_path)/$(basename $ssh_pubkey_path .pub) root@<DEVICE_IP>" echo " ssh -i $(dirname $ssh_pubkey_path)/$(basename $ssh_pubkey_path .pub) root@<DEVICE_IP>"
fi fi
echo ""
if [[ "$BB_VPN" == "autossh" ]]; then
echo ""
echo "${CYAN}Tunnel connection (after first boot):${NC}"
echo " From operator server: ssh -p ${AUTOSSH_REMOTE_PORT} root@127.0.0.1"
echo " One-liner from anywhere (requires GatewayPorts yes on server):"
echo " ssh -p ${AUTOSSH_REMOTE_PORT} root@${AUTOSSH_SERVER}"
fi
echo "" echo ""
echo "${CYAN}Monitor first-boot:${NC}" echo "${CYAN}Monitor first-boot:${NC}"
echo " ssh root@<DEVICE_IP> 'tail -f /root/bb-firstboot.log'" echo " ssh root@<DEVICE_IP> 'tail -f /root/bb-firstboot.log'"