githubixx.ansible_role_wireguard

ansible-role-wireguard

Ta rola Ansible jest używana w moim cyklu blogowym Kubernetes w prosty sposób z Ansible, ale można ją używać samodzielnie. Używam WireGuard oraz tej roli Ansible do skonfigurowania w pełni połączonego VPN między wszystkimi węzłami mojego małego klastra Kubernetes.

Ogólnie rzecz biorąc, WireGuard to tunel sieciowy (VPN) dla IPv4 i IPv6, który korzysta z protokołu UDP. Jeśli potrzebujesz więcej informacji o WireGuard, możesz znaleźć dobre wprowadzenie tutaj: Instalacja WireGuard, nowoczesnego VPN.

Linux

Ta rola powinna działać z:

  • Ubuntu 20.04 (Focal Fossa)
  • Ubuntu 22.04 (Jammy Jellyfish)
  • Ubuntu 24.04 (Noble Numbat)
  • Archlinux
  • Debian 11 (Bullseye)
  • Debian 12 (Bookworm)
  • Fedora 39
  • AlmaLinux 9
  • Rocky Linux 9
  • openSUSE Leap 15.5
  • openSUSE Leap 15.6
  • Oracle Linux 9

Najlepsze starania

  • AlmaLinux 8
  • Rocky Linux 8
  • elementary OS 6
  • CentOS 7 (koniec życia od końca czerwca 2024)

Testy Molecule są dostępne (sprawdź poniżej). Powinno również działać z Raspbian Buster, ale dla tego nie ma dostępnego testu. MacOS (patrz poniżej) powinien też działać częściowo, ale to tylko najlepsze starania.

MacOS

Podczas gdy ten playbook konfiguruje, włącza i uruchamia usługę systemd na Linuxie w sposób, który nie wymaga dodatkowych działań, na MacOS instaluje wymagane pakiety i generuje odpowiedni plik wg0.conf, który następnie umieszczany jest w określonym wireguard_remote_directory (domyślnie /opt/local/etc/wireguard). Aby uruchomić VPN, musisz:

sudo wg-quick up wg0

aby dezaktywować:

sudo wg-quick down wg0

lub możesz zainstalować oficjalną aplikację i zaimportować plik wg0.conf.

Wersje

Oznaczam każdą wersję i staram się trzymać semantycznego wersjonowania. Jeśli chcesz użyć tej roli, polecam sprawdzenie najnowszego oznaczenia. Główna gałąź to w zasadzie rozwój, podczas gdy oznaczenia wskazują stabilne wydania. Ogólnie staram się również utrzymać główną wersję w dobrym stanie.

Wymagania

Domyślnie port 51820 (protokół UDP) powinien być dostępny z zewnątrz. Możesz jednak dostosować ten port, zmieniając zmienną wireguard_port. Musi również być włączone przekazywanie IP, np. za pomocą echo 1 > /proc/sys/net/ipv4/ip_forward. Zdecydowałem się nie wdrażać tej funkcji w tej roli Ansible. Moim zdaniem powinno to być obsługiwane gdzie indziej. Możesz użyć mojej ansible-role-harden-linux. Oprócz zmiany wpisów sysctl (które musisz włączyć, aby zezwolić na przekazywanie IP) zarządza również ustawieniami zapory ogniowej i innymi rzeczami. Niemniej jednak haki PreUp, PreDown, PostUp i PostDown mogą być dobrym miejscem do zrobienia rzeczy związanych z siecią przed uruchomieniem lub zatrzymaniem interfejsu WireGuard.

Dziennik zmian

Historia zmian:

Zobacz pełen CHANGELOG.md

Ostatnie zmiany:

17.0.0

  • ZMIEŃ

    • usunięto wsparcie dla openSUSE 15.4 (osiągnęło koniec życia)
  • CECHA

    • dodano wsparcie dla Ubuntu 24.04
    • dodano wsparcie dla openSUSE 15.6
  • MOLECULE

    • usunięto nieaktualny kod Proxmox
    • zastąpiono pudełko Vagrant rockylinux/9 bento/rockylinux-9
    • użyto ansible.builtin.package dla AlmaLinux
    • usunięto AlmaLinux 8, Rocky Linux 8 i CentOS 7 (nieaktualny Python utrudnia testowanie z Ansible)

