Title: Construisez un tunnel (ssh) de vos propres mains !!
Date: 2013-01-17 20:58
Modified: 2013-01-17 20:58
Category: Réseaux
Tags: ssh, tunnel, debian, sécurité
keywords: ssh, tunnel, debian, sécurité
Slug: construisez-tunnel-ssh
Authors: Victor
Status: published

[TOC]

## Un tunnel sans pelle

<p>Et sans terre sur les mains. Classe non ?</p>

<p>Et bien, c'est possible grâce à SSH. (entre autre hein, tunnel est un terme plutôt répandu en informatique, mais bon ça fait une bonne accroche)</p>

<p>Pour parler plus directement, un tunnel ssh va vous permettre de communiquer via SSH avec un serveur distant, et plus pécisément de rediriger certains ports locaux vers ce serveur, qui en fera ce que vous voulez.</p>

<p>&nbsp;</p>

<p>Typiquement, rediriger un port VNC dans un tunnel SSH permet de se connecter sur une machine distante de manière sécurisée. Alors que VNC de base, c'est quand même tout en clair à l'arrache.</p>

<p>Ce système permet de sécuriser la plupart des routages de ports sales que l'on peut faire sur une box pour rentrer dans son réseau. Bien sûr, il y a aussi des applications techniques plus intéressantes au niveau entreprise&nbsp;:-)</p>

<p>L'un des gros intérêts également, c'est que ça peut être utilisé sur un smartphone (<a href="https://fr.wikipedia.org/wiki/Smartphone">ordiphone</a>) sans aucun hack (ou rootage, ou jailbreak), contrairement à OpenVPN par exemple.</p>

## Il faut pas le dire

<p>Avec cette technique, vous pouvez également (ouh, c'est mal) passer certaines protections ou proxy, par exemple en redirigeant toutes vos connexion HTTP (port 80) sur un tunnel ssh sur le port 443 (HTTPS très rarement filtré) vers votre serveur, qui ensuite vous redirigera vers le site que vous vouliez.</p>

<p>Inconvenient : vous profitez de votre bande passante potentiellement pourrie, surtout si vous vous auto-hébergez (c'est le bien !), puisque où que vous soyiez, toutes vos requêtes Internet passeront par chez vous.</p>

<p>Avantage : vous mettez un doigt dans l'os à tout ces "filtrages" pseudo sécurité qui en fait font chier que les gens honnêtes. (Dont vous faites bien sûr partie)</p>

<p>Ce besoin qu'on a tous connu (ou qu'on imagine au moins) servira de contexte pour ce tuto.</p>

<p>&nbsp;</p>

## Le principe

<p>Comme d'habitude, un petit rappel du principe technique de la chose.</p>

<p>Nous allons mettre en place sur un serveur, placé où bon vous semble, ce qu'on appelle un shell SSH qui attendra des connexions extérieures.</p>

<p>Ce système est sensé permettre un accès SSH à votre serveur. Comme ce n'est pas le but ici, nous allons détourner le problème en mettant en place un shell hyper restreint. De cette façon vous pourrez fournir la connexion à qui vous voulez, en étant sûr qu'ils ne feront pas de mauvaises choses avec votre serveur. (On ne sait jamais :-)&nbsp;)</p>

<p>La connexion se fera grâce à un couple clef/mot de passe, pour une sécurité maximum. La connexion au tunnel sera interdite par tout autre moyen, ce qui permet de limiter les attaques par brute force notamment.</p>

<p>Chaque personne voulant se connecter devra donc posséder un couple clef/mot de passe fourni par vous. Dans cette optique et pour suivre plus simplement qui a quoi, nous allons créer pour chaque compte un utilisateur du système, qui aura le droit d'utiliser le tunnel. Ces utilisateurs appartiendront tous au groupe tunnelssh.</p>

<p>Ce système, même s'il peut créer beaucoup d'utilisateur, présente l'avantage d'être à la fois clair et d'avoir des logs faciles à lire (chaque tentative de connexion étant loggué par utilisateur)</p>

<p>Le système de redirection de port sera à votre convenance. Comme dit plus haut, j'utiliserais pour ma part le port 443, le plus communément ouvert même dans des lieux "limitatifs" sur des wifi "ouverts".</p>

<p>&nbsp;</p>

## Matériels, connaissances, besoins divers

<p>Comme toujours quand on est un gros hacker barbu, plusieurs choses s'imposent.</p>

<p>Tout d'abord, il va vous falloir un serveur sous Linux, qui permettra d'installer la sortie du tunnel. Vous vous connecterez avec votre machine sur lui, qui se chargera de rediriger ce que vous voulez où vous voulez.</p>

