SSH Keys zantral verwalten unter Linux

Nerofu

Cadet 2nd Year
Registriert
Aug. 2016
Beiträge
18
SSH Keys zentral verwalten unter Linux

Hallo zusammen,

ich möchte unsere ssh-keys zentral mit einem Linux Server verwalten.

Kurz zum Aufbau:

- auf dem Server auf dem zugegriffen werden soll, soll beim Zugriff nicht in die authorized_keys geschaut werden sondern ein
Skript ausgeführt werden
, welches auf meinen Verwaltungs- Server auf die Datenbank zugreift.

- Dieses Skript soll dann mit Hilfe der Datenbank immer ein neues authorized_keys file anlegen.

Die Vorteile sind ja ziemlich klar, wir müssen dann bei wechselnder Belegschaft nicht immer alle authorized_keys files anpassen.
Dieses Skript möchte ich in Perl schreiben, da Perl auf allen Servern läuft.


LG,
Nero

__________________________________________________________________________________

Update:

Ich habe entschieden hier ein bisschen meinen Fortschritt & meinen Lernvorgang zu Dokumentieren, vielleicht habt ihr ja noch Anregungen & Ideen.

Mein System: Ubuntu 64x mit XFCE Oberfläche 16.04.1 LTS Xenial Xerus
Seitdem ich auf 16.04.1 LTS upgedated habe läuft LibreOffice nicht mehr. Es haben schon drei Leute mehrere Stunden mit der Behebung des Problems verbracht, aber erfolglos. evtl. werde ich noch ein Thema dazu aufmachen.

Da ich ehrlich gesagt absolut keine Erfahrung mit SSH habe, habe ich mich erst mal auf diversen Seiten informiert, wie SSH und vor allem die key authentication funktioniert.

Hierzu habe ich mich folgenden Quellen bedient:
https://de.wikipedia.org/wiki/Secure_Shell

Da ich noch nie Selber ein SSH Server aufgesetzt habe, habe ich dies zu Übungszwecken nachgeholt.

Zuerst habe ich eine Virtuelle Maschine aufgesetzt mit einem Aktuellen Ubuntu. Eingesetzt habe ich dafür VortualBox. sudo apt-get install virtualbox virtualbox-qt virtualbox-dkms
Ubuntu Download: http://www.ubuntu.com/download

Die Maschine war schnell aufgesetzt und um meine ersten Schritte in SSH zu gehen bin ich ganz einfach diesem Tutorial gefolgt: https://wiki.ubuntuusers.de/SSH/

Das einzige was nicht Funktioniert hat war ssh-copy-id -i ~/.ssh/id_rsa.pub user@server um den Public Key auf den Server zu transferieren. Als Alternativ habe ich SCP benutzt und den Key direkt in authorized_keys kopiert.

Und schwups hatte ich eine sichere SSH Verbindung :)

Als nächstes werde ich einen TCP Client & einen TCP Server in Perl programmieren.

Ich werde versuchen dies hier aktuell zu halten, doch da ich das nur nebenher mache wird das wohl relativ unregelmäßig sein.

LG,
Nero