16.0.2

  • INNE
    • przywrócono zmianę w .github/workflows/release.yml

16.0.1

  • INNE
    • zaktualizowano .github/workflows/release.yml
    • zaktualizowano meta/main.yml

16.0.0

  • ZMIEŃ

    • usunięto wsparcie dla Fedora 37/38 (osiągnęło koniec życia)
  • CECHA

    • dodano wsparcie dla Fedora 39
    • wprowadzono zmienną wireguard_conf_backup do śledzenia zmian w konfiguracji. Domyślnie false. (wkład @shk3bq4d)
    • wprowadzono wireguard_install_kernel_module. Umożliwia pominięcie ładowania modułu jądra wireguard. Domyślnie true (co było poprzednim zachowaniem). (wkład @gregorydlogan)
  • Molecule

    • użyto różnych adresów IP
    • użyto generic pudełek Vagrant dla Rocky Linux
    • użyto pudełek Vagrant alvistack dla Ubuntu
    • użyto oficjalnego pudełka Vagrant Rocky Linux 9
    • użyto oficjalnych pudełek Vagrant AlmaLinux
    • przeniesiono parametry memory i cpus do pudełek Vagrant

Instalacja

  • Pobierz bezpośrednio z Github (zmień katalog na rolę Ansible przed klonowaniem): git clone https://github.com/githubixx/ansible-role-wireguard.git githubixx.ansible_role_wireguard

  • Za pomocą polecenia ansible-galaxy i pobierz bezpośrednio z Ansible Galaxy: ansible-galaxy role install githubixx.ansible_role_wireguard

  • Stwórz plik requirements.yml z następującą zawartością (pobierze rolę z Github) i zainstaluj z ansible-galaxy role install -r requirements.yml:

---
roles:
  - name: githubixx.ansible_role_wireguard
    src: https://github.com/githubixx/ansible-role-wireguard.git
    version: 17.0.0

Zmienne roli

Te zmienne można zmieniać w group_vars/, np.:

# Katalog do przechowywania konfiguracji WireGuard na zdalnych hostach
wireguard_remote_directory: "/etc/wireguard"              # Na Linuxie
# wireguard_remote_directory: "/opt/local/etc/wireguard"  # Na MacOS

# Domyślny port, na którym WireGuard będzie nasłuchiwać, jeśli nie podano inaczej.
wireguard_port: "51820"

# Domyślna nazwa interfejsu, której WireGuard powinien używać, jeśli nie podano inaczej.
wireguard_interface: "wg0"

# Domyślny właściciel pliku wg.conf
wireguard_conf_owner: root

# Domyślna grupa pliku wg.conf
wireguard_conf_group: "{{ 'root' if not ansible_os_family == 'Darwin' else 'wheel' }}"

# Domyślny tryb pliku wg.conf
wireguard_conf_mode: 0600

# Czy jakakolwiek zmiana w pliku wg.conf powinna być zabezpieczona
wireguard_conf_backup: false

# Domyślny stan usługi wireguard
wireguard_service_enabled: "yes"
wireguard_service_state: "started"

