Outils personnels

Reverse ssh : Accéder à un serveur derrière un NAT - Firewall : Différence entre versions

De wikiGite

(Service au démarrage de A)
(SYSTEMD)
 
(21 révisions intermédiaires par 3 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
== Fonctionnement ==
+
== Avec au moins un accès externe ==
 +
Un des serveurs du réseau local protégé par un firewall est accessible en SSH depuis l'extérieur. Lui-même a ensuite accès aux autres serveurs du réseau local.
 +
 
 +
On peut, en ligne de commande, passer par ce serveur pour en atteindre un autre ([[Tunnel_SSH_via_un_serveur_interm%C3%A9diaire]]).
 +
 
 +
On peut aussi se servir de du paramètre ProxyCommand, dans ce cas le plus simple est de préconfigurer la connexion par le fichier .ssh/config du poste local. On y déclare :
 +
Host serveur_intermediaire
 +
    Hostname serveur_intermediaire.domain.com
 +
    User root
 +
    ForwardAgent yes
 +
Host serveur_de_destination
 +
    Hostname 192.168.0.200
 +
    User admin
 +
    ProxyCommand ssh serveur_intermediaire -q -W %h:%p
 +
 
 +
"ForwardAgent" : transférer l'agent local (donc notre config) sur le reverse proxy
 +
"Hostname 192.168.0.200" : pour le serveur final on utilise l'adresse réseau interne, celle connue du serveur_intermediaire
 +
 
 +
On a plus qu'à se connecter par
 +
ssh serveur_de_destination
 +
et l'agent + proxyCommand font le reste.
 +
 
 +
== Sans aucun accès externe ==
 
[[Fichier:Reverse.png]]
 
[[Fichier:Reverse.png]]
 
  
 
Le serveur A se trouvant derriere le par-feu créé un tunnel vers le serveur B. Depuis B on se connecte au serveur A au travers du tunnel ssh.
 
Le serveur A se trouvant derriere le par-feu créé un tunnel vers le serveur B. Depuis B on se connecte au serveur A au travers du tunnel ssh.
 
== Prérequis ==
 
== Prérequis ==
Ajouter cette ligne dans /etc/ssh/sshd_config :
+
Ajouter cette ligne dans /etc/ssh/sshd_config sur B:
 
<source lang="bash">AllowTcpForwarding yes</source>
 
<source lang="bash">AllowTcpForwarding yes</source>
  
Ligne 11 : Ligne 32 :
 
<source lang="bash">adduser userssh</source>
 
<source lang="bash">adduser userssh</source>
  
 +
== Reverse ssh ==
 +
Le port 22222 de l'exemple suivant doit se trouver entre 1024 et 65535. Il faut evidement tenir une liste des ports associés aux machines.
  
== Reverse ssh ==
 
 
Créez le tunnel sur le serveur A :
 
Créez le tunnel sur le serveur A :
 
<source lang="bash">ssh -NR 22222:localhost:22 userssh@serveurB</source>
 
<source lang="bash">ssh -NR 22222:localhost:22 userssh@serveurB</source>
Ligne 20 : Ligne 42 :
  
  
== Service au démarrage de A ==
+
== Lancement automatique sur le serveur A avec autossh ==
  
 
<source lang="bash">aptitude install autossh</source>
 
<source lang="bash">aptitude install autossh</source>
Ligne 30 : Ligne 52 :
 
<source lang="bash">ssh-copy-id -i /root/.ssh/id_dsa.pub userssh@serveurB</source>
 
<source lang="bash">ssh-copy-id -i /root/.ssh/id_dsa.pub userssh@serveurB</source>
  
 +
 +
=== En l’exécutant au démarrage (rc.local) ===
 
ajouter dans /etc/rc.local :
 
ajouter dans /etc/rc.local :
 
<source lang="bash">autossh -i /root/.ssh/id_dsa -NR 22222:localhost:22 userssh@serveurB &</source>
 
<source lang="bash">autossh -i /root/.ssh/id_dsa -NR 22222:localhost:22 userssh@serveurB &</source>
  
  
 +
=== En créant un script d'init ===
 +
==== SYSVINIT ====
 +
Créer un script dans /etc/init.d/autosshd et remplacer les variables REMOTE_ADDR et LISTEN_PORT :
  
Créer un script dans /etc/init.d/autosshd
+
<source lang="bash">
 +
#!/bin/bash
  
<source lang="bash">
 
#! /bin/bash
 
 
### BEGIN INIT INFO
 
### BEGIN INIT INFO
 
# Provides:          autosshd
 
# Provides:          autosshd
# Required-Start:    $local_fs $remote_fs $network $syslog
+
# Required-Start:     
# Required-Stop:    $local_fs $remote_fs $network $syslog
+
# Required-Stop:     
 
# Default-Start:    2 3 4 5
 
# Default-Start:    2 3 4 5
 
# Default-Stop:      0 1 6
 
# Default-Stop:      0 1 6
Ligne 49 : Ligne 75 :
 
### END INIT INFO
 
### END INIT INFO
  
DAEMON_OPTS="-i /root/.ssh/id_dsa -NR 22222:localhost:22 userssh@serveurB &"
+
REMOTE_USER="userssh"
NAME=autossh
+
REMOTE_ADDR="test.systea.fr"
 +
LISTEN_PORT="22222"
 +
 
 +
DAEMON="/usr/bin/autossh"
 
DESC="Autossh daemon"
 
DESC="Autossh daemon"
PID=/tmp/autossh.pid
+
LOGFILE="/var/log/autossh.log"
 +
PIDFILE="/tmp/$REMOTE_USER-$REMOTE_ADDR.pid"
 +
 
 +
export AUTOSSH_PIDFILE=/tmp/$REMOTE_USER-$REMOTE_ADDR.pid
 +
 
 +
test -f $DAEMON || exit 0
  
case "$1" in
+
is_running() {
  start)
+
    if [ -f $PIDFILE ]; then
         CD_TO_APP_DIR="cd /home/gitlab/gitlab"
+
        PID=`cat $PIDFILE`
         START_DAEMON_PROCESS="/var/lib/gems/1.9.1/bin/bundle exec unicorn_rails $DAEMON_OPTS"
+
         if [ -n "$PID" ]; then
        START_RESQUE_PROCESS="./resque.sh"
+
            return 0
 +
         else
 +
            return 1
 +
        fi
 +
    else
 +
        return 1
 +
    fi
 +
}
  
         echo -n "Starting $DESC: "
