OpenWrt - konfiguracja OpenVPN w trybie TUN

OpenWrt - konfiguracja OpenVPN w trybie TUN
Aby uruchomić serwer OpenVPN potrzebujemy router z publicznym adresem IP (dostępnym bezpośrednio z internetu) lub przekierowany jeden z portów na nasz router. Z tego też względu uruchomimy ale nie dostaniemy się do serwera stojącym 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 dynamicznego i wykorzystać dowolny DDNS do podłączenia się do serwera.
Konfigurację przetestowano na wydaniu Barrier Breaker 14.07
Instalacja
W obecnym repozytorium (BB i trunk) istnieje kilka różnych wersji OpenVPN związanych z zastosowaną biblioteką (openssl, polarssl 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. W końcu 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 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 podajmy ż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 wykorzystane zostaną 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ć 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 albo restartujemy router albo wykonujemy restart usług:

# /etc/init.d/network reload
# /etc/init.d/firewall reload

OpenVPN
Sam demon serwera można skonfigurować albo standardowo umieszczając wszystkie jego polecenia w jednym pliku tekstowym albo wykorzystując uci do tego celu. 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 więc je skopiować do routera klienckiego przez scp, przynieść na pendrive, ściągnąć z www/ftp itd. 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 podstawiamy albo adres IP naszego serwera albo 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 tcp
remote SERWER_IP 1194
remote-cert-tls server
verb 3

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ę domyślną, 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
    Tak wykonana konfiguracja umożliwia dostęp tylko do serwera. Można ją zmodyfikować, alby 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 set 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:

    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 porty 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 set 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:

# 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ę serwera czy jego zasobów lokalnych, można także z serwera zrobić telnet/ssh i dostać się do zasobów klienta.
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 serwerem OpenVPN. Chcemy mieć dostęp do obrazu kamery odwołując się bezpośrednio do IP serwera i portu 8080.
Rozwiązanie: wystarczy odpowiednio przekierować porty i na kliencie i na serwerze OpenVPN.
Założenie:

  • 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 ma być przekierowanie na adres wewnętrzny klienta (a ten zrobi przekierowanie na kamerę).

Żródło: http://eko.one.pl/?p=openwrt-openvpntun