# Domyślnie używana jest "wg syncconf", aby zastosować ustawienia interfejsu WireGuard, jeśli
# uległy one zmianie. Starsze narzędzia WireGuard nie oferują tej opcji. W takim
# wypadku jako fallback interfejs WireGuard zostanie zrestartowany. Powoduje to
# krótkie przerwy w połączeniach sieciowych.
#
# Tak więc, choć "false" jest domyślną wartością, rola ustala, czy opcja "syncconf"
# narzędzia "wg" jest dostępna i jeśli nie, przechodzi do "true"
# (co oznacza, że interfejs zostanie zrestartowany, ponieważ jest to jedyna możliwa opcja
# w takim przypadku).
#
# Możliwe opcje:
# - false (domyślnie)
# - true
#
# Obie opcje mają swoje zalety i wady. Domyślna opcja "false" (nie restartuj interfejsu)
# - nie trzeba restartować interfejsu WireGuard, aby zastosować zmiany
# - nie powoduje krótkiej przerwy w połączeniach VPN podczas zastosowania zmian
# - może spowodować, że trasy sieciowe nie zostaną poprawnie przeładowane
#
# Ustawienie wartości opcji na "true" spowoduje
# - restart interfejsu WireGuard, jak sugeruje nazwa, w przypadku zmian
# - spowoduje krótką przerwę w połączeniach VPN podczas zastosowania zmian
# - upewni się, że trasy sieciowe są poprawnie przeładowane
#
# Tak więc w zależności od twojej konfiguracji, która opcja działa najlepiej. Jeśli
# nie masz złożonego routingu, który często się zmienia lub w ogóle
# użycie "false" tutaj powinno być wystarczające. Np. jeśli chcesz tylko
# podłączyć kilka serwerów przez VPN i normalnie tak zostaje.
#
# Jeśli masz bardziej dynamiczną konfigurację routingu, ustawienie tego na "true" może być
# najbezpieczniejszym rozwiązaniem. Również, jeśli chcesz uniknąć możliwości
# stworzenia trudnych do wykrycia skutków ubocznych, warto wziąć ten wybór pod uwagę.
wireguard_interface_restart: false

# Zazwyczaj rola automatycznie tworzy klucz prywatny za pierwszym razem,
# jeśli nie ma jeszcze konfiguracji WireGuard. Jednak ta opcja pozwala
# podać własny klucz prywatny WireGuard, jeśli to naprawdę konieczne. Jako że jest to
# oczywiście bardzo wrażliwa wartość, warto rozważyć użycie narzędzia takiego jak Ansible Vault
# do jej przechowywania w zaszyfrowanej formie.
# wireguard_private_key:

# Ustaw na "false", jeśli pamięć podręczna pakietów nie powinna być aktualizowana
# (istotne tylko, jeśli odpowiedni menedżer pakietów obsługuje tę opcję)
wireguard_update_cache: "true"

# Zazwyczaj rola instaluje i aktywuje moduł jądra wireguard, gdzie
# to stosowne. W niektórych przypadkach może być niemożliwe załadowanie modułów jądra,
# na przykład w przypadku nieuprzywilejowanych gości LXC. Jeśli ustawisz to na false,
# musisz upewnić się, że moduł wireguard jest dostępny w jądrze!
wireguard_install_kernel_module: true

Istnieje również kilka specyficznych dla dystrybucji Linux ustawień:

#######################################
# Ustawienia istotne tylko dla:
# - Ubuntu
# - elementary OS
#######################################

# DEPRECATED: Proszę używać "wireguard_update_cache" zamiast.
# Ustaw na "false", jeśli pamięć podręczna pakietów nie powinna być aktualizowana.
wireguard_ubuntu_update_cache: "{{ wireguard_update_cache }}"

# Ustaw czas ważności pamięci podręcznej pakietów
wireguard_ubuntu_cache_valid_time: "3600"

#######################################
# Ustawienia istotne tylko dla CentOS 7
#######################################

# Ustaw wireguard_centos7_installation_method na "kernel-plus"
# aby użyć jądra kernel-plus, które zawiera wbudowany,
# podpisany moduł WireGuard.
#
# Domyślna opcja "standard" użyje standardowego jądra i
# modułu ELRepo dla WireGuard.
wireguard_centos7_installation_method: "standard"

# Ponownie uruchom hosta, jeśli to konieczne, jeśli używane jest jądro "kernel-plus"
wireguard_centos7_kernel_plus_reboot: true

# Domyślna liczba sekund, aby poczekać, aż maszyna zrestartuje się i zareaguje
# jeśli używane jest "kernel-plus". Jest to istotne tylko, jeśli
# "wireguard_centos7_kernel_plus_reboot" ustawiono na "true".
wireguard_centos7_kernel_plus_reboot_timeout: "600"

