Najlepszy VPN (?) dla OpenWrt
Ostatnia zmiana: 2023-11-03 09:38

WireGuard zyskał popularność dzięki bardzo dobrej wydajności, małemu zapotrzebowaniu na zasoby oraz prostocie konfiguracji. W OpenWrt mamy od dawna przygotowane paczki, więc można wykorzystać je do zrobienia VPNa.
Mimo że ogólna koncepcja WireGuard zakłada połączenia peer-to-peer to nic nie stoi na przeszkodzie żeby utworzyć typową konfigurację Road Warrior - czyli "mobilny klient" podłączony do "serwera". Poradnik opisuje konfigurację "serwera" WireGuard na OpenWrt oraz konfigurację dwóch przykładowych klientów - jednego bazującego na OpenWrt, na Androida oraz ns Windows czy Linuksa. Ponieważ wykorzystany będzie router do instalacji "serwera" - wymagane jest aby miał on publiczny adres IP na wanie (lub przekierowane odpowiednie porty).
Poniższy poradnik przetestowano na OpenWrt w wydaniach od 18.06 do 23.05 i nie on wyczerpuje możliwości konfiguracyjnych WireGuard.

Serwer

Jako serwer zostanie wykorzystany router z OpenWrt, z publicznym adresem IP na interfejsie WAN.

Instalacja

Pakiety dostępne są standardowo w repozytorium, więc instalacja sprowadza się do wydania odpowiednich poleceń (poniższe polecenia wykonujemy na serwerze):


    # opkg update
    # opkg install kmod-wireguard wireguard-tools

Generowanie kluczy

W pierwszej kolejności należy wygenerować parę kluczy dla serwera, prywatny i publiczny:


    # cd /root
    # wg genkey > server.privkey
    # wg pubkey < server.privkey > server.pubkey

Klucz prywatny będzie wpisany do konfiguracji vpn, klucz publiczny niezbędny będzie do konfiguracji klienta. Można więc wykonać:


    # cat /root/server.pubkey

i zapamiętać go do późniejszego wykorzystania.

Następnie potrzebujemy osobnych kluczy dla każdego klienta. Może to zrobić na kliencie, można także zrobić na serwerze. Generuje się identycznymi poleceniami jak dla serwera:


    # cd /root
    # wg genkey > client1.privkey
    # wg pubkey < client1.privkey > client1.pubkey
    
    # wg genkey > client2.privkey
    # wg pubkey < client2.privkey > client2.pubkey

    # wg genkey > client3.privkey
    # wg pubkey < client3.privkey > client3.pubkey
    itd

Pliki z kluczami klienta będą potrzebne do konfiguracji zarówno na serwerze jak i na kliencie. Później nie będą wykorzystywane, bo ich zawartość zostanie wpisana w do plików konfiguracyjnych; same pliki mogą mogą zostać skasowane po konfiguracji.

Sieć

W konfiguracji WireGuarda dodaje się:
- jedną sekcję o nazwie np. "wg0" odnoszącą się do danego urządzenia
- jedną lub więcej sekcji o nazwach np. "wireguard_wg0", osobną dla każdego peera który ma się łączyć do tego urządzenia (lub to urządzenie ma się łączyć z nim).

Dodajemy więc interfejs do konfiguracji sieci:


    # uci set network.wg0=interface
    # uci set network.wg0.proto="wireguard"
    # uci set network.wg0.private_key="$(cat /root/server.privkey)"
    # uci set network.wg0.listen_port="55055"
    # uci add_list network.wg0.addresses="10.9.0.1/24"
    # uci commit network

Teraz powinniśmy dodać konfigurację peera czyli klienta. Robimy to osobno dla każdego klienta którego chcemy połączyć.


    # uci add network wireguard_wg0
    # uci set network.@wireguard_wg0[-1].public_key="tutaj klucz publiczny klienta" # np. do uzyskania przez cat /root/client1.pubkey
    # uci set network.@wireguard_wg0[-1].route_allowed_ips="1"
    # uci add_list network.@wireguard_wg0[-1].allowed_ips="10.9.0.2/32" # dla każdego klienta ma być inny adres IP
    # uci set network.@wireguard_wg0[-1].persistent_keepalive="25"
    # uci set network.@wireguard_wg0[-1].description='openwrt'
    # uci commit network