Nachtrag: Aufgrund der Whitelist musste ich einige Links entfernen :( Ich hoffe es ist trotzdem verständlich.


__________________________________________________________________________________

Update:
Ich habe herausgefunden, das Ältere SSH Versionen AuthorizedKeysCommand nicht unterstützen bzw. nicht alle Funktionen. In den neusten Versionen können Tokens wie zB. der fingerprint mitgegeben werden. In den etwas älteren Versionen wird nur der Benutzer übergeben.

Diese Informationen sind über man sshd_config abzurufen.
Um herauszufinden welche OpenSSH version man besitzt kann man folgenden Befehl benutzen:
sshd -v

LG,
Nero

__________________________________________________________________________________

Update:
Ich habe mir zum Start einen einfachen Client & Server aus dem Internet besorgt.
Quelle: Xmodulo

Server:

Code:
use IO::Socket::INET;
 
# auto-flush on socket
$| = 1;
 
# creating a listening socket
my $socket = new IO::Socket::INET (
    LocalHost => '0.0.0.0',
    LocalPort => '7777',
    Proto => 'tcp',
    Listen => 5,
    Reuse => 1
);
die "cannot create socket $!\n" unless $socket;
print "server waiting for client connection on port 7777\n";
 
while(1)
{
    # waiting for a new client connection
    my $client_socket = $socket->accept();
 
    # get information about a newly connected client
    my $client_address = $client_socket->peerhost();
    my $client_port = $client_socket->peerport();
    print "connection from $client_address:$client_port\n";
 
    # read up to 1024 characters from the connected client
    my $data = "";
    $client_socket->recv($data, 1024);
    print "received data: $data\n";
 
    # write response data to the connected client
    $data = "ok";
    $client_socket->send($data);
 
    # notify client that response has been sent
    shutdown($client_socket, 1);
}
 
$socket->close();


Client:


Code:
use IO::Socket::INET;
 
# auto-flush on socket
$| = 1;
 
# create a connecting socket
my $socket = new IO::Socket::INET (
    PeerHost => '0.0.0.0',
    PeerPort => '7777',
    Proto => 'tcp',
);
die "cannot connect to the server $!\n" unless $socket;
print "connected to the server\n";
 
# data to send to a server
my $req = 'hello world';
my $size = $socket->send($req);
print "sent data of length $size\n";
 
# notify server that request has been sent
shutdown($socket, 1);
 
# receive a response of up to 1024 characters from server
my $response = "";
$socket->recv($response, 1024);
print "received response: $response\n";
 
$socket->close();

Natürlich sollte man #! /usr/bin/perl am Anfang des Skripts nicht vergessen.
Diese Konfiguration Läuft so bei mir, natürlich muss PeerHost & LocalHost angepasst werden.

Nächster Schritt wird sein den Server & Client SSL fähig zu machen.


LG,
Nero


__________________________________________________________________________________

Update:

Ich muss mir erst einmal selber ein SSL-Zertifikat & Key ausstellen. (Nur für die Testumgebung)
Infos zu SSL gibt es hier: https://de.wikipedia.org/wiki/Transport_Layer_Security

Privat Key anlegen:

Code:
openssl genrsa -aes256 -out ca-key.pem 2048
So hat der Key eine Länge von 2048bit und wird mit dem Namen ca-key.pem angelegt.
Die Option „-aes256“ führt dazu, dass der Key mit einem Passwort geschützt wird.

Zertifikat ausstellen:

Code:
openssl req -x509 -new -nodes -extensions v3_ca -key ca-key.pem -days 1024 -out ca-root.pem -sha512
Mit -days wird die Gültigkeitsdauer des Zertifikates in Tagen festgelegt.
Zu beachten ist das der Common Name gültigkeit besitzt in meinem Fall habe ich einfach eine Adresse ausgedacht und in meine hosts /etc/hosts Datei eingetragen mit meiner Server IP:
Code:
 192.168.112.120 test.test.de

LG,
Robin


__________________________________________________________________________________

Update:
Ich bin jetzt endlich dazu gekommen den Client und den Server auf SSL umzusockeln :)
Eigentlich ganz einfach, zu beachten ist, das IO::Socket::SSL kein send & recv kennt.

Die Unterschiede seht ihr dann ja im Code :)

Server:
Code:
#! /usr/bin/perl -w
use strict;
use IO::Socket::SSL;

# auto-flush on socket
$| = 1;

# creating a listening socket
my $socket = new IO::Socket::SSL (
    LocalHost => '192.168.112.120',
    LocalPort => '7777',
    #Proto => 'tcp',
    Listen => 10,

    SSL_cert_file => 'test-cert.pem',
    SSL_key_file => 'test-key.pem',
);
die "cannot create socket $!\n" unless $socket;
print "Server wartet auf Verbindung von Port 7777\n";


