Přístup pomocí SSH na server za NAT-em

S tímto problémkem jsme se v minulosti utkali již vícekrát. Většinou jsme to řešili port forwardingem na routeru/firewallu (klasika). Alternativou je řešení pomocí OpenVPN. To jsme také několikrát využili.

Výjimečně jsme potřebovali tunelovat SSH. Řešili jsme to tak trochu po svém, než jsem při hledání něčeho jiného (jak už to bývá) narazil na Rootu v Jendově blogu na jednodušší řešení.

Kouzlo je ve spuštění jediného příkazu na serveru za NAT-em:

# ssh -R 0.0.0.0:2222:localhost:22 tunel@xx.xx.xx.xx -n -N 
-o ConnectTimeout=20 ConnectionAttempts=1

Je vhodné jej spustit pod speciálním uživatelem, kterému po odladění odebereme shell. Třeba takto, nebo přímou editací /etc/passwd (vipw):

# chsh tunel -s /bin/false

Spouštění je vhodné udělat z crontabu s ověřením, jestli příkaz běží. Nebo z rc.local jednoduchým skriptem (zde pod uživatelem tunel):

#!/bin/bash
while true; do
if wget http://xx.xx.xx.xx/test -q -O /dev/null
  then
    echo ok
    ssh -R 0.0.0.0:2222:localhost:22 tunel@xx.xx.xx.xx -n \
-N -o ConnectTimeout=20 ConnectionAttempts=1
    sleep 10 #když spojení spadne, pokusíme se ho obnovit ...
  else
    echo error
    sleep 1800
  fi
done

Aby skript takto fungoval, je vhodné pro uživatele použitého pro tunelování vygenerovat pár šifrovacích klíčů pro přihlášení bez hesla. Návod je například zde.

Přihlášení na server za NAT-em potom na cílovém serveru bude vypadak takto:

$ ssh -p 2222 root@localhost

To je celé. Půvab řešení je v i tom, že vám nevyrábí problémy iptables (tedy pokud máte povolena spojení na loopback na přístupovém serveru) nebo třeba SELinux.  Pozor. Ten se začne ozyvat až ve chvíli, kdy se pokusíte toto spojení bindnout na venkovní síťové rozhraní přístupového serveru. Pokud jste řídkou výjimkou a SELinux máte ještě zapnutý, tak inspiraci pro jeho rekonfiguraci najdete pod tímto odkazem.

Napsat komentář

Vaše emailová adresa nebude zveřejněna.