Każdy następny klient musi mieć inny swój własny klucz oraz adres IP, czy zmieniamy opcje public_key oraz allowed_ips np.


    # uci add network wireguard_wg0
    # uci set network.@wireguard_wg0[-1].public_key="tutaj klucz publiczny klienta" # np. do uzyskania przez cat /root/client2.pubkey
    # uci set network.@wireguard_wg0[-1].route_allowed_ips="1"
    # uci add_list network.@wireguard_wg0[-1].allowed_ips="10.9.0.3/32" # dla każdego klienta ma być inny adres IP
    # uci set network.@wireguard_wg0[-1].persistent_keepalive="25"
    # uci set network.@wireguard_wg0[-1].description='android'
    
    # uci add network wireguard_wg0
    # uci set network.@wireguard_wg0[-1].public_key="tutaj klucz publiczny klienta" # np. do uzyskania przez cat /root/client3.pubkey
    # uci set network.@wireguard_wg0[-1].route_allowed_ips="1"
    # uci add_list network.@wireguard_wg0[-1].allowed_ips="10.9.0.4/32" # dla każdego klienta ma być inny adres IP
    # uci set network.@wireguard_wg0[-1].persistent_keepalive="25"
    # uci set network.@wireguard_wg0[-1].description='windows'
    
    # uci commit network

Itd, powtarzamy w/w sekcję dla każdego klienta którego chcemy podłączyć zmieniając odpowiednio opcje public_key oraz allowed_ips.
Zostaje restart sieci:


    # /etc/init.d/network restart

Do VPNa będzie używana adresacja 10.9.0.0/24, serwer będzie miał adres 10.9.0.1 i nasłuchiwał będzie na porcie 55055, w większości przypadków nie powinno to kolidować z resztą naszej sieci. Adresacja sieci dla WireGuarda ma być inna (z innej klasy adresowej) niż sieć LAN w routerze. Nie należy dla WireGuarda nadawać takiej samej adresacji jaka jest na LAN.

Firewall

Zmieniamy konfigurację firewalla - otwieramy port na wanie (w tym przykładzie: 55055, musi być taki sam jak w konfiguracji WireGuard) oraz zezwalamy na ruch pomiędzy WireGuard a lan/wan:


    # uci add firewall rule
    # uci set firewall.@rule[-1].src="wan"
    # uci set firewall.@rule[-1].target="ACCEPT"
    # uci set firewall.@rule[-1].proto="udp"
    # uci set firewall.@rule[-1].dest_port="55055"
    # uci set firewall.@rule[-1].name="wireguard"
    # uci add firewall zone
    # uci set firewall.@zone[-1].name='wg'
    # 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].masq='1'
    # uci set firewall.@zone[-1].network='wg0'
    # uci add firewall forwarding
    # uci set firewall.@forwarding[-1].src='wg'
    # uci set firewall.@forwarding[-1].dest='wan'
    # uci add firewall forwarding
    # uci set firewall.@forwarding[-1].src='wan'
    # uci set firewall.@forwarding[-1].dest='wg'
    # uci add firewall forwarding
    # uci set firewall.@forwarding[-1].src='wg'
    # uci set firewall.@forwarding[-1].dest='lan'
    # uci add firewall forwarding
    # uci set firewall.@forwarding[-1].src='lan'
    # uci set firewall.@forwarding[-1].dest='wg'
    # uci commit firewall
    # /etc/init.d/firewall restart

Klienty (peery)

Klient nie musi mieć publicznego adresu IP na wanie, może być za innym routerem (NATem), może mieć dowolne połączenie z internetem np. komórkowe.

OpenWrt

