From 9158fc8ff671707c686fcd40e13b06310112eada Mon Sep 17 00:00:00 2001
From: Trygve Laugstøl <trygvis@inamo.no>
Date: Fri, 21 Aug 2020 13:44:50 +0200
Subject: wireguard2

---
 ansible/roles/wireguard2/README.md         | 21 +++++++
 ansible/roles/wireguard2/defaults/main.yml | 14 +++++
 ansible/roles/wireguard2/handlers/main.yml |  5 ++
 ansible/roles/wireguard2/tasks/absent.yml  | 18 ++++++
 ansible/roles/wireguard2/tasks/install.yml |  6 ++
 ansible/roles/wireguard2/tasks/main.yml    | 13 ++++
 ansible/roles/wireguard2/tasks/present.yml | 99 ++++++++++++++++++++++++++++++
 7 files changed, 176 insertions(+)
 create mode 100644 ansible/roles/wireguard2/README.md
 create mode 100644 ansible/roles/wireguard2/defaults/main.yml
 create mode 100644 ansible/roles/wireguard2/handlers/main.yml
 create mode 100644 ansible/roles/wireguard2/tasks/absent.yml
 create mode 100644 ansible/roles/wireguard2/tasks/install.yml
 create mode 100644 ansible/roles/wireguard2/tasks/main.yml
 create mode 100644 ansible/roles/wireguard2/tasks/present.yml

(limited to 'ansible/roles')