while(1)
{
    # waiting for a new client connection
    my $client_socket = $socket->accept();

    # get information about a newly connected client
     my $client_address = $client_socket->peerhost();
     my $client_port = $client_socket->peerport();
     print "Eingehende Verbindung von: $client_address:$client_port\n";

    # read up to 1024 characters from the connected client
    my $data = <$client_socket>;
    print "Daten empfangen: $data\n";

    # write response data to the connected client
    $data = "Verstanden ich bin der Server!";
    print $client_socket $data;

    # notify client that response has been sent
    shutdown($client_socket, 1);
}

$socket->close();

Client:

Code:
#! /usr/bin/perl

use IO::Socket::SSL;

# auto-flush on socket
$| = 1;

# create a connecting socket
my $socket = new IO::Socket::SSL (
    PeerHost => '192.168.112.120',
    PeerPort => '7777',
    SSL_verify_mode => SSL_VERIFY_NONE
    #Proto => 'tcp',
);
die "cannot connect to the server $!\n" unless $socket;
print "Verbunden mit dem Server.\n";
 
# data to send to a server
my $req = 'Hallo ich bins der Client';
my $size = print $socket $req;
print "Senden von $size Zeichen\n";
 
# notify server that request has been sent
shutdown($socket, 1);
 
# receive a response of up to 1024 characters from server
my $response = "";
#$socket->recv($response, 1024);
my $response = <$socket>;
print "Antwort vom Server: $response\n";

$socket->close();

LG,
Nero


_____________________________________________________________________________________________________________

Update:

Ich möchte, da ich momentan kein CA habe auf den Fingerprint prüfen.
Um diesen herauszufinden habe ich temporär diesen code unter sie socket erstellung des Clients gepackt:
Code:
my $fpr = $socket -> get_fingerprint('sha512');
print "$fpr";

Anschließend habe ich in der Socket Erstellung des Clients nach der Ausgabe des fingerprints gefragt.
Code:
SSL_fingerprint => 'FINGERPRINT',

LG,
Nero


_____________________________________________________________________________________________________________

Update:

Da bin ich wieder :)
Ich habe jetzt einfach mal meine Recherchen zu SSH und das Public-Key Verfahren so gut es geht kurz zusammengefasst:

SSH Secure Shell Was ist das?

SSH ist ein Netzwerkprotokoll, mit dem man eine verschlüsselte Netzwerkverbindung mit einem Gerät herstellen kann. Diese Verbindung wird häufig dazu genutzt um eine entfernte Kommandozeile verfügbar zu machen. Dies funktioniert so, dass die Eingaben auf der lokalen Konsole auf die entfernte Konsole gesendet werden und die Ausgaben der entfernten Konsole auf die lokale übertragen werden. Die Version SSH-2 hat noch mehr Funktionen wie zum Beispiel Datenübertragung via SFTP.

Ursprünglich wurde SSH überwiegend dazu verwendet um sich an entfernten Rechnern anzumelden, doch SSH-2 bietet mittlerweile viel mehr Funktionen. SFTP (SSH File Transfer Protocol) und SCP (Secure Copy) bieten zum Beispiel eine sichere Alternative zu FTP (File Transfer Protocol) & RCP (copy). X11 Also die Übertragung von Fenstern kann über SSH auch gesichert geschehen. Es können auch TCP/IP Verbindungen getunnelt werden, das heißt, dass zum Beispiel sonst unverschlüsselte Verbindungen wie VNC abgesichert werden können. Durch SSHFS (Secure SHell FileSystem) kann man auch Dateisysteme entfernter Rechner lokal mounten. Zudem kann man mit einem
ssh-keyscan den öffentlichen Schlüssel eines entfernten Rechners auslesen. Damit kann man mit der Hilfe des Öffentlichen Schlüssels herausfinden, ob die IP-Adresse und/oder der DNS-Eintrag des Servers manipuliert worden ist. Es ist auch möglich die Verbindung zu komprimieren um Bandbreite zu sparen.

Anwendungsszenarien sind zum Beispiel Secure System Administration (Sichere Systemverwaltung) zum ersetzen von rlogin & telnet ect.. Secure Application Tunneling (Sicheres Tunneln) zum Schutz für TCP/IP- Anwendungen und Secure Remote Command Execution (Sichere Ausführung von Kommandos) um einzelnde Kommandos auf einem anderen Rechner auszuführen.