<p>Pour ma part, j'utilise debian, mais SSH étant plutôt répandu, ça ne posera pas de problème à transcrire ailleurs.</p>

<p>Il vous faudra aussi une autre machine servant de client pour les tests (Ordiphone Android/Iphone, PC fixe, PC portable, tablette, ...)</p>

<p>Il est conseillé de disposer d'un minimum de connaissances dans la ligne de commande, et connaître un peu le réseau (notamment les ports) est un plus apprécié. Cependant, il est possible de copier-coller les commandes, donc pas la peine de trembler si vous ne maitrisez pas le bousin&nbsp;:-)</p>

<p>&nbsp;</p>

<p>Enfin, comme l'objectif est de travailler honnêtement pour promouvoir un Internet plus libre, une bonne bière n'est pas de refus !</p>

<p>&nbsp;</p>

## Bien. On est parti.

### configuration du tunnel

<p>Pour commencer, connectez vous sur votre serveur, via un SSH classique. Si vous utilisez directement un écran/clavier/souris, il faudra vérifier qu'openSSH est correctement installé :</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo aptitude install openssh-server</span></span></p>

<p>Une fois cela fait, nous allons créer une deuxième instance d'OpenSSH server, qui va écouter sur le port 443 et qui servira exclusivement pour le tunnel. Pour ce faire, créez un fichier sshd_config_tunnel, placé dans /etc/ssh :</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo nano /etc/ssh/sshd_config_tunnel</span></span></p>

<p>A l'intérieur, copiez-collez ce qui suit :&nbsp;</p>

<p style="margin-left: 40px;">Port <strong>443</strong><br />
<br />
#ListenAddress ::<br />
#ListenAddress 0.0.0.0<br />
Protocol 2<br />
# HostKeys for protocol version 2<br />
HostKey /etc/ssh/ssh_host_rsa_key<br />
HostKey /etc/ssh/ssh_host_dsa_key<br />
#Privilege Separation is turned on for security<br />
UsePrivilegeSeparation yes<br />
<br />
KeyRegenerationInterval 3600<br />
ServerKeyBits 768<br />
<br />
# Logging<br />
SyslogFacility AUTH<br />
LogLevel INFO<br />
<br />
# Authentication:<br />
LoginGraceTime 120<br />
<strong>PermitRootLogin no<br />
AllowGroups tunnelssh</strong><br />
StrictModes yes<br />
<br />
<strong>AllowTcpForwarding yes</strong><br />
<strong>#PermitOpen IP_LOCALE:PORT_LOCAL</strong><br />
AllowAgentForwarding no<br />
<br />
RSAAuthentication yes<br />
PubkeyAuthentication yes<br />
AuthorizedKeysFile %h/.ssh/authorized_keys<br />
<br />
IgnoreRhosts yes<br />
RhostsRSAAuthentication no<br />
<br />
HostbasedAuthentication no<br />
#IgnoreUserKnownHosts yes<br />
<br />
PermitEmptyPasswords no<br />
<br />
ChallengeResponseAuthentication no<br />
<strong>PasswordAuthentication no</strong><br />
<br />
# Kerberos options<br />
#KerberosAuthentication no<br />
#KerberosGetAFSToken no<br />
#KerberosOrLocalPasswd yes<br />
#KerberosTicketCleanup yes<br />
<br />
# GSSAPI options<br />
#GSSAPIAuthentication no<br />
#GSSAPICleanupCredentials yes<br />
<br />
X11Forwarding no<br />
X11DisplayOffset 10<br />
PrintMotd no<br />
PrintLastLog yes<br />
TCPKeepAlive yes<br />
#UseLogin no<br />
<br />
#MaxStartups 10:30:60<br />
#Banner /etc/issue.net<br />
<br />
AcceptEnv LANG LC_*<br />
<br />
Subsystem sftp /usr/lib/openssh/sftp-server<br />
<br />
UsePAM yes</p>

<p>C'est en fait un fichier de configuration ssh classique modifié pour notre usage. Je l'ai épuré des commentaires pour qu'il ne soit pas trop lourd, et j'ai mis en gras les morceaux importants :</p>

