chore: lots of changes
This commit is contained in:
6
ansible/roles/wireguard/defaults/main.yml
Normal file
6
ansible/roles/wireguard/defaults/main.yml
Normal file
@@ -0,0 +1,6 @@
|
||||
wireguard_interface: wg0
|
||||
wireguard_port: 51820
|
||||
wireguard_address: 10.8.0.1/24
|
||||
wireguard_server_ip: 94.16.110.151 # oder deine Domain
|
||||
|
||||
wireguard_network: "10.8.0.0/24"
|
||||
133
ansible/roles/wireguard/tasks/configure.yml
Normal file
133
ansible/roles/wireguard/tasks/configure.yml
Normal file
@@ -0,0 +1,133 @@
|
||||
# --------------------------------------------------------
|
||||
# WireGuard installieren
|
||||
# --------------------------------------------------------
|
||||
|
||||
- name: Stelle sicher, dass WireGuard installiert ist
|
||||
apt:
|
||||
name: wireguard
|
||||
state: present
|
||||
update_cache: yes
|
||||
become: true
|
||||
when: ansible_connection != "local"
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Server-Schlüssel erzeugen und speichern
|
||||
# --------------------------------------------------------
|
||||
|
||||
- name: Prüfe ob privater Server-Schlüssel existiert
|
||||
stat:
|
||||
path: /etc/wireguard/privatekey
|
||||
register: privkey_file
|
||||
become: true
|
||||
when: ansible_connection != "local"
|
||||
|
||||
- name: Erstelle Schlüsselpaar für Server (wenn nicht vorhanden)
|
||||
command: wg genkey
|
||||
register: server_private_key
|
||||
when: ansible_connection != "local" and (not privkey_file.stat.exists | default(true))
|
||||
|
||||
- name: Speichere privaten Schlüssel
|
||||
copy:
|
||||
content: "{{ server_private_key.stdout }}"
|
||||
dest: /etc/wireguard/privatekey
|
||||
mode: "0600"
|
||||
when: server_private_key.stdout is defined and server_private_key.stdout is defined
|
||||
|
||||
- name: Lies privaten Schlüssel ein
|
||||
slurp:
|
||||
src: /etc/wireguard/privatekey
|
||||
become: true
|
||||
when: ansible_connection != "local"
|
||||
|
||||
- name: Erzeuge öffentlichen Server-Schlüssel
|
||||
command: "echo '{{ wg_privkey }}' | wg pubkey"
|
||||
register: wg_pubkey
|
||||
when: ansible_connection != "local"
|
||||
|
||||
- name: Privaten Server-Schlüssel anzeigen
|
||||
debug:
|
||||
msg: "{{ server_private_key }}"
|
||||
when: ansible_connection != "local"
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Client-Key-Erzeugung lokal (einmalig pro Client)
|
||||
# --------------------------------------------------------
|
||||
|
||||
- name: Generiere privaten Schlüssel für Clients (auf dem Server)
|
||||
command: wg genkey
|
||||
args:
|
||||
creates: "/etc/wireguard/client-{{ item.name }}.key"
|
||||
loop: "{{ wireguard_clients }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
register: client_private_keys
|
||||
when: ansible_connection != "local"
|
||||
|
||||
|
||||
- name: Erzeuge öffentlichen Schlüssel für Clients
|
||||
command: "echo '{{ client_privkey_result.stdout }}' | wg pubkey"
|
||||
register: client_pubkey_result
|
||||
when:
|
||||
- ansible_connection != "local"
|
||||
- client_privkey_result is defined
|
||||
- client_privkey_result.stdout is defined
|
||||
|
||||
- name: wireguard_clients mit public_key anreichern
|
||||
set_fact:
|
||||
wireguard_clients: "{{ wireguard_clients_with_pubkey | default([]) + [ item.0 | combine({'public_key': item.1.stdout|trim }) ] }}"
|
||||
loop: "{{ wireguard_clients | zip(client_public_keys.results) | list }}"
|
||||
when: client_public_keys is defined
|
||||
|
||||
- name: Aktuelles wireguard_clients-Set überschreiben
|
||||
set_fact:
|
||||
wireguard_clients: "{{ wireguard_clients_with_pubkey }}"
|
||||
when: wireguard_clients_with_pubkey is defined
|
||||
|
||||
# --------------------------------------------------------
|
||||
# Konfigurationsdatei erzeugen
|
||||
# --------------------------------------------------------
|
||||
|
||||
#- debug:
|
||||
# var: wireguard_clients
|
||||
|
||||
- name: Render wg0.conf
|
||||
template:
|
||||
src: wg0.conf.j2
|
||||
dest: /etc/wireguard/wg0.conf
|
||||
when: wg_privkey is defined and wg_privkey != ""
|
||||
|
||||
# --------------------------------------------------------
|
||||
# IP Forwarding & WireGuard aktivieren
|
||||
# --------------------------------------------------------
|
||||
|
||||
- name: Aktiviere IP-Forwarding
|
||||
sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: 1
|
||||
state: present
|
||||
sysctl_set: yes
|
||||
reload: yes
|
||||
become: true
|
||||
when: ansible_connection != "local"
|
||||
|
||||
- name: Starte und aktiviere WireGuard
|
||||
systemd:
|
||||
name: wg-quick@wg0
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: yes
|
||||
become: true
|
||||
when: ansible_connection != "local"
|
||||
|
||||
- name: Verteilt für jeden Client die Client-Config
|
||||
template:
|
||||
src: client.conf.j2
|
||||
dest: "/etc/wireguard/clients/{{ item.name }}.conf"
|
||||
owner: root
|
||||
group: root
|
||||
mode: 0600
|
||||
loop: "{{ wireguard_clients }}"
|
||||
#delegate_to: localhost
|
||||
run_once: true
|
||||
become: true
|
||||
when: ansible_connection != "local"
|
||||
54
ansible/roles/wireguard/tasks/failsafe.yml
Normal file
54
ansible/roles/wireguard/tasks/failsafe.yml
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
# roles/wireguard/tasks/failsafe.yml
|
||||
# Sicherstellt, dass SSH über VPN funktioniert und ein Fallback vorhanden ist
|
||||
|
||||
- name: Stelle sicher, dass wireguard_network gesetzt ist
|
||||
assert:
|
||||
that:
|
||||
- wireguard_network is defined
|
||||
fail_msg: "wireguard_network muss gesetzt sein (z. B. 10.8.0.0/24)"
|
||||
|
||||
- name: Automatisch externe IP als fallback_ip setzen (nur wenn nicht gesetzt)
|
||||
shell: curl -s ifconfig.me
|
||||
register: detected_fallback_ip
|
||||
when: fallback_ip is not defined
|
||||
changed_when: false
|
||||
|
||||
- name: Setze fallback_ip dynamisch als Ansible-Fact (wenn nicht gesetzt)
|
||||
set_fact:
|
||||
fallback_ip: "{{ detected_fallback_ip.stdout }}"
|
||||
when: fallback_ip is not defined
|
||||
|
||||
- name: (Optional) Erlaube temporär Fallback-SSH von aktueller IP
|
||||
ufw:
|
||||
rule: allow
|
||||
port: 22
|
||||
proto: tcp
|
||||
from_ip: "{{ fallback_ip }}"
|
||||
|
||||
- name: Erlaube SSH-Zugriff über VPN
|
||||
ufw:
|
||||
rule: allow
|
||||
port: 22
|
||||
proto: tcp
|
||||
from_ip: "{{ wireguard_network }}"
|
||||
|
||||
- name: (Warnung) Prüfe ob VPN-Interface aktiv ist
|
||||
shell: ip a show dev wg0
|
||||
register: vpn_interface_check
|
||||
failed_when: false
|
||||
|
||||
- name: Hinweis, wenn VPN-Interface nicht aktiv ist
|
||||
debug:
|
||||
msg: "⚠️ VPN-Interface wg0 scheint nicht aktiv zu sein. SSH über VPN wird nicht funktionieren."
|
||||
when: vpn_interface_check.rc != 0
|
||||
|
||||
- name: (Optional) SSH von überall blockieren – nur wenn VPN aktiv
|
||||
when:
|
||||
- ssh_lockdown | default(false)
|
||||
- vpn_interface_check.rc == 0
|
||||
ufw:
|
||||
rule: deny
|
||||
port: 22
|
||||
proto: tcp
|
||||
from_ip: 0.0.0.0/0
|
||||
83
ansible/roles/wireguard/tasks/firewall.yml
Normal file
83
ansible/roles/wireguard/tasks/firewall.yml
Normal file
@@ -0,0 +1,83 @@
|
||||
# Beispiel: Passe jeden Task in dieser Datei so an:
|
||||
- name: Aktiviere Firewall-Regeln für WireGuard
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ wireguard_port }}"
|
||||
proto: udp
|
||||
become: true
|
||||
when: ansible_connection != "local"
|
||||
- name: Prüfe, ob UFW installiert ist
|
||||
command: which ufw
|
||||
register: ufw_installed
|
||||
ignore_errors: true
|
||||
changed_when: false
|
||||
|
||||
- name: Installiere UFW (falls nicht vorhanden)
|
||||
apt:
|
||||
name: ufw
|
||||
state: present
|
||||
update_cache: yes
|
||||
when: ufw_installed.rc != 0
|
||||
|
||||
# Setze Standardrichtlinien (erst Konfiguration, dann am Ende aktivieren)
|
||||
- name: Setze Policy für eingehenden Traffic auf "deny"
|
||||
ufw:
|
||||
direction: incoming
|
||||
policy: deny
|
||||
|
||||
- name: Setze Policy für ausgehenden Traffic auf "allow"
|
||||
ufw:
|
||||
direction: outgoing
|
||||
policy: allow
|
||||
|
||||
# WireGuard-Port freigeben (UDP)
|
||||
- name: WireGuard-Port erlauben
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ wireguard_port | default(51820) }}"
|
||||
proto: udp
|
||||
|
||||
# SSH von bestimmter IP erlauben
|
||||
- name: SSH von deiner IP erlauben (empfohlen)
|
||||
ufw:
|
||||
rule: allow
|
||||
port: 22
|
||||
proto: tcp
|
||||
from_ip: "{{ fallback_ip }}"
|
||||
when: fallback_ip is defined and fallback_ip | length > 0
|
||||
|
||||
# Temporär für Tests: SSH für alle erlauben (nur bei Bedarf!)
|
||||
- name: SSH von überall erlauben (fail-safe, NUR während Setup/Test)
|
||||
ufw:
|
||||
rule: allow
|
||||
port: 22
|
||||
proto: tcp
|
||||
when: (not (fallback_ip is defined and fallback_ip | length > 0)) or (enable_ssh_from_anywhere | default(false))
|
||||
|
||||
# Masquerading für WireGuard
|
||||
- name: NAT für WireGuard aktivieren
|
||||
iptables:
|
||||
table: nat
|
||||
chain: POSTROUTING
|
||||
out_interface: "{{ wireguard_exit_interface | default('eth0') }}"
|
||||
source: "{{ wireguard_network }}"
|
||||
jump: MASQUERADE
|
||||
|
||||
- name: WireGuard Kernel-Modul laden
|
||||
modprobe:
|
||||
name: wireguard
|
||||
state: present
|
||||
|
||||
# UFW ganz am Schluss aktivieren
|
||||
- name: UFW aktivieren
|
||||
ufw:
|
||||
state: enabled
|
||||
|
||||
- name: Aktive UFW-Regeln anzeigen (zum Debuggen)
|
||||
command: ufw status verbose
|
||||
register: ufw_status
|
||||
changed_when: false
|
||||
|
||||
- name: Zeige UFW-Regeln im Ansible-Output
|
||||
debug:
|
||||
var: ufw_status.stdout
|
||||
60
ansible/roles/wireguard/tasks/generate_client_single.yml
Normal file
60
ansible/roles/wireguard/tasks/generate_client_single.yml
Normal file
@@ -0,0 +1,60 @@
|
||||
- name: Key-Verzeichnis für Client anlegen
|
||||
file:
|
||||
path: "{{ role_path }}/client-keys/{{ client.name }}"
|
||||
state: directory
|
||||
mode: "0700"
|
||||
become: true
|
||||
|
||||
- name: Existenz des privaten Schlüssels prüfen
|
||||
stat:
|
||||
path: "{{ role_path }}/client-keys/{{ client.name }}/private.key"
|
||||
register: client_private_key_stat
|
||||
|
||||
- name: Privaten Schlüssel generieren (nur falls nicht vorhanden)
|
||||
command: wg genkey
|
||||
register: genpriv
|
||||
args:
|
||||
chdir: "{{ role_path }}/client-keys/{{ client.name }}"
|
||||
when: not client_private_key_stat.stat.exists
|
||||
|
||||
- name: Privaten Schlüssel speichern (nur falls nicht vorhanden)
|
||||
copy:
|
||||
content: "{{ genpriv.stdout }}"
|
||||
dest: "{{ role_path }}/client-keys/{{ client.name }}/private.key"
|
||||
mode: "0600"
|
||||
when: not client_private_key_stat.stat.exists
|
||||
|
||||
- name: Public Key aus privaten Schlüssel generieren (bei Neuerstellung)
|
||||
command: wg pubkey
|
||||
args:
|
||||
stdin: "{{ genpriv.stdout }}"
|
||||
chdir: "{{ role_path }}/client-keys/{{ client.name }}"
|
||||
register: genpub
|
||||
when: not client_private_key_stat.stat.exists
|
||||
|
||||
- name: Bestehenden privaten Schlüssel laden (falls vorhanden)
|
||||
slurp:
|
||||
src: "{{ role_path }}/client-keys/{{ client.name }}/private.key"
|
||||
register: loaded_private
|
||||
when: client_private_key_stat.stat.exists
|
||||
|
||||
- name: Public Key aus gespeichertem Private Key erzeugen (falls vorhanden)
|
||||
command: wg pubkey
|
||||
args:
|
||||
stdin: "{{ loaded_private.content | b64decode }}"
|
||||
chdir: "{{ role_path }}/client-keys/{{ client.name }}"
|
||||
register: genpub_existing
|
||||
when: client_private_key_stat.stat.exists
|
||||
|
||||
- name: Public Key für Client in Datei schreiben
|
||||
copy:
|
||||
content: >
|
||||
{{ (genpub.stdout if not client_private_key_stat.stat.exists else genpub_existing.stdout) }}
|
||||
dest: "{{ role_path }}/client-keys/{{ client.name }}/public.key"
|
||||
mode: "0644"
|
||||
|
||||
- name: Variablen für Client setzen (private/public key, Adresse)
|
||||
set_fact:
|
||||
"wg_{{ client.name }}_private_key": "{{ (genpriv.stdout if not client_private_key_stat.stat.exists else loaded_private.content | b64decode) }}"
|
||||
"wg_{{ client.name }}_public_key": "{{ (genpub.stdout if not client_private_key_stat.stat.exists else genpub_existing.stdout) }}"
|
||||
"wg_{{ client.name }}_address": "{{ client.address }}"
|
||||
39
ansible/roles/wireguard/tasks/generate_clients.yml
Normal file
39
ansible/roles/wireguard/tasks/generate_clients.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
- name: Schleife über alle WireGuard-Clients
|
||||
include_tasks: generate_client_single.yml
|
||||
loop: "{{ wireguard_clients }}"
|
||||
loop_control:
|
||||
loop_var: client
|
||||
|
||||
- name: Generiere privaten Schlüssel für jeden Client
|
||||
shell: "wg genkey"
|
||||
register: wg_client_private_keys
|
||||
loop: "{{ wireguard_clients }}"
|
||||
loop_control:
|
||||
label: "{{ item.name }}"
|
||||
# kein delegate_to mehr!
|
||||
run_once: true # ggf. auch entfernen, siehe Anmerkung unten
|
||||
|
||||
- name: Setze globale Client-Key-Facts für alle Clients
|
||||
set_fact:
|
||||
wg_all_clients_private_keys: >-
|
||||
{{
|
||||
wg_all_clients_private_keys | default({}) | combine({
|
||||
item.1.name: item.0.stdout
|
||||
})
|
||||
}}
|
||||
loop: "{{ wg_client_private_keys.results | zip(wireguard_clients) | list }}"
|
||||
delegate_to: localhost
|
||||
run_once: true
|
||||
|
||||
|
||||
- name: Generiere Private Keys für Clients
|
||||
command: "wg genkey"
|
||||
register: client_keys_raw
|
||||
loop: "{{ wireguard_clients }}"
|
||||
loop_control:
|
||||
loop_var: client
|
||||
changed_when: false
|
||||
|
||||
- name: Mappe Keys nach Namen
|
||||
set_fact:
|
||||
wg_all_clients_private_keys: "{{ dict(wireguard_clients | map(attribute='name') | list | zip(client_keys_raw.results | map(attribute='stdout') | list)) }}"
|
||||
7
ansible/roles/wireguard/tasks/install.yml
Normal file
7
ansible/roles/wireguard/tasks/install.yml
Normal file
@@ -0,0 +1,7 @@
|
||||
- name: Stelle sicher, dass WireGuard installiert ist
|
||||
apt:
|
||||
name: wireguard
|
||||
state: present
|
||||
update_cache: yes
|
||||
become: true
|
||||
when: ansible_connection != "local"
|
||||
22
ansible/roles/wireguard/tasks/main.yml
Normal file
22
ansible/roles/wireguard/tasks/main.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
#- include_tasks: install.yml
|
||||
#- include_tasks: configure.yml
|
||||
#- include_tasks: generate_clients.yml
|
||||
#- include_tasks: firewall.yml
|
||||
|
||||
|
||||
- name: Installiere WireGuard
|
||||
import_tasks: install.yml
|
||||
when: ansible_connection != "local"
|
||||
|
||||
- name: Konfiguriere WireGuard
|
||||
import_tasks: configure.yml
|
||||
|
||||
- name: Generiert .conf Dateien
|
||||
import_tasks: generate_clients.yml
|
||||
|
||||
- name: Setze Firewall-Regeln
|
||||
import_tasks: firewall.yml
|
||||
when: ansible_connection != "local"
|
||||
|
||||
- name: Wende VPN-Failsafe-Regeln an
|
||||
import_tasks: failsafe.yml
|
||||
10
ansible/roles/wireguard/templates/client.conf.j2
Normal file
10
ansible/roles/wireguard/templates/client.conf.j2
Normal file
@@ -0,0 +1,10 @@
|
||||
[Interface]
|
||||
PrivateKey = {{ wg_all_clients_private_keys[item.name] }}
|
||||
Address = {{ item.address }}/32
|
||||
DNS = 1.1.1.1
|
||||
|
||||
[Peer]
|
||||
PublicKey = {{ item.public_key }}
|
||||
Endpoint = {{ wireguard_server_ip }}:{{ wireguard_port }}
|
||||
AllowedIPs = {{ wireguard_network }}, {{ wireguard_server_ip }}/32
|
||||
PersistentKeepalive = 25
|
||||
12
ansible/roles/wireguard/templates/wg0.conf.j2
Normal file
12
ansible/roles/wireguard/templates/wg0.conf.j2
Normal file
@@ -0,0 +1,12 @@
|
||||
[Interface]
|
||||
Address = {{ wireguard_address }}
|
||||
PrivateKey = {{ wg_privkey | b64decode | trim }}
|
||||
ListenPort = {{ wireguard_port }}
|
||||
PostUp = iptables -A FORWARD -i {{ wireguard_interface }} -j ACCEPT; iptables -A FORWARD -o {{ wireguard_interface }} -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
|
||||
PostDown = iptables -D FORWARD -i {{ wireguard_interface }} -j ACCEPT; iptables -D FORWARD -o {{ wireguard_interface }} -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
|
||||
|
||||
{% for client in wireguard_clients %}
|
||||
[Peer]
|
||||
PublicKey = {{ client.public_key }}
|
||||
AllowedIPs = {{ client.address }}/32
|
||||
{% endfor %}
|
||||
Reference in New Issue
Block a user