# Ponownie uruchom hosta, jeśli to konieczne, jeśli używane jest standardowe jądro
wireguard_centos7_standard_reboot: true

# Domyślna liczba sekund, aby poczekać, aż maszyna zrestartuje się i zareaguje
# jeśli używane jest standardowe jądro. Jest to istotne tylko, jeśli
# "wireguard_centos7_standard_reboot" ustawiono na "true".
wireguard_centos7_standard_reboot_timeout: "600"

#########################################
# Ustawienia istotne tylko dla RockyLinux 8
#########################################

# Ustaw wireguard_rockylinux8_installation_method na "dkms"
# aby zbudować moduł WireGuard ze źródła, przy użyciu wireguard-dkms.
# Jest to wymagane, jeśli używasz własnego jądra i/lub Twoja architektura
# nie jest x86_64.
#
# Domyślna opcja "standard" zainstaluje moduł jądra
# z kmod-wireguard z ELRepo.
wireguard_rockylinux8_installation_method: "standard"

Każdy host w host_vars/ powinien skonfigurować co najmniej jeden adres za pomocą wireguard_address lub wireguard_addresses. wireguard_address może zawierać tylko jeden adres IPv4, dlatego zaleca się użycie zmiennej wireguard_addresses, która może zawierać tablicę zarówno adresów IPv4, jak i IPv6.

wireguard_addresses:
  - "10.8.0.101/24"

Oczywiście wszystkie IP powinny znajdować się w tej samej podsieci, jak /24, który widzimy w powyższym przykładzie. Jeśli wireguard_allowed_ips nie jest ustawione, to domyślne wartości to IP określone w wireguard_address i wireguard_addresses bez CIDR, ale zamiast tego z /32 (IPv4) lub /128 (IPv6), co zasadniczo jest trasą hosta (zobacz templates/wg.conf.j2). Zobaczmy ten przykład i załóżmy, że nie ustawisz wireguard_allowed_ips jawnie:

[Interface]
Address = 10.8.0.2/24
PrivateKey = ....
ListenPort = 51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.101/32
Endpoint = controller01.p.domain.tld:51820

To część konfiguracji WireGuard z mojego komputera. Ma adres IP VPN 10.8.0.2 i mamy podsieć /24, w której znajdują się wszystkie moje hosty WireGuard. Możesz również zobaczyć, że mamy tutaj punkt dostępu z końcówką controller01.p.domain.tld:51820. Kiedy wireguard_allowed_ips nie jest jawnie ustawione, szablon Ansible doda wpis AllowedIPs z IP tego hosta plus /32 lub /128. W WireGuard zasadniczo określa to trasowanie. Konfiguracja powyżej mówi: Na moim komputerze z IP 10.8.0.2 chcę wysłać cały ruch do 10.8.0.101/32 do punktu dostępu controller01.p.domain.tld:51820. Teraz załóżmy, że ustawiamy wireguard_allowed_ips: "0.0.0.0/0". Wtedy wynikowa konfiguracja wygląda tak.

[Interface]
Address = 10.8.0.2/24
PrivateKey = ....
ListenPort = 51820

[Peer]
PublicKey = ....
AllowedIPs = 0.0.0.0/0
Endpoint = controller01.p.domain.tld:51820

Teraz to zasadniczo to samo co powyżej, ALE teraz konfiguracja mówi: Chcę routować KAŻDY ruch pochodzący z mojego komputera do punktu dostępu controller01.p.domain.tld:51820. Oczywiście zależy od tego, czy ten punkt dostępu potrafi obsługiwać ten ruch, a to już od Ciebie zależy, jak skonfigurujesz trasowanie punktu dostępu ;-)

Możesz określić dodatkowe opcjonalne ustawienia (nie mają domyślnych wartości i nie będą ustawione, jeśli nie są podane poza wireguard_allowed_ips, jak już wspomniano) również dla hostów w host_vars/ (lub w pliku inwentarza Ansible, jeśli wolisz). Wartości dla poniższych zmiennych są jedynie przykładami i nie mają domyślnych ustawień (po więcej informacji i przykładów zobacz wg-quick.8):

