Tym-Project

From: SUPINFO
To: Tous
Subject: IT

Mettre en Place Un Tunnel-proxy SSH Autonome

Dans cet article je vous expliquais comment mettre en place un serveur servant à faire du tunneling ssh. Mais quid de la partie client me direz vous ? Et bien c’est ce dont il est question ici…

Je vais donc vous présenter un script que j’utilise pour gérer un tunnel ssh permanent, en réutilisant les principes d’authentification sans mot de passe. La première chose à faire est donc de générer une paire de clés sur le client :

ssh-keygen -t rsa

Comme habituellement, on copie la clé publique par un quelconque moyen sur le serveur. Comme ici l’utilisateur prox ne possède pas de mot de passe, on va passer par un autre compte. Il est déconseillé d’utiliser le compte root directement, il faut donc passer par un user normal. Voici par exemple une suite de commandes à exécuter :

scp ~/.ssh/id_rsa.pub tym@server.chez-moi.com:~
ssh -p 443 tym@server.chez-moi.com

Puis sur le serveur, où l’on passe en utilisateur root :

su - cat id_rsa.pub >> /home/tun1/.ssh/know_hosts && rm id_rsa.pub

Le serveur est maintenant prêt à nous authentifier sans mot de passe, il est temps de se pencher sur le script client. La première fonction est celle qui crée le tunnel. En l’occurrence dynamiquement sur le port 8080 :

1
2
3
4
function ssh_to_server(){
    /usr/bin/ssh -nN -D 8080 -p 443 tun1@server.chez-moi.com &
    echo $! > /var/run/ssh_prox_pid
}

Ce qui est intéressant ici c’est l’utilisation des options n et N (source) :

-N
    N'exécute aucune commande distante. Utilisé pour les transferts de ports (seulement dans la version 2 du protocole). 
-n
    redirige l'entrée standard vers /dev/null (en fait, empêche la lecture depuis l'entrée standard). À utiliser lors d'une utilisation de ssh en arrière-plan. [...]

Donc l’utilisation de ces deux options en plus du ”&” (lancement dans un processus fils) permettent de lancer le tunnel en arrière plan.

Afin que le script soit suffisamment robuste nous allons ajouter un peu plus de code. Tout d’abord une fonction pour vérifier la bonne connectivité à internet…inutile d’essayer d’ouvrir le tunnel pour rien :

1
2
3
function test_network(){
    ping -c 2 clubic.com
}

Ensuite une fonction pour tester si le tunnel est déjà lancé ou non :

1
2
3
function test_prox(){
    ps aux | grep -v 'grep' | grep `cat /var/run/ssh_prox_pid`
}

Ici ”[man]grep[/man] -v grep” sert à ne pas afficher le processus du grep, et donc ne pas fausser le résultat (sinon il serait toujours positif, même sans tunnel en route).

Et enfin le corps du script :

1
2
3
4
5
6
7
8
9
10
11
12
while :; do
    #Si le tunnel n'est pas déjà lancé
    if ! test_prox ;then
        #Alors on teste si le réseau est bien connecté
        if test_network;then
            #Si oui ou ouvre le tunnel ssh_to_server
        else
            #Si non le script "dors" 5 secondes
            sleep 5
        fi
    fi
done

Il ne reste plus qu’a planifier le lancement du script au démarrage, en utilisant [man]crontab[/man] par exemple :

# m h dom mon dow command @reboot /root/ssh_prox &

Voici le code du script complet :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash

function ssh_to_server(){
    /usr/bin/ssh -nN -D 8080 -p 443 tun1@server.chez-moi.com &
    echo $! > /var/run/ssh_prox_pid
}

function test_network(){
    ping -c 2 clubic.com
}

function test_prox(){
    ps aux | grep -v "grep" | grep `cat /var/run/ssh_prox_pid`
}

while :;do
    if ! test_prox ;then
        if test_network;then
            ssh_to_server
        else
            sleep  5
        fi
    fi
done

Bon bash ;-)

Comments