\ <ins > 26.04.2018 Nachtrag
Schreiben Sie eine Shell-Funktion namens "find_agent", um sie jedes Mal manuell aufzulösen. Es ist sicherlich praktisch, automatisch zu wechseln, aber es gibt nicht viele Male, in denen dies erforderlich ist, und LD_PRELOAD stört manchmal beim Debuggen, sodass es nicht viel Nutzen gab ...
Ich habe github verwendet, um die Verbindung von SSH_AUTH_SOCK zu überprüfen. Die Tasten, die ich normalerweise benutze, werden normalerweise in Github abgelegt, daher habe ich Probleme mit ssh, weil es um das Timing des Git-Push geht. Socket-Dateien sollten mit Pfadnamen versehen sein
find_agent () {
local GLOBS=("/tmp/com.apple.launchd.*/Listeners" "/tmp/ssh-*/agent.*");
for g in "${GLOBS[@]}"; do
for c in ${g}; do
SSH_AUTH_SOCK="$c";
[ ! -S "${SSH_AUTH_SOCK}" ] && continue;
ssh -T [email protected];
[ $? -eq 1 ] && return 0;
done;
done
}
</ins>
Nachfolgend finden Sie die Beschreibung vom 12.02.2016
github https://github.com/takei-yuya/alt_ssh_auth_sock
Ich bin auf einem Skiausflug nach Akita gekommen, aber ich war frei im Gasthaus, also habe ich es geschrieben.
Eine Story, um das Problem zu vermeiden, dass die Referenz von SSH_AUTH_SOCK, die für die Übertragung von SSH-Agenten durch Trennen / Anhängen verwendet wird, falsch ausgerichtet ist, wenn der Bildschirm am Verbindungsziel von SSH verwendet wird.
Mit anderen Worten, so etwas
local $ # ssh-Aktivieren Sie die Agentenübertragung und stellen Sie eine Verbindung zu hostA her
local $ ssh -A hostA
hostA $ #SSH automatisch am Verbindungsziel_AUTH_Die Umgebungsvariable SOCK ist gesetzt
hostA $ declare -p SSH_AUTH_SOCK
declare -x SSH_AUTH_SOCK="/tmp/ssh-XXXXXXXXXX/agent.11111"
hostA $ #Dieser Socket ist für diese Sitzung mit dem sshd verbunden
hostA $ ps -p 11111
PID TTY TIME CMD
11111 ? 00:00:00 sshd
hostA $ #Selbst wenn auf hostA kein Schlüssel vorhanden ist, werden die Schlüsselinformationen über den Socket übertragen.
hostA $ #Sie können mit Schlüsselauthentifizierung eine Verbindung zu einem anderen Host herstellen
hostA $ ssh hostB
hostB $ exit
hostA $ #Bildschirm speichert die Umgebungsvariablen, wenn der Bildschirm gestartet wird
hostA $ screen -S ssh_test
hostA(screen) $ declare -p SSH_AUTH_SOCK
declare -x SSH_AUTH_SOCK="/tmp/ssh-XXXXXXXXXX/agent.11111"
hostA(screen) $ ^A^D #Ablösen
hostA $ #Dieser Socket wird ungültig, wenn die SSH-Sitzung abläuft
hostA $ #Versuchen Sie, die Verbindung wiederherzustellen
hostA $ exit
local $ ssh -A hostA
hostA $ #Der Socket-Pfad ändert sich, weil sich die Sitzung geändert hat
hostA $ declare -p SSH_AUTH_SOCK
declare -x SSH_AUTH_SOCK="/tmp/ssh-YYYYYYYYYY/agent.33333"
hostA $ #Alte Sitzung sshd ist weg
hostA $ ps -p 11111
PID TTY TIME CMD
hostA $ #In der Bildschirmsitzung sind die Umgebungsvariablen jedoch immer noch veraltet ...
hostA $ screen -x ssh_test
hostA(screen) $ declare -p SSH_AUTH_SOCK
declare -x SSH_AUTH_SOCK="/tmp/ssh-XXXXXXXXXX/agent.11111"
hostA(screen) $ #Altes ssh-Agententransfer stellt keine Verbindung her ...
hostA(screen) $ ssh hostB
Permission denied (publickey).
Es ist also lange her, aber diese Art von Phänomen. Ich möchte etwas dagegen tun.
Die Ursache ist, dass die Umgebungsvariablen in der Sitzung auf dem Bildschirm nicht aktualisiert werden.
Versuchen Sie es mit einem Mechanismus namens LD_PRELOAD.
Grob gesagt scheint es ein Mechanismus zu sein, eine dynamische Bibliothek beim Starten eines Prozesses zwangsweise einzufügen. Es kann verwendet werden, um 400.000 Systemaufrufe und Bibliotheksfunktionsaufrufe zu verknüpfen oder zu stehlen.
Die Zielfunktion ist getenv
. Mit anderen Worten, die Idee, Umgebungsvariablen von außen gewaltsam zu manipulieren.
Überprüfen Sie den aktuellen SSH_AUTH_SOCK
und versuchen Sie es mit einem anderen Socket, wenn Sie keine Verbindung zum Socket herstellen können. Die zu versuchenden Socket-Kandidaten werden durch das Dateikugelmuster einer anderen Umgebungsvariablen angegeben.
Mit anderen Worten
hostA(screen) $ ssh hostB
Permission denied (publickey).
hostA(screen) $ export LD_PRELOAD="/path/to/injection_lib"
hostA(screen) $ export ALT_SSH_AUTH_SOCK="/tmp/ssh-*/agent.*"
hostA(screen) $ ssh hostB
github: https://github.com/takei-yuya/alt_ssh_auth_sock
#define _GNU_SOURCE // for RTLD_NEXT
#include <stdlib.h>
#include <dlfcn.h>
#include <string.h>
#include <glob.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
//Statische Variable zum Speichern des ursprünglichen getenv
static char* (*_original_getenv)(const char *name) = NULL;
//Es scheint, dass Sie mithilfe der GNU-Erweiterung eine Funktion erstellen können, die vor der Hauptfunktion ausgeführt werden soll.
static void _alt_ssh_auth_sock_init() __attribute__((constructor));
static void _alt_ssh_auth_sock_init() {
//Speichern Sie das Original getenv
_original_getenv = dlsym(RTLD_NEXT, "getenv");
}
//Stellen Sie sicher, dass die Steckdose aktiv ist. ...... Ich verbinde mich nur.
int check_socket(const char* socket_file_path) {
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socket_file_path, sizeof(addr.sun_path) / sizeof(char));
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
int ret = connect(fd, (struct sockaddr *)&addr, sizeof(struct sockaddr_un));
close(fd);
return ret;
}
//Überschreiben Sie das Verhalten von getenv
char* getenv(const char *name) {
if (!_original_getenv) {
//etwas__attribute__((constructor))Funktioniert möglicherweise nicht, also nur für den Fall
_alt_ssh_auth_sock_init();
}
if (strcmp(name, "SSH_AUTH_SOCK") != 0) {
// SSH_AUTH_Mit Ausnahme von SOCK wird die ursprüngliche Funktion unverändert verwendet.
return _original_getenv(name);
}
char* ssh_auth_sock = _original_getenv("SSH_AUTH_SOCK");
if (!ssh_auth_sock) {
// SSH_AUTH_Wenn SOCK nicht definiert ist, kehren Sie so zurück, wie es ist.
return ssh_auth_sock; // == NULL
}
char* alt_ssh_auth_sock = _original_getenv("ALT_SSH_AUTH_SOCK");
if (!alt_ssh_auth_sock) {
//Wenn das alternative Socket-Muster nicht angegeben ist, kann nichts unternommen werden. Geben Sie also auf und kehren Sie so zurück, wie es ist
return ssh_auth_sock;
}
if (check_socket(ssh_auth_sock) == 0) {
//Wenn der aktuelle Socket aktiv ist, kehren Sie wie er ist zurück, ohne den Glob zu erweitern
return ssh_auth_sock;
}
//Erweitern Sie das Glob-Muster
glob_t pglob;
if (glob(alt_ssh_auth_sock, GLOB_NOSORT, NULL, &pglob) != 0) {
globfree(&pglob);
}
int i;
for (i = 0; i < pglob.gl_pathc; ++i) {
if (check_socket(pglob.gl_pathv[i]) == 0) {
//Wenn Sie eine lebende Steckdose finden
break;
}
}
if (i < pglob.gl_pathc) {
// SSH_AUTH_SOCK überschreiben
setenv("SSH_AUTH_SOCK", pglob.gl_pathv[i], 1);
ssh_auth_sock = _original_getenv("SSH_AUTH_SOCK");
}
globfree(&pglob);
return ssh_auth_sock;
}
Alles gepostet, weil es kurz ist. Die Details sind wie im Kommentar geschrieben, aber nachdem ich das ursprüngliche getenv gespeichert habe, verwende ich es aus getenv heraus, um es zu überschreiben.
Wie zu bauen
cc -Wall -fPIC -shared -o libaltsshauthsock.so alt_ssh_auth_sock.c -ldl
Vielleicht brauchst du Soname. Ein bisschen passend hier.
Derzeit denke ich, dass es am besten ist, Umgebungsvariablen in bashrc oder so zu setzen.
$ echo 'export LD_PRELOAD="/path/to/libaltsshauthsock.so"' >> ~/.bashrc
$ echo 'export ALT_SSH_AUTH_SOCK="/tmp/ssh-*/agent.*"' >> ~/.bashrc
Alles was Sie tun müssen, ist den Bildschirm wie gewohnt zu verwenden. Sie sollten in der Lage sein, ssh und git zu verwenden, ohne etwas zu tun, selbst wenn Sie das Anhängen / Trennen und Trennen der Sitzung wiederholen.
TODO:
Recommended Posts