Hogyan érhetjük el NAT hálózat mögött lévő otthoni vagy munkahelyi Linux-os számítógépünket fordított SSH csatorna segítségével

botond küldte be 2019. 01. 10., cs - 02:02 időpontban

Tartalom

 

Bevezető

Manapság egyre gyakrabban felmerül az igény arra, hogy az ember bárhonnan el tudja érni otthoni vagy munkahelyi számítógépét, hogy fájlokat mozgathasson/szinkronizálhasson akár mobiltelefonjára, vagy parancsokat futtathasson az otthoni / munkahelyi számítógépén, bárhonnan. Erre nagyon sok kész megoldást találhatunk jobbnál jobb távirányító vagy adatszinkronizáló programok formájában, sőt még ingyenes változatokban is, ahol a másik gépről vagy mobilról nagyszerűen lehet kezelni a beállított távoli gép asztalát, vagy akár fájlokat szinkronizálhatunk velük. Ez mind szép, és jó, de mindegyikkel ugyanaz a gond: csak arra tudjuk őket használni, amire készítették. Távoli asztal kapcsolat, fájlküldés, vagy touchpad funkció mobilról.

De mi van akkor, ha mi egyedi felhasználási módon vagy automatizáltan szeretnénk adatforgalmat bonyolítani a kapcsolaton keresztül grafikus felület igénybevétele nélkül, vagy csak egy protokollszintű adatcsatornát szeretnénk nyitni távolról a számítógépünkkel, amin más eszközökkel, programokkal cserélhetünk adatokat? Ez már nem olyan egyszerű, ugyanis a fogyatkozó IPv4-es címek miatt a legtöbb internetszolgáltató NAT (Network Address Translation) hálózat mögé helyezi a lakossági internetkapcsolat végpontjait, ami olyan, mintha több előfizető egy nagy router mögött lenne. Ez annyit jelent, hogy az előfizetők kisebb csoportjai ugyanazt a publikus IP-címet kapják meg, amivel az internetre léphetnek. Vagy éppen egy céges tűzfal állja utunkat a mögötte lévő gépek elérése közben. Bármelyik szituáció is legyen, így nehézkessé válik hogy a nyílt internetről elérhessünk a kívánt számítógépet.

Egyszerű port továbbításokkal még neki lehetne állni a dolognak, de ha egy többszörösen beágyazott (router, tűzfal, stb) hálózat mögötti gépet szeretnénk "kintről" elérni, akkor a port átirányításokkal is rendesen meggyűlhet a bajunk. De szerencsére van megoldás!

Ebben a leírásban egy fordított SSH alagút segítségével építünk ki egy SSH kapcsolatot, amin keresztül már bármikor hozzáférhetünk a cél számítógéphez, legyen az akárhány router vagy tűzfal mögött is.

 

 

Előfeltételek

Ezt a beállítást Linuxon végezzük el, tehát első körben szükségünk lesz egy Linux rendszert futtató otthoni vagy munkahelyi számítógépre. Windows rendszerre is vannak külön SSH tunnel-ező programok, de ebben a leírásban csak a Linux beállításával foglalkozunk. Ha mégis valaki mindenképpen el szeretné érni a külvilágból az otthoni Windows gépét, akkor célszerű feltelepíteni egy Cygwin rendszert, amit érdemes lebutítani a lehető legminimálisabb szintre (SSH, SSHd, alap shell parancsok, stb), hogy ne fogyasszon sok erőforrást. Ezután már működni fognak benne a leírás további részei. A továbbiakban ezt a gépet nevezzük otthoni számítógépnek.

Másodsorban szükségünk lesz egy élő SSH hozzáféréshez, ami elérhető bárhonnan az internetről. Ez lehet egy szerverparkban elhelyezett saját szerver vagy egy bérelt szerver, vagy egy havi kb. 1000 forintos VPS szolgáltatás, amin van root hozzáférésünk. De akár egy ismerősnél lévő Linuxos számítógép is lehet, ami egy fix IP-címre van kapcsolva és bekéredzkedhetünk egy SSH hozzáférés kérése erejéig. Ezt az SSH hozzáféréssel rendelkező szervert nevezzük közvetítő szervernek.

