Advanced multiply raspberry pi reverse ssh tunnels

Eran Goldman-Malka · July 24, 2018

I need to control more than one pi from ssh, and I found some questions without answers about it in StackOverflow.

I’ll write my own solution. Any suggestion is welcome.

Raspberry Pi

Installation:

sudo apt install sshpass
cat ~/.ssh/support.pub > /tmp/script
sshpass -p [SUPPORT_PASSWORD] ssh [SUPPORT_USER]@[SUPPORT_SERVER] 
bash -s /tmp/script >> /tmp/support.pub
cat /tmp/support.pub >> ~/.ssh/authorized_keys 

Usage

We’ll write a script that tries to connect to the server every minute. If there is a connection continue, if not, create one.

vim /opt/reversesssh


#!/bin/bash

SUPPORT_USER="openhabian"
SUPPORT_SERVER="192.168.178.55"

function getPort() {
  echo "/opt/next.py $(cat /var/lib/dbus/machine-id)" > /tmp/script
  port=$(ssh -l $SUPPORT_USER $SUPPORT_SERVER 'bash -s' echo $port
}

createTunnel() {
  getPort
  /usr/bin/ssh -N -R $port:localhost:22 -l $SUPPORT_USER $SUPPORT_SERVER
}

/bin/pidof ssh
if [[ $? -ne 0 ]]; then
  echo Creating new tunnel connection
  createTunnel
fi

sudo chmod +x /opt/reversessh

crontab -e

\*/1 \* \* \* * /opt/reversessh

Server

Installation

create an ssh key with an empty passphrase

ssh-keygen -f ~/.ssh/support -C support -t rsa

create the next python script

vim /opt/next.py


#!/usr/bin/python3
import sys
import json
import os.path

pi = {}
pi[sys.argv[1]] = 10000

dbPath = '/opt/portdb'
if not os.path.isfile(dbPath):
    with open(dbPath,'w+') as f:
        f.write(json.dumps(pi))
else:
    with open(dbPath,'r') as f:
        data = json.load(f)
        if not sys.argv[1] in data:
            data[sys.argv[1]] = 10000+len(data)

with open(dbPath,'w+') as f:
    f.write(json.dumps(data))

print(data[sys.argv[1]])

make it executable

sudo chmod +x /opt/next.py

Usage

From the server to connect to the pi

ssh -l pi -p [PI_PORT] localhost

Twitter, Facebook