diff --git a/.gitignore b/.gitignore index 7193b27..007ec54 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ megalinter-reports/ inventories/production .galaxy/ +inventories/test/wireguard_configs diff --git a/ansible.cfg b/ansible.cfg index e5bb87f..9393156 100644 --- a/ansible.cfg +++ b/ansible.cfg @@ -4,3 +4,4 @@ inventory = inventories/default/hosts interpreter_python = /usr/bin/python3.12 no_log = ${ANSIBLE_NO_LOG:true} inventory_ignore_patterns = ^wireguard_configs/.*$,^netplan_configs/.*$,^ssh_keys/.*$ +inventory_ignore_extensions = .orig,.bak,.swp,.vaulted diff --git a/inventories/test/group_vars/all/vars.yml b/inventories/test/group_vars/all/vars.yml index 73f3c45..b8c9b3f 100644 --- a/inventories/test/group_vars/all/vars.yml +++ b/inventories/test/group_vars/all/vars.yml @@ -10,3 +10,4 @@ bootstrap_user: "test-bootstrap" dns1: 8.8.8.8 dns2: 8.8.4.4 disable_ipv6: false +manage_ufw: false diff --git a/inventories/test/group_vars/wireguard/vars.yml b/inventories/test/group_vars/wireguard/vars.yml index 29ab310..a045ad0 100644 --- a/inventories/test/group_vars/wireguard/vars.yml +++ b/inventories/test/group_vars/wireguard/vars.yml @@ -1,9 +1,13 @@ --- -wireguard_port: 51821 +wireguard_port: 51842 wireguard_endpoint: "vpn.example.com" -wireguard_allowed_ips: "10.10.0.1/32, 192.168.0.1/24" +wireguard_allowed_lan_ips: "10.10.0.1/32, 192.168.0.1/24" +wireguard_dns_servers: [8.8.8.8] wireguard_client_peers: - name: "alice" ip: "10.10.0.2/32" - name: "bob" ip: "10.10.0.3/32" +# default is inventory_dir/wireguard_configs +# moved outside of inventory_dir since this breaks molecule tests +local_wireguard_config_dir: "/tmp/molecule/wireguard_configs" diff --git a/inventories/test/hosts b/inventories/test/hosts index be906c6..904eaaa 100644 --- a/inventories/test/hosts +++ b/inventories/test/hosts @@ -1,2 +1,5 @@ [example_group] #testhost ansible_host=10.42.42.42 + +[wireguard] +testhost-ubuntu-24.04 diff --git a/inventories/test/wireguard_configs/.gitkeep b/inventories/test/wireguard_configs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/molecule/wireguard/converge.yml b/molecule/wireguard/converge.yml index 8f9f1da..b810c16 100644 --- a/molecule/wireguard/converge.yml +++ b/molecule/wireguard/converge.yml @@ -1,6 +1,6 @@ --- - name: Converge - hosts: all + hosts: wireguard become: yes roles: diff --git a/molecule/wireguard/molecule.yml b/molecule/wireguard/molecule.yml index 59e489e..090b5ee 100644 --- a/molecule/wireguard/molecule.yml +++ b/molecule/wireguard/molecule.yml @@ -19,3 +19,4 @@ provisioner: group_vars: "../../inventories/test/group_vars/" host_vars: "../../inventories/test/host_vars/" hosts: "../../inventories/test/hosts" + diff --git a/molecule/wireguard/tests/test_wireguard-client-configs.py b/molecule/wireguard/tests/test_wireguard-client-configs.py new file mode 100644 index 0000000..98bc95a --- /dev/null +++ b/molecule/wireguard/tests/test_wireguard-client-configs.py @@ -0,0 +1,19 @@ +from pathlib import Path + +def test_wireguard_config_dir_exists_locally(): + client_config_dir: Path = Path("/tmp/molecule/wireguard_configs/clients/alice") + + assert client_config_dir.exists(), f"{client_config_dir} missing on controller" + assert client_config_dir.is_dir(), f"{client_config_dir} is not a directory on controller" + +def test_wireguard_client_config(): + client_config_dir: Path = Path("/tmp/molecule/wireguard_configs/clients/alice") + + assert client_config_dir.exists(), f"{client_config_dir} missing on controller" + assert client_config_dir.is_dir(), f"{client_config_dir} is not a directory on controller" + + client_all_config_file: Path = client_config_dir / "vpn-acme-all.conf.vaulted" + assert client_all_config_file.exists(), f"{client_all_config_file} missing in local inventory" + + client_lan_config_file: Path = client_config_dir / "vpn-acme-lan.conf.vaulted" + assert client_lan_config_file.exists(), f"{client_lan_config_file} missing in local inventory" diff --git a/molecule/wireguard/tests/test_wireguard-server.py b/molecule/wireguard/tests/test_wireguard-server.py index 6d48087..82812a6 100644 --- a/molecule/wireguard/tests/test_wireguard-server.py +++ b/molecule/wireguard/tests/test_wireguard-server.py @@ -1,3 +1,6 @@ +import re +import pytest + def test_wireguard_config_file_exists(host): config_file = host.file("/etc/wireguard/wg0.conf") @@ -6,7 +9,6 @@ def test_wireguard_config_file_exists(host): def test_wireguard_config_file_permissions(host): - """Test that the WireGuard configuration file has correct permissions.""" config_file = host.file("/etc/wireguard/wg0.conf") # WireGuard config files should be readable only by root for security @@ -15,15 +17,38 @@ def test_wireguard_config_file_permissions(host): assert config_file.mode == 0o600 -def test_wireguard_config_file_content(host): - """Test that the WireGuard configuration file contains expected content.""" +def test_wireguard_server_conf_content(host): config_file = host.file("/etc/wireguard/wg0.conf") - content = config_file.content_string + wg0_conf_content = config_file.content_string + + # server part + assert "[Interface]" in wg0_conf_content + assert "# Ansible managed" in wg0_conf_content + assert "Address = 10.10.0.1/24" in wg0_conf_content + assert "ListenPort = 51842" in wg0_conf_content + assert "PrivateKey = " in wg0_conf_content + assert "DNS = 8.8.8.8" in wg0_conf_content + + # client peer part + alice_peer = ( + r'# BEGIN peer alice\n' + r'\[Peer\]\n' + r'PublicKey = [A-Za-z0-9+/]{43}=\n' + r'AllowedIPs = 10\.10\.0\.2/32\n' + r'PreSharedKey = [A-Za-z0-9+/]{43}=\n' + r'# END peer alice' + ) + + assert re.search(alice_peer, wg0_conf_content), "alice peer section not found or invalid format" + + bob_peer = ( + r'# BEGIN peer bob\n' + r'\[Peer\]\n' + r'PublicKey = [A-Za-z0-9+/]{43}=\n' + r'AllowedIPs = 10\.10\.0\.3/32\n' + r'PreSharedKey = [A-Za-z0-9+/]{43}=\n' + r'# END peer bob' + ) - # Check for required sections and parameters - assert "[Interface]" in content - assert "# Ansible managed" in content - assert "Address = 10.10.0.1/24" in content - assert "ListenPort = 51820" in content - assert "PrivateKey = " in content + assert re.search(bob_peer, wg0_conf_content), "bob peer section not found or invalid format" diff --git a/roles/wireguard/README.md b/roles/wireguard/README.md new file mode 100644 index 0000000..6f01165 --- /dev/null +++ b/roles/wireguard/README.md @@ -0,0 +1,28 @@ +# Wireguard + +this role takes care of installing and configuring wireguard: + +- installs wireguard on the server +- generates the server config +- generates the client config (stored in local inventory) +- sets up ufw config (NAT) for wireguard (ufw rules have to configured in ufw role) + +## Client config + +configure clients in inventory `group_vars/wireguard` like so: + +```yaml +wireguard_client_peers: + - name: "alice" + ip: "10.10.0.2/32" +``` + +configs are stored and encrypted (ansible-vault) locally in `inventories/production/wireguard_configs/clients` + +to generate the QR code for the client config, run: + +`ansible-vault view vpn-acme-all.conf.vault | qrencode -t ansiutf8` + +or import the config into network manager after decrypting: + +`nmcli connection import type wireguard file vpn-acme-all.conf` diff --git a/roles/wireguard/defaults/main.yml b/roles/wireguard/defaults/main.yml index 0343d15..a7a5817 100644 --- a/roles/wireguard/defaults/main.yml +++ b/roles/wireguard/defaults/main.yml @@ -1,18 +1,21 @@ --- +wireguard_company: "acme" wireguard_interface: wg0 wireguard_internal_server_ip: "10.10.0.1/24" +wireguard_subnet: "10.10.0.0/24" +wireguard_external_interface: "eth0" wireguard_port: 51820 # Peers configuration wireguard_client_peers: [] # Example: -# wireguard_peers: +# wireguard_client_peers: # - name: "alice" # ip: "10.10.0.2/32" # DNS servers (optional) -wireguard_dns: [] +wireguard_dns_servers: [10.10.0.1] # MTU (optional) wireguard_mtu: "" @@ -20,3 +23,5 @@ wireguard_mtu: "" # PostUp and PostDown commands (optional) wireguard_post_up: [] wireguard_post_down: [] + +manage_ufw: true diff --git a/roles/wireguard/handlers/main.yml b/roles/wireguard/handlers/main.yml index 2f987f1..790723d 100644 --- a/roles/wireguard/handlers/main.yml +++ b/roles/wireguard/handlers/main.yml @@ -3,3 +3,7 @@ ansible.builtin.systemd: name: "wg-quick@{{ wireguard_interface }}" state: restarted + +- name: reload ufw + community.general.ufw: + state: reloaded diff --git a/roles/wireguard/tasks/2_server-config.yml b/roles/wireguard/tasks/2_server-config.yml index cc81400..374d2f9 100644 --- a/roles/wireguard/tasks/2_server-config.yml +++ b/roles/wireguard/tasks/2_server-config.yml @@ -7,79 +7,12 @@ owner: root group: root -- name: Set wg config file path - ansible.builtin.set_fact: - wireguard_config_path: "/etc/wireguard/{{ wireguard_interface }}.conf" - -- name: Check if WireGuard config exists - stat: - path: "{{ wireguard_config_path }}" - register: wireguard_config_stat - -- name: When WireGuard config exists, extract existing key - when: wireguard_config_stat.stat.exists - block: - - name: Extract WireGuard private key if present - shell: "grep '^PrivateKey' {{ wireguard_config_path }} | awk '{print $3}'" - register: wireguard_private_key - changed_when: false - when: wireguard_config_stat.stat.exists - - name: Set private key fact - ansible.builtin.set_fact: - wireguard_private_key: "{{ wireguard_private_key.stdout }}" - no_log: true - rescue: - - name: there was an error extracting the private key - debug: - msg: "there was an error extracting wireguard private key in existing config on {{ inventory_hostname }}." - - name: Fail explicitly after extracting private key error - fail: - msg: "extracting wireguard private key failed on {{ inventory_hostname }}." - always: - - name: extract wireguard private key block finished (success or failure) - debug: - msg: "extracting wireguard private key block finished on {{ inventory_hostname }}." - -- name: When WireGuard config does not yet exist - when: not wireguard_config_stat.stat.exists - block: - - name: Generate WireGuard private key - ansible.builtin.shell: | - wg genkey - register: wireguard_private_key_generated - changed_when: false - when: not wireguard_config_stat.stat.exists - no_log: true - - name: Set private key fact - ansible.builtin.set_fact: - wireguard_private_key: "{{ wireguard_private_key_generated.stdout }}" - no_log: true - rescue: - - name: there was an error generating the private key - debug: - msg: "there was an error generating wireguard private key on {{ inventory_hostname }}." - - name: Fail explicitly after wireguard private key generation error - fail: - msg: "wireguard private key generation failed failed on {{ inventory_hostname }}." - always: - - name: generating wireguard private key block finished (success or failure) - debug: - msg: "generating wireguard private key block finished on {{ inventory_hostname }}." - -- name: Generate WireGuard public key - ansible.builtin.shell: | - echo "{{ wireguard_private_key }}" | wg pubkey - register: wireguard_public_key - changed_when: false - no_log: true - -- name: Set public key fact - ansible.builtin.set_fact: - wireguard_public_key: "{{ wireguard_public_key.stdout }}" +- name: When WireGuard config exists, extract existing keys + include_tasks: "process-server-keys.yml" - name: Display public key ansible.builtin.debug: - msg: "WireGuard Public Key: {{ wireguard_public_key }}" + msg: "WireGuard Public Key: {{ wireguard_server_public_key }}" - name: Deploy WireGuard interface configuration ansible.builtin.template: @@ -88,10 +21,4 @@ mode: '0600' owner: root group: root - notify: Restart WireGuard - -- name: Enable and start WireGuard interface - ansible.builtin.systemd: - name: "wg-quick@{{ wireguard_interface }}" - enabled: true - state: started + changed_when: false diff --git a/roles/wireguard/tasks/3_clients.yml b/roles/wireguard/tasks/3_clients.yml index d5432d0..da55298 100644 --- a/roles/wireguard/tasks/3_clients.yml +++ b/roles/wireguard/tasks/3_clients.yml @@ -1,15 +1,14 @@ --- +- name: Load common wireguard facts + include_tasks: "facts.yml" + - name: Set local_user ansible.builtin.set_fact: local_user: "{{ lookup('env', 'USER') }}" -- name: Set local_wireguard_config_dir - ansible.builtin.set_fact: - local_wireguard_config_dir: "{{ inventory_dir }}/wireguard_configs" - - name: Set local_wireguard_client_config_dir ansible.builtin.set_fact: - local_wireguard_client_config_dir: "{{ inventory_dir }}/wireguard_configs/clients" + local_wireguard_client_config_dir: "{{ local_wireguard_config_dir }}/clients" - name: Make sure client config directory exists for given inventory delegate_to: localhost @@ -20,3 +19,9 @@ owner: "{{ local_user }}" group: "{{ local_user }}" changed_when: false + +- name: Create client config files + include_tasks: "create-client-config.yml" + loop_control: + loop_var: client + loop: "{{ wireguard_client_peers }}" diff --git a/roles/wireguard/tasks/4_ufw.yml b/roles/wireguard/tasks/4_ufw.yml new file mode 100644 index 0000000..a9c42fd --- /dev/null +++ b/roles/wireguard/tasks/4_ufw.yml @@ -0,0 +1,4 @@ +--- +- name: Setup wireguard ufw config + include_tasks: "ufw.yml" + when: manage_ufw diff --git a/roles/wireguard/tasks/5_service.yml b/roles/wireguard/tasks/5_service.yml new file mode 100644 index 0000000..78a2843 --- /dev/null +++ b/roles/wireguard/tasks/5_service.yml @@ -0,0 +1,6 @@ +--- +- name: Enable and start WireGuard interface + ansible.builtin.systemd: + name: "wg-quick@{{ wireguard_interface }}" + enabled: true + state: restarted diff --git a/roles/wireguard/tasks/9_local-config-backup.yml b/roles/wireguard/tasks/9_local-config-backup.yml index 3041dfa..865bf22 100644 --- a/roles/wireguard/tasks/9_local-config-backup.yml +++ b/roles/wireguard/tasks/9_local-config-backup.yml @@ -1,4 +1,7 @@ --- +- name: Load common wireguard facts + include_tasks: "facts.yml" + - name: Set local_user ansible.builtin.set_fact: local_user: "{{ lookup('env', 'USER') }}" @@ -23,10 +26,8 @@ - name: Make sure wireguard_configs directory exists for given inventory delegate_to: localhost - become: yes - become_user: "{{ local_user }}" ansible.builtin.file: - path: "{{ inventory_dir }}/wireguard_configs" + path: "{{ local_wireguard_config_dir }}" state: directory mode: "0700" owner: "{{ local_user }}" @@ -50,13 +51,20 @@ run_once: true changed_when: false -- name: Encrypt the fetched file with Ansible Vault +- name: Encrypt server config for if it has changed delegate_to: localhost become: yes become_user: "{{ local_user }}" - command: "ansible-vault encrypt {{ local_tmp_server_bkp_config_path }} --output {{ inventory_dir }}/wireguard_configs/wg0.conf.vault" - ignore_errors: yes - run_once: true + shell: | + set -euo pipefail + if [ -f "{{ local_wireguard_config_dir }}/wg0.conf.vaulted" ]; then + if ansible-vault view "{{ local_wireguard_config_dir }}/wg0.conf.vaulted" | cmp -s - "{{ local_tmp_server_bkp_config_path }}"; then + exit 0 + fi + fi + ansible-vault encrypt "{{ local_tmp_server_bkp_config_path }}" --output "{{ local_wireguard_config_dir }}/wg0.conf.vaulted" + args: + executable: /bin/bash changed_when: false - name: Remove the unencrypted fetched file diff --git a/roles/wireguard/tasks/create-client-config.yml b/roles/wireguard/tasks/create-client-config.yml new file mode 100644 index 0000000..33ec8e3 --- /dev/null +++ b/roles/wireguard/tasks/create-client-config.yml @@ -0,0 +1,144 @@ +--- +- name: Set client config all path + ansible.builtin.set_fact: + client_config_all_path: "{{ local_wireguard_client_config_dir }}/{{ client.name }}/vpn-{{ wireguard_company }}-all.conf" + +- name: Set client config lan path + ansible.builtin.set_fact: + client_config_lan_path: "{{ local_wireguard_client_config_dir }}/{{ client.name }}/vpn-{{ wireguard_company }}-lan.conf" + +- name: Extract existing server keys + include_tasks: "process-server-keys.yml" + +- name: Make sure client config dir exists for given client + delegate_to: localhost + ansible.builtin.file: + path: "{{ local_wireguard_client_config_dir }}/{{ client.name }}" + state: directory + mode: "0700" + owner: "{{ local_user }}" + group: "{{ local_user }}" + +- name: Check if client config exists + delegate_to: localhost + stat: + path: "{{ client_config_all_path }}.vaulted" + register: client_config_stat + +- name: Create client private key + ansible.builtin.shell: | + wg genkey + register: generated_client_private_key + when: not client_config_stat.stat.exists + +- name: Extract client config private key if present + delegate_to: localhost + become: yes + become_user: "{{ local_user }}" + shell: "ansible-vault view {{ client_config_all_path }}.vaulted | grep '^PrivateKey' | awk '{print $3}'" + register: existing_client_private_key + changed_when: false + when: client_config_stat.stat.exists + +- name: set client_private_key + ansible.builtin.set_fact: + client_private_key: "{{ existing_client_private_key.stdout | default(generated_client_private_key.stdout) }}" + +- name: Extract client config preshared key if present + delegate_to: localhost + become: yes + become_user: "{{ local_user }}" + shell: "ansible-vault view {{ client_config_all_path }}.vaulted | grep '^PresharedKey' | awk '{print $3}'" + register: existing_client_preshared_key + changed_when: false + when: client_config_stat.stat.exists + +- name: Create client private key + ansible.builtin.shell: | + wg genpsk + register: generated_client_preshared_key + when: not client_config_stat.stat.exists + +- name: set client_preshared_key + ansible.builtin.set_fact: + client_preshared_key: "{{ existing_client_preshared_key.stdout | default(generated_client_preshared_key.stdout) }}" + +- name: Create client config for {{ client.name }} (all) + delegate_to: localhost + ansible.builtin.template: + src: "client-peer-all.conf.j2" + dest: "{{ client_config_all_path }}" + mode: "0600" + owner: "{{ local_user }}" + group: "{{ local_user }}" + changed_when: false + +- name: Encrypt client config for {{ client.name }} (all) if it has changed + delegate_to: localhost + become: yes + become_user: "{{ local_user }}" + shell: | + set -euo pipefail + if [ -f "{{ client_config_all_path }}.vaulted" ]; then + if ansible-vault view "{{ client_config_all_path }}.vaulted" | cmp -s - "{{ client_config_all_path }}"; then + exit 0 + fi + fi + ansible-vault encrypt "{{ client_config_all_path }}" --output "{{ client_config_all_path }}.vaulted" + args: + executable: /bin/bash + changed_when: false + +- name: Create client config for {{ client.name }} (lan) + delegate_to: localhost + ansible.builtin.template: + src: "client-peer-lan.conf.j2" + dest: "{{ client_config_lan_path }}" + mode: "0600" + owner: "{{ local_user }}" + group: "{{ local_user }}" + changed_when: false + +- name: Encrypt client config for {{ client.name }} (lan) if it has changed + delegate_to: localhost + become: yes + become_user: "{{ local_user }}" + shell: | + set -euo pipefail + if [ -f "{{ client_config_lan_path }}.vaulted" ]; then + if ansible-vault view "{{ client_config_lan_path }}.vaulted" | cmp -s - "{{ client_config_lan_path }}"; then + exit 0 + fi + fi + ansible-vault encrypt "{{ client_config_lan_path }}" --output "{{ client_config_lan_path }}.vaulted" + args: + executable: /bin/bash + changed_when: false + +- name: Shred and delete unencrypted config files + delegate_to: localhost + become: yes + become_user: "{{ local_user }}" + ansible.builtin.shell: | + shred -u "{{ config }}" + loop: "{{ [client_config_all_path, client_config_lan_path] }}" + loop_control: + loop_var: config + changed_when: false + +- name: Extract client public key + shell: "echo '{{ client_private_key }}' | wg pubkey" + register: client_public_key + changed_when: false + +- name: Set client public key fact + ansible.builtin.set_fact: + client_public_key: "{{ client_public_key.stdout }}" + +- name: Append peer config to server config + ansible.builtin.blockinfile: + path: /etc/wireguard/{{ wireguard_interface }}.conf + block: "{{ lookup('template', 'client-peer-section.conf.j2') }}" + marker: "# {mark} peer {{ client.name }}" + insertafter: EOF + changed_when: false diff --git a/roles/wireguard/tasks/facts.yml b/roles/wireguard/tasks/facts.yml new file mode 100644 index 0000000..1579fe7 --- /dev/null +++ b/roles/wireguard/tasks/facts.yml @@ -0,0 +1,5 @@ +--- +- name: Set local_wireguard_config_dir + ansible.builtin.set_fact: + local_wireguard_config_dir: "{{ inventory_dir }}/wireguard_configs" + when: local_wireguard_config_dir is not defined diff --git a/roles/wireguard/tasks/process-server-keys.yml b/roles/wireguard/tasks/process-server-keys.yml new file mode 100644 index 0000000..e3c854d --- /dev/null +++ b/roles/wireguard/tasks/process-server-keys.yml @@ -0,0 +1,39 @@ +--- +- name: Set wg config file path + ansible.builtin.set_fact: + wireguard_server_config_path: "/etc/wireguard/{{ wireguard_interface }}.conf" + +- name: Check if WireGuard config exists + stat: + path: "{{ wireguard_server_config_path }}" + register: wireguard_server_config_stat + +- name: Extract WireGuard private key if present + shell: "grep '^PrivateKey' {{ wireguard_server_config_path }} | awk '{print $3}'" + register: existing_wireguard_server_private_key + changed_when: false + when: wireguard_server_config_stat.stat.exists + +- name: Generate WireGuard private key + ansible.builtin.shell: | + wg genkey + register: wireguard_server_private_key_generated + changed_when: false + when: not wireguard_server_config_stat.stat.exists + no_log: true + +- name: Set server private key fact + ansible.builtin.set_fact: + wireguard_server_private_key: "{{ existing_wireguard_server_private_key.stdout | default(wireguard_server_private_key_generated.stdout) }}" + no_log: true + +- name: Extract WireGuard public key if present + shell: "echo '{{ wireguard_server_private_key }}' | wg pubkey" + register: wireguard_server_public_key + changed_when: false + when: wireguard_server_private_key is defined + +- name: Set public key fact + ansible.builtin.set_fact: + wireguard_server_public_key: "{{ wireguard_server_public_key.stdout }}" + when: wireguard_server_private_key is defined diff --git a/roles/wireguard/tasks/ufw.yml b/roles/wireguard/tasks/ufw.yml new file mode 100644 index 0000000..c415b14 --- /dev/null +++ b/roles/wireguard/tasks/ufw.yml @@ -0,0 +1,29 @@ +--- +- name: Set UFW default forward policy to ACCEPT + lineinfile: + path: "/etc/default/ufw" + regexp: "^DEFAULT_FORWARD_POLICY=" + line: 'DEFAULT_FORWARD_POLICY="ACCEPT"' + backup: yes + notify: reload ufw + +- name: Check if NAT rules already exist in before.rules + command: grep -q "NAT table rules for WireGuard" /etc/ufw/before.rules + register: nat_rules_exist + changed_when: false + failed_when: false + +- name: Add NAT masquerading rules to UFW before.rules + blockinfile: + path: /etc/ufw/before.rules + insertbefore: '^\*filter' + marker: "# {mark} ANSIBLE MANAGED BLOCK - WireGuard NAT" + block: | + # NAT table rules for WireGuard + *nat + :POSTROUTING ACCEPT [0:0] + -A POSTROUTING -s {{ wireguard_subnet }} -o {{ wireguard_external_interface }} -j MASQUERADE + COMMIT + backup: yes + when: nat_rules_exist.rc != 0 + notify: reload ufw diff --git a/roles/wireguard/templates/client-peer-all.conf.j2 b/roles/wireguard/templates/client-peer-all.conf.j2 index e69de29..a7db8c0 100644 --- a/roles/wireguard/templates/client-peer-all.conf.j2 +++ b/roles/wireguard/templates/client-peer-all.conf.j2 @@ -0,0 +1,13 @@ +[Interface] +PrivateKey = {{ client_private_key }} +Address = {{ client.ip }} +{% if wireguard_dns_servers | length > 0 %} +DNS = {{ wireguard_dns_servers | join(', ') }} +{% endif %} + +[Peer] +PublicKey = {{ wireguard_server_public_key }} +PresharedKey = {{ client_preshared_key }} +Endpoint = {{ wireguard_endpoint }}:{{ wireguard_port }} +AllowedIPs = 0.0.0.0/0 +PersistentKeepalive = 25 diff --git a/roles/wireguard/templates/client-peer-lan.conf.j2 b/roles/wireguard/templates/client-peer-lan.conf.j2 index 3fcf4f2..ded7e62 100644 --- a/roles/wireguard/templates/client-peer-lan.conf.j2 +++ b/roles/wireguard/templates/client-peer-lan.conf.j2 @@ -1,10 +1,13 @@ [Interface] -PrivateKey = {{ private_key }} -Address = {{ peer.ip }} -DNS = {{ dns1 }} +PrivateKey = {{ client_private_key }} +Address = {{ client.ip }} +{% if wireguard_dns_servers | length > 0 %} +DNS = {{ wireguard_dns_servers | join(', ') }} +{% endif %} [Peer] -PublicKey = {{ wireguard_server_public_key }} +PublicKey = {{ wireguard_server_public_key }} +PresharedKey = {{ client_preshared_key }} Endpoint = {{ wireguard_endpoint }}:{{ wireguard_port }} -AllowedIPs = {{ allowed_ips }} +AllowedIPs = {{ wireguard_allowed_lan_ips }} PersistentKeepalive = 25 diff --git a/roles/wireguard/templates/client-peer-section.conf.j2 b/roles/wireguard/templates/client-peer-section.conf.j2 new file mode 100644 index 0000000..c79a79c --- /dev/null +++ b/roles/wireguard/templates/client-peer-section.conf.j2 @@ -0,0 +1,4 @@ +[Peer] +PublicKey = {{ client_public_key }} +AllowedIPs = {{ client.ip }} +PreSharedKey = {{ client_preshared_key }} diff --git a/roles/wireguard/templates/wg-interface.conf.j2 b/roles/wireguard/templates/wg-interface.conf.j2 index 0aa63f9..5489f17 100644 --- a/roles/wireguard/templates/wg-interface.conf.j2 +++ b/roles/wireguard/templates/wg-interface.conf.j2 @@ -2,14 +2,14 @@ # {{ ansible_managed }} Address = {{ wireguard_internal_server_ip }} ListenPort = {{ wireguard_port }} -PrivateKey = {{ wireguard_private_key }} +PrivateKey = {{ wireguard_server_private_key }} {% if wireguard_mtu %} MTU = {{ wireguard_mtu }} {% endif %} -{% if wireguard_dns | length > 0 %} -DNS = {{ wireguard_dns | join(', ') }} +{% if wireguard_dns_servers | length > 0 %} +DNS = {{ wireguard_dns_servers | join(', ') }} {% endif %} {% for command in wireguard_post_up %} @@ -19,20 +19,3 @@ PostUp = {{ command }} {% for command in wireguard_post_down %} PostDown = {{ command }} {% endfor %} - -{% for peer in wireguard_client_peers %} - -[Peer] -# Peer: {{ peer.name }} -PublicKey = {{ peer.public_key }} -{% if peer.preshared_key is defined %} -PresharedKey = {{ peer.preshared_key }} -{% endif %} -AllowedIPs = {{ peer.allowed_ips }} -{% if peer.endpoint is defined %} -Endpoint = {{ peer.endpoint }} -{% endif %} -{% if peer.persistent_keepalive is defined %} -PersistentKeepalive = {{ peer.persistent_keepalive }} -{% endif %} -{% endfor %}