És végül kell egy számítógép, vagy mobiltelefon, tablet, stb, ami az interneten bárhol lehet, a lényeg, hogy tudjunk róla SSH kapcsolatot kezdeményezni, végtére is ez lenne  a célunk, hogy bárhonnan elérjük az otthoni számítógépet SSH-n keresztül. Ezt nevezzük innentől kliens számítógépnek.

Ezeken felül még szükséges a jelszó nélküli SSH belépés beállítása az otthoni számítógépről a közvetítő szerver felé, hogy a későbbi automatikus csatlakozás is működhessen.

 

Működési elv

A könnyebb átláthatóság kedvéért először vázoljuk fel röviden az egésznek a működési elvét. Adott a fent felsorolt három összetevő, amiknek a szerepe a következő:

Az otthoni számítógépről nyitunk egy SSH alagutat a közvetítő szerverre. Kifelé ugye gond nélkül lehet SSH-t használni bárhova. Ezen a nyitott SSH alagúton keresztül a közvetítő szerver már bármikor tud visszafelé csatlakozni az otthoni számítógépre. Ezért is hívják fordított SSH alagútnak. És mivel a közvetítő szerver bárhonnan elérhető az internetről, ezért a kliens számítógépről fel tudunk rá csatlakozni. Innentől már csak a közvetítő szervernek kell megnyitnia az új kapcsolatot vissza az otthoni számítógép felé, majd közvetítenie a két gép közötti forgalmat.

Ezen az elven működnek egyébként a VPN hálózatok, és a fentebb említett távirányító, fájlszinkronizáló programok is, amik a saját kiszolgálóikat használják közvetítő szervernek. Így tehát most magunk állítunk össze egy VPN-hez hasonló saját hálózatot.

 

Kapcsolat beállítása

A kapcsolat beállítása során több paramétert is használunk, amik a leírás végéig ugyanazok maradnak. Ezért most itt definiáljuk őket:

  • A közvetítő szerver IP-címe legyen 100.100.100.100
  • Szükség lesz egy portra is, amit átirányítunk a közvetítés során, ez pedig legyen 12345
  • Az otthoni számítógép felhasználója legyen otthoni_felhasznalo
  • A közvetítő szerveren használt felhasználó pedig legyen kozvetito_felhasznalo

A továbbiakban tehát Ezekkel a paraméterekkel fogom elkészíteni a beállításokat, így nem keverjük őket össze. Itt mindenki helyettesítse be a saját IP-címét, portszámát és felhasználó neveit.

Én e leírás készítése közben az asztali gépemmel (otthoni számítógép NAT-olt DIGI net+routerrel) saját bérelt szerveremmel (közvetítő szerver), és (mobilnetre állított) mobiltelefonommal (kliens számítógép) hajtom végre ezeket a beállításokat a saját paramétereimmel, ahol a mobilnetről fogom elérni az itthoni gépemet. Így garantálni tudom a dolgok működőképességét.

Fordított SSH alagút létesítése

Először nyitunk egy fordított SSH alagutat az otthoni számítógépről a közvetítő szerver felé. Ehhez az ssh parancsot használjuk.

Az otthoni számítógépen az otthoni_felhasznalo-val adjuk ki a következő parancsot:

ssh -fN -R 12345:localhost:22 kozvetito_felhasznalo@100.100.100.100

Ahol a kapcsolók és paraméterek jelentése a következő:

  • -fN: Az ssh parancsot a háttérbe rakja és nem futtat le semmilyen parancsot a közvetítő szerveren. Csak port átirányításnál használjuk
  • -R 12345:localhost:22: Ez definiálja a fordított SSH alagutat: A közvetítő szerver 12345-ös számú portját továbbítja a helyi gép (otthoni számítógép) 22-es portjára. Ha az alapértelmezett 22-es SSH porttól eltérőt használunk az otthoni gépünkön, akkor természetesen használjuk azt. Valamint ügyeljünk rá, hogy az általam itt kiválasztott 12345-ös számú port ne legyen használatban más programok által, mert akkor másik portot kell választani.
  • kozvetito_felhasznalo@100.100.100.100: Ez pedig értelemszerűen a csatlakozást határozza meg a közvetítő szerver felé a kozvetito_felhasznalo-hoz.