wireguard_allowed_ips: ""
wireguard_endpoint: "host1.domain.tld"
wireguard_persistent_keepalive: "30"
wireguard_dns: "1.1.1.1"
wireguard_fwmark: "1234"
wireguard_mtu: "1492"
wireguard_table: "5000"
wireguard_preup:
  - ...
wireguard_predown:
  - ...
wireguard_postup:
  - ...
wireguard_postdown:
  - ...
wireguard_save_config: "true"

wireguard_(preup|predown|postup|postdown) są określone jako listy. Oto dwa przykłady:

wireguard_postup:
  - iptables -t nat -A POSTROUTING -o ens12 -j MASQUERADE
  - iptables -A FORWARD -i %i -j ACCEPT
  - iptables -A FORWARD -o %i -j ACCEPT
wireguard_preup:
  - echo 1 > /proc/sys/net/ipv4/ip_forward
  - ufw allow 51820/udp

Polecenia są wykonywane w kolejności, jak opisano w wg-quick.8.

Dodatkowo można dodać "niezarządzane" punkty dostępu. Te punkty nie są obsługiwane przez Ansible i nie są częścią grupy Ansible vpn, np.:

wireguard_unmanaged_peers:
  client.example.com:
    public_key: 5zsSBeZZ8P9pQaaJvY9RbELQulcwC5VBXaZ93egzOlI=
    # preshared_key: ... np. z ansible-vault?
    allowed_ips: 10.0.0.3/32
    endpoint: client.example.com:51820
    persistent_keepalive: 0

Jeden z wireguard_address (przestarzałe) lub wireguard_addresses (zalecane) jest wymagany, jak już wspomniano. Jest to adresy interfejsu nazwanego, który jest określony przez zmienną wireguard_interface (domyślnie wg0). Oczywiście każdy host potrzebuje co najmniej jeden unikalny adres IP VPN. Jeśli nie ustawisz wireguard_endpoint, playbook użyje nazwy hosta określonej w grupie hostów vpn (nazwa hosta inwentarza Ansible). Jeśli ustawisz wireguard_endpoint na "" (pusty ciąg), ten punkt nie będzie miał punktu dostępu. Oznacza to, że ten host może uzyskiwać dostęp tylko do hostów, które mają wireguard_endpoint. To jest przydatne dla klientów, którzy nie udostępniają żadnych usług w VPN i chcą tylko uzyskiwać dostęp do usług na innych hostach. Więc jeśli zdefiniujesz tylko jeden host z wireguard_endpoint ustawionym, a wszystkie inne hosty będą miały wireguard_endpoint ustawione na "" (pusty ciąg), to oznacza, że masz tylko klientów oprócz jednego, który w tym przypadku jest serwerem WireGuard. Trzecią możliwością jest ustawienie wireguard_endpoint na jakąś nazwę hosta. Np. jeśli masz różne nazwy hostów dla prywatnego i publicznego DNS tego hosta i potrzebujesz różnych wpisów DNS w takim przypadku ustawienie wireguard_endpoint staje się przydatne. Weźmy na przykład powyższy adres IP: wireguard_address: "10.8.0.101". To jest adres prywatny i stworzyłem wpis DNS dla tego prywatnego adresu jak host01.i.domain.tld (i dla wewnętrznego w tym przypadku). Dla publicznego adresu utworzyłem wpis DNS jak host01.p.domain.tld (p dla publicznego). wireguard_endpoint musi być interfejsem, przez który inni członkowie grupy vpn mogą się łączyć. Więc w tym przypadku ustawiłbym wireguard_endpoint na host01.p.domain.tld, ponieważ WireGuard normalnie musi być w stanie połączyć się z publicznym IP innych hostów.