+
start_autossh() {
         if [ `whoami` = root ]; then
+
    if ! is_running; then
          sudo -u gitlab sh -c "$CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS && $START_RESQUE_PROCESS"
+
         echo -n "Starting $DESC"
 +
         $DAEMON -i /root/.ssh/id_dsa -NR $LISTEN_PORT:localhost:22 $REMOTE_USER@$REMOTE_ADDR >> $LOGFILE 2>&1 &
 +
        sleep 1;
 +
        if is_running; then
 +
            echo " [DONE] : Running @ pid $PID "
 
         else
 
         else
          $CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS && $START_RESQUE_PROCESS
+
            echo '[FAIL]';
 
         fi
 
         fi
         echo "$NAME."
+
    else
        ;;
+
         echo "[FAIL] Already running (pid $PID)"
  stop)
+
    fi
 +
}
 +
 
 +
stop_autossh() {
 +
    if is_running; then
 
         echo -n "Stopping $DESC: "
 
         echo -n "Stopping $DESC: "
         kill -QUIT `cat $PID`
+
         kill -s SIGTERM $PID
         kill -QUIT `cat $RESQUE_PID`
+
         echo "[DONE]"
        echo "$NAME."
+
    else
         ;;
+
        echo "[FAIL] : Not running "
  restart)
+
    fi
         echo -n "Restarting $DESC: "
+
    [ -f $APIDFILE ] && rm -f $PIDFILE
        kill -USR2 `cat $PID`
+
}
         kill -USR2 `cat $RESQUE_PID`
+
 
        echo "$NAME."
+
case "$1" in
         ;;
+
    start)
  reload)
+
        start_autossh
         echo -n "Reloading $DESC configuration: "
+
    ;;
        kill -HUP `cat $PID`
+
    stop)
         kill -HUP `cat $RESQUE_PID`
+
         stop_autossh
        echo "$NAME."
+
    ;;
         ;;
+
    force-reload|restart)
  *)
+
         stop_autossh
         echo "Usage: $NAME {start|stop|restart|reload}" >&2
+
        start_autossh
         exit 1
+
    ;;
        ;;
