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.