Advanced multiply raspberry pi reverse ssh tunnels

erangoldman@gmail.com, 24 July 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.

Architecture

Raspberry Pi

Installation:

<span class="hljs-built_in">sudo apt install  sshpass
echo</span> <span class="hljs-string">"cat ~/.ssh/support.pub"</span> >> /tmp/script
sshpass -p [SUPPORT_PASSWORD] ssh [SUPPORT_USER]@[SUPPORT_SERVER] <span class="hljs-string">'bash -s'</span> < /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

<span class="hljs-meta">#!/bin/bash
</span>
SUPPORT_USER=<span class="hljs-string">"openhabian"</span>
SUPPORT_SERVER=<span class="hljs-string">"192.168.178.55"</span>

<span class="hljs-keyword">function</span> <span class="hljs-function"><span class="hljs-title">getPort</span></span>() {
  <span class="hljs-built_in">echo</span> <span class="hljs-string">"/opt/next.py <span class="hljs-variable">$(cat /var/lib/dbus/machine-id)</span>"</span> > /tmp/script
  port=$(ssh <span class="hljs-_">-l</span> <span class="hljs-variable">$SUPPORT_USER</span> <span class="hljs-variable">$SUPPORT_SERVER</span> <span class="hljs-string">'bash -s'</span> < /tmp/script)
  <span class="hljs-built_in">echo</span> <span class="hljs-variable">$port</span>
}

<span class="hljs-function"><span class="hljs-title">createTunnel</span></span>() {
  getPort
  /usr/bin/ssh -N -R <span class="hljs-variable">$port</span>:localhost:22 <span class="hljs-_">-l</span> <span class="hljs-variable">$SUPPORT_USER</span> <span class="hljs-variable">$SUPPORT_SERVER</span>
}

/bin/pidof ssh
<span class="hljs-keyword">if</span> [[ $? <span class="hljs-_">-ne</span> 0 ]]; <span class="hljs-keyword">then</span>
  <span class="hljs-built_in">echo</span> Creating new tunnel connection
  createTunnel
<span class="hljs-keyword">fi</span>

sudo chmod +x  /opt/reversessh

crontab -e

*/1 * * * * /opt/reversessh

Server

Installation

create an ssh key with empty passphrase

ssh-keygen <span class="hljs-_">-f</span> ~/.ssh/support -C support -t rsa

create the next port script

vim /opt/next.py

<span class="hljs-comment">#!/usr/bin/python3</span>
<span class="hljs-keyword">import</span> sys
<span class="hljs-keyword">import</span> json
<span class="hljs-keyword">import</span> os.path

pi = {}
pi[sys.argv[<span class="hljs-number">1</span>]] = <span class="hljs-number">10000</span>

dbPath = <span class="hljs-string">'/opt/portdb'</span>
<span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> os.path.isfile(dbPath):
    <span class="hljs-keyword">with</span> open(dbPath,<span class="hljs-string">'w+'</span>) <span class="hljs-keyword">as</span> f:
        f.write(json.dumps(pi))
<span class="hljs-keyword">else</span>:
    <span class="hljs-keyword">with</span> open(dbPath,<span class="hljs-string">'r'</span>) <span class="hljs-keyword">as</span> f:
        data = json.load(f)
        <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> sys.argv[<span class="hljs-number">1</span>] <span class="hljs-keyword">in</span> data:
            data[sys.argv[<span class="hljs-number">1</span>]] = <span class="hljs-number">10000</span>+len(data)

<span class="hljs-keyword">with</span> open(dbPath,<span class="hljs-string">'w+'</span>) <span class="hljs-keyword">as</span> f:
    f.write(json.dumps(data))

print(data[sys.argv[<span class="hljs-number">1</span>]])

make it executable

sudo chmod +x /opt/next.py

 

Usage

From the server to connect to the pi

 ssh <span class="hljs-_">-l</span> pi -p [PI_PORT] localhost