Podobnie jak serwer, klient wymaga wygenerowania pary kluczy. Można to wykonać na serwerze jak pokazano w tym poradniku, można także wygenerować je osobno. Nie ma to znaczenia, ale ostatecznie musimy dysponować kluczem prywatnym i publicznym dla urządzenia oraz kluczem publicznym serwera do którego będziemy się łączyć.
Konfiguracja klienta przebiega w bardzo podobny sposób (przykładowy klient będzie miał adres 10.9.0.2, adres IP musi się zgadzać z tym co jest wpisane w konfiguracji serwera w odpowiedniej; poniższe polecenia wykonujemy na kliencie):


    # opkg update
    # opkg install kmod-wireguard wireguard-tools
    
    # uci set network.wg0=interface
    # uci set network.wg0.proto="wireguard"
    # uci set network.wg0.private_key="--tutaj klucz prywatny klienta"
    # uci add_list network.wg0.addresses="10.9.0.2/32"

oraz dodajemy konfigurację peera, czyli w tym przypadku serwera:


    # uci add network wireguard_wg0
    # uci set network.@wireguard_wg0[-1].public_key="tutaj klucz publiczny serwera"
    # uci set network.@wireguard_wg0[-1].route_allowed_ips="1"
    # uci add_list network.@wireguard_wg0[-1].allowed_ips="0.0.0.0/0"
    # uci set network.@wireguard_wg0[-1].endpoint_host="adres ip serwera"
    # uci set network.@wireguard_wg0[-1].endpoint_port="55055"
    # uci set network.@wireguard_wg0[-1].persistent_keepalive="25"
    # uci set network.@wireguard_wg0[-1].description="serwer"
    # uci commit network
    # /etc/init.d/network restart

Gdzie:
- tutaj klucz prywatny klienta - zawartość klucza prywatnego klienta. Jest to zawartość pliku z kluczem prywatnym klienta wygenerowanego podczas robienia serwera, do uzyskania np. przez wykonanie polecenia cat /root/client1.pubkey na serwerze.
- tutaj klucz publiczny serwera - zawartość klucza publicznego serwera który był skopiowany podczas robienia konfiguracji serwera, do uzyskania np. przez wykonanie polecenia cat /root/server.pubkey na serwerze.
- adres ip serwera - adres IP serwera na interfejsie WAN (musi to być publiczne IP) lub jego nazwa domenowa (może być Dynamic DNS)
- 55055 - port nasłuchu serwera który został podany w jego konfiguracji i który został otworzony na wanie serwera
- 0.0.0.0/0 - cały ruch z klienta będzie przechodził przez tunel WireGuard. Jeżeli chcemy tylko dostęp do serwera to podajemy 10.9.0.1/32, jeżeli tylko do jego lanu to dodajemy dodatkowo 192.168.1.1/24 itd. Można podać klika podsieci jednocześnie. Wprowadzenie 0.0.0.0/0 spowoduje że zostanie zastąpiona trasa domyślna na kliencie, aby tego uniknąć stosuje się zapis typu "0.0.0.0/1" oraz "128.0.0.0/1".

Konfiguracje klienta na serwerze już dodaliśmy wcześniej podczas konfiguracji, jeżeli nie była dodana to trzeba dodać konfiguracje na serwerze (poniższe polecenia wykonujemy na serwerze, tylko jeżeli wcześniej tego nie zrobiliśmy):


    # uci add network wireguard_wg0
    # uci set network.@wireguard_wg0[-1].public_key="tutaj klucz publiczny klienta client1"
    # uci set network.@wireguard_wg0[-1].route_allowed_ips="1"
    # uci add_list network.@wireguard_wg0[-1].allowed_ips="10.9.0.2/32"
    # uci set network.@wireguard_wg0[-1].persistent_keepalive="25"
    # uci set network.@wireguard_wg0[-1].description="openwrt"
    # uci commit network
    # /etc/init.d/network restart


Bardzo ważne jest żeby nie pomylić kluczy - w sekcji "wg0" jest zawsze zawartość klucza prywatnego danego urządzenia (*.privkey), w sekcjach "wireagurd_wg0" są klucze publiczne peerów (*.pubkey).

Po restarcie powinna być możliwość pingowania serwera i klienta (adresów 10.9.0.1 i 10.9.0.2); cały ruch klienta powinien być przepuszczony przez tunel WireGuard i powinien mieć on dostęp do internetu.

Android

