[LINUX] L'histoire de la tentative de pousser SSH_AUTH_SOCK obsolète avec LD_PRELOAD à l'écran

\ <ins > 26/04/2018 postscript

Que s'est-il passé après deux ans

É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.

Qu'est-ce que c'est?

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.

que vas-tu faire?

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

Ça arrive

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.

Comment utiliser

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.

Que faire ensuite

TODO:

--Compatible avec Mac --Pour Mac, il semble utiliser la variable d'environnement DYLD_INSERT_LIBRARIES au lieu de LD_PRELOAD.

Recommended Posts

L'histoire de la tentative de pousser SSH_AUTH_SOCK obsolète avec LD_PRELOAD à l'écran
L'histoire d'essayer de reconnecter le client
L'histoire de l'échec de la mise à jour de "calendar.day_abbr" sur l'écran d'administration de django
Histoire d'essayer d'utiliser Tensorboard avec Pytorch
Une histoire sur la tentative de contribuer à l'analyse COVID-19 avec l'offre gratuite d'AWS et l'échec
L'histoire de ne pas pouvoir exécuter pygame avec pycharm
L'histoire de la mise en place de MeCab dans Ubuntu 16.04
L'histoire d'essayer deep3d et de perdre
L'histoire du changement de pep8 en pycodestyle
L'histoire d'un débutant en apprentissage profond essayant de classer les guitares avec CNN
L'histoire de l'apprentissage profond avec TPU
Introduction à Python avec Atom (en route)
L'histoire d'essayer Sourcetrail × macOS × VS Code
L'histoire de la fabrication de soracom_exporter (j'ai essayé de surveiller SORACOM Air avec Prometheus)
Histoire de passer de Pipenv à la poésie
L'histoire d'un technicien de haut niveau essayant de prédire la survie du Titanic
Une histoire qui a échoué lors de la tentative de suppression du suffixe d'une chaîne avec rstrip
Je ne trouve pas l'horloge tsc! ?? L'histoire d'essayer d'écrire un patch de noyau
Je veux tracer les informations de localisation de GTFS Realtime sur Jupyter! (Avec ballon)
Un moyen simple de remplir le début de 0 en fonction du nombre de chiffres dans le nombre [Python]
Un mémo sur la façon de surmonter le problème difficile de la capture d'effets avec l'IA
Une note de malentendu lors de la tentative de chargement de l'intégralité du module self-made avec Python3
Une histoire sur la tentative d'introduire Linter au milieu d'un projet Python (Flask)
L'histoire de l'arrêt du service de production avec la commande hostname
Ajoutez des informations au bas de la figure avec Matplotlib
L'histoire du partage de l'environnement pyenv avec plusieurs utilisateurs
Essayez d'estimer le nombre de likes sur Twitter
Essayez d'obtenir le contenu de Word avec Golang
Transition vers l'écran de mise à jour avec le Django a tag
L'histoire de vouloir acheter une aventure en forme de bague
L'histoire de l'utilisation de Circleci pour construire des roues Manylinux
Comment enregistrer les mêmes données plusieurs fois avec une seule entrée sur l'écran de gestion de Django
Comment connaître le nombre de GPU de python ~ Remarques sur l'utilisation du multitraitement avec pytorch ~
J'ai essayé de trouver l'entropie de l'image avec python
Mémo pour obtenir la valeur côté html-javascript avec jupyter
L'histoire de la mise en œuvre du sujet Facebook Messenger Bot avec python
J'ai essayé de trouver la moyenne de plusieurs colonnes avec TensorFlow
lire le tag qui vous est attribué dans ec2 avec boto3
Sakura L'histoire du fonctionnement de la bouteille Python sur Internet
L'histoire de l'introduction de Jedi (package de complétion automatique de python) dans emacs
Exécutons la commande à temps avec le bot discord
Paramètres pour entrer et déboguer le contenu de la bibliothèque avec VS Code
L'histoire du rubyiste aux prises avec Python :: Dict data with pycall
Essayez d'automatiser le fonctionnement des périphériques réseau avec Python
Jusqu'au début du tutoriel django avec pycharm sous Windows
Une histoire sur la façon de traiter le problème CORS
L'histoire de la copie de données de S3 vers TeamDrive de Google
Lors de la génération d'un grand nombre de graphiques avec matplotlib, je ne souhaite pas afficher le graphique à l'écran (environnement jupyter)
Technologie qui prend en charge Jupyter: Tralets (histoire d'essayer de déchiffrer)
Enregistrer des images sur le Web sur un lecteur avec Python (Colab)
L'histoire de la définition de la clé privée à 600 avec chmod
L'histoire de la création d'un bot de boîte à questions avec discord.py
Obtenez le nom d'hôte du PC hôte avec Docker sous Linux
Récupérez la source de la page à charger indéfiniment avec python.
Essayez d'extraire les caractéristiques des données de capteur avec CNN
J'ai essayé de déverrouiller l'entrée 2 lock sésame d'une simple pression sur le bouton AWS IoT
Authentification à deux facteurs avec Cognito + Amplify (entrez ID / PW / "valeur de code à deux facteurs" sur l'écran de connexion pour vous authentifier)
Une histoire dans laquelle l'algorithme est arrivé à une conclusion ridicule en essayant de résoudre correctement le problème du voyageur de commerce
L'histoire de la construction de Zabbix 4.4