blog.bartlweb - a technologist's external brain

SSH Web Gateway mit dem OpenSource Tool shellinabox

Der eigentlich für den direkten Konsolenzugriff über Web gedachte Dienst shellinabox lässt sich hervorragend dazu verwenden ein Gateway für SSH-Verbindungen herzustellen. Dies ist vor allem, dann interessant wenn des Öfteren Maschinen aus Netzen die keine Verbindungen zu Port 22 oder manuell definierten Ports über 1024 zulassen, gewartet werden müssen.

Aus Sicherheitsgründen sollten Sie so einen Dienst nur auf einer eigenen Maschine (z.B. virtuell) einrichten, für das zugrunde liegende System eigene sonst nicht verwendete Passwörter definieren und den shellinabox-Daemon nur mit eingeschränkten Rechten starten.

Der Service lässt sich unter https://tools.bartlweb.net/webssh ausprobieren.

Die HTML-Implementierung funktioniert in allen modernen Browsern und lässt sich via Apache mod_proxy ins Netz bringen. Die Eingabe von Sonderzeichen macht allerdings in Firefox Probleme, daher empfehle ich die Nutzung unter Chrome. Wer dennoch auf Firefox angewiesen ist kann zumindest mathematische Symbole anstelle der normalen Tasten über das Nummernpad eingeben.

Installation

Richten Sie eine eigene Linux-Installation für den Service ein. Dann laden Sie sich die aktuelle Version von shellinabox unter http://code.google.com/p/shellinabox/ herunter. Entpacken Sie den Inhalt des Archivs und kompilieren bzw. installieren Sie das Tool mit den im Verzeichnis des Quellcodes ausgeführten Befehlen ./configure, make und make install.

Autostart und Startparameter

Um shellinabox mit der gewünschten Konfiguration zu starten benötigen wir ein Wrapper-Skript die wir z.B. in das Home-Verzeichnis (hier /home/webssh/start_shellinabox.sh) unseres Benutzers, unter dem wir shellinabox ausführen wollen (hier webssh), legen. Darin rufen wir das Tool shellinabox auf und konfigurieren es wie folgt:

  • --background: Im Hintergrund als Dienst starten.
  • --service: Wir bieten unserer nachfolgendes Shelllskript als Service an. Dabei wird der Service nach dem folgenden Schema definiert /:<username>:<group>:HOME:'<script>'
    • <username> / <group>: Username und Gruppe des Nutzers, mit dessen Rechte das angegebene Skript ausgeführt wird.
    • HOME: Definiert das Home-Verzeichnis des angegebenen Benutzers als zu verwendendes Arbeitsverzeichnis.
    • <script>: Pfad zum Skript, dessen Ausgabe bei Aufruf des Dienstes über die Weboberfläche angezeigt wird.

Daraus ergibt sich der folgende Inhalt für unser Wrapper-Skript:

#!/bin/sh
/usr/local/bin/shellinaboxd --background --service=/:webssh:webssh:HOME:'/home/webssh/shellinabox_sshwrapper.sh'

Damit der shellinabox-Daemon nun bei jedem Start ausgeführt wird, rufen wir das angelegte Skript über die Crontab-Datei des Nutzers webssh auf.

@reboot /home/webssh/start_shellinabox.sh >> /dev/null 2>&1

SSH-Service Shellskript

Die Ausgabe des folgenden Shellskripts wird dem Nutzer bei Aufruf der Weboberfläche angezeigt. Hier fragen wir nach den Parametern des Remotehosts (Hostadresse, Hostport und Benutzername), fangen Anfragen an interne IPs ab und starten die eigentliche SSH-Verbindung. Um SSH-Verbindungen nicht aufgrund von wechselnden Hostkeys zu blockieren, akzeptieren wir unbekannte Hosts automatisch und verwerfen diese durch Speichern in /dev/null.

Kopieren Sie den nachfolgenden Code in die Datei /home/webssh/shellinabox_sshwrapper.sh.

#!/bin/bash
 
#
# get host
#
 
read -p "SSH remote host (hostname or ip address): " host;
 
if [ -z "$host" ]; then
    echo ""
    echo ""
    echo "A hostname or ip address of the remote host is required."
    echo ""
    echo ""
    exit
fi
 
if [[ "$host" == "localhost" ]] || [[ "$host" = "0"  ]] || [[ "$host" = "::"  ]] || [[ "$host" = "::1"  ]] || [[ "$host" = "127.0.0."*  ]] || [[ "$host" = "0.0.0.0"  ]] || [[ "$host" = "10."*  ]] || [[ "$host" = "192.168."*  ]]; then
    echo ""
    echo ""
    echo "Connections to internal network devices are not supported."
    echo ""
    echo ""
    exit
