diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..6284cf1 --- /dev/null +++ b/.yamllint @@ -0,0 +1,19 @@ +extends: default + +rules: + braces: {max-spaces-inside: 1, level: error} + brackets: {max-spaces-inside: 1, level: error} + colons: {max-spaces-after: -1, level: error} + commas: {max-spaces-after: -1, level: error} + comments: disable + comments-indentation: disable + document-start: disable + empty-lines: {max: 3, level: error} + hyphens: {level: error} + indentation: disable + key-duplicates: enable + line-length: disable + new-line-at-end-of-file: disable + new-lines: {type: unix} + trailing-spaces: enable + truthy: disable diff --git a/Readme.md b/Readme.md index c3ed9b9..f3d38e5 100644 --- a/Readme.md +++ b/Readme.md @@ -1,40 +1,195 @@ -# ansible-ffmwu.git +# Ansible Freifunk MWU -An dieser Stelle soll der ganze ansible-script-junk entstehen, um ein FFMWU-Gateway automagisiert aufzusetzen. Das Geraffel kann später auch auf andere server-Typen erweitert werden, wenn sinnvoll. -Ein server muss minimal vorbereitet sein, bevor er mit den hiesigen Skripten zum Gate (oder zu Sonstigem) gemacht werden kann. Insbesondere müssen die folgenden Voraussetzungen erfüllt sein (diese werden vom playbook `test-prerequisites.yml` getestet): +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 sollen im MWU-DNS eingetragen sein. -- Es muss eine nakte unterstützte linux-Version aufgesetzt sein (aktuell Ubuntu 14.04, bald Debian). -- Es muss einen user admin geben, auf den die Admins Zugriff haben; dieser muss root-Zugang über sudo haben. +- 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. -Zusätzlich ist sehr empfehlenswert, dass die Admins die Maschinen mit ihren fqdns in ihrer ssh-config definiert haben. +Diese Voraussetzungen werden von der Rolle `prerequisites` geprüft, die Rolle sollte als erste Rolle in jedem +Playbook eingebunden sein. -Bisher gibt es hier zwei Sammlungen von files: zum Einen der Beginn des eigentlichen Zwecks: bisher kann eine Rolle (auf Basis der obigen Voraussetzungen) alle FFMWU-Server in dem ihnen allen identischen Aspekt vorbereiten, der Pflege der ssh keys der admins. Zum Anderen gibt es ein playbook, das eine lokale Test-VM aufsetzt, auf der man alle eigentlichen playbooks und Rollen testen kann, ohne ernsthaften Schaden anzurichten. +Voraussetzungen für die Control Machine: -## Aufsetzen und Pflegen von Gateways +- 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` -Alle FFMWU-Gatways sind auch FFMWU-Server, alle anderen server bei uns überraschenderweise auch; so sind auch Alle im inventory in der Gruppe 'ff-servers' zusammengefasst. Der Aspekt, der allen FFMWU-Servern gemein ist, sind die ssh-keys der admins. Auf einigen servern gibt es allerdings weitere Zugriffsberechtigte (spezialisierte admins). +Die Server werden mit ihren FQDNs im Ansible Inventory hinterlegt, bedenkt das für eure ssh-config. -So gibt es eine Rolle ('ffmwu-server'), die allen hosts dieser Gruppe zugewiesen ist (über das playbook 'ffmwu-servers.yml', später auch über Abhängigkeiten der speziellern playbooks). Dieses playbook (einfach starten) weist die Rolle zu, welche ihrerseits die shh keys auf den hosts pflegt. +## 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): -Die Rolle besteht aus nur einem task und einer definierten Variable, die die keys der admins enthält. Sind auf einem host weitere ssh keys von Nöten, so werden disse als hostvar definiert. +|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.nodes.instances[x].pass|Key|fastd/mzvpn|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|| +|fastd.intragate.instances[x].pass|Key|fastd/mzigvpn|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)|| -## Erzeugen einer test-VM +Weitere Gruppen-Variablen: -Um die playbooks und Rollen gefahrlos testen zu können, bietet sich ein test host an. Hierfür kann eine lokale VM zu Einsatz kommen, wenn die Voraussetzungen stimmen. +|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|| -Damit auf der lokalen Maschine (der ansible controle machine) VMs ablaufen (und mit dem playbook angelegt werden) können, müssen verschiedene Voraussetzungen erfüllt sein. U. a.: -- installierte Pakete zu libvirt, kvm und qemu und Pakete virt-manager, isomaster -- >15G freier Plattenplatz -- ansible >= 2.1 +## Host-Variablen +Alle Server- bzw. Gateway-spezifischen Parameter werden als Host-Variablen abgebildet: -Leider sind die letzten 2 Meter der Aufgabe offenbar in dieser Art nicht automatisierbar. Deshalb muss der user an einer Stelle mit 'isomaster' kurz etwas manuell durchführen -Das playbook 'loctevm-reset.yml' einfach ausführen. +|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| -### bekannte Probleme +## Sensible Informationen -- Wenn die VM wegen Zugriffsfehler auf die virtuellen volumes nicht startet, können die Berechtigungen der übergeordneten Verzeichnisse Schuld sein -> hier mal schauen. -- Ein Schritt scheint nicht automagisierbar, hier werden isomaster & der user benötigt. -- Bisher wird direkt die 64bit-Version ausgewählt. +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: +``` +- 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` diff --git a/ansible.cfg b/ansible.cfg index 3d96197..8fdbb75 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -1,10 +1,13 @@ [defaults] -# local -inventory = ./inventory/hosts -retry_files_save_path = ~/.ansible/retry-files -#vault_password_file = ~/.ansible/vault-password-file -# remote -remote_tmp = $HOME/ansible_tmp +inventory = ./inventory +retry_files_enabled = False +remote_tmp = $HOME/ansible_tmp +remote_user = admin +ansible_managed = Ansible managed - don't edit this file! +roles_path = ./roles + +[privilege_escalation] +become = True #[ssh_connection] #pipelining = True diff --git a/ffmwu-build.yml b/ffmwu-build.yml deleted file mode 100755 index 958d485..0000000 --- a/ffmwu-build.yml +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/ansible-playbook ---- -- hosts: build-servers - remote_user: admin - strategy: linear - - roles: - - ffmwu-build diff --git a/ffmwu-servers.yml b/ffmwu-servers.yml deleted file mode 100755 index 157eb00..0000000 --- a/ffmwu-servers.yml +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/ansible-playbook ---- - -- hosts: ff-servers - remote_user: admin - strategy: linear - - roles: - - ffmwu-server diff --git a/inventory/ffmwu-build-servers b/inventory/ffmwu-build-servers new file mode 100644 index 0000000..515e960 --- /dev/null +++ b/inventory/ffmwu-build-servers @@ -0,0 +1,2 @@ +[ffmwu-build-servers] +milchreis.freifunk-mwu.de diff --git a/inventory/ffmwu-gateways b/inventory/ffmwu-gateways new file mode 100644 index 0000000..9d785b2 --- /dev/null +++ b/inventory/ffmwu-gateways @@ -0,0 +1,2 @@ +[ffmwu-gateways] +uffschnitt.freifunk-mwu.de diff --git a/inventory/ffmwu-servers b/inventory/ffmwu-servers new file mode 100644 index 0000000..b7b5ead --- /dev/null +++ b/inventory/ffmwu-servers @@ -0,0 +1,2 @@ +[ffmwu-servers] +milchreis.freifunk-mwu.de diff --git a/inventory/group_vars/all b/inventory/group_vars/all new file mode 100644 index 0000000..458482e --- /dev/null +++ b/inventory/group_vars/all @@ -0,0 +1,174 @@ +--- +as_private_mwu: 65037 +as_public_ffrl: 201701 + +internet_exit_tcp_mss_ipv4: 1240 +internet_exit_tcp_mss_ipv6: 1220 + +routing_tables: + icvpn: 23 + mwu: 41 + internet: 61 + +icvpn_ipv4_transfer_net: 10.207.0.0/16 +icvpn_ipv6_transfer_net: fec0::a:cf:0:0/96 +bgp_loopback_net: 10.37.0.0/18 +bgp_ipv4_transfer_net: 10.37.0.0/18 +bgp_ipv6_transfer_net: fd37:b4dc:4b1e::/64 + +http_domain_internal: ffmwu.org +http_domain_external: freifunk-mwu.de + +meshes: + - id: mz + site_number: 37 + site_code: ffmz + site_name: Mainz + ipv4_network: 10.37.0.0/18 + ipv6_ula: + - fd37:b4dc:4b1e::/48 + ipv6_public: + - 2a03:2260:11a::/48 + dnssl: + - ffmz.org + - user.ffmz.org + batman: + it: 10000 + gw: server 96mbit/96mbit + mm: 0 + dat: 0 + hop_penalty: 60 + radvd: + maxrtradvinterval: 900 + advvalidlifetime: 864000 + advpreferredlifetime: 172800 + iface_mtu: 1350 + fastd: + nodes: + instances: + - id: 0 + mtu: 1406 + peers: + repo: https://github.com/freifunk-mwu/peers-ffmz.git + version: master + pass: fastd/mzvpn + - id: 1 + mtu: 1312 + peers: + repo: https://github.com/freifunk-mwu/peers-ffmz.git + version: master + pass: fastd/mzvpn + intragate: + instances: + - id: 0 + mtu: 1406 + peers: + repo: https://github.com/freifunk-mwu/ffmz-infrastructure-peers.git + version: master + pass: fastd/mzigvpn + dns: + master: fd37:b4dc:4b1e::a25:103 + forward_zones: + - name: ffmz.org + - name: user.ffmz.org + - name: bb.ffmz.org + - name: nodes.ffmz.org + - name: ffbin + master: fd37:b4dc:4b1e::a25:10c + http_domain_internal: ffmz.org + http_domain_external: freifunk-mainz.de + + - id: wi + site_number: 56 + site_code: ffwi + site_name: Wiesbaden + ipv4_network: 10.56.0.0/18 + ipv6_ula: + - fd56:b4dc:4b1e::/48 + ipv6_public: + - 2a03:2260:11b::/48 + dnssl: + - ffwi.org + - user.ffwi.org + batman: + it: 10000 + gw: server 96mbit/96mbit + mm: 0 + dat: 0 + hop_penalty: 60 + radvd: + maxrtradvinterval: 900 + advvalidlifetime: 864000 + advpreferredlifetime: 172800 + iface_mtu: 1350 + fastd: + nodes: + instances: + - id: 0 + mtu: 1406 + peers: + repo: https://github.com/freifunk-mwu/peers-ffwi.git + version: master + pass: fastd/wivpn + - id: 1 + mtu: 1312 + peers: + repo: https://github.com/freifunk-mwu/peers-ffwi.git + version: master + pass: fastd/wivpn + intragate: + instances: + - id: 0 + mtu: 1406 + peers: + repo: https://github.com/freifunk-mwu/ffwi-infrastructure-peers.git + version: master + pass: fastd/wiigvpn + dns: + master: fd56:b4dc:4b1e::a38:103 + forward_zones: + - name: ffwi.org + - name: user.ffwi.org + - name: bb.ffwi.org + - name: nodes.ffwi.org + http_domain_internal: ffwi.org + http_domain_external: wiesbaden.freifunk.net + +icvpn: + prefix: mwu + interface: icvpn + icvpn_repo: https://github.com/freifunk/icvpn + +bgp_mwu_servers: + spinat: + ipv4: 10.37.0.7 + ipv6: fd37:b4dc:4b1e::a25:7 + lotuswurzel: + ipv4: 10.37.0.23 + ipv6: fd37:b4dc:4b1e::a25:17 + ingwer: + ipv4: 10.37.0.161 + ipv6: fd37:b4dc:4b1e::a25:a1 + wasserfloh: + ipv4: 10.37.0.231 + ipv6: fd37:b4dc:4b1e::a25:e7 + zuckerwatte: + ipv4: 10.37.1.2 + ipv6: fd37:b4dc:4b1e::a25:102 + aubergine: + ipv4: 10.37.1.3 + ipv6: fd37:b4dc:4b1e::a25:103 + zwiebel: + ipv4: 10.37.1.0 + ipv6: fd37:b4dc:4b1e::a25:100 + glueckskeks: + ipv4: 10.37.1.1 + ipv6: fd37:b4dc:4b1e::a25:101 + suesskartoffel: + ipv4: 10.37.1.4 + ipv6: fd37:b4dc:4b1e::a25:104 + +legacy_gateways: + - ingwer + - lotuswurzel + - spinat diff --git a/inventory/group_vars/gates b/inventory/group_vars/gates deleted file mode 100644 index a074597..0000000 --- a/inventory/group_vars/gates +++ /dev/null @@ -1,3 +0,0 @@ ---- - -fastd_config: 'gate' diff --git a/inventory/group_vars/meshing-only-srv b/inventory/group_vars/meshing-only-srv deleted file mode 100644 index a1d400f..0000000 --- a/inventory/group_vars/meshing-only-srv +++ /dev/null @@ -1,3 +0,0 @@ ---- - -fastd_config: 'meshing-only' diff --git a/inventory/group_vars/meshing-srv b/inventory/group_vars/meshing-srv deleted file mode 100644 index 922f42c..0000000 --- a/inventory/group_vars/meshing-srv +++ /dev/null @@ -1,19 +0,0 @@ ---- - -communities: - - mz - - wi - -community_params: - mz: - fastd_port: 10037 - abbreviation: mz - name: mainz - repo: freifunk-mwu/peers-ffmz - xtra_peers: - - peers_bingen - wi: - fastd_port: 10056 - abbreviation: wi - name: wiesbaden - repo: freifunk-mwu/peers-ffwi diff --git a/inventory/host_vars/aubergine.freifunk-mwu.de b/inventory/host_vars/aubergine.freifunk-mwu.de deleted file mode 100644 index bc82ec6..0000000 --- a/inventory/host_vars/aubergine.freifunk-mwu.de +++ /dev/null @@ -1,4 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing diff --git a/inventory/host_vars/churro.freifunk-mwu.de b/inventory/host_vars/churro.freifunk-mwu.de deleted file mode 100644 index bc82ec6..0000000 --- a/inventory/host_vars/churro.freifunk-mwu.de +++ /dev/null @@ -1,4 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing diff --git a/inventory/host_vars/extrasahne.freifunk-mwu.de b/inventory/host_vars/extrasahne.freifunk-mwu.de deleted file mode 100644 index ff09e51..0000000 --- a/inventory/host_vars/extrasahne.freifunk-mwu.de +++ /dev/null @@ -1,6 +0,0 @@ ---- - -ansible_managed_server: True -ansible_managed_meshing: True - -fastd_alias: gw_extrasahne diff --git a/inventory/host_vars/glueckskeks.freifunk-mwu.de b/inventory/host_vars/glueckskeks.freifunk-mwu.de deleted file mode 100644 index bc82ec6..0000000 --- a/inventory/host_vars/glueckskeks.freifunk-mwu.de +++ /dev/null @@ -1,4 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing diff --git a/inventory/host_vars/ingwer.freifunk-mwu.de b/inventory/host_vars/ingwer.freifunk-mwu.de deleted file mode 100644 index bc82ec6..0000000 --- a/inventory/host_vars/ingwer.freifunk-mwu.de +++ /dev/null @@ -1,4 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing diff --git a/inventory/host_vars/linse.freifunk-mwu.de b/inventory/host_vars/linse.freifunk-mwu.de deleted file mode 100644 index 5b67d99..0000000 --- a/inventory/host_vars/linse.freifunk-mwu.de +++ /dev/null @@ -1,3 +0,0 @@ ---- - -ansible_managed_server: True diff --git a/inventory/host_vars/lotuswurzel.freifunk-mwu.de b/inventory/host_vars/lotuswurzel.freifunk-mwu.de deleted file mode 100644 index bc82ec6..0000000 --- a/inventory/host_vars/lotuswurzel.freifunk-mwu.de +++ /dev/null @@ -1,4 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing diff --git a/inventory/host_vars/milchreis.freifunk-mwu.de b/inventory/host_vars/milchreis.freifunk-mwu.de deleted file mode 100644 index a6193da..0000000 --- a/inventory/host_vars/milchreis.freifunk-mwu.de +++ /dev/null @@ -1,7 +0,0 @@ ---- - -ansible_managed_server: True -ansible_managed_build: True - -h_v_add_auth_keys: | - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDJhcbPmN6qjd+KI5t8tOVJYqS/8Jef2bAUZFlLYU6kBxZDa0Qu7Hg30z50hFcavoM6Dnh24kiZHsvCdKZ3u8mr6WhaJzDPxDm8YKk2U5WOKrQ48eq4LKU3dIOiO/5M0u90P51hF90J8/bgmp9HpNL31/8g6RT2kjBkwk62ATXF4eb0kyENHPdDn2axInKQ3z8sxhpCWhWE6J/LKIPI5J66E7F+CR7rhvk2h0ikGyBy8xZhJWY/U/IDyDV0JmvW6TNmXi4bUvUhm2lY7PRen6Xvq5UAEjC3K4YtcBCLrNtfyIR7N7vHTuuaDUjdOGCF88KdzxZ5AxIPmhN9WVj+HydCJjB1TiAzINg2egZ3Ot4juXVAi5QbU5Addw0yJdoTwGHe0mrjQ1e+VsMziDR2wZvpsU+x+D8xWmsBAh+V4vDm9gowVo5vPfFMRxAlPktNtrERSNB84OwCLtrhDc+a6BGxVuR1EHbt9H2hAUfsxRVSmwGGm5bG4QOI/DbUsARhthiYQ2Q7cNXGl0UrMkxfFpO86fiH35j3F8Cqr9oQTJOnaK64e8+zwbw+L0XxVPtAPgIGsNeNbam+ALIlbj9RQP1Cin0dlq3QCdEZ1UWdcN38RL+z27LzMgubFnapnWnlmnjqtfKAXldwwQxe1qsdWvzMA4PE/AEUF+NL5w89TYUWdw== maesto@GLaDOS diff --git a/inventory/host_vars/spinat.freifunk-mwu.de b/inventory/host_vars/spinat.freifunk-mwu.de deleted file mode 100644 index bc82ec6..0000000 --- a/inventory/host_vars/spinat.freifunk-mwu.de +++ /dev/null @@ -1,4 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing diff --git a/inventory/host_vars/suesskartoffel.freifunk-mwu.de b/inventory/host_vars/suesskartoffel.freifunk-mwu.de deleted file mode 100644 index 9e44bdf..0000000 --- a/inventory/host_vars/suesskartoffel.freifunk-mwu.de +++ /dev/null @@ -1,7 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing - -h_v_add_auth_keys: | - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt00Ozv50kIis7YKBaey5alVps98ZzW4CVO9tA8AHvsGXn8cleROjcGdbz/YwPm2RH+A+GQrRqCuEf3SPVxvthlVUuHQPKzDdX3PpcakN05CoEwR3zVwjwdzXaO3fKbN5ZCEUKTpaJU6Lngi6vO6HLzsuYloSJs3t7PGpV1xp3YESyXX7D78w9YRJSe2n3WMrA40lQ91u79V0efoX1mKQYzPH86uwhWsOqi08DvE6gxsqKMY6P06nljmsQOFsdX8S/HVrWtIcnne50b63vPMMLRkOLa5FP6qMIjU3LiirrpL80r1gmVZGVRHO6uJr+mrOb6A76cZ7LT8jaKFgnVhOyw== msslovi0@wyoming.local diff --git a/inventory/host_vars/uffschnitt.freifunk-mwu.de b/inventory/host_vars/uffschnitt.freifunk-mwu.de new file mode 100644 index 0000000..51aaa82 --- /dev/null +++ b/inventory/host_vars/uffschnitt.freifunk-mwu.de @@ -0,0 +1,31 @@ +--- +magic: 101 +ipv4_dhcp_range: 8 + +ffrl_public_ipv4_nat: 185.66.195.37/32 + +ffrl_exit_server: + ffrl-a-ak-ber: + public_ipv4_address: 185.66.195.0 + tunnel_ipv4_network: 100.64.9.42/31 + tunnel_ipv6_network: 2a03:2260:0:3bd::/64 + ffrl-b-ak-ber: + public_ipv4_address: 185.66.195.1 + tunnel_ipv4_network: 100.64.9.48/31 + tunnel_ipv6_network: 2a03:2260:0:3c0::/64 + ffrl-a-ix-dus: + public_ipv4_address: 185.66.193.0 + tunnel_ipv4_network: 100.64.9.46/31 + tunnel_ipv6_network: 2a03:2260:0:3bf::/64 + ffrl-b-ix-dus: + public_ipv4_address: 185.66.193.1 + tunnel_ipv4_network: 100.64.9.52/31 + tunnel_ipv6_network: 2a03:2260:0:3c2::/64 + ffrl-a-fra2-fra: + public_ipv4_address: 185.66.194.0 + tunnel_ipv4_network: 100.64.9.44/31 + tunnel_ipv6_network: 2a03:2260:0:3be::/64 + ffrl-b-fra2-fra: + public_ipv4_address: 185.66.194.1 + tunnel_ipv4_network: 100.64.9.50/31 + tunnel_ipv6_network: 2a03:2260:0:3c1::/64 diff --git a/inventory/host_vars/wasserfloh.freifunk-mwu.de b/inventory/host_vars/wasserfloh.freifunk-mwu.de deleted file mode 100644 index bc82ec6..0000000 --- a/inventory/host_vars/wasserfloh.freifunk-mwu.de +++ /dev/null @@ -1,4 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing diff --git a/inventory/host_vars/zuckerwatte.freifunk-mwu.de b/inventory/host_vars/zuckerwatte.freifunk-mwu.de deleted file mode 100644 index 9fa8544..0000000 --- a/inventory/host_vars/zuckerwatte.freifunk-mwu.de +++ /dev/null @@ -1,12 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing - -h_v_add_auth_keys: | - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHs63QNerevCI6wt2Gpq/IpHTPVeHIP8aKIOrRCUlKWR ccgx@small-x - ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAgEAwbfFERETgOAF7iOJFTfJAXQwOWykceRXa151PWG+hiln8X2729tdFyEhztL0tJ0ln+VCj29KLc4mG23qCBW48d35btZTkdVUhFSY/PY/bMQEBiWG2MCAWxJ329i/Blw92xvlFARJNhyPzKSxgYYGRhkncbcKXoX9QWhCBY8KfH+08X9tFOxj4osYn/+dXm7Sg5mqJG4ETmdAAy5afNGE+K+NyBafcg35Y+gBfxNzilGc2/2I0lSsiEcUr+StNxhMMZ/NtQ1N2G9iPziqpu/LYlPl/2mtya+6MPtfSfoYpggIyMqcT+KSPsmxyJod0SrI1vgrX7qa0aJV08dN+gThDb8pOBEb6NG2iQEIbmTKy7XoSpF13lnAVDtPv20PjLpUR6IKZtWNnlN2hVtZLhgyeEIDMnVjmNwloItkqsKP1H96eLSoj1g9B9IOYPPxq5pf6VJKizFAI0jsxGZk0gX/QX4DoVxrD57KXrHKEuFAM4eIjHKMXeRq3Ewbn3bHT1QXevjwBtoW2hxY8Pligc0W0sHt2jW0MxaSiE0LM+hGk0Jy9rquC3+gGU7fD2kLM6nff3wzQJXCORkfdyqvMFUqwpkZmjL4qCypt04peTwkWzs/W4LlHWyc4CJGp0jKIAOA8JRxs/FJf9CyN8N+0AY6xXAZ1UPqs+wPkZ9j5hYcaHs= magic - ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAhrDPtvVZb9I7Z2dXl3IXa34sT41/7YCl0kBJ2pgOzrTqXn6HjM8iY7duMxr1ScWlsaIoJAJmpML1LM7hkRJiray5YgjXjcNaz8HxDkV/JLLUMqzQSeDuVTFZzrQBQknzEehuA6XPTLRcgPMnpKhyt3TU4E3rHTDEFLHGEn2I9IZeImGdrehgWoJQz0gGyXI5h49bj6AXHz4etgH349ZCvQWY2e/127owcoPK5EyFBsDMKgnfdxCpAHa3vWFdUnbwqHiVu445qr2U4PiG2AK6PZKRsMauR9jBG1EfeRrc7STcx3OYRbBaQoHJkvw8dD0bH5tI1VVnXfZ2CYOyIGWHJw== mitch - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPDUI92QCs7D8mpCoqUug1fOcKf7V5nyKZJiyFfsz0T/ ccgx@mobile-x - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFx5FdrQYkd11mEBxEZLUjdI1gOlee8kP+imUTInsYGK9r3wuoiVoWX4ZdemhB6ezmJwY7mmqjHpFixct3FDdZDvoQjbbS0jM9zQtLp3quHlgpbhCSCG0NOzsjRMJhV1rQguVXDBcDxXZf1YDr9S4YJWPJ1USPPE9IILdbDl6lgaTxsEpeL6unQ3SHUkwLnQVnof1DAsS9yyyDouKMAnoiLIqOi2firerm+2KjtWXpQGF8d58eXg8FSy6iWHmy+mEOBo5W2vy8CT80hR72Ynyy4JjijvSjUzqHs9bJjxCVWOV1/4sZ5GUgNzNknIduny4tR744JRmWDfeCjCS9T3TdpKbL7Xd6pjPW4/q5Z3u0DZFutR3tBp0Xm69ic4QQZVMa14FZcipKNdE+uTpIzfpClz2e4RBR8DlJn2DexvEGSGJu3t8uOFqVnJrkmJL/eIWkRpYe+JvpaF7M7K+dM/aQWOtoTWQrmujGUqXLvSyFnuUk4PhPc3an+HaxYFCBcVGQHypc7VyAg/Bm14ZBYbj93c0UTUV01VKu5/tCjq42+hDvMsn1ZyuZ66hnnZizLzIZGH3ciGdZwPp+32nC0sT09Y8pbAZFhN6sfQHDvVrHpOjJXmbBKZ2xjYoUKoi4rdds7sLhvuJV0a3i56WR8CCIx94UGjxkfJ0A9RR24AlAuQ== mattsches@gmail.com - ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAt00Ozv50kIis7YKBaey5alVps98ZzW4CVO9tA8AHvsGXn8cleROjcGdbz/YwPm2RH+A+GQrRqCuEf3SPVxvthlVUuHQPKzDdX3PpcakN05CoEwR3zVwjwdzXaO3fKbN5ZCEUKTpaJU6Lngi6vO6HLzsuYloSJs3t7PGpV1xp3YESyXX7D78w9YRJSe2n3WMrA40lQ91u79V0efoX1mKQYzPH86uwhWsOqi08DvE6gxsqKMY6P06nljmsQOFsdX8S/HVrWtIcnne50b63vPMMLRkOLa5FP6qMIjU3LiirrpL80r1gmVZGVRHO6uJr+mrOb6A76cZ7LT8jaKFgnVhOyw== msslovi0@wyoming.local diff --git a/inventory/host_vars/zwiebel.freifunk-mwu.de b/inventory/host_vars/zwiebel.freifunk-mwu.de deleted file mode 100644 index bc82ec6..0000000 --- a/inventory/host_vars/zwiebel.freifunk-mwu.de +++ /dev/null @@ -1,4 +0,0 @@ ---- - -ansible_managed_server: True -# not yet: ansible_managed_meshing diff --git a/inventory/hosts b/inventory/hosts deleted file mode 100644 index 4dc8637..0000000 --- a/inventory/hosts +++ /dev/null @@ -1,38 +0,0 @@ -[gates] -spinat.freifunk-mwu.de -lotuswurzel.freifunk-mwu.de -wasserfloh.freifunk-mwu.de -# kaschu.freifunk-mwu.de # außer Dienst -ingwer.freifunk-mwu.de # (Debian) -#mettigel.freifunk-mwu.de -#parmesan.freifunk-mwu.de -extrasahne.freifunk-mwu.de require_dns=False # (Debian 8) FIXME: set IPv6 - -[meshing-srv:children] -gates -meshing-only-srv -test-vms - -[meshing-only-srv] -aubergine.freifunk-mwu.de # int. DNS-master -zuckerwatte.freifunk-mwu.de # web, blogs, wiki -churro.freifunk-mwu.de # Abloesung: web, blogs, wiki (Debian) -glueckskeks.freifunk-mwu.de # -zwiebel.freifunk-mwu.de # -suesskartoffel.freifunk-mwu.de # - -[ff-servers:children] -gates -meshing-only-srv -simple-ff-servers -build-servers -test-vms - -[simple-ff-servers] # not meshing -linse.freifunk-mwu.de # ext. DNS-master - -[build-servers] -milchreis.freifunk-mwu.de - -[test-vms] -local-test-vm.ffmwu.local ansible_host=192.168.137.7 require_dns=False diff --git a/inventory/test-vms b/inventory/test-vms new file mode 100644 index 0000000..64d8c34 --- /dev/null +++ b/inventory/test-vms @@ -0,0 +1,2 @@ +[test-vms] +local-test-vm.ffmwu.local ansible_host=192.168.137.7 require_dns=False diff --git a/loctevm-test-prerequisites.yml b/loctevm-test-prerequisites.yml deleted file mode 100755 index 46a4096..0000000 --- a/loctevm-test-prerequisites.yml +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/ansible-playbook ---- - -- hosts: test-vms - remote_user: admin - strategy: free - - roles: - - ffmwu-prereqs diff --git a/playbooks/build-server.yml b/playbooks/build-server.yml new file mode 100755 index 0000000..3bf1f7c --- /dev/null +++ b/playbooks/build-server.yml @@ -0,0 +1,7 @@ +#!/usr/bin/ansible-playbook + +- hosts: ffmwu-build-servers + remote_user: admin + roles: + - prerequisites + - ffmwu-build diff --git a/playbooks/gateways.yml b/playbooks/gateways.yml new file mode 100755 index 0000000..8adeeb0 --- /dev/null +++ b/playbooks/gateways.yml @@ -0,0 +1,34 @@ +#!/usr/bin/ansible-playbook + +- hosts: ffmwu-gateways + remote_user: admin + roles: + - handlers + - prerequisites + - server-apt-repos + - server-basic + - system-sysctl-gateway + - git-repos + - service-haveged + - service-ntpd + - kmod-batman + - network-routetables + - network-batman + - network-meshbridge + - network-fastd + - network-ffrl + - network-iptables-gateway + - network-routing + - service-dhcpd + - service-nginx + - service-nginx-firmware + - service-radvd + - service-fastd + - service-fastd-mesh + - service-fastd-intragate + - service-tinc + - service-bird + - service-bird-icvpn + - service-bird-ffrl + - service-bind-slave + - service-respondd diff --git a/loctevm-meshing.yml b/playbooks/localtestvm-meshing.yml similarity index 65% rename from loctevm-meshing.yml rename to playbooks/localtestvm-meshing.yml index 0d6cd3a..e6cde23 100755 --- a/loctevm-meshing.yml +++ b/playbooks/localtestvm-meshing.yml @@ -1,11 +1,9 @@ #!/usr/bin/ansible-playbook ---- - include: loctevm-provide.yml - hosts: test-vms remote_user: admin - strategy: linear - - roles: - - ffmwu-meshing + roles: + - prerequisites + - ffmwu-meshing diff --git a/loctevm-provide.yml b/playbooks/localtestvm-provide.yml similarity index 99% rename from loctevm-provide.yml rename to playbooks/localtestvm-provide.yml index 2fca683..6f75733 100755 --- a/loctevm-provide.yml +++ b/playbooks/localtestvm-provide.yml @@ -1,5 +1,4 @@ #!/usr/bin/ansible-playbook ---- # localhost (aka 127.0.0.1) is the hypervisor (hard-coded) - hosts: test-vms diff --git a/ffmwu-meshing.yml b/playbooks/meshing.yml similarity index 57% rename from ffmwu-meshing.yml rename to playbooks/meshing.yml index c1bfe50..6dc49f4 100755 --- a/ffmwu-meshing.yml +++ b/playbooks/meshing.yml @@ -1,9 +1,7 @@ #!/usr/bin/ansible-playbook ---- - hosts: meshing-srv remote_user: admin - strategy: linear - - roles: - - ffmwu-meshing + roles: + - prerequisites + - ffmwu-meshing diff --git a/test-prerequisites.yml b/playbooks/servers.yml similarity index 66% rename from test-prerequisites.yml rename to playbooks/servers.yml index 7f740e5..5a45db1 100755 --- a/test-prerequisites.yml +++ b/playbooks/servers.yml @@ -1,9 +1,7 @@ #!/usr/bin/ansible-playbook ---- - hosts: ff-servers remote_user: admin - strategy: free - roles: - - ffmwu-prereqs + - prerequisites + - ffmwu-server diff --git a/roles/ffmwu-bird/tasks/main.yml b/roles/ffmwu-bird/tasks/main.yml index be1ba94..cd2807e 100644 --- a/roles/ffmwu-bird/tasks/main.yml +++ b/roles/ffmwu-bird/tasks/main.yml @@ -7,7 +7,6 @@ owner: admin group: bird mode: 0750 - become: yes - name: standardise file ownerships file: @@ -16,7 +15,6 @@ owner: admin group: bird mode: 0750 - become: yes with_items: - /etc/bird/bird.conf - /etc/bird/mwu_peers_v4.inc diff --git a/roles/ffmwu-build/handlers/main.yml b/roles/ffmwu-build/handlers/main.yml index 7996492..fc9d637 100644 --- a/roles/ffmwu-build/handlers/main.yml +++ b/roles/ffmwu-build/handlers/main.yml @@ -1,15 +1,12 @@ --- - name: check apache syntax command: /usr/sbin/apachectl -t - become: true - name: restart systemd unit apache2 systemd: name: apache2 state: restarted - become: true - name: update apt cache apt: update_cache: yes - become: true diff --git a/roles/ffmwu-build/tasks/git-repos.yml b/roles/ffmwu-build/tasks/git-repos.yml index 52f1d4d..daeeb16 100644 --- a/roles/ffmwu-build/tasks/git-repos.yml +++ b/roles/ffmwu-build/tasks/git-repos.yml @@ -4,3 +4,4 @@ repo: https://github.com/freifunk-mwu/sites-ffmwu.git dest: /home/admin/clones/sites-ffmwu version: stable + become: false diff --git a/roles/ffmwu-build/tasks/packages.yml b/roles/ffmwu-build/tasks/packages.yml index 6838671..71b26b5 100644 --- a/roles/ffmwu-build/tasks/packages.yml +++ b/roles/ffmwu-build/tasks/packages.yml @@ -4,7 +4,6 @@ repo: 'deb https://repo.universe-factory.net/debian/ sid main' state: present filename: 'neoraider' - become: true notify: update apt cache - name: add apt repository of freifunk-mwu @@ -12,7 +11,6 @@ repo: 'deb http://repo.freifunk-mwu.de/debian/ jessie main' state: present filename: 'ffmwu' - become: true notify: update apt cache - name: add apt-key of neoraider @@ -20,14 +18,12 @@ keyserver: keyserver.ubuntu.com id: 16EF3F64CB201D9C state: present - become: true notify: update apt cache - name: add apt-key of freifunk-mwu package sigs apt_key: url: http://repo.freifunk-mwu.de/83A70084.gpg.key state: present - become: true notify: update apt cache - name: install needed packages for build-server @@ -50,4 +46,3 @@ - subversion - unzip - zlib1g-dev - become: true diff --git a/roles/ffmwu-build/tasks/rsyncd.yml b/roles/ffmwu-build/tasks/rsyncd.yml index 208fd74..bc838e7 100644 --- a/roles/ffmwu-build/tasks/rsyncd.yml +++ b/roles/ffmwu-build/tasks/rsyncd.yml @@ -4,18 +4,15 @@ src: rsyncd.conf dest: /etc/rsyncd.conf mode: 0640 - become: true - name: install rsnyc systemd unit copy: src: rsync.service dest: /etc/systemd/system/ mode: 0644 - become: true - name: ensure rsync is started on boot as a daemon systemd: name: rsync state: started enabled: True - become: true diff --git a/roles/ffmwu-build/tasks/web.yml b/roles/ffmwu-build/tasks/web.yml index 311865b..710f607 100644 --- a/roles/ffmwu-build/tasks/web.yml +++ b/roles/ffmwu-build/tasks/web.yml @@ -5,13 +5,11 @@ owner: admin group: admin recurse: yes - become: true - name: enable apache module ssl apache2_module: state: present name: ssl - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -20,7 +18,6 @@ command: /usr/sbin/a2dissite 000-default args: removes: /etc/apache2/sites-enabled/000-default.conf - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -29,7 +26,6 @@ command: /usr/sbin/a2dissite default-ssl args: removes: /etc/apache2/sites-enabled/default-ssl.conf - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -38,7 +34,6 @@ command: /usr/sbin/a2disconf other-vhosts-access-log args: removes: /etc/apache2/conf-enabled/other-vhosts-access-log.conf - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -49,7 +44,6 @@ regexp: '^([\s\t]+)?SSLCipherSuite' line: "SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA" state: present - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -60,7 +54,6 @@ regexp: '^([\s\t]+)?SSLProtocol' line: "SSLProtocol all -SSLv2 -SSLv3" state: present - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -71,7 +64,6 @@ regexp: "^ServerTokens" line: "ServerTokens Prod" state: present - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -82,7 +74,6 @@ regexp: "^ServerSignature" line: "ServerSignature EMail" state: present - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -91,7 +82,6 @@ template: src: ffmwu-default-http.conf.j2 dest: /etc/apache2/sites-available/ffmwu-default-http.conf - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -100,7 +90,6 @@ template: src: ffmwu-default-https.conf.j2 dest: /etc/apache2/sites-available/ffmwu-default-https.conf - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -109,7 +98,6 @@ command: /usr/sbin/a2ensite ffmwu-default-http args: creates: /etc/apache2/sites-enabled/ffmwu-default-http.conf - become: true notify: - check apache syntax - restart systemd unit apache2 @@ -118,7 +106,6 @@ command: /usr/sbin/a2ensite ffmwu-default-https args: creates: /etc/apache2/sites-enabled/ffmwu-default-https.conf - become: true notify: - check apache syntax - restart systemd unit apache2 diff --git a/roles/ffmwu-meshing/tasks/fastd-config.yml b/roles/ffmwu-meshing/tasks/fastd-config.yml index d30e95a..2054e28 100644 --- a/roles/ffmwu-meshing/tasks/fastd-config.yml +++ b/roles/ffmwu-meshing/tasks/fastd-config.yml @@ -40,7 +40,7 @@ line: secret "{{f_key_pair.stdout_lines[0] |regex_replace('^Secret. ','')}}"; mode: 0400 regexp: '^secret ".*";' - state : present + state: present - name: write out fastd public key - {{mf_com.abbreviation}} lineinfile: @@ -50,7 +50,7 @@ line: key "{{f_key_pair.stdout_lines[1] |regex_replace('^Public. ','')}}"; mode: 0440 regexp: '^key ".*";' - state : present + state: present register: f_pub_key ignore_errors: True diff --git a/roles/ffmwu-meshing/tasks/fastd.yml b/roles/ffmwu-meshing/tasks/fastd.yml index 3a212bb..623339e 100644 --- a/roles/ffmwu-meshing/tasks/fastd.yml +++ b/roles/ffmwu-meshing/tasks/fastd.yml @@ -2,7 +2,6 @@ - name: ensure correct ownership of /etc/fastd file: path=/etc/fastd state=directory mode=0750 owner=admin group=admin - become: True - name: find ssh keyfile name for use with git shell: grep IdentityFile ~/.ssh/config | awk '{print $2}' diff --git a/roles/ffmwu-prereqs/tasks/main.yml b/roles/ffmwu-prereqs/tasks/main.yml deleted file mode 100755 index 912db2e..0000000 --- a/roles/ffmwu-prereqs/tasks/main.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- - -- name: assert IPv4 DNS entry - local_action: shell dig A {{ inventory_hostname }} | egrep '^{{ inventory_hostname }}' - changed_when: False - when: "{{ require_dns | default('True') }}" - -- name: assert IPv6 DNS entry - local_action: shell dig AAAA {{ inventory_hostname }} | egrep '^{{ inventory_hostname }}' - changed_when: False - when: "{{ require_dns | default('True') }}" - -- name: test access to admin account (ssh key neccessary!) - command: "true" - changed_when: False - -- name: test access to root account - command: "true" - changed_when: False - become: True - become_user: root - -- name: fail on wrong OS type and version # TODO: include debian - fail: msg="unsupported OS type or version - {{ ansible_distribution }} {{ ansible_distribution_major_version }}" - when: not ( ( ansible_distribution=="Ubuntu" and ansible_distribution_major_version|int==14 ) or ( ansible_distribution=="Debian" and ansible_distribution_major_version|int==8 ) ) diff --git a/roles/ffmwu-server/tasks/main.yml b/roles/ffmwu-server/tasks/main.yml index 265cd6e..07e8678 100644 --- a/roles/ffmwu-server/tasks/main.yml +++ b/roles/ffmwu-server/tasks/main.yml @@ -10,7 +10,6 @@ - block: - name: ensure needed system users are present user: name=admin comment="Freifunk MWU Admin" shell=/bin/bash state=present - become: True - name: ensure all wanted ssh keys exclusively authorized_key: exclusive=True state=present user=admin @@ -18,11 +17,9 @@ - name: ensure vim is default editor alternatives: name=editor path=/usr/bin/vim.basic - become: True - name: set timezone to Europe/Berlin timezone: name=Europe/Berlin - become: True when: (ansible_managed_server is defined) and (ansible_managed_server) # end block diff --git a/roles/git-repos/README.md b/roles/git-repos/README.md new file mode 100644 index 0000000..51f5acb --- /dev/null +++ b/roles/git-repos/README.md @@ -0,0 +1,18 @@ +# Ansible role git-repos + +Diese Ansible role klont wichtige git Repositories. + +- installiert git +- legt /home/admin/clones an +- klont alle git Repositories aus dem Dictionary `common_repos` + +## Benötigte Variablen + +- Dictionary `common_repos` # role variable +``` +common_repos: + name: # name des Repositories == Ordner Name + repo_url: # HTTP-URL zum Repository +... + +``` diff --git a/roles/git-repos/tasks/main.yml b/roles/git-repos/tasks/main.yml new file mode 100644 index 0000000..05ce77d --- /dev/null +++ b/roles/git-repos/tasks/main.yml @@ -0,0 +1,23 @@ +--- +- name: install git packages + package: + name: "{{ item }}" + state: present + with_items: + - git + +- name: ensure git directory is present + file: + path: /home/admin/clones + state: directory + mode: 0755 + owner: admin + group: admin + +- name: clone git repositories + git: + repo: "{{ item.value.repo_url }}" + dest: "/home/admin/clones/{{ item.key }}" + version: "{{ item.value.version }}" + with_dict: "{{ common_repos }}" + become: false diff --git a/roles/git-repos/vars/main.yml b/roles/git-repos/vars/main.yml new file mode 100644 index 0000000..57b5cad --- /dev/null +++ b/roles/git-repos/vars/main.yml @@ -0,0 +1,11 @@ +--- +common_repos: + backend-scripts: + repo_url: https://github.com/freifunk-mwu/backend-scripts.git + version: ansible + icvpn-meta: + repo_url: https://github.com/freifunk/icvpn-meta.git + version: master + icvpn-scripts: + repo_url: https://github.com/freifunk/icvpn-scripts.git + version: master diff --git a/roles/handlers/handlers/main.yml b/roles/handlers/handlers/main.yml new file mode 100644 index 0000000..b0dd612 --- /dev/null +++ b/roles/handlers/handlers/main.yml @@ -0,0 +1,95 @@ +--- +- name: reload systemd + systemd: + daemon_reload: yes + +- name: reload network interfaces + systemd: + name: networking + state: reloaded + +- name: activate sysfs variables + systemd: + name: sysfsutils + state: restarted + +- name: restart bind9 + systemd: + name: bind9 + state: restarted + +- name: reload systemd unit bird + systemd: + name: bird + state: reloaded + +- name: reload systemd unit bird6 + systemd: + name: bird6 + state: reloaded + +- name: restart isc dhcp server + systemd: + name: isc-dhcp-server + enabled: yes + state: restarted + +- name: restart fastd intragate instances + systemd: + name: "fastd@{{ item.0.id }}igvpn-{{ item.1.mtu }}" + state: restarted + with_subelements: + - "{{ meshes }}" + - fastd.intragate.instances + +- name: restart fastd mesh instances + systemd: + name: "fastd@{{ item.0.id }}vpn-{{ item.1.mtu }}" + state: restarted + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + +- name: restart systemd unit radvd + systemd: + name: radvd + state: restarted + +- name: restart respondd + systemd: + name: "respondd-{{ item.id }}" + state: restarted + with_items: "{{ meshes }}" + +- name: restart systemd unit tinc + systemd: + name: tinc + enabled: yes + state: restarted + +- name: restart systemd unit ffmwu-static-routes + systemd: + name: ffmwu-static-routes + state: restarted + +- name: restart systemd unit ffmwu-ip-rules + systemd: + name: ffmwu-ip-rules + state: restarted + +- name: restart respondd + systemd: + name: "respondd-{{ item.id }}" + state: restarted + with_items: "{{ meshes }}" + +- name: iptables-restore + shell: iptables-restore < /etc/iptables/rules.v4 + +- name: ip6tables-restore + shell: ip6tables-restore < /etc/iptables/rules.v6 + +- name: reload nginx + systemd: + name: nginx + state: reloaded diff --git a/roles/kmod-batman/README.md b/roles/kmod-batman/README.md new file mode 100644 index 0000000..552fbf6 --- /dev/null +++ b/roles/kmod-batman/README.md @@ -0,0 +1,6 @@ +# Ansible role kmod-batman +Diese Ansible role installiert das Kernel Modul batman-adv: + +- Linux Kernel Headers +- Kernel Modul batman-adv +- Userspace Tool batctl diff --git a/roles/kmod-batman/tasks/main.yml b/roles/kmod-batman/tasks/main.yml new file mode 100644 index 0000000..8cc799e --- /dev/null +++ b/roles/kmod-batman/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: install batman-module and linux headers + package: + name: "{{ item }}" + state: present + with_items: + - linux-headers-amd64 + - batman-adv-dkms + - batctl + +- name: configure batman module to load on system boot + template: + src: batman-adv.module.conf.j2 + dest: /etc/modules-load.d/batman-adv.conf + +- name: load batman module + modprobe: + name: "batman-adv" + state: present diff --git a/roles/kmod-batman/templates/batman-adv.module.conf.j2 b/roles/kmod-batman/templates/batman-adv.module.conf.j2 new file mode 100644 index 0000000..b0b819f --- /dev/null +++ b/roles/kmod-batman/templates/batman-adv.module.conf.j2 @@ -0,0 +1,5 @@ +# +# Load batman-adv module on system boot +# {{ ansible_managed }} +# +batman-adv diff --git a/include/loctevm-provide-iso.inc.yml b/roles/localtestvm/tasks/loctevm-provide-iso.inc.yml similarity index 99% rename from include/loctevm-provide-iso.inc.yml rename to roles/localtestvm/tasks/loctevm-provide-iso.inc.yml index d5273b6..632a344 100644 --- a/include/loctevm-provide-iso.inc.yml +++ b/roles/localtestvm/tasks/loctevm-provide-iso.inc.yml @@ -1,7 +1,7 @@ --- - name: retrieve install iso - get_url: + get_url: checksum: "sha1:23dde0f195170d9fbe99547f9df75838acc95b5e" dest: "{{ vm_path }}/debian-8.6.0-amd64-i386-netinst.iso" force: no @@ -24,7 +24,7 @@ loop_control: loop_var: lri_item delegate_to: 127.0.0.1 # local action - + - name: manual intervention 1 - extract configs debug: msg: | @@ -125,4 +125,3 @@ # remote_src: True # though remote equals local ... # delegate_to: 127.0.0.1 # local action # register: primcopy - diff --git a/include/loctevm-provide-net.inc.yml b/roles/localtestvm/tasks/loctevm-provide-net.inc.yml similarity index 100% rename from include/loctevm-provide-net.inc.yml rename to roles/localtestvm/tasks/loctevm-provide-net.inc.yml diff --git a/include/loctevm-provide-prereq.inc.yml b/roles/localtestvm/tasks/loctevm-provide-prereq.inc.yml similarity index 95% rename from include/loctevm-provide-prereq.inc.yml rename to roles/localtestvm/tasks/loctevm-provide-prereq.inc.yml index 2112b07..a310745 100644 --- a/include/loctevm-provide-prereq.inc.yml +++ b/roles/localtestvm/tasks/loctevm-provide-prereq.inc.yml @@ -18,15 +18,14 @@ - name: ensure admin user user: comment="FFMWU Administrator" name=admin shell=/bin/bash state=present - become: True - name: ensure users ssh key to admin user authorized_key: user=admin key="{{ lookup('file', '~/.ssh/id_rsa.pub') }}" exclusive=no - become: True - name: ensure users ssh key to bootstrap user authorized_key: user=hein key="{{ lookup('file', '~/.ssh/id_rsa.pub') }}" + become: false - name: ensure no-pw sudo capability for admin and bootstrap user lineinfile: @@ -35,8 +34,6 @@ line: "admin,hein ALL = (root) NOPASSWD: ALL" mode: 0440 validate: visudo -c -f %s - become: True - name: from this point on prevent pw for bootstrap user user: user=hein password=X - become: True diff --git a/include/loctevm-provide-vm.inc.yml b/roles/localtestvm/tasks/loctevm-provide-vm.inc.yml similarity index 100% rename from include/loctevm-provide-vm.inc.yml rename to roles/localtestvm/tasks/loctevm-provide-vm.inc.yml diff --git a/templates/loctenet.xml b/roles/localtestvm/templates/loctenet.xml similarity index 100% rename from templates/loctenet.xml rename to roles/localtestvm/templates/loctenet.xml diff --git a/templates/loctevm-pool.xml b/roles/localtestvm/templates/loctevm-pool.xml similarity index 100% rename from templates/loctevm-pool.xml rename to roles/localtestvm/templates/loctevm-pool.xml diff --git a/templates/loctevm.xml b/roles/localtestvm/templates/loctevm.xml similarity index 100% rename from templates/loctevm.xml rename to roles/localtestvm/templates/loctevm.xml diff --git a/templates/preseed.cfg b/roles/localtestvm/templates/preseed.cfg similarity index 100% rename from templates/preseed.cfg rename to roles/localtestvm/templates/preseed.cfg diff --git a/roles/network-batman/README.md b/roles/network-batman/README.md new file mode 100644 index 0000000..0e11f2d --- /dev/null +++ b/roles/network-batman/README.md @@ -0,0 +1,46 @@ +# Ansible role network-batman + +Diese Ansible role konfiguriert batman-adv Netzwerk Interfaces. + +- dummy interface pro mesh +- batman-adv interface pro mesh +- konfiguriert sysfs variablen: + - Hop Penalty pro batman-adv interface + +## Benötigte Variablen + +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + ipv4_network: +... + batman: + it: # integer: originator interval + gw: # string: gateway mode + mm: # boolean: multicast mode + dat: # boolean: distributed arp table + hop_penalty: # integer: hop penalty +... + fastd: + nodes: + instances: + - id: 0 # integer + mtu: # integer + ... + intragate: + instances: + - id: 0 # integer + mtu: # integer + ... + +´´´ +- Host Variable `magic` + +## MAC-Adressen + +Die MAC-Adressen der Interfaces werden aus dem IPv4-Subnetz sowie der `magic`-Nummer des Hosts berechnet. + +xx0-prefix: `02:00` +xxbat-prefix: `02:01` diff --git a/roles/network-batman/tasks/main.yml b/roles/network-batman/tasks/main.yml new file mode 100644 index 0000000..99f7477 --- /dev/null +++ b/roles/network-batman/tasks/main.yml @@ -0,0 +1,17 @@ +--- +- name: create dummy interfaces + template: + src: dummy.j2 + dest: "/etc/network/interfaces.d/{{ item.id }}0" + notify: reload network interfaces + with_items: "{{ meshes }}" + +- name: create batman interfaces + template: + src: batman.j2 + dest: "/etc/network/interfaces.d/{{ item.id }}bat" + notify: reload network interfaces + with_items: "{{ meshes }}" + +- name: flush handlers + meta: flush_handlers diff --git a/roles/network-batman/templates/batman.j2 b/roles/network-batman/templates/batman.j2 new file mode 100644 index 0000000..557af93 --- /dev/null +++ b/roles/network-batman/templates/batman.j2 @@ -0,0 +1,15 @@ +#jinja2: trim_blocks:False +{% set ip4hex = item.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') | ip4_hex() -%} +{% set mac = '0201' + ip4hex -%} +# +# {{ ansible_managed }} +# +auto {{ item.id }}bat +iface {{ item.id }}bat + hwaddress {{ mac | hwaddr('linux') }} + batman-ifaces {{ item.id }}0 {% for instance in item.fastd.nodes.instances %}{{ item.id }}vpn-{{ instance.mtu }}{% if not loop.last %} {% endif %}{% endfor %} {% for instance in item.fastd.intragate.instances %}{{ item.id }}igvpn-{{ instance.mtu }}{% if not loop.last %} {% endif %}{% endfor %} + batman-hop-penalty {{ item.batman.hop_penalty }} + post-up /usr/sbin/batctl -m $IFACE it {{ item.batman.it }} + post-up /usr/sbin/batctl -m $IFACE gw {{ item.batman.gw }} + post-up /usr/sbin/batctl -m $IFACE mm {{ item.batman.mm }} + post-up /usr/sbin/batctl -m $IFACE dat {{ item.batman.dat }} diff --git a/roles/network-batman/templates/dummy.j2 b/roles/network-batman/templates/dummy.j2 new file mode 100644 index 0000000..a18a325 --- /dev/null +++ b/roles/network-batman/templates/dummy.j2 @@ -0,0 +1,9 @@ +{% set ip4hex = item.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') | ip4_hex() -%} +{% set mac = '0200' + ip4hex -%} +# +# {{ ansible_managed }} +# +auto {{ item.id }}0 +iface {{ item.id }}0 + link-type dummy + hwaddress {{ mac | hwaddr('linux') }} diff --git a/roles/network-fastd/README.md b/roles/network-fastd/README.md new file mode 100644 index 0000000..10202a8 --- /dev/null +++ b/roles/network-fastd/README.md @@ -0,0 +1,40 @@ +# Ansible role network-fastd + +Diese Ansible role konfiguriert Netzwerk Interfaces für die definierten fastd Instanzen. + +Es wird zwischen node- und intragate-Instanzen unterschieden. + +## Interface-Benamung +Node-Interfaces: $mesh.id + vpn + '-' + $mesh.fastd.nodes.instances.xx.mtu, z.B. "mzvpn-1312" +Intragate-Interfaces: $mesh.id + 'ig' + vpn + '-' + $mesh.fastd.intragate.instances.xx.mtu, z.B. "mzigvpn-1312" + +## Benötigte Variablen + +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + ipv4_network: +... + fastd: + nodes: + instances: + - id: 0 # integer + mtu: # integer + ... + intragate: + instances: + - id: 0 # integer + mtu: # integer + ... + +´´´ +- Host Variable `magic` + +## MAC-Adressen + +Die MAC-Adressen der Interfaces werden aus dem IPv4-Subnetz sowie der `magic`-Nummer des Hosts berechnet. + +xxvpn-$mtu prefix: `02:2x` # x = ID der fastd-Instanz +xxigvpn-$mtu prefix: `02:3x` # x = ID der fastd-Instanz diff --git a/roles/network-fastd/tasks/main.yml b/roles/network-fastd/tasks/main.yml new file mode 100644 index 0000000..d82aede --- /dev/null +++ b/roles/network-fastd/tasks/main.yml @@ -0,0 +1,21 @@ +--- +- name: create fastd mesh interfaces + template: + src: fastd-mesh.j2 + dest: "/etc/network/interfaces.d/{{ item.0.id }}vpn-{{ item.1.mtu }}" + notify: reload network interfaces + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + +- name: create fastd intragate interfaces + template: + src: fastd-intragate.j2 + dest: "/etc/network/interfaces.d/{{ item.0.id }}igvpn-{{ item.1.mtu }}" + notify: reload network interfaces + with_subelements: + - "{{ meshes }}" + - fastd.intragate.instances + +- name: flush handlers + meta: flush_handlers diff --git a/roles/network-fastd/templates/fastd-intragate.j2 b/roles/network-fastd/templates/fastd-intragate.j2 new file mode 100644 index 0000000..aa5b4c1 --- /dev/null +++ b/roles/network-fastd/templates/fastd-intragate.j2 @@ -0,0 +1,8 @@ +{% set ip4hex = item.0.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') | ip4_hex() -%} +{% set mac = '023' + item.1.id|string + ip4hex -%} +# +# {{ ansible_managed }} +# +auto {{ item.0.id }}igvpn-{{ item.1.mtu }} +iface {{ item.0.id }}igvpn-{{ item.1.mtu }} + hwaddress {{ mac | hwaddr('linux') }} diff --git a/roles/network-fastd/templates/fastd-mesh.j2 b/roles/network-fastd/templates/fastd-mesh.j2 new file mode 100644 index 0000000..0e484fc --- /dev/null +++ b/roles/network-fastd/templates/fastd-mesh.j2 @@ -0,0 +1,8 @@ +{% set ip4hex = item.0.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') | ip4_hex() -%} +{% set mac = '022' + item.1.id|string + ip4hex -%} +# +# {{ ansible_managed }} +# +auto {{ item.0.id }}vpn-{{ item.1.mtu }} +iface {{ item.0.id }}vpn-{{ item.1.mtu }} + hwaddress {{ mac | hwaddr('linux') }} diff --git a/roles/network-ffrl/README.md b/roles/network-ffrl/README.md new file mode 100644 index 0000000..4ba787e --- /dev/null +++ b/roles/network-ffrl/README.md @@ -0,0 +1,33 @@ +# Ansible role network-ffrl + +Diese Ansible role konfiguriert die GRE-Tunnel Interfaces, die für den Internet-Exit über Freifunk Rheinland benötigt werden. + +## Benötigte Variablen +- Dictionary `ffrl_exit_server` (Host Variable) +´´´ +ffrl_exit_server: + ffrl-a-ak-ber: + public_ipv4_address: 185.66.195.0 + tunnel_ipv4_network: # IPv4 Tunnel Transfernetz + tunnel_ipv6_network: # IPv6 Tunnel Transfernetz + ffrl-b-ak-ber: + public_ipv4_address: 185.66.195.1 + tunnel_ipv4_network: + tunnel_ipv6_network: + ffrl-a-ix-dus: + public_ipv4_address: 185.66.193.0 + tunnel_ipv4_network: + tunnel_ipv6_network: + ffrl-b-ix-dus: + public_ipv4_address: 185.66.193.1 + tunnel_ipv4_network: + tunnel_ipv6_network: + ffrl-a-fra2-fra: + public_ipv4_address: 185.66.194.0 + tunnel_ipv4_network: + tunnel_ipv6_network: + ffrl-b-fra2-fra: + public_ipv4_address: 185.66.194.1 + tunnel_ipv4_network: + tunnel_ipv6_network: +´´´ diff --git a/roles/network-ffrl/tasks/main.yml b/roles/network-ffrl/tasks/main.yml new file mode 100644 index 0000000..8ef075a --- /dev/null +++ b/roles/network-ffrl/tasks/main.yml @@ -0,0 +1,16 @@ +--- +- name: create ffrl interfaces + template: + src: ffrl.j2 + dest: "/etc/network/interfaces.d/{{ item.key }}" + notify: reload network interfaces + with_dict: "{{ ffrl_exit_server }}" + +- name: create ffrl-nat dummy interface + template: + src: ffrl_nat.j2 + dest: "/etc/network/interfaces.d/ffrl-nat" + notify: reload network interfaces + +- name: flush handlers + meta: flush_handlers diff --git a/roles/network-ffrl/templates/ffrl.j2 b/roles/network-ffrl/templates/ffrl.j2 new file mode 100644 index 0000000..f8323c3 --- /dev/null +++ b/roles/network-ffrl/templates/ffrl.j2 @@ -0,0 +1,15 @@ +# +# {{ ansible_managed }} +# +auto {{ item.key }} +iface {{ item.key }} inet tunnel + mode gre + local {{ ansible_default_ipv4.address | ipaddr('public') | ipaddr('address') }} + endpoint {{ item.value.public_ipv4_address | ipaddr('public') | ipaddr('address') }} + + ttl 64 + mtu 1400 + tunnel-physdev {{ ansible_default_ipv4.interface }} + + address {{ item.value.tunnel_ipv4_network | ipaddr('net') | ipaddr('1') | ipaddr('ip/prefix') }} + address {{ item.value.tunnel_ipv6_network | ipaddr('net') | ipaddr('2') | ipaddr('ip/prefix') }} diff --git a/roles/network-ffrl/templates/ffrl_nat.j2 b/roles/network-ffrl/templates/ffrl_nat.j2 new file mode 100644 index 0000000..39523e9 --- /dev/null +++ b/roles/network-ffrl/templates/ffrl_nat.j2 @@ -0,0 +1,7 @@ +# +# {{ ansible_managed }} +# +auto ffrl-nat +iface ffrl-nat + link-type dummy + address {{ ffrl_public_ipv4_nat | ipaddr('host') }} diff --git a/roles/network-iptables-gateway/README.md b/roles/network-iptables-gateway/README.md new file mode 100644 index 0000000..bd8c854 --- /dev/null +++ b/roles/network-iptables-gateway/README.md @@ -0,0 +1,29 @@ +# Ansible role network-iptables-gateway + +Diese Ansible role konfiguriert iptables Regeln für IPv4+IPv6 eines Freifunk Gateways. + +- installiert iptables+iptables-persistent +- schreibt rules.v4 + rules.v6 +- setzt netfilter sysctl parameter + +## Benötigte Variablen + +- List `sysctl_settings_netfilter` (Rollen Variable) +´´´ +sysctl_settings_netfilter: + - name: # sysctl-Parameter + value: # zu setzender Wert + +´´´ +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + ipv4_network: +... + +´´´ +- Variable `internet_exit_tcp_mss_ipv4` +- Variable `internet_exit_tcp_mss_ipv6` +- Host Variable `ffrl_public_ipv4_nat` # Format ip-adresse/prefix diff --git a/roles/network-iptables-gateway/tasks/main.yml b/roles/network-iptables-gateway/tasks/main.yml new file mode 100644 index 0000000..a8a2e84 --- /dev/null +++ b/roles/network-iptables-gateway/tasks/main.yml @@ -0,0 +1,35 @@ +--- +- name: install iptables packages + package: + name: "{{ item }}" + state: present + with_items: + - iptables + - iptables-persistent + +- name: load netfilter modules + modprobe: + name: "{{ item }}" + state: present + with_items: + - nf_conntrack + - nf_conntrack_ipv4 + +- name: set netfilter sysctl settings + sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + state: present + with_items: "{{ sysctl_settings_netfilter }}" + +- name: write iptables configuration + template: + src: rules.v4.j2 + dest: /etc/iptables/rules.v4 + notify: iptables-restore + +- name: write ip6tables configuration + template: + src: rules.v6.j2 + dest: /etc/iptables/rules.v6 + notify: ip6tables-restore diff --git a/roles/network-iptables-gateway/templates/rules.v4.j2 b/roles/network-iptables-gateway/templates/rules.v4.j2 new file mode 100644 index 0000000..94cdc07 --- /dev/null +++ b/roles/network-iptables-gateway/templates/rules.v4.j2 @@ -0,0 +1,42 @@ +# +# {{ ansible_managed }} +# +*filter +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -d {{ ansible_default_ipv4.address | ipaddr('public') }}/32 -p gre -j ACCEPT +-A INPUT -m conntrack --ctstate INVALID -j DROP +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +{% for mesh_forward in meshes %} +{% for mesh_recursive in meshes recursive %} +{% if not mesh_forward.id == mesh_recursive.id %} +-A FORWARD -i {{ mesh_forward.id }}br -o {{ mesh_recursive.id }}br -j ACCEPT +{% endif %} +{% endfor %} +{% endfor %} +-A FORWARD -m conntrack --ctstate INVALID -j DROP +-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A OUTPUT -s {{ ansible_default_ipv4.address | ipaddr('public') }}/32 -p gre -j ACCEPT +-A OUTPUT -m conntrack --ctstate INVALID -j DROP +-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +COMMIT +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +-A POSTROUTING -o ffrl+ -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss ! --mss 0:{{ internet_exit_tcp_mss_ipv4 }} -j TCPMSS --set-mss {{ internet_exit_tcp_mss_ipv4 }} +COMMIT +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +:ffrl-nat - [0:0] +{% for mesh in meshes %} +-A POSTROUTING -s {{ mesh.ipv4_network | ipaddr('private') | ipaddr('net') }} -o ffrl+ -j ffrl-nat +{% endfor %} +-A ffrl-nat -o ffrl+ -j SNAT --to-source {{ ffrl_public_ipv4_nat | ipaddr('address') }} +COMMIT diff --git a/roles/network-iptables-gateway/templates/rules.v6.j2 b/roles/network-iptables-gateway/templates/rules.v6.j2 new file mode 100644 index 0000000..7c97f3f --- /dev/null +++ b/roles/network-iptables-gateway/templates/rules.v6.j2 @@ -0,0 +1,35 @@ +# +# {{ ansible_managed }} +# +*filter +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +-A INPUT -m conntrack --ctstate INVALID -j DROP +-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +{% for mesh_forward in meshes %} +{% for mesh_recursive in meshes recursive %} +{% if not mesh_forward.id == mesh_recursive.id %} +-A FORWARD -i {{ mesh_forward.id }}br -o {{ mesh_recursive.id }}br -j ACCEPT +{% endif %} +{% endfor %} +{% endfor %} +-A FORWARD -m conntrack --ctstate INVALID -j DROP +-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +-A OUTPUT -m conntrack --ctstate INVALID -j DROP +-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT +COMMIT +*mangle +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:FORWARD ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +-A POSTROUTING -o ffrl+ -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss ! --mss 0:{{ internet_exit_tcp_mss_ipv6 }} -j TCPMSS --set-mss {{ internet_exit_tcp_mss_ipv6 }} +COMMIT +*nat +:PREROUTING ACCEPT [0:0] +:INPUT ACCEPT [0:0] +:OUTPUT ACCEPT [0:0] +:POSTROUTING ACCEPT [0:0] +COMMIT diff --git a/roles/network-iptables-gateway/vars/main.yml b/roles/network-iptables-gateway/vars/main.yml new file mode 100644 index 0000000..1d44152 --- /dev/null +++ b/roles/network-iptables-gateway/vars/main.yml @@ -0,0 +1,6 @@ +--- +sysctl_settings_netfilter: + - name: net.netfilter.nf_conntrack_tcp_timeout_established + value: 86400 + - name: net.netfilter.nf_conntrack_max + value: 262140 diff --git a/roles/network-meshbridge/README.md b/roles/network-meshbridge/README.md new file mode 100644 index 0000000..ada7e95 --- /dev/null +++ b/roles/network-meshbridge/README.md @@ -0,0 +1,30 @@ +# Ansible role network-meshbridge + +Diese Ansible role konfiguriert die Linux Bridges für die Freifunk Meshes. + +- linux bridge pro mesh inklusive IP-Konfiguration +- konfiguriert sysfs variablen: + - hash_max + +## Benötigte Variablen + +- Dictionary `meshes` +´´´ +meshes: + -id: xx +... + ipv4_network: +... + ipv6_ula: + - fdxx.../48 # ipv6 ula prefix + ipv6_public: + - 2xxx.../48 # ipv6 public prefix + +´´´ +- Host Variable `magic` + +## MAC-Adressen + +Die MAC-Adressen der Interfaces werden aus dem IPv4-Subnetz sowie der `magic`-Nummer des Hosts berechnet. + +xxbr-prefix: `02:10` diff --git a/roles/network-meshbridge/tasks/main.yml b/roles/network-meshbridge/tasks/main.yml new file mode 100644 index 0000000..c1796d1 --- /dev/null +++ b/roles/network-meshbridge/tasks/main.yml @@ -0,0 +1,17 @@ +--- +- name: create mesh bridges + template: + src: bridge.j2 + dest: "/etc/network/interfaces.d/{{ item.id }}br" + notify: reload network interfaces + with_items: "{{ meshes }}" + +- name: set sysfs variables + template: + src: sysfs.j2 + dest: "/etc/sysfs.d/99-{{ item.id }}br.conf" + with_items: "{{ meshes }}" + notify: activate sysfs variables + +- name: flush handlers + meta: flush_handlers diff --git a/roles/network-meshbridge/templates/bridge.j2 b/roles/network-meshbridge/templates/bridge.j2 new file mode 100644 index 0000000..626f08d --- /dev/null +++ b/roles/network-meshbridge/templates/bridge.j2 @@ -0,0 +1,17 @@ +{% set ip4hex = item.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') | ip4_hex() -%} +{% set mac = '0210' + ip4hex -%} +# +# {{ ansible_managed }} +# +auto {{ item.id }}br +iface {{ item.id }}br +# hwaddress {{ mac | hwaddr('linux') }} <-- preferred way, not working - ipv6 addresses not set on boot + pre-up /sbin/ip link set address {{ mac | hwaddr('linux') }} dev $IFACE # ^^^ dirty workaround to get rid of + address {{ item.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('ip/prefix') }} +{% for prefix in item.ipv6_ula %} + address {{ prefix | ipaddr('net') | ipsubnet(64, 0) | ipaddr(magic) | ipaddr('ip/prefix') }} +{% endfor %} +{% for prefix in item.ipv6_public %} + address {{ prefix | ipaddr('net') | ipsubnet(64, 0) | ipaddr(magic) | ipaddr('ip/prefix') }} +{% endfor %} + bridge-ports {{ item.id }}bat diff --git a/roles/network-meshbridge/templates/sysfs.j2 b/roles/network-meshbridge/templates/sysfs.j2 new file mode 100644 index 0000000..45f71ad --- /dev/null +++ b/roles/network-meshbridge/templates/sysfs.j2 @@ -0,0 +1,4 @@ +# +# {{ ansible_managed }} +# +class/net/{{ item.id }}br/bridge/hash_max = 16384 diff --git a/roles/network-routetables/README.md b/roles/network-routetables/README.md new file mode 100644 index 0000000..0ecc6d1 --- /dev/null +++ b/roles/network-routetables/README.md @@ -0,0 +1,12 @@ +# Ansible role network-routetables + +Diese Ansible role legt die erforderlichen routing tables an. + +## Benötigte Variablen + +- `routing_tables` +´´´ +routing_tables: + $name: # integer + +´´´ diff --git a/roles/network-routetables/tasks/main.yml b/roles/network-routetables/tasks/main.yml new file mode 100644 index 0000000..d816c2f --- /dev/null +++ b/roles/network-routetables/tasks/main.yml @@ -0,0 +1,8 @@ +--- +- name: create routing tables + lineinfile: + path: /etc/iproute2/rt_tables + regexp: '^{{ item.value }}' + line: "{{ item.value }}{{ '\t' }}{{ item.key }}" + state: present + with_dict: "{{ routing_tables }}" diff --git a/roles/network-routing/README.md b/roles/network-routing/README.md new file mode 100644 index 0000000..db00a5b --- /dev/null +++ b/roles/network-routing/README.md @@ -0,0 +1,33 @@ +# Ansible role network-routing + +Diese Ansible role konfiguriert System Einstellung bzgl. IP Routing. + +- konfiguriert statische Routen (systemd Unit) + - Mesh Routen für die Routing Tabelle `mwu` + - Blackhole Routes für die Routing Tabellen `internet` + `main` +- konfiguriert IP rules (systemd Unit) +- konfiguriert sysctl Parameter + +## Benötigte Variablen + +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + site_name: + ipv4_network: + ipv6_ula: + ipv6_public: +´´´ +- List `sysctl_settings_gateway` (Rollen-Variable) +``` +sysctl_settings_routing: + - name: # sysctl-Parameter + value: # zu setzender Wert +... +- Host Variable `ffrl_public_ipv4_nat` # Format ip-adresse/prefix +- Host Dictionary `ffrl_exit_server + +´´´ +- Host Variable `magic` diff --git a/roles/network-routing/tasks/main.yml b/roles/network-routing/tasks/main.yml new file mode 100644 index 0000000..8091636 --- /dev/null +++ b/roles/network-routing/tasks/main.yml @@ -0,0 +1,61 @@ +--- +- name: write systemd unit ffmwu-static-routes.service + template: + src: ffmwu-static-routes.service.j2 + dest: /etc/systemd/system/ffmwu-static-routes.service + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: write static route scripts + template: + src: "{{ item }}.j2" + dest: "/usr/local/bin/{{ item }}" + owner: root + group: root + mode: 0750 + with_items: + - ffmwu-add-static-routes.sh + - ffmwu-del-static-routes.sh + notify: restart systemd unit ffmwu-static-routes + +- name: enable systemd unit ffmwu-static-routes.service + systemd: + name: ffmwu-static-routes + enabled: yes + state: started + +- name: write systemd unit ffmwu-ip-rules.service + template: + src: ffmwu-ip-rules.service.j2 + dest: /etc/systemd/system/ffmwu-ip-rules.service + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: write ip rule scripts + template: + src: "{{ item }}.j2" + dest: "/usr/local/bin/{{ item }}" + owner: root + group: root + mode: 0750 + with_items: + - ffmwu-add-ip-rules.sh + - ffmwu-del-ip-rules.sh + notify: restart systemd unit ffmwu-ip-rules + +- name: enable systemd unit ffmwu-ip-rules.service + systemd: + name: ffmwu-ip-rules + enabled: yes + state: started + +- name: set freifunk gateway sysctl settings + sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + state: present + with_items: "{{ sysctl_settings_routing }}" diff --git a/roles/network-routing/templates/ffmwu-add-ip-rules.sh.j2 b/roles/network-routing/templates/ffmwu-add-ip-rules.sh.j2 new file mode 100644 index 0000000..7dcee4f --- /dev/null +++ b/roles/network-routing/templates/ffmwu-add-ip-rules.sh.j2 @@ -0,0 +1,82 @@ +#!/bin/sh +# +# {{ ansible_managed }} +# + +# Priority 7 - lookup rt_table mwu for all incoming traffic of freifunk related interfaces +{% for mesh in meshes %} +ip -4 rule add from {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup mwu priority 7 +ip -4 rule add to {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup mwu priority 7 +ip -4 rule add from all oif {{ mesh.id }}br lookup mwu priority 7 +{% for ula in mesh.ipv6_ula %} +ip -6 rule add from {{ ula }} lookup mwu priority 7 +ip -6 rule add to {{ ula }} lookup mwu priority 7 +{% endfor %} +{% for public in mesh.ipv6_public %} +ip -6 rule add from {{ public }} lookup mwu priority 7 +ip -6 rule add to {{ public }} lookup mwu priority 7 +{% endfor %} +ip -6 rule add from all oif {{ mesh.id }}br lookup mwu priority 7 +{% endfor %} + +# Priority 23 - lookup rt_table icvpn for all incoming traffic of freifunk bridges +{% for mesh in meshes %} +ip -4 rule add from {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup icvpn priority 23 +ip -4 rule add to {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup icvpn priority 23 +ip -4 rule add from all oif {{ mesh.id }}br lookup icvpn priority 23 +{% for ula in mesh.ipv6_ula %} +ip -6 rule add from {{ ula }} lookup icvpn priority 23 +ip -6 rule add to {{ ula }} lookup icvpn priority 23 +{% endfor %} +{% for public in mesh.ipv6_public %} +ip -6 rule add from {{ public }} lookup icvpn priority 23 +ip -6 rule add to {{ public }} lookup icvpn priority 23 +{% endfor %} +ip -6 rule add from all oif {{ mesh.id }}br lookup icvpn priority 23 +{% endfor %} +ip -4 rule add from all oif icvpn lookup icvpn priority 23 +ip -6 rule add from all oif icvpn lookup icvpn priority 23 + +# Priority 41 - lookup rt_table internet for all incoming traffic of freifunk bridges +{% for mesh in meshes %} +ip -4 rule add from {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup internet priority 41 +{% for ula in mesh.ipv6_ula %} +ip -6 rule add from {{ ula }} lookup internet priority 41 +ip -6 rule add to {{ ula }} lookup internet priority 41 +{% endfor %} +{% for public in mesh.ipv6_public %} +ip -6 rule add from {{ public }} lookup internet priority 41 +ip -6 rule add to {{ public }} lookup internet priority 41 +{% endfor %} +ip -6 rule add from all oif {{ mesh.id }}br lookup internet priority 41 +{% endfor %} +ip -4 rule add from {{ ffrl_public_ipv4_nat | ipaddr('host') }} lookup internet priority 41 +ip -4 rule add to {{ ffrl_public_ipv4_nat | ipaddr('host') }} lookup internet priority 41 + +# Priority 61 - at this point this is the end of policy routing for freifunk related routes +{% for mesh in meshes %} +ip -4 rule add from all iif {{ mesh.id }}br type unreachable priority 61 +ip -6 rule add from all iif {{ mesh.id }}br type unreachable priority 61 +{% endfor %} +ip -4 rule add from all iif icvpn type unreachable priority 61 +ip -4 rule add from all iif {{ ansible_default_ipv4.interface }} type unreachable priority 61 +{% for server_id, server_value in ffrl_exit_server.iteritems() %} +ip -4 rule add from all iif {{ server_id }} type unreachable priority 61 +ip -6 rule add from all iif {{ server_id }} type unreachable priority 61 +{% endfor %} +ip -6 rule add from all iif icvpn type unreachable priority 61 +ip -6 rule add from all iif {{ ansible_default_ipv6.interface }} type unreachable priority 61 +{% for mesh in meshes %} +{% for public in mesh.ipv6_public %} +ip -6 rule add from {{ public }} type unreachable priority 61 +ip -6 rule add to {{ public }} type unreachable priority 61 +{% endfor %} +{% endfor %} + +# Priority 107 - lookup policies for the gateway host self originating traffic +ip -4 rule add from all lookup mwu priority 107 +ip -4 rule add from all lookup icvpn priority 107 +ip -6 rule add from all lookup mwu priority 107 +ip -6 rule add from all lookup icvpn priority 107 + +exit 0 diff --git a/roles/network-routing/templates/ffmwu-add-static-routes.sh.j2 b/roles/network-routing/templates/ffmwu-add-static-routes.sh.j2 new file mode 100644 index 0000000..07834e8 --- /dev/null +++ b/roles/network-routing/templates/ffmwu-add-static-routes.sh.j2 @@ -0,0 +1,66 @@ +#!/bin/sh +# +# {{ ansible_managed }} +# + +{% for mesh in meshes %} +# static {{ mesh.site_name }} routes for rt_table mwu +/sbin/ip -4 route add {{ mesh.ipv4_network }} proto static dev {{ mesh.id }}br table mwu +{% for ula in mesh.ipv6_ula %} +/sbin/ip -6 route add {{ ula | ipaddr('net') | ipsubnet(64, 0) | ipaddr('subnet') }} proto static dev {{ mesh.id }}br table mwu +{% endfor %} +{% for public in mesh.ipv6_public %} +/sbin/ip -6 route add {{ public | ipaddr('net') | ipsubnet(64, 0) | ipaddr('subnet') }} proto static dev {{ mesh.id }}br table mwu +/sbin/ip -6 route add {{ public | ipaddr('net') | ipsubnet(56, magic) | ipsubnet(64, 0) | ipaddr('subnet') }} proto static dev {{ mesh.id }}br table mwu +{% endfor %} +{% if not loop.last %} + +{% endif %} +{% endfor %} + +# static blackhole routes for rt_table internet +/sbin/ip -4 route add blackhole 0.0.0.0/8 table internet +/sbin/ip -4 route add blackhole 10.0.0.0/8 table internet +/sbin/ip -4 route add blackhole 100.64.0.0/10 table internet +/sbin/ip -4 route add blackhole 127.0.0.0/8 table internet +/sbin/ip -4 route add blackhole 169.254.0.0/16 table internet +/sbin/ip -4 route add blackhole 172.16.0.0/12 table internet +/sbin/ip -4 route add blackhole 192.0.0.0/24 table internet +/sbin/ip -4 route add blackhole 192.0.2.0/24 table internet +/sbin/ip -4 route add blackhole 192.88.99.0/24 table internet +/sbin/ip -4 route add blackhole 192.168.0.0/16 table internet +/sbin/ip -4 route add blackhole 198.18.0.0/15 table internet +/sbin/ip -4 route add blackhole 198.51.100.0/24 table internet +/sbin/ip -4 route add blackhole 203.0.113.0/24 table internet +/sbin/ip -4 route add blackhole 224.0.0.0/4 table internet +/sbin/ip -4 route add blackhole 240.0.0.0/4 table internet +/sbin/ip -4 route add blackhole 255.255.255.255/32 table internet +/sbin/ip -6 route add blackhole fec0::/10 table internet +/sbin/ip -6 route add blackhole fc00::/7 table internet +/sbin/ip -6 route add blackhole ff00::/8 table internet +/sbin/ip -6 route add blackhole ::/96 table internet +/sbin/ip -6 route add blackhole 0:0:0:0:0:ffff::/96 table internet + +# static blackhole routes for rt_table main +/sbin/ip -4 route add blackhole 0.0.0.0/8 table main +/sbin/ip -4 route add blackhole 10.0.0.0/8 table main +/sbin/ip -4 route add blackhole 100.64.0.0/10 table main +/sbin/ip -4 route add blackhole 127.0.0.0/8 table main +/sbin/ip -4 route add blackhole 169.254.0.0/16 table main +/sbin/ip -4 route add blackhole 172.16.0.0/12 table main +/sbin/ip -4 route add blackhole 192.0.0.0/24 table main +/sbin/ip -4 route add blackhole 192.0.2.0/24 table main +/sbin/ip -4 route add blackhole 192.88.99.0/24 table main +/sbin/ip -4 route add blackhole 192.168.0.0/16 table main +/sbin/ip -4 route add blackhole 198.18.0.0/15 table main +/sbin/ip -4 route add blackhole 198.51.100.0/24 table main +/sbin/ip -4 route add blackhole 203.0.113.0/24 table main +/sbin/ip -4 route add blackhole 224.0.0.0/4 table main +/sbin/ip -4 route add blackhole 240.0.0.0/4 table main +/sbin/ip -4 route add blackhole 255.255.255.255/32 table main +/sbin/ip -6 route add blackhole fec0::/10 table main +/sbin/ip -6 route add blackhole fc00::/7 table main +/sbin/ip -6 route add blackhole ff00::/8 table main +/sbin/ip -6 route add blackhole ::/96 table main +/sbin/ip -6 route add blackhole 0:0:0:0:0:ffff::/96 table main +/sbin/ip -6 route add blackhole ::/0 table main diff --git a/roles/network-routing/templates/ffmwu-del-ip-rules.sh.j2 b/roles/network-routing/templates/ffmwu-del-ip-rules.sh.j2 new file mode 100644 index 0000000..8fcfd36 --- /dev/null +++ b/roles/network-routing/templates/ffmwu-del-ip-rules.sh.j2 @@ -0,0 +1,82 @@ +#!/bin/sh +# +# {{ ansible_managed }} +# + +# Priority 7 - lookup rt_table mwu for all incoming traffic of freifunk related interfaces +{% for mesh in meshes %} +ip -4 rule del from {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup mwu priority 7 +ip -4 rule del to {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup mwu priority 7 +ip -4 rule del from all oif {{ mesh.id }}br lookup mwu priority 7 +{% for ula in mesh.ipv6_ula %} +ip -6 rule del from {{ ula }} lookup mwu priority 7 +ip -6 rule del to {{ ula }} lookup mwu priority 7 +{% endfor %} +{% for public in mesh.ipv6_public %} +ip -6 rule del from {{ public }} lookup mwu priority 7 +ip -6 rule del to {{ public }} lookup mwu priority 7 +{% endfor %} +ip -6 rule del from all oif {{ mesh.id }}br lookup mwu priority 7 +{% endfor %} + +# Priority 23 - lookup rt_table icvpn for all incoming traffic of freifunk bridges +{% for mesh in meshes %} +ip -4 rule del from {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup icvpn priority 23 +ip -4 rule del to {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup icvpn priority 23 +ip -4 rule del from all oif {{ mesh.id }}br lookup icvpn priority 23 +{% for ula in mesh.ipv6_ula %} +ip -6 rule del from {{ ula }} lookup icvpn priority 23 +ip -6 rule del to {{ ula }} lookup icvpn priority 23 +{% endfor %} +{% for public in mesh.ipv6_public %} +ip -6 rule del from {{ public }} lookup icvpn priority 23 +ip -6 rule del to {{ public }} lookup icvpn priority 23 +{% endfor %} +ip -6 rule del from all oif {{ mesh.id }}br lookup icvpn priority 23 +{% endfor %} +ip -4 rule del from all oif icvpn lookup icvpn priority 23 +ip -6 rule del from all oif icvpn lookup icvpn priority 23 + +# Priority 41 - lookup rt_table internet for all incoming traffic of freifunk bridges +{% for mesh in meshes %} +ip -4 rule del from {{ mesh.ipv4_network | ipaddr('network') }}/16 lookup internet priority 41 +{% for ula in mesh.ipv6_ula %} +ip -6 rule del from {{ ula }} lookup internet priority 41 +ip -6 rule del to {{ ula }} lookup internet priority 41 +{% endfor %} +{% for public in mesh.ipv6_public %} +ip -6 rule del from {{ public }} lookup internet priority 41 +ip -6 rule del to {{ public }} lookup internet priority 41 +{% endfor %} +ip -6 rule del from all oif {{ mesh.id }}br lookup internet priority 41 +{% endfor %} +ip -4 rule del from {{ ffrl_public_ipv4_nat | ipaddr('host') }} lookup internet priority 41 +ip -4 rule del to {{ ffrl_public_ipv4_nat | ipaddr('host') }} lookup internet priority 41 + +# Priority 61 - at this point this is the end of policy routing for freifunk related routes +{% for mesh in meshes %} +ip -4 rule del from all iif {{ mesh.id }}br type unreachable priority 61 +ip -6 rule del from all iif {{ mesh.id }}br type unreachable priority 61 +{% endfor %} +ip -4 rule del from all iif icvpn type unreachable priority 61 +ip -4 rule del from all iif {{ ansible_default_ipv4.interface }} type unreachable priority 61 +{% for server_id, server_value in ffrl_exit_server.iteritems() %} +ip -4 rule del from all iif {{ server_id }} type unreachable priority 61 +ip -6 rule del from all iif {{ server_id }} type unreachable priority 61 +{% endfor %} +ip -6 rule del from all iif icvpn type unreachable priority 61 +ip -6 rule del from all iif {{ ansible_default_ipv6.interface }} type unreachable priority 61 +{% for mesh in meshes %} +{% for public in mesh.ipv6_public %} +ip -6 rule del from {{ public }} type unreachable priority 61 +ip -6 rule del to {{ public }} type unreachable priority 61 +{% endfor %} +{% endfor %} + +# Priority 107 - lookup policies for the gateway host self originating traffic +ip -4 rule del from all lookup mwu priority 107 +ip -4 rule del from all lookup icvpn priority 107 +ip -6 rule del from all lookup mwu priority 107 +ip -6 rule del from all lookup icvpn priority 107 + +exit 0 diff --git a/roles/network-routing/templates/ffmwu-del-static-routes.sh.j2 b/roles/network-routing/templates/ffmwu-del-static-routes.sh.j2 new file mode 100644 index 0000000..1a71a32 --- /dev/null +++ b/roles/network-routing/templates/ffmwu-del-static-routes.sh.j2 @@ -0,0 +1,66 @@ +#!/bin/sh +# +# {{ ansible_managed }} +# + +{% for mesh in meshes %} +# static {{ mesh.site_name }} routes for rt_table mwu +/sbin/ip -4 route del {{ mesh.ipv4_network }} proto static dev {{ mesh.id }}br table mwu +{% for ula in mesh.ipv6_ula %} +/sbin/ip -6 route del {{ ula | ipaddr('net') | ipsubnet(64, 0) }} proto static dev {{ mesh.id }}br table mwu +{% endfor %} +{% for public in mesh.ipv6_public %} +/sbin/ip -6 route del {{ public | ipaddr('net') | ipsubnet(64, 0) }} proto static dev {{ mesh.id }}br table mwu +/sbin/ip -6 route del {{ public | ipaddr('net') | ipsubnet(64, magic) }} proto static dev {{ mesh.id }}br table mwu +{% endfor %} +{% if not loop.last %} + +{% endif %} +{% endfor %} + +# static blackhole routes for rt_table internet +/sbin/ip -4 route del blackhole 0.0.0.0/8 table internet +/sbin/ip -4 route del blackhole 10.0.0.0/8 table internet +/sbin/ip -4 route del blackhole 100.64.0.0/10 table internet +/sbin/ip -4 route del blackhole 127.0.0.0/8 table internet +/sbin/ip -4 route del blackhole 169.254.0.0/16 table internet +/sbin/ip -4 route del blackhole 172.16.0.0/12 table internet +/sbin/ip -4 route del blackhole 192.0.0.0/24 table internet +/sbin/ip -4 route del blackhole 192.0.2.0/24 table internet +/sbin/ip -4 route del blackhole 192.88.99.0/24 table internet +/sbin/ip -4 route del blackhole 192.168.0.0/16 table internet +/sbin/ip -4 route del blackhole 198.18.0.0/15 table internet +/sbin/ip -4 route del blackhole 198.51.100.0/24 table internet +/sbin/ip -4 route del blackhole 203.0.113.0/24 table internet +/sbin/ip -4 route del blackhole 224.0.0.0/4 table internet +/sbin/ip -4 route del blackhole 240.0.0.0/4 table internet +/sbin/ip -4 route del blackhole 255.255.255.255/32 table internet +/sbin/ip -6 route del blackhole fec0::/10 table internet +/sbin/ip -6 route del blackhole fc00::/7 table internet +/sbin/ip -6 route del blackhole ff00::/8 table internet +/sbin/ip -6 route del blackhole ::/96 table internet +/sbin/ip -6 route del blackhole 0:0:0:0:0:ffff::/96 table internet + +# static blackhole routes for rt_table main +/sbin/ip -4 route del blackhole 0.0.0.0/8 table main +/sbin/ip -4 route del blackhole 10.0.0.0/8 table main +/sbin/ip -4 route del blackhole 100.64.0.0/10 table main +/sbin/ip -4 route del blackhole 127.0.0.0/8 table main +/sbin/ip -4 route del blackhole 169.254.0.0/16 table main +/sbin/ip -4 route del blackhole 172.16.0.0/12 table main +/sbin/ip -4 route del blackhole 192.0.0.0/24 table main +/sbin/ip -4 route del blackhole 192.0.2.0/24 table main +/sbin/ip -4 route del blackhole 192.88.99.0/24 table main +/sbin/ip -4 route del blackhole 192.168.0.0/16 table main +/sbin/ip -4 route del blackhole 198.18.0.0/15 table main +/sbin/ip -4 route del blackhole 198.51.100.0/24 table main +/sbin/ip -4 route del blackhole 203.0.113.0/24 table main +/sbin/ip -4 route del blackhole 224.0.0.0/4 table main +/sbin/ip -4 route del blackhole 240.0.0.0/4 table main +/sbin/ip -4 route del blackhole 255.255.255.255/32 table main +/sbin/ip -6 route del blackhole fec0::/10 table main +/sbin/ip -6 route del blackhole fc00::/7 table main +/sbin/ip -6 route del blackhole ff00::/8 table main +/sbin/ip -6 route del blackhole ::/96 table main +/sbin/ip -6 route del blackhole 0:0:0:0:0:ffff::/96 table main +/sbin/ip -6 route del blackhole ::/0 table main diff --git a/roles/network-routing/templates/ffmwu-ip-rules.service.j2 b/roles/network-routing/templates/ffmwu-ip-rules.service.j2 new file mode 100644 index 0000000..0ef051a --- /dev/null +++ b/roles/network-routing/templates/ffmwu-ip-rules.service.j2 @@ -0,0 +1,12 @@ +[Unit] +Description=Manage Freifunk MWU IP rules +After=network-online.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/local/bin/ffmwu-add-ip-rules.sh +ExecStop=/usr/local/bin/ffmwu-del-ip-rules.sh + +[Install] +WantedBy=multi-user.target diff --git a/roles/network-routing/templates/ffmwu-static-routes.service.j2 b/roles/network-routing/templates/ffmwu-static-routes.service.j2 new file mode 100644 index 0000000..e793f81 --- /dev/null +++ b/roles/network-routing/templates/ffmwu-static-routes.service.j2 @@ -0,0 +1,12 @@ +[Unit] +Description=Manage Freifunk MWU static routes +After=network-online.target networking.service + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/local/bin/ffmwu-add-static-routes.sh +ExecStop=/usr/local/bin/ffmwu-del-static-routes.sh + +[Install] +WantedBy=multi-user.target diff --git a/roles/network-routing/vars/main.yml b/roles/network-routing/vars/main.yml new file mode 100644 index 0000000..97dd4ea --- /dev/null +++ b/roles/network-routing/vars/main.yml @@ -0,0 +1,14 @@ +--- +sysctl_settings_routing: + - name: net.ipv4.ip_forward + value: 1 + - name: net.ipv4.conf.default.rp_filter + value: 0 + - name: net.ipv4.conf.all.rp_filter + value: 0 + - name: net.ipv6.conf.all.forwarding + value: 1 + - name: net.ipv6.conf.all.accept_ra + value: 0 + - name: net.ipv6.conf.default.accept_ra + value: 0 diff --git a/roles/packages/tasks/main.yml b/roles/packages/tasks/main.yml index 62beb1d..81c049c 100644 --- a/roles/packages/tasks/main.yml +++ b/roles/packages/tasks/main.yml @@ -21,7 +21,6 @@ with_items: "{{ (pkg_repo_list|default({})).repo_keys | default([]) }}" loop_control: loop_var: pkg_item - become: True # see defaults in with - when: (pkg_repo_list is defined) and (pkg_repo_list.repo_keys is defined) - name: ensure defined apt repos @@ -33,7 +32,6 @@ with_items: "{{ (pkg_repo_list|default({})).repos | default([]) }}" loop_control: loop_var: pkg_item - become: True # see defaults in with - when: (pkg_repo_list is defined) and (pkg_repo_list.repos is defined) # see defaults in with - when: pkg_repo_list is defined @@ -48,7 +46,6 @@ with_items: "{{meshing_pkg_pkg_list | default([])}}" loop_control: loop_var: mwu_m_item - become: True # see default in with - when: meshing_pkg_pkg_list is defined - name: ensure defined python libs @@ -56,7 +53,6 @@ with_items: "{{meshing_pkg_pip_list | default([])}}" loop_control: loop_var: mwu_m_item - become: True # see default in with - when: meshing_pkg_pip_list is defined when: (really_do is defined) and (really_do) diff --git a/roles/prerequisites/README.md b/roles/prerequisites/README.md new file mode 100644 index 0000000..5cd087a --- /dev/null +++ b/roles/prerequisites/README.md @@ -0,0 +1,18 @@ +# Ansible role prerequisites + +Diese Ansible role prüft ob die Voraussetzungen für ein Freifunk Gateway erfüllt sind. + +- Forward-DNS Eintrag $FQDN == ausgelesener IPv4-Adresse +- Forward-DNS Eintrag $FQDN == ausgelesener IPv6-Adresse +- CNAME Eintrag gate$magic.freifunk-mwu.de == $FQDN +- CNAME Eintrag icvpn$magic.freifunk-mwu.de == $FQDN +- Linux Distribution == Debian +- Debian Version == 9 + +## Benötigte Variablen + +Die folgenden Variablen werden über einen DNS Lookup gesetzt: +- Variable `dns_host_ipv4_address` (Rollen-Variable) +- Variable `dns_host_ipv6_address` (Rollen-Variable) +- Variable `dns_gate_num_cname` (Rollen-Variable) +- Variable `dns_gate_icvpn_cname` (Rollen-Variable) diff --git a/roles/prerequisites/tasks/main.yml b/roles/prerequisites/tasks/main.yml new file mode 100755 index 0000000..43f2cb9 --- /dev/null +++ b/roles/prerequisites/tasks/main.yml @@ -0,0 +1,15 @@ +--- + +- name: Check DNS entries and target distribution + assert: + that: + - "dns_host_ipv4_address in ansible_all_ipv4_addresses" + - "dns_host_ipv6_address in ansible_all_ipv6_addresses" + - "dns_gate_num_cname == inventory_hostname" + - "dns_gate_icvpn_cname == inventory_hostname" + - "ansible_distribution == 'Debian'" + - "ansible_distribution_major_version == '9'" + +- name: Test root access for admin account + command: "true" + changed_when: False diff --git a/roles/prerequisites/vars/main.yml b/roles/prerequisites/vars/main.yml new file mode 100644 index 0000000..6cb0cdd --- /dev/null +++ b/roles/prerequisites/vars/main.yml @@ -0,0 +1,8 @@ +--- +dns_gate_num: "gate{{ magic }}.{{ http_domain_external }}" +dns_gate_icvpn: "icvpn{{ magic }}.{{ http_domain_external }}" + +dns_host_ipv4_address: "{{ lookup('dig', inventory_hostname, 'qtype=A') }}" +dns_host_ipv6_address: "{{ lookup('dig', inventory_hostname, 'qtype=AAAA') }}" +dns_gate_num_cname: "{{ lookup('dig', dns_gate_num, 'qtype=CNAME') | regex_replace('\\.$') }}" +dns_gate_icvpn_cname: "{{ lookup('dig', dns_gate_icvpn, 'qtype=CNAME') | regex_replace('\\.$') }}" diff --git a/roles/server-apt-repos/README.md b/roles/server-apt-repos/README.md new file mode 100644 index 0000000..2a1e2f9 --- /dev/null +++ b/roles/server-apt-repos/README.md @@ -0,0 +1,13 @@ +# Ansible role server-apt-repos + +Diese Ansible role konfiguriert zusätzliche APT Repositories. + +- installiert Freifunk MWU Debian APT PGP Key +- konfiguriert APT Repositories aus der Liste `repos` + +## Benötigte Variablen + +- Liste `repos` (Rollen Variable) + - `name`: String == Name der Konfigurationsdatei unter /etc/apt/sources.list.d + - `repo`: String + - `update_cache`: yes|no diff --git a/roles/server-apt-repos/tasks/main.yml b/roles/server-apt-repos/tasks/main.yml new file mode 100644 index 0000000..f6f0e26 --- /dev/null +++ b/roles/server-apt-repos/tasks/main.yml @@ -0,0 +1,22 @@ +--- +- name: ensure dirmngr and apt-transport-https are installed + package: + name: "{{ item }}" + state: present + with_items: + - dirmngr + - apt-transport-https + +- name: ensure apt key for freifunk-mwu is present + apt_key: + state: present + id: 83A70084 + url: "http://repo.freifunk-mwu.de/83A70084.gpg.key" + +- name: ensure needed apt repos are present + apt_repository: + state: present + repo: "{{ item.repo }}" + update_cache: "{{ item.update_cache }}" + filename: "{{ item.name }}" + with_items: "{{ repos }}" diff --git a/roles/server-apt-repos/vars/main.yml b/roles/server-apt-repos/vars/main.yml new file mode 100644 index 0000000..1c355b4 --- /dev/null +++ b/roles/server-apt-repos/vars/main.yml @@ -0,0 +1,8 @@ +--- +repos: + - name: freifunk + repo: 'deb http://repo.freifunk-mwu.de/debian stretch main' + update_cache: yes + - name: freifunk + repo: 'deb-src http://repo.freifunk-mwu.de/debian stretch main' + update_cache: yes diff --git a/roles/server-basic/README.md b/roles/server-basic/README.md new file mode 100644 index 0000000..2761041 --- /dev/null +++ b/roles/server-basic/README.md @@ -0,0 +1,14 @@ +# Ansible role server-basic + +Diese Ansible role installiert Pakete, die auf allen MWU-Server benötigt werden. + +- installiert Pakete, die auf allen Servern benötigt werden +- setzt vim als default Editor +- setzt die Zeitzone auf Europe/Berlin +- generiert und setzt default locale +- konfiguriert das dummy Kernel Modul + +## Benötigte Variablen + +- Liste `packages` (Rollen Variable) +- Variable `default_locale` (Rollen-Variable) diff --git a/roles/server-basic/tasks/main.yml b/roles/server-basic/tasks/main.yml new file mode 100644 index 0000000..f3fcd68 --- /dev/null +++ b/roles/server-basic/tasks/main.yml @@ -0,0 +1,43 @@ +--- +- name: ensure common packages are installed + package: + name: "{{ item }}" + state: present + with_items: "{{ packages }}" + +- name: ensure vim is default editor + alternatives: + name: editor + path: /usr/bin/vim.basic + +- name: ensure default locale is installed + locale_gen: + name: "{{ default_locale }}" + state: present + +- name: ensure default locale is set + command: "/usr/bin/localectl set-locale LANG={{ default_locale }}" + changed_when: false + +- name: set timezone to Europe/Berlin + timezone: + name: Europe/Berlin + +- name: create ffmwu custom config dir + file: + path: /home/admin/.config + state: directory + owner: admin + group: admin + mode: 0750 + +- name: configure dummy module to load on system boot + template: + src: dummy.module.conf.j2 + dest: /etc/modules-load.d/dummy.conf + +- name: load dummy module + modprobe: + name: "dummy" + state: present + params: "numdummies=0" diff --git a/roles/server-basic/templates/dummy.module.conf.j2 b/roles/server-basic/templates/dummy.module.conf.j2 new file mode 100644 index 0000000..4beefe7 --- /dev/null +++ b/roles/server-basic/templates/dummy.module.conf.j2 @@ -0,0 +1,5 @@ +# +# Load dummy module on system boot +# {{ ansible_managed }} +# +dummy diff --git a/roles/server-basic/vars/main.yml b/roles/server-basic/vars/main.yml new file mode 100644 index 0000000..722d395 --- /dev/null +++ b/roles/server-basic/vars/main.yml @@ -0,0 +1,15 @@ +--- +packages: + - apt-transport-https + - bridge-utils + - ethtool + - ifupdown2 + - man-db + - mlocate + - mosh + - python3-yaml + - sudo + - sysfsutils + - vim + +default_locale: "en_US.UTF-8" diff --git a/roles/service-bind-slave/README.md b/roles/service-bind-slave/README.md new file mode 100644 index 0000000..42d4f12 --- /dev/null +++ b/roles/service-bind-slave/README.md @@ -0,0 +1,38 @@ +# Ansible role service-bind-slave + +Diese Ansible role installiert und konfiguriert den DNS Server BIND auf einem Freifunk Gateway. +Die Gateways agieren lediglich als Slave-DNS Server. + +- installiert BIND Pakete +- schreibt named.conf + named.conf.options + named.conf.logging +- schreibt named.conf.icvpn nur wenn noch nicht vorhanden +- schreibt für jedes Mesh eine Konfigurationsdatei named.conf.$site_code + - Forward-Zones müssen im `meshes`-Dict angegeben werden + - Reverse DNS Zones werden automatisch aus den benutzten IP-Subnetzen erzeugt + +## Benötigte Variablen + +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + site_code: # string + ipv4_network: + ipv6_ula: + - # ULA-Prefix + - ... + dns: + master: # IP-Adresse des DNS Masters + forward_zones: + - name: $zone # DNS-Domain + master: # optional: IP-Adresse des DNS Masters, wenn die vom übergeordneten abweicht. + +´´´ +- Variable `icvpn_ipv4_transfer_net` +- Variable `icvpn_ipv6_transfer_net` +- Host Variable `magic` + +## Benötigte roles + +- git-repos diff --git a/roles/service-bind-slave/meta/main.yml b/roles/service-bind-slave/meta/main.yml new file mode 100644 index 0000000..9a46e8e --- /dev/null +++ b/roles/service-bind-slave/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: git-repos } diff --git a/roles/service-bind-slave/tasks/main.yml b/roles/service-bind-slave/tasks/main.yml new file mode 100644 index 0000000..d985682 --- /dev/null +++ b/roles/service-bind-slave/tasks/main.yml @@ -0,0 +1,91 @@ +--- +- name: install dns server packages + package: + name: "{{ item }}" + state: present + with_items: + - bind9 + - bind9-doc + - bind9utils + +- name: write named.conf + template: + src: named.conf.j2 + dest: /etc/bind/named.conf + owner: root + group: bind + mode: 0644 + notify: restart bind9 + +- name: write named.conf.options + template: + src: named.conf.options.j2 + dest: /etc/bind/named.conf.options + owner: root + group: bind + mode: 0644 + notify: restart bind9 + +- name: write named.conf.logging + template: + src: named.conf.logging.j2 + dest: /etc/bind/named.conf.logging + owner: root + group: bind + mode: 0644 + notify: restart bind9 + +- name: write named.conf for meshes + template: + src: named.conf.mesh.j2 + dest: /etc/bind/named.conf.{{ item.site_code }} + owner: root + group: bind + mode: 0644 + notify: restart bind9 + with_items: "{{ meshes }}" + +- name: write initial icvpn bind config + shell: /usr/bin/python3 /home/admin/clones/icvpn-scripts/mkdns -f bind -x mwu -x bingen -s /home/admin/clones/icvpn-meta > /etc/bind/named.conf.icvpn + args: + chdir: /home/admin/clones/icvpn-scripts + creates: /etc/bind/named.conf.icvpn + notify: restart bind9 + +- name: set file attributes for icvpn config + file: + path: /etc/bind/named.conf.icvpn + mode: 0644 + owner: admin + group: bind + notify: restart bind9 + +- name: write systemd unit icvpn-dns-update.service + template: + src: icvpn-dns-update.service.j2 + dest: /etc/systemd/system/icvpn-dns-update.service + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: write systemd timer icvpn-dns-update.timer + template: + src: icvpn-dns-update.timer.j2 + dest: /etc/systemd/system/icvpn-dns-update.timer + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: configure systemd unit/timer icvpn-dns-update + systemd: + name: icvpn-dns-update.timer + enabled: yes + state: started + +- name: enable systemd unit bind9 + systemd: + name: bind9 + enabled: yes + state: started diff --git a/roles/service-bind-slave/templates/icvpn-dns-update.service.j2 b/roles/service-bind-slave/templates/icvpn-dns-update.service.j2 new file mode 100644 index 0000000..3a21e89 --- /dev/null +++ b/roles/service-bind-slave/templates/icvpn-dns-update.service.j2 @@ -0,0 +1,10 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Update icvpn bind configuration + +[Service] +ExecStart=/home/admin/clones/backend-scripts/gen_icvpn_dns_gw.sh +User=admin +Group=admin diff --git a/roles/service-bind-slave/templates/icvpn-dns-update.timer.j2 b/roles/service-bind-slave/templates/icvpn-dns-update.timer.j2 new file mode 100644 index 0000000..261691c --- /dev/null +++ b/roles/service-bind-slave/templates/icvpn-dns-update.timer.j2 @@ -0,0 +1,12 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Timer which schedules icvpn-bind-update.service + +[Timer] +OnBootSec=2h +OnUnitActiveSec=2d + +[Install] +WantedBy=timers.target diff --git a/roles/service-bind-slave/templates/named.conf.j2 b/roles/service-bind-slave/templates/named.conf.j2 new file mode 100644 index 0000000..e7d3814 --- /dev/null +++ b/roles/service-bind-slave/templates/named.conf.j2 @@ -0,0 +1,11 @@ +// +// {{ ansible_managed }} +// + +include "/etc/bind/named.conf.options"; +include "/etc/bind/named.conf.default-zones"; +include "/etc/bind/named.conf.logging"; +{% for mesh in meshes %} +include "/etc/bind/named.conf.{{ mesh.site_code }}"; +{% endfor %} +include "/etc/bind/named.conf.icvpn"; diff --git a/roles/service-bind-slave/templates/named.conf.logging.j2 b/roles/service-bind-slave/templates/named.conf.logging.j2 new file mode 100644 index 0000000..21908ef --- /dev/null +++ b/roles/service-bind-slave/templates/named.conf.logging.j2 @@ -0,0 +1,9 @@ +// +// {{ ansible_managed }} +// + +logging { + channel null { null; }; + category default { null; }; +}; + diff --git a/roles/service-bind-slave/templates/named.conf.mesh.j2 b/roles/service-bind-slave/templates/named.conf.mesh.j2 new file mode 100644 index 0000000..3a9a77a --- /dev/null +++ b/roles/service-bind-slave/templates/named.conf.mesh.j2 @@ -0,0 +1,58 @@ +// +// {{ ansible_managed }} +// + +// ACLs +masters "ns-master-{{ item.site_code }}" { + {{ item.dns.master }}; +}; + +{% for zone in item.dns.forward_zones %} +{% if zone.master is defined %} +masters "ns-master-{{ zone.name }}" { + {{ zone.master }}; +}; + +{% endif %} +{% endfor %} + +acl "intern-{{ item.site_code }}" { + {{ item.ipv4_network | ipaddr('net') | ipaddr('network/prefix') }}; +{% for prefix in item.ipv6_ula %} + {{ prefix | ipaddr('net') | ipaddr('network/prefix') }}; +{% endfor %} +}; + +// DNS forward zones for {{ item.site_code }} +{% for zone in item.dns.forward_zones %} +zone "{{ zone.name }}." { + type slave; + file "{{ zone.name }}.db"; +{% if zone.master is defined %} + masters { ns-master-{{ zone.name }}; }; +{% else %} + masters { ns-master-{{ item.site_code }}; }; +{% endif %} +}; +{% if not loop.last %} + +{% endif %} +{% endfor %} + +// DNS reverse zones for {{ item.site_code }} +zone "{{ item.ipv4_network | ipaddr('net') | ipaddr('revdns') }}" { + type slave; + file "{{ item.ipv4_network | ipaddr('net') | ipaddr('revdns') }}"; + masters { ns-master-{{ item.site_code }}; }; +}; + +{% for prefix in item.ipv6_ula %} +zone "{{ prefix | ipaddr('net') | ipaddr('revdns') }}" { + type slave; + file "{{ prefix | ipaddr('net') | ipaddr('revdns') }}"; + masters { ns-master-{{ item.site_code }}; }; +}; +{% if not loop.last %} + +{% endif %} +{% endfor %} diff --git a/roles/service-bind-slave/templates/named.conf.options.j2 b/roles/service-bind-slave/templates/named.conf.options.j2 new file mode 100644 index 0000000..38edce5 --- /dev/null +++ b/roles/service-bind-slave/templates/named.conf.options.j2 @@ -0,0 +1,37 @@ +// +// {{ ansible_managed }} +// +options { + directory "/var/cache/bind"; + + dnssec-validation no; + auth-nxdomain no; + + allow-query { any; }; + allow-recursion { + 127.0.0.1; + ::1; +{% for mesh in meshes %} + intern-{{ mesh.site_code }}; +{% endfor %} + }; + allow-transfer { any; }; + + listen-on { + 127.0.0.1; +{% for mesh in meshes %} + {{ mesh.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') }}; +{% endfor %} + {{ icvpn_ipv4_transfer_net | ipaddr('net') | ipsubnet(24, 37) | ipaddr(magic) | ipaddr('address') }}; + }; + + listen-on-v6 { + ::1; +{% for mesh in meshes %} +{% for ip in mesh.ipv6_ula %} + {{ ip | ipaddr('net') | ipsubnet(64, 0) | ipaddr(magic) | ipaddr('address') }}; +{% endfor %} +{% endfor %} + {{ icvpn_ipv6_transfer_net | ipaddr('net') | ipsubnet(112, 37) | ipaddr(magic) | ipaddr('address') }}; + }; +}; diff --git a/roles/service-bird-ffrl/README.md b/roles/service-bird-ffrl/README.md new file mode 100644 index 0000000..78f98b3 --- /dev/null +++ b/roles/service-bird-ffrl/README.md @@ -0,0 +1,52 @@ +# Ansible role service-bird-ffrl + +Diese Ansible role ergänzt die benötigte bird + bird6 Konfiguration für den Internet-Uplink über Freifunk Rheinland. + +- schreibt ffrl_ipv4.conf + ffrl_ipv6.conf +- schreibt ffrl_ipv4_peers.conf + ffrl_ipv6_peers.conf + +## Benötigte Variablen + +- Variable `as_public_ffrl` # Public ASN Freifunk Rheinland +- Dictionary `meshes` +``` +meshes: + - id: xx +... + ipv6_public: + - # Public IPv6-Netzwerk +``` +- Host Dictionary `ffrl_exit_server` +´´´ +ffrl_exit_server: + ffrl-a-ak-ber: + public_ipv4_address: 185.66.195.0 + tunnel_ipv4_network: # Tunnel-Netzwerk in CIDR + tunnel_ipv6_network: # IPv6 Transfernetz + ffrl-b-ak-ber: + public_ipv4_address: 185.66.195.1 + tunnel_ipv4_network: + tunnel_ipv6_network: + ffrl-a-ix-dus: + public_ipv4_address: 185.66.193.0 + tunnel_ipv4_network: + tunnel_ipv6_network: + ffrl-b-ix-dus: + public_ipv4_address: 185.66.193.1 + tunnel_ipv4_network: + tunnel_ipv6_network: + ffrl-a-fra2-fra: + public_ipv4_address: 185.66.194.0 + tunnel_ipv4_network: + tunnel_ipv6_network: + ffrl-b-fra2-fra: + public_ipv4_address: 185.66.194.1 + tunnel_ipv4_network: + tunnel_ipv6_network: +´´´ +- Host Variable `ffrl_public_ipv4_nat` # Format ip-adresse/prefix +- Host Variable `magic` + +## Benötigte roles + +- service-bird diff --git a/roles/service-bird-ffrl/meta/main.yml b/roles/service-bird-ffrl/meta/main.yml new file mode 100644 index 0000000..04e04b1 --- /dev/null +++ b/roles/service-bird-ffrl/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: service-bird } diff --git a/roles/service-bird-ffrl/tasks/main.yml b/roles/service-bird-ffrl/tasks/main.yml new file mode 100644 index 0000000..400e414 --- /dev/null +++ b/roles/service-bird-ffrl/tasks/main.yml @@ -0,0 +1,36 @@ +--- +- name: write ffrl_ipv4.conf.j2 + template: + src: ffrl_ipv4.conf.j2 + dest: /etc/bird/ffrl_ipv4.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird + +- name: write ffrl_ipv6.conf.j2 + template: + src: ffrl_ipv6.conf.j2 + dest: /etc/bird/ffrl_ipv6.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird6 + +- name: write ffrl_ipv4_peers.conf + template: + src: ffrl_ipv4_peers.conf.j2 + dest: /etc/bird/ffrl_ipv4_peers.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird + +- name: write ffrl_ipv6_peers.conf + template: + src: ffrl_ipv6_peers.conf.j2 + dest: /etc/bird/ffrl_ipv6_peers.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird6 diff --git a/roles/service-bird-ffrl/templates/ffrl_ipv4.conf.j2 b/roles/service-bird-ffrl/templates/ffrl_ipv4.conf.j2 new file mode 100644 index 0000000..c20abc7 --- /dev/null +++ b/roles/service-bird-ffrl/templates/ffrl_ipv4.conf.j2 @@ -0,0 +1,74 @@ +# +# {{ ansible_managed }} +# + +# Variables +define ffrl_as = {{ as_public_ffrl }}; +define ffrl_nat_address = {{ ffrl_public_ipv4_nat | ipaddr('address') }}; + +# Routing Table +table ffrl; + +# Functions +function is_ffrl_nat() { + return net ~ [ + {{ ffrl_public_ipv4_nat | ipaddr('host') }} + ]; +} + +function is_ffrl_tunnel_nets() { + return net ~ [ +{% for peer_id, peer_value in ffrl_exit_server.iteritems() %} + {{ peer_value.tunnel_ipv4_network }}{{ "," if not loop.last else "" }} +{% endfor %} + ]; +} + +# Filters +filter ebgp_ffrl_import_filter { + if is_default() then accept; + reject; +} + +filter ebgp_ffrl_export_filter { + if is_ffrl_nat() then accept; + reject; +} + +# Protocols +protocol direct ffrl_nat { + table ffrl; + interface "ffrl-nat"; + import where is_ffrl_nat(); +} + +protocol direct ffrl_tunnels { + table ffrl; + interface "ffrl-*"; + import where is_ffrl_tunnel_nets(); +} + +protocol kernel kernel_ffrl { + scan time 30; + import none; + export filter { + krt_prefsrc = ffrl_nat_address; + accept; + }; + table ffrl; + kernel table ipt_internet; +}; + +# Templates +template bgp ffrl_uplink { + table ffrl; + local as mwu_as; + import keep filtered; + import filter ebgp_ffrl_import_filter; + export filter ebgp_ffrl_export_filter; + next hop self; + direct; +}; + +# Include FFRL IPv4 peers +include "ffrl_ipv4_peers.con?"; diff --git a/roles/service-bird-ffrl/templates/ffrl_ipv4_peers.conf.j2 b/roles/service-bird-ffrl/templates/ffrl_ipv4_peers.conf.j2 new file mode 100644 index 0000000..5f6f1fb --- /dev/null +++ b/roles/service-bird-ffrl/templates/ffrl_ipv4_peers.conf.j2 @@ -0,0 +1,13 @@ +# +# {{ ansible_managed }} +# + +{% for peer_id, peer_value in ffrl_exit_server.iteritems() %} +protocol bgp '{{ peer_id }}' from ffrl_uplink { + source address {{ peer_value.tunnel_ipv4_network | ipaddr('net') | ipaddr('1') | ipaddr('address') }}; + neighbor {{ peer_value.tunnel_ipv4_network | ipaddr('net') | ipaddr('address') }} as ffrl_as; +}; +{% if not loop.last %} + +{% endif %} +{% endfor %} diff --git a/roles/service-bird-ffrl/templates/ffrl_ipv6.conf.j2 b/roles/service-bird-ffrl/templates/ffrl_ipv6.conf.j2 new file mode 100644 index 0000000..57ed1d4 --- /dev/null +++ b/roles/service-bird-ffrl/templates/ffrl_ipv6.conf.j2 @@ -0,0 +1,80 @@ +# +# {{ ansible_managed }} +# + +# Variables +define ffrl_as = {{ as_public_ffrl }}; + +# Routing Table +table ffrl; + +# Functions +function is_ffrl_public_nets() { + return net ~ [ +{% for mesh in meshes %} +{% for prefix in mesh.ipv6_public %} + {{ prefix }}{48,56}{{ "," if not loop.last else "" }}{% endfor %}{{ "," if not loop.last else "" }} +{% endfor %} + ]; +} + +function is_ffrl_tunnel_nets() { + return net ~ [ +{% for peer_id, peer_value in ffrl_exit_server.iteritems() %} + {{ peer_value.tunnel_ipv6_network }}{{ "," if not loop.last else "" }} +{% endfor %} + ]; +} + +# Filters +filter ebgp_ffrl_import_filter { + if is_default() then accept; + reject; +} + +filter ebgp_ffrl_export_filter { + if is_ffrl_public_nets() then accept; + reject; +} + +# Protocols +protocol static ffrl_public_routes { + table ffrl; +{% for mesh in meshes %} +{% for prefix in mesh.ipv6_public %} + route {{ prefix }} reject; + route {{ prefix | ipaddr('net') | ipsubnet(56, magic) | ipaddr('network/prefix') }} reject; +{% endfor %} +{% endfor %} +} + +protocol direct ffrl_tunnels { + table ffrl; + interface "ffrl-*"; + import where is_ffrl_tunnel_nets(); +} + +protocol kernel kernel_ffrl { + scan time 30; + import none; + export filter { + if is_default() then accept; + reject; + }; + table ffrl; + kernel table ipt_internet; +}; + +# Templates +template bgp ffrl_uplink { + table ffrl; + local as mwu_as; + import keep filtered; + import filter ebgp_ffrl_import_filter; + export filter ebgp_ffrl_export_filter; + next hop self; + direct; +}; + +# Include FFRL IPv4 peers +include "ffrl_ipv6_peers.con?"; diff --git a/roles/service-bird-ffrl/templates/ffrl_ipv6_peers.conf.j2 b/roles/service-bird-ffrl/templates/ffrl_ipv6_peers.conf.j2 new file mode 100644 index 0000000..ef495ed --- /dev/null +++ b/roles/service-bird-ffrl/templates/ffrl_ipv6_peers.conf.j2 @@ -0,0 +1,13 @@ +# +# {{ ansible_managed }} +# + +{% for peer_id, peer_value in ffrl_exit_server.iteritems() %} +protocol bgp '{{ peer_id }}' from ffrl_uplink { + source address {{ peer_value.tunnel_ipv6_network | ipaddr('net') | ipaddr('2') | ipaddr('address') }}; + neighbor {{ peer_value.tunnel_ipv6_network | ipaddr('net') | ipaddr('1') | ipaddr('address') }} as ffrl_as; +}; +{% if not loop.last %} + +{% endif %} +{% endfor %} diff --git a/roles/service-bird-icvpn/README.md b/roles/service-bird-icvpn/README.md new file mode 100644 index 0000000..d999fc6 --- /dev/null +++ b/roles/service-bird-icvpn/README.md @@ -0,0 +1,19 @@ +# Ansible role service-bird-icvpn + +Diese Ansible role ergänzt die benötigte bird + bird6 Konfiguration für das Freifunk Intercity VPN. + +- installiert bird +- schreibt icvpn_ipv4.conf + icvpn_ipv6.conf +- schreibt initiale ICVPN peers config (nur wenn nicht vorhanden) +- schreibt initiale ICVPN ROA config (nur wenn nicht vorhanden) + +## Benötigte Variablen + +- Variable `icvpn_ipv4_transfer_net` # IPv4-Range des ICVPN Transfer Netzes +- Variable `icvpn_ipv6_transfer_net` # IPv6-Range des ICVPN Transfer Netzes +- Host Variable `magic` + +## Benötigte roles + +- git-repos +- service-bird diff --git a/roles/service-bird-icvpn/meta/main.yml b/roles/service-bird-icvpn/meta/main.yml new file mode 100644 index 0000000..0c405d4 --- /dev/null +++ b/roles/service-bird-icvpn/meta/main.yml @@ -0,0 +1,5 @@ +--- +dependencies: + - { role: git-repos } + - { role: service-tinc } + - { role: service-bird } diff --git a/roles/service-bird-icvpn/tasks/main.yml b/roles/service-bird-icvpn/tasks/main.yml new file mode 100644 index 0000000..6d50e99 --- /dev/null +++ b/roles/service-bird-icvpn/tasks/main.yml @@ -0,0 +1,92 @@ +--- +- name: generate initial icvpn_ipv4_peers.conf + shell: /usr/bin/python3 /home/admin/clones/icvpn-scripts/mkbgp -4 -f bird -x mwu -d ebgp_icvpn -s /home/admin/clones/icvpn-meta > /etc/bird/icvpn_ipv4_peers.conf + args: + chdir: /home/admin/clones/icvpn-scripts + creates: /etc/bird/icvpn_ipv4_peers.conf + notify: reload systemd unit bird + +- name: generate initial icvpn_ipv6_peers.conf + shell: /usr/bin/python3 /home/admin/clones/icvpn-scripts/mkbgp -6 -f bird -x mwu -d ebgp_icvpn -s /home/admin/clones/icvpn-meta > /etc/bird/icvpn_ipv6_peers.conf + args: + chdir: /home/admin/clones/icvpn-scripts + creates: /etc/bird/icvpn_ipv6_peers.conf + notify: reload systemd unit bird6 + +- name: generate initial icvpn_ipv4_roa.conf + shell: /usr/bin/python3 /home/admin/clones/icvpn-scripts/mkroa -4 -f bird -x mwu -m 20 -s /home/admin/clones/icvpn-meta > /etc/bird/icvpn_ipv4_roa.conf + args: + chdir: /home/admin/clones/icvpn-scripts + creates: /etc/bird/icvpn_ipv4_roa.conf + notify: reload systemd unit bird + +- name: generate initial icvpn_ipv6_roa.conf + shell: /usr/bin/python3 /home/admin/clones/icvpn-scripts/mkroa -6 -f bird -x mwu -m 64 -s /home/admin/clones/icvpn-meta > /etc/bird/icvpn_ipv6_roa.conf + args: + chdir: /home/admin/clones/icvpn-scripts + creates: /etc/bird/icvpn_ipv6_roa.conf + notify: reload systemd unit bird6 + +- name: write icvpn_ipv4.conf + template: + src: icvpn_ipv4.conf.j2 + dest: /etc/bird/icvpn_ipv4.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird + +- name: write icvpn_ipv6.conf + template: + src: icvpn_ipv6.conf.j2 + dest: /etc/bird/icvpn_ipv6.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird6 + +- name: set file attributes for ipv4 roa and peer config + file: + path: "{{ item }}" + mode: 0640 + owner: admin + group: bird + notify: reload systemd unit bird + with_items: + - /etc/bird/icvpn_ipv4_peers.conf + - /etc/bird/icvpn_ipv4_roa.conf + +- name: set file attributes for ipv6 roa and peer config + file: + path: "{{ item }}" + mode: 0640 + owner: admin + group: bird + notify: reload systemd unit bird6 + with_items: + - /etc/bird/icvpn_ipv6_peers.conf + - /etc/bird/icvpn_ipv6_roa.conf + +- name: write systemd unit icvpn-tinc-bgp-update.service + template: + src: icvpn-tinc-bgp-update.service.j2 + dest: /etc/systemd/system/icvpn-tinc-bgp-update.service + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: write systemd timer icvpn-tinc-bgp-update.timer + template: + src: icvpn-tinc-bgp-update.timer.j2 + dest: /etc/systemd/system/icvpn-tinc-bgp-update.timer + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: configure systemd unit/timer icvpn-tinc-bgp-update + systemd: + name: icvpn-tinc-bgp-update.timer + enabled: yes + state: started diff --git a/roles/service-bird-icvpn/templates/icvpn-tinc-bgp-update.service.j2 b/roles/service-bird-icvpn/templates/icvpn-tinc-bgp-update.service.j2 new file mode 100644 index 0000000..d4c964d --- /dev/null +++ b/roles/service-bird-icvpn/templates/icvpn-tinc-bgp-update.service.j2 @@ -0,0 +1,10 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Update tinc hosts and bgp peers for icvpn + +[Service] +ExecStart=/home/admin/clones/backend-scripts/gen_icvpn_bgp_gw.sh +User=admin +Group=admin diff --git a/roles/service-bird-icvpn/templates/icvpn-tinc-bgp-update.timer.j2 b/roles/service-bird-icvpn/templates/icvpn-tinc-bgp-update.timer.j2 new file mode 100644 index 0000000..b2c612e --- /dev/null +++ b/roles/service-bird-icvpn/templates/icvpn-tinc-bgp-update.timer.j2 @@ -0,0 +1,12 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Timer which schedules icvpn-tinc-bgp-update.service + +[Timer] +OnBootSec=1h +OnUnitActiveSec=2d + +[Install] +WantedBy=timers.target diff --git a/roles/service-bird-icvpn/templates/icvpn_ipv4.conf.j2 b/roles/service-bird-icvpn/templates/icvpn_ipv4.conf.j2 new file mode 100644 index 0000000..d5409db --- /dev/null +++ b/roles/service-bird-icvpn/templates/icvpn_ipv4.conf.j2 @@ -0,0 +1,75 @@ +# +# {{ ansible_managed }} +# + +# Variables +define icvpn_address = {{ icvpn_ipv4_transfer_net | ipaddr('net') | ipsubnet(24, 37) | ipaddr(magic) | ipaddr('address') }}; + +# ROA +roa table roa_icvpn { + include "icvpn_ipv4_roa.con?"; +} + +# Filters +filter icvpn_import_filter { + if is_mwu_self_nets() then reject; + if is_chaosvpn() then accept; + if roa_check(roa_icvpn) = ROA_VALID then { + if is_freifunk() then accept; + if is_dn42() then accept; + } else { + if roa_check(roa_icvpn) = ROA_UNKNOWN then { + if is_dn42() then { + print "ROA UNKNOWN for dn42 net, accepting: ", net, " ASN: ", bgp_path.last; + accept; + } + if is_freifunk() then { + print "ROA UNKNOWN for freifunk net, accepting: ", net, " ASN: ", bgp_path.last; + accept; + } + } + if roa_check(roa_icvpn) = ROA_INVALID then { + if is_freifunk() then { + print "ROA INVALID for freifunk net, accept: ", net, " ASN: ", bgp_path.last; + accept; + } + } + reject; + } + reject; +} + +# Protocols +protocol kernel kernel_mwu { + scan time 30; + import none; + export filter { + if is_mwu_self_nets() then + reject; + krt_prefsrc = icvpn_address; + accept; + }; + kernel table ipt_icvpn; +}; + +# Templates +template bgp ebgp_icvpn { + local icvpn_address as mwu_as; + import keep filtered on; + import filter icvpn_import_filter; + export filter { + if is_mwu_self_nets() then { + accept; + } + if source = RTS_BGP then { + if is_freifunk() || is_dn42() then { + accept; + } + } + reject; + }; + direct; +} + +# Include ICVPN IPv4 peers +include "icvpn_ipv4_peers.con?"; diff --git a/roles/service-bird-icvpn/templates/icvpn_ipv6.conf.j2 b/roles/service-bird-icvpn/templates/icvpn_ipv6.conf.j2 new file mode 100644 index 0000000..eb41c3f --- /dev/null +++ b/roles/service-bird-icvpn/templates/icvpn_ipv6.conf.j2 @@ -0,0 +1,67 @@ +# +# {{ ansible_managed }} +# + +# Variables +define icvpn_address = {{ icvpn_ipv6_transfer_net | ipaddr('net') | ipsubnet(112, 37) | ipaddr(magic) | ipaddr('address') }}; + +# ROA +roa table roa_icvpn { + include "icvpn_ipv6_roa.con?"; +} + +# Filters +filter icvpn_import_filter { + if is_mwu_self_nets() then reject; + if roa_check(roa_icvpn) = ROA_VALID then { + if is_ula() then accept; + } else { + if roa_check(roa_icvpn) = ROA_UNKNOWN then { + if is_ula() then { + print "ROA UNKNOWN for net, accepting: ", net, " ASN: ", bgp_path.last; + accept; + } + } + if roa_check(roa_icvpn) = ROA_INVALID then { + if is_ula() then { + print "ROA INVALID for net, accept: ", net, " ASN: ", bgp_path.last; + accept; + } + } + reject; + } + reject; +} + +# Protocols +protocol kernel kernel_mwu { + scan time 30; + import none; + export filter { + if is_mwu_self_nets() then + reject; + krt_prefsrc = icvpn_address; + accept; + }; + kernel table ipt_icvpn; +}; + +# Templates +template bgp ebgp_icvpn { + local icvpn_address as mwu_as; + import keep filtered on; + import filter icvpn_import_filter; + export filter { + if is_mwu_self_nets() then { + accept; + } + if source = RTS_BGP then { + accept; + } + reject; + }; + direct; +} + +# Include ICVPN IPv6 peers +include "icvpn_ipv6_peers.con?"; diff --git a/roles/service-bird/README.md b/roles/service-bird/README.md new file mode 100644 index 0000000..22995c5 --- /dev/null +++ b/roles/service-bird/README.md @@ -0,0 +1,35 @@ +# Ansible role service-bird + +Diese Ansible role installiert und konfiguriert den bird daemon. + +- installiert bird +- aktiviert systemd units bird + bird6 +- schreibt bird.conf + bird6.conf +- konfiguriert bird für iBGP mit allen anderen FFMWU-Servern + +Im iBGP peeren wir mangels separatem Transfernetz (im Moment) im Mainzer Mesh Netz. + +## Benötigte Variablen + +- Variable `bgp_loopback_net` # IPv4-Range des Mainzer Meshes, hieraus werden die Loopback Adressen gewählt. +- Variable `bgp_ipv4_transfer_net` # IPv4-Range des Mainzer Meshes, das aktuell als Transfernetz benutzt wird. +- Variable `bgp_ipv6_transfer_net` # IPv6-Range des Mainzer Meshes, das aktuell als Transfernetz benutzt wird. +- Variable `bgp_as_private_mwu` # Private ASN von Freifunk MWU +- Dictionary `bgp_mwu_servers` +``` + spinat: # kurzer Hostname des Peers + ipv4: 10.37.0.7 # IPv4-Adresse des Peers + ipv6: fd37:b4dc:4b1e::a25:7 # IPv6-Adresse des Peers +... + +``` +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + ipv4_network: + ipv6_ula: + - # IPv6-ULA Network +´´´ +- Host Variable `magic` diff --git a/roles/service-bird/tasks/main.yml b/roles/service-bird/tasks/main.yml new file mode 100644 index 0000000..5239d3a --- /dev/null +++ b/roles/service-bird/tasks/main.yml @@ -0,0 +1,59 @@ +--- +- name: install bird packages + package: + name: "{{ item }}" + state: present + with_items: + - bird-bgp + - bird-doc + +- name: set directory permissions for /etc/bird + file: + path: /etc/bird + state: directory + mode: 0755 + +- name: write bird.conf + template: + src: bird.conf.j2 + dest: /etc/bird/bird.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird + +- name: write bird6.conf + template: + src: bird6.conf.j2 + dest: /etc/bird/bird6.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird6 + +- name: write mwu_ipv4_peers.conf + template: + src: mwu_ipv4_peers.conf.j2 + dest: /etc/bird/mwu_ipv4_peers.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird + +- name: write mwu_ipv6_peers.conf + template: + src: mwu_ipv6_peers.conf.j2 + dest: /etc/bird/mwu_ipv6_peers.conf + mode: 0640 + owner: bird + group: bird + notify: reload systemd unit bird6 + +- name: enable + start systemd units bird + bird6 + systemd: + name: bird{{ item }} + enabled: yes + state: started + with_items: + - "" + - 6 diff --git a/roles/service-bird/templates/bird.conf.j2 b/roles/service-bird/templates/bird.conf.j2 new file mode 100644 index 0000000..ee231a1 --- /dev/null +++ b/roles/service-bird/templates/bird.conf.j2 @@ -0,0 +1,76 @@ +# +# {{ ansible_managed }} +# + +# Variables +define mwu_address = {{ bgp_ipv4_transfer_net | ipaddr('net') | ipaddr(magic) | ipaddr('address') }}; +define mwu_as = {{ as_private_mwu }}; +define router_id = {{ bgp_loopback_net | ipaddr('net') | ipaddr(magic) | ipaddr('address') }}; + +# General +timeformat protocol iso long; +router id router_id; + +# Functions +function is_default() { + return net ~ [ + 0.0.0.0/0 + ]; +} + +function is_freifunk() { + return net ~ [ + 10.0.0.0/8{16,24} + ]; +} + +function is_dn42() { + return net ~ [ + 172.20.0.0/14{20,28} + ]; +} + +function is_chaosvpn() { + return net ~ [ + 172.31.0.0/16+ + ]; +} + +function is_mwu_self_nets() { + return net ~ [ +{% for mesh in meshes %} + {{ mesh.ipv4_network | ipaddr('net') }}+{{ "," if not loop.last else "" }} +{% endfor %} + ]; +} + +# Protocols +protocol device { + scan time 30; +}; + +protocol direct mwu_subnets { +{% for mesh in meshes %} + interface "{{ mesh.id }}br"; +{% endfor %} + import where is_mwu_self_nets(); +}; + +# Templates +template bgp ibgp_mwu { + local mwu_address as mwu_as; + import keep filtered on; + import all; + export where source = RTS_BGP; + direct; + gateway direct; +}; + +# Include IPv4 MWU peers +include "mwu_ipv4_peers.con?"; + +# Include IPv4 ICVPN configuration +include "icvpn_ipv4.con?"; + +# Include IPv4 FFRL configuration +include "ffrl_ipv4.con?"; diff --git a/roles/service-bird/templates/bird6.conf.j2 b/roles/service-bird/templates/bird6.conf.j2 new file mode 100644 index 0000000..650c0ce --- /dev/null +++ b/roles/service-bird/templates/bird6.conf.j2 @@ -0,0 +1,65 @@ +# +# {{ ansible_managed }} +# + +# Variables +define router_id = {{ bgp_loopback_net | ipaddr('net') | ipaddr(magic) | ipaddr('address') }}; +define mwu_address = {{ bgp_ipv6_transfer_net | ipaddr('net') | ipaddr(magic) | ipaddr('address') }}; +define mwu_as = {{ as_private_mwu }}; + +# General +timeformat protocol iso long; +router id router_id; + +# Functions +function is_default() { + return net ~ [ + ::/0 + ]; +} + +function is_ula() { + return net ~ [ + fc00::/7{48,64} + ]; +} + +function is_mwu_self_nets() { + return net ~ [ +{% for mesh in meshes %} +{% for ula in mesh.ipv6_ula %} + {{ ula | ipaddr('net') }}+{{ "," if not loop.last else "" }}{% endfor %}{{ "," if not loop.last else "" }} +{% endfor %} + ]; +} + +# Protocols +protocol device { + scan time 30; +}; + +protocol direct mwu_subnets { +{% for mesh in meshes %} + interface "{{ mesh.id }}br"; +{% endfor %} + import where is_mwu_self_nets(); +}; + +# Templates +template bgp ibgp_mwu { + local mwu_address as mwu_as; + import keep filtered on; + import all; + export where source = RTS_BGP; + direct; + gateway direct; +}; + +# Include IPv6 MWU peers +include "mwu_ipv6_peers.con?"; + +# Include IPv6 ICVPN configuration +include "icvpn_ipv6.con?"; + +# Include IPv6 FFRL configuration +include "ffrl_ipv6.con?"; diff --git a/roles/service-bird/templates/mwu_ipv4_peers.conf.j2 b/roles/service-bird/templates/mwu_ipv4_peers.conf.j2 new file mode 100644 index 0000000..153c36a --- /dev/null +++ b/roles/service-bird/templates/mwu_ipv4_peers.conf.j2 @@ -0,0 +1,12 @@ +# +# {{ ansible_managed }} +# + +{% for item, value in bgp_mwu_servers.iteritems() %} +{% if item != inventory_hostname_short %} +protocol bgp mwu_{{ item }} from ibgp_mwu { + neighbor {{ value.ipv4 }} as mwu_as; +}; +{% endif %} + +{% endfor %} diff --git a/roles/service-bird/templates/mwu_ipv6_peers.conf.j2 b/roles/service-bird/templates/mwu_ipv6_peers.conf.j2 new file mode 100644 index 0000000..59051ff --- /dev/null +++ b/roles/service-bird/templates/mwu_ipv6_peers.conf.j2 @@ -0,0 +1,12 @@ +# +# {{ ansible_managed }} +# + +{% for item, value in bgp_mwu_servers.iteritems() %} +{% if item != inventory_hostname_short %} +protocol bgp mwu_{{ item }} from ibgp_mwu { + neighbor {{ value.ipv6 }} as mwu_as; +}; +{% endif %} + +{% endfor %} diff --git a/roles/service-dhcpd/README.md b/roles/service-dhcpd/README.md new file mode 100644 index 0000000..45d5742 --- /dev/null +++ b/roles/service-dhcpd/README.md @@ -0,0 +1,29 @@ +# Ansible role service-dhcpd + +Diese Ansible role installiert und konfiguriert den isc dhcp daemon. +Wir nutzen diesen nur zur Verteilung von IPv4-Adressen. + +- installiert isc-dhcp-server +- setzt interfaces in /etc/default/isc-dhcp-server +- schreibt dhcpd.conf + +## Benötigte Variablen + +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + site_name: # string + site_code: # string + ipv4_network: + dnssl: + - $domain # string + iface_mtu: # integer +´´´ +- Host Variable `magic` +- Host Variable `ipv4_dhcp_range` + +## DHCP Range + +In der Host-Variable `ipv4_dhcp_range` wird als Integer die Nummer des /22 Blocks aus `ipv4_network` definiert, welcher als DHCP Range verwendet werden soll. Dem Gateway Lotuswurzel ist die DHCP-Range 10.X.16.0-10.X.19.255 zugewiesen. Diese ist der 4. /22er Block, also wird in der Host-Variable für die Lotuswurzel `4` geschrieben. diff --git a/roles/service-dhcpd/tasks/main.yml b/roles/service-dhcpd/tasks/main.yml new file mode 100644 index 0000000..f4a82a1 --- /dev/null +++ b/roles/service-dhcpd/tasks/main.yml @@ -0,0 +1,34 @@ +--- +- name: install dhcp packages + package: + name: isc-dhcp-server + state: present + +- name: concatenate meshbridge interfaces + set_fact: + dhcp_interfaces: "{% for mesh in meshes %}{{ mesh.id }}br{% if not loop.last %} {% endif %}{% endfor %}" + +- name: set ipv4 interfaces isc dhcp should listen on + lineinfile: + path: /etc/default/isc-dhcp-server + regexp: '^INTERFACESv4="' + line: 'INTERFACESv4="{{ dhcp_interfaces }}"' + notify: restart isc dhcp server + +- name: set ipv6 interfaces isc dhcp should listen on + lineinfile: + path: /etc/default/isc-dhcp-server + regexp: '^INTERFACESv6="' + line: 'INTERFACESv6=""' + +- name: configure isc dhcp server + template: + src: dhcpd.conf.j2 + dest: /etc/dhcp/dhcpd.conf + notify: restart isc dhcp server + +- name: enable systemd unit isc-dhcp-server + systemd: + name: isc-dhcp-server + enabled: yes + state: started diff --git a/roles/service-dhcpd/templates/dhcpd.conf.j2 b/roles/service-dhcpd/templates/dhcpd.conf.j2 new file mode 100644 index 0000000..80a7c76 --- /dev/null +++ b/roles/service-dhcpd/templates/dhcpd.conf.j2 @@ -0,0 +1,28 @@ +# +# {{ ansible_managed }} +# +ddns-update-style none; + +authoritative; +server-name "{{ inventory_hostname_short }}"; + +log-facility local7; + +default-lease-time 300; +min-lease-time 300; +max-lease-time 300; + +{% for mesh in meshes %} +# DHCP subnet for site {{ mesh.site_name }} ({{ mesh.site_code }}) +subnet {{ mesh.ipv4_network | ipaddr('network') }} netmask {{ mesh.ipv4_network | ipaddr('netmask') }} { + range {{ mesh.ipv4_network | ipsubnet(22, ipv4_dhcp_range) | ipaddr('net') | ipaddr('network') }} {{ mesh.ipv4_network | ipsubnet(22, ipv4_dhcp_range) | ipaddr('net') | ipaddr('broadcast') }}; + option routers {{ mesh.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') }}; + option domain-name-servers {{ mesh.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') }}; + option domain-search {% for domain in mesh.dnssl %}"{{ domain }}"{% if not loop.last %}, {% endif %}{% endfor %}; + option ntp-servers {{ mesh.ipv4_network | ipaddr('net') | ipaddr(magic) | ipaddr('address') }}; + option interface-mtu {{ mesh.iface_mtu }}; +} +{% if not loop.last %} + +{% endif %} +{% endfor %} diff --git a/roles/service-fastd-intragate/README.md b/roles/service-fastd-intragate/README.md new file mode 100644 index 0000000..2127c19 --- /dev/null +++ b/roles/service-fastd-intragate/README.md @@ -0,0 +1,40 @@ +# Ansible role service-fastd-intragate + +Diese Ansible role konfiguriert die fastd-Instanz für die Intra-Server Kommunikation. + +- konfiguriert xxigvpn-Instanzen +- stellt sicher, dass die Instanz-Verzeichnisse existieren +- schreibt fastd.conf +- schreibt secret.conf + - der private fastd Schlüssel wird aus dem Admin passwordstore gelesen (YAML key secret) +- erstellt die erforderlichen peers Ordner +- klont die fastd peer repos + +## Benötigte Variablen + +- Dictionary `meshes` +``` +meshes: + - id: xx +... + site_number: # integer + fastd: + nodes: + instances: + - id: 0 # integer + mtu: # integer + peers: + repo: # String - https Link zum Github Repository + version: # String - Branch oder Commit ID + pass: # String - Pfad des fastd secrets im Admin Pass + ... +``` + +## fastd Secrets + +Die privaten Schlüssel der fastd Instanzen sind sehr sensible Informationen, weshalb wir diese in ein nicht öffentliches passwordstore ausgelagert haben. +Bevor man ein Gateway aufsetzt, müssen die privaten Schlüssel für alle benötigten fastd Instanzen generiert und im passwordstore hinterlegt werden. + +## Abhängigkeiten + +- role `service-fastd` diff --git a/roles/service-fastd-intragate/meta/main.yml b/roles/service-fastd-intragate/meta/main.yml new file mode 100644 index 0000000..2f66f75 --- /dev/null +++ b/roles/service-fastd-intragate/meta/main.yml @@ -0,0 +1,5 @@ +--- +dependencies: + - { role: git-repos } + - { role: network-fastd } + - { role: service-fastd } diff --git a/roles/service-fastd-intragate/tasks/main.yml b/roles/service-fastd-intragate/tasks/main.yml new file mode 100644 index 0000000..d7bb227 --- /dev/null +++ b/roles/service-fastd-intragate/tasks/main.yml @@ -0,0 +1,58 @@ +--- +- name: create fastd intragate directories + file: + path: "/etc/fastd/{{ item.0.id }}igvpn-{{ item.1.mtu }}" + state: directory + mode: 0755 + with_subelements: + - "{{ meshes }}" + - fastd.intragate.instances + +- name: create fastd peer intragate directories + file: + path: "/etc/fastd/{{ item.0.id }}igvpn-{{ item.1.mtu }}/peers" + state: directory + mode: 0755 + owner: admin + group: admin + with_subelements: + - "{{ meshes }}" + - fastd.intragate.instances + +- name: clone fastd peer intragate repos + git: + repo: "{{ item.1.peers.repo }}" + dest: "/etc/fastd/{{ item.0.id }}igvpn-{{ item.1.mtu }}/peers" + version: "{{ item.1.peers.version }}" + update: no + with_subelements: + - "{{ meshes }}" + - fastd.intragate.instances + become: false + +- name: template fastd mesh config + template: + src: fastd-intragate.conf.j2 + dest: "/etc/fastd/{{ item.0.id }}igvpn-{{ item.1.mtu }}/fastd.conf" + notify: restart fastd intragate instances + with_subelements: + - "{{ meshes }}" + - fastd.intragate.instances + +- name: write fastd intragate secret + template: + src: fastd-secret.conf.j2 + dest: "/etc/fastd/{{ item.0.id }}igvpn-{{ item.1.mtu }}/secret.conf" + notify: restart fastd intragate instances + with_subelements: + - "{{ meshes }}" + - fastd.intragate.instances + +- name: configure systemd unit fastd@ + systemd: + name: "fastd@{{ item.0.id }}igvpn-{{ item.1.mtu }}" + enabled: yes + state: started + with_subelements: + - "{{ meshes }}" + - fastd.intragate.instances diff --git a/roles/service-fastd-intragate/templates/fastd-intragate.conf.j2 b/roles/service-fastd-intragate/templates/fastd-intragate.conf.j2 new file mode 100644 index 0000000..b7945eb --- /dev/null +++ b/roles/service-fastd-intragate/templates/fastd-intragate.conf.j2 @@ -0,0 +1,25 @@ +# +# {{ ansible_managed }} +# +log level warn; +hide ip addresses yes; +hide mac addresses yes; + +method "aes128-ctr+umac"; + +interface "{{ item.0.id }}igvpn-{{ item.1.mtu }}"; + +bind {{ ansible_default_ipv4.address | ipaddr('public') }}:11{{ item.1.id }}{{ item.0.site_number }}; +bind {{ ansible_default_ipv6.address | ipaddr('public') | ipwrap }}:11{{ item.1.id }}{{ item.0.site_number }}; + +include "secret.conf"; +mtu {{ item.1.mtu }}; + +peer group "servers" { + include peers from "peers/gates"; + include peers from "peers/services"; +} + +on up "/bin/systemctl reload networking"; + +status socket "/var/run/fastd-{{ item.0.id }}igvpn-{{ item.1.mtu }}.status"; diff --git a/roles/service-fastd-intragate/templates/fastd-secret.conf.j2 b/roles/service-fastd-intragate/templates/fastd-secret.conf.j2 new file mode 100644 index 0000000..c8d0e15 --- /dev/null +++ b/roles/service-fastd-intragate/templates/fastd-secret.conf.j2 @@ -0,0 +1,4 @@ +# +# {{ ansible_managed }} +# +secret "{{ lookup('passwordstore', item.1.pass + '/' + inventory_hostname_short + ' subkey=secret') }}"; diff --git a/roles/service-fastd-mesh/README.md b/roles/service-fastd-mesh/README.md new file mode 100644 index 0000000..f7fad8e --- /dev/null +++ b/roles/service-fastd-mesh/README.md @@ -0,0 +1,45 @@ +# Ansible role service-fastd-mesh + +Diese Ansible role konfiguriert die fastd-Instanz für die Knoten Kommunikation. + +- stellt sicher, dass die Instanz-Verzeichnisse existieren +- schreibt fastd.conf +- schreibt secret.conf + - der private fastd Schlüssel wird aus dem Admin passwordstore gelesen (YAML key secret) +- erstellt die erforderlichen peers Ordner +- klont die fastd peer repos +- klont bingener fastd peer repo (im Moment hardcoded) + +## Instanz-Benamung +Node-Instanzen: $mesh.id + vpn + '-' + $mesh.fastd.nodes.instances.xx.mtu, z.B. "mzvpn-1312" +Intragate-Instanzen: $mesh.id + 'ig' + vpn + '-' + $mesh.fastd.intragate.instances.xx.mtu, z.B. "mzigvpn-1312" + +## Benötigte Variablen + +- Dictionary `meshes` +``` +meshes: + - id: xx +... + site_number: # integer + fastd: + nodes: + instances: + - id: 0 # integer + mtu: # integer + peers: + repo: # String - https Link zum Github Repository + version: # String - Branch oder Commit ID + pass: # String - Pfad des fastd secrets im Admin Pass + ... +``` +- Liste `legacy_gateways` + +## fastd Secrets + +Die privaten Schlüssel der fastd Instanzen sind sehr sensible Informationen, weshalb wir diese in ein nicht öffentliches passwordstore ausgelagert haben. +Bevor man ein Gateway aufsetzt, müssen die privaten Schlüssel für alle benötigten fastd Instanzen generiert und im passwordstore hinterlegt werden. + +## Abhängigkeiten + +- role `service-fastd` diff --git a/roles/service-fastd-mesh/files/peer_limit.conf b/roles/service-fastd-mesh/files/peer_limit.conf new file mode 100644 index 0000000..f294c83 --- /dev/null +++ b/roles/service-fastd-mesh/files/peer_limit.conf @@ -0,0 +1 @@ +peer limit 200; diff --git a/roles/service-fastd-mesh/meta/main.yml b/roles/service-fastd-mesh/meta/main.yml new file mode 100644 index 0000000..2f66f75 --- /dev/null +++ b/roles/service-fastd-mesh/meta/main.yml @@ -0,0 +1,5 @@ +--- +dependencies: + - { role: git-repos } + - { role: network-fastd } + - { role: service-fastd } diff --git a/roles/service-fastd-mesh/tasks/main.yml b/roles/service-fastd-mesh/tasks/main.yml new file mode 100644 index 0000000..879fe80 --- /dev/null +++ b/roles/service-fastd-mesh/tasks/main.yml @@ -0,0 +1,165 @@ +--- +- name: create fastd directories + file: + path: "/etc/fastd/{{ item.0.id }}vpn-{{ item.1.mtu }}" + state: directory + mode: 0755 + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + +- name: create fastd peer mesh directories + file: + path: "/etc/fastd/{{ item.0.id }}vpn-{{ item.1.mtu }}/peers" + state: directory + mode: 0755 + owner: admin + group: admin + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + +- name: create fastd peer mesh directories for ffbin + file: + path: "/etc/fastd/mzvpn-{{ item }}/peers_bingen" + state: directory + mode: 0755 + owner: admin + group: admin + with_items: + - 1406 + - 1312 + +- name: clone fastd peer mesh repos + git: + repo: "{{ item.1.peers.repo }}" + dest: "/etc/fastd/{{ item.0.id }}vpn-{{ item.1.mtu }}/peers" + version: "{{ item.1.peers.version }}" + update: no + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + become: false + +- name: clone fastd peer mesh repo for ffbin + git: + repo: https://github.com/freifunk-bingen/peers-ffbin.git + dest: "/etc/fastd/mzvpn-{{ item }}/peers_bingen" + version: master + update: no + with_items: + - 1406 + - 1312 + become: false + +- name: template fastd mesh config + template: + src: fastd-mesh.conf.j2 + dest: "/etc/fastd/{{ item.0.id }}vpn-{{ item.1.mtu }}/fastd.conf" + notify: restart fastd mesh instances + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + +- name: write fastd mesh secret + template: + src: fastd-secret.conf.j2 + dest: "/etc/fastd/{{ item.0.id }}vpn-{{ item.1.mtu }}/secret.conf" + notify: restart fastd mesh instances + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + +- name: copy peer_limit.conf if not exist + copy: + src: peer_limit.conf + dest: "/etc/fastd/{{ item.0.id }}vpn-{{ item.1.mtu }}/peer_limit.conf" + owner: admin + group: admin + mode: 0640 + force: no + notify: restart fastd mesh instances + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + +- name: set file attributes for peer_limit.conf + file: + path: "/etc/fastd/{{ item.0.id }}vpn-{{ item.1.mtu }}/peer_limit.conf" + mode: 0640 + owner: admin + group: admin + notify: restart fastd mesh instances + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances + +- name: write systemd unit fastd-sync-meshkeys.service + template: + src: fastd-sync-meshkeys.service.j2 + dest: /etc/systemd/system/fastd-sync-meshkeys.service + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: write systemd timer fastd-sync-meshkeys.timer + template: + src: fastd-sync-meshkeys.timer.j2 + dest: /etc/systemd/system/fastd-sync-meshkeys.timer + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: create fastd_status.json file + file: + path: /var/www/html/fastd_status.json + state: touch + owner: admin + group: admin + mode: 0644 + +- name: write configuration for fastd-peer-limit-update script + template: + src: fastd_peer_limit_config.yaml.j2 + dest: /home/admin/.config/fastd_peer_limit_config.yaml + owner: admin + group: admin + mode: 0644 + +- name: write systemd unit fastd-peer-limit-update.service + template: + src: fastd-peer-limit-update.service.j2 + dest: /etc/systemd/system/fastd-peer-limit-update.service + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: write systemd timer fastd-peer-limit-update.timer + template: + src: fastd-peer-limit-update.timer.j2 + dest: /etc/systemd/system/fastd-peer-limit-update.timer + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: configure systemd timers for fastd-mesh instance + systemd: + name: "{{ item }}.timer" + enabled: yes + state: started + with_items: + - fastd-sync-meshkeys + - fastd-peer-limit-update + +- name: configure systemd unit fastd@ + systemd: + name: "fastd@{{ item.0.id }}vpn-{{ item.1.mtu }}" + enabled: yes + state: started + with_subelements: + - "{{ meshes }}" + - fastd.nodes.instances diff --git a/roles/service-fastd-mesh/templates/fastd-mesh.conf.j2 b/roles/service-fastd-mesh/templates/fastd-mesh.conf.j2 new file mode 100644 index 0000000..bcee23f --- /dev/null +++ b/roles/service-fastd-mesh/templates/fastd-mesh.conf.j2 @@ -0,0 +1,32 @@ +# +# {{ ansible_managed }} +# +log level warn; +hide ip addresses yes; +hide mac addresses yes; + +method "salsa2012+umac"; + +interface "{{ item.0.id }}vpn-{{ item.1.mtu }}"; + +bind {{ ansible_default_ipv4.address | ipaddr('public') }}:10{{ item.1.id }}{{ item.0.site_number }}; +bind {{ ansible_default_ipv6.address | ipaddr('public') | ipwrap }}:10{{ item.1.id }}{{ item.0.site_number }}; + +include "secret.conf"; +mtu {{ item.1.mtu }}; + +peer group "vpn_nodes" { + include "peer_limit.conf"; + include peers from "peers"; +{% if item.0.id == "mz" %} + include peers from "peers_bingen"; +{% endif %} +} + +peer group "servers" { + include peers from "peers/servers"; +} + +on up "/bin/systemctl reload networking"; + +status socket "/var/run/fastd-{{ item.0.id }}vpn-{{ item.1.mtu }}.status"; diff --git a/roles/service-fastd-mesh/templates/fastd-peer-limit-update.service.j2 b/roles/service-fastd-mesh/templates/fastd-peer-limit-update.service.j2 new file mode 100644 index 0000000..963809e --- /dev/null +++ b/roles/service-fastd-mesh/templates/fastd-peer-limit-update.service.j2 @@ -0,0 +1,10 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Update fastd peer limits + +[Service] +ExecStart=/home/admin/clones/backend-scripts/limit_fastd_peers_gw.py +User=admin +Group=admin diff --git a/roles/service-fastd-mesh/templates/fastd-peer-limit-update.timer.j2 b/roles/service-fastd-mesh/templates/fastd-peer-limit-update.timer.j2 new file mode 100644 index 0000000..880c912 --- /dev/null +++ b/roles/service-fastd-mesh/templates/fastd-peer-limit-update.timer.j2 @@ -0,0 +1,12 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Timer which schedules fastd-peer-limit-update.service + +[Timer] +OnBootSec=5min +OnUnitActiveSec=5min + +[Install] +WantedBy=timers.target diff --git a/roles/service-fastd-mesh/templates/fastd-secret.conf.j2 b/roles/service-fastd-mesh/templates/fastd-secret.conf.j2 new file mode 100644 index 0000000..c8d0e15 --- /dev/null +++ b/roles/service-fastd-mesh/templates/fastd-secret.conf.j2 @@ -0,0 +1,4 @@ +# +# {{ ansible_managed }} +# +secret "{{ lookup('passwordstore', item.1.pass + '/' + inventory_hostname_short + ' subkey=secret') }}"; diff --git a/roles/service-fastd-mesh/templates/fastd-sync-meshkeys.service.j2 b/roles/service-fastd-mesh/templates/fastd-sync-meshkeys.service.j2 new file mode 100644 index 0000000..70a181b --- /dev/null +++ b/roles/service-fastd-mesh/templates/fastd-sync-meshkeys.service.j2 @@ -0,0 +1,10 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Update fastd mesh peers repos + +[Service] +ExecStart=/home/admin/clones/backend-scripts/sync_meshkeys_gw.sh +User=admin +Group=admin diff --git a/roles/service-fastd-mesh/templates/fastd-sync-meshkeys.timer.j2 b/roles/service-fastd-mesh/templates/fastd-sync-meshkeys.timer.j2 new file mode 100644 index 0000000..cea04f0 --- /dev/null +++ b/roles/service-fastd-mesh/templates/fastd-sync-meshkeys.timer.j2 @@ -0,0 +1,12 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Update fastd mesh peers repos timer + +[Timer] +OnBootSec=5m +OnUnitActiveSec=15m + +[Install] +WantedBy=timers.target diff --git a/roles/service-fastd-mesh/templates/fastd_peer_limit_config.yaml.j2 b/roles/service-fastd-mesh/templates/fastd_peer_limit_config.yaml.j2 new file mode 100644 index 0000000..1139226 --- /dev/null +++ b/roles/service-fastd-mesh/templates/fastd_peer_limit_config.yaml.j2 @@ -0,0 +1,26 @@ +# +# {{ ansible_managed }} +# +ansible_gate: True +additional: 8 +fastd_instances: +{% for mesh in meshes %} +{% for instance in mesh.fastd.nodes.instances %} + - {{ mesh.id }}vpn-{{ instance.mtu }} +{% endfor %} +{% endfor %} +cronlog: '/home/admin/.cronlog/limit.%s.log' +fastd_config: '/etc/fastd/%s/peer_limit.conf' +fastd_status: '/usr/local/bin/fastd-status' +gateways: +{% for gateway in groups['ffmwu-gateways'] %} + - {{ gateway.rstrip('.freifunk-mwu.de') }} +{% endfor %} +{% for gateway in legacy_gateways %} + - {{ gateway }} +{% endfor %} +restart_max: 43200 +stat: 'fastd_status.json' +stat_ext: 'http://%s.freifunk-mwu.de/%s' +stat_local: '/var/www/html/%s' +timeout: 900 diff --git a/roles/service-fastd/README.md b/roles/service-fastd/README.md new file mode 100644 index 0000000..345c9be --- /dev/null +++ b/roles/service-fastd/README.md @@ -0,0 +1,5 @@ +# Ansible role service-fastd + +Diese Ansible role installiert die erforderlichen Pakete für die fastd Rollen. + +- installiert fastd + git diff --git a/roles/service-fastd/files/fastd-status b/roles/service-fastd/files/fastd-status new file mode 100644 index 0000000..286b026 --- /dev/null +++ b/roles/service-fastd/files/fastd-status @@ -0,0 +1,17 @@ +#!/usr/bin/perl -w + +use strict; + +use IO::Socket::UNIX qw( SOCK_STREAM ); + +$ARGV[0] or die("Usage: fastd-status \n"); + +my $socket = IO::Socket::UNIX->new( + Type => SOCK_STREAM, + Peer => $ARGV[0], +) + or die("Can't connect to server: $!\n"); + +foreach my $line (<$socket>) { + print $line; +} diff --git a/roles/service-fastd/tasks/main.yml b/roles/service-fastd/tasks/main.yml new file mode 100644 index 0000000..dcd65ad --- /dev/null +++ b/roles/service-fastd/tasks/main.yml @@ -0,0 +1,30 @@ +--- +- name: install fastd packages + package: + name: "{{ item }}" + state: present + with_items: + - fastd + - git + +- name: mask legacy service fastd + systemd: + name: fastd + masked: yes + +- name: write systemd unit fastd@.service + template: + src: fastd@.service.j2 + dest: /etc/systemd/system/fastd@.service + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: copy fastd status script + copy: + src: fastd-status + dest: /usr/local/bin/fastd-status + owner: root + group: root + mode: 0755 diff --git a/roles/service-fastd/templates/fastd@.service.j2 b/roles/service-fastd/templates/fastd@.service.j2 new file mode 100644 index 0000000..47c30c1 --- /dev/null +++ b/roles/service-fastd/templates/fastd@.service.j2 @@ -0,0 +1,11 @@ +[Unit] +Description=Fast and Secure Tunnelling Daemon (connection %i) +After=network.target + +[Service] +Type=notify +ExecStart=/usr/bin/fastd --syslog-level info --syslog-ident fastd@%i -c /etc/fastd/%i/fastd.conf +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/roles/service-haveged/README.md b/roles/service-haveged/README.md new file mode 100644 index 0000000..a6b81ad --- /dev/null +++ b/roles/service-haveged/README.md @@ -0,0 +1,3 @@ +# Ansible role service-haveged + +Diese Ansible role installiert und startet den haveged daemon. diff --git a/roles/service-haveged/tasks/main.yml b/roles/service-haveged/tasks/main.yml new file mode 100644 index 0000000..e7fac1b --- /dev/null +++ b/roles/service-haveged/tasks/main.yml @@ -0,0 +1,11 @@ +--- +- name: install haveged + package: + name: haveged + state: present + +- name: start and enable systemd unit haveged + systemd: + name: haveged + enabled: yes + state: started diff --git a/roles/service-nginx-firmware/README.md b/roles/service-nginx-firmware/README.md new file mode 100644 index 0000000..77e5c75 --- /dev/null +++ b/roles/service-nginx-firmware/README.md @@ -0,0 +1,22 @@ +# Ansible role service-nginx-firmware + +Diese Ansible role konfiguriert die Firmware Synchronisation und die erforderlichen nginx vHosts. + +- verwaltet `/var/www/html/firmware` +- installiert und konfiguriert den systemd timer firmware-sync +- schreibt firmware.conf + +## Benötigte Variablen + +- Variable `http_domain_external` # string: Externe Freifunk MWU Domain +- Variable `http_domain_internal` # string: Interne Freifunk MWU Domain +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + site_name: # string +... + http_domain_external: # string: Externe Mesh Domain + http_domain_internal: # string: Interne Mesh Domain +´´´ diff --git a/roles/service-nginx-firmware/meta/main.yml b/roles/service-nginx-firmware/meta/main.yml new file mode 100644 index 0000000..814b458 --- /dev/null +++ b/roles/service-nginx-firmware/meta/main.yml @@ -0,0 +1,3 @@ +--- +dependencies: + - { role: service-nginx } diff --git a/roles/service-nginx-firmware/tasks/main.yml b/roles/service-nginx-firmware/tasks/main.yml new file mode 100644 index 0000000..ffde07a --- /dev/null +++ b/roles/service-nginx-firmware/tasks/main.yml @@ -0,0 +1,41 @@ +--- +- name: manage firmware directory + file: + path: /var/www/html/firmware + state: directory + mode: 0755 + owner: www-data + group: www-data + +- name: write systemd unit firmware-sync.service + template: + src: firmware-sync.service.j2 + dest: /etc/systemd/system/firmware-sync.service + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: write systemd timer firmware-sync.timer + template: + src: firmware-sync.timer.j2 + dest: /etc/systemd/system/firmware-sync.timer + owner: root + group: root + mode: 0644 + notify: reload systemd + +- name: configure systemd unit/timer firmware-sync + systemd: + name: firmware-sync.timer + enabled: yes + state: started + +- name: write firmware.conf + template: + src: firmware_vhost.conf.j2 + dest: /etc/nginx/conf.d/firmware.conf + owner: root + group: root + mode: 0644 + notify: reload nginx diff --git a/roles/service-nginx-firmware/templates/firmware-sync.service.j2 b/roles/service-nginx-firmware/templates/firmware-sync.service.j2 new file mode 100644 index 0000000..cc79408 --- /dev/null +++ b/roles/service-nginx-firmware/templates/firmware-sync.service.j2 @@ -0,0 +1,11 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Synchronize Freifunk MWU Firmware directory + +[Service] +Type=oneshot +ExecStart=/usr/bin/rsync -avh4 --delete rsync://milchreis.freifunk-mwu.de:873/firmware /var/www/html/firmware +User=www-data +Group=www-data diff --git a/roles/service-nginx-firmware/templates/firmware-sync.timer.j2 b/roles/service-nginx-firmware/templates/firmware-sync.timer.j2 new file mode 100644 index 0000000..1d995c3 --- /dev/null +++ b/roles/service-nginx-firmware/templates/firmware-sync.timer.j2 @@ -0,0 +1,12 @@ +# +# {{ ansible_managed }} +# +[Unit] +Description=Timer which schedules firmware-sync.service + +[Timer] +OnBootSec=30min +OnUnitActiveSec=10min + +[Install] +WantedBy=timers.target diff --git a/roles/service-nginx-firmware/templates/firmware_vhost.conf.j2 b/roles/service-nginx-firmware/templates/firmware_vhost.conf.j2 new file mode 100644 index 0000000..e966631 --- /dev/null +++ b/roles/service-nginx-firmware/templates/firmware_vhost.conf.j2 @@ -0,0 +1,32 @@ +server { + listen 80; + server_name firmware.{{ http_domain_internal }} firmware.{{ http_domain_external }}; + + charset utf-8; + server_tokens off; + + root /var/www/html/firmware; + location / { + autoindex on; + autoindex_exact_size off; + } +} + +{% for mesh in meshes %} +server { + listen 80; + server_name firmware.{{ mesh.http_domain_internal }} firmware.{{ mesh.http_domain_external }}; + + charset utf-8; + server_tokens off; + + root /var/www/html/firmware/{{ mesh.site_name.lower() }}; + location / { + autoindex on; + autoindex_exact_size off; + } +} +{% if not loop.last %} + +{% endif %} +{% endfor %} diff --git a/roles/service-nginx/README.md b/roles/service-nginx/README.md new file mode 100644 index 0000000..b45bba2 --- /dev/null +++ b/roles/service-nginx/README.md @@ -0,0 +1,12 @@ +# Ansible role service-nginx + +Diese Ansible role installiert und konfiguriert den Web Server nginx. + +- installiert das offizielle Debian Repository von nginx.org +- installiert nginx +- schreibt default.conf +- installiert die Standard MWU Gateway Webseite + +## Benötigte Variablen + +- Variable `inventory_hostname_short` diff --git a/roles/service-nginx/files/style.css b/roles/service-nginx/files/style.css new file mode 100644 index 0000000..1dea88f --- /dev/null +++ b/roles/service-nginx/files/style.css @@ -0,0 +1,53 @@ +body +{ + background: #ffffff; + color: #000000; + font-family: "Source Code Pro", "Consolas", "Courier New", "Monaco", monospace; + font-size: 12px; + white-space: nowrap; +} + +footer +{ + margin: 2em 0; +} + +a +{ + color: #ff4b57; +} + +.block +{ + margin: 1em; + padding: .5em; + border-radius: .5em; + border: #f9f9f9 1px solid; +} + +.cblock +{ + background: #000000; + color: #ffffff; + margin: 1em; + padding: .5em; + border-radius: .5em; + display: block; +} + +.ifblock +{ + display: inline-block; + vertical-align: top; + text-align: center; + margin: .1em; + padding: .5em; + min-width: 10em; + border: #f9f9f9 1px solid; + border-radius: .5em; +} + +.ifimg +{ + display: block; +} diff --git a/roles/service-nginx/tasks/main.yml b/roles/service-nginx/tasks/main.yml new file mode 100644 index 0000000..912e588 --- /dev/null +++ b/roles/service-nginx/tasks/main.yml @@ -0,0 +1,52 @@ +--- +- name: add official nginx apt key + apt_key: + state: present + id: 7BD9BF62 + url: "https://nginx.org/keys/nginx_signing.key" + +- name: add official nginx apt repository + apt_repository: + state: present + repo: "{{ item }}" + update_cache: yes + filename: nginx + with_items: + - deb http://nginx.org/packages/debian/ stretch nginx + - deb-src http://nginx.org/packages/debian/ stretch nginx + +- name: install nginx packages + package: + name: nginx + state: present + +- name: write nginx configuration default.conf + template: + src: default.conf.j2 + dest: /etc/nginx/conf.d/default.conf + mode: 0644 + notify: reload nginx + +- name: manage html directory for static files + file: + path: /var/www/html/static + state: directory + mode: 0755 + +- name: copy css stylesheet + copy: + src: style.css + dest: /var/www/html/static/style.css + mode: 0644 + +- name: write index.html + template: + src: index.html.j2 + dest: /var/www/html/index.html + mode: 0644 + +- name: configure systemd unit nginx + systemd: + name: nginx + state: started + enabled: yes diff --git a/roles/service-nginx/templates/default.conf.j2 b/roles/service-nginx/templates/default.conf.j2 new file mode 100644 index 0000000..f09ede1 --- /dev/null +++ b/roles/service-nginx/templates/default.conf.j2 @@ -0,0 +1,14 @@ +server { + listen 80 default_server; + server_name _; + + charset utf-8; + server_tokens off; + + root /var/www/html; + location / { + index index.html; + autoindex on; + autoindex_exact_size off; + } +} diff --git a/roles/service-nginx/templates/index.html.j2 b/roles/service-nginx/templates/index.html.j2 new file mode 100644 index 0000000..eb8c0fd --- /dev/null +++ b/roles/service-nginx/templates/index.html.j2 @@ -0,0 +1,25 @@ + + + + + Freifunk MWU Gateway "{{ inventory_hostname_short }}" + + + + + +
+