Oto mały przykład, jak używam playbooka: Używam WireGuard do skonfigurowania w pełni połączonego VPN (każdy host może bezpośrednio łączyć się z każdym innym hostem) i uruchamiam mój klaster Kubernetes (K8s) w Hetzner Cloud (ale powinieneś być w stanie używać dowolnego dostawcy, którego chcesz). Tak więc ważne komponenty, takie jak kontroler K8s i węzły robocze (w tym aplikacje), komunikują się tylko przez szyfrowany VPN WireGuard. Również (jak już wspomniano) mam dwóch klientów. Obydwoje mają zainstalowane kubectl i mają dostęp do wewnętrznego serwera API Kubernetes, korzystając z VPN WireGuard. Jeden z dwóch klientów również wystawia punkt dostępu WireGuard, ponieważ serwer pocztowy Postfix w chmurze i moja wewnętrzna poczta muszą mieć możliwość komunikacji. Myślę, że to może być nietypowy przypadek użycia dla WireGuard :D Ale pokazuje to, co jest możliwe. Pozwól, że wyjaśnię konfigurację, co może pomóc Ci w wykorzystaniu tej roli Ansible.

Po pierwsze, oto część mojego pliku inwentarza Ansible:

[vpn]
controller0[1:3].i.domain.tld
worker0[1:2].i.domain.tld
server.at.home.i.domain.tld
workstation.i.domain.tld

[k8s_controller]
controller0[1:3].i.domain.tld

[k8s_worker]
worker0[1:2].i.domain.tld

Jak widzisz, mam tutaj trzy grupy: vpn (wszystkie hosty, na których zainstalowane zostanie WireGuard), k8s_controller (węzły kontrolera Kubernetes) i k8s_worker (węzły robocze Kubernetes). i w nazwie domeny oznacza wewnętrzny. Wszystkie wpisy DNS i.domain.tld mają rekord A, który wskazuje na adres IP WireGuard, który wkrótce zdefiniujemy dla każdego hosta, np.: controller01.i.domain.tld. IN A 10.8.0.101. Powodem tego jest to, że wszystkie komponenty Kubernetes wiążą się i nasłuchują tylko na interfejsie WireGuard w mojej konfiguracji. A ponieważ potrzebuję tych wewnętrznych adresów IP dla wszystkich moich komponentów Kubernetes, określam wpisy DNS w moim pliku inwentarza Ansible. Dzięki temu jestem w stanie łatwo korzystać z nazw hostów inwentarza Ansible oraz zmiennych w playbookach i szablonach.

Dla węzłów kontrolera Kubernetes określiłem następujące zmienne hosta:

Plik inwentarza Ansible: host_vars/controller01.i.domain.tld

---
wireguard_addresses:
  - "10.8.0.101/24"
wireguard_endpoint: "controller01.p.domain.tld"
ansible_host: "controller01.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Plik inwentarza Ansible: host_vars/controller02.i.domain.tld:

---
wireguard_addresses:
  - "10.8.0.102/24"
wireguard_endpoint: "controller02.p.domain.tld"
ansible_host: "controller02.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Plik inwentarza Ansible: host_vars/controller03.i.domain.tld:

---
wireguard_addresses:
  - "10.8.0.103/24"
wireguard_endpoint: "controller03.p.domain.tld"
ansible_host: "controller03.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Określiłem tutaj ansible_python_interpreter dla każdego węzła, ponieważ węzły kontrolerów korzystają z Ubuntu 18.04, które domyślnie ma zainstalowany Python 3. ansible_host jest ustawione na publiczny DNS tego hosta. Ansible użyje tej nazwy do połączenia się z hostem za pośrednictwem SSH. Tę samą wartość używam również dla wireguard_endpoint, ponieważ z tego samego powodu. Punkty dostępu WireGuard muszą łączyć się z innymi punktami dostępu przez publiczny adres IP (cóż, przynajmniej przez adres IP, z którym hosty WireGuard mogą się łączyć - może to być również adres prywatny, jeśli działa dla Ciebie). Adresy określone w wireguard_address lub wireguard_addresses muszą być oczywiście unikalne dla każdego hosta.

Dla węzłów roboczych Kubernetes określiłem następujące zmienne:

