Instalacja i konfiguracja sieci VPN na OpenWrt
Ostatnia zmiana: 2017-07-11 21:36

W poprzednim poradniku została zaprezentowana konfiguracja OpenVPN z wykorzystaniem hasła współdzielonego. Jest dość prosta i wykorzystuje tryb bridge (TAP), jednakże wielu użytkowników potrzebuje trybu routowania (TUN). W tym poradniku przedstawiono właśnie taką konfigurację z wykorzystaniem certyfikatów.
Aby uruchomić serwer OpenVPN potrzebujemy router z publicznym adresem IP (dostępnym bezpośrednio z internetu) lub potrzebujemy przekierowany choć jeden z portów na nasz router. Z tego też względu uruchomimy ale nie dostaniemy się do serwera stojącego za natem lub z zablokowanym ruchem wejściowym (np. dla sieci komórkowych - bez wykupienia odpowiedniej usługi u operatora nie uzyskamy dostępu do routera). Adres IP może być stały, można też skorzystać z adresu dynamicznego połączonego z dowolną usługą DDNS.
Konfigurację przetestowano na wydaniu OpenWrt Barrier Breaker 14.07.

Instalacja

W OpenWrt/LEDE istnieje kilka różnych wersji OpenVPN związanych z zastosowaną biblioteką kryptograficzną (w zależności od wydania: openssl, polarssl, mbedtls lub nossl). Wybieramy jedną z nich:


    # opkg update
    # opkg install openvpn-openssl openvpn-easy-rsa

Generowanie certyfikatów

OpenVPN można skonfigurować na kilka różnych sposobów, korzystając z certyfikatów, haseł współdzielonych, autoryzacji przez bazę danych itp. W tym przypadku wykorzystany zostanie jeden z najpopularniejszych sposobów - certyfikatów, osobnych dla każdego podłączonego klienta. Przed konfigurację samego OpenVPN należy takie certyfikaty wygenerować, a robi się to wywołując odpowiednie polecenia.


    # build-ca

