\ <ins > 26/04/2018 postscript
Écrivez une fonction shell appelée find_agent
pour le résoudre manuellement à chaque fois.
Il est certainement pratique de basculer automatiquement, mais cela n'est pas souvent nécessaire, et LD_PRELOAD gêne parfois le débogage, il n'y a donc pas beaucoup d'avantages ...
J'ai utilisé github pour vérifier la connexion de SSH_AUTH_SOCK. Les clés que j'utilise habituellement sont généralement placées dans github, donc j'ai des problèmes avec ssh car il s'agit du timing de git push. Les fichiers de socket doivent être globalisés avec des chemins
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>
Ci-dessous la description du 12/02/2016
github https://github.com/takei-yuya/alt_ssh_auth_sock
Je suis venu à Akita lors d'un voyage de ski, mais j'étais libre à l'auberge alors je l'ai écrit.
Une histoire pour éviter le problème que la référence de SSH_AUTH_SOCK utilisée pour le transfert ssh-agent par détachement / attachement est mal alignée lors de l'utilisation de screen à la destination de connexion de ssh.
En d'autres termes, ce genre de chose
local $ # ssh-Activer le transfert d'agent et se connecter à l'hôteA
local $ ssh -A hostA
hostA $ #SSH automatiquement à la destination de la connexion_AUTH_La variable d'environnement SOCK est définie
hostA $ declare -p SSH_AUTH_SOCK
declare -x SSH_AUTH_SOCK="/tmp/ssh-XXXXXXXXXX/agent.11111"
hostA $ #Cette socket est connectée au sshd pour cette session
hostA $ ps -p 11111
PID TTY TIME CMD
11111 ? 00:00:00 sshd
hostA $ #Même s'il n'y a pas de clé sur hostA, les informations de clé sont transférées via le socket.
hostA $ #Vous pouvez vous connecter à un autre hôte avec une authentification par clé
hostA $ ssh hostB
hostB $ exit
hostA $ #screen enregistre les variables d'environnement au démarrage de screen
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 #Détacher
hostA $ #Ce socket devient invalide à l'expiration de la session SSH
hostA $ #Essayez de vous reconnecter
hostA $ exit
local $ ssh -A hostA
hostA $ #Le chemin du socket change car la session a changé
hostA $ declare -p SSH_AUTH_SOCK
declare -x SSH_AUTH_SOCK="/tmp/ssh-YYYYYYYYYY/agent.33333"
hostA $ #L'ancienne session sshd a disparu
hostA $ ps -p 11111
PID TTY TIME CMD
hostA $ #Cependant, dans la session écran, les variables d'environnement sont toujours obsolètes ...
hostA $ screen -x ssh_test
hostA(screen) $ declare -p SSH_AUTH_SOCK
declare -x SSH_AUTH_SOCK="/tmp/ssh-XXXXXXXXXX/agent.11111"
hostA(screen) $ #Vieux ssh-le transfert d'agent ne se connecte pas ...
hostA(screen) $ ssh hostB
Permission denied (publickey).
Cela fait donc longtemps, mais ce genre de phénomène. Je veux faire quelque chose à ce sujet.
La cause est que les variables d'environnement ne sont pas mises à jour dans la session à l'écran.
Essayez d'utiliser un mécanisme appelé LD_PRELOAD.
En gros, cela semble être un mécanisme pour insérer de force une bibliothèque dynamique lors du démarrage d'un processus. Il peut être utilisé pour accrocher ou voler 400 000 appels système et appels de fonction de bibliothèque.
La fonction cible est getenv
. En d'autres termes, l'idée de falsifier de force les variables d'environnement de l'extérieur.
Vérifiez le SSH_AUTH_SOCK
actuel et si vous ne pouvez pas vous connecter au socket, essayez un autre socket. Les sockets candidats à essayer sont spécifiés par le modèle de fichier glob d'une autre variable d'environnement.
En d'autres termes
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>
//Variable statique pour stocker le getenv original
static char* (*_original_getenv)(const char *name) = NULL;
//Il semble que vous puissiez créer une fonction à exécuter avant la fonction principale en utilisant l'extension GNU.
static void _alt_ssh_auth_sock_init() __attribute__((constructor));
static void _alt_ssh_auth_sock_init() {
//Enregistrez le getenv d'origine
_original_getenv = dlsym(RTLD_NEXT, "getenv");
}
//Assurez-vous que le socket est actif. ...... Je suis juste en train de me connecter.
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;
}
//Remplacer le comportement de getenv
char* getenv(const char *name) {
if (!_original_getenv) {
//Quelque chose__attribute__((constructor))Peut ne pas fonctionner, donc juste au cas où
_alt_ssh_auth_sock_init();
}
if (strcmp(name, "SSH_AUTH_SOCK") != 0) {
// SSH_AUTH_Sauf pour SOCK, la fonction d'origine est utilisée telle quelle.
return _original_getenv(name);
}
char* ssh_auth_sock = _original_getenv("SSH_AUTH_SOCK");
if (!ssh_auth_sock) {
// SSH_AUTH_Si SOCK n'est pas défini, retournez tel quel.
return ssh_auth_sock; // == NULL
}
char* alt_ssh_auth_sock = _original_getenv("ALT_SSH_AUTH_SOCK");
if (!alt_ssh_auth_sock) {
//Si le modèle de socket alternatif n'est pas donné, rien ne peut être fait, alors abandonnez et revenez tel quel
return ssh_auth_sock;
}
if (check_socket(ssh_auth_sock) == 0) {
//Si le socket actuel est actif, retournez tel quel sans développer le glob
return ssh_auth_sock;
}
//Développez le modèle glob
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) {
//Si vous trouvez une prise vivante
break;
}
}
if (i < pglob.gl_pathc) {
// SSH_AUTH_Écraser SOCK
setenv("SSH_AUTH_SOCK", pglob.gl_pathv[i], 1);
ssh_auth_sock = _original_getenv("SSH_AUTH_SOCK");
}
globfree(&pglob);
return ssh_auth_sock;
}
Le tout affiché car il est court. Les détails sont tels que je l'ai écrit dans le commentaire, mais après avoir enregistré le getenv original, je l'utilise depuis getenv pour l'écraser.
Comment construire
cc -Wall -fPIC -shared -o libaltsshauthsock.so alt_ssh_auth_sock.c -ldl
Peut-être avez-vous besoin de soname. Un peu convenable par ici.
Pour le moment, je pense qu'il est préférable de définir des variables d'environnement dans bashrc ou quelque chose comme ça.
$ echo 'export LD_PRELOAD="/path/to/libaltsshauthsock.so"' >> ~/.bashrc
$ echo 'export ALT_SSH_AUTH_SOCK="/tmp/ssh-*/agent.*"' >> ~/.bashrc
Tout ce que vous avez à faire est d'utiliser screen comme d'habitude. Vous devriez être capable d'utiliser ssh et git sans rien faire, même si vous répétez l'attachement / détachement et déconnexion de la session.
TODO:
--Compatible avec Mac --Pour Mac, il semble utiliser la variable d'environnement DYLD_INSERT_LIBRARIES au lieu de LD_PRELOAD.
Recommended Posts