Problem
Du versuchst, sicher zu bleiben. Wie bitte? Ja, zu sicher. Wenn du für verschiedene Kunden arbeitest und so tickst wie ich, möchtest du vielleicht nicht denselben Schlüssel für jeden Kunden verwenden. Der Bequemlichkeit halber fügst du nun alle deine Schlüssel deinem lokalen Agenten hinzu:
ssh-add key1
...
ssh-add keyN
Klasse. Sicher und trotzdem bequem. Bis du einen Auth-Fehler bekommst:
Received disconnect from a.b.c.d port 22:2: Too many authentication failures
Du prüfst den Benutzernamen doppelt. Du prüfst doppelt, ob dein Schlüssel im Agenten geladen ist. Du fängst an, an dir selbst zu zweifeln. Und doch scheint es keine Erklärung zu geben.
Grund
Nach etwas Suche im Netz bekommst du plötzlich die Antwort:
Dein SSH-Client schickt den ersten Schlüssel. Wird er nicht akzeptiert, den zweiten und so weiter. Und wenn du deinen Server etwas abgesichert hast, trennt er nach einer bestimmten Anzahl von Versuchen einfach die Verbindung mit dem obigen Fehler. Das Knifflige daran ist, dass es bei manchen Servern funktioniert (bei denen der Schlüssel innerhalb des konfigurierten Limits liegt) und bei anderen nicht. Sobald man die Erklärung liest, wird es klar und völlig nachvollziehbar.
Ein weiteres Hindernis: Einfach -i zu übergeben, hilft nicht, da -i die Schlüssel nicht auf den angegebenen beschränkt.
Lösung
Du kannst das umgehen, indem du deinem SSH-Client Optionen übergibst, die den Schlüssel auf einen angegebenen beschränken:
-o "IdentitiesOnly yes" -i <Pfad zu deinem privaten Schlüssel>
Der offensichtliche Nachteil ist, dass du dir diese Optionen entweder merken oder sie in deiner SSH-Konfiguration für jeden Server hinterlegen musst.
Ein weiterer Ansatz ist, deinen Agenten je nach Arbeit neu zu konfigurieren. Denn wir springen ja nie zwischen Aufgaben hin und her, oder? Um diesen Weg zu gehen, kannst du das mit direnv so handhaben:
ssh-add -D
ssh-add <key>
Beim Wechsel in dieses Verzeichnis würden alle vorhandenen Schlüssel entfernt und der angegebene hinzugefügt. Der Nachteil hier ist, dass das im Terminal gut funktioniert, grafische Umgebungen aber außen vor bleiben. Zusätzlich werden beim Hin- und Herspringen deine Schlüssel in einem Terminal entfernt, und das andere Terminal ist für die dortige Arbeit ungültig.
Du könntest für jede Shell einen weiteren Agenten starten und den Socket separat exportieren, aber das habe ich nicht getestet.