Freifunk MWU Gateway {{ inventory_hostname_short }}

+
+
Firmware
+
Traffic
+ + diff --git a/roles/service-ntpd/README.md b/roles/service-ntpd/README.md new file mode 100644 index 0000000..6d9dfaa --- /dev/null +++ b/roles/service-ntpd/README.md @@ -0,0 +1,7 @@ +# Ansible role service-ntpd + +Diese Ansible role installiert und startet den haveged daemon. + +- stellt sicher, dass systemd-timesyncd nicht läuft +- installiert ntp pakete +- startet den ntp daemon diff --git a/roles/service-ntpd/tasks/main.yml b/roles/service-ntpd/tasks/main.yml new file mode 100644 index 0000000..e2e6cde --- /dev/null +++ b/roles/service-ntpd/tasks/main.yml @@ -0,0 +1,22 @@ +--- +- name: ensure systemd-timesyncd is disabled + systemd: + name: systemd-timesyncd + enabled: no + state: stopped + +- name: install ntp packages + package: + name: "{{ item }}" + state: present + with_items: + - ntp + - ntp-doc + - ntpdate + - ntpstat + +- name: enable and start ntp daemon + systemd: + name: ntp + enabled: yes + state: started diff --git a/roles/service-prometheus/LICENSE b/roles/service-prometheus/LICENSE new file mode 100644 index 0000000..9aba21a --- /dev/null +++ b/roles/service-prometheus/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 William Yeh + + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/roles/service-prometheus/README.md b/roles/service-prometheus/README.md new file mode 100644 index 0000000..2b7d0b2 --- /dev/null +++ b/roles/service-prometheus/README.md @@ -0,0 +1,239 @@ + +FFMWU prometheus +============ + + +## Summary + +Prometheus ansible role based on **[williamyeh.prometheus](https://galaxy.ansible.com/williamyeh/prometheus/)** + +This Ansible role has the following features for [Prometheus](http://prometheus.io/): + + - Install specific versions of [Prometheus server](https://github.com/prometheus/prometheus), [Node exporter](https://github.com/prometheus/node_exporter), [Alertmanager](https://github.com/prometheus/alertmanager). + - Handlers for restart/reload/stop events; + - Bare bone configuration (*real* configuration should be left to user's template files; see **Usage** section below). + +## Role Variables + + +### Mandatory variables + +The components to be installed: + +```yaml +# Supported components: +# +# [Server components] +# - "prometheus" +# - "alertmanager" +# +# [Exporter components] +# - "node_exporter" +# +prometheus_components +``` + + + +### Optional variables: general settings + + +User-configurable defaults: + +```yaml +# user and group +prometheus_user: prometheus +prometheus_group: prometheus + + +# directory for executable files +prometheus_install_path: /opt/prometheus + +# directory for configuration files +prometheus_config_path: /etc/prometheus + +# directory for PID files +prometheus_pid_path: /var/run/prometheus + +# directory for temporary files +prometheus_download_path: /tmp + +# version of helper utility "gosu" +gosu_version: "1.10" +``` + +### Optional variables: Prometheus server + +User-configurable defaults: + +```yaml +# which version? +prometheus_version: 2.0.0 + +# directory for rule files +prometheus_rule_path: {{ prometheus_config_path }}/rules + +# directory for file_sd files +prometheus_file_sd_config_path: {{ prometheus_config_path }}/tgroups + +# directory for runtime database +prometheus_db_path: /var/lib/prometheus +``` + + + + + + +User-installable configuration file (see [doc](http://prometheus.io/docs/operating/configuration/) for details): + + +```yaml +# main conf template relative to `playbook_dir`; +# to be installed to "{{ prometheus_config_path }}/prometheus.yml" +prometheus_conf_main +``` + + +User-installable rule files (see [doc](http://prometheus.io/docs/alerting/rules/) for details): + + +```yaml +# rule files to be installed to "{{ prometheus_rule_path }}" directory; +# dict fields: +# - key: memo for this rule +# - value: +# - src: file relative to `playbook_dir` +# - dest: target file relative to `{{ prometheus_rule_path }}` +prometheus_rule_files +``` + + +Additional command-line arguments, if any (use `prometheus --help` to see the full list of arguments): + +```yaml +prometheus_opts +``` + + +### Optional variables: Node exporter + + +User-configurable defaults: + +```yaml +# which version? +node_exporter_version: 0.15.1 +``` + +Additional command-line arguments, if any (use `node_exporter --help` to see the full list of arguments): + +```yaml +node_exporter_opts +``` + + +### Optional variables: Alertmanager + + +User-configurable defaults: + +```yaml +# which version? +alertmanager_version: 0.10.0 + +# directory for runtime database (currently for `silences.json`) +alertmanager_db_path: /var/lib/alertmanager +``` + +User-installable alertmanager conf file (see [doc](http://prometheus.io/docs/alerting/alertmanager/) for details): +See files directory alertmanager.yml + + +Additional command-line arguments, if any (use `alertmanager --help` to see the full list of arguments): + +```yaml +prometheus_alertmanager_opts +``` + + + + +## Handlers + +Prometheus server: + +- `reload prometheus` + +Alertmanager: + +- `reload alertmanager` + + +## Usage + + +### Step 1: add role + +Add role name `service-prometheus` to your playbook file. + + +### Step 2: add variables + +Set vars in your playbook file, if necessary. + +Simple example: + +```yaml +--- +# file: simple-playbook.yml + +- hosts: all + become: True + roles: + - service-prometheus + + vars: + prometheus_components: [ "prometheus", "alertmanager" ] +``` + + +### Step 3: copy user's config files, if necessary + + +More practical example: + +```yaml +--- +# file: complex-playbook.yml + +- hosts: all + become: True + roles: + - service-prometheus + + vars: + prometheus_components: + - prometheus + - node_exporter + - alertmanager + + prometheus_rule_files: + this_is_rule_1_InstanceDown: + src: some/path/basic.rules + dest: basic.rules +``` + + +### Step 4: browse the default Prometheus pages + +Open the page in your browser: + +- Prometheus - `http://HOST:9090` or `http://HOST:9090/consoles/node.html` + +- Alertmanager - `http://HOST:9093` + + +## License + +MIT License. See the [LICENSE file](LICENSE) for details. diff --git a/roles/service-prometheus/defaults/main.yml b/roles/service-prometheus/defaults/main.yml new file mode 100644 index 0000000..c639e3e --- /dev/null +++ b/roles/service-prometheus/defaults/main.yml @@ -0,0 +1,32 @@ +--- +# +# user-configurable defaults +# + +prometheus_components: + - "node_exporter" + +prometheus_user: prometheus +prometheus_group: prometheus + +prometheus_version: 2.0.0 +node_exporter_version: 0.15.1 +alertmanager_version: 0.10.0 + +gosu_version: "1.10" + +prometheus_install_path: /opt/prometheus +prometheus_config_path: /etc/prometheus +prometheus_rule_path: "{{ prometheus_config_path }}/rules" +prometheus_file_sd_config_path: "{{ prometheus_config_path }}/tgroups" +prometheus_db_path: /var/lib/prometheus +alertmanager_db_path: /var/lib/alertmanager +prometheus_pid_path: /var/run/prometheus + +prometheus_download_path: /tmp +prometheus_workdir: "{{ prometheus_download_path }}/prometheus_workdir" +prometheus_goroot: "{{ prometheus_workdir }}/go" +prometheus_gopath: "{{ prometheus_workdir }}/gopath" + +prometheus_default_opts: "--config.file={{ prometheus_config_path }}/prometheus.yml --storage.tsdb.path={{ prometheus_db_path }}" +alertmanager_default_opts: "-config.file={{ prometheus_config_path }}/alertmanager.yml -storage.path={{ alertmanager_db_path }}" diff --git a/roles/service-prometheus/files/alertmanager.yml b/roles/service-prometheus/files/alertmanager.yml new file mode 100644 index 0000000..abab519 --- /dev/null +++ b/roles/service-prometheus/files/alertmanager.yml @@ -0,0 +1,13 @@ +global: + +route: + group_by: ['alertname', 'cluster'] + group_wait: 30s + group_interval: 5m + repeat_interval: 3h + receiver: 'default-pager' + +receivers: + - name: 'default-pager' + pagerduty_configs: + - service_key: diff --git a/roles/service-prometheus/handlers/main.yml b/roles/service-prometheus/handlers/main.yml new file mode 100644 index 0000000..a293535 --- /dev/null +++ b/roles/service-prometheus/handlers/main.yml @@ -0,0 +1,9 @@ +- name: reload prometheus + service: + name: prometheus + state: reloaded + +- name: reload alertmanager + service: + name: alertmanager + state: reloaded diff --git a/roles/service-prometheus/tasks/alertmanager.yml b/roles/service-prometheus/tasks/alertmanager.yml new file mode 100644 index 0000000..3436a94 --- /dev/null +++ b/roles/service-prometheus/tasks/alertmanager.yml @@ -0,0 +1,61 @@ +--- +# Install Prometheus alertmanager. + +- name: set internal variables, part 1 + set_fact: + alertmanager_signature: "alertmanager-{{ alertmanager_version }}.linux-amd64" + +- name: set internal variables, part 2 + set_fact: + alertmanager_daemon_dir: "{{ prometheus_install_path }}/{{ alertmanager_signature }}" + +- name: set download url + set_fact: + alertmanager_tarball_url: "https://github.com/prometheus/alertmanager/releases/download/v{{ alertmanager_version }}/{{ alertmanager_signature }}.tar.gz" + +- name: download and uncompress alertmanager tarball + unarchive: + src: "{{ alertmanager_tarball_url }}" + dest: "{{ prometheus_install_path }}" + copy: no + owner: "{{ prometheus_user }}" + group: "{{ prometheus_group }}" + mode: "go-w" + creates: "{{ alertmanager_daemon_dir }}" + +- name: create alertmanager /usr/local/bin links + file: + src: "{{ alertmanager_daemon_dir }}/{{ item }}" + dest: "/usr/local/bin/{{ item }}" + state: link + with_items: + - "alertmanager" + - "amtool" + +- name: mkdir for alertmanager data (silences.json for now) + file: + path: "{{ item }}" + state: directory + owner: "{{ prometheus_user }}" + group: "{{ prometheus_group }}" + mode: "u=rwx,g=rx,o=" + with_items: + - "{{ alertmanager_db_path }}" + +- name: copy alertmanager systemd config + template: + src: "alertmanager.service.j2" + dest: "/lib/systemd/system/alertmanager.service" + +- name: install alertmanager config file + copy: + src: "alertmanager.yml" + dest: "{{ prometheus_config_path }}/alertmanager.yml" + notify: + - reload alertmanager + +- name: enable alertmanager service + service: + name: alertmanager + enabled: yes + state: started diff --git a/roles/service-prometheus/tasks/install-gosu.yml b/roles/service-prometheus/tasks/install-gosu.yml new file mode 100644 index 0000000..78c686a --- /dev/null +++ b/roles/service-prometheus/tasks/install-gosu.yml @@ -0,0 +1,19 @@ +# Install "gosu" utility. +# +# @see https://github.com/tianon/gosu +# + +- name: set internal variables for convenience + set_fact: + gosu_bin_url: "https://github.com/tianon/gosu/releases/download/{{ gosu_version }}/gosu-amd64" + +- name: download gosu executable + get_url: + url: "{{ gosu_bin_url }}" + dest: "/usr/local/bin/gosu" + +- name: add executable permission + file: + path: "/usr/local/bin/gosu" + state: file + mode: "a+x" diff --git a/roles/service-prometheus/tasks/main.yml b/roles/service-prometheus/tasks/main.yml new file mode 100644 index 0000000..4ed1092 --- /dev/null +++ b/roles/service-prometheus/tasks/main.yml @@ -0,0 +1,51 @@ +# Top-level installer for Prometheus. + +- name: create Prometheus group + group: + name: "{{ prometheus_group }}" + state: present + +- name: create Prometheus user + user: + name: "{{ prometheus_user }}" + group: "{{ prometheus_group }}" + createhome: no + shell: /sbin/nologin + comment: "Prometheus User" + state: present + +- name: create base directories + file: + path: "{{ item }}" + state: directory + owner: "{{ prometheus_user }}" + group: "{{ prometheus_group }}" + mode: "u=rwx,g=rx,o=" + with_items: + - "{{ prometheus_install_path }}" + - "{{ prometheus_config_path }}" + - "{{ prometheus_pid_path }}" + +- name: install helper utility "gosu" + include_tasks: install-gosu.yml + +- name: install and configure prometheus service + include_tasks: prometheus.yml + when: '"prometheus" in prometheus_components' + +- name: install and configure node-exporter service + include_tasks: node-exporter.yml + when: '"node_exporter" in prometheus_components' + +- name: install and configure alertmanager service + include_tasks: alertmanager.yml + when: '"alertmanager" in prometheus_components' + +- name: set {{ prometheus_install_path }} permissions, owner and group + file: + path: "{{ prometheus_install_path }}" + state: directory + owner: "{{ prometheus_user }}" + group: "{{ prometheus_group }}" + mode: "go-w" + recurse: yes diff --git a/roles/service-prometheus/tasks/node-exporter.yml b/roles/service-prometheus/tasks/node-exporter.yml new file mode 100644 index 0000000..cb55d53 --- /dev/null +++ b/roles/service-prometheus/tasks/node-exporter.yml @@ -0,0 +1,40 @@ +# Install Prometheus node-exporter. +# +# @see http://prometheus.io/docs/introduction/getting_started/ + +- name: set internal variables for convenience + set_fact: + node_exporter_daemon_dir: "{{ prometheus_install_path }}/node_exporter-{{ node_exporter_version }}.linux-amd64" + node_exporter_tarball_url: "https://github.com/prometheus/node_exporter/releases/download/v{{ node_exporter_version }}/node_exporter-{{ node_exporter_version }}.linux-amd64.tar.gz" + +- name: download and untar node_exporter tarball + unarchive: + src: "{{ node_exporter_tarball_url }}" + dest: "{{ prometheus_install_path }}" + copy: no + creates: "{{ node_exporter_daemon_dir }}" + +- name: create node_exporter /usr/local/bin link + file: + src: "{{ node_exporter_daemon_dir }}/node_exporter" + dest: "/usr/local/bin/node_exporter" + state: link + +- name: mkdir for data + file: + path: "{{ prometheus_db_path }}" + state: directory + owner: "{{ prometheus_user }}" + group: "{{ prometheus_group }}" + mode: "u=rwx,g=rx,o=" + +- name: copy systemd config to server + template: + src: "../templates/node_exporter.service.j2" + dest: "/lib/systemd/system/node_exporter.service" + +- name: enable node_exporter service + service: + name: node_exporter + enabled: yes + state: started diff --git a/roles/service-prometheus/tasks/prometheus.yml b/roles/service-prometheus/tasks/prometheus.yml new file mode 100644 index 0000000..53fae23 --- /dev/null +++ b/roles/service-prometheus/tasks/prometheus.yml @@ -0,0 +1,79 @@ +# Install Prometheus server. +# +# @see http://prometheus.io/docs/introduction/getting_started/ +# + +- name: set internal variables for convenience + set_fact: + prometheus_daemon_dir: "{{ prometheus_install_path }}/prometheus-{{ prometheus_version }}.linux-amd64" + prometheus_tarball_url: "https://github.com/prometheus/prometheus/releases/download/v{{ prometheus_version }}/prometheus-{{ prometheus_version }}.linux-amd64.tar.gz" + +- name: set prometheus default options + set_fact: + prometheus_default_opts: "{{ prometheus_default_opts }} --web.console.templates={{ prometheus_daemon_dir }}/consoles --web.console.libraries={{ prometheus_daemon_dir }}/console_libraries" + +- name: download and untar prometheus tarball + unarchive: + src: "{{ prometheus_tarball_url }}" + dest: "{{ prometheus_install_path }}" + copy: no + creates: "{{ prometheus_daemon_dir }}" + +- name: create prometheus /usr/local/bin links + file: + src: "{{ prometheus_daemon_dir }}/{{ item }}" + dest: "/usr/local/bin/{{ item }}" + state: link + with_items: + - "prometheus" + - "promtool" + +- name: mkdir for config and data + file: + path: "{{ item }}" + state: directory + owner: "{{ prometheus_user }}" + group: "{{ prometheus_group }}" + mode: "u=rwx,g=rx,o=" + with_items: + - "{{ prometheus_rule_path }}" + - "{{ prometheus_file_sd_config_path }}" + - "{{ prometheus_db_path }}" + +- name: copy prometheus systemd config + template: + src: "prometheus.service.j2" + dest: "/lib/systemd/system/prometheus.service" + +- name: copy rule files from playbook's, if any + copy: + src: "{{ playbook_dir }}/{{ item.value.src }}" + dest: "{{ prometheus_rule_path }}/{{ item.value.dest }}" + validate: "{{ prometheus_daemon_dir }}/promtool check rules %s" + with_dict: '{{ prometheus_rule_files | default({}) }}' + notify: + - reload prometheus + +- name: copy prometheus main config file from role's default, if necessary + template: + src: "prometheus.yml.j2" + dest: "{{ prometheus_config_path }}/prometheus.yml" + validate: "{{ prometheus_daemon_dir }}/promtool check config %s" + when: prometheus_conf_main is not defined + notify: + - reload prometheus + +- name: copy prometheus main config file from playbook's, if any + template: + src: "{{ playbook_dir }}/{{ prometheus_conf_main }}" + dest: "{{ prometheus_config_path }}/prometheus.yml" + validate: "{{ prometheus_daemon_dir }}/promtool check config %s" + when: prometheus_conf_main is defined + notify: + - reload prometheus + +- name: enable prometheus service + service: + name: prometheus + enabled: yes + state: started diff --git a/roles/service-prometheus/templates/alertmanager.service.j2 b/roles/service-prometheus/templates/alertmanager.service.j2 new file mode 100644 index 0000000..891e35f --- /dev/null +++ b/roles/service-prometheus/templates/alertmanager.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=Prometheus alertmanager. +After=network.target + +[Service] +Type=simple + +PIDFile={{ prometheus_pid_path }}/alertmanager.pid + +User={{ prometheus_user }} +Group={{ prometheus_group }} + +{% if prometheus_opts is defined %} +ExecStart={{ alertmanager_daemon_dir }}/alertmanager {{ alertmanager_default_opts }} {{ alertmanager_opts }} +{% else %} +ExecStart={{ alertmanager_daemon_dir }}/alertmanager {{ alertmanager_default_opts }} +{% endif %} +ExecReload=/bin/kill -HUP $MAINPID diff --git a/roles/service-prometheus/templates/node_exporter.service.j2 b/roles/service-prometheus/templates/node_exporter.service.j2 new file mode 100644 index 0000000..abb2007 --- /dev/null +++ b/roles/service-prometheus/templates/node_exporter.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=node_exporter - Prometheus exporter for machine metrics. +After=network.target + +[Service] +Type=simple + +PIDFile={{ prometheus_pid_path }}/node_exporter.pid + +User={{ prometheus_user }} +Group={{ prometheus_group }} + +{% if node_exporter_opts is defined %} +ExecStart={{ node_exporter_daemon_dir }}/node_exporter {{ node_exporter_opts }} +{% else %} +ExecStart={{ node_exporter_daemon_dir }}/node_exporter +{% endif %} +ExecReload=/bin/kill -HUP $MAINPID diff --git a/roles/service-prometheus/templates/prometheus.service.j2 b/roles/service-prometheus/templates/prometheus.service.j2 new file mode 100644 index 0000000..f6773cb --- /dev/null +++ b/roles/service-prometheus/templates/prometheus.service.j2 @@ -0,0 +1,18 @@ +[Unit] +Description=Prometheus server daemon. +After=network.target + +[Service] +Type=simple + +PIDFile={{ prometheus_pid_path }}/prometheus.pid + +User={{ prometheus_user }} +Group={{ prometheus_group }} + +{% if prometheus_opts is defined %} +ExecStart={{ prometheus_daemon_dir }}/prometheus {{ prometheus_default_opts }} {{ prometheus_node_exporter_opts }} +{% else %} +ExecStart={{ prometheus_daemon_dir }}/prometheus {{ prometheus_default_opts }} +{% endif %} +ExecReload=/bin/kill -HUP $MAINPID diff --git a/roles/service-prometheus/templates/prometheus.yml.j2 b/roles/service-prometheus/templates/prometheus.yml.j2 new file mode 100644 index 0000000..93a3eb0 --- /dev/null +++ b/roles/service-prometheus/templates/prometheus.yml.j2 @@ -0,0 +1,36 @@ +global: + scrape_interval: 15s # By default, scrape targets every 15 seconds. + evaluation_interval: 15s # By default, scrape targets every 15 seconds. + # scrape_timeout is set to the global default (10s). + + # The labels to add to any time series or alerts when communicating with + # external systems (federation, remote storage, Alertmanager). + external_labels: + monitor: 'master' + +{% if prometheus_rule_files is defined %} +# Rule files specifies a list of files from which rules are read. +rule_files: + {% for (key, value) in prometheus_rule_files.iteritems() %} + - {{ prometheus_rule_path }}/{{ value.dest }} + {% endfor %} +{% endif %} + +# A list of scrape configurations. +scrape_configs: + + - job_name: 'prometheus' + scrape_interval: 10s + scrape_timeout: 10s + static_configs: + - targets: ['localhost:9090'] + + - job_name: "node" + file_sd_configs: + - files: + - '{{ prometheus_file_sd_config_path }}/*.json' + - '{{ prometheus_file_sd_config_path }}/*.yml' + - '{{ prometheus_file_sd_config_path }}/*.yaml' + #static_configs: + #- targets: + # - "localhost:9100" diff --git a/roles/service-radvd/README.md b/roles/service-radvd/README.md new file mode 100644 index 0000000..be02ed7 --- /dev/null +++ b/roles/service-radvd/README.md @@ -0,0 +1,22 @@ +# Ansible role service-radvd + +Diese Ansible role installiert und konfiguriert den radvd daemon. + +- installiert radvd +- aktiviert systemd unit +- schreibt radvd.conf + +## Benötigte Variablen + +- Dictionary `meshes` +´´´ +meshes: + - id: xx +... + ipv6_ula: + - # ULA-Prefix - String + ipv6_public: + - # Public-Prefix - String + iface_mtu: # Integer +´´´ +- Host Variable `magic` diff --git a/roles/service-radvd/tasks/main.yml b/roles/service-radvd/tasks/main.yml new file mode 100644 index 0000000..feeb46d --- /dev/null +++ b/roles/service-radvd/tasks/main.yml @@ -0,0 +1,17 @@ +--- +- name: install radvd packages + package: + name: radvd + state: present + +- name: configure radvd + template: + src: radvd.conf.j2 + dest: /etc/radvd.conf + notify: restart systemd unit radvd + +- name: enable systemd unit radvd + systemd: + name: radvd + enabled: yes + state: started diff --git a/roles/service-radvd/templates/radvd.conf.j2 b/roles/service-radvd/templates/radvd.conf.j2 new file mode 100644 index 0000000..e38b42a --- /dev/null +++ b/roles/service-radvd/templates/radvd.conf.j2 @@ -0,0 +1,44 @@ + +# +# {{ ansible_managed }} +# +{% for mesh in meshes %} +interface {{ mesh.id }}br +{ + AdvSendAdvert on; + IgnoreIfMissing on; + MaxRtrAdvInterval {{ mesh.radvd.maxrtradvinterval }}; + AdvLinkMTU {{ mesh.iface_mtu }}; + + RDNSS {% for prefix in mesh.ipv6_ula %}{{ prefix | ipaddr('net') | ipsubnet(64, 0) | ipaddr(magic) | ipaddr('address') }} +{% endfor %} + { + FlushRDNSS off; + }; + +{% for prefix in mesh.ipv6_ula %} + prefix {{ prefix | ipaddr('net') | ipsubnet(64, 0) | ipaddr('subnet') }} + { + AdvValidLifetime {{ mesh.radvd.advvalidlifetime }}; + AdvPreferredLifetime {{ mesh.radvd.advpreferredlifetime }}; + }; +{% if not loop.last %} + +{% endif %} +{% endfor %} + +{% for prefix in mesh.ipv6_public %} + prefix {{ prefix | ipaddr('net') | ipsubnet(56, magic) | ipsubnet(64, 0) | ipaddr('subnet') }} + { + AdvValidLifetime {{ mesh.radvd.advvalidlifetime }}; + AdvPreferredLifetime {{ mesh.radvd.advpreferredlifetime }}; + }; +{% if not loop.last %} + +{% endif %} +{% endfor %} +}; +{% if not loop.last %} + +{% endif %} +{% endfor %} diff --git a/roles/service-respondd/README.md b/roles/service-respondd/README.md new file mode 100644 index 0000000..e8a5579 --- /dev/null +++ b/roles/service-respondd/README.md @@ -0,0 +1,16 @@ +# Ansible role service-respondd + +Diese Ansible role installiert und konfiguriert die respondd Implementierung `mesh-announce`. +Pro Mesh Netzwerk muss eine `mesh-announce`-Instanz laufen. + +- installiert `mesh-announce` (Github Clone) +- installiert pro Mesh Netzwerk eine systemd unit + +## Benötigte Variablen + +- Dictionary `meshes` +´´´ +meshes: + - id: xx + site_code: # string +´´´ diff --git a/roles/service-respondd/tasks/main.yml b/roles/service-respondd/tasks/main.yml new file mode 100644 index 0000000..4ae43cc --- /dev/null +++ b/roles/service-respondd/tasks/main.yml @@ -0,0 +1,31 @@ +--- +- name: install packages + package: + name: python3-netifaces + state: present + +- name: clone respondd repo + git: + repo: https://github.com/freifunk-mwu/mesh-announce.git + dest: /home/admin/clones/mesh-announce + version: mwu-respondd + become: false + +- name: write systemd unit files + template: + src: respondd.service.j2 + dest: "/etc/systemd/system/respondd-{{ item.id }}.service" + owner: root + group: root + mode: 0644 + notify: + - reload systemd + - restart respondd + with_items: "{{ meshes }}" + +- name: configure systemd unit files + systemd: + name: "respondd-{{ item.id }}" + enabled: yes + state: started + with_items: "{{ meshes }}" diff --git a/roles/service-respondd/templates/respondd.service.j2 b/roles/service-respondd/templates/respondd.service.j2 new file mode 100644 index 0000000..201a1f6 --- /dev/null +++ b/roles/service-respondd/templates/respondd.service.j2 @@ -0,0 +1,10 @@ +[Unit] +Description=respondd instance {{ item.id }} + +[Service] +ExecStart=/home/admin/clones/mesh-announce/respondd.py -i {{ item.id }}br {% for interface in item.fastd.nodes.instances %}-i {{ item.id }}vpn-{{ interface.mtu }}{% if not loop.last %} {% endif %}{% endfor %} -b {{ item.id }}bat -s {{ item.site_code }} -d /home/admin/clones/mesh-announce/ +Restart=always +Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +[Install] +WantedBy=multi-user.target diff --git a/roles/service-tinc/README.md b/roles/service-tinc/README.md new file mode 100644 index 0000000..855df5c --- /dev/null +++ b/roles/service-tinc/README.md @@ -0,0 +1,35 @@ +# Ansible role service-tinc + +Diese Ansible role installiert und konfiguriert den tinc daemon, der für die Verbindung in das InterCity-VPN benötigt wird. + +- installiert tinc +- erzeugt icvpn tinc Instanz + - klont freifunk/icvpn repo + - schreibt tinc.conf + - schreibt tinc-up hook script + - schreibt tinc-down hook script + - liest tinc private key aus dem pass + +## Benötigte Variablen + +- Dictionary `icvpn` +``` +icvpn: + prefix: mwu + interface: icvpn + icvpn_repo: https://github.com/freifunk/icvpn +``` +- Variable `icvpn_ipv4_transfer_net` +- Variable `icvpn_ipv6_transfer_net` +- Dictionary `routing_tables` +``` +routing_tables: + icvpn: 23 + ... +``` +- Host Variable `magic` + +## tinc private key + +Der private Schlüssel der icvpn tinc-Instanz liegt im passwordstore. +Bevor man ein Gateway aufsetzt, muss der private Schlüssel generiert und im passwordstore hinterlegt werden. diff --git a/roles/service-tinc/tasks/main.yml b/roles/service-tinc/tasks/main.yml new file mode 100644 index 0000000..5ee461d --- /dev/null +++ b/roles/service-tinc/tasks/main.yml @@ -0,0 +1,87 @@ +--- +- name: install tinc packages + package: + name: "{{ item }}" + state: present + with_items: + - tinc + +- name: clone icvpn repo + git: + repo: "{{ icvpn.icvpn_repo }}" + dest: /etc/tinc/{{ icvpn.interface }} + version: master + update: no + +- name: set directory permissions + file: + path: /etc/tinc/{{ icvpn.interface }} + state: directory + owner: admin + group: admin + recurse: yes + +- name: register metanodes + command: cat /etc/tinc/{{ icvpn.interface }}/metanodes + register: metanodes + changed_when: false + +- name: enable freifunk/icvpn post-merge script + copy: + remote_src: yes + src: /etc/tinc/{{ icvpn.interface }}/scripts/post-merge + dest: /etc/tinc/{{ icvpn.interface }}/.git/hooks/ + owner: admin + group: admin + mode: 0755 + +- name: write tinc.conf + template: + src: tinc.conf.j2 + dest: /etc/tinc/{{ icvpn.interface }}/tinc.conf + mode: 0664 + owner: admin + group: admin + notify: restart systemd unit tinc + +- name: write tinc-up hook script + template: + src: tinc-up.j2 + dest: /etc/tinc/{{ icvpn.interface }}/tinc-up + mode: 0775 + owner: admin + group: admin + notify: restart systemd unit tinc + +- name: write tinc-down hook script + template: + src: tinc-down.j2 + dest: /etc/tinc/{{ icvpn.interface }}/tinc-down + mode: 0775 + owner: admin + group: admin + notify: restart systemd unit tinc + +- name: write tinc private key + template: + src: rsa_key.priv.j2 + dest: /etc/tinc/{{ icvpn.interface }}/rsa_key.priv + mode: 0600 + owner: admin + group: admin + notify: restart systemd unit tinc + +- name: write nets.boot + template: + src: nets.boot.j2 + dest: /etc/tinc/nets.boot + mode: 0644 + owner: root + group: root + notify: restart systemd unit tinc + +- name: configure systemd unit tinc + systemd: + name: tinc + enabled: yes + state: started diff --git a/roles/service-tinc/templates/nets.boot.j2 b/roles/service-tinc/templates/nets.boot.j2 new file mode 100644 index 0000000..5e4cdf7 --- /dev/null +++ b/roles/service-tinc/templates/nets.boot.j2 @@ -0,0 +1,5 @@ +# +# {{ ansible_managed }} +# +# This file contains all names of the networks to be started on system startup. +{{ icvpn.interface }} diff --git a/roles/service-tinc/templates/rsa_key.priv.j2 b/roles/service-tinc/templates/rsa_key.priv.j2 new file mode 100644 index 0000000..1a7a690 --- /dev/null +++ b/roles/service-tinc/templates/rsa_key.priv.j2 @@ -0,0 +1 @@ +{{ lookup('passwordstore', 'tinc/icvpn/' + inventory_hostname_short + '_private returnall=true') }} diff --git a/roles/service-tinc/templates/tinc-down.j2 b/roles/service-tinc/templates/tinc-down.j2 new file mode 100644 index 0000000..f0a44b0 --- /dev/null +++ b/roles/service-tinc/templates/tinc-down.j2 @@ -0,0 +1,11 @@ +#!/bin/sh +# +# {{ ansible_managed }} +# +/sbin/ip addr del dev ${INTERFACE} {{ icvpn_ipv4_transfer_net | ipaddr('net') | ipsubnet(24, 37) | ipaddr(magic) | ipaddr('address') }}/16 broadcast {{ icvpn_ipv4_transfer_net | ipaddr('net') | ipaddr('broadcast') }} +/sbin/ip -6 addr del dev ${INTERFACE} {{ icvpn_ipv6_transfer_net | ipaddr('net') | ipsubnet(112, 37) | ipaddr(magic) | ipaddr('address') }}/96 + +/sbin/ip -4 route del {{ icvpn_ipv4_transfer_net }} proto static dev ${INTERFACE} table {{ routing_tables.icvpn }} +/sbin/ip -6 route del {{ icvpn_ipv6_transfer_net }} proto static dev ${INTERFACE} table {{ routing_tables.icvpn }} + +/sbin/ip link set dev ${INTERFACE} down diff --git a/roles/service-tinc/templates/tinc-up.j2 b/roles/service-tinc/templates/tinc-up.j2 new file mode 100644 index 0000000..57f0131 --- /dev/null +++ b/roles/service-tinc/templates/tinc-up.j2 @@ -0,0 +1,14 @@ +{% set ip4hex = icvpn_ipv4_transfer_net | ipaddr('net') | ipsubnet(24, 37) | ipaddr(magic) | ipaddr('address') | ip4_hex() -%} +{% set mac = '02f0' + ip4hex -%} +#!/bin/sh +# +# {{ ansible_managed }} +# +/sbin/ifconfig ${INTERFACE} hw ether {{ mac | hwaddr('linux') }} +/sbin/ip link set dev ${INTERFACE} up + +/sbin/ip -4 route add {{ icvpn_ipv4_transfer_net }} proto static dev ${INTERFACE} table {{ routing_tables.icvpn }} +/sbin/ip -6 route add {{ icvpn_ipv6_transfer_net }} proto static dev ${INTERFACE} table {{ routing_tables.icvpn }} + +/sbin/ip addr add dev ${INTERFACE} {{ icvpn_ipv4_transfer_net | ipaddr('net') | ipsubnet(24, 37) | ipaddr(magic) | ipaddr('address') }}/16 broadcast {{ icvpn_ipv4_transfer_net | ipaddr('net') | ipaddr('broadcast') }} scope link +/sbin/ip -6 addr add dev ${INTERFACE} {{ icvpn_ipv6_transfer_net | ipaddr('net') | ipsubnet(112, 37) | ipaddr(magic) | ipaddr('address') }}/96 preferred_lft 0 diff --git a/roles/service-tinc/templates/tinc.conf.j2 b/roles/service-tinc/templates/tinc.conf.j2 new file mode 100644 index 0000000..15f2e96 --- /dev/null +++ b/roles/service-tinc/templates/tinc.conf.j2 @@ -0,0 +1,12 @@ +Name = {{ icvpn.prefix }}{{ magic }} +PrivateKeyFile = /etc/tinc/{{ icvpn.interface }}/rsa_key.priv +Mode = Switch +PingTimeout = 30 +Port = 10655 +Hostnames = yes +GraphDumpFile = /etc/tinc/{{ icvpn.interface }}/topo.dot +Interface = {{ icvpn.interface }} + +{% for metanode in metanodes.stdout_lines %} +ConnectTo = {{ metanode }} +{% endfor %} diff --git a/roles/system-sysctl-gateway/README.md b/roles/system-sysctl-gateway/README.md new file mode 100644 index 0000000..13c5d33 --- /dev/null +++ b/roles/system-sysctl-gateway/README.md @@ -0,0 +1,12 @@ +# Ansible role system-sysctl-gateway +Diese Ansible role setzt Freifunk Gateway spezifische sysctl-Parameter. + +## Benötigte Variablen +- List `sysctl_settings_gateway` (Rollen-Variable) +``` +sysctl_settings_gateway: + - name: # sysctl-Parameter + value: # zu setzender Wert +... + +´´´ diff --git a/roles/system-sysctl-gateway/tasks/main.yml b/roles/system-sysctl-gateway/tasks/main.yml new file mode 100644 index 0000000..f46d562 --- /dev/null +++ b/roles/system-sysctl-gateway/tasks/main.yml @@ -0,0 +1,7 @@ +--- +- name: set freifunk gateway sysctl settings + sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + state: present + with_items: "{{ sysctl_settings_gateway }}" diff --git a/roles/system-sysctl-gateway/vars/main.yml b/roles/system-sysctl-gateway/vars/main.yml new file mode 100644 index 0000000..77211d4 --- /dev/null +++ b/roles/system-sysctl-gateway/vars/main.yml @@ -0,0 +1,18 @@ +--- +sysctl_settings_gateway: + - name: net.ipv4.neigh.default.gc_thresh1 + value: 1024 + - name: net.ipv4.neigh.default.gc_thresh2 + value: 2048 + - name: net.ipv4.neigh.default.gc_thresh3 + value: 4096 + - name: net.ipv6.conf.all.autoconf + value: 0 + - name: net.ipv6.conf.default.autoconf + value: 0 + - name: net.ipv6.neigh.default.gc_thresh1 + value: 1024 + - name: net.ipv6.neigh.default.gc_thresh2 + value: 2048 + - name: net.ipv6.neigh.default.gc_thresh3 + value: 4096