From 5c566ef8d02727c57f49320bee1efca6aeb8276c Mon Sep 17 00:00:00 2001 From: Elizabeth Hunt Date: Sun, 24 Mar 2024 22:51:07 -0400 Subject: [PATCH] wireguard --- TODO.md | 1 + deploy.yml | 6 ++ docs/INFRA_PLAYBOOK.md | 9 +++ group_vars/host_domains.yml | 8 +- group_vars/wireguard-mesh.yml | 4 + inventory | 29 ++++--- playbooks/deploy-wireguard-endpoint.yml | 6 ++ playbooks/deploy-wireguard-mesh.yml | 6 ++ .../roles/wireguard-endpoint/files/.gitignore | 1 + .../roles/wireguard-endpoint/tasks/main.yml | 40 ++++++++++ playbooks/roles/wireguard-mesh/tasks/main.yml | 80 +++++++++++++++++++ .../templates/inframesh.conf.j2 | 17 ++++ 12 files changed, 192 insertions(+), 15 deletions(-) create mode 100644 docs/INFRA_PLAYBOOK.md create mode 100644 group_vars/wireguard-mesh.yml create mode 100644 playbooks/deploy-wireguard-endpoint.yml create mode 100644 playbooks/deploy-wireguard-mesh.yml create mode 100644 playbooks/roles/wireguard-endpoint/files/.gitignore create mode 100644 playbooks/roles/wireguard-endpoint/tasks/main.yml create mode 100644 playbooks/roles/wireguard-mesh/tasks/main.yml create mode 100644 playbooks/roles/wireguard-mesh/templates/inframesh.conf.j2 diff --git a/TODO.md b/TODO.md index 086234a..6f6c6ed 100644 --- a/TODO.md +++ b/TODO.md @@ -2,3 +2,4 @@ - [ ] read email for service accounts dmarc.report, postmaster email users, give access to infra users - [ ] allow infra users to ssh into any machine in infra, regular users into their tilde account on himmel - [ ] allow ufw and setup wireguard on himmel +- [ ] internal vpn for infra, figure out routing diff --git a/deploy.yml b/deploy.yml index 68c3e5e..68d4a83 100644 --- a/deploy.yml +++ b/deploy.yml @@ -1,5 +1,8 @@ --- +- name: Wireguard Endpoint + ansible.builtin.import_playbook: playbooks/deploy-wireguard-endpoint.yml + - name: Common configurations ansible.builtin.import_playbook: playbooks/deploy-common.yml @@ -17,3 +20,6 @@ - name: Gitea ansible.builtin.import_playbook: playbooks/deploy-gitea.yml + +- name: Wireguard Mesh + ansible.builtin.import_playbook: playbooks/deploy-wireguard-mesh.yml diff --git a/docs/INFRA_PLAYBOOK.md b/docs/INFRA_PLAYBOOK.md new file mode 100644 index 0000000..043d4dc --- /dev/null +++ b/docs/INFRA_PLAYBOOK.md @@ -0,0 +1,9 @@ +Registering a new internal machine : + +1. Register .pub.infra.hatecomputers.club A record -> public ipv4 +2. Register .int.infra.hatecomputers.club A record -> internal ipv4 in 10.155.0.0/16 subnet +3. Put it on the internal VPN. i.e. add .pub... in the wireguard-mesh after allowing ssh to root and everything +4. Run the wireguard-mesh playbook +5. Update the inventory record in wireguard-mesh to .int... +6. Now run the deploy-common playbook to allow ssh only internally, debugging as necessary if needed ; it should just work :)) +7. Add your new roles! diff --git a/group_vars/host_domains.yml b/group_vars/host_domains.yml index 5167211..8765d74 100644 --- a/group_vars/host_domains.yml +++ b/group_vars/host_domains.yml @@ -1,10 +1,10 @@ --- host_domains: - fern.hatecomputers.club: - # - fern.hatecomputers.club + fern.infra.hatecomputers.club: + - fern.hatecomputers.club - auth.hatecomputers.club - mail.hatecomputers.club - himmel.hatecomputers.club: - # - himmel.hatecomputers.club + himmel.infra.hatecomputers.club: + - himmel.hatecomputers.club - git.hatecomputers.club diff --git a/group_vars/wireguard-mesh.yml b/group_vars/wireguard-mesh.yml new file mode 100644 index 0000000..efecddd --- /dev/null +++ b/group_vars/wireguard-mesh.yml @@ -0,0 +1,4 @@ +--- + +wireguard_listen_port: 51830 +wireguard_subnet: 10.155.0.0/16 diff --git a/inventory b/inventory index c8384cc..2dc1b6f 100644 --- a/inventory +++ b/inventory @@ -1,24 +1,31 @@ [docker] -fern.hatecomputers.club ansible_user=root ansible_connection=ssh -himmel.hatecomputers.club ansible_user=root ansible_connection=ssh +fern.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh +himmel.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh [host_domains] -fern.hatecomputers.club ansible_user=root ansible_connection=ssh -himmel.hatecomputers.club ansible_user=root ansible_connection=ssh +fern.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh +himmel.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh [nginx] -fern.hatecomputers.club ansible_user=root ansible_connection=ssh -himmel.hatecomputers.club ansible_user=root ansible_connection=ssh +fern.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh +himmel.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh [certbot] -fern.hatecomputers.club ansible_user=root ansible_connection=ssh -himmel.hatecomputers.club ansible_user=root ansible_connection=ssh +fern.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh +himmel.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh [kanidm] -fern.hatecomputers.club ansible_user=root ansible_connection=ssh +fern.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh [mail] -fern.hatecomputers.club ansible_user=root ansible_connection=ssh +fern.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh [gitea] -himmel.hatecomputers.club ansible_user=root ansible_connection=ssh +himmel.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh + +[wireguard-mesh] +himmel.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh +fern.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh + +[wireguard-endpoint] +himmel.int.infra.hatecomputers.club ansible_user=root ansible_connection=ssh diff --git a/playbooks/deploy-wireguard-endpoint.yml b/playbooks/deploy-wireguard-endpoint.yml new file mode 100644 index 0000000..4f87e97 --- /dev/null +++ b/playbooks/deploy-wireguard-endpoint.yml @@ -0,0 +1,6 @@ +--- + +- name: Wireguard-endpoint setup + hosts: wireguard-endpoint + roles: + - wireguard-endpoint diff --git a/playbooks/deploy-wireguard-mesh.yml b/playbooks/deploy-wireguard-mesh.yml new file mode 100644 index 0000000..6e7cd85 --- /dev/null +++ b/playbooks/deploy-wireguard-mesh.yml @@ -0,0 +1,6 @@ +--- + +- name: Wireguard-mesh setup + hosts: wireguard-mesh + roles: + - wireguard-mesh diff --git a/playbooks/roles/wireguard-endpoint/files/.gitignore b/playbooks/roles/wireguard-endpoint/files/.gitignore new file mode 100644 index 0000000..5571ff7 --- /dev/null +++ b/playbooks/roles/wireguard-endpoint/files/.gitignore @@ -0,0 +1 @@ +wireguard.cfg diff --git a/playbooks/roles/wireguard-endpoint/tasks/main.yml b/playbooks/roles/wireguard-endpoint/tasks/main.yml new file mode 100644 index 0000000..226fceb --- /dev/null +++ b/playbooks/roles/wireguard-endpoint/tasks/main.yml @@ -0,0 +1,40 @@ +--- + +- name: Install wireguard + ansible.builtin.apt: + name: + - wireguard + state: latest + +- name: Copy config + ansible.builtin.copy: + src: wireguard.cfg + dest: /etc/wireguard/hatecomputers.conf + owner: root + group: root + mode: 0600 + +- name: Enable and persist ip forwarding + ansible.builtin.sysctl: + name: net.ipv4.ip_forward + value: "1" + state: present + sysctl_set: true + reload: true + +- name: Allow wireguard endpoint ufw + ansible.builtin.ufw: + rule: allow + port: '51820' + proto: 'udp' + +- name: Start wireguard and enable on boot + ansible.builtin.systemd: + name: wg-quick@hatecomputers + enabled: true + state: started + +- name: Hotreload wireguard + ansible.builtin.shell: > + bash -c + "wg syncconf inframesh <(wg-quick strip inframesh)" diff --git a/playbooks/roles/wireguard-mesh/tasks/main.yml b/playbooks/roles/wireguard-mesh/tasks/main.yml new file mode 100644 index 0000000..02d2290 --- /dev/null +++ b/playbooks/roles/wireguard-mesh/tasks/main.yml @@ -0,0 +1,80 @@ +--- + +- name: Install wireguard + ansible.builtin.apt: + name: + - wireguard + - ufw + state: present + +- name: Get node ips from dns records + ansible.builtin.shell: "dig +short {{ item }} | tail -n1" + register: wireguard_node_ip + with_items: "{{ groups['wireguard-mesh'] }}" + +- name: Massage node ips + ansible.builtin.set_fact: > + wireguard_node_ips={{ wireguard_node_ips|default({}) + | combine( {item.item: item.stdout} ) }} + with_items: "{{ wireguard_node_ip.results }}" + +- name: Allow wireguard endpoint ufw + ansible.builtin.ufw: + rule: allow + port: "{{ wireguard_listen_port }}" + proto: 'udp' + +- name: Generate Wireguard keypair + ansible.builtin.shell: > + wg genkey | tee /etc/wireguard/privatekey + | wg pubkey | tee /etc/wireguard/publickey + args: + creates: /etc/wireguard/privatekey + +- name: Register private key + ansible.builtin.shell: cat /etc/wireguard/privatekey + register: wireguard_private_key + changed_when: false + +- name: Register public key + ansible.builtin.shell: cat /etc/wireguard/publickey + register: wireguard_public_key + changed_when: false + +- name: Generate Preshared keyskeypair + ansible.builtin.shell: "wg genpsk > /etc/wireguard/psk-{{ item }}" + args: + creates: "/etc/wireguard/psk-{{ item }}" + when: inventory_hostname < item + with_items: "{{ groups['wireguard-mesh'] }}" + +- name: Register preshared key + ansible.builtin.shell: "cat /etc/wireguard/psk-{{ item }}" + register: wireguard_preshared_key + changed_when: false + when: inventory_hostname < item + with_items: "{{ groups['wireguard-mesh'] }}" + +- name: Massage preshared keys + ansible.builtin.set_fact: > + wireguard_preshared_keys={{ wireguard_preshared_keys|default({}) + | combine( {item.item: item.stdout} ) }} + when: item.skipped is not defined + with_items: "{{ wireguard_preshared_key.results }}" + +- name: Build config + ansible.builtin.template: + src: inframesh.conf.j2 + dest: /etc/wireguard/inframesh.conf + owner: root + mode: 0640 + +- name: Enable wireguard + ansible.builtin.systemd: + name: wg-quick@inframesh + enabled: true + +- name: Hotreload wireguard + ansible.builtin.shell: > + bash -c + "wg syncconf inframesh <(wg-quick strip inframesh)" diff --git a/playbooks/roles/wireguard-mesh/templates/inframesh.conf.j2 b/playbooks/roles/wireguard-mesh/templates/inframesh.conf.j2 new file mode 100644 index 0000000..aa15d23 --- /dev/null +++ b/playbooks/roles/wireguard-mesh/templates/inframesh.conf.j2 @@ -0,0 +1,17 @@ +[Interface] +Address={{ wireguard_node_ips[inventory_hostname] }}/32 +SaveConfig=true +ListenPort={{ wireguard_listen_port }} +PrivateKey={{ wireguard_private_key.stdout }} + +{% for peer in groups['wireguard-mesh'] %} +{% if peer != inventory_hostname %} + +[Peer] +PublicKey={{ hostvars[peer].wireguard_public_key.stdout }} +PresharedKey={{ wireguard_preshared_keys[peer] if inventory_hostname < peer else hostvars[peer].wireguard_preshared_keys[inventory_hostname] }} +AllowedIPs={{ wireguard_node_ips[peer] }}/32 +Endpoint={{ peer | replace('.int.', '.pub.') }}:{{ wireguard_listen_port }} + +{% endif %} +{% endfor %}