<ul>
	<li>Port 443 : c'est ici que vous allez définir sur quel port écoute votre serveur. Comme dit précedemment, j'utilise le port 443, mais vous mettez ce que vous voulez.</li>
	<li>PermitRootLogin no : cette directive va interdire toute connexion au serveur avec l'utilisateur root.</li>
	<li>AllowGroups tunnelssh : cela permet d'autoriser uniquement les utilisateurs appartenant au groupe tunnelssh de se connecter.</li>
	<li>AllowTcpForwarding yes : cette directive va autoriser votre serveur SSH à transmettre ce qui lui arrive dessus vers une autre machine (typiquement vos requêtes Internet)</li>
	<li>#PermitOpen IP_LOCALE:PORT_LOCAL : cette directive (ici commenté) peut vous servir si vous voulez utiliser votre tunnel pour accéder à une seule machine de votre réseau local. Par exemple, pour vous connecter sur votre PC avec VNC. Si vous désirez utilisez votre tunnel pour accéder à Internet, laissez cette ligne commentée.</li>
	<li>PasswordAuthentication no : cette directive va imposer l'utilisation d'une clef SSH pour vous connecter au serveur.</li>
</ul>

<p>&nbsp;</p>

<p>Il va également vous falloir lancer ce serveur en parallèle du vrai serveur SSH (que je vous conseille de laisser pour les accès "administratifs" dont vous pourriez avoir besoin).</p>

<p>Pour ce faire, il suffit de créer dans le dossier /etc/init.d/ un nouveau fichier de lancement ssh :</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo nano /etc/init.d/ssh_tunnel</span></span></p>

<p>Dans lequel vous pouvez copiez-collez :</p>

<p style="margin-left: 40px;">#! /bin/sh<br />
<br />
### BEGIN INIT INFO<br />
# Provides: sshd_tunnel<br />
# Required-Start: $remote_fs $syslog<br />
# Required-Stop: $remote_fs $syslog<br />
# Default-Start: 2 3 4 5<br />
# Default-Stop: 0 1 6<br />
# Short-Description: OpenBSD Secure Shell server<br />
### END INIT INFO<br />
<br />
set -e<br />
<br />
# /etc/init.d/ssh: start and stop the OpenBSD "secure shell(tm)" daemon<br />
<br />
test -x /usr/sbin/sshd || exit 0<br />
( /usr/sbin/sshd -\? 2&gt;&amp;1 | grep -q OpenSSH ) 2&gt;/dev/null || exit 0<br />
<br />
umask 022<br />
<br />
if test -f /etc/default/ssh; then<br />
. /etc/default/ssh<br />
fi<br />
<br />
. /lib/lsb/init-functions<br />
<br />
if [ -n "$2" ]; then<br />
SSHD_OPTS="$SSHD_OPTS $2"<br />
fi<br />
<br />
SSHD_OPTS="$SSHD_OPTS -f<strong> /etc/ssh/sshd_config_tunnel"</strong><br />
<br />
# Are we running from init?<br />
run_by_init() {<br />
([ "$previous" ] &amp;&amp; [ "$runlevel" ]) || [ "$runlevel" = S ]<br />
}<br />
<br />
check_for_no_start() {<br />
# forget it if we're trying to start, and /etc/ssh/sshd_not_to_be_run exists<br />
if [ -e /etc/ssh/sshd_not_to_be_run ]; then<br />
if [ "$1" = log_end_msg ]; then<br />
log_end_msg 0<br />
fi<br />
if ! run_by_init; then<br />
log_action_msg "OpenBSD Secure Shell server not in use (/etc/ssh/sshd_not_to_be_run)"<br />
fi<br />
exit 0<br />
fi<br />
}<br />
<br />
check_dev_null() {<br />
if [ ! -c /dev/null ]; then<br />
if [ "$1" = log_end_msg ]; then<br />
log_end_msg 1 || true<br />
fi<br />
if ! run_by_init; then<br />
log_action_msg "/dev/null is not a character device!"<br />
fi<br />
exit 1<br />
fi<br />
}<br />
<br />
check_privsep_dir() {<br />
# Create the PrivSep empty dir if necessary<br />
if [ ! -d /var/run/<strong>sshd_tunnel</strong> ]; then<br />
mkdir /var/run/<strong>sshd_tunnel</strong><br />
chmod 0755 /var/run/<strong>sshd_tunnel</strong><br />
fi<br />
}<br />
<br />
check_config() {<br />
if [ ! -e /etc/ssh/sshd_not_to_be_run ]; then<br />
/usr/sbin/sshd $SSHD_OPTS -t || exit 1<br />
fi<br />
}<br />
<br />
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"<br />
<br />
case "$1" in<br />
start)<br />
check_privsep_dir<br />
check_for_no_start<br />
check_dev_null<br />
log_daemon_msg "Starting OpenBSD Secure Shell server" <strong>"sshd_tunnel"</strong><br />
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/<strong>sshd_tunnel.pid</strong> --exec /usr/sbin/sshd -- $SSHD_OPTS; then<br />
log_end_msg 0<br />
else<br />
log_end_msg 1<br />
fi<br />
;;<br />
stop)<br />
log_daemon_msg "Stopping OpenBSD Secure Shell server" <strong>"sshd_tunnel"</strong><br />
if start-stop-daemon --stop --quiet --oknodo --pidfile /var/run/<strong>sshd_tunnel.pid</strong>; then<br />
log_end_msg 0<br />
else<br />
log_end_msg 1<br />
fi<br />
;;<br />
<br />
reload|force-reload)<br />
check_for_no_start<br />
check_config<br />
log_daemon_msg "Reloading OpenBSD Secure Shell server's configuration" <strong>"sshd_tunnel"</strong><br />
if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile /var/run/<strong>sshd_tunnel.pid</strong> --exec /usr/sbin/sshd; then<br />
log_end_msg 0<br />
else<br />
log_end_msg 1<br />
fi<br />
;;<br />
<br />
restart)<br />
check_privsep_dir<br />
check_config<br />
log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"<br />
start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile /var/run/<strong>sshd_tunnel.pid</strong><br />
check_for_no_start log_end_msg<br />
check_dev_null log_end_msg<br />
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/<strong>sshd_tunnel.pid</strong> --exec /usr/sbin/sshd -- $SSHD_OPTS; then<br />
log_end_msg 0<br />
else<br />
log_end_msg 1<br />
fi<br />
;;<br />
<br />
try-restart)<br />
check_privsep_dir<br />
check_config<br />
log_daemon_msg "Restarting OpenBSD Secure Shell server" "sshd"<br />
set +e<br />
start-stop-daemon --stop --quiet --retry 30 --pidfile /var/run/<strong>sshd_tunnel.pid</strong><br />
RET="$?"<br />
set -e<br />
case $RET in<br />
0)<br />
# old daemon stopped<br />
check_for_no_start log_end_msg<br />
check_dev_null log_end_msg<br />
if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/<strong>sshd_tunnel.pid</strong> --exec /usr/sbin/sshd -- $SSHD_OPTS; then<br />
log_end_msg 0<br />
else<br />
log_end_msg 1<br />
fi<br />
;;<br />
1)<br />
# daemon not running<br />
log_progress_msg "(not running)"<br />
log_end_msg 0<br />
;;<br />
*)<br />
# failed to stop<br />
log_progress_msg "(failed to stop)"<br />
log_end_msg 1<br />
;;<br />
esac<br />
;;<br />
<br />
status)<br />
status_of_proc -p /var/run/<strong>sshd_tunnel.pid</strong> /usr/sbin/sshd sshd &amp;&amp; exit 0 || exit $?<br />
;;<br />
<br />
*)<br />
log_action_msg "Usage: /etc/init.d/<strong>ssh_tunne</strong>l {start|stop|reload|force-reload|restart|try-restart|status}"<br />
exit 1<br />
esac<br />
<br />
exit 0</p>

