From 9afb4b63894b5d2a7e142e249d99fbfec763da91 Mon Sep 17 00:00:00 2001 From: Fabio Sinibaldi Date: Thu, 16 Jul 2026 19:16:24 +0200 Subject: [PATCH] Playbook vpn_server --- ansible/playbooks/README.md | 36 +++++++++- .../roles/wireguard_server/handlers/main.yaml | 5 ++ .../tasks/configure_server.yaml | 31 +++++++++ .../tasks/gather_current_config.yaml | 20 ++++++ .../tasks/generate_client_configs.yaml | 67 +++++++++++++++++++ .../tasks/generate_server_keys.yaml | 49 ++++++++++++++ .../tasks/install_wireguard.yaml | 25 +++++++ .../roles/wireguard_server/tasks/main.yaml | 6 ++ .../templates/wg_config_template.yaml | 13 ++++ .../templates/wireguard_client.jinja | 18 +++++ .../templates/wireguard_server.jinja | 27 ++++++++ ansible/playbooks/vpn_server.yaml | 6 ++ 12 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 ansible/playbooks/roles/wireguard_server/handlers/main.yaml create mode 100644 ansible/playbooks/roles/wireguard_server/tasks/configure_server.yaml create mode 100644 ansible/playbooks/roles/wireguard_server/tasks/gather_current_config.yaml create mode 100644 ansible/playbooks/roles/wireguard_server/tasks/generate_client_configs.yaml create mode 100644 ansible/playbooks/roles/wireguard_server/tasks/generate_server_keys.yaml create mode 100644 ansible/playbooks/roles/wireguard_server/tasks/install_wireguard.yaml create mode 100644 ansible/playbooks/roles/wireguard_server/tasks/main.yaml create mode 100644 ansible/playbooks/roles/wireguard_server/templates/wg_config_template.yaml create mode 100644 ansible/playbooks/roles/wireguard_server/templates/wireguard_client.jinja create mode 100644 ansible/playbooks/roles/wireguard_server/templates/wireguard_server.jinja create mode 100644 ansible/playbooks/vpn_server.yaml diff --git a/ansible/playbooks/README.md b/ansible/playbooks/README.md index 2615dc5..8cf3ecc 100644 --- a/ansible/playbooks/README.md +++ b/ansible/playbooks/README.md @@ -8,6 +8,7 @@ Implementa la configurazione di base di un nodo per poter essere gestito dagli a - crea l'utente ansible - registra le chiavi ssh degli utenti configurati +**Target Hosts : all** #### Parametri @@ -18,7 +19,6 @@ ansible_authorized_keys: key: ``` - #### Chiamata Per lanciare il playbook e' necessario specificare l'utente da utilizzare per connettersi ed esguire il playbook con l'opzione *-e*'. L'opzione '*-K*' invece permette di chiedere la password dell'utente remoto @@ -27,4 +27,36 @@ L'opzione '*-K*' invece permette di chiedere la password dell'utente remoto ansible-playbook -i inventories/.yaml playbooks/bootstrap.yaml -e 'ansible_user=' -K ``` -### VPN Server \ No newline at end of file +### VPN Server +Istanzia un server Wireguard abilitando il tunneling del traffico. + +**Target Hosts : wireguard_server** + +#### Generazione chiavi e configurazioni dei Peer +Genera in */wg_clients/< ANSIBLE_HOSTNAME >/* i file di configurazione per i peer configurati. + +**NB** +Il playbook e' a conoscenza della chiave privata del peer solo se e' stato necessario generarla durante l'esecuzione. In caso contrario viene riportata solo la chiave pubblica ed e' compito dell'utente inserire la chiave privata. + +Il playbook genera le chiavi nei seguenti casi : +- nessuna chiave pubblica e' stata fornita e il peer non e' gia' configurato sul server +- Force Regeneration = True + + + +#### Parametri +Il playbook si aspetta le seguenti variabili +``` +wg_interface: wg0 +wg_port: 51820 +wg_server_address: 192.168.101.1/32 + +wg_peers: + - name: + # publicKey: + ip: "192.168.101.4/32" + allowedIPs : + - "192.168.101.0/24" + - "10.22.0.0/16" + forceRegeneration: False +``` \ No newline at end of file diff --git a/ansible/playbooks/roles/wireguard_server/handlers/main.yaml b/ansible/playbooks/roles/wireguard_server/handlers/main.yaml new file mode 100644 index 0000000..862ff4f --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/handlers/main.yaml @@ -0,0 +1,5 @@ +--- +- name: Restart WireGuard + ansible.builtin.systemd: + name: "wg-quick@{{ wg_interface }}" + state: restarted \ No newline at end of file diff --git a/ansible/playbooks/roles/wireguard_server/tasks/configure_server.yaml b/ansible/playbooks/roles/wireguard_server/tasks/configure_server.yaml new file mode 100644 index 0000000..c3de507 --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/tasks/configure_server.yaml @@ -0,0 +1,31 @@ +# wireguard_server.yml - Configure WireGuard VPN server +--- +- name: Get Private Key [privatekey => var_privatekey] + shell: cat privatekey + register: wg_server_private_key + args: + chdir: /etc/wireguard + +- name: Deploy WireGuard server configuration + ansible.builtin.template: + src: templates/wireguard_server.jinja + dest: "/etc/wireguard/{{ wg_interface }}.conf" + owner: root + group: root + mode: '0600' + notify: Restart WireGuard + +- name: Enable and start WireGuard + ansible.builtin.systemd: + name: "wg-quick@{{ wg_interface }}" + state: started + enabled: true + +- name: Open WireGuard port in firewall + community.general.ufw: + rule: allow + port: "{{ wg_port }}" + proto: udp + comment: "WireGuard VPN" + ignore_errors: true + diff --git a/ansible/playbooks/roles/wireguard_server/tasks/gather_current_config.yaml b/ansible/playbooks/roles/wireguard_server/tasks/gather_current_config.yaml new file mode 100644 index 0000000..f1b8def --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/tasks/gather_current_config.yaml @@ -0,0 +1,20 @@ +--- +- name: Check if config already exists + stat: + path: "/etc/wireguard/{{ wg_interface }}.conf" + register: interface_configuration + +- name: Parse configuration + ansible.utils.cli_parse: + command: "cat /etc/wireguard/{{ wg_interface }}.conf " + parser: + name: ansible.netcommon.native + template_path: templates/wg_config_template.yaml + set_fact: existing_wg_config + when: interface_configuration.stat.exists + +- name: Updating client configs info + set_fact: + wg_peers: "{{ wg_peers | community.general.lists_mergeby([{'name':item.key,'publicKey':item.value.publicKey}] ,'name')}}" + when: item.key in (wg_peers | map(attribute='name')) + loop: "{{ existing_wg_config | ansible.builtin.dict2items }}" diff --git a/ansible/playbooks/roles/wireguard_server/tasks/generate_client_configs.yaml b/ansible/playbooks/roles/wireguard_server/tasks/generate_client_configs.yaml new file mode 100644 index 0000000..cda5b78 --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/tasks/generate_client_configs.yaml @@ -0,0 +1,67 @@ +--- +- name: Init generated Keys dict + set_fact: + generated_keys: [] + +- name : Gather needed key generation + set_fact: + generated_keys: "{{ generated_keys + [{'name': item.name}] }}" + when : item.publicKey is not defined or (item.forceRegeneration is defined and item.forceRegeneration) + loop: "{{ wg_peers }}" + +- name : Generate private keys + command : wg genkey + register: privateKeyObjects + loop : "{{ generated_keys }}" + + +- name : Generate public keys + shell : echo "{{privateKeyObjects.results[ansible_loop.index0].stdout}}" | wg pubkey + register: publicKeyObjects + loop : "{{ generated_keys }}" + loop_control: + extended: true + +- name: Registering generated keys + set_fact: + generated_keys: "{{ generated_keys | community.general.lists_mergeby ([{'privateKey' : privateKeyObjects.results[ansible_loop.index0].stdout, 'publicKey' : publicKeyObjects.results[ansible_loop.index0].stdout, 'name':item.name }],'name') }}" + loop: "{{ generated_keys }}" + loop_control: + extended: true + +- name: Updating client configs info + set_fact: + wg_peers: "{{ wg_peers | community.general.lists_mergeby(generated_keys,'name')}}" + + +- name: Delete local configs directory + become: false + local_action : ansible.builtin.file + args: + path: "{{ playbook_dir }}/wg_clients/{{ inventory_hostname }}" + state: absent + + +- name: Re-create local configs directory + become: false + local_action : ansible.builtin.file + args: + path: "{{ playbook_dir }}/wg_clients/{{ inventory_hostname }}" + state: directory + mode: '0700' + + + +- name : Generate client config file + become: false + local_action : ansible.builtin.template + args: + src: templates/wireguard_client.jinja + dest: "{{ playbook_dir }}/wg_clients/{{ inventory_hostname }}/{{ item.name }}.conf" + vars: + wg_client_public_key: "{{ item.publicKey }}" + wg_client_private_key: "{{ item.privateKey | default('')}}" + wg_client_address: "{{ item.ip }}" + allowed_ips : "{{ item.allowedIPs }}" + wg_server : "{{ inventory_hostname }}" + loop: "{{ wg_peers }}" diff --git a/ansible/playbooks/roles/wireguard_server/tasks/generate_server_keys.yaml b/ansible/playbooks/roles/wireguard_server/tasks/generate_server_keys.yaml new file mode 100644 index 0000000..27b11d5 --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/tasks/generate_server_keys.yaml @@ -0,0 +1,49 @@ +# generate_keys.yml - Generate WireGuard key pairs +--- +- name: Create WireGuard directory + ansible.builtin.file: + path: /etc/wireguard + state: directory + mode: '0700' + +- name: Check if server private key already exists + ansible.builtin.stat: + path: /etc/wireguard/privatekey + register: privatekey_file + +- name: Generate server private key + ansible.builtin.command: wg genkey + register: wg_private_key + when: not privatekey_file.stat.exists + changed_when: true + +- name: Save server private key + ansible.builtin.copy: + content: "{{ wg_private_key.stdout }}" + dest: /etc/wireguard/privatekey + owner: root + group: root + mode: '0600' + when: not privatekey_file.stat.exists + +- name: Read server private key + ansible.builtin.slurp: + src: /etc/wireguard/privatekey + register: private_key_content + +- name: Generate server public key from private key + ansible.builtin.shell: echo "{{ private_key_content.content | b64decode | trim }}" | wg pubkey + register: wg_server_public_key + changed_when: false + +- name: Save server public key + ansible.builtin.copy: + content: "{{ wg_server_public_key.stdout }}" + dest: /etc/wireguard/publickey + owner: root + group: root + mode: '0644' + +- name: Display public key for reference + ansible.builtin.debug: + msg: "Public key for {{ inventory_hostname }}: {{ wg_server_public_key.stdout }}" \ No newline at end of file diff --git a/ansible/playbooks/roles/wireguard_server/tasks/install_wireguard.yaml b/ansible/playbooks/roles/wireguard_server/tasks/install_wireguard.yaml new file mode 100644 index 0000000..b297304 --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/tasks/install_wireguard.yaml @@ -0,0 +1,25 @@ +# install_wireguard.yml - Install WireGuard on Linux hosts +--- +- name: Install WireGuard on Debian/Ubuntu + ansible.builtin.apt: + name: + - wireguard + - wireguard-tools + state: present + update_cache: true + when: ansible_os_family == "Debian" + +- name: Install WireGuard on RHEL/CentOS 8+ + ansible.builtin.yum: + name: + - wireguard-tools + state: present + when: ansible_os_family == "RedHat" + +- name: Enable IP forwarding + ansible.posix.sysctl: + name: net.ipv4.ip_forward + value: '1' + sysctl_set: true + state: present + reload: true diff --git a/ansible/playbooks/roles/wireguard_server/tasks/main.yaml b/ansible/playbooks/roles/wireguard_server/tasks/main.yaml new file mode 100644 index 0000000..5de9e1a --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/tasks/main.yaml @@ -0,0 +1,6 @@ +--- +- include_tasks: install_wireguard.yaml +- include_tasks: gather_current_config.yaml +- include_tasks: generate_server_keys.yaml +- include_tasks: generate_client_configs.yaml +- include_tasks: configure_server.yaml diff --git a/ansible/playbooks/roles/wireguard_server/templates/wg_config_template.yaml b/ansible/playbooks/roles/wireguard_server/templates/wg_config_template.yaml new file mode 100644 index 0000000..84986d5 --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/templates/wg_config_template.yaml @@ -0,0 +1,13 @@ +--- +- example: "# Peer ID : fabio_test" + getval: '# Peer ID : (?P\S+)' + result: + "{{ peer_id }}": + name: "{{ peer_id }}" + shared: true + +- example: "PublicKey = 9a3tgXpF5CAOffbHZdW1QBEJgSLFnBDVbD1JaMPgzkM=" + getval: 'PublicKey = (?P\S+)' + result: + "{{ peer_id }}": + publicKey: "{{ publicKey }}" \ No newline at end of file diff --git a/ansible/playbooks/roles/wireguard_server/templates/wireguard_client.jinja b/ansible/playbooks/roles/wireguard_server/templates/wireguard_client.jinja new file mode 100644 index 0000000..7a7b20c --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/templates/wireguard_client.jinja @@ -0,0 +1,18 @@ +[Interface] +{% if wg_client_private_key is defined and wg_client_private_key != None and wg_client_private_key != ''%} +PrivateKey = {{wg_client_private_key}} +{% else%} + +# Public and private keys were pre generated by client +# Insert private key below and uncomment in order to use the present configuration +# PrivateKey = + +{% endif %} + +Address = {{wg_client_address}} + +[Peer] +PublicKey = {{wg_server_public_key.stdout}} +AllowedIPs = {{ allowed_ips | join(', ') }} +Endpoint = {{ wg_server }}:{{ wg_port }} +PersistentKeepalive = 25 \ No newline at end of file diff --git a/ansible/playbooks/roles/wireguard_server/templates/wireguard_server.jinja b/ansible/playbooks/roles/wireguard_server/templates/wireguard_server.jinja new file mode 100644 index 0000000..2a8c72f --- /dev/null +++ b/ansible/playbooks/roles/wireguard_server/templates/wireguard_server.jinja @@ -0,0 +1,27 @@ +# templates/wireguard-server.conf.j2 - WireGuard server configuration +# Managed by Ansible - do not edit manually + +[Interface] +Address = {{ wg_server_address }} +ListenPort = {{ wg_port }} +PrivateKey = {{ wg_server_private_key.stdout }} + +# IP forwarding +PreUp = sysctl -w net.ipv4.ip_forward=1 +# IP masquerading +PreUp = iptables -t mangle -A PREROUTING -i {{wg_interface}} -j MARK --set-mark 0x30 +PreUp = iptables -t nat -A POSTROUTING ! -o {{wg_interface}} -m mark --mark 0x30 -j MASQUERADE +PostDown = iptables -t mangle -D PREROUTING -i {{wg_interface}} -j MARK --set-mark 0x30 +PostDown = iptables -t nat -D POSTROUTING ! -o {{wg_interface}} -m mark --mark 0x30 -j MASQUERADE + + +{% for peer in wg_peers %} +# Peer ID : {{ peer.name }} +[Peer] +PublicKey = {{ peer.publicKey }} +AllowedIPs = {{ peer.ip }} +{% if peer.persistent_keepalive is defined %} +PersistentKeepalive = {{ peer.persistent_keepalive }} +{% endif %} + +{% endfor %} \ No newline at end of file diff --git a/ansible/playbooks/vpn_server.yaml b/ansible/playbooks/vpn_server.yaml new file mode 100644 index 0000000..3b1af8e --- /dev/null +++ b/ansible/playbooks/vpn_server.yaml @@ -0,0 +1,6 @@ +--- +- name: Configure VPN Server + hosts: wireguard_server + become: true + roles: + - wireguard_server