diff --git a/ansible/roles/wireguard2/README.md b/ansible/roles/wireguard2/README.md
new file mode 100644
index 0000000..d154546
--- /dev/null
+++ b/ansible/roles/wireguard2/README.md
@@ -0,0 +1,21 @@
+# Iptables configuration
+
+This is required:
+
+  iptables -P FORWARD ACCEPT
+
+It can possibly be modified to not accept by default, and only allow
+to/from our networks but I don't know how to do that.
+
+# Useful commands
+
+Cleaning everything and restarting.
+
+  ip link del dev wg0
+  systemctl restart systemd-networkd
+
+# References
+
+  * https://www.eisfunke.com/article/docker-wireguard-systemd.html - Notice that this is not using the "alternate routing table" technique.
+  * https://nickb.dev/blog/routing-select-docker-containers-through-wireguard-vpn
+  * https://docs.docker.com/network/bridge/#enable-forwarding-from-docker-containers-to-the-outside-world
diff --git a/ansible/roles/wireguard2/defaults/main.yml b/ansible/roles/wireguard2/defaults/main.yml
new file mode 100644
index 0000000..43bc7c6
--- /dev/null
+++ b/ansible/roles/wireguard2/defaults/main.yml
@@ -0,0 +1,14 @@
+wireguard_state: present
+wireguard_if: wg0
+public_keys_path: wireguard/{{ wireguard_if }}
+wireguard_routing_table: 242
+
+# Set this to something random. Make sure you open it in your firewall.
+# wireguard_listen_port:
+
+file_index: 60
+path_prefix: "/etc/systemd/network/{{ file_index }}"
+netdev_path: "{{ path_prefix }}-{{ wireguard_if}}.netdev"
+network_path: "{{ path_prefix }}-{{ wireguard_if}}.network"
+public_key_path: "{{ path_prefix }}-{{ wireguard_if}}.key"
+private_key_path: "{{ path_prefix }}-{{ wireguard_if}}.pub"
diff --git a/ansible/roles/wireguard2/handlers/main.yml b/ansible/roles/wireguard2/handlers/main.yml
new file mode 100644
index 0000000..f0170dd
--- /dev/null
+++ b/ansible/roles/wireguard2/handlers/main.yml
@@ -0,0 +1,5 @@
+- name: systemctl restart systemd-networkd
+  become: yes
+  systemd:
+    name: systemd-networkd
+    state: restarted
diff --git a/ansible/roles/wireguard2/tasks/absent.yml b/ansible/roles/wireguard2/tasks/absent.yml
new file mode 100644
index 0000000..82bfeb1
--- /dev/null
+++ b/ansible/roles/wireguard2/tasks/absent.yml
@@ -0,0 +1,18 @@
+- name: Clean old files
+  become: yes
+  file:
+    path: "{{ item }}"
+    state: absent
+  loop:
+    - "{{ netdev_path}}"
+    - "{{ network_path}}"
+    - "{{ private_key_path }}"
+    - "{{ public_key_path }}"
+  notify: systemctl restart systemd-networkd
+
+- name: remove interface
+  become: yes
+  shell: "ip l del dev {{ wireguard_if }}"
+  register: if_del
+  changed_when: if_del.rc == 0
+  failed_when: false
diff --git a/ansible/roles/wireguard2/tasks/install.yml b/ansible/roles/wireguard2/tasks/install.yml
new file mode 100644
index 0000000..61c152d
--- /dev/null
+++ b/ansible/roles/wireguard2/tasks/install.yml
@@ -0,0 +1,6 @@
+- name: apt install wireguard
+  become: yes
+  apt:
+    install_recommends: no
+    name:
+      - wireguard
diff --git a/ansible/roles/wireguard2/tasks/main.yml b/ansible/roles/wireguard2/tasks/main.yml
new file mode 100644
index 0000000..0985b01
--- /dev/null
+++ b/ansible/roles/wireguard2/tasks/main.yml
@@ -0,0 +1,13 @@
+- include_tasks:
+    file: install.yml
+    apply:
+      tags: never,install
+  tags: always
+
+- debug: var=wireguard_state
+
+- import_tasks: present.yml
+  when: wireguard_state == "present"
+
+- import_tasks: absent.yml
+  when: wireguard_state == "absent"
diff --git a/ansible/roles/wireguard2/tasks/present.yml b/ansible/roles/wireguard2/tasks/present.yml
new file mode 100644
index 0000000..967ec7d
--- /dev/null
+++ b/ansible/roles/wireguard2/tasks/present.yml
@@ -0,0 +1,99 @@
+- name: "wg genkey {{ private_key_path }}"
+  become: yes
+  shell: "wg genkey | tee {{ private_key_path }} | wg pubkey > {{ public_key_path }}"
+  args:
+    creates: "{{ private_key_path }}"
+  register: wg_private_key_gen
+
+- name: chmod/chown keys
+  become: yes
+  file:
+    owner: systemd-network
+    group: adm
+    mode: 0640
+    path: "{{ item }}"
+  loop:
+    - "{{ private_key_path }}"
+    - "{{ public_key_path }}"
+
+- when: wg_private_key_gen.changed
+  become: yes
+  fetch:
+    src: "{{ public_key_path }}"
+    dest: "files/{{ public_keys_path }}/{{ ansible_hostname }}.pub"
+    flat: true
+
+- become: yes
+  slurp:
+    src: "{{ private_key_path }}"
+  register: wg_private_key
+
+- name: "Create {{ netdev_path }}"
+  become: yes
+  notify: systemctl restart systemd-networkd
+  copy:
+    owner: systemd-network
+    group: adm
+    mode: 0640
+    dest: "{{ netdev_path }}"
+    content: |
+      [NetDev]
+      Name={{ wireguard_if }}
+      Kind=wireguard
+      Description=Wireguard VPN ({{ wireguard_if }})
+
+      [WireGuard]
+      PrivateKey={{ wg_private_key['content'] | b64decode }}
+      {%- if wireguard_listen_port is defined %}
+      ListenPort={{ wireguard_listen_port }}
+      {% endif %}
+      {% for peer, data in wireguard_peers|dictsort %}
+      {% if peer != ansible_hostname %}
+
+      # {{ peer }}
+      [WireGuardPeer]
+      PublicKey={{ data.public_key if data.public_key is defined else lookup('file', public_keys_path + "/" + peer + ".pub") }}
+      {% if data.endpoint is defined %}
+      {% if data.endpoint == "auto" %}
+      Endpoint={{ hostvars[peer]['ansible_host'] }}:{{ data.listen_port if data.listen_port is defined else wireguard_listen_port }}
+      {% else %}
+      Endpoint={{ data.endpoint }}:{{ data.listen_port if data.listen_port is defined else wireguard_listen_port }}
+      {% endif %}
+      {% endif %}
+      {% for ip in data.allowed_ips|default([]) %}
+      AllowedIPs={{ ip }}
+      {% endfor %}
+      PersistentKeepalive={{ data.keepalive if data.keepalive is defined else "60" }}
+      {% endif %}{# skip this host #}
+      {% endfor %}
+
+- name: "Create {{ network_path }}"
+  become: yes
+  notify: systemctl restart systemd-networkd
+  copy:
+    owner: systemd-network
+    group: adm
+    mode: 0640
+    dest: "{{ network_path }}"
+    content: |
+      [Match]
+      Name={{ wireguard_if }}
+
+      [Address]
+      Address={{ wireguard_address4 }}
+
+      # Routers
+      {% for router in wireguard_routers %}
+      {% if router.state|default("absent") == "present" %}
+
+      [Route]
+      Gateway={{ router.gateway|ipaddr('address') }}
+      Destination={{ router.network }}
+      {% endif %}{# state #}
+      {% endfor %}
+
+- become: yes
+  systemd:
+    unit: systemd-networkd
+    state: started
+    enabled: yes
-- 
cgit v1.2.3