<p>Ce fichier est une copie du fichier /etc/init.d/ssh classique, mais modifié pour lancer le bon fichier de configuration et pour tourner en parallèle du serveur classique (notamment avec son propre pid)</p>

<p>Les parties modifiées sont en gras.</p>

<p>Enregistrez le fichier puis rendez-le exécutable.</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo chmod 755 /etc/init.d/ssh_tunnel</span></span></p>

<p>Si vous le souhaitez, vous pouvez configurer le tunnel pour se lancer au démarrage :</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo update-rc.d ssh_tunnel defaults</span></span></p>

### Configuration du groupe d'utilisateur

<p>Nous allons ensuite créer le groupe tunnelssh, qui sera utilisé pour toutes les connexions.</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo groupadd tunnelssh</span></span></p>

<p>Il suffira ensuite de créer vos utilisateurs comme appartenant à ce groupe pour leur donner l'autorisation de se connecter au tunnel. Nous allons voir un script permettant de faire ça tout seul.&nbsp;:-)</p>

### Configuration du shell

<p>Afin que vos utilisateurs ne puissent pas se balader dans votre serveur via l'accès SSH du tunnel, nous allons créer un shell bidon. Cela permettra en plus d'afficher une jolie bannière pour l'utilisation du tunnel.</p>

<p>En avant. Créez un fichier dans /usr/bin :</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo nano /usr/bin/tunnelshell</span></span></p>

<p>Qui contient quelque chose dans ce genre là :</p>

<p style="margin-left: 40px;">#!/bin/bash<br />
echo "Connexion limitée au tunnel SSH."<br />
read -p "Appuyez sur ENTREE pour vous déconnecter..."</p>

<p>Ainsi, toute personne se connectant sur votre tunnel verra apparaître ce message :</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">Connexion limitée au tunnel SSH.</span></span></p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">Appuyez sur ENTREE pour vous déconnecter...</span></span></p>

