Możliwość dostępu do komputera przy pomocy tunelu
Ostatnia zmiana: 2014-12-17 20:26

Często istnieje potrzeba dostania się do komputera który jest zza natem i nie ma bezpośredniej możliwości przekierowania portów na routerze. Najczęściej ma to miejsce będąc w sieci bez publicznego adresu IP, z zablokowanymi portami lub np. przy połączeniach komórkowych. Obejściem tego problemu jest utworzenie tunelu z tego komputera do innego, posiadającego publiczny adres IP. Odwołując się wtedy do tego zdalnego komputera wracamy tunelem do naszego komputera. Opisana metoda z wykorzystaniem SSH nazywana jest "odwrotny tunel" (reverse tunnel), ponieważ to klient nawiązuje połączenie z hostem w sieci.

Zaletą rozwiązania jest możliwość dostania się do zasobów urządzenia które nawiązuje połączenie, brak potrzeby instalacji dodatkowego oprogramowania, wadą zaś - potrzeba uzyskania dostępu do komputera z publicznym adresem IP, widocznym w sieci.

Założenia: urządzenie zza natem z OpenWrt bez publicznego adresu IP do którego będziemy chcieli dostać się przez SSH (zwany dalej klientem), zdalny komputer w sieci z publicznym adresem, z zainstalowanym serwerem SSH (zwany dalej serwerem). Dla celów testowych urządzeniem które nawiązywało połączenie był router z OpenWrt z połączeniem komórkowym, zdalny komputer zaś zwykłym serwerem z systemem Linux (Debian) z zainstalowanym OpenSSH.

Konto na serwerze

Zakładamy że posiadamy już konto na serwerze, dostęp do niego możliwy jest przy pomocy pary użytkownik/hasło. Odblokowany musi być dostęp od strony internetu, więc należy pamiętać o firewallu!

Zestawienie tunelu

adres_serwera - nazwa lub adres ip serwera z SSH dostępny w sieci
użytkownik - nazwa konta na serwera SSH
22 - numer portu SSH na komputerze klienta
1234 - numer portu na serwerze na którym będzie nasłuchiwał koniec tunelu


    # ssh -f -NT -R 1234:localhost:22 użytkownik@adres_serwera

Zapyta się o hasło, należy je podać. Jeżeli dane autoryzacyjne są poprawne, powinien zostać zestawiony tunel pomiędzy zdalnym routerem na porcie 1234 a lokalnym klientem na porcie 22. Aby to sprawdzić, wystarczy zalogować się do serwera a następnie połączyć się ssh z portem 1234:


    $ ssh -p 1234 root@127.0.0.1

Jeżeli uzyskamy dostęp do klienta to wszystko jest w porządku.

Wymieniamy klucze

Powyższe rozwiązanie jest prawidłowe, ale ma jeden problem - należy ręcznie podawać hasło. Aby uniknąć tego, można wygenerować odpowiedni klucz i łączyć się automatycznie.

Generowanie klucza

Generujemy (na kliencie) nasz sekretny klucz, dzięki któremu będzie możliwe połączenie:


    # dropbearkey -t rsa -f rsa_secret.txt 
Will output 1024 bit rsa secret key to 'rsa_secret.txt'
Generating key, this may take a while...
Public key portion is:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwDQ+T0iGoqbYDXd7cX32+tepbLo8l2LcHXYn06M7Nk+IkXHdGzjAR5eFLVzHsEp3T2Q9QQaaZ+LqlWZG5k0UOAyKk+TPX82B00NXnn8ejGty0cziZluQtLi6qDSQs7JwcwbsFiQlACBRegx4lT2wC8eaxeDzsNKyryJ4UJYpFgL8i8L root@OpenWrt
Fingerprint: md5 71:78:79:75:cd:cb:46:62:f8:cf:42:d1:31:30:9b:0d

Klucz został wygenerowany, interesuje nas natomiast jeszcze wyświetlony klucz publiczny, czyli część:


ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgwDQ+T0iGoqbYDXd7cX32+tepbLo8l2LcHXYn06M7Nk+IkXHdGzjAR5eFLVzHsEp3T2Q9QQaaZ+LqlWZG5k0UOAyKk+TPX82B00NXnn8ejGty0cziZluQtLi6qDSQs7JwcwbsFiQlACBRegx4lT2wC8eaxeDzsNKyryJ4UJYpFgL8i8L root@OpenWrt

Należy go dodać do pliku authorized_keys na koncie użytkownika na serwerze. Najprościej przesłać go przy pomocy ssh na zdalne konto:


    # dropbearkey  -y -f rsa_secret.txt | grep ssh > klucz_pub.txt
    # scp klucz_pub.txt użytkownik@adres_serwera:~/.ssh/.

Następnie logujemy się na konto użytkownik i dodajemy nasz klucz publiczny do pliku authorized_keys


    $ cd ~/.ssh
    $ cat klucz_pub.txt >> authorized_keys
    $ rm klucz_pub.txt

(lub bezpośrednio bez logowania podając odpowiednie polecenie wraz z ssh)

Test połączenia

Teraz już zdalny system powinien nas rozpoznawać, można więc sprawdzić zestawienie tunelu:


    # ssh -f -NT -R 1234:localhost:22 użytkownik@adres_serwera -i /root/rsa_secret.txt

Jeżeli nie zapytał się o hasło i automatycznie zestawił tunel - wszystko jest w porządku.

Automatyzacja

Jeżeli chcemy automatycznie zestawiać tunel należy dodać w/w polecenie do skryptów startowych, np. do /etc/rc.local. Jednakże jeżeli połączenie internetowe zostanie zerwane, tunel także zostanie przerwany. Lepszym rozwiązaniem jest więc wykorzystanie crona do zestawienia tunelu i sprawdzenia jego dostępności.
Tworzymy plik np. /bin/tunel.sh o następującej zawartości:


    #!/bin/sh
    T="ssh -f -NT -R 1234:localhost:22 użytkownik@adres_serwera -i /root/rsa_secret.txt"
    pgrep -f "$T" > /dev/null 2>&1 || $T

I dodajemy do crona wykonanie pliku /bin/tunel.sh np. co 5 min. Nie zapominamy o nadaniu praw wykonania do tego pliku:


    # chmod 755 /bin/tunel.sh

Uwagi końcowe

Do dostania się do komputera można użyć także Active Port Forwarder.
Sposób automatyzacji tworzenia tunelu zaczerpnięto z forum eko.one.pl.

Taką samą funkcjonalność uzyska się instalując pakiet sshtunnel. Jego plik konfiguracyjny znajduje się w /etc/config/sshtunnel, a sama konfiguracja odbywa się przez uci.

Od strony klienta nie ma potrzeby otwierania żadnego portu na firewallu. Od strony serwera oczywiście niezbędne jest otworzenie portu ssh (22).
Dodatkowo, jeżeli zestawiamy tunel do innego portu niż ssh (22), a kliencie jest dropbear to może konieczne okazać się dodanie opcji GatewayPorts. Dla OpenWrt wygląda to w następujący sposób:


    # uci set dropbear.@dropbear[0].GatewayPorts=1
    # uci commit dropbear
    # /etc/init.d/dropbear restart