+
    status)
 +
        if is_running; then
 +
            echo "$DESC: running (pid $PID)"
 +
            exit 0
 +
         else
 +
            echo "$DESC: not running"
 +
            [ -f $PIDFILE ] && exit 1 || exit 3
 +
         fi
 +
    ;;
 +
    log)
 +
         if [ -f $LOGFILE ]; then
 +
            tail $LOGFILE
 +
         else
 +
            echo "[FAIL] : log file '$LOGFILE' does't exist"
 +
         fi
 +
    ;;
 +
    *)
 +
         echo "Usage: $0 {start|stop|restart|force-reload|status|log}"
 +
         exit 3
 +
    ;;
 
esac
 
esac
  
 
exit 0
 
exit 0
 +
 
</source>
 
</source>
  
Ligne 101 : Ligne 170 :
 
  update-rc.d autosshd defaults
 
  update-rc.d autosshd defaults
  
 +
==== SYSTEMD ====
 +
En créant un script /etc/systemd/system/foo-autossh.service
 +
<source lang="bash">
 +
[Unit]
 +
Description=AutoSSH service for a reverse tunnel from foo to bar
 +
After=network.target
 +
 +
[Service]
 +
User=autossh
 +
# -p [PORT]
 +
# -l [user]
 +
# -M 0 --> no monitoring
 +
# -N Just open the connection and do nothing (not interactive)
 +
# LOCALPORT:IP_ON_EXAMPLE_COM:PORT_ON_EXAMPLE_COM
 +
ExecStart=/usr/bin/autossh -M 0 -f -N -T -q -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -R 22222:localhost:22 userssh@serveurB
 +
ExecStop=killall -s KILL autossh
 +
Restart=always
 +
RestartSec=60
 +
 +
[Install]
 +
WantedBy=multi-user.target
 +
</source>
  
== Se connecter à d'autres port ==
+
== Se connecter à d'autres ports ==
 
On souhaite par exemple se connecter à un serveur web se trouvant sur A.
 
On souhaite par exemple se connecter à un serveur web se trouvant sur A.
  
Ligne 110 : Ligne 201 :
 
Sur B :
 
Sur B :
 
<source lang="bash">firefox "http://127.0.0.1:22280"</source>
 
<source lang="bash">firefox "http://127.0.0.1:22280"</source>
 +
 +
== Se connecter à partir d'un poste client ==
 +
 +
Poste ---> INTERNET ---> serveurB ---> INTERNET ---> serveurA
 +
 +
Sur le poste on lance :
 +
<source lang="bash">ssh root@serveurB -t ssh -p 22222 root@127.0.0.1</source>

Version actuelle datée du 11 janvier 2018 à 11:14

Avec au moins un accès externe

Un des serveurs du réseau local protégé par un firewall est accessible en SSH depuis l'extérieur. Lui-même a ensuite accès aux autres serveurs du réseau local.

On peut, en ligne de commande, passer par ce serveur pour en atteindre un autre (Tunnel_SSH_via_un_serveur_intermédiaire).

On peut aussi se servir de du paramètre ProxyCommand, dans ce cas le plus simple est de préconfigurer la connexion par le fichier .ssh/config du poste local. On y déclare :

Host serveur_intermediaire
   Hostname serveur_intermediaire.domain.com
   User root
   ForwardAgent yes
Host serveur_de_destination
   Hostname 192.168.0.200
   User admin
   ProxyCommand ssh serveur_intermediaire -q -W %h:%p

"ForwardAgent" : transférer l'agent local (donc notre config) sur le reverse proxy "Hostname 192.168.0.200" : pour le serveur final on utilise l'adresse réseau interne, celle connue du serveur_intermediaire

On a plus qu'à se connecter par

ssh serveur_de_destination

et l'agent + proxyCommand font le reste.

Sans aucun accès externe

Reverse.png

Le serveur A se trouvant derriere le par-feu créé un tunnel vers le serveur B. Depuis B on se connecte au serveur A au travers du tunnel ssh.

Prérequis

Ajouter cette ligne dans /etc/ssh/sshd_config sur B:

AllowTcpForwarding yes

Par sécurité créer un utilisateur dédié au tunnel sur B :

adduser userssh

Reverse ssh

Le port 22222 de l'exemple suivant doit se trouver entre 1024 et 65535. Il faut evidement tenir une liste des ports associés aux machines.

Créez le tunnel sur le serveur A :

ssh -NR 22222:localhost:22 userssh@serveurB

Se connecter au tunnel depuis le serveur B

