Jak skonfigurować klienta VPN na routerze z OpenWRT

Spis treści

Ostatnio pisałem trochę o konfiguracji serwera VPN na Debianie oraz podłączaniu do niego różnych linux'owych klientów, w tym też smartfonów wyposażonych w system Android. O ile konfiguracja pojedynczego klienta OpenVPN nie jest jakoś szczególnie trudna, to mając w swojej sieci domowej kilka urządzeń zdolnych łączyć się z internetem zarówno przewodowo jak i bezprzewodowo, to dostosowanie konfiguracji na każdym z tych sprzętów może być ździebko problematyczne. To co łączy te wszystkie urządzenia w naszym domu, to router WiFi. Zwykle każdy komputer, nawet ten najmniejszy, łączy się z takim routerem w celu nawiązania połączenia ze światem. Dlatego też zamiast konfigurować osobno wszystkie te urządzenia elektroniczne, możemy skonfigurować sobie router w taki sposób, by cały zebrany ruch z sieci lokalnej przesłał do serwera VPN. Standardowej klasy routery nie wspierają połączeń VPN i by taki mechanizm zaimplementować potrzebne nam będzie alternatywne firmware pokroju LEDE/OpenWRT. W tym artykule postaramy się skonfigurować połączenie VPN dla sieci domowej w oparciu o router Archer C2600 od TP-LINK, który ma wgrany najnowszy snapshot LEDE Chaos Calmer (r2392).

Niezbędne oprogramowanie na potrzeby VPN

Nie da się ukryć, że oprogramowanie, które umożliwi nam nawiązanie połączenia VPN, trochę waży. Trzeba także brać pod uwagę fakt szyfrowania całego ruchu, co też obciąży mocno procesor routera. Te dwie rzeczy nie stanowią aż takiego problemu w przypadku Archer'a C2600, bo on ma flash 32 MiB i dwa rdzenie taktowane 1,2 GHz:

openvpn-vpn-lede-openwrt-router-tp-link

Na innych routerach, które mają mniejszy flash i słabszy procesor, OpenVPN może sprawić drobne problemy, zwłaszcza przy mocniejszych szyfrach. O ile w przypadku wolnego miejsca na flash możemy coś poradzić, np przeprowadzić extroot, o tyle w przypadku procesora zbytnio nic nie zrobimy i taki dodatkowy narzut (overhead) odbije się spowolnieniem transmisji danych.

Z tego co zauważyłem w LEDE mamy z grubsza trzy pakiety, które mogą nam posłużyć do skonfigurowania klienta VPN, są to: openvpn-nossl , openvpn-openssl oraz openvpn-polarssl . Ten pierwszy pakiet możemy sobie darować, bo nie zapewnia on wsparcia dla szyfrowanego połączenia z VPN. Musimy zdecydować się na jeden z dwóch pozostałych pakietów. Generalnie rzecz biorąc PolarSSL ma niby zastąpić OpenSSL ale znowu OpenVPN ma pewne ograniczenia w przypadku wykorzystywania PolarSSL. Dlatego też zainstalujemy sobie openvpn-openssl , z tym, że nasz router musi mieć minimum 1 MiB wolnego miejsca na flash'u. Logujemy się zatem na router i wydajemy w terminalu poniższe polecenia:

# opkg update
# opkg install openvpn-openssl

Konfiguracja klienta VPN na LEDE/OpenWRT

Z pakietem openvpn-openssl został dostarczony skrypt startowy zlokalizowany w /etc/init.d/openvpn i jeśli chcemy, aby klient VPN łączył się automatycznie z serwerem po starcie routera, to naturalnie przydałoby się dodać ten skrypt do autostartu w poniższy sposób:

# /etc/init.d/openvpn enable

Konfiguracja dla demona openvpn jest przechowywana w pliku /etc/config/openvpn i musimy ją sobie dostosować w oparciu o konfigurację serwera VPN, z którym zamierzamy się połączyć. Ten plik konfiguracyjny jest dość rozbudowany i ma około 400 linijek. Większość z nich to komentarze.

Plik /etc/config/openvpn jest podzielony na trzy sekcje. Pierwsza z nich dotyczy konfiguracji klienta VPN za pomocą zewnętrznego pliku. Druga dotyczy konfiguracji serwera VPN na routerze (nas to zbytnio nie interesuje). Trzecia sekcja zaś umożliwia skonfigurowanie klienta VPN za pomocą interfejsu UCI.

Konfiguracja OpenVPN w zewnętrznym pliku

W przypadku, gdy skonfigurowaliśmy sobie połączenie z serwerem VPN na komputerze, to powinniśmy dysponować stosownym plikiem konfiguracyjnym, który możemy wgrać na router. Następnie w pliku /etc/config/openvpn musimy ustawić jedynie poniższe parametry:

...
config openvpn custom_config
    option enabled 1
    option config /etc/openvpn/morfitronik.conf
...

W pliku /etc/openvpn/morfitronik.conf umieszczamy konfigurację dla klienta OpenVPN:

client
dev tun
proto udp
remote 11.22.33.44 1194
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
cipher AES-256-CBC
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384
auth SHA512
keysize 256
tls-version-min 1.2
comp-lzo
verb 3
auth-nocache

remote-cert-tls server
verify-x509-name "morfitronik-server-vpn" name

key-direction 1

<ca>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</ca>
<cert>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</cert>
<key>
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
</key>
<tls-auth>
-----BEGIN OpenVPN Static key V1-----
....
-----END OpenVPN Static key V1-----
</tls-auth>