<p>Comme indiqué, une pression de la touche entrée provoque la déconnexion immédiate du tunnel.<br />
Vous êtes bien sûr libre de changer le message !&nbsp;;-)</p>

### On y est !

<p>A ce stade, votre tunnel ssh est prêt à être utilisé. Il suffit de créer un utilisateur appartenant au groupe tunnelssh, de lui configurer comme shell /usr/bin/tunnelshell, puis de lui créer son couple clef/mot de passe.</p>

<p>Comme je suis super sympa (mouahahah), je vous propose un petit script qui fait tout ça tout seul.</p>

<p>Je vous conseille de le placer dans le dossier /root, ou à défaut dans un dossier à accès limité, puisqu'il contiendra tous les certificats de tous vos utilisateurs.</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo mkdir /root/tunnelSSH</span></span></p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo nano /root/tunnelSSH/Addsshtunneluser.sh</span></span></p>

<p>Dans celui-ci, vous pouvez mettre :&nbsp;</p>

<p style="margin-left: 40px;">#!/bin/bash<br />
<br />
if [ "$1" = "" ]; then<br />
echo "Usage : Addsshtunneluser.sh name passphrase<br />
fi<br />
<br />
if [ "$2" = "" ]; then<br />
echo "Usage : Addsshtunneluser.sh name passphrase<br />
fi<br />
<br />
mkdir /home/$1<br />
mkdir /home/$1/.ssh<br />
useradd $1 --home-dir /home/$1 --groups tunnelssh --no-user-group --shell /usr/bin/tunnelshell<br />
ssh-keygen -t dsa -b 1024 -N $2 -f /home/$1/.ssh/id_dsa<br />
cp /home/$1/.ssh/id_dsa.pub /home/$1/.ssh/authorized_keys<br />
chmod 700 /home/$1/.ssh<br />
chmod 600 /home/$1/.ssh/authorized_keys<br />
chown -R $1:tunnelssh /home/$1<br />
cp /home/$1/.ssh/id_dsa tunnelssh-$1</p>

<p>Ce script s'exécute de la manière suivante :</p>

<p><span style="color:#ffffff;"><span style="background-color:#000000;">$ sudo bash /root/tunnelSSH/Addsshtunneluser.sh UTILISATEUR MOTDEPASSE</span></span></p>

<ul>
	<li>UTILISATEUR est le nom du nouvel utilisateur à créer</li>
	<li>MOTDEPASSE est le mot de passe à donner à l'utilisateur</li>
</ul>

<p>Le script va alors créer un utilisateur portant ce nom. L'utilisateur appartiendra au groupe tunnelssh, et disposera de son répertorie /home/UTILISATEUR</p>

<p>Le script va ensuite créer la clef SSH à l'aide du MOTDEPASSE (on parle bien sûr d'un couple clef privée/clef publique). Il va ensuite copier la dite clef dans le dossier /root/tunnelSSH/ avec un nom du type tunnelssh-UTILISATEUR, ce qui va vous permettre de la récupérer facilement pour la transmettre à l'utilisateur concerné.</p>

<p>Il lui faudra alors utiliser cette clef pour configurer son tunnel ssh de la manière suivante :</p>

<ul>
	<li>Adresse : l'adresse IP ou FQDN de votre serveur</li>
	<li>Port : le port d'écoute de votre tunnel (ici 443)</li>
	<li>Utilisateur : son nom d'utilisateur</li>
	<li>Connexion par clef : avec la clef que vous lui avez transmis ainsi que le mot de passe associé</li>
</ul>

<p>Normalement, tout doit baigner !</p>

## Voila, c'est creusé

<p>Avec tout ça, vous devriez être à même de vous connecter depuis n'importe où sur votre serveur.</p>

<p>A titre informatif, pour mettre en place le tunnel côté client :</p>

<ul>
	<li>Windows : utilisez <a href="http://www.putty.org/">Putty</a> (allié à PuttyGen pour transformer votre clef en format Putty)</li>
	<li>Linux/MacOSX : utilisez simplement openssh&nbsp;:-)</li>
	<li>Android : utilisez <a href="https://play.google.com/store/apps/details?id=org.connectbot">ConnectBot</a></li>
	<li>iPhone : Payez... Mais vous l'avez choisi avec un tel téléphone !</li>
</ul>

<p>Si jamais j'ai des demandes, je me lancerai dans un petit tuto pour l'une ou l'autre des plateformes&nbsp;:-)</p>

<p>Si vous avez des soucis, posez la question dans les commentaires !</p>