Plik inwentarza Ansible: host_vars/worker01.i.domain.tld

---
wireguard_addresses:
  - "10.8.0.111/24"
wireguard_endpoint: "worker01.p.domain.tld"
wireguard_persistent_keepalive: "30"
ansible_host: "worker01.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Plik inwentarza Ansible: host_vars/worker02.i.domain.tld:

---
wireguard_addresses:
  - "10.8.0.112/24"
wireguard_endpoint: "worker02.p.domain.tld"
wireguard_persistent_keepalive: "30"
ansible_host: "worker02.p.domain.tld"
ansible_python_interpreter: /usr/bin/python3

Jak widzisz, zmienne są w zasadzie takie same jak mają węzły kontrolera z jedną wyjątkiem: wireguard_persistent_keepalive: "30". Moje węzły robocze (w Hetzner Cloud) i mój serwer wewnętrzny (mój serwer w domu) są połączone, ponieważ mam uruchomiony Postfix na moich węzłach w chmurze, a zewnętrzny serwer Postfix przekazuje odbierane maile do mojego serwera wewnętrznego (i odwrotnie). Potrzebowałem ustawienia keepalive, ponieważ od czasu do czasu węzły chmurowe i wewnętrzny serwer traciły połączenie, a to ustawienie rozwiązało problem. Powodem tego jest oczywiście to, że mój wewnętrzny serwer jest za NATem, a NAT/zapora muszą utrzymać ważność mapowania NAT/zapory (NAT i utrzymanie mapy zapory).

Dla mojego wewnętrznego serwera w domu (połączonego przez router DSL do internetu) mamy tę konfigurację:

---
wireguard_addresses:
  - "10.8.0.1/24"
wireguard_endpoint: "server.at.home.p.domain.tld"
wireguard_persistent_keepalive: "30"
ansible_host: 192.168.2.254
ansible_port: 22

Domyślnie demon SSH nasłuchuje na innym porcie niż 22 na wszystkich moich publicznych węzłach, ale wewnętrznie używam portu 22 i dlatego muszę ustawić ansible_port: 22 tutaj. Również ansible_host to oczywiście wewnętrzny adres IP dla tego hosta. Wartość wireguard_endpoint to dynamiczny wpis DNS. Ponieważ mój adres IP w domu nie jest statyczny, muszę co minutę uruchamiać skrypt na moim serwerze domowym, który sprawdza, czy adres IP się zmienił, a jeśli tak, to aktualizuje mój rekord DNS. Używam funkcji DynHost OVH do tego, ale możesz używać dowolnego dostawcy DynDNS, jakiego chcesz. Również przekazuję ruch przychodzący na porcie 51820/UDP do mojego wewnętrznego serwera, aby umożliwić przychodzący ruch WireGuard. Adresy IP z wireguard_address i wireguard_addresses muszą być oczywiście częścią naszej podsieci WireGuard.

A na koniec dla mojego komputera stacjonarnego (na którym uruchamiam wszystkie polecenia ansible-playbook):

wireguard_addresses:
  - "10.8.0.2/24"
wireguard_endpoint: ""
ansible_connection: local
ansible_become: false

Jak widzisz, wireguard_endpoint: "" jest tutaj pustym ciągiem. Oznacza to, że rola Ansible nie ustawi punktu dostępu dla mojego komputera. Ponieważ nie ma potrzeby, aby inne hosty łączyły się z moim komputerem, nie ma sensu definiować punktu dostępu. Tak więc w tym przypadku mogę uzyskiwać dostęp do wszystkich hostów zdefiniowanych w grupie Ansible vpn z mojego komputera, ale nie odwrotnie. Zatem wynikowa konfiguracja WireGuard dla mojego komputera wygląda tak:

[Interface]
Address = 10.8.0.2/24
PrivateKey = ....
ListenPort = 51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.101/32
Endpoint = controller01.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.102/32
Endpoint = controller02.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.103/32
Endpoint = controller03.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.111/32
PersistentKeepalive = 30
Endpoint = worker01.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.112/32
PersistentKeepalive = 30
Endpoint = worker02.p.domain.tld:51820