Beispiel für den Ablauf einer SSH-Sitzung:
- Zuerst wird ein TCP-Verbindung (Port 22) aufgebaut
- Danach schickt der Server seine Protokollversion und die
verfügbaren Protokolle
- Der Client antwortet ebenfalls mit dem Senden seiner unterstützten
Version und das gewählte Protokoll. Er verlangt
auch den öffentlichen Schlüssel des Servers
- Der Server schickt seinen öffentlichen Schlüssel
- Der Client generiert einen Session Key und verschlüsselt ihn mit
dem öffentlichen Schlüssel des Servers
- Der Server entschlüsselt den Session Key mit seinem privaten Schlüssel
und ab jetzt werden alle Daten, die zwischen
Server und Client ausgetauscht werden, mit einem symmetrischen Verfahren (Session Key) verschlüsselt.

Und dieses Beispiel zeigt auch warum das Public-Key verfahren so gut ist. Da nur der Server die Pakete entschlüsseln kann ist es fast ausgeschlossen, das jemand die Pakete in einer realistischen Zeit entschlüsseln kann. Dies liegt an der angewendeten Verschlüsselungsmethode. Das RSA-Kryptosystem (Rivest, Shamir und Adleman) das bereits 1977 entwickelt wurde ist eins der besten Public-Key verfahren.

Dies Funktioniert, mit einer Funktion bei der eine Richtung leicht zu berechnen ist, jedoch ist die andere Richtung also die Umkehrfunktion sehr schwierig zu berechnen. Dies wird auch als Einwegfunktion bezichnet. Die Falltürfunktion lässt sich in diesem Fall aber leicht lösen, wenn man eine Zusatzinformation hat.

Ich habe mich größtenteils bei Wikipedia bedient.

LG,
Nero
 
Zuletzt bearbeitet:
Mir geht es ja um das Basteln :)
Ergänzung ()

Hallo Leute,

nur eine Frage am Rande: Sind solche Themen hier eigentlich erwünscht?
Soll ich weiter machen?
Gibt es eine maximale Länge? :rolleyes:

LG,
Nero
 
Finde ich interessant wie das versuchst zu lösen

Ich nutze Puppet für das Verwalten der Keys, dann ist auf allen Maschinen gleich genau so wie ich es haben will und noch ein paar andere Dinge...
 
Nerofu schrieb:
Mir geht es ja um das Basteln :)
Basteln ist immer gut, richtig.

Dir ist aber klar, dass das deine "aufgebohrte" public key authentication neue Angriffspunkte ins Spiel bringt und für den praktischen Einatz keine gute Idee ist? Wenn public key auth für die eigene Umgebung nicht sinnvoll ist, bietet ssh nicht zuletzt via PAM die Möglichkeit, andere etablierte Verfahren zu nutzen. Sich dort umzusehen, ein geeignetes Verfahren zu finden und zum Einsatz zu bringen hat auch Bastelpotential. Von einem Eigenbau sollte man abseits reiner Spielwiesen absehen, wenn man nicht _wirklich_ _fit_ in solchen Sachen ist (was über 99,999% der Menschen nicht sind).
 
  • Gefällt mir
Reaktionen: klausk1978
Ich habe es so gelöst, dass ich die Keys in Paketen hinterlegt habe. Mein Repo Server generiert das Paket, auf den Servern wird das aktualisiert und ein Key ist schnell hinzugefügt oder entfernt. Ansonsten ist die LDAP Methode natürlich eine Alternative.

Dein Projekt ist interessant und bitte mach weiter, viele fürchten sich vor Dinge, welche neu sind :rolleyes:
 
Ich musste jetzt leider pausieren, aber bin bald wieder dran. Ich mache erst mal ein paar Recherchen zu SSH, Public Key Verfahren, Authorized Key Command & SSL, bevor ich weiter mache. Ich möchte nachher auch auf ein vernünftiges Ergebnis kommen.
 
Zurück
Oben