commit 38e79b3659595dae8b7a6c04c2cb17e75d5ae267 Author: Brian Lee Date: Tue May 23 08:30:17 2023 -0700 Rewrote playbook as a role. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d93ab0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +vars/targets/*.yml +!vars/targets/example.yml \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..4baac1e --- /dev/null +++ b/LICENSE @@ -0,0 +1,17 @@ +MIT No Attribution License + +Copyright (c) 2023 Brian Lee + +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. + +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/README.md b/README.md new file mode 100644 index 0000000..d53f170 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Ansible Role: Wireguard + +This Ansible Role manages wireguard configuration. + +## Requirements + +None. + +## Platforms + +Any distro with a repository that has wireguard-tools. It has only been tested on the following: + +* Ubuntu 22.04 +* Debian 11 + +### Legacy systems + +For distros that do not have the package in their repositories, see the [official installation instructions](https://www.wireguard.com/install/) for your specific distro. + +For example, the older Debian 10 buster basically needs you to build the module for the kernel using dkms: + +```bash +apt-get install linux-headers-$(uname -r) +apt-get reinstall wireguard-dkms +``` + +## Role Variables + +Available variables are listed below, along with default values (see `defaults/main.yml`): + +```yaml +wireguard_public_key: '..' +wireguard_private_key: '..' +wireguard_subnet: 10.0.0.0/24 +wireguard_address: 10.0.0.1/24 +wireguard_listen_port: 42069 +wireguard_peers: + - { allowed_ips: '10.0.0.100/32', public_key: '..' } +``` + +## Secrets + +I use [pass](https://www.passwordstore.org/) as a local secret store, which keeps credentials outside of any source code repository. To add credentials for a new host, generate a new key pair for a host `example.acme.com`: + +```bash +key=$(wg genkey) +echo $key | pass insert -e example.com/hostname/WIREGUARD_PRIVATE_KEY +echo $key | wg pubkey +unset key +``` + +Then add an entry to your `.env` so you can source the private key before the playbook runs. + +```bash +export example_WIREGUARD_PRIVATE_KEY=$(pass acme.com/example/WIREGUARD_PRIVATE_KEY) +``` + +## Example Playbook + +```yaml +- hosts: all + roles: + - bleetube.wireguard +``` \ No newline at end of file diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..38e22a0 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,11 @@ +--- +wireguard_snat_address: "{{ ansible_default_ipv4.address|default(ansible_all_ipv4_addresses[0]) }}" +wireguard_inet_if: "{{ ansible_default_ipv4.interface }}" +wireguard_if: wg0 +wireguard_forward_targets: + - 0.0.0.0/0 +wireguard_packages: + - iptables # missing in some Debian 11 cloudimages + - tcpdump + - wireguard + - wireguard-tools \ No newline at end of file diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..38309c2 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: restart {{ wireguard_if }} + ansible.builtin.service: + name: wg-quick@{{ wireguard_if }} + state: restarted \ No newline at end of file diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..6099501 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,2 @@ +--- +dependencies: [] \ No newline at end of file diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..c054183 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,47 @@ +--- +#- name: Load target host configuration if it is defined. +# ansible.builtin.include_vars: +# file: "{{ item }}" +# with_first_found: +# - files: +# - "vars/targets/{{ inventory_hostname_short }}.yml" +# - "../../host_vars/wireguard/{{ inventory_hostname_short }}.yml" +# skip: true +# tags: test + +- name: Assert the private key has been configured. + ansible.builtin.assert: + that: + - wireguard_private_key != '' + fail_msg: "FAILED: Wireguard private key is not set." + no_log: true + +- name: Install and update Wireguard related packages + ansible.builtin.package: + name: "{{ item }}" + state: latest + loop: "{{ wireguard_packages }}" + +# https://docs.ansible.com/ansible/latest/collections/ansible/posix/sysctl_module.html +- ansible.posix.sysctl: + name: "{{ item }}" + value: 1 + sysctl_set: yes + loop: + - net.ipv4.ip_forward + - net.ipv6.conf.all.forwarding + +# TODO: come up with a way to have different routing policy templates for different hosts +- name: Configure Wireguard forwarding + ansible.builtin.template: + src: routes.sh.j2 + dest: /etc/wireguard/routes.sh + mode: '0755' + +- name: Configure Wireguard tunnel + ansible.builtin.template: + src: interface.conf.j2 + dest: "/etc/wireguard/{{ wireguard_if }}.conf" + mode: '0600' + notify: "restart {{ wireguard_if }}" + tags: interface diff --git a/templates/interface.conf.j2 b/templates/interface.conf.j2 new file mode 100644 index 0000000..41ea533 --- /dev/null +++ b/templates/interface.conf.j2 @@ -0,0 +1,13 @@ +[Interface] +Address = {{ wireguard_address }} +PostUp = /etc/wireguard/routes.sh add +PostDown = /etc/wireguard/routes.sh del +ListenPort = {{ wireguard_listen_port }} +PrivateKey = {{ wireguard_private_key }} +SaveConfig = false + +{% for peer in wireguard_peers %} +[Peer] +PublicKey = {{ peer.public_key }} +AllowedIPs = {{ peer.allowed_ips }} +{% endfor %} diff --git a/templates/routes.sh.j2 b/templates/routes.sh.j2 new file mode 100644 index 0000000..a0e7579 --- /dev/null +++ b/templates/routes.sh.j2 @@ -0,0 +1,22 @@ +#!/bin/bash +set -x + + +if [[ "add" == ${1} ]] +then +{% for forward_target in wireguard_forward_targets %} + iptables -A FORWARD -i {{ wireguard_if }} -d {{ forward_target }} -j ACCEPT +{% endfor %} + iptables -A FORWARD -o {{ wireguard_if }} -j ACCEPT + iptables -t nat -A POSTROUTING -s {{ wireguard_subnet }} -o {{ wireguard_inet_if }} -j SNAT --to-source {{ wireguard_snat_address }} + iptables -P FORWARD DROP +fi + +if [[ "del" == ${1} ]] +then +{% for forward_target in wireguard_forward_targets %} + iptables -D FORWARD -i {{ wireguard_if }} -d {{ forward_target }} -j ACCEPT +{% endfor %} + iptables -D FORWARD -o {{ wireguard_if }} -j ACCEPT + iptables -t nat -D POSTROUTING -s {{ wireguard_subnet }} -o {{ wireguard_inet_if }} -j SNAT --to-source {{ wireguard_snat_address }} +fi