ssh -p 22222 rootA@127.0.0.1


Lancement automatique sur le serveur A avec autossh

aptitude install autossh

Générer une paire de clef avec root

ssh-keygen -t dsa

Faire un echange de clef avec le serveur B:

ssh-copy-id -i /root/.ssh/id_dsa.pub userssh@serveurB


En l’exécutant au démarrage (rc.local)

ajouter dans /etc/rc.local :

autossh -i /root/.ssh/id_dsa -NR 22222:localhost:22 userssh@serveurB &


En créant un script d'init

SYSVINIT

Créer un script dans /etc/init.d/autosshd et remplacer les variables REMOTE_ADDR et LISTEN_PORT :

#!/bin/bash

### BEGIN INIT INFO
# Provides:          autosshd
# Required-Start:    
# Required-Stop:     
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the autossh daemon
# Description:       starts autossh
### END INIT INFO

REMOTE_USER="userssh"
REMOTE_ADDR="test.systea.fr"
LISTEN_PORT="22222"

DAEMON="/usr/bin/autossh"
DESC="Autossh daemon"
LOGFILE="/var/log/autossh.log"
PIDFILE="/tmp/$REMOTE_USER-$REMOTE_ADDR.pid"

export AUTOSSH_PIDFILE=/tmp/$REMOTE_USER-$REMOTE_ADDR.pid

test -f $DAEMON || exit 0

is_running() {
    if [ -f $PIDFILE ]; then
        PID=`cat $PIDFILE`
        if [ -n "$PID" ]; then
            return 0
        else
            return 1
        fi
    else
        return 1
    fi
}

start_autossh() {
    if ! is_running; then
        echo -n "Starting $DESC"
        $DAEMON -i /root/.ssh/id_dsa -NR $LISTEN_PORT:localhost:22 $REMOTE_USER@$REMOTE_ADDR >> $LOGFILE 2>&1 &
        sleep 1;
        if is_running; then
            echo " [DONE] : Running @ pid $PID "
        else
            echo '[FAIL]';
        fi
    else
        echo "[FAIL] Already running (pid $PID)"
    fi
}

stop_autossh() {
    if is_running; then
        echo -n "Stopping $DESC: "
        kill -s SIGTERM $PID
        echo "[DONE]"
    else
        echo "[FAIL] : Not running "
    fi
    [ -f $APIDFILE ] && rm -f $PIDFILE
}

case "$1" in
    start)
        start_autossh
    ;;
    stop)
        stop_autossh
    ;;
    force-reload|restart)
        stop_autossh
        start_autossh
    ;;
    status)
        if is_running; then
            echo "$DESC: running (pid $PID)"
            exit 0
        else
            echo "$DESC: not running"
            [ -f $PIDFILE ] && exit 1 || exit 3
        fi
    ;;
    log)
        if [ -f $LOGFILE ]; then
            tail $LOGFILE
        else
            echo "[FAIL] : log file '$LOGFILE' does't exist"
        fi
    ;;
    *)
        echo "Usage: $0 {start|stop|restart|force-reload|status|log}"
        exit 3
    ;;
esac

exit 0

Autoriser l'execution du script :

chmod +x /etc/init.d/autosshd

Ajouter le script au démarage :

update-rc.d autosshd defaults

SYSTEMD

En créant un script /etc/systemd/system/foo-autossh.service

[Unit]
Description=AutoSSH service for a reverse tunnel from foo to bar
After=network.target

[Service]
User=autossh
# -p [PORT]
# -l [user]
# -M 0 --> no monitoring
# -N Just open the connection and do nothing (not interactive)
# LOCALPORT:IP_ON_EXAMPLE_COM:PORT_ON_EXAMPLE_COM
ExecStart=/usr/bin/autossh -M 0 -f -N -T -q -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -R 22222:localhost:22 userssh@serveurB
ExecStop=killall -s KILL autossh
Restart=always
RestartSec=60

[Install]
WantedBy=multi-user.target

Se connecter à d'autres ports

On souhaite par exemple se connecter à un serveur web se trouvant sur A.

Sur A :

ssh -NR 22280:localhost:80 userssh@serveurB

Sur B :

firefox "http://127.0.0.1:22280"

Se connecter à partir d'un poste client

Poste ---> INTERNET ---> serveurB ---> INTERNET ---> serveurA

Sur le poste on lance :

ssh root@serveurB -t ssh -p 22222 root@127.0.0.1