[Peer]
PublicKey = ....
AllowedIPs = 10.8.0.1/32
PersistentKeepalive = 30
Endpoint = server.at.home.p.domain.tld:51820

Inne pliki konfiguracyjne WireGuard (wg0.conf domyślnie) wyglądają podobnie, ale oczywiście [Interface] zawiera konfigurację tego konkretnego hosta, a wpisy [Peer] zawierają konfigurację innych hostów.

Przykłady playbooków

- hosts: vpn
  roles:
    - githubixx.ansible_role_wireguard
  hosts: vpn
  roles:
    -
      role: githubixx.ansible_role_wireguard
      tags: role-wireguard

Przykładowy inwentarz używający dwóch różnych interfejsów WireGuard na hoście "multi"

To skomplikowany przykład używający formatu inwentarza yaml:

vpn1:
  hosts:
    multi:
      wireguard_addresses:
        - "10.9.0.1/32"
      wireguard_allowed_ips: "10.9.0.1/32, 192.168.2.0/24"
      wireguard_endpoint: multi.example.com
    nated:
      wireguard_addresses:
        - "10.9.0.2/32"
      wireguard_allowed_ips: "10.9.0.2/32, 192.168.3.0/24"
      wireguard_persistent_keepalive: 15
      wireguard_endpoint: nated.example.com
      wireguard_postup:
        - iptables -t nat -A POSTROUTING -o ens12 -j MASQUERADE
        - iptables -A FORWARD -i %i -j ACCEPT
        - iptables -A FORWARD -o %i -j ACCEPT
      wireguard_postdown:
        - iptables -t nat -D POSTROUTING -o ens12 -j MASQUERADE
        - iptables -D FORWARD -i %i -j ACCEPT
        - iptables -D FORWARD -o %i -j ACCEPT

vpn2:
  hosts:
    # Użyj innej nazwy i zdefiniuj ansible_host, aby uniknąć mieszania zmiennych bez
    # potrzeby prefiksowania zmiennych nazwą interfejsu.
    multi-wg1:
      ansible_host: multi
      wireguard_interface: wg1
      # przy użyciu wielu interfejsów na jednym hoście, musimy użyć różnych portów
      wireguard_port: 51821
      wireguard_addresses:
        - "10.9.1.1/32"
      wireguard_endpoint: multi.example.com
    another:
      wireguard_address:
        - "10.9.1.2/32"
      wireguard_endpoint: another.example.com

Przykładowe playbooki dla powyższego przykładu:

- hosts: vpn1
  roles:
    - githubixx.ansible_role_wireguard
- hosts: vpn2
  roles:
    - githubixx.ansible_role_wireguard

Testowanie

Ta rola ma mały zestaw testowy, który jest tworzony za pomocą Molecule, libvirt (vagrant-libvirt) i QEMU/KVM. Proszę zobaczyć mój post na blogu Testowanie ról Ansible z Molecule, libvirt (vagrant-libvirt) i QEMU/KVM, aby dowiedzieć się jak skonfigurować. Konfiguracja testowa jest tutaj.

Następnie można wykonać molekułę:

molecule converge

To skonfiguruje dość wiele maszyn wirtualnych (VM) z różnymi obsługiwanymi systemami operacyjnymi Linux. Aby przeprowadzić kilka testów:

molecule verify

Aby dokonać oczyszczenia, uruchom

molecule destroy

Istnieje też mała konfiguracja Molecule, która naśladuje centralny serwer WireGuard z kilkoma klientami:

molecule converge -s single-server

Licencja

GNU General Public License v3.0 lub później

Informacje o autorze

http://www.tauceti.blog

O projekcie

Installs Wireguard incl. systemd integration

Zainstaluj
ansible-galaxy install githubixx.ansible_role_wireguard
Licencja
Unknown
Pobrania
239.1k
Właściciel
Senior System Engineer - Python, Go, Cloud, Kubernetes, Commodore, Retro, 80's ;-)