Ha a közvetítő szerverünkön (a nagyobb biztonság érdekében) eltérő, egyedi SSH csatlakozási portot használunk az alapértelmezett 22-es porttól, akkor szúrjuk a végére a -p kapcsolóval:

ssh -fN -R 12345:localhost:22 kozvetito_felhasznalo@100.100.100.100 -p <egyedi portszám>

Ha sikeres a parancs futtatása, akkor egyből visszakapjuk a shell-t. Ehhez persze már működnie kell a fentebb már említett jelszó nélküli SSH belépésnek, hogy felhasználói beavatkozás nélkül menjen a bejelentkezés a közvetítő szerverre.

Ezután lépjünk be a közvetítő szerverre, és a netstat paranccsal ellenőrizzük, hogy valóban létrejött-e az átirányítás:

sudo netstat -nap | grep 12345

Ha működik, akkor ilyesminek kell lennie a kimenetnek:

tcp   0   0 127.0.0.1:12345    0.0.0.0:*      LISTEN    14377/sshd: kozvetito_felhasznalo

Fordított SSH alagút lezárása

Ha szükséges, bármikor lezárhatjuk a kapcsolatot az SSH alagút bármelyik végéről.

Kapcsolat lezárása a közvetítő szerverről:

A közvetítő szerveren történő lezáráshoz az előző netstat parancstól kapott kimenetben lévő process ID kilövésével zárhatjuk le az SSH alagutat a közvetítő szerveren kiadott paranccsal:

kill 14377

Kapcsolat lezárása az otthoni számítógépről:

Ha pedig a túloldalon, azaz az otthoni számítógépről szeretnénk bontani az SSH alagutat, akkor először ki kell keresni a háttérben elindított SSH parancs processz ID-jét:

ps -x | grep 12345:localhost

A -x kapcsolóval kapjuk meg a háttérben futó folyamatokat is. Kimenetként kiad valami hasonlót:

3191 ? Ss 0:00 ssh -fN -R 12345:localhost:22 <kozvetito_felhasznalo>@100.100.100.100

Ezután lőjük ki a kapott PID-et:

kill 3191

Azonban még ne zárjuk le a csatornát, vagy nyissuk meg újra, mert még dolgunk lesz vele.

Csatlakozás NAT-olt géphez a közvetítő szerverre lépéssel

Innentől kezdve ha bárhonnan belépünk a közvetítő szerverre, akkor arról be tudunk jelentkezni az otthoni számítógépbe a közvetítő szerveren kiadott alábbi paranccsal:

ssh -p 12345 otthoni_felhasznalo@localhost

Figyeljünk rá, hogy az otthoni számítógépen lévő otthoni_felhasznalo nevet adjuk meg, azután pedig annak a jelszavát, és nem a közvetítő szerverét.

Itt annyi történik, hogy a közvetítő szerveren az SSH paranccsal önmagára kapcsolódunk (localhost), de mivel az átirányított porton lépünk be, így azt a fentebb beállított átirányítás következtében a közvetítő szerver már irányítja is át a nyitva tartott SSH alagút túlsó végén lévő számítógép 22-es portjára, azaz az otthoni számítógép SSH protokolljára. És mivel az otthoni számítógép felhasználónevét adtuk meg, így azzal be is jelentkezik az SSH-ra, majd kéri a jelszót, mert ugye visszafele nincs beállítva a nyilvános kulcs.

Első belépéskor a jelszó bekérése előtt jön a szokásos első belépéskori kérdés, amire yes-el válaszoljunk:

The authenticity of host '[localhost]:12345 ([::1]:12345)' can't be established.
ECDSA key fingerprint is xx:xx:xx:xx:xx:42:e8:13:55:0b:96:ce:f7:fe:87:e9.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[localhost]:12345' (ECDSA) to the list of known hosts.

