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)
- usunięto wsparcie dla
CECHA
- dodano wsparcie dla
Ubuntu 24.04
- dodano wsparcie dla
openSUSE 15.6
- dodano wsparcie dla
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
iCentOS 7
(nieaktualny Python utrudnia testowanie z Ansible)
- usunięto nieaktualny kod
16.0.2
- INNE
- przywrócono zmianę w
.github/workflows/release.yml
- przywrócono zmianę w
16.0.1
- INNE
- zaktualizowano
.github/workflows/release.yml
- zaktualizowano
meta/main.yml
- zaktualizowano
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ślniefalse
. (wkład @shk3bq4d) - wprowadzono
wireguard_install_kernel_module
. Umożliwia pominięcie ładowania modułu jądrawireguard
. Domyślnietrue
(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
icpus
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 zansible-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
Installs Wireguard incl. systemd integration
ansible-galaxy install githubixx.ansible_role_wireguard