Zostanie zadane nam kilka pytań o dane do głównego klucza. Przykładowe dane które wprowadziłem:


    Country Name (2 letter code) [US]:PL
    State or Province Name (full name) [CA]:Masovian
    Locality Name (eg, city) [SanFrancisco]:Warsaw
    Organization Name (eg, company) [Fort-Funston]:Home
    Organizational Unit Name (eg, section) [MyOrganizationalUnit]:Home
    Common Name (eg, your name or your server's hostname) [Fort-Funston CA]:OpenWrt Server
    Name [EasyRSA]:Router
    Email Address [me@myhost.mydomain]:cezary@eko.one.pl

Następnie:


    # build-dh

Generowanie trwa bardzo długo. Ostatecznie generujemy właściwy certyfikat dla serwera:


    # build-key-server serwer

Znów nastąpi pytanie o dane, podajemy je:


    Country Name (2 letter code) [US]:PL
    State or Province Name (full name) [CA]:Masovian
    Locality Name (eg, city) [SanFrancisco]:Warsaw
    Organization Name (eg, company) [Fort-Funston]:Home
    Organizational Unit Name (eg, section) [MyOrganizationalUnit]:Home
    Common Name (eg, your name or your server's hostname) [serwer]:OpenWrt Server
    Name [EasyRSA]:Router
    Email Address [me@myhost.mydomain]:cezary@eko.one.pl

    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    Using configuration from /etc/easy-rsa/openssl-1.0.0.cnf
    Check that the request matches the signature
    Signature ok
    The Subject's Distinguished Name is as follows
    countryName           :PRINTABLE:'PL'
    stateOrProvinceName   :PRINTABLE:'Masovian'
    localityName          :PRINTABLE:'Warsaw'
    organizationName      :PRINTABLE:'Home'
    organizationalUnitName:PRINTABLE:'Home'
    commonName            :PRINTABLE:'OpenWrt Server'
    name                  :PRINTABLE:'Router'
    emailAddress          :IA5STRING:'cezary@eko.one.pl'
    Certificate is to be certified until May 13 08:02:50 2025 GMT (3650 days)
    Sign the certificate? [y/n]:y


    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated

Generujemy także certyfikaty dla poszczególnych klientów:


    # build-key-pkcs12 malgosia

Znów pojawią się pytania o te same dane:


    Country Name (2 letter code) [US]:PL
    State or Province Name (full name) [CA]:Masovian
    Locality Name (eg, city) [SanFrancisco]:Warsaw
    Organization Name (eg, company) [Fort-Funston]:Home
    Organizational Unit Name (eg, section) [MyOrganizationalUnit]:Home
    Common Name (eg, your name or your server's hostname) [malgosia]:malgosia
    Name [EasyRSA]:Router
    Email Address [me@myhost.mydomain]:malgosia@eko.one.pl

    Please enter the following 'extra' attributes
    to be sent with your certificate request
    A challenge password []:
    An optional company name []:
    Using configuration from /etc/easy-rsa/openssl-1.0.0.cnf
    Check that the request matches the signature
    Signature ok
    The Subject's Distinguished Name is as follows
    countryName           :PRINTABLE:'PL'
    stateOrProvinceName   :PRINTABLE:'Masovian'
    localityName          :PRINTABLE:'Warsaw'
    organizationName      :PRINTABLE:'Home'
    organizationalUnitName:PRINTABLE:'Home'
    commonName            :PRINTABLE:'malgosia'
    name                  :PRINTABLE:'Router'
    emailAddress          :IA5STRING:'malgosia@eko.one.pl'
    Certificate is to be certified until May 13 08:05:54 2025 GMT (3650 days)
    Sign the certificate? [y/n]:y


    1 out of 1 certificate requests certified, commit? [y/n]y
    Write out database with 1 new entries
    Data Base Updated
    Enter Export Password:
    Verifying - Enter Export Password:

Przy udzielaniu odpowiedzi podajemy podobne dane, jednakże pamiętajmy o polu Common Name - podajemy tam inny opis. Nie podajemy żadnych haseł, potwierdzamy chęć podpisania certyfikatu i jego zatwierdzenia.
Analogicznie generujemy certyfikaty dla innych klientów:


    # build-key-pkcs12 jacek
    # build-key-pkcs12 telefon
    # build-key-pkcs12 tablet
    itd

Certyfikaty pojawią się katalogu /etc/easy-rsa/keys pod nazwami jakie podaliśmy (ca.*, serwer.*, malgosia.*, jacek.*, telefon.*, tablet.* itd). Certyfikaty serwera kopiujemy do katalogu OpenVPN:

 
    # cp /etc/easy-rsa/keys/ca.crt /etc/easy-rsa/keys/serwer.* /etc/easy-rsa/keys/dh2048.pem /etc/openvpn

zaś certyfikaty dla klientów zostaną wykorzystane w późniejszej ich konfiguracji. Jeżeli z jakiegoś powodu chcemy pozbyć się certyfikatów żeby np. wygenerować nowe, można posłużyć się poleceniem:


    # clean-all

Konfiguracja serwera

network

Dodajemy nową sekcję do sieci:


    # uci set network.vpn=interface
    # uci set network.vpn.ifname=tun0
    # uci set network.vpn.proto=none
    # uci commit

firewall

Tworzymy odpowiednią strefę i zezwalamy na transmisję vpn<->wan


    # uci add firewall zone
    # uci set firewall.@zone[-1].name=vpn
    # uci set firewall.@zone[-1].input=ACCEPT
    # uci set firewall.@zone[-1].forward=ACCEPT
    # uci set firewall.@zone[-1].output=ACCEPT
    # uci set firewall.@zone[-1].network=vpn
    # uci add firewall forwarding
    # uci set firewall.@forwarding[-1].src='vpn'
    # uci set firewall.@forwarding[-1].dest='wan'

oraz na otworzenie odpowiedniego portu na wanie:


    # uci add firewall rule
    # uci set firewall.@rule[-1].name=OpenVPN
    # uci set firewall.@rule[-1].target=ACCEPT
    # uci set firewall.@rule[-1].src=wan
    # uci set firewall.@rule[-1].proto=udp
    # uci set firewall.@rule[-1].dest_port=1194
    # uci commit firewall

Standardowym portem wykorzystywanym przez OpenVPN jest 1194/udp. Jednakże niektóre routery pośredniczące mogą mieć problem przy udp, należy więc użyć protokołu tcp. Oczywiście nic nie stoi na przeszkodzie aby użyć portu 53/udp czy 443/tcp, a nawet niestandardowego np. 30192. Należy tylko pamiętać aby taki sam port wskazać w samej konfiguracji OpenVPN.
Po konfiguracji firewalla i sieci restartujemy router:


    # reboot

OpenVPN

Sam demon serwera można skonfigurować albo standardowo umieszczając wszystkie jego polecenia w jednym pliku tekstowym albo wykorzystując do tego celu uci. Wykorzystujemy sposób zgodny z OpenWrt i dodajmy nową sekcję konfiguracyjną (tu: o nazwie home):


    # uci set openvpn.home=openvpn
    # uci set openvpn.home.enabled=1
    # uci set openvpn.home.dev=tun
    # uci set openvpn.home.port=1194
    # uci set openvpn.home.proto=udp
    # uci set openvpn.home.log=/tmp/openvpn.log
    # uci set openvpn.home.verb=3
    # uci set openvpn.home.ca=/etc/openvpn/ca.crt
    # uci set openvpn.home.cert=/etc/openvpn/serwer.crt
    # uci set openvpn.home.key=/etc/openvpn/serwer.key
    # uci set openvpn.home.server='10.8.0.0 255.255.255.0'
    # uci set openvpn.home.dh=/etc/openvpn/dh2048.pem
    # uci commit openvpn

Należy pamiętać o:
- nazewnictwie plików kluczy serwera (w tym przykładzie: serwer.crt / serwer.key - pod taką nazwą zostały wygenerowane dla serwera)
- odpowiednim porcie który otworzyliśmy na firewallu (w tym przykładzie: 1194)
- odpowiednim protokole na który otworzyliśmy port na firewallu (w tym przykładzie: udp)
Uruchamiamy serwer:


    # /etc/init.d/openvpn enable
    # /etc/init.d/openvpn start

Konfiguracja klienta

Klient OpenVPN może być za natem, za prywatnym adresem. Nie ma potrzeby otwierania portów na firewallu, dowolnego innego przekierowania portów, można użyć modemu komórkowego czy podłączyć się do publicznego hotspota. Jedyne wymaganie to oczywiście dostęp do internetu.

OpenWrt

Posługujemy się podobną konfiguracją (ale na kliencie):


    # opkg update
    # opkg install openvpn-openssl

Potrzebujemy także wygenerowanych wcześniej certyfikatów; należy je skopiować do routera klienckiego przez scp, przenieść na pendrive, ściągnąć z www/ftp itp. Muszą znaleźć się na kliencie np. w katalogu /etc/openvpn. W tym przykładzie wykorzystujemy pliki: ca.crt, malgosia.key i malgosia.crt.


    # uci set openvpn.malgosia=openvpn
    # uci set openvpn.malgosia.enabled=1
    # uci set openvpn.malgosia.dev=tun
    # uci set openvpn.malgosia.proto=udp
    # uci set openvpn.malgosia.log=/tmp/openvpn.log                
    # uci set openvpn.malgosia.verb=3
    # uci set openvpn.malgosia.ca=/etc/openvpn/ca.crt
    # uci set openvpn.malgosia.cert=/etc/openvpn/malgosia.crt
    # uci set openvpn.malgosia.key=/etc/openvpn/malgosia.key
    # uci set openvpn.malgosia.client=1
    # uci set openvpn.malgosia.remote_cert_tls=server
    # uci set openvpn.malgosia.remote="SERWER_IP 1194"
    # uci commit openvpn

Istotnie sprawy:
- SERWER_IP zamieniamy albo na adres IP naszego serwera albo na jego nazwę domenową
- port (tutaj: 1194) ustawiamy zgodnie z konfiguracją serwera
- protokół (tutaj: udp) ustawiamy zgodnie z konfiguracją serwera

Uruchamiamy:


    # /etc/init.d/openvpn enable
    # /etc/init.d/openvpn start

Jeżeli wszystko jest dobrze, w pliku /tmp/openvpn.log powinna być informacja o nawiązaniu połączenia. Aby przekonać się czy to działa - można wykonać np. ssh root@10.8.0.1 - powinniśmy dostać się do serwera.

Inni klienci

Jeżeli nie konfigurujemy OpenWrt tylko inne urządzenie (zwykły Linux, Windows czy nawet Androida), można posłużyć się zwykłym plikiem tekstowym zwierającym konfigurację. Dla w/w odpowiednikiem jest:


    client
    ca /etc/openvpn/ca.crt
    cert /etc/openvpn/malgosia.crt
    dev tun
    key /etc/openvpn/malgosia.key
    log /tmp/openvpn.log
    proto udp
    remote SERWER_IP 1194
    remote-cert-tls server
    verb 3

Konfigurację przeprowadzamy zgodnie z ideologią danego systemu, pamiętając o zapewnieniu odpowiednich praw np. do ustawienia tablic routingu. Z tego też powodu w systemie Windows klient OpenVPN powinien być uruchomiony na prawach administratora. Ścieżki do certyfikatów należy odpowiednio zmienić, stosownie do danego systemu operacyjnego i ich położenia.

Rozwiązywanie problemów

Czas

Kluczowa sprawa - połączenie może nie zostać nawiązane, jeżeli nie zgadza się czas na serwerze i kliencie, a tym samym certyfikat jest nieważny lub jeszcze nie jest ważny. Oba systemy muszą mieć ustawiony poprawny czas.

Routing

Zwykłe route -n powinno pokazać trasę do serwera OpenVPN. W logach (grep "route add" /tmp/openvpn.log) powinna być informacja o dodaniu do tablicy routingu nowej ścieżki do serwera. traceroute 10.8.0.1 powinno wykazać trasę przez tunel vpn, traceroute 8.8.8.8 powinno dać trasę do googli przez domyślny interfejs. Nie powinno być problemu z dostępem do internetu.

Interfejs

Po wykonaniu ifconfig powinien pojawić się interfejs np. tun0 i mieć adres przydzielony z serwera (np. 10.8.0.6).

Tuning konfiguracji

W/w konfiguracja umożliwia dostęp tylko do serwera. Można ją zmodyfikować, aby zmienić funkcjonalność tunelu.

Dostęp do sieci lokalnej za serwerem

Na serwerze OpenVPN definiujemy jaką trasę ma wysłać do klienta, aby klient mógł się odwołać do sieci lokalnej serwera:


    # uci add_list openvpn.home.push='route 192.168.1.0 255.255.255.0'
    # uci commit openvpn

Dodatkowo należy jeszcze dodać na serwerze do strefy VPN opcję masq 1 (w pliku /etc/config/firewall):


    config zone
        option name 'vpn'
        option input 'ACCEPT'
        option forward 'ACCEPT'
        option output 'ACCEPT'
        option network 'vpn'
        option masq '1'

Oraz dodajemy możliwość forwardu pakietów pomiędzy vpn a lan


    # uci add firewall forwarding
    # uci set firewall.@forwarding[-1].src='vpn'
    # uci set firewall.@forwarding[-1].dest='lan'
    # uci commit firewall

Zapisujmy całość i restartujemy router lub usługi:


    # /etc/init.d/openvpn restart
    # /etc/init.d/firewall reload

Pamiętajmy że może to sprawić niezły problem jeżeli klient ma drugą sieć (np. lan) o takiej samej adresacji. Należy wtedy zmienić zakres adresów serwera lub klienta. Należy też pamiętać, aby urządzenie w sieci lokalnej za serwerem miało poprawnie ustawiony gateway, inaczej możemy nie móc ani go pingować ani dostać się do jego zasobów.

Przekierowanie całego ruchu klientów przez tunel vpn

Do tej pory wyjście na zewnątrz w świat było zrealizowane przez łącze klienta. Jeżeli chcemy aby cały ruch szedł przez tunel vpn (co jest przydatne np. przy korzystaniu z publicznych hotspotów), należy odpowiednio poinstruować serwer, żeby zmienił klientowi trasę domyślną. Znów dodajemy na serwerze:


    # uci add_list openvpn.home.push='redirect-gateway def1'
    # uci commit openvpn
    # /etc/init.d/openvpn restart

I restartujemy także OpenVPN na kliencie. Jeżeli spojrzymy na tabelę routingu na kliencie to okaże się, że została dodana nowa trasa domyślna na przez tunel. To samo powinny pokazać logi klienta OpenVPN:


    # grep 0.0.0.0 /tmp/openvpn.log 
    Sat May 16 11:11:17 2015 /sbin/route add -net 0.0.0.0 netmask 128.0.0.0 gw 10.8.0.5

Dostęp do urządzenia klienckiego

To jest właściwość samego tunelu - można zrobić z klienta połączenie do serwera i przy pomocy telnetu/ssh dostać się do serwera czy jego zasobów lokalnych; można także z serwera zrobić telnet/ssh i dostać się do zasobów klienta. Połączenie jest "dwustronne" i o ile ruch nie został ograniczony specjalnie np. firewallem to obie strony powinny mieć dostęp do siebie.

Przykłady

Dostęp do kamery za klientem

Scenariusz: mamy kamerę IP nasłuchującą na porcie 8080. Podłączamy ją do routera który pełni rolę klienta OpenVPN, łączącego się przez łącze 3G/LTE (komórkowe) z jakimś serwerem OpenVPN dostępnym w internecie. Chcemy mieć dostęp do obrazu kamery odwołując się bezpośrednio do adresu IP serwera i portu 8080.
Rozwiązanie: wystarczy odpowiednio przekierować porty i na kliencie i na serwerze OpenVPN.

Założenia:
- tworzymy konfigurację podaną powyżej
- adres klienta OpenVPN: 10.8.0.6
- adres LAN za klientem OpenVPN: 192.168.2.0/24
- adres kamery: 192.168.2.2, ma ustawiony bramę domyślną na 192.168.2.1
- port kamery: 8080
- interfejs wan serwera OpenVPN: eth1

Konfiguracja klienta OpenVPN (do wpisania w /etc/firewall.user)


    iptables -I FORWARD -i tun0 -p tcp -d 192.168.2.2 --dport 8080 -j ACCEPT
    iptables -t nat -I PREROUTING -i tun0 -p tcp --dport 8080 -j DNAT --to-destination 192.168.2.2:8080

Dzięki temu wszystko co pojawi się na vpn na porcie 8080 ma zostać przekierowane do kamery. Będąc zalogowanym do serwera OpenVPN można bezpośrednio odwołać się do adresu 10.8.0.6:8080 (adresu klienta) żeby zobaczyć dane z kamery.

Konfiguracja serwera OpenVPN (do wpisania w /etc/firewall.user)


    iptables -I FORWARD -i eth1 -p tcp -d 10.8.0.6 --dport 8080 -j ACCEPT
    iptables -t nat -I PREROUTING -i eth1 -p tcp --dport 8080 -j DNAT --to-destination 10.8.0.6:8080

Wszystko co pojawi się na wanie serwera OpenVPN na porcie 8080 ma być przekierowanie na adres wewnętrzny klienta na port 8080 (a ten zrobi przekierowanie na kamerę).