Ekkor a közvetítő szerveren tárolásra kerül az otthoni számítógép, mint ismert hoszt. Ezután adjuk meg az otthoni számítógép felhasználójának jelszavát, és már bent is vagyunk az otthoni gépen.

Csatlakozás NAT-olt géphez közvetlenül az SSH alagúton keresztül

Idáig működik minden, viszont ez még nem tökéletes, mert kétszer kell bejelentkeznünk hogy elérjük az otthoni számítógépet. Egyszer be kell jelentkeznünk a közvetítő szerverre, majd onnan pedig az otthoni számítógépre. Ez így egy kicsit kényelmetlen.

Szerencsére van megoldás erre is, hogy csak egyszer kelljen belépnünk ahhoz, hogy elérjük az otthoni számítógépet. Ehhez  a közvetítő szerveren be kell állítanunk az sshd-t, hogy ne csak a localhostról engedje a port átirányítást, hanem külső címekről is.

A közvetítő szerveren nyissuk meg a /etc/ssh/sshd_conf fájlt:

sudo nano /etc/ssh/sshd_config

És adjuk hozzá a következő sort:

GatewayPorts clientspecified

Majd indítsuk újra az ssh daemont:

sudo service sshd restart

Ezután zárjuk le a csatornát a fentebb leírt módon az alagút valamelyik végéről, majd az otthoni számítógépen ismét nyissunk egy új SSH tunnel-t, de kicsit másképp:

ssh -fN -R 100.100.100.100:12345:localhost:22 kozvetito_felhasznalo@100.100.100.100

(az egyedi portot itt is a végére szúrhatjuk, ha nem a 22-es portot használjuk a közvetítő szerveren)

Itt annyi a különbség a fenti SSH alagút nyitásához képest, hogy megadtuk a közvetítő szerver publikus IP-címét is, így a csatorna végpontja most már nem a 127.0.0.1:12345 (mivel nem adtuk meg korábban, így a localhost az alapértelmezett), hanem a 100.100.100.100:12345, azaz a közvetítő szerver publikus IP-címe, ami azt jelenti, hogy a csatorna másik vége elérhető közvetlenül a külvilág felől is, anélkül, hogy be kellene jelentkezni a közvetítő szerverre.

A csatorna megnyitása után itt is ellenőrizhetjük az átirányítás sikerességét a közvetítő szerveren kiadott paranccsal:

sudo netstat -nap | grep 12345
tcp    0   0 100.100.100.100:12345    0.0.0.0:*     LISTEN      23060/sshd: kozvetito_felhasznalo

Ezután már bárhonnan csatlakozhatunk az otthoni számítógéphez egyetlen belépéssel. A kliens számítógépen tehát adjuk ki a következő parancsot:

ssh -p 12345 otthoni_felhasznalo@100.100.100.100

Tehát az otthoni számítógép felhasználónevét adjuk meg és a közvetítő szerverhez csatlakozunk a megfelelő portszámmal. Ekkor a közvetítő szerver automatikusan továbbítja a forgalmat és egyből az otthoni számítógépen találjuk magunkat.

Persze az elején kezdhettük volna kapásból ezzel a localhost-os megoldás helyett, azonban érdemes szem előtt tartani, hogy az ilyen módon a külvilág felé is elérhetővé tett port átirányítás kevésbé biztonságos, mint a fenti "két lépcsős" bejelentkezés. Mert így már egyel több port van nyitva, ami egy port szkennelésnél is látható. Persze az SSH kapcsolat biztonságos, csak érdemes megemlíteni, mint biztonsági kockázatot, ami egyébként minden nyitott portra érvényes.

 

 

Tartós SSH alagút beállítása

Már csak egy dolog hiányzik a tökéletes működéshez, mégpedig a stabilitás. A fentiek szépen működnek mindaddig, amíg nem történik egy hálózati kimaradás, vagy éppen a szolgáltató gondol egyet és IP-címet vált, stb. Mert ilyen esetekben az SSH kapcsolat megszakad, és akkor annyi az alagútnak, nem érjük el többé távolról a gépünket. Márpedig így nem tudunk alapozni egy ilyen kapcsolatra, ami elég sérülékeny.