Instalujemy ze sklepu Google aplikację WireGuard, następnie uruchamiamy ją i konfigurujemy (nazwy opcji mogą się różnić w zależności od wersji klienta):
- klikamy na "+"
- wybieramy "Create from scratch"
- albo wpisujmy klucz prywatny wygenerowany na serwerze
- albo klikamy na przycisk "GENERATE", klikamy na "Public Key" - kopiujemy to do schowka i wysyłamy sobie mejlem lub zapamiętujemy w inny sposób
- uzupełniamy pola:
    * "Name" - dowolna nazwa połączenia
    * "Addresses" - podajemy adres IP klienta w notacji "10.9.0.3/32"
    * "DNS servers" - ustawiamy np. 8.8.8.8 lub podajemy adres IP routera (10.9.0.1)
- klikamy "ADD PEER"
    * "Public Key" - tu podajemy klucz publiczny serwera, skopiowany/zapamiętany podczas konfiguracji serwera
    * "Allowed IPs" - podajemy "0.0.0.0/0"
    * "Endpoint" - adres IP serwera i port lub nazwa domenowa serwera/ddns i port, w notacji "ADRESIP:PORT"
    * "Persistent keepalive" - podajemy np. 25
Zapisujmy konfigurację.

Następnie dodajemy klienta (peera) do serwera (poniższe polecenia wykonujemy na serwerze, tylko jeżeli wcześniej nie został dodany):


    # uci add network wireguard_wg0
    # uci set network.@wireguard_wg0[-1].public_key="tutaj klucz publiczny klienta"
    # uci set network.@wireguard_wg0[-1].route_allowed_ips="1"
    # uci add_list network.@wireguard_wg0[-1].allowed_ips="10.9.0.3/32"
    # uci set network.@wireguard_wg0[-1].persistent_keepalive="25"
    # uci set network.@wireguard_wg0[-1].description="android"
    # uci commit network
    # /etc/init.d/network restart

Po uruchomieniu VPNa w androidzie sprawdzamy czy mamy połączenie z internetem i z jakim adresem wychodzimy w świat.

Klient Windows lub Linuks

Dla innych systemów można utworzyć odpowiedni plik konfiguracyjny dla WireGuarda:


[Interface]
PrivateKey = tutaj klucz prywatny klienta
Address = 10.9.0.4/32

[Peer]
PublicKey = tutaj klucz publiczny serwera
AllowedIPs = 0.0.0.0/0
Endpoint = adres ip serwera:55055

Oczywiście uzupełniając brakujące dane. Oczywiście, podobnie jak w poprzednich przypadkach, dodajemy odpowiednią sekcję peera z konfiguracji serwera jeżeli wcześniej tego nie zrobiliśmy.

Zakończenie

Stan podłączonych peerów (bez znaczenia czy na kliencie czy serwerze) można podejrzeć poleceniem


    # wg

Każdy klient musi mieć unikalny adres IP więc przy dodawanie następnego klienta/peera odpowiednio zmieniamy adresy.
WireGuard można także wykorzystać do łączenia wielu sieci z innymi sieciami. Przykładowe konfiguracje można znaleźć na forum witryny.
Sam pakiet z OpenWrt zawiera także prosty skrypt monitorujący połączenie WireGuard (klienta). Aby go używać wystarczy dodać do crona odpowiednie polecenie:


    # echo '* * * * * /usr/bin/wireguard_watchdog' >> /etc/crontabs/root
    # /etc/init.d/cron restart

Scenariusze

Tunel WireGuard zestawiony jako dodatkowe łącze i jeden port LAN związany bezpośrednio z wireguard. Podłączając się do tego portu klient wychodzi w świat przez vpn'a, podłączając się do innego portu - przez wan.
Rozwiązanie: https://eko.one.pl/forum/viewtopic.php?pid=286636#p286636

Wykorzystanie zewnętrznego serwera VPS do dostępu do routera przez WireGuarda.
Rozwiązanie: https://eko.one.pl/forum/viewtopic.php?pid=291616#p291616

Zmiana dnsów na routerze po zestawieniu tunelu Wireguard.
Rozwiązanie: https://eko.one.pl/forum/viewtopic.php?pid=291895#p291895