Sicherheit bei Remote-Verbindung über libssh

Daemotron

Well-Known Member
Moin moin,

Hinweis: das ist ein (ausnahmsweise) ein Cross-Post; mir geht es allerdings darum, ein möglichst breites Meinungsbild zu bekommen.

ich bin gerade dabei, mir ein Tool zu schnitzen, mit dem ich mehrere Server und Jails bequem vom heimischen Rechner aus konfigurieren und verwalten kann [1]. Der Zugang zum entfernten System soll dabei über SSH erfolgen (ich nutze dafür libssh); allerdings stellt sich hier jetzt die Frage nach der Sicherheit eines solchen Zugangs.

Bisher gibt es auf meinen Servern einen "normalen" User, und nur dieser darf sich per SSH einloggen. root-Rechte erwirbt dieser normalerweise, indem er su nutzt. Aus praktischen Erwägungen heraus lässt sich diese Vorgehensweise nicht ohne weiteres nachbilden, was auch mit dem Aufbau des SSH-Protokolls zusammenhängt: Jeder Befehl wird in einem neuen Channel abgefeuert; der Kontext bleibt also nur erhalten, wenn gleich der erste Befehl selbst einen Kontext herstellt, in dem dann alles weitere geschieht (z. B. eine Shell, was sich dann von außen nur schwer bis gar nicht skripten lässt).

Ich sehe daher drei theoretisch mögliche Vorgehensweisen:
  • Anders als bisher darf root sich doch direkt per SSH einloggen, natürlich beschränkt auf Public Key Authentication
  • Es darf sich weiterhin nur ein normaler User einloggen; dieser darf aber sudo ohne Passworteingabe nutzen
  • Es darf sich weiterhin nur ein normaler User einloggen; dieser spawnt als erstes eine Shell, in deren Kontext dann alles weitere abläuft.
Meine Pro's und Con's:
Pro a: Einfach umzusetzen, PubKey sehr schwer zu knacken
Contra a: root ist ein bekannter Account => minimaler Vorteil bei einem Brute Force Angriff

Pro b: Immer noch relativ einfach umzusetzen, PubKey sehr schwer zu knacken, kein bekanntes User-Handle
Contra b: sudo ohne Passwort-Schutz => wer in den Account reinkommt, ist faktisch root

Pro c: PubKey sehr schwer zu knacken, kein bekanntes User-Handle, selbst bei erfolgreichem Einbruch noch keine root-Rechte
Contra c: Sehr komplex (und damit fehleranfällig) in der Umsetzung, root-Passwort muss irgendwie lokal gespeichert werden

Momentan tendiere ich zu Variante a., da ich den tatsächlichen Sicherheitsgewinn der Varianten b. und c. als sehr gering einschätze - wie seht Ihr das? Habe ich ggf. etwas übersehen?



[1] https://github.com/daemotron/controlbeast
 
Servus!

Seit vielen Jahren administriere ich UNIX Server via SSH auf Port 24 (nicht um die Sicherheit damit zu erhöhen, sondern das Log-Spamming zu eliminieren) mit folgenden Optionen in der sshd_config (nur relevante Settings):

Code:
PermitRootLogin without-password
PubkeyAuthentication yes
AllowedUsers root usera userb
RhostsRSAAuthentication no
HostbasedAuthentication no
PasswordAuthentication yes
PermitEmptyPasswords no
ChallengeResponseAuthentication no
KerberosAuthentication no
GSSAPIAuthentication no
UsePAM no
AllowAgentForwarding no  # ausser auf ausgewählten Ausnahmen
AllowTcpForwarding no
GatewayPorts no
X11Forwarding no
UseDNS no

HTH & Ciao.
Markus
 
Variante a.

Du kannst zusätzlich auf dem Server bestimmte public keys auf bestimmte Kommandos festsetzen, die damit nur ausgeführt werden können. So kann der Key auch keine Shell starten z.B.

Über brute force würde ich mir bei pubkey auth keine Gedanken machen. Port 22 ratelimiten und fertig. Ich hab auf meinen privaten Servern eine GeoIP-Datenbank als pf-Tabellen importiert und begrenze SSH generell auf Deutschland und erlaube es von da nur mit rate limit.
 
http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip

Quick'n'dirty perl macht daraus pf-Tabellen:

Code:
use diagnostics -verbose;
use strict;
use warnings;

use Net::IP qw{ip_iptobin ip_range_to_prefix};

my %geoip;

open(CSV, "GeoIPCountryWhois.csv") || die "Failed: $!\n";
while(<CSV>) {
        chomp;
        my ($net, $bc, $net_i, $bc_i, $cc, $country) = m{ "([^"]+)"[^"]* }gx;
        push(@{$geoip{$cc}}, ip_range_to_prefix(ip_iptobin($net, 4), ip_iptobin($bc, 4), 4));
}

foreach my $cc (sort keys %geoip) {
        print "table <GeoIP_$cc> const persist { ", join(", ", @{$geoip{$cc}}), " }\n";
}

Ist nicht sehr schnell, ich bin kein Perl -Guru.
 
Zurück
Oben