Po wyjaśnienie użytych tutaj opcji odsyłam do wpisu podlinkowanego we wstępie.

Konfiguracja OpenVPN przez UCI

Alternatywną metodą konfiguracji klienta OpenVPN na LEDE/OpenWRT jest skorzystanie z interfejsu UCI. W pliku /etc/config/openvpn na samym dole mamy odpowiednią sekcję. Włączamy ją przestawiając poniższy parametr:

...
config openvpn sample_client
    option enabled 1
...

Dalej musimy uwzględnić wszystkie opcje, które zwykle podaje się w pliku konfiguracyjnym OpenVPN, z tym, że musimy je poprzedzić słówkiem option . Poniżej przykład:

...
option client 1
option dev tun
option proto udp
list remote "11.22.33.44 1194"
option resolv_retry infinite
option nobind 1
option persist_key 1
option persist_tun 1
option user nobody
option ca /etc/openvpn/certs/morfitronik-ca.crt
option cert /etc/openvpn/certs/morfitronik-client-vpn-router-c2600.crt
option key /etc/openvpn/certs/morfitronik-client-vpn-router-c2600.key
option ns_cert_type server
option tls_auth "/etc/openvpn/certs/morfitronik-ta.key 1"
option cipher AES-256-CBC
option tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384
option auth SHA512
option keysize 256
option tls-version-min 1.2
option remote-cert-tls
option verify-x509-name "morfitronik-server-vpn name"
option comp_lzo yes
option verb 4

Problem z UCI jest taki, że klucze/certyfikaty klienta i serwera trzeba niestety umieszczać w osobnych plikach.

Certyfikaty klienckie

Ja jestem zwolennikiem uwierzytelniania użytkowników za pomocą certyfikatów klienckich. Dlatego też mam w taki sposób skonfigurowany swój serwer VPN. Bez przedstawienia takiego certyfikatu, żaden klient nie będzie w stanie zestawić połączenia. Opis jak wygenerować takie certyfikaty w oparciu o easy-rsa został opisany osobno. Tutaj warto nadmienić, że w LEDE/OpenWRT mamy dostępny pakiet openvpn-easy-rsa , którym możemy się posłużyć przy generowaniu certyfikatów. Niemniej jednak, to rozwiązanie nie jest zbytnio zalecane ze względu na niewielką moc obliczeniową takiego przeciętnego routera WiFi, przez cały proces będzie trwał kilka godzin.

Konfiguracja firewall'a na potrzeby OpenVPN

W zasadzie bez znaczenia jest sposób, który sobie wybierzemy w celu dostarczenia konfiguracji dla demona OpenVPN. Jeśli w tej chwili byśmy uruchomili usługę, to router będzie w stanie przesłać wszystkie swoje dane bezpośrednio do serwera VPN. Problem jednak jest w tym, że klienci w sieci LAN za routerem nie mają połączenia z internetem. Możemy co prawda połączyć się z routerem ale nie mamy wyjścia na świat. Problem tkwi w konfiguracji zapory. Musimy zatem skonfigurować sobie forwarding dla nowych interfejsów i włączyć im również NAT. W tym celu trzeba poddać edycji dwa pliki i dodać do nich poniższą zawartość.

Plik /etc/config/network :

config interface 'vpn'
    option ifname 'tun0'
    option proto 'none'

Plik /etc/config/firewall :

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

config forwarding
    option src              'lan'
    option dest             'vpn'

Zapisujemy i resetujemy router. I to w zasadzie cała konfiguracja jeśli chodzi o przesyłanie ruchu ze wszystkich urządzeń w sieci domowej WiFi do serwera VPN. Jeśli zaś chodzi o ewentualne przecieki DNS, to zawsze możemy skonfigurować sobie szyfrowany DNS w oparciu o dnscrypt-proxy również na routerze.

Test połączenia z serwerem VPN

W zasadzie połączenie powinno działać OOTB po zresetowaniu routera. Jeśli jednak nie mamy pewności do tego czy cały mechanizm został poprawnie skonfigurowany, to naturalnie możemy zajrzeć w log ( logread ) i poszukać wpisów zaczynających się od openvpn . Jeśli nie znajdziemy żadnych błędów i będzie w logu figurować Initialization Sequence Completed , to oznacza to, że połączenie z serwerem VPN zostało pomyślnie ustawione. Jeśli zaś mamy w logu również PUSH_REPLY,redirect-gateway def1 , to cały ruch z routera wędruje do serwera VPN w formie szyfrowanej. Dla pewności można także podejrzeć regułki na zaporze ( iptables -nvL ) i poszukać interfejsu tun0 . Jeśli pakiety są zliczane, to ruch jest zarządzany przez OpenVPN. No i oczywiście możemy podejrzeć tablicę routingu via ip route show , gdzie obecność tras 0.0.0.0/1 oraz 128.0.0.0/1 oznacza, że żaden pakiet wysyłany do internetu nie leci poza szyfrowanym tunelem.

Mikhail Morfikov avatar
Mikhail Morfikov
Po ponad 10 latach spędzonych z różnej maści linux'ami (Debian/Ubuntu, OpenWRT, Android) mogę śmiało powiedzieć, że nie ma rzeczy niemożliwych i problemów, których nie da się rozwiązać. Jedną umiejętność, którą ludzki umysł musi posiąść, by wybrnąć nawet z tej najbardziej nieprzyjemniej sytuacji, to zdolność logicznego rozumowania.