Erre kínál megoldást az autossh parancs, ami automatikusan újracsatlakozik, így hálózati gubanc után újraépíti nekünk az SSH alagutunkat.

Az otthoni számítógépen telepítsük fel a programot az alábbi apt-get paranccsal:

sudo apt-get install autossh

Itt már mindenképpen szükséges a fentebb említett jelszó nélküli SSH belépés beállítása, mert enélkül nem fog tudni újracsatlakozni távollétünkben.

Ha van nyitva korábbi csatornánk, zárjuk be, és nyissunk egy újat helyette az autossh segítségével.

autossh \
    -M 10900 \
    -o "PubkeyAuthentication=yes" \
    -o "StrictHostKeyChecking=false" \
    -o "PasswordAuthentication=no" \
    -o "ServerAliveInterval 60" \
    -o "ServerAliveCountMax 3" \
    -fN \
    -R 100.100.100.100:12345:localhost:22 kozvetito_felhasznalo@100.100.100.100

A parancs hossza miatt több sorba tördeltem hogy áttekinthetőbb legyen.

A paraméterek jelentése a következő:

  • -M 10900: Monitor port. Ezt használja az autossh program a teszt adatok küldözgetéséhez, amivel figyeli a kapcsolat állapotát.
  • -o "PubkeyAuthentication=yes": Nyilvános kulcsos hitelesítést használ a jelszó helyett (emiatt kell a beállítás)
  • -o "StrictHostKeyChecking=false": Kihagyja az ismeretlen hosztok ellenőrzését.
  • -o "PasswordAuthentication=no": Ez együtt jár a nyilvános kulcsos opcióval: kikapcsolja a jelszó bekérését
  • -o "ServerAliveInterval 60": Életjel küldése 60 másodpercenként
  • -o "ServerAliveCountMax 3": Maximum ennyi életjelet küld el kapott válasz nélkül. Utána lebontja a kapcsolatot, majd újracsatlakozik.
  • -fN: Háttérbe rakja magát, ugyanúgy, mint az ssh parancsnál, és nem futtat parancsot.
  • -R...: Ezek pedig a már korábban is használt tunnelező beállítások

(Itt is a végéhez fűzhetjük a -p paraméterrel az egyedi SSH portszámot, amennyiben nem a 22-est használjuk a közvetítő szerveren)

Ezzel a paranccsal már stabil SSH tunnel jön létre, ami automatikusan újracsatlakozik, ha hálózati kimaradás történne.

Ezt a csatornát pedig az alábbi módon bonthatjuk az otthoni számítógépről:

killall autossh

(persze ha nem használunk más autossh példányokat, mert akkor marad a PID kikeresése és annak kilövése)

Ha pedig a gép újraindítása után is szeretnénk hogy elinduljon, akkor az autossh parancsot tegyük bele egy shell scriptbe, tegyük futtathatóvá, majd állítsuk be a gépünk automatikus indításába.

 

Konklúzió

Ezzel a módszerrel tehát bárhonnan elérhetővé tehetjük otthoni vagy munkahelyi számítógépünket, bárhol is legyünk. Az SSH tunnel kiépítésével már sok mindenre használható a kapcsolat, nem csak terminál parancsok futtatására. Használható SFTP fájlkezelésre, vagy rsync-el történő fájlszinkronizálásra, vagy bármire, ami SSH kapcsolaton keresztül működik. Én például a mobiltelefonomon lévő X-Plore fájlkezelőben állítottam be magamnak az itthoni gépemet az SSH fájlátvitel részbe, így bárhonnan kényelmesen hozzáférek az itthoni dolgaimhoz.

Természetesen én is használok távirányító programot (TeamViewer), de ahogy a legelején is írtam, ez nem mindig a legpraktikusabb választás. Például a fájlátviteli része messze nem olyan kényelmes, mint az X-Plore fájlkezelő. Amúgy távoli asztal kezelésre tökéletes.

 

 

Hozzászólások

csak egy telefon a diginek hogy "ne legyek NATolva". Simán beállítják. Egy portforward a routeredben... No meg egy ingyenes domain szolgáltatás (pl. ipdns.hu).