fi
 
#
# get port
#
 
read -p "SSH remote port [22]: " port;
 
if [ -z "$port" ]; then
    port=22;
fi
 
if [[ -n ${port//[0-9]/} ]]; then
    echo ""
    echo ""
    echo "Port must be a number between 0 and 65535."
    echo ""
    echo ""
    exit
fi
 
#
# get username
#
 
read -p "SSH remote username: " username;
 
if [ -z "$username" ]; then
    echo ""
    echo ""
    echo "A username of the remote host is required."
    echo ""
    echo ""
    exit
fi
 
#
# execute ssh command
#
 
echo ""
echo ""
exec ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o "LogLevel ERROR" -p $port $username@$host;

Dieser Artikel hat Dir deinen Tag gerettet?

... und mühevolles Probieren, Recherchieren und damit Stunden an Zeit gespart? Oder einfach nur Dein Problem gelöst?

Dann würde ich mich freuen, wenn Du meine Zeit für die Erstellung dieses Blogartikels mit einer kleinen Anerkennung honorierst:

Zahlung mit PayPal oder Kreditkarte.

Hinweis zur Verwendung

Die Übermittlung einer Zahlung ist eine persönliche Anerkennung Ihrerseits an den Entwickler (Christian Bartl, Privatperson). Eine Zahlung ist nicht zweckgebunden und es ist keine Gegenleistung zu erwarten. Bitte beachten Sie, dass für eine übermittelte Zahlung keine Quittung ausgestellt werden kann.

Über den Autor

Christian Bartl

Christian Bartl Projektmanagement & Konzeption für Online und Mobile

Als Technologie-Enthusiast und begeisterter Programmierer entwickle ich in meiner Freizeit Websites, Software und IT-Lösungen, die mir selbst und anderen den Alltag vereinfachen.

mehr auf bartl.me

Kommentare

  1. Moin,

    funzt alles prima. Eine Anmerkung: In die Liste de lokalen Adressen im wrapper muss auch 0.0.0.0 hinzugefügt werden, ansonsten kann es passieren dass man doch lokal rauskommt.

    Gruß
    -- hgb

    kommentieren

    1. Hallo Hans-Georg,
      vielen Dank für den Tipp!
      lg Christian

      kommentieren

    2. ich verstehe nicht ganz wieso das 10er netz gesperrt ist aber nicht z.B. 127.1.2.3, darüber kommt man dann nämlich doch noch gut auf den localhost 127.34.2.111 würde ich dann auch noch gleich sperren :-)

      kommentieren

      1. Damit hast du natürlich nicht ganz unrecht. Habe das Skript im Blogbeitrag eben angepasst.

        Danke,
        Christian

        kommentieren

        1. Das 172.16-wasauchimmer.0.0er Subnetz wird auch noch zugelassen...

          kommentieren

  2. An sich super sache. Ich bekomms jedoch nicht installiert, bzw kompiliert. (ich mach zum ersten mal).
    Ich kann einfach libssl10.9.8 nicht finden.
    Würde mich freuen, wenn mir jemand hilft. Da so eine Webconsole die Lösung zu einem meiner Probleme wäre.

    kommentieren

    1. Hallo TheSirati97,
      unter Ubuntu lässt sich shellinabox sogar über die integrierte Paketverwaltung installieren (apt-get install shellinabox) - je nach deiner verwendeten Distribution müsstest du schauen ob es dafür nicht auch bereits fertige Pakete gibt. Wenn du libssl vermisst, musst du dieses ebenfalls zuvor über den Paketmanager deiner Distribution installieren.
      lg Christian

      kommentieren

      1. Ich hab Debian 8. ich probier mal ob es dort auch vorhanden ist.

        kommentieren

      2. Super, apt-get kennt es. Da wird sich mein Freund freuen!

        (ich versteh echt nicht, warum Schulen allen scheiß blocken)

        kommentieren

      3. An sich funktioniert es super. Hab aber noch eine Frage:
        Ist es möglich den webserver auf einer bestimmten IP laufen zu lassen. Ich will nicht das er alle verfügbaren IP's bindet.

        kommentieren

        1. Die Hilfe findest du unter https://code.google.com/p/shellinabox/wiki/shellinaboxd_man.
          Wenn du den Zugriff steuern oder sogar mit Passwort schützen willst bietet es sich an einen Apache Webserver mit mod_proxy davor zu schalten und shellinabox nur über den Proxy anzusprechen.

          lg Christian

          kommentieren

          1. Eeyup, die hatte ich mir angesehen. Gab da halt keine solche Option. Vielleicht mach ich es dann über einen Tunnel.

            Naja erstmal geht es. wenn auch etwas unoptimal.

          2. So hier bin ich nochmal. Ich habe einen Bug gefunden, der mich dazu zwingt dieses nett Tool in den Müll zuschmeißen. Zumindest solang der Bug existiert.

            Wenn man einfach den Browsertab schließt, wird Serverseitig die SSH Verbindung nicht beendet. Das führt dazu das erstens Geistverbindungen entstehen und zweitens der InputStream komische Sachen auf dem SSH Server empfängt.
            Dadurch ist der CommandInterpreter durchgängig damit beschäftigt irgendeinen Bullshit zu interpretieren. Was bei mir pro Geist-SSHVerbindung ein Serverkern auslastet. Das geht natürlich gar nicht, und hat zu einem ZwischenzeitlichenAausfall meines Dienstes geführt. Da Die 8 Kerne meines Servers mit 13 Threads beschäftigt waren ,die gerne einenen gaznen Kern für sich hätten.

            Ich werde jetzt auch den Autor des Tools anschreiben.

          3. Das mit den nicht korrekt beendeten Verbindungen kann ich bei mir am System nachvollziehen. Eine Auswirkung auf die Systemlast hat dies bei mir allerdings nicht.

          4. Das mit der Systemlast liegt glaube ich etwas daran wie bei mir die Daten verarbeitet werden. Trotzdem finde ich es ziemlich blöd das sowas wie dass ordnungsgemäße schließen der Verbindungen vergessen wird.

  3. Hi, wie bekomm ich hin, dass der Server beim öffnen auch nach der Domain zum connecten fragt, wie bei dir?
    Ich bekomm ihn auf localhost und zu ner Domain die ich mit dem start an gebe. Aber leider nicht, das er die Domain und user/pw abfragt.

    kommentieren

    1. Hallo Manuel,

      shellinbox stellt prinzipiell nur eine Verbindung zur lokalen Shell des Gerätes her, kann aber beim Start auf ein Skript oder ein Programm eingeschränkt werden. Für das von dir gewünschte Verhalten ist das im Artikel erwähnte Shell-Skript zuständig.

      lg Christian

      kommentieren

  4. Thank you !
    This is very helpful tool for me!

    kommentieren

  5. Hallo,

    weiß jemand wie man dieses nette Tool, wenn es per Docker installiert ist, dazu zwingt immer das startscript aufzurufen?

    kommentieren

    1. bzw. bekomme ich immer diesen Fehler beim loginversuch:

      Cannot make/remove an entry for the specified session
      Session closed.

      kommentieren

  6. Ich kann das ganze im Moment leider nicht als Proof of Concept machen von daher muss ich mir meine Antworten erfragen. Das ganze funktioniert ohne root? Sprich auf einem shared Hoster unter normalen Nutzerrechten.
    Und laesst sich der Port anpassen?
    Danke fuer den tollen Service auch wenn mir die geplante Wartung gerade echt unguenstig kommt...

    kommentieren

    1. Hallo Theo,
      shellinabox erlaubt die Konfiguration des Ports mit --port , wobei ich empfehlen würde Apache oder Nginx als transparenten Proxy vorzuschalten.
      Der Dienst lässt sich auch ohne Root-Rechte starten und du kannst beim Start sogar einen beliebigen Nutzer unter dem der Dienst ausgeführt werden soll mit --user definieren.
      lg Christian

      kommentieren

  7. Hi, it works really nice. I have to ask, would it be possible to send host and user credentials as a request straight from the browser and just open session? Thank you so much for sharing all this.

    kommentieren

    1. Hi N Paun,

      sorry, but that is not possible, due to the technical fact, that the ssh login is already a shell script executed on the remote host.

      Greetings,
      Christian

      kommentieren

Kommentar schreiben

Der hier angegebene Name wird gemeinsam mit deinem Kommentar auf der Website veröffentlicht.

Deine E-Mail-Adresse wird zur einmaligen Benachrichtigung bei Veröffentlichung des Kommentars genutzt.

Benachrichtigung per E-Mail über Antworten auf meinen Kommentar erhalten.

Bitte tippe die Zahlenkombination "2471" ein, nur dann kann ich deinen Kommentar entgegennehmen.

Bitte fülle dieses Feld nicht aus, nur dann kann ich deinen Kommentar entgegennehmen.