Reverse ssh : Accéder à un serveur derrière un NAT - Firewall : Différence entre versions
De wikiGite
(→Reverse ssh) |
(→SYSTEMD) |
||
(20 révisions intermédiaires par 3 utilisateurs non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
− | == | + | == 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> | ||
Par sécurité créer un utilisateur dédié au tunnel sur B : | Par sécurité créer un utilisateur dédié au tunnel sur B : | ||
<source lang="bash">adduser userssh</source> | <source lang="bash">adduser userssh</source> | ||
− | |||
== Reverse ssh == | == Reverse ssh == | ||
− | Le port 22222 de l'exemple suivant doit se trouver entre 1024 et 65535. Il faut evidement tenir une liste des ports | + | 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 : | Créez le tunnel sur le serveur A : | ||
Ligne 21 : | Ligne 41 : | ||
<source lang="bash">ssh -p 22222 rootA@127.0.0.1</source> | <source lang="bash">ssh -p 22222 rootA@127.0.0.1</source> | ||
− | == | + | |
+ | == Lancement automatique sur le serveur A avec autossh == | ||
<source lang="bash">aptitude install autossh</source> | <source lang="bash">aptitude install autossh</source> | ||
Ligne 31 : | 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 : | ||
− | + | <source lang="bash"> | |
+ | #!/bin/bash | ||
− | |||
− | |||
### BEGIN INIT INFO | ### BEGIN INIT INFO | ||
# Provides: autosshd | # Provides: autosshd | ||
− | # Required-Start: | + | # Required-Start: |
− | # Required-Stop: | + | # 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 50 : | Ligne 75 : | ||
### END INIT INFO | ### END INIT INFO | ||
− | + | REMOTE_USER="userssh" | |
− | + | REMOTE_ADDR="test.systea.fr" | |
+ | LISTEN_PORT="22222" | ||
+ | |||
+ | DAEMON="/usr/bin/autossh" | ||
DESC="Autossh daemon" | 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 | ||
+ | } | ||
− | echo -n "Starting $DESC | + | 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 | else | ||
− | + | echo '[FAIL]'; | |
fi | fi | ||
− | echo "$ | + | else |
− | + | echo "[FAIL] Already running (pid $PID)" | |
− | + | fi | |
+ | } | ||
+ | |||
+ | stop_autossh() { | ||
+ | if is_running; then | ||
echo -n "Stopping $DESC: " | echo -n "Stopping $DESC: " | ||
− | kill - | + | kill -s SIGTERM $PID |
− | + | echo "[DONE]" | |
− | + | else | |
− | ;; | + | echo "[FAIL] : Not running " |
− | + | fi | |
− | echo | + | [ -f $APIDFILE ] && rm -f $PIDFILE |
− | + | } | |
− | + | ||
− | + | case "$1" in | |
− | ;; | + | start) |
− | + | start_autossh | |
− | + | ;; | |
− | + | stop) | |
− | + | stop_autossh | |
− | + | ;; | |
− | ;; | + | force-reload|restart) |
− | + | stop_autossh | |
− | echo "Usage: $ | + | start_autossh |
− | exit | + | ;; |
− | + | 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 102 : | 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 | + | == 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 111 : | 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
Sommaire
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
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