Pourquoi ce travail cron rsync + ssh me donne-t-il des erreurs «Autorisation refusée (publickey)»?

20

Je fais des sauvegardes fréquentes sur un disque local que je souhaite synchroniser quotidiennement avec un serveur distant.

Le serveur cible est configuré pour l'accès par clé SSH (pas de mot de passe) uniquement. Étant donné que ma clé SSH principale pour ce serveur est protégée par une phrase secrète, j'ai créé une deuxième clé SSH (non protégée par une phrase secrète) + utilisateur à utiliser pour les sauvegardes sans assistance - de cette façon, je n'ai pas besoin d'être présent pour saisir ma phrase secrète lors de l'exécution de cron .

J'utilise cron et rsync, et toutes les commandes fonctionnent individuellement, mais échouent lorsqu'elles sont combinées.

Le plus loin que j'ai obtenu pendant le dépannage est en cours d'exécution

env -i sh -c "rsync -lrstRO --delete --exclude 'lost+found' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/"

qui renvoie l'erreur

Permission denied (publickey).
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(226) [sender=3.1.0]

Des conseils sur la façon de résoudre ce problème davantage?


Voici ce que j'ai essayé jusqu'à présent et je suis à court d'idées:

  1. Cron tourne définitivement ps aux | grep cron
  2. Rien d'inhabituel dans / var / log / syslog Sep 7 13:22:01 desktop CRON[6735]: (tom) CMD (sh /home/tom/Documents/Scripts/offsite-backup)

  3. SSH dans le terminal vers le serveur distant pendant le travail de l'utilisateur de sauvegarde ssh [email protected]

  4. L'exécution de la commande dans Terminal fonctionne parfaitement rsync -lrstRO --delete --exclude 'lost+found' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/
  5. La spécification manuelle du chemin d'accès à la clé de sauvegarde-utilisateur n'a aucun effet rsync -lrstRO --delete --exclude 'lost+found' -e 'ssh -i /home/tom/.ssh/backups-only' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/

  6. Remplacer la commande non fonctionnelle par une commande de test simple fonctionne echo "Hello world" > ~/Desktop/test.txt

  7. Crier / jurer devant l'ordinateur n'a eu aucun effet (mais m'a fait me sentir mieux temporairement).


Modifier 1:

Voici mon fichier crontab et le script qu'il appelle.

...
# m h  dom mon dow   command
MAILTO=""
* * * * * sh /home/tom/Documents/Scripts/offsite-backup

et

#!/bin/bash

rsync -lrstRO --delete --exclude 'lost+found' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/

Modifier 2:

Juste pour clarifier, /var/log/auth.logsur le serveur cible contient la ligne Sep 11 08:23:01 <hostname> CRON[24421]: pam_unix(cron:session): session closed for user rootC'est déroutant car je n'exécute plus cron toutes les minutes localement, mais une nouvelle entrée apparaît toujours toutes les minutes dans les journaux du serveur. Fichiers Crontab pour tous utilisateurs (y compris root) sur le serveur sont vides et ne font rien.

De plus, les «sauvegardes uniquement» de l'utilisateur ont été créées uniquement sur le serveur et avec des droits limités, avec une clé SSH dédiée copiée sur ma machine de bureau. Je suppose que c'est la voie à suivre car tout fonctionne lors de l'exécution manuelle des commandes.

Le fichier crontab affiché ci-dessus est pour moi, l'utilisateur 'tom' sur ma machine de bureau. Mon intention est de le faire appeler le script qui devrait se connecter au serveur en tant qu'utilisateur «sauvegardes uniquement». J'ai juste essayé d'exécuter le script de sauvegarde (plutôt que la commande à l'intérieur) et il a réussi à se connecter et à fonctionner. Je l'ai exécuté sur mon bureau en tant qu'utilisateur 'tom', le même utilisateur qui a créé le travail cron qui ne fonctionnera pas. Voici la sortie du journal du serveur correspondant à cette connexion réussie

Sep 11 08:35:31 <hostname> sshd[25071]: error: Could not load host key: /etc/ssh/ssh_host_ed25519_key
Sep 11 08:35:32 <hostname> sshd[25071]: Accepted publickey for backups-only from <desktop IP> port 54242 ssh2: RSA e2:e6:07:27:c1:continues...
Sep 11 08:35:32 <hostname> sshd[25071]: pam_unix(sshd:session): session opened for user backups-only by (uid=0)
Sep 11 08:35:32 <hostname> systemd-logind[638]: New session 12 of user backups-only.
Sep 11 08:36:00 <hostname> sshd[25133]: Received disconnect from <desktop IP>: 11: disconnected by user
Sep 11 08:36:00 <hostname> sshd[25071]: pam_unix(sshd:session): session closed for user backups-only
Tom Brossman
la source
Si 3. fonctionne en utilisant le fichier clé et 6. fonctionne également, alors ... euh ... que dit le fichier journal sshd du côté réception?
Jan
@Jan I getSep 7 14:45:01 <hostname> CRON[18716]: pam_unix(cron:session): session closed for user root
Tom Brossman
C'est soit la mauvaise ligne de journal, soit l'utilisateur qui essaie de se connecter via ssh est root ... Ou est-ce à partir de la machine qui lance les sauvegardes?
Jan
1
Tom, 2 questions juste pour être sûr que dans votre premier commentaire, la logline a CRON [...], mais ça devrait ressembler Sep 7 16:06:02 <hostname> sshd[6747].... Êtes-vous sûr à 100% que cette ligne de connexion provient du serveur et que c'est la bonne ligne? La crontab que vous avez publiée est la crontab des sauvegardes uniquement ? Essayez également d'ajouter le fichier d'identité manuellement:rsync .... -e 'ssh -i /home/user/.ssh/identity' ...
janvier
1
De plus, cette ligne que auth.logvous avez publiée sous Edit 2 est destinée à l'exécution de cron sur le serveur et ne devrait avoir rien à voir avec vos tentatives de connexion. Pouvez-vous essayer tail -f /var/log/auth.logsur le serveur pendant que vous essayez d'exécuter le script via cron? De plus, je ne sais pas si cela fonctionnerait, mais pouvez-vous essayer votre première envcommande avec rsync .... -e 'ssh -vvv -i /home/user/.ssh/identity ...pour voir si elle génère plus d'erreurs?
Alaa Ali

Réponses:

15

Étant donné que tout fonctionne correctement à partir de la ligne de commande, l'erreur Permission denied (publickey)signifie que la partie SSH dersync utilise un fichier d'identité différent de celui du nom d'utilisateur spécifié.

À partir du commentaire de Jan sur la question d'origine, nous pouvons spécifier le fichier d'identité dans la rsynccommande en utilisant -e 'ssh -i /path/to/identity.file' ....

L'utilisation de la commande ci-dessous pour commencer avec un nouvel environnement dans cron et en spécifiant le chemin d'accès complet au fichier résout apparemment le problème:

env -i sh -c "rsync -lrstRO --delete --exclude 'lost+found' -e 'ssh -i /home/tom/.ssh/backups-only' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/"

Je suis toujours très intéressé par cette découverte. Cela a probablement à voir avec cron, le fait qu'il commence avec des variables d'environnement minimales et l'agent ssh. Je mettrai en place le même scénario dans quelques jours pour le tester et faire rapport.

Alaa Ali
la source
1
Voulez-vous dire que vous avez couruenv -i sh -c "rsync -lrstRO --delete --exclude 'lost+found' -e 'ssh -i /path/to/identity.file' /Backups/auto-daily-backups/./ [email protected]:/backups/desktop/"
qazwsx
@Problemania whops, fixed.
Alaa Ali
Je vois que vous avez une réponse, mais je suis curieux de lancer «sudo crontab -e» qui est le cron racine. Que se passe-t-il si vous «crontab -e» lorsque vous êtes connecté en tant qu'utilisateur «sauvegarde».
wlraider70
Je pense que vous vouliez dire cela pour la personne qui a posé la question. Mais il utilisait la crontab de son nom d'utilisateur, pas root, et je pense qu'il ne voulait pas utiliser la crontab de l'utilisateur de sauvegarde.
Alaa Ali
lorsque j'exécute un script similaire avec mon utilisateur, il prend la clé ssh via X11, donc j'avais besoin d'une copie locale si la clé, et assurez-vous que ce fichier a le propriétaire et les droits corrects, combinés avec ce qui précède a bien fonctionné pour moi.
Sverre
1

Je viens de résoudre ce problème qui m'a occupé ..

Impossible de se connecter en RSYNC sur SSH, malgré avoir stipulé l'identité de SSH ... Rien n'est fait ... Rsync dit "permission refusée" et ssh me dit "read_passphrase: impossible d'ouvrir / dev / tty: Aucun périphérique ou adresse de ce type"

Mais j'ai lu un article qui expliquait que le crontab a son propre environnement qui n'est pas le même que root. Je le savais déjà, mais je ne comprenais pas l'impact que cela pouvait avoir sur SSH lors de l'utilisation de SSH-AGENT

Mais mes échanges de clés SSH se font avec PassPhrase ... donc si l'environnement est différent et mon RSYNC sur SSH attend une phrase secrète qui ne peut pas être entrée => les informations de débogage SSH indiquent également l'erreur:

"debug1: read_passphrase: impossible d'ouvrir / dev / tty: aucun périphérique ou adresse de ce type" => Eh bien oui non TTY = pas de phrase secrète = non autorisé

Sur ma machine, j'utilise "Keychain" pour lancer l'agent SSH, donc je n'ai pas à ressaisir la phrase secrète à chaque fois que j'essaye une connexion à distance. Le trousseau génère un fichier qui contient les informations suivantes

SSH_AUTH_SOCK = /tmp/ssh-PWg3yHAARGmP/agent.18891; export SSH_AUTH_SOCK; SSH_AGENT_PID = 18893; export SSH_AGENT_PID;

==> La commande SSH-AGENT renvoie les mêmes informations.

Donc, au final, ce sont ces informations liées à la session en cours qui permettent de futures authentifications de la session en cours, sans avoir besoin de saisir la phrase secrète car déjà faite précédemment et mémorisée ...

==> La solution est là ... il suffit dans le script lancé par la crontab, et de "source" le fichier contenant ces informations ou de le faire sur la ligne de commande ds la crontab ...

exemple: 14 09 * * *. /home/foo/.keychain/foo.serveur.org-sh && scp -vvv -P 22 /tmp/mon_fic/toto.sh [email protected]:. >> / var / log / check_connexion.log 2> & 1 ou utilisez la commande "source /home/foo/keychain/foo.server.org-sh" dans le script qui démarre une connexion en utilisant SSH.

=> Avec ce sourcing, plus de soucis. Les informations de SSH_AUTH_SOCK et SSH_AGENT_PID sont chargées dans l'environnement du Crontab et sont donc connues, le RSYNC sur SSH fonctionne sans aucun problème.

Ça m'a occupé mais maintenant ça marche :)

SoniXtrA
la source
1

Avertissement pour ceux qui utilisent le transfert d'agent SSH:

Si vous voyez ce comportement lors du débogage d'un script sur un hôte distant, c'est parce que même avec le -e "ssh -i /path/to/key" indicateur, ssh utilisera votre clé locale (transférée) plutôt que celle sur le serveur.

Exemple concret: J'ai un script sur le serveur de développement qui extrait les données du "serveur de données" en utilisant rsync sur ssh. Lorsque je me connecte au serveur de développement et que je l'exécute, tout va bien, mais lors de l'exécution à partir de cron, l'autorisation est refusée. En ajoutant de la verbosité au processus SSH (indicateur -vv), j'ai remarqué ce qui suit:

debug2: key: /home/nighty/.ssh/id_rsa (0x562d8b974820),
debug2: key: /home/juanr/.ssh/id_rsa (0x562d8b962930), explicit
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/nighty/.ssh/id_rsa
debug2: we sent a publickey packet, wait for reply
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug2: input_userauth_pk_ok: fp 1a:19:08:9f:80:16:b1:db:55:42:9a:52:b2:49:9b:0a
debug1: Authentication succeeded (publickey).

Ce qui m'a fait comprendre ici, c'est que par pur hasard, il se trouve que j'ai un nom d'utilisateur différent sur l'hôte local ("nighty") que sur le serveur de développement ("juanr").

Remarquez comment il marque la clé sur le serveur de développement comme "explicite", mais utilise toujours la clé transférée de mon ordinateur portable pour se connecter. Faire un ssh-copy-idà ce stade ne résout rien, car il réinstalle simplement la clé transférée plutôt que celle du développeur serveur. Si vous utilisez ssh-copy-id avec le transfert d'agent, vous devez spécifier la clé à installer avec l'indicateur -i:ssh-copy-id -i ~/.ssh/id_rsa.pub user@host .

jrial
la source
0

Avez-vous déjà essayé l'ancienne astuce de nettoyage des fichiers hôtes? Je veux dire:

rm ~/.ssh/known_hosts

Cela vaut la peine d'essayer car ssh le reconstruira et vous vous débarrasserez des choses périmées. Vous pouvez bien sûr également supprimer les pièces appartenant à un IP / Host donné.

Plus de questions: votre tâche cron s'exécute-t-elle sous votre UID ou s'exécute-t-elle en tant qu'utilisateur cron ou root?

runlevel0
la source
1
Les commandes fonctionnent chacune individuellement, donc je ne vois pas comment la suppression ~/.ssh/known_hostschangerait quoi que ce soit? Et cron s'exécute en tant que mon utilisateur «tom» sur le bureau, avec l'intention de se connecter au serveur en tant que «sauvegardes uniquement» de l'utilisateur avec cette clé SSH correspondante (sans mot de passe), qui est dans l'utilisateur tom ~/.ssh.
Tom Brossman
3
@ runlevel0 Ni le -rni le -fdrapeau ne sont nécessaires pour supprimer - known_hostsc'est un fichier normal (pas un répertoire), et ce n'est pas en lecture seule. rm .ssh/known-hostsserait considérablement plus sûr, étant donné qu'une faute de frappe à un seul caractère - l'ajout accidentel d'un espace entre .et ssh/known_hostsaprès rm -rf(ou rm -r) supprimerait généralement tout le contenu du dossier de départ de l'utilisateur!
Eliah Kagan du
Salut Eliah, excellent point en effet !! J'utilise le drapeau -rf comme une action réflexe, mais vous avez absolument raison. Moi mauvais.
runlevel0
0

Utilisez le rrsync script avec une clé ssh dédiée comme suit:

Serveur REMOTE

mkdir ~/bin
gunzip /usr/share/doc/rsync/scripts/rrsync.gz -c > ~/bin/rrsync
chmod +x ~/bin/rrsync

Ordinateur LOCAL

ssh-keygen -f ~/.ssh/id_remote_backup -C "Automated remote backup"      #NO passphrase
scp ~/.ssh/id_remote_backup.pub [email protected]:/home/devel/.ssh

Ordinateur distant

cat id_remote_backup.pub >> authorized_keys

Ajoutez à la ligne nouvellement ajoutée ce qui suit

command="$HOME/bin/rrsync -ro ~/backups/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding

Pour que le résultat ressemble

command="$HOME/bin/rrsync -ro ~/backups/",no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding ssh-rsa AAA...vp Automated remote backup

LOCAL

Mettez votre crontabscript suivant avec xpermission:

#!/bin/sh
echo ""
echo ""
echo "CRON:" `date`
set -xv
rsync -e "ssh -i $HOME/.ssh/id_remote_backup" -avzP [email protected]:/ /home/user/servidor 

Source: http://www.guyrutenberg.com/2014/01/14/restricting-ssh-access-to-rsync/

Alessandro Cuttin
la source
0

Pour essayer de déboguer, ajoutez à la partie ssh "ssh -v" de cette façon, vous pouvez obtenir le mode détaillé avec des informations utiles.

Modifier: à partir de la page de manuel:

-v      Verbose mode.  Causes ssh to print debugging messages about its progress.  This is helpful in debugging connection,
             authentication, and configuration problems.  Multiple -v options increase the verbosity.  The maximum is 3.
Pedro Luz
la source
-1

Je pense que vous n'avez pas configuré correctement le fichier sshd_config. Vérifiez cela PermitRootLogin yeset PubkeyAuthentication yes pour la maintenance à distance.

Anandu M Das
la source
1
Il n'essaie pas de se connecter en tant que root, et il a probablement correctement configuré l'authentification par clé publique car il peut ssh et même exécuter la commande de sauvegarde à partir du terminal avec succès.
Alaa Ali
1
Merci pour les conseils mais je n'ai définitivement pas PermitRootLoginactivé et je n'ai pas l'intention de changer cela. La meilleure pratique consiste à le désactiver, et ssh uniquement en tant qu'utilisateur normal (ajoutez-les à vos 'sudoers' si nécessaire) et jamais en tant que root.
Tom Brossman