209 lines
12 KiB
Markdown
209 lines
12 KiB
Markdown
# Ansible Freifunk MWU
|
|
|
|
Wir, die Freifunk MWU Community, nutzen Ansible um unsere Freifunk Server aufzusetzen und zu konfigurieren. In
|
|
diesem Repository verwalten wir unsere Ansible Roles und Playbooks.
|
|
|
|
Ein Server muss minimal vorbereitet sein, bevor dieser per Ansible z.B. zu einem Freifunk-Gateway gemacht werden
|
|
kann. Die folgenden Voraussetzungen müssen erfüllt sein:
|
|
|
|
- Ein dedizierter (v)server muss existieren und unter einer IPv4- und einer IPv6-Adresse öffentlich erreichbar sein.
|
|
- Die Adressen müssen im MWU-DNS eingetragen sein.
|
|
- Als Betriebssystem muss Debian Stretch installiert sein.
|
|
- Für Ansible muss Python 2.6 oder höher installiert sein.
|
|
- Es muss einen User admin geben, auf den die Admins Zugriff haben; dieser muss Root-Zugang über sudo haben.
|
|
|
|
Diese Voraussetzungen werden von der Rolle `prerequisites` geprüft, die Rolle sollte als erste Rolle in jedem
|
|
Playbook eingebunden sein.
|
|
|
|
Voraussetzungen für die Control Machine:
|
|
|
|
- Python 2 (Versionen 2.6 oder 2.7) oder 3 (Versionen 3.5 oder höher)
|
|
- Ansible Version >= 2.4.0.0
|
|
- Python Modul `netaddr`
|
|
- Python Modul `dnspython`
|
|
|
|
Die Server werden mit ihren FQDNs im Ansible Inventory hinterlegt, bedenkt das für eure ssh-config.
|
|
|
|
## Gruppen-Variablen
|
|
Viele Variablen sind Mesh-spezifisch und werden auf allen Gateways benötigt. Deshalb verwalten wir die Liste `meshes`. Jeder Listeneintrag ist ein Dictionary. Diese Liste befindet sich in der Sondergruppe `all` (inventory/group_vars/all) und steht damit allen Hosts im Inventory zur Verfügung.
|
|
Diese Liste ist quasi das Herzstück zur Konfiguration der Mesh-spezifischen Parameter auf den Freifunk-Gateways. Jedes Dictionary repräsentiert eine Mesh-Wolke/Domain/Layer2-Netzwerk und ist wie folgt aufgebaut (Beispiel Mainz):
|
|
|
|
|Name|Type|Value|Format|Comment|
|
|
|----|----|-----|------|-------|
|
|
|id |Variable|mz|string|Zum Teil werden Interface-Namen davon abgeleitet, z.B. `mzbr` oder `mzbat`|
|
|
|site_number|Variable|37|integer|Fließt in IP-Adress-Berechnung ein|
|
|
|site_code|Variable|ffmz|string||
|
|
|site_name|Variable|Mainz|string||
|
|
|ipv4_network|Variable|10.37.0.0/18|string; Network/Prefix||
|
|
|ipv6_ula|List|- fd37:b4dc:4b1e::/48|string; Network/Prefix||
|
|
|ipv6_public|List|- 2a03:2260:11a::/48|string; Network/Prefix||
|
|
|dnssl|List|- ffmz.org|string|DNS Search List (dhcp/radvd)|
|
|
|batman|Dictionary||||
|
|
|batman.it|Key|10000|integer||
|
|
|batman.gw|Key|server 96mbit/96mbit|string||
|
|
|batman.mm|Key|0|boolean||
|
|
|batman.dat|Key|0|boolean||
|
|
|batman.hop_penalty|Key|60|integer||
|
|
|radvd|Dictionary||||
|
|
|radvd.maxrtradvinterval|Key|900|integer||
|
|
|radvd.advvalidlifetime|Key|864000|integer||
|
|
|radvd.advpreferredlifetime|Key|172800|integer||
|
|
|iface_mtu|Variable|1350|integer|Client MTU|
|
|
|fastd|Dictionary||||
|
|
|fastd.nodes|Dictionary||||
|
|
|fastd.nodes.instances|List|||Jeder Listeneintrag ist ein Dictionary; Instanzen für Node-Kommunikation|
|
|
|fastd.nodes.instances[x].id|Key|0|integer||
|
|
|fastd.nodes.instances[x].mtu|Key|1406|integer||
|
|
|fastd.nodes.instances[x].peers|Dictionary||||
|
|
|fastd.nodes.instances[x].peers.repo|Key|https://github.com/freifunk-mwu/peers-ffmz.git|URL||
|
|
|fastd.nodes.instances[x].peers.version|Key|master|string||
|
|
|fastd.intragate|Dictionary||||
|
|
|fastd.intragate.instances|List|||Jeder Listeneintrag ist ein Dictionary; Instanzen für Intragate-Kommunikation|
|
|
|fastd.intragate.instances[x].id|Key|0|integer||
|
|
|fastd.intragate.instances[x].mtu|Key|1406|integer||
|
|
|fastd.intragate.instances[x].peers|Dictionary||||
|
|
|fastd.intragate.instances[x].peers.repo|Key|https://github.com/freifunk-mwu/peers-ffmz.git|URL||
|
|
|fastd.intragate.instances[x].peers.version|Key|master|string||
|
|
|dns|Dictionary||||
|
|
|dns.master|Key|fd37:b4dc:4b1e::a25:103|string; IP-Adresse|DNS-Master IP|
|
|
|dns.forward_zones|List||||
|
|
|dns.forward_zones[x].name|Key|ffmz.org|string||
|
|
|dns.forward_zones[x].master|Key|fd37:b4dc:4b1e::a25:10c|string; IP-Adresse|Optional - überschreibt dns.master|
|
|
|http_domain_internal|Variable|ffmz.org|string|Haupt-Domain für HTTP-Server(intern)|
|
|
|http_domain_external|Variable|freifunk-mainz.de|string|Haupt-Domain für HTTP-Server(extern)||
|
|
|
|
Weitere Gruppen-Variablen:
|
|
|
|
|Name|Type|Value|Format|Comment|
|
|
|----|----|-----|------|-------|
|
|
|as_private_mwu|Variable|65037|integer|Privates AS von Freifunk MWU|
|
|
|as_public_ffrl|Variable|201701|integer|Public AS von Freifunk Rheinland|
|
|
|internet_exit_tcp_mss_ipv4|Variable|1240|integer|IPv4 TCP MSS|
|
|
|internet_exit_tcp_mss_ipv6|Variable|1220|integer|IPv6 TCP MSS|
|
|
|routing_tables|Dictionary||||
|
|
|routing_tables.icvpn|Key|23|integer||
|
|
|routing_tables.mwu|Key|41|integer||
|
|
|routing_tables.internet|Key|61|integer||
|
|
|icvpn_ipv4_transfer_net|Variable|10.207.0.0/16|string; Network/Prefix|ICVPN IPv4 Transfernetz|
|
|
|icvpn_ipv6_transfer_net|Variable|fec0::a:cf:0:0/96|string; Network/Prefix|ICVPN IPv6 Transfernetz|
|
|
|bgp_loopback_net|Variable|10.37.0.0/18|string; Network/Prefix|MWU Loopback Netz für dynamisches Routing|
|
|
|bgp_ipv4_transfer_net|Variable|10.37.0.0/18|string; Network/Prefix|MWU IPv4 Transfernetz für dynamisches Routing|
|
|
|bgp_ipv6_transfer_net|Variable|fd37:b4dc:4b1e::/64|string; Network/Prefix|MWU IPv6 Transfernetz für dynamisches Routing|
|
|
|http_domain_internal|Variable|ffmwu.org|string|Haupt-Domain für HTTP-Server(intern)|
|
|
|http_domain_external|Variable|freifunk-mwu.de|string|Haupt-Domain für HTTP-Server(extern)|
|
|
|icvpn|Dictionary|||ICVPN Informationen|
|
|
|icvpn.prefix|Key|mwu|string|Prefix für MWU Gateways, z.B. `mwu7` für Spinat|
|
|
|icvpn.interface|Key|icvpn|string|Name für ICVPN Interface + tinc Instanz|
|
|
|icvpn.icvpn_repo|Key|https://github.com/freifunk/icvpn|string|URL zum freifunk/icvpn Repository|
|
|
|bgp_mwu_servers|Dictionary|||Enthält pro BGP MWU peer ein Dictionary - IP-Adressen aus bgp_ipvX_transfer_net|
|
|
|bgp_mwu_servers.spinat|Dictionary||||
|
|
|bgp_mwu_servers.spinat.ipv4|Variable|10.37.0.7|string - IPv4-Adresse||
|
|
|bgp_mwu_server.spinat.ipv6|Variable|fd37:b4dc:4b1e::a25:7|string - IPv6-Adresse||
|
|
|
|
|
|
## Host-Variablen
|
|
Alle Server- bzw. Gateway-spezifischen Parameter werden als Host-Variablen abgebildet:
|
|
|
|
|Name|Type|Value|Format|Comment|
|
|
|----|----|-----|------|-------|
|
|
|magic|Variable|7|integer|Muss eindeutig unter allen Servern sein|
|
|
|ipv4_dhcp_range|Variable|6|integer|Wenn man das Mesh-Netz (/18) in /22er-Subnetze unterteilt und durchnummeriert, ist der Wert hier die Nummer des zu verwendenden /22er Subnetzes zwecks DHCP-Adress-Vergabe|
|
|
|ffrl_public_ipv4_nat|Variable|185.66.195.32/32|IP/Prefix|Öffentliche IPv4-NAT-Adresse|
|
|
|ffrl_exit_server|Dictionary|||Enthält pro FFRL Tunnel ein Dictionary|
|
|
|ffrl_exit_server.ffrl-a-ak-ber|Dictionary|||Name = Interface|
|
|
|ffrl_exit_server.ffrl-a-ak-ber.public_ipv4_address|Key|185.66.195.0|IP-Adresse|IP-Adresse der Tunnel-Gegenstelle|
|
|
|ffrl_exit_server.ffrl-a-ak-ber.tunnel_ipv4_network|Key|100.64.2.226/31|Network/Prefix|Internes IPv4-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-a-ak-ber.tunnel_ipv6_network|Key|2a03:2260:0:17b::/64|Network/Prefix|Internes IPv6-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-b-ak-ber|Dictionary|||Name = Interface|
|
|
|ffrl_exit_server.ffrl-b-ak-ber.public_ipv4_address|Key|185.66.195.1|IP-Adresse|IP-Adresse der Tunnel-Gegenstelle|
|
|
|ffrl_exit_server.ffrl-b-ak-ber.tunnel_ipv4_network|Key|100.64.2.228/31|Network/Prefix|Internes IPv4-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-b-ak-ber.tunnel_ipv6_network|Key|2a03:2260:0:17c::/64|Network/Prefix|Internes IPv6-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-a-ix-dus|Dictionary|||Name = Interface|
|
|
|ffrl_exit_server.ffrl-a-ix-dus.public_ipv4_address|Key|185.66.193.0|IP-Adresse|IP-Adresse der Tunnel-Gegenstelle|
|
|
|ffrl_exit_server.ffrl-a-ix-dus.tunnel_ipv4_network|Key|100.64.2.230/31|Network/Prefix|Internes IPv4-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-a-ix-dus.tunnel_ipv6_network|Key|2a03:2260:0:17d::/64|Network/Prefix|Internes IPv6-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-b-ix-dus|Dictionary|||Name = Interface|
|
|
|ffrl_exit_server.ffrl-b-ix-dus.public_ipv4_address|Key|185.66.193.1|IP-Adresse|IP-Adresse der Tunnel-Gegenstelle|
|
|
|ffrl_exit_server.ffrl-b-ix-dus.tunnel_ipv4_network|Key|100.64.2.232/31|Network/Prefix|Internes IPv4-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-b-ix-dus.tunnel_ipv6_network|Key|2a03:2260:0:17e::/64|Network/Prefix|Internes IPv6-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-a-fra2-fra|Dictionary|||Name = Interface|
|
|
|ffrl_exit_server.ffrl-a-fra2-fra.public_ipv4_address|Key|185.66.194.0|IP-Adresse|IP-Adresse der Tunnel-Gegenstelle|
|
|
|ffrl_exit_server.ffrl-a-fra2-fra.tunnel_ipv4_network|Key|100.64.0.186/31|Network/Prefix|Internes IPv4-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-a-fra2-fra.tunnel_ipv6_network|Key|2a03:2260:0:63::/64|Network/Prefix|Internes IPv6-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-b-fra2-fra|Dictionary|||Name = Interface|
|
|
|ffrl_exit_server.ffrl-b-fra2-fra.public_ipv4_address|Key|185.66.194.1|IP-Adresse|IP-Adresse der Tunnel-Gegenstelle|
|
|
|ffrl_exit_server.ffrl-b-fra2-fra.tunnel_ipv4_network|Key|100.64.0.188/31|Network/Prefix|Internes IPv4-Tunnel-Subnetz|
|
|
|ffrl_exit_server.ffrl-b-fra2-fra.tunnel_ipv6_network|Key|2a03:2260:0:64::/64|Network/Prefix|Internes IPv6-Tunnel-Subnetz|
|
|
|fastd_secrets|Dictionary|||Ein Eintrag pro fastd-Interface mit passwordstore lookup zum pass-Pfad|
|
|
|fastd_secrets.mzvpn|Key|"{{ lookup('passwordstore', 'fastd/mzvpn/spinat subkey=secret') }}"|||
|
|
|fastd_secrets.wivpn|Key|"{{ lookup('passwordstore', 'fastd/wivpn/spinat subkey=secret') }}"|||
|
|
|fastd_secrets.mzigvpn|Key|"{{ lookup('passwordstore', 'fastd/mzvpn/spinat subkey=secret') }}"|||
|
|
|fastd_secrets.wiigvpn|Key|"{{ lookup('passwordstore', 'fastd/wivpn/spinat subkey=secret') }}"|||
|
|
|tinc_private_key|Variable|"{{ lookup('passwordstore', 'tinc/icvpn/spinat_private returnall=true') }}"||Passwordstore lookup zum pass-Pfad|
|
|
|
|
## Sensible Informationen
|
|
|
|
Sensible Daten, z.B. private keys für Dienste wie fastd und tinc verwalten wir in einem [Password Store](https://www.passwordstore.org/).
|
|
Falls ihr mehrere Password Stores verwaltet, denkt vor Benutzung von Ansible daran, die Umgebungsvariable auf den richtigen Store zu verweisen:
|
|
```
|
|
export PASSWORD_STORE_DIR=...
|
|
```
|
|
|
|
## Aufsetzen eines neuen Gateways
|
|
|
|
- FQDN im Inventory zur Gruppe ffmwu-gateways hinzufügen
|
|
- Host-Variablen setzen
|
|
- inventory/host_vars/$FQDN
|
|
|
|
```
|
|
---
|
|
# Gateway-Nummer, von der vieles abgeleitet wird. Integer zwischen 1-254. Muss eindeutig unter allen FFMWU Servern sein.
|
|
magic:
|
|
|
|
# Die Nummer des /22er IPv4-Subnetzes, das per DHCP verteilt werden soll.
|
|
# z.B. 5 für 10.X.16.0/22 (fünftes /22 Subnetz aus 10.X.0.0/18)
|
|
ipv4_dhcp_range:
|
|
|
|
# FFRL (muss vorher bereits zugewiesen worden sein)
|
|
# Öffentliche IPv4 NAT Adresse, Format: IP/Prefix
|
|
ffrl_public_ipv4_nat:
|
|
|
|
ffrl_exit_server:
|
|
ffrl-a-ak-ber:
|
|
public_ipv4_address: 185.66.195.0
|
|
tunnel_ipv4_network: # Format: IP/Maske
|
|
tunnel_ipv6_network:
|
|
ffrl-b-ak-ber:
|
|
public_ipv4_address: 185.66.195.1
|
|
tunnel_ipv4_network: # Format: IP/Maske
|
|
tunnel_ipv6_network:
|
|
ffrl-a-ix-dus:
|
|
public_ipv4_address: 185.66.193.0
|
|
tunnel_ipv4_network: # Format: IP/Maske
|
|
tunnel_ipv6_network:
|
|
ffrl-b-ix-dus:
|
|
public_ipv4_address: 185.66.193.1
|
|
tunnel_ipv4_network: # Format: IP/Maske
|
|
tunnel_ipv6_network:
|
|
ffrl-a-fra2-fra:
|
|
public_ipv4_address: 185.66.194.0
|
|
tunnel_ipv4_network: # Format: IP/Maske
|
|
tunnel_ipv6_network:
|
|
ffrl-b-fra2-fra:
|
|
public_ipv4_address: 185.66.194.1
|
|
tunnel_ipv4_network: # Format: IP/Maske
|
|
tunnel_ipv6_network:
|
|
|
|
# Pfade zu den fastd secrets im passwordstore
|
|
fastd_secrets:
|
|
mzvpn: "{{ lookup('passwordstore', 'fastd/mzvpn/$Hostname subkey=secret') }}"
|
|
wivpn: "{{ lookup('passwordstore', 'fastd/wivpn/$Hostname subkey=secret') }}"
|
|
mzigvpn: "{{ lookup('passwordstore', 'fastd/mzvpn/$Hostname subkey=secret') }}"
|
|
wiigvpn: "{{ lookup('passwordstore', 'fastd/wivpn/$Hostname subkey=secret') }}"
|
|
|
|
# Pfade zum tinc secret im passwordstore
|
|
tinc_private_key: "{{ lookup('passwordstore', 'tinc/icvpn/$hostname_private returnall=true') }}"
|
|
```
|
|
- Neues Gateway aufsetzen per `ansible-playbook playbooks/gateways.yml`
|
|
- Hierbei werden die definierten Rollen auch auf schon aufgesetzte Gateways angewandt, was unkritisch ist, weil wir unsere Rollen idempotent schreiben.
|
|
- Um die Rollen nur auf das neu aufzusetzende Gateway anzuwenden: `ansible-playbook playbooks/gateways.yml --limit=$FQDN`
|