refactor(deployment): Remove WireGuard VPN dependency and restore public service access
Remove WireGuard integration from production deployment to simplify infrastructure: - Remove docker-compose-direct-access.yml (VPN-bound services) - Remove VPN-only middlewares from Grafana, Prometheus, Portainer - Remove WireGuard middleware definitions from Traefik - Remove WireGuard IPs (10.8.0.0/24) from Traefik forwarded headers All monitoring services now publicly accessible via subdomains: - grafana.michaelschiemer.de (with Grafana native auth) - prometheus.michaelschiemer.de (with Basic Auth) - portainer.michaelschiemer.de (with Portainer native auth) All services use Let's Encrypt SSL certificates via Traefik.
This commit is contained in:
@@ -179,6 +179,141 @@ sudo ufw allow 51820/udp comment 'WireGuard VPN'
|
||||
sudo iptables -A INPUT -p udp --dport 51820 -j ACCEPT
|
||||
```
|
||||
|
||||
## Split-Tunnel Routing & NAT Fix
|
||||
|
||||
### A. Quick Fix Commands (manuell auf dem Server)
|
||||
```bash
|
||||
WAN_IF=${WAN_IF:-eth0}
|
||||
WG_IF=${WG_IF:-wg0}
|
||||
WG_NET=${WG_NET:-10.8.0.0/24}
|
||||
WG_PORT=${WG_PORT:-51820}
|
||||
EXTRA_NETS=${EXTRA_NETS:-"192.168.178.0/24 172.20.0.0/16"}
|
||||
|
||||
sudo sysctl -w net.ipv4.ip_forward=1
|
||||
sudo tee /etc/sysctl.d/99-${WG_IF}-forward.conf >/dev/null <<'EOF'
|
||||
# WireGuard Forwarding
|
||||
net.ipv4.ip_forward=1
|
||||
EOF
|
||||
sudo sysctl --system
|
||||
|
||||
# iptables Variante
|
||||
sudo iptables -t nat -C POSTROUTING -s ${WG_NET} -o ${WAN_IF} -j MASQUERADE 2>/dev/null \
|
||||
|| sudo iptables -t nat -A POSTROUTING -s ${WG_NET} -o ${WAN_IF} -j MASQUERADE
|
||||
sudo iptables -C FORWARD -i ${WG_IF} -s ${WG_NET} -o ${WAN_IF} -j ACCEPT 2>/dev/null \
|
||||
|| sudo iptables -A FORWARD -i ${WG_IF} -s ${WG_NET} -o ${WAN_IF} -j ACCEPT
|
||||
sudo iptables -C FORWARD -o ${WG_IF} -d ${WG_NET} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null \
|
||||
|| sudo iptables -A FORWARD -o ${WG_IF} -d ${WG_NET} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
for NET in ${EXTRA_NETS}; do
|
||||
sudo iptables -C FORWARD -i ${WG_IF} -d ${NET} -j ACCEPT 2>/dev/null || sudo iptables -A FORWARD -i ${WG_IF} -d ${NET} -j ACCEPT
|
||||
done
|
||||
|
||||
# nftables Variante
|
||||
sudo nft list table inet wireguard_${WG_IF} >/dev/null 2>&1 || sudo nft add table inet wireguard_${WG_IF}
|
||||
sudo nft list chain inet wireguard_${WG_IF} postrouting >/dev/null 2>&1 \
|
||||
|| sudo nft add chain inet wireguard_${WG_IF} postrouting '{ type nat hook postrouting priority srcnat; }'
|
||||
sudo nft list chain inet wireguard_${WG_IF} forward >/dev/null 2>&1 \
|
||||
|| sudo nft add chain inet wireguard_${WG_IF} forward '{ type filter hook forward priority filter; policy accept; }'
|
||||
sudo nft list chain inet wireguard_${WG_IF} postrouting | grep -q "${WAN_IF}" \
|
||||
|| sudo nft add rule inet wireguard_${WG_IF} postrouting oifname "${WAN_IF}" ip saddr ${WG_NET} masquerade
|
||||
sudo nft list chain inet wireguard_${WG_IF} forward | grep -q "iifname \"${WG_IF}\"" \
|
||||
|| sudo nft add rule inet wireguard_${WG_IF} forward iifname "${WG_IF}" ip saddr ${WG_NET} counter accept
|
||||
sudo nft list chain inet wireguard_${WG_IF} forward | grep -q "oifname \"${WG_IF}\"" \
|
||||
|| sudo nft add rule inet wireguard_${WG_IF} forward oifname "${WG_IF}" ip daddr ${WG_NET} ct state established,related counter accept
|
||||
for NET in ${EXTRA_NETS}; do
|
||||
sudo nft list chain inet wireguard_${WG_IF} forward | grep -q "${NET}" \
|
||||
|| sudo nft add rule inet wireguard_${WG_IF} forward iifname "${WG_IF}" ip daddr ${NET} counter accept
|
||||
done
|
||||
|
||||
# Firewall Hooks
|
||||
if command -v ufw >/dev/null && sudo ufw status | grep -iq "Status: active"; then
|
||||
sudo sed -i 's/^DEFAULT_FORWARD_POLICY=.*/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw
|
||||
sudo ufw allow ${WG_PORT}/udp
|
||||
sudo ufw route allow in on ${WG_IF} out on ${WAN_IF} to any
|
||||
fi
|
||||
if command -v firewall-cmd >/dev/null && sudo firewall-cmd --state >/dev/null 2>&1; then
|
||||
sudo firewall-cmd --permanent --zone=${FIREWALLD_ZONE:-public} --add-port=${WG_PORT}/udp
|
||||
sudo firewall-cmd --permanent --zone=${FIREWALLD_ZONE:-public} --add-masquerade
|
||||
sudo firewall-cmd --reload
|
||||
fi
|
||||
|
||||
sudo systemctl enable --now wg-quick@${WG_IF}
|
||||
sudo wg show
|
||||
```
|
||||
|
||||
### B. Skript: `deployment/ansible/scripts/setup-wireguard-routing.sh`
|
||||
```bash
|
||||
cd deployment/ansible
|
||||
sudo WAN_IF=eth0 WG_IF=wg0 WG_NET=10.8.0.0/24 EXTRA_NETS="192.168.178.0/24 172.20.0.0/16" \
|
||||
./scripts/setup-wireguard-routing.sh
|
||||
```
|
||||
*Erkennt automatisch iptables/nftables und konfiguriert optional UFW/Firewalld.*
|
||||
|
||||
### C. Ansible Playbook: `playbooks/wireguard-routing.yml`
|
||||
```bash
|
||||
cd deployment/ansible
|
||||
ansible-playbook -i inventory/production.yml playbooks/wireguard-routing.yml \
|
||||
-e "wg_interface=wg0 wg_addr=10.8.0.1/24 wg_net=10.8.0.0/24 wan_interface=eth0" \
|
||||
-e '{"extra_nets":["192.168.178.0/24","172.20.0.0/16"],"firewall_backend":"iptables","manage_ufw":true}'
|
||||
```
|
||||
*Variablen:* `wg_interface`, `wg_addr`, `wg_net`, `wan_interface`, `extra_nets`, `firewall_backend` (`iptables|nftables`), `manage_ufw`, `manage_firewalld`, `firewalld_zone`.
|
||||
|
||||
### D. Beispiel `wg0.conf` Ausschnitt
|
||||
```ini
|
||||
[Interface]
|
||||
Address = 10.8.0.1/24
|
||||
ListenPort = 51820
|
||||
PrivateKey = <ServerPrivateKey>
|
||||
|
||||
# iptables
|
||||
PostUp = iptables -t nat -C POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE 2>/dev/null || iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
|
||||
PostUp = iptables -C FORWARD -i wg0 -s 10.8.0.0/24 -j ACCEPT 2>/dev/null || iptables -A FORWARD -i wg0 -s 10.8.0.0/24 -j ACCEPT
|
||||
PostUp = iptables -C FORWARD -o wg0 -d 10.8.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || iptables -A FORWARD -o wg0 -d 10.8.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
PostDown = iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE 2>/dev/null || true
|
||||
PostDown = iptables -D FORWARD -i wg0 -s 10.8.0.0/24 -j ACCEPT 2>/dev/null || true
|
||||
PostDown = iptables -D FORWARD -o wg0 -d 10.8.0.0/24 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || true
|
||||
|
||||
# nftables (stattdessen)
|
||||
# PostUp = nft -f /etc/nftables.d/wireguard-wg0.nft
|
||||
# PostDown = nft delete table inet wireguard_wg0 2>/dev/null || true
|
||||
|
||||
[Peer]
|
||||
PublicKey = <ClientPublicKey>
|
||||
AllowedIPs = 10.8.0.5/32, 192.168.178.0/24, 172.20.0.0/16
|
||||
PersistentKeepalive = 25
|
||||
```
|
||||
|
||||
### E. Windows Client (AllowedIPs & Tests)
|
||||
```ini
|
||||
[Interface]
|
||||
Address = 10.8.0.5/32
|
||||
DNS = 10.8.0.1 # optional
|
||||
|
||||
[Peer]
|
||||
PublicKey = <ServerPublicKey>
|
||||
Endpoint = vpn.example.com:51820
|
||||
AllowedIPs = 10.8.0.0/24, 192.168.178.0/24, 172.20.0.0/16
|
||||
PersistentKeepalive = 25
|
||||
```
|
||||
PowerShell:
|
||||
```powershell
|
||||
wg show
|
||||
Test-Connection -Source 10.8.0.5 -ComputerName 10.8.0.1
|
||||
Test-Connection 192.168.178.1
|
||||
Test-NetConnection -ComputerName 192.168.178.10 -Port 22
|
||||
```
|
||||
Optional: `Set-DnsClientNrptRule -Namespace "internal.lan" -NameServers 10.8.0.1`.
|
||||
|
||||
### F. Troubleshooting & Rollback
|
||||
- Checks: `ip r`, `ip route get <target>`, `iptables -t nat -S`, `nft list ruleset`, `sysctl net.ipv4.ip_forward`, `wg show`, `tcpdump -i wg0`, `tcpdump -i eth0 host 10.8.0.5`.
|
||||
- Häufige Fehler: falsches WAN-Interface, Forwarding/NAT fehlt, doppelte Firewalls (iptables + nftables), Docker-NAT kollidiert, Policy-Routing aktiv.
|
||||
- Rollback:
|
||||
- `sudo rm /etc/sysctl.d/99-wg0-forward.conf && sudo sysctl -w net.ipv4.ip_forward=0`
|
||||
- iptables: Regeln mit `iptables -D` entfernen (siehe oben).
|
||||
- nftables: `sudo nft delete table inet wireguard_wg0`.
|
||||
- UFW: `sudo ufw delete allow 51820/udp`, Route-Regeln entfernen, `DEFAULT_FORWARD_POLICY` zurücksetzen.
|
||||
- Firewalld: `firewall-cmd --permanent --remove-port=51820/udp`, `--remove-masquerade`, `--reload`.
|
||||
- Dienst: `sudo systemctl disable --now wg-quick@wg0`.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### WireGuard startet nicht
|
||||
@@ -281,4 +416,4 @@ Bei Problemen:
|
||||
1. Prüfe Logs: `sudo journalctl -u wg-quick@wg0`
|
||||
2. Prüfe Status: `sudo wg show`
|
||||
3. Prüfe Firewall: `sudo ufw status`
|
||||
4. Teste Connectivity: `ping 10.8.0.1` (vom Client)
|
||||
4. Teste Connectivity: `ping 10.8.0.1` (vom Client)
|
||||
|
||||
229
deployment/ansible/playbooks/generate-wireguard-client.yml
Normal file
229
deployment/ansible/playbooks/generate-wireguard-client.yml
Normal file
@@ -0,0 +1,229 @@
|
||||
---
|
||||
# WireGuard Client Configuration Generator
|
||||
# Usage: ansible-playbook playbooks/generate-wireguard-client.yml -e "client_name=michael-laptop"
|
||||
|
||||
- name: Generate WireGuard Client Configuration
|
||||
hosts: server
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
vars:
|
||||
# Default values (can be overridden with -e)
|
||||
wireguard_config_dir: "/etc/wireguard"
|
||||
wireguard_interface: "wg0"
|
||||
wireguard_server_endpoint: "{{ ansible_default_ipv4.address }}"
|
||||
wireguard_server_port: 51820
|
||||
wireguard_vpn_network: "10.8.0.0/24"
|
||||
wireguard_server_ip: "10.8.0.1"
|
||||
|
||||
# Client output directory (local)
|
||||
client_config_dir: "{{ playbook_dir }}/../wireguard/configs"
|
||||
|
||||
# Required variable (must be passed via -e)
|
||||
# client_name: "device-name"
|
||||
|
||||
tasks:
|
||||
- name: Validate client_name is provided
|
||||
assert:
|
||||
that:
|
||||
- client_name is defined
|
||||
- client_name | length > 0
|
||||
fail_msg: "ERROR: client_name must be provided via -e client_name=<name>"
|
||||
success_msg: "Generating config for client: {{ client_name }}"
|
||||
|
||||
- name: Validate client_name format (alphanumeric and hyphens only)
|
||||
assert:
|
||||
that:
|
||||
- client_name is match('^[a-zA-Z0-9-]+$')
|
||||
fail_msg: "ERROR: client_name must contain only letters, numbers, and hyphens"
|
||||
success_msg: "Client name format is valid"
|
||||
|
||||
- name: Check if WireGuard server is configured
|
||||
stat:
|
||||
path: "{{ wireguard_config_dir }}/{{ wireguard_interface }}.conf"
|
||||
register: server_config
|
||||
|
||||
- name: Fail if server config doesn't exist
|
||||
fail:
|
||||
msg: "WireGuard server config not found. Run setup-wireguard-host.yml first."
|
||||
when: not server_config.stat.exists
|
||||
|
||||
- name: Read server public key
|
||||
slurp:
|
||||
src: "{{ wireguard_config_dir }}/server_public.key"
|
||||
register: server_public_key_raw
|
||||
|
||||
- name: Set server public key fact
|
||||
set_fact:
|
||||
server_public_key: "{{ server_public_key_raw.content | b64decode | trim }}"
|
||||
|
||||
- name: Get next available IP address
|
||||
shell: |
|
||||
# Parse existing peer IPs from wg0.conf
|
||||
existing_ips=$(grep -oP 'AllowedIPs\s*=\s*\K[0-9.]+' {{ wireguard_config_dir }}/{{ wireguard_interface }}.conf 2>/dev/null || echo "")
|
||||
|
||||
# Start from .2 (server is .1)
|
||||
i=2
|
||||
while [ $i -le 254 ]; do
|
||||
ip="10.8.0.$i"
|
||||
if ! echo "$existing_ips" | grep -q "^$ip$"; then
|
||||
echo "$ip"
|
||||
exit 0
|
||||
fi
|
||||
i=$((i + 1))
|
||||
done
|
||||
|
||||
echo "ERROR: No free IP addresses" >&2
|
||||
exit 1
|
||||
register: next_ip_result
|
||||
changed_when: false
|
||||
|
||||
- name: Set client IP fact
|
||||
set_fact:
|
||||
client_ip: "{{ next_ip_result.stdout | trim }}"
|
||||
|
||||
- name: Display client IP assignment
|
||||
debug:
|
||||
msg: "Assigned IP for {{ client_name }}: {{ client_ip }}"
|
||||
|
||||
- name: Check if client already exists
|
||||
shell: |
|
||||
grep -q "# Client: {{ client_name }}" {{ wireguard_config_dir }}/{{ wireguard_interface }}.conf
|
||||
register: client_exists
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Warn if client already exists
|
||||
debug:
|
||||
msg: "WARNING: Client '{{ client_name }}' already exists in server config. Creating new keys anyway."
|
||||
when: client_exists.rc == 0
|
||||
|
||||
- name: Generate client private key
|
||||
shell: wg genkey
|
||||
register: client_private_key_result
|
||||
changed_when: true
|
||||
no_log: true
|
||||
|
||||
- name: Generate client public key
|
||||
shell: echo "{{ client_private_key_result.stdout }}" | wg pubkey
|
||||
register: client_public_key_result
|
||||
changed_when: false
|
||||
no_log: true
|
||||
|
||||
- name: Generate preshared key
|
||||
shell: wg genpsk
|
||||
register: preshared_key_result
|
||||
changed_when: true
|
||||
no_log: true
|
||||
|
||||
- name: Set client key facts
|
||||
set_fact:
|
||||
client_private_key: "{{ client_private_key_result.stdout | trim }}"
|
||||
client_public_key: "{{ client_public_key_result.stdout | trim }}"
|
||||
preshared_key: "{{ preshared_key_result.stdout | trim }}"
|
||||
no_log: true
|
||||
|
||||
- name: Create client config directory on control node
|
||||
delegate_to: localhost
|
||||
file:
|
||||
path: "{{ client_config_dir }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
become: false
|
||||
|
||||
- name: Generate client WireGuard configuration
|
||||
delegate_to: localhost
|
||||
copy:
|
||||
content: |
|
||||
[Interface]
|
||||
# Client: {{ client_name }}
|
||||
# Generated: {{ ansible_date_time.iso8601 }}
|
||||
PrivateKey = {{ client_private_key }}
|
||||
Address = {{ client_ip }}/32
|
||||
DNS = 1.1.1.1, 8.8.8.8
|
||||
|
||||
[Peer]
|
||||
# WireGuard Server
|
||||
PublicKey = {{ server_public_key }}
|
||||
PresharedKey = {{ preshared_key }}
|
||||
Endpoint = {{ wireguard_server_endpoint }}:{{ wireguard_server_port }}
|
||||
AllowedIPs = {{ wireguard_vpn_network }}
|
||||
PersistentKeepalive = 25
|
||||
dest: "{{ client_config_dir }}/{{ client_name }}.conf"
|
||||
mode: '0600'
|
||||
become: false
|
||||
no_log: true
|
||||
|
||||
- name: Add client peer to server configuration
|
||||
blockinfile:
|
||||
path: "{{ wireguard_config_dir }}/{{ wireguard_interface }}.conf"
|
||||
marker: "# {mark} ANSIBLE MANAGED BLOCK - Client: {{ client_name }}"
|
||||
block: |
|
||||
|
||||
[Peer]
|
||||
# Client: {{ client_name }}
|
||||
PublicKey = {{ client_public_key }}
|
||||
PresharedKey = {{ preshared_key }}
|
||||
AllowedIPs = {{ client_ip }}/32
|
||||
no_log: true
|
||||
|
||||
- name: Reload WireGuard configuration
|
||||
shell: wg syncconf {{ wireguard_interface }} <(wg-quick strip {{ wireguard_interface }})
|
||||
args:
|
||||
executable: /bin/bash
|
||||
|
||||
- name: Generate QR code (ASCII)
|
||||
delegate_to: localhost
|
||||
shell: |
|
||||
qrencode -t ansiutf8 < {{ client_config_dir }}/{{ client_name }}.conf > {{ client_config_dir }}/{{ client_name }}.qr.txt
|
||||
become: false
|
||||
changed_when: true
|
||||
|
||||
- name: Generate QR code (PNG)
|
||||
delegate_to: localhost
|
||||
shell: |
|
||||
qrencode -t png -o {{ client_config_dir }}/{{ client_name }}.qr.png < {{ client_config_dir }}/{{ client_name }}.conf
|
||||
become: false
|
||||
changed_when: true
|
||||
|
||||
- name: Display QR code for mobile devices
|
||||
delegate_to: localhost
|
||||
shell: cat {{ client_config_dir }}/{{ client_name }}.qr.txt
|
||||
register: qr_code_output
|
||||
become: false
|
||||
changed_when: false
|
||||
|
||||
- name: Client configuration summary
|
||||
debug:
|
||||
msg:
|
||||
- "========================================="
|
||||
- "WireGuard Client Configuration Created!"
|
||||
- "========================================="
|
||||
- ""
|
||||
- "Client: {{ client_name }}"
|
||||
- "IP Address: {{ client_ip }}/32"
|
||||
- "Public Key: {{ client_public_key }}"
|
||||
- ""
|
||||
- "Configuration Files:"
|
||||
- " Config: {{ client_config_dir }}/{{ client_name }}.conf"
|
||||
- " QR Code (ASCII): {{ client_config_dir }}/{{ client_name }}.qr.txt"
|
||||
- " QR Code (PNG): {{ client_config_dir }}/{{ client_name }}.qr.png"
|
||||
- ""
|
||||
- "Server Configuration:"
|
||||
- " Endpoint: {{ wireguard_server_endpoint }}:{{ wireguard_server_port }}"
|
||||
- " Allowed IPs: {{ wireguard_vpn_network }}"
|
||||
- ""
|
||||
- "Next Steps:"
|
||||
- " Linux/macOS: sudo cp {{ client_config_dir }}/{{ client_name }}.conf /etc/wireguard/ && sudo wg-quick up {{ client_name }}"
|
||||
- " Windows: Import {{ client_name }}.conf in WireGuard GUI"
|
||||
- " iOS/Android: Scan QR code with WireGuard app"
|
||||
- ""
|
||||
- "Test Connection:"
|
||||
- " ping {{ wireguard_server_ip }}"
|
||||
- " curl -k https://{{ wireguard_server_ip }}:8080 # Traefik Dashboard"
|
||||
- ""
|
||||
- "========================================="
|
||||
|
||||
- name: Display QR code
|
||||
debug:
|
||||
msg: "{{ qr_code_output.stdout_lines }}"
|
||||
309
deployment/ansible/playbooks/setup-wireguard-host.yml
Normal file
309
deployment/ansible/playbooks/setup-wireguard-host.yml
Normal file
@@ -0,0 +1,309 @@
|
||||
---
|
||||
# Ansible Playbook: WireGuard Host-based VPN Setup
|
||||
# Purpose: Deploy minimalistic WireGuard VPN for admin access
|
||||
# Architecture: Host-based (systemd), no Docker, no DNS
|
||||
|
||||
- name: Setup WireGuard VPN (Host-based)
|
||||
hosts: all
|
||||
become: yes
|
||||
|
||||
vars:
|
||||
# WireGuard Configuration
|
||||
wg_interface: wg0
|
||||
wg_network: 10.8.0.0/24
|
||||
wg_server_ip: 10.8.0.1
|
||||
wg_netmask: 24
|
||||
wg_port: 51820
|
||||
|
||||
# Network Configuration
|
||||
wan_interface: eth0 # Change to your WAN interface (eth0, ens3, etc.)
|
||||
|
||||
# Admin Service Ports (VPN-only access)
|
||||
admin_service_ports:
|
||||
- 8080 # Traefik Dashboard
|
||||
- 9090 # Prometheus
|
||||
- 3001 # Grafana
|
||||
- 9000 # Portainer
|
||||
- 8001 # Redis Insight
|
||||
|
||||
# Public Service Ports
|
||||
public_service_ports:
|
||||
- 80 # HTTP
|
||||
- 443 # HTTPS
|
||||
- 22 # SSH
|
||||
|
||||
# Rate Limiting
|
||||
wg_enable_rate_limit: true
|
||||
|
||||
# Paths
|
||||
wg_config_dir: /etc/wireguard
|
||||
wg_backup_dir: /root/wireguard-backup
|
||||
nft_config_file: /etc/nftables.d/wireguard.nft
|
||||
|
||||
tasks:
|
||||
# ========================================
|
||||
# 1. Pre-flight Checks
|
||||
# ========================================
|
||||
|
||||
- name: Check if running as root
|
||||
assert:
|
||||
that: ansible_user_id == 'root'
|
||||
fail_msg: "This playbook must be run as root"
|
||||
|
||||
- name: Detect WAN interface
|
||||
shell: ip route | grep default | awk '{print $5}' | head -n1
|
||||
register: detected_wan_interface
|
||||
changed_when: false
|
||||
|
||||
- name: Set WAN interface if not specified
|
||||
set_fact:
|
||||
wan_interface: "{{ detected_wan_interface.stdout }}"
|
||||
when: wan_interface == 'eth0' and detected_wan_interface.stdout != ''
|
||||
|
||||
- name: Display detected network configuration
|
||||
debug:
|
||||
msg:
|
||||
- "WAN Interface: {{ wan_interface }}"
|
||||
- "VPN Network: {{ wg_network }}"
|
||||
- "VPN Server IP: {{ wg_server_ip }}"
|
||||
|
||||
# ========================================
|
||||
# 2. Backup Existing Configuration
|
||||
# ========================================
|
||||
|
||||
- name: Create backup directory
|
||||
file:
|
||||
path: "{{ wg_backup_dir }}"
|
||||
state: directory
|
||||
mode: '0700'
|
||||
|
||||
- name: Backup existing WireGuard config (if exists)
|
||||
shell: |
|
||||
if [ -d {{ wg_config_dir }} ]; then
|
||||
tar -czf {{ wg_backup_dir }}/wireguard-backup-$(date +%Y%m%d-%H%M%S).tar.gz {{ wg_config_dir }}
|
||||
echo "Backup created"
|
||||
else
|
||||
echo "No existing config"
|
||||
fi
|
||||
register: backup_result
|
||||
changed_when: "'Backup created' in backup_result.stdout"
|
||||
|
||||
# ========================================
|
||||
# 3. Install WireGuard
|
||||
# ========================================
|
||||
|
||||
- name: Update apt cache
|
||||
apt:
|
||||
update_cache: yes
|
||||
cache_valid_time: 3600
|
||||
when: ansible_os_family == 'Debian'
|
||||
|
||||
- name: Install WireGuard and dependencies
|
||||
apt:
|
||||
name:
|
||||
- wireguard
|
||||
- wireguard-tools
|
||||
- qrencode # For QR code generation
|
||||
- nftables
|
||||
state: present
|
||||
when: ansible_os_family == 'Debian'
|
||||
|
||||
- name: Ensure WireGuard kernel module is loaded
|
||||
modprobe:
|
||||
name: wireguard
|
||||
state: present
|
||||
|
||||
- name: Verify WireGuard module is available
|
||||
shell: lsmod | grep -q wireguard
|
||||
register: wg_module_check
|
||||
failed_when: wg_module_check.rc != 0
|
||||
changed_when: false
|
||||
|
||||
# ========================================
|
||||
# 4. Generate Server Keys (if not exist)
|
||||
# ========================================
|
||||
|
||||
- name: Create WireGuard config directory
|
||||
file:
|
||||
path: "{{ wg_config_dir }}"
|
||||
state: directory
|
||||
mode: '0700'
|
||||
|
||||
- name: Check if server private key exists
|
||||
stat:
|
||||
path: "{{ wg_config_dir }}/server_private.key"
|
||||
register: server_private_key_stat
|
||||
|
||||
- name: Generate server private key
|
||||
shell: wg genkey > {{ wg_config_dir }}/server_private.key
|
||||
when: not server_private_key_stat.stat.exists
|
||||
|
||||
- name: Set server private key permissions
|
||||
file:
|
||||
path: "{{ wg_config_dir }}/server_private.key"
|
||||
mode: '0600'
|
||||
|
||||
- name: Generate server public key
|
||||
shell: cat {{ wg_config_dir }}/server_private.key | wg pubkey > {{ wg_config_dir }}/server_public.key
|
||||
when: not server_private_key_stat.stat.exists
|
||||
|
||||
- name: Read server private key
|
||||
slurp:
|
||||
src: "{{ wg_config_dir }}/server_private.key"
|
||||
register: server_private_key_content
|
||||
|
||||
- name: Read server public key
|
||||
slurp:
|
||||
src: "{{ wg_config_dir }}/server_public.key"
|
||||
register: server_public_key_content
|
||||
|
||||
- name: Set server key facts
|
||||
set_fact:
|
||||
wg_server_private_key: "{{ server_private_key_content.content | b64decode | trim }}"
|
||||
wg_server_public_key: "{{ server_public_key_content.content | b64decode | trim }}"
|
||||
|
||||
- name: Display server public key
|
||||
debug:
|
||||
msg: "Server Public Key: {{ wg_server_public_key }}"
|
||||
|
||||
# ========================================
|
||||
# 5. Configure WireGuard
|
||||
# ========================================
|
||||
|
||||
- name: Deploy WireGuard server configuration
|
||||
template:
|
||||
src: ../templates/wg0.conf.j2
|
||||
dest: "{{ wg_config_dir }}/wg0.conf"
|
||||
mode: '0600'
|
||||
notify: restart wireguard
|
||||
|
||||
- name: Enable IP forwarding
|
||||
sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: '1'
|
||||
sysctl_set: yes
|
||||
state: present
|
||||
reload: yes
|
||||
|
||||
# ========================================
|
||||
# 6. Configure nftables Firewall
|
||||
# ========================================
|
||||
|
||||
- name: Create nftables config directory
|
||||
file:
|
||||
path: /etc/nftables.d
|
||||
state: directory
|
||||
mode: '0755'
|
||||
|
||||
- name: Deploy WireGuard firewall rules
|
||||
template:
|
||||
src: ../templates/wireguard-host-firewall.nft.j2
|
||||
dest: "{{ nft_config_file }}"
|
||||
mode: '0644'
|
||||
notify: reload nftables
|
||||
|
||||
- name: Include WireGuard rules in main nftables config
|
||||
lineinfile:
|
||||
path: /etc/nftables.conf
|
||||
line: 'include "{{ nft_config_file }}"'
|
||||
create: yes
|
||||
state: present
|
||||
notify: reload nftables
|
||||
|
||||
- name: Enable nftables service
|
||||
systemd:
|
||||
name: nftables
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
# ========================================
|
||||
# 7. Enable and Start WireGuard
|
||||
# ========================================
|
||||
|
||||
- name: Enable WireGuard interface
|
||||
systemd:
|
||||
name: wg-quick@wg0
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Verify WireGuard is running
|
||||
command: wg show wg0
|
||||
register: wg_status
|
||||
changed_when: false
|
||||
|
||||
- name: Display WireGuard status
|
||||
debug:
|
||||
msg: "{{ wg_status.stdout_lines }}"
|
||||
|
||||
# ========================================
|
||||
# 8. Health Checks
|
||||
# ========================================
|
||||
|
||||
- name: Check WireGuard interface exists
|
||||
command: ip link show wg0
|
||||
register: wg_interface_check
|
||||
failed_when: wg_interface_check.rc != 0
|
||||
changed_when: false
|
||||
|
||||
- name: Check firewall rules applied
|
||||
command: nft list ruleset
|
||||
register: nft_rules
|
||||
failed_when: "'wireguard_firewall' not in nft_rules.stdout"
|
||||
changed_when: false
|
||||
|
||||
- name: Verify admin ports are blocked from public
|
||||
shell: nft list chain inet wireguard_firewall input | grep -q "admin_service_ports.*drop"
|
||||
register: admin_port_block_check
|
||||
failed_when: admin_port_block_check.rc != 0
|
||||
changed_when: false
|
||||
|
||||
# ========================================
|
||||
# 9. Post-Installation Summary
|
||||
# ========================================
|
||||
|
||||
- name: Create post-installation summary
|
||||
debug:
|
||||
msg:
|
||||
- "========================================="
|
||||
- "WireGuard VPN Setup Complete!"
|
||||
- "========================================="
|
||||
- ""
|
||||
- "Server Configuration:"
|
||||
- " Interface: wg0"
|
||||
- " Server IP: {{ wg_server_ip }}/{{ wg_netmask }}"
|
||||
- " Listen Port: {{ wg_port }}"
|
||||
- " Public Key: {{ wg_server_public_key }}"
|
||||
- ""
|
||||
- "Network Configuration:"
|
||||
- " VPN Network: {{ wg_network }}"
|
||||
- " WAN Interface: {{ wan_interface }}"
|
||||
- ""
|
||||
- "Admin Service Access (VPN-only):"
|
||||
- " Traefik Dashboard: https://{{ wg_server_ip }}:8080"
|
||||
- " Prometheus: http://{{ wg_server_ip }}:9090"
|
||||
- " Grafana: https://{{ wg_server_ip }}:3001"
|
||||
- " Portainer: http://{{ wg_server_ip }}:9000"
|
||||
- " Redis Insight: http://{{ wg_server_ip }}:8001"
|
||||
- ""
|
||||
- "Next Steps:"
|
||||
- " 1. Generate client config: ./scripts/generate-client-config.sh <device-name>"
|
||||
- " 2. Import config on client device"
|
||||
- " 3. Connect and verify access"
|
||||
- ""
|
||||
- "Firewall Status: ACTIVE (nftables)"
|
||||
- " - Public ports: 80, 443, 22"
|
||||
- " - VPN port: {{ wg_port }}"
|
||||
- " - Admin services: VPN-only access"
|
||||
- ""
|
||||
- "========================================="
|
||||
|
||||
handlers:
|
||||
- name: restart wireguard
|
||||
systemd:
|
||||
name: wg-quick@wg0
|
||||
state: restarted
|
||||
|
||||
- name: reload nftables
|
||||
systemd:
|
||||
name: nftables
|
||||
state: reloaded
|
||||
212
deployment/ansible/playbooks/wireguard-routing.yml
Normal file
212
deployment/ansible/playbooks/wireguard-routing.yml
Normal file
@@ -0,0 +1,212 @@
|
||||
---
|
||||
- name: Configure WireGuard split tunnel routing
|
||||
hosts: production
|
||||
become: true
|
||||
gather_facts: true
|
||||
|
||||
vars:
|
||||
wg_interface: wg0
|
||||
wg_addr: 10.8.0.1/24
|
||||
wg_net: 10.8.0.0/24
|
||||
wan_interface: eth0
|
||||
listening_port: 51820
|
||||
extra_nets:
|
||||
- 192.168.178.0/24
|
||||
- 172.20.0.0/16
|
||||
firewall_backend: iptables # or nftables
|
||||
manage_ufw: false
|
||||
manage_firewalld: false
|
||||
firewalld_zone: public
|
||||
|
||||
pre_tasks:
|
||||
- name: Ensure required collections are installed (documentation note)
|
||||
debug:
|
||||
msg: >
|
||||
Install collections if missing:
|
||||
ansible-galaxy collection install ansible.posix community.general
|
||||
when: false
|
||||
|
||||
tasks:
|
||||
- name: Ensure WireGuard config directory exists
|
||||
ansible.builtin.file:
|
||||
path: "/etc/wireguard"
|
||||
state: directory
|
||||
mode: "0700"
|
||||
owner: root
|
||||
group: root
|
||||
|
||||
- name: Persist IPv4 forwarding
|
||||
ansible.builtin.copy:
|
||||
dest: "/etc/sysctl.d/99-{{ wg_interface }}-forward.conf"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
content: |
|
||||
# Managed by Ansible - WireGuard {{ wg_interface }}
|
||||
net.ipv4.ip_forward=1
|
||||
|
||||
- name: Enable IPv4 forwarding runtime
|
||||
ansible.posix.sysctl:
|
||||
name: net.ipv4.ip_forward
|
||||
value: "1"
|
||||
state: present
|
||||
reload: true
|
||||
|
||||
- name: Configure MASQUERADE (iptables)
|
||||
community.general.iptables:
|
||||
table: nat
|
||||
chain: POSTROUTING
|
||||
out_interface: "{{ wan_interface }}"
|
||||
source: "{{ wg_net }}"
|
||||
jump: MASQUERADE
|
||||
state: present
|
||||
when: firewall_backend == "iptables"
|
||||
|
||||
- name: Allow forwarding wg -> wan (iptables)
|
||||
community.general.iptables:
|
||||
table: filter
|
||||
chain: FORWARD
|
||||
in_interface: "{{ wg_interface }}"
|
||||
out_interface: "{{ wan_interface }}"
|
||||
source: "{{ wg_net }}"
|
||||
jump: ACCEPT
|
||||
state: present
|
||||
when: firewall_backend == "iptables"
|
||||
|
||||
- name: Allow forwarding wan -> wg (iptables)
|
||||
community.general.iptables:
|
||||
table: filter
|
||||
chain: FORWARD
|
||||
out_interface: "{{ wg_interface }}"
|
||||
destination: "{{ wg_net }}"
|
||||
ctstate: RELATED,ESTABLISHED
|
||||
jump: ACCEPT
|
||||
state: present
|
||||
when: firewall_backend == "iptables"
|
||||
|
||||
- name: Allow forwarding to extra nets (iptables)
|
||||
community.general.iptables:
|
||||
table: filter
|
||||
chain: FORWARD
|
||||
in_interface: "{{ wg_interface }}"
|
||||
destination: "{{ item }}"
|
||||
jump: ACCEPT
|
||||
state: present
|
||||
loop: "{{ extra_nets }}"
|
||||
when: firewall_backend == "iptables"
|
||||
|
||||
- name: Allow return from extra nets (iptables)
|
||||
community.general.iptables:
|
||||
table: filter
|
||||
chain: FORWARD
|
||||
source: "{{ item }}"
|
||||
out_interface: "{{ wg_interface }}"
|
||||
ctstate: RELATED,ESTABLISHED
|
||||
jump: ACCEPT
|
||||
state: present
|
||||
loop: "{{ extra_nets }}"
|
||||
when: firewall_backend == "iptables"
|
||||
|
||||
- name: Deploy nftables WireGuard rules
|
||||
ansible.builtin.template:
|
||||
src: "{{ playbook_dir }}/../templates/wireguard-nftables.nft.j2"
|
||||
dest: "/etc/nftables.d/wireguard-{{ wg_interface }}.nft"
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
when: firewall_backend == "nftables"
|
||||
notify: Reload nftables
|
||||
|
||||
- name: Ensure nftables main config includes WireGuard rules
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/nftables.conf
|
||||
regexp: '^include "/etc/nftables.d/wireguard-{{ wg_interface }}.nft";$'
|
||||
line: 'include "/etc/nftables.d/wireguard-{{ wg_interface }}.nft";'
|
||||
create: true
|
||||
when: firewall_backend == "nftables"
|
||||
notify: Reload nftables
|
||||
|
||||
- name: Manage UFW forward policy
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/default/ufw
|
||||
regexp: '^DEFAULT_FORWARD_POLICY='
|
||||
line: 'DEFAULT_FORWARD_POLICY="ACCEPT"'
|
||||
when: manage_ufw
|
||||
|
||||
- name: Allow WireGuard port in UFW
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ listening_port }}"
|
||||
proto: udp
|
||||
comment: "WireGuard VPN"
|
||||
when: manage_ufw
|
||||
|
||||
- name: Allow routed traffic via UFW (wg -> wan)
|
||||
ansible.builtin.command:
|
||||
cmd: "ufw route allow in on {{ wg_interface }} out on {{ wan_interface }} to any"
|
||||
register: ufw_route_result
|
||||
changed_when: "'Skipping' not in ufw_route_result.stdout"
|
||||
when: manage_ufw
|
||||
|
||||
- name: Allow extra nets via UFW
|
||||
ansible.builtin.command:
|
||||
cmd: "ufw route allow in on {{ wg_interface }} to {{ item }}"
|
||||
loop: "{{ extra_nets }}"
|
||||
register: ufw_extra_result
|
||||
changed_when: "'Skipping' not in ufw_extra_result.stdout"
|
||||
when: manage_ufw
|
||||
|
||||
- name: Allow WireGuard port in firewalld
|
||||
ansible.posix.firewalld:
|
||||
zone: "{{ firewalld_zone }}"
|
||||
port: "{{ listening_port }}/udp"
|
||||
permanent: true
|
||||
state: enabled
|
||||
when: manage_firewalld
|
||||
|
||||
- name: Enable firewalld masquerade
|
||||
ansible.posix.firewalld:
|
||||
zone: "{{ firewalld_zone }}"
|
||||
masquerade: true
|
||||
permanent: true
|
||||
state: enabled
|
||||
when: manage_firewalld
|
||||
|
||||
- name: Allow forwarding from WireGuard via firewalld
|
||||
ansible.posix.firewalld:
|
||||
permanent: true
|
||||
state: enabled
|
||||
immediate: false
|
||||
rich_rule: 'rule family="ipv4" source address="{{ wg_net }}" accept'
|
||||
when: manage_firewalld
|
||||
|
||||
- name: Allow extra nets via firewalld
|
||||
ansible.posix.firewalld:
|
||||
permanent: true
|
||||
state: enabled
|
||||
immediate: false
|
||||
rich_rule: 'rule family="ipv4" source address="{{ item }}" accept'
|
||||
loop: "{{ extra_nets }}"
|
||||
when: manage_firewalld
|
||||
|
||||
- name: Ensure wg-quick service enabled and restarted
|
||||
ansible.builtin.systemd:
|
||||
name: "wg-quick@{{ wg_interface }}"
|
||||
enabled: true
|
||||
state: restarted
|
||||
|
||||
- name: Show WireGuard status
|
||||
ansible.builtin.command: "wg show {{ wg_interface }}"
|
||||
register: wg_status
|
||||
changed_when: false
|
||||
failed_when: false
|
||||
|
||||
- name: Render routing summary
|
||||
ansible.builtin.debug:
|
||||
msg: |
|
||||
WireGuard routing updated for {{ wg_interface }}
|
||||
{{ wg_status.stdout }}
|
||||
|
||||
handlers:
|
||||
- name: Reload nftables
|
||||
ansible.builtin.command: nft -f /etc/nftables.conf
|
||||
156
deployment/ansible/scripts/setup-wireguard-routing.sh
Executable file
156
deployment/ansible/scripts/setup-wireguard-routing.sh
Executable file
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/env bash
|
||||
# setup-wireguard-routing.sh
|
||||
# Idempotent WireGuard split-tunnel routing helper.
|
||||
# Detects iptables/nftables and optional UFW/Firewalld to configure forwarding + NAT.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
WAN_IF=${WAN_IF:-eth0}
|
||||
WG_IF=${WG_IF:-wg0}
|
||||
WG_NET=${WG_NET:-10.8.0.0/24}
|
||||
WG_ADDR=${WG_ADDR:-10.8.0.1/24}
|
||||
WG_PORT=${WG_PORT:-51820}
|
||||
EXTRA_NETS_DEFAULT="192.168.178.0/24 172.20.0.0/16"
|
||||
EXTRA_NETS="${EXTRA_NETS:-$EXTRA_NETS_DEFAULT}"
|
||||
FIREWALL_BACKEND=${FIREWALL_BACKEND:-auto}
|
||||
FIREWALLD_ZONE=${FIREWALLD_ZONE:-public}
|
||||
|
||||
read -r -a EXTRA_NETS_ARRAY <<< "${EXTRA_NETS}"
|
||||
|
||||
abort() {
|
||||
echo "Error: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_root() {
|
||||
if [[ "${EUID}" -ne 0 ]]; then
|
||||
abort "please run as root (sudo ./setup-wireguard-routing.sh)"
|
||||
fi
|
||||
}
|
||||
|
||||
detect_backend() {
|
||||
case "${FIREWALL_BACKEND}" in
|
||||
iptables|nftables) echo "${FIREWALL_BACKEND}"; return 0 ;;
|
||||
auto)
|
||||
if command -v nft >/dev/null 2>&1; then
|
||||
echo "nftables"; return 0
|
||||
fi
|
||||
if command -v iptables >/dev/null 2>&1; then
|
||||
echo "iptables"; return 0
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
abort "no supported firewall backend found (install iptables or nftables)"
|
||||
}
|
||||
|
||||
ensure_sysctl() {
|
||||
local sysctl_file="/etc/sysctl.d/99-${WG_IF}-forward.conf"
|
||||
cat <<EOF > "${sysctl_file}"
|
||||
# Managed by setup-wireguard-routing.sh
|
||||
net.ipv4.ip_forward=1
|
||||
EOF
|
||||
sysctl -w net.ipv4.ip_forward=1 >/dev/null
|
||||
sysctl --system >/dev/null
|
||||
}
|
||||
|
||||
apply_iptables() {
|
||||
iptables -t nat -C POSTROUTING -s "${WG_NET}" -o "${WAN_IF}" -j MASQUERADE 2>/dev/null || \
|
||||
iptables -t nat -A POSTROUTING -s "${WG_NET}" -o "${WAN_IF}" -j MASQUERADE
|
||||
|
||||
iptables -C FORWARD -i "${WG_IF}" -s "${WG_NET}" -o "${WAN_IF}" -j ACCEPT 2>/dev/null || \
|
||||
iptables -A FORWARD -i "${WG_IF}" -s "${WG_NET}" -o "${WAN_IF}" -j ACCEPT
|
||||
|
||||
iptables -C FORWARD -o "${WG_IF}" -d "${WG_NET}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \
|
||||
iptables -A FORWARD -o "${WG_IF}" -d "${WG_NET}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
|
||||
for net in "${EXTRA_NETS_ARRAY[@]}"; do
|
||||
[[ -z "${net}" ]] && continue
|
||||
iptables -C FORWARD -i "${WG_IF}" -d "${net}" -j ACCEPT 2>/dev/null || \
|
||||
iptables -A FORWARD -i "${WG_IF}" -d "${net}" -j ACCEPT
|
||||
iptables -C FORWARD -s "${net}" -o "${WG_IF}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT 2>/dev/null || \
|
||||
iptables -A FORWARD -s "${net}" -o "${WG_IF}" -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
|
||||
done
|
||||
}
|
||||
|
||||
apply_nftables() {
|
||||
local table="inet wireguard_${WG_IF}"
|
||||
nft list table ${table} >/dev/null 2>&1 || nft add table ${table}
|
||||
|
||||
nft list chain ${table} postrouting >/dev/null 2>&1 || \
|
||||
nft add chain ${table} postrouting '{ type nat hook postrouting priority srcnat; }'
|
||||
|
||||
nft list chain ${table} forward >/dev/null 2>&1 || \
|
||||
nft add chain ${table} forward '{ type filter hook forward priority filter; policy accept; }'
|
||||
|
||||
nft list chain ${table} postrouting | grep -q "oifname \"${WAN_IF}\" ip saddr ${WG_NET}" || \
|
||||
nft add rule ${table} postrouting oifname "${WAN_IF}" ip saddr ${WG_NET} masquerade
|
||||
|
||||
nft list chain ${table} forward | grep -q "iifname \"${WG_IF}\" ip saddr ${WG_NET}" || \
|
||||
nft add rule ${table} forward iifname "${WG_IF}" ip saddr ${WG_NET} counter accept
|
||||
|
||||
nft list chain ${table} forward | grep -q "oifname \"${WG_IF}\" ip daddr ${WG_NET}" || \
|
||||
nft add rule ${table} forward oifname "${WG_IF}" ip daddr ${WG_NET} ct state established,related counter accept
|
||||
|
||||
for net in "${EXTRA_NETS_ARRAY[@]}"; do
|
||||
[[ -z "${net}" ]] && continue
|
||||
nft list chain ${table} forward | grep -q "iifname \"${WG_IF}\" ip daddr ${net}" || \
|
||||
nft add rule ${table} forward iifname "${WG_IF}" ip daddr ${net} counter accept
|
||||
done
|
||||
}
|
||||
|
||||
configure_ufw() {
|
||||
if command -v ufw >/dev/null 2>&1 && ufw status | grep -iq "Status: active"; then
|
||||
sed -i 's/^DEFAULT_FORWARD_POLICY=.*/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw
|
||||
ufw allow "${WG_PORT}"/udp >/dev/null
|
||||
ufw route allow in on "${WG_IF}" out on "${WAN_IF}" to any >/dev/null 2>&1 || true
|
||||
for net in "${EXTRA_NETS_ARRAY[@]}"; do
|
||||
[[ -z "${net}" ]] && continue
|
||||
ufw route allow in on "${WG_IF}" to "${net}" >/dev/null 2>&1 || true
|
||||
done
|
||||
ufw reload >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
configure_firewalld() {
|
||||
if command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1; then
|
||||
firewall-cmd --permanent --zone="${FIREWALLD_ZONE}" --add-port=${WG_PORT}/udp >/dev/null
|
||||
firewall-cmd --permanent --zone="${FIREWALLD_ZONE}" --add-masquerade >/dev/null
|
||||
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 \
|
||||
"iif ${WG_IF} oif ${WAN_IF} -s ${WG_NET} -j ACCEPT" >/dev/null 2>&1 || true
|
||||
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 \
|
||||
"oif ${WG_IF} -d ${WG_NET} -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT" >/dev/null 2>&1 || true
|
||||
for net in "${EXTRA_NETS_ARRAY[@]}"; do
|
||||
[[ -z "${net}" ]] && continue
|
||||
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 \
|
||||
"iif ${WG_IF} -d ${net} -j ACCEPT" >/dev/null 2>&1 || true
|
||||
done
|
||||
firewall-cmd --reload >/dev/null
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_service() {
|
||||
systemctl enable "wg-quick@${WG_IF}" >/dev/null
|
||||
systemctl restart "wg-quick@${WG_IF}"
|
||||
}
|
||||
|
||||
show_status() {
|
||||
echo "WireGuard routing configured with ${WG_IF} (${WG_ADDR}) via ${WAN_IF}"
|
||||
wg show "${WG_IF}" || true
|
||||
ip route show table main | grep "${WG_NET}" || true
|
||||
}
|
||||
|
||||
main() {
|
||||
require_root
|
||||
ensure_sysctl
|
||||
backend=$(detect_backend)
|
||||
case "${backend}" in
|
||||
iptables) apply_iptables ;;
|
||||
nftables) apply_nftables ;;
|
||||
esac
|
||||
configure_ufw
|
||||
configure_firewalld
|
||||
ensure_service
|
||||
show_status
|
||||
}
|
||||
|
||||
main "$@"
|
||||
50
deployment/ansible/templates/wg0.conf.j2
Normal file
50
deployment/ansible/templates/wg0.conf.j2
Normal file
@@ -0,0 +1,50 @@
|
||||
# WireGuard Server Configuration
|
||||
# Interface: wg0
|
||||
# Network: {{ wg_network }}
|
||||
# Server IP: {{ wg_server_ip }}
|
||||
|
||||
[Interface]
|
||||
PrivateKey = {{ wg_server_private_key }}
|
||||
Address = {{ wg_server_ip }}/{{ wg_netmask }}
|
||||
ListenPort = {{ wg_port | default(51820) }}
|
||||
|
||||
# Enable IP forwarding for VPN routing
|
||||
PostUp = sysctl -w net.ipv4.ip_forward=1
|
||||
|
||||
# nftables: Setup VPN routing and firewall
|
||||
PostUp = nft add table inet wireguard
|
||||
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
|
||||
PostUp = nft add chain inet wireguard forward { type filter hook forward priority filter\; }
|
||||
|
||||
# NAT for VPN traffic (masquerade to WAN)
|
||||
PostUp = nft add rule inet wireguard postrouting oifname "{{ wan_interface }}" ip saddr {{ wg_network }} masquerade
|
||||
|
||||
# Allow VPN traffic forwarding
|
||||
PostUp = nft add rule inet wireguard forward iifname "wg0" ip saddr {{ wg_network }} accept
|
||||
PostUp = nft add rule inet wireguard forward oifname "wg0" ip daddr {{ wg_network }} ct state established,related accept
|
||||
|
||||
# Cleanup on shutdown
|
||||
PostDown = nft delete table inet wireguard
|
||||
|
||||
# Peers (automatically managed)
|
||||
# Format:
|
||||
# [Peer]
|
||||
# # Description: device-name
|
||||
# PublicKey = peer_public_key
|
||||
# PresharedKey = peer_preshared_key
|
||||
# AllowedIPs = 10.8.0.X/32
|
||||
# PersistentKeepalive = 25 # Optional: for clients behind NAT
|
||||
|
||||
{% for peer in wg_peers | default([]) %}
|
||||
[Peer]
|
||||
# {{ peer.name }}
|
||||
PublicKey = {{ peer.public_key }}
|
||||
{% if peer.preshared_key is defined %}
|
||||
PresharedKey = {{ peer.preshared_key }}
|
||||
{% endif %}
|
||||
AllowedIPs = {{ peer.allowed_ips }}
|
||||
{% if peer.persistent_keepalive | default(true) %}
|
||||
PersistentKeepalive = 25
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
116
deployment/ansible/templates/wireguard-host-firewall.nft.j2
Normal file
116
deployment/ansible/templates/wireguard-host-firewall.nft.j2
Normal file
@@ -0,0 +1,116 @@
|
||||
#!/usr/sbin/nft -f
|
||||
# WireGuard VPN Firewall Rules
|
||||
# Purpose: Isolate admin services behind VPN, allow public access only to ports 80, 443, 22
|
||||
# Generated by Ansible - DO NOT EDIT MANUALLY
|
||||
|
||||
table inet wireguard_firewall {
|
||||
# Define sets for easy management
|
||||
set vpn_network {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
elements = { {{ wg_network }} }
|
||||
}
|
||||
|
||||
set admin_service_ports {
|
||||
type inet_service
|
||||
elements = {
|
||||
8080, # Traefik Dashboard
|
||||
9090, # Prometheus
|
||||
3001, # Grafana
|
||||
9000, # Portainer
|
||||
8001, # Redis Insight
|
||||
{% for port in additional_admin_ports | default([]) %}
|
||||
{{ port }}, # {{ port }}
|
||||
{% endfor %}
|
||||
}
|
||||
}
|
||||
|
||||
set public_service_ports {
|
||||
type inet_service
|
||||
elements = {
|
||||
80, # HTTP
|
||||
443, # HTTPS
|
||||
22, # SSH
|
||||
{% for port in additional_public_ports | default([]) %}
|
||||
{{ port }}, # {{ port }}
|
||||
{% endfor %}
|
||||
}
|
||||
}
|
||||
|
||||
# Input chain - Handle incoming traffic
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
|
||||
# Allow established/related connections
|
||||
ct state established,related accept
|
||||
|
||||
# Allow loopback
|
||||
iifname "lo" accept
|
||||
|
||||
# Allow ICMP (ping)
|
||||
ip protocol icmp accept
|
||||
ip6 nexthdr icmpv6 accept
|
||||
|
||||
# Allow SSH (public)
|
||||
tcp dport 22 accept
|
||||
|
||||
# Allow WireGuard port (public)
|
||||
udp dport {{ wg_port | default(51820) }} accept comment "WireGuard VPN"
|
||||
|
||||
# Allow public web services (HTTP/HTTPS)
|
||||
tcp dport @public_service_ports accept comment "Public services"
|
||||
|
||||
# Allow VPN network to access admin services
|
||||
ip saddr @vpn_network tcp dport @admin_service_ports accept comment "VPN admin access"
|
||||
|
||||
# Block public access to admin services
|
||||
tcp dport @admin_service_ports counter log prefix "BLOCKED_ADMIN_SERVICE: " drop
|
||||
|
||||
# Log and drop all other traffic
|
||||
counter log prefix "BLOCKED_INPUT: " drop
|
||||
}
|
||||
|
||||
# Forward chain - Handle routed traffic (VPN to services)
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop;
|
||||
|
||||
# Allow established/related connections
|
||||
ct state established,related accept
|
||||
|
||||
# Allow VPN clients to access local services
|
||||
iifname "wg0" ip saddr @vpn_network accept comment "VPN to services"
|
||||
|
||||
# Allow return traffic to VPN clients
|
||||
oifname "wg0" ip daddr @vpn_network ct state established,related accept
|
||||
|
||||
# Log and drop all other forwarded traffic
|
||||
counter log prefix "BLOCKED_FORWARD: " drop
|
||||
}
|
||||
|
||||
# Output chain - Allow all outgoing traffic
|
||||
chain output {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
|
||||
# NAT chain - Masquerade VPN traffic to WAN
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority srcnat;
|
||||
|
||||
# Masquerade VPN traffic going to WAN
|
||||
oifname "{{ wan_interface }}" ip saddr @vpn_network masquerade comment "VPN NAT"
|
||||
}
|
||||
}
|
||||
|
||||
# Optional: Rate limiting for VPN port (DDoS protection)
|
||||
{% if wg_enable_rate_limit | default(true) %}
|
||||
table inet wireguard_ratelimit {
|
||||
chain input {
|
||||
type filter hook input priority -10;
|
||||
|
||||
# Rate limit WireGuard port: 10 connections per second per IP
|
||||
udp dport {{ wg_port | default(51820) }} \
|
||||
meter vpn_ratelimit { ip saddr limit rate over 10/second } \
|
||||
counter log prefix "VPN_RATELIMIT: " drop
|
||||
}
|
||||
}
|
||||
{% endif %}
|
||||
15
deployment/ansible/templates/wireguard-nftables.nft.j2
Normal file
15
deployment/ansible/templates/wireguard-nftables.nft.j2
Normal file
@@ -0,0 +1,15 @@
|
||||
table inet wireguard_{{ wg_interface }} {
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority srcnat;
|
||||
oifname "{{ wan_interface }}" ip saddr {{ wg_net }} masquerade
|
||||
}
|
||||
|
||||
chain forward {
|
||||
type filter hook forward priority filter;
|
||||
iifname "{{ wg_interface }}" ip saddr {{ wg_net }} counter accept
|
||||
oifname "{{ wg_interface }}" ip daddr {{ wg_net }} ct state established,related counter accept
|
||||
{% for net in extra_nets %}
|
||||
iifname "{{ wg_interface }}" ip daddr {{ net }} counter accept
|
||||
{% endfor %}
|
||||
}
|
||||
}
|
||||
14
deployment/ansible/wireguard/configs/michael-pc.conf
Normal file
14
deployment/ansible/wireguard/configs/michael-pc.conf
Normal file
@@ -0,0 +1,14 @@
|
||||
[Interface]
|
||||
# Client: michael-pc
|
||||
# Generated: 2025-11-05T01:02:14Z
|
||||
PrivateKey = MHgxUzmEHQ15EB3v4TaXEcJAZNRaBd54/ZDcN6nN8lI=
|
||||
Address = 10.8.0.2/32
|
||||
DNS = 1.1.1.1, 8.8.8.8
|
||||
|
||||
[Peer]
|
||||
# WireGuard Server
|
||||
PublicKey = SFxxHe4bunfQ1Xid5AMXbBgY+AjlxNtRHQ5uYjSib3E=
|
||||
PresharedKey = WsnvFp6WrF/y9fQwn3RgOTmwMS2UHoqIBRKrTPZ5lW8=
|
||||
Endpoint = 94.16.110.151:51820
|
||||
AllowedIPs = 10.8.0.0/24
|
||||
PersistentKeepalive = 25
|
||||
206
deployment/scripts/cleanup-old-wireguard.sh
Executable file
206
deployment/scripts/cleanup-old-wireguard.sh
Executable file
@@ -0,0 +1,206 @@
|
||||
#!/bin/bash
|
||||
# Cleanup Old WireGuard Docker Setup
|
||||
# Purpose: Remove old WireGuard Docker stack and CoreDNS before migrating to host-based setup
|
||||
# WARNING: This will stop and remove the old VPN setup!
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# Configuration
|
||||
# ========================================
|
||||
|
||||
DEPLOYMENT_DIR="/home/michael/dev/michaelschiemer/deployment"
|
||||
WIREGUARD_STACK_DIR="${DEPLOYMENT_DIR}/stacks/wireguard"
|
||||
COREDNS_STACK_DIR="${DEPLOYMENT_DIR}/stacks/coredns"
|
||||
ARCHIVE_DIR="${DEPLOYMENT_DIR}/wireguard-docker-archive-$(date +%Y%m%d)"
|
||||
|
||||
# ========================================
|
||||
# Pre-flight Checks
|
||||
# ========================================
|
||||
|
||||
print_info "WireGuard Docker Setup Cleanup Script"
|
||||
echo ""
|
||||
print_warning "This script will:"
|
||||
echo " - Stop WireGuard Docker container"
|
||||
echo " - Stop CoreDNS container (if exists)"
|
||||
echo " - Archive old configuration"
|
||||
echo " - Remove Docker stacks"
|
||||
echo ""
|
||||
print_warning "VPN access will be lost until new host-based setup is deployed!"
|
||||
echo ""
|
||||
read -p "Continue? (type 'yes' to proceed): " -r
|
||||
if [[ ! $REPLY == "yes" ]]; then
|
||||
print_info "Aborted by user"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ========================================
|
||||
# Stop Docker Containers
|
||||
# ========================================
|
||||
|
||||
print_info "Stopping WireGuard Docker container..."
|
||||
if [ -d "$WIREGUARD_STACK_DIR" ]; then
|
||||
cd "$WIREGUARD_STACK_DIR"
|
||||
if [ -f "docker-compose.yml" ]; then
|
||||
docker-compose down || print_warning "WireGuard container already stopped or not found"
|
||||
fi
|
||||
else
|
||||
print_warning "WireGuard stack directory not found: $WIREGUARD_STACK_DIR"
|
||||
fi
|
||||
|
||||
print_info "Stopping CoreDNS Docker container (if exists)..."
|
||||
if [ -d "$COREDNS_STACK_DIR" ]; then
|
||||
cd "$COREDNS_STACK_DIR"
|
||||
if [ -f "docker-compose.yml" ]; then
|
||||
docker-compose down || print_warning "CoreDNS container already stopped or not found"
|
||||
fi
|
||||
else
|
||||
print_info "CoreDNS stack directory not found (may not have existed)"
|
||||
fi
|
||||
|
||||
# ========================================
|
||||
# Archive Old Configuration
|
||||
# ========================================
|
||||
|
||||
print_info "Creating archive of old configuration..."
|
||||
mkdir -p "$ARCHIVE_DIR"
|
||||
|
||||
# Archive WireGuard stack
|
||||
if [ -d "$WIREGUARD_STACK_DIR" ]; then
|
||||
print_info "Archiving WireGuard stack..."
|
||||
cp -r "$WIREGUARD_STACK_DIR" "$ARCHIVE_DIR/wireguard-stack"
|
||||
print_success "WireGuard stack archived to: $ARCHIVE_DIR/wireguard-stack"
|
||||
fi
|
||||
|
||||
# Archive CoreDNS stack
|
||||
if [ -d "$COREDNS_STACK_DIR" ]; then
|
||||
print_info "Archiving CoreDNS stack..."
|
||||
cp -r "$COREDNS_STACK_DIR" "$ARCHIVE_DIR/coredns-stack"
|
||||
print_success "CoreDNS stack archived to: $ARCHIVE_DIR/coredns-stack"
|
||||
fi
|
||||
|
||||
# Archive old Ansible files
|
||||
print_info "Archiving old Ansible playbooks..."
|
||||
if [ -d "${DEPLOYMENT_DIR}/wireguard-old" ]; then
|
||||
cp -r "${DEPLOYMENT_DIR}/wireguard-old" "$ARCHIVE_DIR/ansible-old"
|
||||
fi
|
||||
|
||||
# Archive nftables templates
|
||||
if [ -f "${DEPLOYMENT_DIR}/ansible/templates/wireguard-nftables.nft.j2" ]; then
|
||||
mkdir -p "$ARCHIVE_DIR/ansible-templates"
|
||||
cp "${DEPLOYMENT_DIR}/ansible/templates/wireguard-nftables.nft.j2" "$ARCHIVE_DIR/ansible-templates/"
|
||||
fi
|
||||
|
||||
# Create archive summary
|
||||
cat > "$ARCHIVE_DIR/ARCHIVE_INFO.txt" <<EOF
|
||||
WireGuard Docker Setup Archive
|
||||
Created: $(date)
|
||||
|
||||
This archive contains the old WireGuard Docker-based setup that was replaced
|
||||
with a host-based WireGuard configuration.
|
||||
|
||||
Contents:
|
||||
- wireguard-stack/: Docker Compose stack for WireGuard
|
||||
- coredns-stack/: Docker Compose stack for CoreDNS (if existed)
|
||||
- ansible-old/: Old Ansible playbooks and configs
|
||||
- ansible-templates/: Old nftables templates
|
||||
|
||||
To restore old setup (NOT RECOMMENDED):
|
||||
1. Stop new host-based WireGuard: systemctl stop wg-quick@wg0
|
||||
2. Copy stacks back: cp -r wireguard-stack ../stacks/
|
||||
3. Start container: cd ../stacks/wireguard && docker-compose up -d
|
||||
|
||||
For new host-based setup, see:
|
||||
- deployment/wireguard/README.md
|
||||
- deployment/ansible/playbooks/setup-wireguard-host.yml
|
||||
EOF
|
||||
|
||||
print_success "Archive created at: $ARCHIVE_DIR"
|
||||
|
||||
# ========================================
|
||||
# Remove Docker Stacks
|
||||
# ========================================
|
||||
|
||||
print_info "Removing old Docker stacks..."
|
||||
|
||||
read -p "Remove WireGuard Docker stack directory? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
if [ -d "$WIREGUARD_STACK_DIR" ]; then
|
||||
rm -rf "$WIREGUARD_STACK_DIR"
|
||||
print_success "WireGuard Docker stack removed"
|
||||
fi
|
||||
fi
|
||||
|
||||
read -p "Remove CoreDNS Docker stack directory? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
if [ -d "$COREDNS_STACK_DIR" ]; then
|
||||
rm -rf "$COREDNS_STACK_DIR"
|
||||
print_success "CoreDNS Docker stack removed"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ========================================
|
||||
# Clean up Docker Resources
|
||||
# ========================================
|
||||
|
||||
print_info "Cleaning up Docker resources..."
|
||||
|
||||
# Remove WireGuard network
|
||||
docker network rm wireguard-net 2>/dev/null || print_info "WireGuard network already removed"
|
||||
|
||||
# Remove unused volumes
|
||||
print_info "Removing unused Docker volumes..."
|
||||
docker volume prune -f || print_warning "Could not prune volumes"
|
||||
|
||||
# ========================================
|
||||
# Summary
|
||||
# ========================================
|
||||
|
||||
echo ""
|
||||
print_success "=========================================="
|
||||
print_success "Cleanup Complete!"
|
||||
print_success "=========================================="
|
||||
echo ""
|
||||
echo "Archive Location: $ARCHIVE_DIR"
|
||||
echo ""
|
||||
print_info "Next Steps:"
|
||||
echo " 1. Deploy host-based WireGuard:"
|
||||
echo " cd ${DEPLOYMENT_DIR}/ansible"
|
||||
echo " ansible-playbook playbooks/setup-wireguard-host.yml"
|
||||
echo ""
|
||||
echo " 2. Generate client configs:"
|
||||
echo " cd ${DEPLOYMENT_DIR}/scripts"
|
||||
echo " sudo ./generate-client-config.sh <device-name>"
|
||||
echo ""
|
||||
echo " 3. Verify new setup:"
|
||||
echo " sudo wg show wg0"
|
||||
echo " sudo systemctl status wg-quick@wg0"
|
||||
echo ""
|
||||
print_warning "Old Docker-based VPN is now inactive!"
|
||||
print_info "VPN access will be restored after deploying host-based setup"
|
||||
echo ""
|
||||
282
deployment/scripts/generate-client-config.sh
Executable file
282
deployment/scripts/generate-client-config.sh
Executable file
@@ -0,0 +1,282 @@
|
||||
#!/bin/bash
|
||||
# WireGuard Client Configuration Generator
|
||||
# Purpose: Generate client configs with QR codes for easy mobile import
|
||||
# Usage: ./generate-client-config.sh <client-name>
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# ========================================
|
||||
# Configuration
|
||||
# ========================================
|
||||
|
||||
WG_CONFIG_DIR="/etc/wireguard"
|
||||
CLIENT_CONFIG_DIR="$(dirname "$0")/../wireguard/configs"
|
||||
WG_INTERFACE="wg0"
|
||||
WG_SERVER_CONFIG="${WG_CONFIG_DIR}/${WG_INTERFACE}.conf"
|
||||
WG_NETWORK="10.8.0.0/24"
|
||||
WG_SERVER_IP="10.8.0.1"
|
||||
WG_PORT="51820"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# ========================================
|
||||
# Helper Functions
|
||||
# ========================================
|
||||
|
||||
print_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
check_root() {
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
print_error "This script must be run as root (for server config modifications)"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
check_dependencies() {
|
||||
local deps=("wg" "wg-quick" "qrencode")
|
||||
local missing=()
|
||||
|
||||
for dep in "${deps[@]}"; do
|
||||
if ! command -v "$dep" &> /dev/null; then
|
||||
missing+=("$dep")
|
||||
fi
|
||||
done
|
||||
|
||||
if [ ${#missing[@]} -ne 0 ]; then
|
||||
print_error "Missing dependencies: ${missing[*]}"
|
||||
print_info "Install with: apt install wireguard wireguard-tools qrencode"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
get_next_client_ip() {
|
||||
# Find highest used IP in last octet and add 1
|
||||
if [ ! -f "$WG_SERVER_CONFIG" ]; then
|
||||
echo "10.8.0.2"
|
||||
return
|
||||
fi
|
||||
|
||||
local last_octet=$(grep -oP 'AllowedIPs\s*=\s*10\.8\.0\.\K\d+' "$WG_SERVER_CONFIG" 2>/dev/null | sort -n | tail -1)
|
||||
|
||||
if [ -z "$last_octet" ]; then
|
||||
echo "10.8.0.2"
|
||||
else
|
||||
echo "10.8.0.$((last_octet + 1))"
|
||||
fi
|
||||
}
|
||||
|
||||
get_server_public_key() {
|
||||
if [ ! -f "${WG_CONFIG_DIR}/server_public.key" ]; then
|
||||
print_error "Server public key not found at ${WG_CONFIG_DIR}/server_public.key"
|
||||
print_info "Run the Ansible playbook first: ansible-playbook setup-wireguard-host.yml"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat "${WG_CONFIG_DIR}/server_public.key"
|
||||
}
|
||||
|
||||
get_server_endpoint() {
|
||||
# Try to detect public IP
|
||||
local public_ip
|
||||
public_ip=$(curl -s -4 ifconfig.me 2>/dev/null || curl -s -4 icanhazip.com 2>/dev/null || echo "YOUR_SERVER_IP")
|
||||
|
||||
echo "${public_ip}:${WG_PORT}"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# Main Script
|
||||
# ========================================
|
||||
|
||||
main() {
|
||||
print_info "WireGuard Client Configuration Generator"
|
||||
echo ""
|
||||
|
||||
# Validate input
|
||||
if [ $# -ne 1 ]; then
|
||||
print_error "Usage: $0 <client-name>"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo " $0 michael-laptop"
|
||||
echo " $0 iphone"
|
||||
echo " $0 office-desktop"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local client_name="$1"
|
||||
|
||||
# Validate client name (alphanumeric + dash/underscore only)
|
||||
if ! [[ "$client_name" =~ ^[a-zA-Z0-9_-]+$ ]]; then
|
||||
print_error "Client name must contain only alphanumeric characters, dashes, and underscores"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Pre-flight checks
|
||||
check_root
|
||||
check_dependencies
|
||||
|
||||
# Create client config directory
|
||||
mkdir -p "$CLIENT_CONFIG_DIR"
|
||||
|
||||
# Check if client already exists
|
||||
if [ -f "${CLIENT_CONFIG_DIR}/${client_name}.conf" ]; then
|
||||
print_warning "Client config for '${client_name}' already exists"
|
||||
read -p "Regenerate? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
print_info "Aborted"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
print_info "Generating configuration for client: ${client_name}"
|
||||
echo ""
|
||||
|
||||
# Generate client keys
|
||||
print_info "Generating client keys..."
|
||||
local client_private_key=$(wg genkey)
|
||||
local client_public_key=$(echo "$client_private_key" | wg pubkey)
|
||||
local client_preshared_key=$(wg genpsk)
|
||||
|
||||
# Get server information
|
||||
print_info "Reading server configuration..."
|
||||
local server_public_key=$(get_server_public_key)
|
||||
local server_endpoint=$(get_server_endpoint)
|
||||
|
||||
# Assign client IP
|
||||
local client_ip=$(get_next_client_ip)
|
||||
print_info "Assigned client IP: ${client_ip}"
|
||||
|
||||
# Create client config file
|
||||
print_info "Creating client configuration file..."
|
||||
cat > "${CLIENT_CONFIG_DIR}/${client_name}.conf" <<EOF
|
||||
[Interface]
|
||||
# Client: ${client_name}
|
||||
# Generated: $(date)
|
||||
PrivateKey = ${client_private_key}
|
||||
Address = ${client_ip}/32
|
||||
|
||||
# DNS: Use Cloudflare/Quad9 (change if needed)
|
||||
DNS = 1.1.1.1, 9.9.9.9
|
||||
|
||||
[Peer]
|
||||
# Server
|
||||
PublicKey = ${server_public_key}
|
||||
PresharedKey = ${client_preshared_key}
|
||||
Endpoint = ${server_endpoint}
|
||||
|
||||
# Route only VPN network through tunnel (split-tunnel)
|
||||
AllowedIPs = ${WG_NETWORK}
|
||||
|
||||
# Keep connection alive (NAT traversal)
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
|
||||
chmod 600 "${CLIENT_CONFIG_DIR}/${client_name}.conf"
|
||||
|
||||
# Add peer to server configuration
|
||||
print_info "Adding peer to server configuration..."
|
||||
|
||||
# Check if peer already exists in server config
|
||||
if grep -q "# ${client_name}" "$WG_SERVER_CONFIG" 2>/dev/null; then
|
||||
print_info "Removing old peer entry..."
|
||||
# Remove old peer entry (from comment to next empty line or end of file)
|
||||
sed -i "/# ${client_name}/,/^$/d" "$WG_SERVER_CONFIG"
|
||||
fi
|
||||
|
||||
# Append new peer
|
||||
cat >> "$WG_SERVER_CONFIG" <<EOF
|
||||
|
||||
[Peer]
|
||||
# ${client_name}
|
||||
PublicKey = ${client_public_key}
|
||||
PresharedKey = ${client_preshared_key}
|
||||
AllowedIPs = ${client_ip}/32
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
|
||||
# Reload WireGuard to apply changes
|
||||
print_info "Reloading WireGuard configuration..."
|
||||
systemctl reload wg-quick@${WG_INTERFACE}
|
||||
|
||||
# Verify peer is active
|
||||
sleep 1
|
||||
if wg show ${WG_INTERFACE} | grep -q "$client_public_key"; then
|
||||
print_success "Peer successfully added to server"
|
||||
else
|
||||
print_warning "Peer added to config but not yet active (will activate when client connects)"
|
||||
fi
|
||||
|
||||
# Generate QR code for mobile devices
|
||||
print_info "Generating QR code for mobile import..."
|
||||
qrencode -t ansiutf8 < "${CLIENT_CONFIG_DIR}/${client_name}.conf" > "${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
|
||||
qrencode -t png -o "${CLIENT_CONFIG_DIR}/${client_name}.qr.png" < "${CLIENT_CONFIG_DIR}/${client_name}.conf"
|
||||
|
||||
# Display success summary
|
||||
echo ""
|
||||
print_success "=========================================="
|
||||
print_success "Client Configuration Created!"
|
||||
print_success "=========================================="
|
||||
echo ""
|
||||
echo "Client Name: ${client_name}"
|
||||
echo "Client IP: ${client_ip}"
|
||||
echo "Config File: ${CLIENT_CONFIG_DIR}/${client_name}.conf"
|
||||
echo "QR Code (text): ${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
|
||||
echo "QR Code (PNG): ${CLIENT_CONFIG_DIR}/${client_name}.qr.png"
|
||||
echo ""
|
||||
echo "Server Endpoint: ${server_endpoint}"
|
||||
echo "VPN Network: ${WG_NETWORK}"
|
||||
echo ""
|
||||
print_info "=========================================="
|
||||
print_info "Import Instructions:"
|
||||
print_info "=========================================="
|
||||
echo ""
|
||||
echo "Desktop (Linux/macOS):"
|
||||
echo " sudo cp ${CLIENT_CONFIG_DIR}/${client_name}.conf /etc/wireguard/"
|
||||
echo " sudo wg-quick up ${client_name}"
|
||||
echo ""
|
||||
echo "Desktop (Windows):"
|
||||
echo " 1. Open WireGuard GUI"
|
||||
echo " 2. Click 'Import tunnel(s) from file'"
|
||||
echo " 3. Select: ${CLIENT_CONFIG_DIR}/${client_name}.conf"
|
||||
echo ""
|
||||
echo "Mobile (iOS/Android):"
|
||||
echo " 1. Open WireGuard app"
|
||||
echo " 2. Tap '+' > 'Create from QR code'"
|
||||
echo " 3. Scan QR code below or from: ${CLIENT_CONFIG_DIR}/${client_name}.qr.png"
|
||||
echo ""
|
||||
print_info "QR Code (scan with phone):"
|
||||
echo ""
|
||||
cat "${CLIENT_CONFIG_DIR}/${client_name}.qr.txt"
|
||||
echo ""
|
||||
print_info "=========================================="
|
||||
print_info "Verify Connection:"
|
||||
print_info "=========================================="
|
||||
echo ""
|
||||
echo "After connecting:"
|
||||
echo " ping ${WG_SERVER_IP}"
|
||||
echo " curl -k https://${WG_SERVER_IP}:8080 # Traefik Dashboard"
|
||||
echo ""
|
||||
print_success "Configuration complete! Client is ready to connect."
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
307
deployment/scripts/manual-wireguard-setup.sh
Executable file
307
deployment/scripts/manual-wireguard-setup.sh
Executable file
@@ -0,0 +1,307 @@
|
||||
#!/bin/bash
|
||||
# Manual WireGuard Setup Script
|
||||
# Purpose: Step-by-step WireGuard installation and configuration
|
||||
# This script shows what needs to be done - review before executing!
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
print_step() {
|
||||
echo -e "${BLUE}[STEP]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# ========================================
|
||||
# Configuration
|
||||
# ========================================
|
||||
|
||||
WG_INTERFACE="wg0"
|
||||
WG_NETWORK="10.8.0.0/24"
|
||||
WG_SERVER_IP="10.8.0.1"
|
||||
WG_PORT="51820"
|
||||
WG_CONFIG_DIR="/etc/wireguard"
|
||||
WAN_INTERFACE="eth0" # ANPASSEN an dein System!
|
||||
|
||||
# ========================================
|
||||
# Pre-flight Checks
|
||||
# ========================================
|
||||
|
||||
print_step "Pre-flight Checks"
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
print_error "This script must be run as root"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if WireGuard is installed
|
||||
if ! command -v wg &> /dev/null; then
|
||||
print_error "WireGuard is not installed"
|
||||
echo "Install with: apt update && apt install -y wireguard wireguard-tools qrencode nftables"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
print_success "Pre-flight checks passed"
|
||||
|
||||
# ========================================
|
||||
# Step 1: Create WireGuard Directory
|
||||
# ========================================
|
||||
|
||||
print_step "Creating WireGuard directory"
|
||||
|
||||
mkdir -p ${WG_CONFIG_DIR}
|
||||
chmod 700 ${WG_CONFIG_DIR}
|
||||
|
||||
print_success "Directory created: ${WG_CONFIG_DIR}"
|
||||
|
||||
# ========================================
|
||||
# Step 2: Generate Server Keys
|
||||
# ========================================
|
||||
|
||||
print_step "Generating server keys"
|
||||
|
||||
cd ${WG_CONFIG_DIR}
|
||||
|
||||
if [ ! -f server_private.key ]; then
|
||||
wg genkey | tee server_private.key | wg pubkey > server_public.key
|
||||
chmod 600 server_private.key
|
||||
chmod 644 server_public.key
|
||||
print_success "Server keys generated"
|
||||
else
|
||||
print_warning "Server keys already exist - skipping generation"
|
||||
fi
|
||||
|
||||
SERVER_PRIVATE_KEY=$(cat server_private.key)
|
||||
SERVER_PUBLIC_KEY=$(cat server_public.key)
|
||||
|
||||
echo ""
|
||||
echo "Server Public Key: ${SERVER_PUBLIC_KEY}"
|
||||
echo ""
|
||||
|
||||
# ========================================
|
||||
# Step 3: Create WireGuard Configuration
|
||||
# ========================================
|
||||
|
||||
print_step "Creating WireGuard configuration"
|
||||
|
||||
cat > ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf <<EOF
|
||||
[Interface]
|
||||
# Server Configuration
|
||||
PrivateKey = ${SERVER_PRIVATE_KEY}
|
||||
Address = ${WG_SERVER_IP}/24
|
||||
ListenPort = ${WG_PORT}
|
||||
|
||||
# Enable IP forwarding
|
||||
PostUp = sysctl -w net.ipv4.ip_forward=1
|
||||
|
||||
# NAT Configuration with nftables
|
||||
PostUp = nft add table inet wireguard
|
||||
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
|
||||
PostUp = nft add rule inet wireguard postrouting oifname "${WAN_INTERFACE}" ip saddr ${WG_NETWORK} masquerade
|
||||
|
||||
# Cleanup on shutdown
|
||||
PostDown = nft delete table inet wireguard
|
||||
|
||||
# Peers will be added here via generate-client-config.sh
|
||||
EOF
|
||||
|
||||
chmod 600 ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf
|
||||
|
||||
print_success "Configuration created: ${WG_CONFIG_DIR}/${WG_INTERFACE}.conf"
|
||||
|
||||
# ========================================
|
||||
# Step 4: Create nftables Firewall Rules
|
||||
# ========================================
|
||||
|
||||
print_step "Creating nftables firewall rules"
|
||||
|
||||
cat > /etc/nftables.d/wireguard.nft <<'EOF'
|
||||
#!/usr/sbin/nft -f
|
||||
|
||||
# WireGuard Host-based Firewall Configuration
|
||||
# Purpose: Secure VPN access with admin service protection
|
||||
|
||||
table inet wireguard_firewall {
|
||||
# Define sets for efficient rule matching
|
||||
set vpn_network {
|
||||
type ipv4_addr
|
||||
flags interval
|
||||
elements = { 10.8.0.0/24 }
|
||||
}
|
||||
|
||||
set admin_service_ports {
|
||||
type inet_service
|
||||
elements = {
|
||||
8080, # Traefik Dashboard
|
||||
9090, # Prometheus
|
||||
3001, # Grafana
|
||||
9000, # Portainer
|
||||
8001, # Redis Insight
|
||||
}
|
||||
}
|
||||
|
||||
set public_service_ports {
|
||||
type inet_service
|
||||
elements = {
|
||||
80, # HTTP
|
||||
443, # HTTPS
|
||||
22, # SSH
|
||||
}
|
||||
}
|
||||
|
||||
# Input chain - Control incoming connections
|
||||
chain input {
|
||||
type filter hook input priority filter; policy drop;
|
||||
|
||||
# Allow established/related connections
|
||||
ct state established,related accept
|
||||
|
||||
# Allow loopback
|
||||
iif lo accept
|
||||
|
||||
# Allow ICMP (ping)
|
||||
ip protocol icmp accept
|
||||
ip6 nexthdr icmpv6 accept
|
||||
|
||||
# Allow WireGuard port
|
||||
udp dport 51820 accept
|
||||
|
||||
# Allow VPN network to access admin services
|
||||
ip saddr @vpn_network tcp dport @admin_service_ports accept
|
||||
|
||||
# Allow public access to public services
|
||||
tcp dport @public_service_ports accept
|
||||
|
||||
# Block public access to admin services (with logging)
|
||||
tcp dport @admin_service_ports counter log prefix "BLOCKED_ADMIN_SERVICE: " drop
|
||||
|
||||
# Rate limit SSH to prevent brute force
|
||||
tcp dport 22 ct state new limit rate 10/minute accept
|
||||
|
||||
# Drop everything else
|
||||
counter log prefix "BLOCKED_INPUT: " drop
|
||||
}
|
||||
|
||||
# Forward chain - Control packet forwarding
|
||||
chain forward {
|
||||
type filter hook forward priority filter; policy drop;
|
||||
|
||||
# Allow established/related connections
|
||||
ct state established,related accept
|
||||
|
||||
# Allow VPN network to forward
|
||||
ip saddr @vpn_network accept
|
||||
|
||||
# Drop everything else
|
||||
counter log prefix "BLOCKED_FORWARD: " drop
|
||||
}
|
||||
|
||||
# Output chain - Allow all outgoing by default
|
||||
chain output {
|
||||
type filter hook output priority filter; policy accept;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
chmod 755 /etc/nftables.d/wireguard.nft
|
||||
|
||||
print_success "Firewall rules created: /etc/nftables.d/wireguard.nft"
|
||||
|
||||
# ========================================
|
||||
# Step 5: Enable IP Forwarding
|
||||
# ========================================
|
||||
|
||||
print_step "Enabling IP forwarding"
|
||||
|
||||
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard.conf
|
||||
sysctl -p /etc/sysctl.d/99-wireguard.conf
|
||||
|
||||
print_success "IP forwarding enabled"
|
||||
|
||||
# ========================================
|
||||
# Step 6: Apply nftables Rules
|
||||
# ========================================
|
||||
|
||||
print_step "Applying nftables firewall rules"
|
||||
|
||||
if [ -f /etc/nftables.d/wireguard.nft ]; then
|
||||
nft -f /etc/nftables.d/wireguard.nft
|
||||
print_success "Firewall rules applied"
|
||||
else
|
||||
print_error "Firewall rules file not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# ========================================
|
||||
# Step 7: Enable and Start WireGuard
|
||||
# ========================================
|
||||
|
||||
print_step "Enabling and starting WireGuard service"
|
||||
|
||||
systemctl enable wg-quick@${WG_INTERFACE}
|
||||
systemctl start wg-quick@${WG_INTERFACE}
|
||||
|
||||
print_success "WireGuard service enabled and started"
|
||||
|
||||
# ========================================
|
||||
# Step 8: Verify Installation
|
||||
# ========================================
|
||||
|
||||
print_step "Verifying installation"
|
||||
|
||||
echo ""
|
||||
echo "WireGuard Status:"
|
||||
wg show ${WG_INTERFACE}
|
||||
|
||||
echo ""
|
||||
echo "Service Status:"
|
||||
systemctl status wg-quick@${WG_INTERFACE} --no-pager
|
||||
|
||||
echo ""
|
||||
echo "nftables Rules:"
|
||||
nft list table inet wireguard_firewall
|
||||
|
||||
# ========================================
|
||||
# Summary
|
||||
# ========================================
|
||||
|
||||
echo ""
|
||||
print_success "=========================================="
|
||||
print_success "WireGuard Installation Complete!"
|
||||
print_success "=========================================="
|
||||
echo ""
|
||||
echo "Server IP: ${WG_SERVER_IP}"
|
||||
echo "Listen Port: ${WG_PORT}"
|
||||
echo "VPN Network: ${WG_NETWORK}"
|
||||
echo "Interface: ${WG_INTERFACE}"
|
||||
echo ""
|
||||
print_step "Next Steps:"
|
||||
echo " 1. Generate client configs:"
|
||||
echo " cd /home/michael/dev/michaelschiemer/deployment/scripts"
|
||||
echo " sudo ./generate-client-config.sh <client-name>"
|
||||
echo ""
|
||||
echo " 2. Import client config on your device"
|
||||
echo ""
|
||||
echo " 3. Connect and test access to admin services:"
|
||||
echo " - Traefik Dashboard: https://10.8.0.1:8080"
|
||||
echo " - Prometheus: http://10.8.0.1:9090"
|
||||
echo " - Grafana: https://10.8.0.1:3001"
|
||||
echo " - Portainer: http://10.8.0.1:9000"
|
||||
echo " - Redis Insight: http://10.8.0.1:8001"
|
||||
echo ""
|
||||
@@ -1,14 +0,0 @@
|
||||
services:
|
||||
coredns:
|
||||
image: coredns/coredns:1.11.1
|
||||
container_name: coredns
|
||||
restart: unless-stopped
|
||||
network_mode: host
|
||||
command: -conf /etc/coredns/Corefile
|
||||
volumes:
|
||||
- ./Corefile:/etc/coredns/Corefile:ro
|
||||
healthcheck:
|
||||
# Disable healthcheck - CoreDNS is a minimal image without shell
|
||||
# CoreDNS runs fine (verified by DNS queries working correctly)
|
||||
# If needed, health can be checked externally via dig
|
||||
disable: true
|
||||
@@ -1,141 +0,0 @@
|
||||
services:
|
||||
portainer:
|
||||
image: portainer/portainer-ce:latest
|
||||
container_name: portainer
|
||||
restart: unless-stopped
|
||||
# DIRECT ACCESS: Bind only to VPN gateway IP
|
||||
ports:
|
||||
- "10.8.0.1:9002:9000" # Port 9002 to avoid conflict with MinIO (port 9000)
|
||||
networks:
|
||||
- monitoring-internal
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- portainer-data:/data
|
||||
# Removed Traefik labels - direct access only
|
||||
|
||||
prometheus:
|
||||
image: prom/prometheus:latest
|
||||
container_name: prometheus
|
||||
restart: unless-stopped
|
||||
user: "65534:65534"
|
||||
# DIRECT ACCESS: Bind only to VPN gateway IP
|
||||
ports:
|
||||
- "10.8.0.1:9090:9090"
|
||||
networks:
|
||||
- monitoring-internal
|
||||
- app-internal
|
||||
volumes:
|
||||
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||
- ./prometheus/alerts.yml:/etc/prometheus/alerts.yml:ro
|
||||
- prometheus-data:/prometheus
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
- '--storage.tsdb.path=/prometheus'
|
||||
- '--storage.tsdb.retention.time=30d'
|
||||
- '--web.console.libraries=/usr/share/prometheus/console_libraries'
|
||||
- '--web.console.templates=/usr/share/prometheus/consoles'
|
||||
- '--web.enable-lifecycle'
|
||||
# Removed Traefik labels - direct access only
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:latest
|
||||
container_name: grafana
|
||||
restart: unless-stopped
|
||||
# DIRECT ACCESS: Bind only to VPN gateway IP
|
||||
ports:
|
||||
- "10.8.0.1:3001:3000"
|
||||
networks:
|
||||
- monitoring-internal
|
||||
- app-internal
|
||||
environment:
|
||||
# Updated root URL for direct IP access
|
||||
- GF_SERVER_ROOT_URL=http://10.8.0.1:3001
|
||||
- GF_SECURITY_ADMIN_USER=${GRAFANA_ADMIN_USER}
|
||||
- GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_ADMIN_PASSWORD}
|
||||
- GF_USERS_ALLOW_SIGN_UP=false
|
||||
- GF_INSTALL_PLUGINS=${GRAFANA_PLUGINS}
|
||||
- GF_LOG_LEVEL=info
|
||||
- GF_ANALYTICS_REPORTING_ENABLED=false
|
||||
# Performance: Disable external connections to grafana.com
|
||||
- GF_PLUGIN_GRAFANA_COM_URL=
|
||||
- GF_CHECK_FOR_UPDATES=false
|
||||
- GF_CHECK_FOR_PLUGIN_UPDATES=false
|
||||
# Disable background plugin installer completely
|
||||
- GF_FEATURE_TOGGLES_ENABLE=disablePluginInstaller
|
||||
- GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=
|
||||
volumes:
|
||||
- grafana-data:/var/lib/grafana
|
||||
- ./grafana/grafana.ini:/etc/grafana/grafana.ini:ro
|
||||
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
||||
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
||||
# Removed Traefik labels - direct access only
|
||||
depends_on:
|
||||
prometheus:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
node-exporter:
|
||||
image: prom/node-exporter:latest
|
||||
container_name: node-exporter
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- app-internal
|
||||
volumes:
|
||||
- /proc:/host/proc:ro
|
||||
- /sys:/host/sys:ro
|
||||
- /:/rootfs:ro
|
||||
command:
|
||||
- '--path.procfs=/host/proc'
|
||||
- '--path.sysfs=/host/sys'
|
||||
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9100/metrics"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
cadvisor:
|
||||
image: gcr.io/cadvisor/cadvisor:latest
|
||||
container_name: cadvisor
|
||||
restart: unless-stopped
|
||||
privileged: true
|
||||
networks:
|
||||
- app-internal
|
||||
volumes:
|
||||
- /:/rootfs:ro
|
||||
- /var/run:/var/run:ro
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker/:/var/lib/docker:ro
|
||||
- /dev/disk/:/dev/disk:ro
|
||||
devices:
|
||||
- /dev/kmsg
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/healthz"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
|
||||
volumes:
|
||||
portainer-data:
|
||||
name: portainer-data
|
||||
prometheus-data:
|
||||
name: prometheus-data
|
||||
grafana-data:
|
||||
name: grafana-data
|
||||
|
||||
networks:
|
||||
# New internal network for monitoring services
|
||||
monitoring-internal:
|
||||
name: monitoring-internal
|
||||
driver: bridge
|
||||
app-internal:
|
||||
external: true
|
||||
@@ -41,7 +41,7 @@ services:
|
||||
- "traefik.http.routers.prometheus.entrypoints=websecure"
|
||||
- "traefik.http.routers.prometheus.tls=true"
|
||||
- "traefik.http.routers.prometheus.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.routers.prometheus.middlewares=prometheus-auth"
|
||||
- "traefik.http.routers.prometheus.middlewares=prometheus-auth@docker"
|
||||
- "traefik.http.middlewares.prometheus-auth.basicauth.users=${PROMETHEUS_AUTH}"
|
||||
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
|
||||
healthcheck:
|
||||
@@ -75,9 +75,6 @@ services:
|
||||
- "traefik.http.routers.grafana.entrypoints=websecure"
|
||||
- "traefik.http.routers.grafana.tls=true"
|
||||
- "traefik.http.routers.grafana.tls.certresolver=letsencrypt"
|
||||
# VPN IP whitelist: Use middleware defined in Traefik dynamic config
|
||||
# Middleware is defined in deployment/stacks/traefik/dynamic/middlewares.yml
|
||||
- "traefik.http.routers.grafana.middlewares=grafana-vpn-only@file"
|
||||
- "traefik.http.services.grafana.loadbalancer.server.port=3000"
|
||||
depends_on:
|
||||
prometheus:
|
||||
|
||||
@@ -52,25 +52,6 @@ http:
|
||||
# - "127.0.0.1/32"
|
||||
# - "10.0.0.0/8"
|
||||
|
||||
# VPN-only IP allowlist for Grafana and other monitoring services
|
||||
# Restrict access strictly to the WireGuard network
|
||||
# Note: ipAllowList checks the real client IP from the connection
|
||||
# When connected via VPN, client IP should be from 10.8.0.0/24
|
||||
# If client IP shows public IP, the traffic is NOT going through VPN
|
||||
# TEMPORARY: Added public IP for testing - REMOVE after fixing VPN routing!
|
||||
grafana-vpn-only:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- "10.8.0.0/24" # WireGuard VPN network (10.8.0.1 = server, 10.8.0.x = clients)
|
||||
- "89.246.96.244/32" # TEMPORARY: Public IP for testing - REMOVE after VPN routing is fixed!
|
||||
|
||||
# VPN-only IP allowlist for general use (Traefik Dashboard, etc.)
|
||||
# Restrict access strictly to the WireGuard network
|
||||
vpn-only:
|
||||
ipAllowList:
|
||||
sourceRange:
|
||||
- "10.8.0.0/24" # WireGuard VPN network
|
||||
|
||||
# Chain multiple middlewares
|
||||
default-chain:
|
||||
chain:
|
||||
|
||||
@@ -64,10 +64,8 @@ providers:
|
||||
|
||||
# Forwarded Headers Configuration
|
||||
# This ensures Traefik correctly identifies the real client IP
|
||||
# Important for VPN access where requests come from WireGuard interface
|
||||
forwardedHeaders:
|
||||
trustedIPs:
|
||||
- "10.8.0.0/24" # WireGuard VPN network
|
||||
- "127.0.0.1/32" # Localhost
|
||||
- "172.17.0.0/16" # Docker bridge network
|
||||
- "172.18.0.0/16" # Docker user-defined networks
|
||||
|
||||
22
deployment/stacks/wireguard/.env.example
Normal file
22
deployment/stacks/wireguard/.env.example
Normal file
@@ -0,0 +1,22 @@
|
||||
# WireGuard VPN Configuration
|
||||
|
||||
# Server endpoint (auto-detected or set manually)
|
||||
SERVERURL=auto
|
||||
|
||||
# WireGuard port
|
||||
SERVERPORT=51820
|
||||
|
||||
# VPN network subnet
|
||||
INTERNAL_SUBNET=10.8.0.0/24
|
||||
|
||||
# Allowed IPs (VPN network only - no split tunneling)
|
||||
ALLOWEDIPS=10.8.0.0/24
|
||||
|
||||
# DNS configuration (use host DNS)
|
||||
PEERDNS=auto
|
||||
|
||||
# Timezone
|
||||
TZ=Europe/Berlin
|
||||
|
||||
# Peers (managed manually)
|
||||
PEERS=0
|
||||
49
deployment/stacks/wireguard/docker-compose.yml
Normal file
49
deployment/stacks/wireguard/docker-compose.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
services:
|
||||
wireguard:
|
||||
image: linuxserver/wireguard:1.0.20210914
|
||||
container_name: wireguard
|
||||
restart: unless-stopped
|
||||
|
||||
cap_add:
|
||||
- NET_ADMIN
|
||||
- SYS_MODULE
|
||||
|
||||
environment:
|
||||
- PUID=1000
|
||||
- PGID=1000
|
||||
- TZ=Europe/Berlin
|
||||
- SERVERURL=auto
|
||||
- SERVERPORT=51820
|
||||
- PEERS=0 # Managed manually via config files
|
||||
- PEERDNS=auto # Use host DNS
|
||||
- INTERNAL_SUBNET=10.8.0.0/24
|
||||
- ALLOWEDIPS=10.8.0.0/24 # VPN network only
|
||||
- LOG_CONFS=true
|
||||
|
||||
volumes:
|
||||
- ./config:/config
|
||||
- /lib/modules:/lib/modules:ro
|
||||
|
||||
ports:
|
||||
- "51820:51820/udp"
|
||||
|
||||
sysctls:
|
||||
- net.ipv4.conf.all.src_valid_mark=1
|
||||
|
||||
healthcheck:
|
||||
test: ["CMD", "bash", "-c", "wg show wg0 | grep -q interface"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
logging:
|
||||
driver: "json-file"
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: wireguard-net
|
||||
driver: bridge
|
||||
370
deployment/wireguard/CLIENT-IMPORT-GUIDE.md
Normal file
370
deployment/wireguard/CLIENT-IMPORT-GUIDE.md
Normal file
@@ -0,0 +1,370 @@
|
||||
# WireGuard Client Import & Connection Guide
|
||||
|
||||
Anleitung zum Importieren und Verbinden der generierten WireGuard Client-Konfiguration.
|
||||
|
||||
## Generierte Konfiguration
|
||||
|
||||
**Client Name**: michael-pc
|
||||
**Config File**: `/home/michael/dev/michaelschiemer/deployment/ansible/wireguard/configs/michael-pc.conf`
|
||||
**Client IP**: 10.8.0.2/32
|
||||
**Server Endpoint**: 94.16.110.151:51820
|
||||
**VPN Network**: 10.8.0.0/24
|
||||
|
||||
---
|
||||
|
||||
## Import auf verschiedenen Plattformen
|
||||
|
||||
### Linux (Ubuntu/Debian)
|
||||
|
||||
```bash
|
||||
# 1. Konfiguration nach /etc/wireguard/ kopieren
|
||||
sudo cp /home/michael/dev/michaelschiemer/deployment/ansible/wireguard/configs/michael-pc.conf /etc/wireguard/
|
||||
|
||||
# 2. Berechtigungen setzen
|
||||
sudo chmod 600 /etc/wireguard/michael-pc.conf
|
||||
|
||||
# 3. VPN-Verbindung starten
|
||||
sudo wg-quick up michael-pc
|
||||
|
||||
# 4. Status prüfen
|
||||
sudo wg show michael-pc
|
||||
|
||||
# 5. Bei Boot automatisch starten (optional)
|
||||
sudo systemctl enable wg-quick@michael-pc
|
||||
```
|
||||
|
||||
**Verbindung trennen**:
|
||||
```bash
|
||||
sudo wg-quick down michael-pc
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### macOS
|
||||
|
||||
```bash
|
||||
# 1. WireGuard installieren (falls nicht vorhanden)
|
||||
brew install wireguard-tools
|
||||
|
||||
# 2. Konfiguration importieren
|
||||
sudo cp /home/michael/dev/michaelschiemer/deployment/ansible/wireguard/configs/michael-pc.conf /etc/wireguard/
|
||||
|
||||
# 3. VPN starten
|
||||
sudo wg-quick up michael-pc
|
||||
|
||||
# 4. Status prüfen
|
||||
sudo wg show michael-pc
|
||||
```
|
||||
|
||||
**Alternative**: WireGuard GUI App für macOS verwenden
|
||||
- Download: https://apps.apple.com/app/wireguard/id1451685025
|
||||
- "Add Tunnel from File" → `michael-pc.conf` auswählen
|
||||
- Verbindung aktivieren
|
||||
|
||||
---
|
||||
|
||||
### Windows
|
||||
|
||||
**Via WireGuard GUI** (empfohlen):
|
||||
|
||||
1. **WireGuard GUI installieren**:
|
||||
- Download: https://www.wireguard.com/install/
|
||||
- Installer ausführen
|
||||
|
||||
2. **Konfiguration importieren**:
|
||||
- WireGuard GUI öffnen
|
||||
- "Import tunnel(s) from file"
|
||||
- `michael-pc.conf` auswählen
|
||||
|
||||
3. **Verbindung aktivieren**:
|
||||
- Tunnel "michael-pc" in der Liste anklicken
|
||||
- "Activate" Button drücken
|
||||
|
||||
4. **Status prüfen**:
|
||||
- Status sollte "Active" zeigen
|
||||
- Transfer-Statistiken werden angezeigt
|
||||
|
||||
---
|
||||
|
||||
### Android
|
||||
|
||||
**Via WireGuard App**:
|
||||
|
||||
1. **WireGuard App installieren**:
|
||||
- Google Play Store: "WireGuard"
|
||||
|
||||
2. **Konfiguration importieren**:
|
||||
- Option 1: `michael-pc.conf` auf Gerät übertragen und importieren
|
||||
- Option 2: QR Code scannen (falls generiert)
|
||||
|
||||
3. **Verbindung aktivieren**:
|
||||
- Tunnel antippen
|
||||
- Toggle aktivieren
|
||||
|
||||
---
|
||||
|
||||
### iOS
|
||||
|
||||
**Via WireGuard App**:
|
||||
|
||||
1. **WireGuard App installieren**:
|
||||
- App Store: "WireGuard"
|
||||
|
||||
2. **Konfiguration importieren**:
|
||||
- Option 1: `michael-pc.conf` via AirDrop/iCloud übertragen
|
||||
- Option 2: QR Code scannen (falls generiert)
|
||||
|
||||
3. **Verbindung aktivieren**:
|
||||
- Tunnel antippen
|
||||
- Toggle aktivieren
|
||||
|
||||
---
|
||||
|
||||
## Konnektivitätstest
|
||||
|
||||
Nach erfolgreicher Verbindung:
|
||||
|
||||
### 1. VPN Gateway Ping
|
||||
|
||||
```bash
|
||||
ping 10.8.0.1
|
||||
```
|
||||
|
||||
**Erwartete Ausgabe**:
|
||||
```
|
||||
PING 10.8.0.1 (10.8.0.1) 56(84) bytes of data.
|
||||
64 bytes from 10.8.0.1: icmp_seq=1 ttl=64 time=1.23 ms
|
||||
64 bytes from 10.8.0.1: icmp_seq=2 ttl=64 time=1.15 ms
|
||||
```
|
||||
|
||||
✅ **Erfolg**: VPN-Verbindung funktioniert
|
||||
|
||||
---
|
||||
|
||||
### 2. Admin Services Zugriff
|
||||
|
||||
**Traefik Dashboard** (HTTPS):
|
||||
```bash
|
||||
curl -k https://10.8.0.1:8080
|
||||
```
|
||||
|
||||
**Prometheus** (HTTP):
|
||||
```bash
|
||||
curl http://10.8.0.1:9090
|
||||
```
|
||||
|
||||
**Grafana** (HTTPS):
|
||||
```bash
|
||||
curl -k https://10.8.0.1:3001
|
||||
```
|
||||
|
||||
**Portainer** (HTTP):
|
||||
```bash
|
||||
curl http://10.8.0.1:9000
|
||||
```
|
||||
|
||||
**Redis Insight** (HTTP):
|
||||
```bash
|
||||
curl http://10.8.0.1:8001
|
||||
```
|
||||
|
||||
**Browser-Zugriff**:
|
||||
- Traefik: https://10.8.0.1:8080
|
||||
- Prometheus: http://10.8.0.1:9090
|
||||
- Grafana: https://10.8.0.1:3001
|
||||
- Portainer: http://10.8.0.1:9000
|
||||
- Redis Insight: http://10.8.0.1:8001
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Problem: Keine Verbindung zum Server
|
||||
|
||||
**Symptome**:
|
||||
- `ping 10.8.0.1` timeout
|
||||
- WireGuard Status zeigt "Handshake failed"
|
||||
|
||||
**Lösungen**:
|
||||
|
||||
1. **Server Endpoint prüfen**:
|
||||
```bash
|
||||
# Prüfe ob Server erreichbar ist
|
||||
ping 94.16.110.151
|
||||
|
||||
# Prüfe ob Port 51820 offen ist
|
||||
nc -zvu 94.16.110.151 51820
|
||||
```
|
||||
|
||||
2. **Firewall auf Server prüfen**:
|
||||
```bash
|
||||
# Auf Server ausführen
|
||||
sudo nft list ruleset | grep 51820
|
||||
```
|
||||
|
||||
3. **WireGuard Server Status prüfen**:
|
||||
```bash
|
||||
# Auf Server ausführen
|
||||
sudo systemctl status wg-quick@wg0
|
||||
sudo wg show wg0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: VPN verbindet, aber kein Zugriff auf Admin Services
|
||||
|
||||
**Symptome**:
|
||||
- `ping 10.8.0.1` funktioniert
|
||||
- `curl http://10.8.0.1:9090` timeout
|
||||
|
||||
**Lösungen**:
|
||||
|
||||
1. **Routing prüfen**:
|
||||
```bash
|
||||
# Auf Client
|
||||
ip route | grep 10.8.0
|
||||
```
|
||||
|
||||
2. **Firewall-Rules auf Server prüfen**:
|
||||
```bash
|
||||
# Auf Server
|
||||
sudo nft list table inet wireguard_firewall
|
||||
```
|
||||
|
||||
3. **Service-Status prüfen**:
|
||||
```bash
|
||||
# Auf Server - Services sollten laufen
|
||||
docker ps | grep prometheus
|
||||
docker ps | grep grafana
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: DNS funktioniert nicht
|
||||
|
||||
**Symptome**:
|
||||
- Kann keine Domains auflösen
|
||||
|
||||
**Lösung**:
|
||||
```bash
|
||||
# DNS-Server in Client-Config prüfen
|
||||
grep DNS /etc/wireguard/michael-pc.conf
|
||||
# Sollte sein: DNS = 1.1.1.1, 8.8.8.8
|
||||
|
||||
# DNS-Resolver testen
|
||||
nslookup google.com 1.1.1.1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Problem: Verbindung bricht ständig ab
|
||||
|
||||
**Symptome**:
|
||||
- Verbindung disconnected nach einigen Minuten
|
||||
|
||||
**Lösungen**:
|
||||
|
||||
1. **PersistentKeepalive prüfen**:
|
||||
```bash
|
||||
grep PersistentKeepalive /etc/wireguard/michael-pc.conf
|
||||
# Sollte sein: PersistentKeepalive = 25
|
||||
```
|
||||
|
||||
2. **NAT/Router-Timeout**:
|
||||
- PersistentKeepalive verhindert NAT-Timeout
|
||||
- Wert auf 25 Sekunden gesetzt
|
||||
|
||||
---
|
||||
|
||||
## Firewall-Validierung
|
||||
|
||||
### Public Access sollte blockiert sein
|
||||
|
||||
**Von außerhalb des VPNs testen** (z.B. vom Internet):
|
||||
|
||||
```bash
|
||||
# Diese Requests sollten FEHLSCHLAGEN (timeout oder connection refused):
|
||||
curl --max-time 5 http://94.16.110.151:9090 # Prometheus
|
||||
curl --max-time 5 http://94.16.110.151:8080 # Traefik Dashboard
|
||||
curl --max-time 5 http://94.16.110.151:9000 # Portainer
|
||||
|
||||
# Nur Public Services sollten erreichbar sein:
|
||||
curl http://94.16.110.151:80 # HTTP (funktioniert)
|
||||
curl https://94.16.110.151:443 # HTTPS (funktioniert)
|
||||
```
|
||||
|
||||
**Erwartetes Ergebnis**:
|
||||
- ❌ Admin-Ports (8080, 9090, 3001, 9000, 8001): Timeout oder Connection Refused
|
||||
- ✅ Public-Ports (80, 443): Erreichbar
|
||||
|
||||
### Firewall-Logs prüfen
|
||||
|
||||
**Auf Server**:
|
||||
```bash
|
||||
# Geblockte Zugriffe auf Admin-Services loggen
|
||||
sudo journalctl -k | grep "BLOCKED_ADMIN_SERVICE"
|
||||
|
||||
# Beispiel-Ausgabe:
|
||||
# [ 123.456] BLOCKED_ADMIN_SERVICE: IN=eth0 OUT= SRC=203.0.113.42 DST=94.16.110.151 PROTO=TCP DPT=8080
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sicherheitshinweise
|
||||
|
||||
### ✅ Best Practices
|
||||
|
||||
1. **Private Keys schützen**:
|
||||
- Niemals Private Keys committen oder teilen
|
||||
- Berechtigungen: `chmod 600` für .conf Dateien
|
||||
|
||||
2. **Regelmäßige Key-Rotation**:
|
||||
- Empfohlen: Jährlich neue Keys generieren
|
||||
- Bei Kompromittierung: Sofort neue Keys erstellen
|
||||
|
||||
3. **Client-Zugriff widerrufen**:
|
||||
```bash
|
||||
# Auf Server: Peer aus Konfiguration entfernen
|
||||
sudo nano /etc/wireguard/wg0.conf
|
||||
# [Peer]-Block für michael-pc entfernen
|
||||
|
||||
# WireGuard neu laden
|
||||
sudo wg syncconf wg0 <(wg-quick strip wg0)
|
||||
```
|
||||
|
||||
4. **VPN-Monitoring**:
|
||||
```bash
|
||||
# Aktive Verbindungen prüfen
|
||||
sudo wg show wg0
|
||||
|
||||
# Letzte Handshake-Zeit prüfen
|
||||
sudo wg show wg0 latest-handshakes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nächste Schritte
|
||||
|
||||
Nach erfolgreicher VPN-Verbindung:
|
||||
|
||||
1. ✅ **VPN-Zugriff verifizieren**: Gateway ping + Admin Services Zugriff
|
||||
2. ✅ **Firewall-Rules validieren**: Public Access blockiert, VPN Access erlaubt
|
||||
3. ⏭️ **Weitere Clients hinzufügen** (optional):
|
||||
```bash
|
||||
ansible-playbook playbooks/generate-wireguard-client.yml -e "client_name=laptop"
|
||||
ansible-playbook playbooks/generate-wireguard-client.yml -e "client_name=phone"
|
||||
```
|
||||
|
||||
4. ⏭️ **Backup der Client-Configs**:
|
||||
```bash
|
||||
# Configs sind in .gitignore - manuelles Backup notwendig
|
||||
tar -czf wireguard-client-configs-backup-$(date +%Y%m%d).tar.gz \
|
||||
/home/michael/dev/michaelschiemer/deployment/ansible/wireguard/configs/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Erstellt**: 2025-11-05
|
||||
**Client Config**: michael-pc (10.8.0.2/32)
|
||||
**Server Endpoint**: 94.16.110.151:51820
|
||||
**VPN Network**: 10.8.0.0/24
|
||||
259
deployment/wireguard/INDEX.md
Normal file
259
deployment/wireguard/INDEX.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# WireGuard Setup - Dokumentations-Index
|
||||
|
||||
Kompletter Index aller Dokumentation und Scripts für das minimalistic WireGuard Setup.
|
||||
|
||||
## 📚 Dokumentation
|
||||
|
||||
### Haupt-Dokumentation
|
||||
|
||||
| Datei | Zweck | Zielgruppe |
|
||||
|-------|-------|------------|
|
||||
| **README.md** | Vollständige Dokumentation mit Architektur, Setup, Troubleshooting | Alle Nutzer |
|
||||
| **QUICKSTART.md** | 5-Minuten Quick Start Guide | Neue Nutzer |
|
||||
| **INSTALLATION-LOG.md** | Schritt-für-Schritt Installations-Log | Systemadministratoren |
|
||||
| **INDEX.md** (diese Datei) | Übersicht aller Dateien | Navigation |
|
||||
|
||||
### Client-Dokumentation
|
||||
|
||||
| Datei | Zweck |
|
||||
|-------|-------|
|
||||
| **configs/README.md** | Client Config Verzeichnis Dokumentation und Sicherheitshinweise |
|
||||
| **configs/.gitignore** | Verhindert Commit von sensitiven Client Configs |
|
||||
|
||||
## 🛠️ Scripts
|
||||
|
||||
### Setup Scripts
|
||||
|
||||
| Script | Zweck | Ausführung |
|
||||
|--------|-------|------------|
|
||||
| **scripts/manual-wireguard-setup.sh** | Manuelles Setup-Script für Host-Installation | `sudo ./manual-wireguard-setup.sh` |
|
||||
| **scripts/generate-client-config.sh** | Client Config Generator mit QR Codes | `sudo ./generate-client-config.sh <client-name>` |
|
||||
| **scripts/cleanup-old-wireguard.sh** | Cleanup des alten Docker-basierten Setups | `sudo ./cleanup-old-wireguard.sh` |
|
||||
|
||||
### Ansible Automation
|
||||
|
||||
| Datei | Zweck |
|
||||
|-------|-------|
|
||||
| **ansible/playbooks/setup-wireguard-host.yml** | Vollständiges Ansible Playbook für automatisches Deployment |
|
||||
| **ansible/templates/wg0.conf.j2** | WireGuard Server Config Template |
|
||||
| **ansible/templates/wireguard-host-firewall.nft.j2** | nftables Firewall Rules Template |
|
||||
|
||||
## 🚀 Quick Start - Welche Datei nutzen?
|
||||
|
||||
### Für Anfänger: QUICKSTART.md
|
||||
```bash
|
||||
cat deployment/wireguard/QUICKSTART.md
|
||||
```
|
||||
- 5-Minuten Setup
|
||||
- Einfache Schritt-für-Schritt Anleitung
|
||||
- Für Linux, Windows, macOS, iOS, Android
|
||||
|
||||
### Für Erfahrene: README.md
|
||||
```bash
|
||||
cat deployment/wireguard/README.md
|
||||
```
|
||||
- Vollständige Architektur-Übersicht
|
||||
- Detaillierte Konfigurationsoptionen
|
||||
- Troubleshooting-Guide
|
||||
- Sicherheits-Best-Practices
|
||||
|
||||
### Für Automatisierung: Ansible
|
||||
```bash
|
||||
cd deployment/ansible
|
||||
ansible-playbook playbooks/setup-wireguard-host.yml
|
||||
```
|
||||
- Vollautomatisches Deployment
|
||||
- Idempotent und wiederholbar
|
||||
- Backup und Rollback-Support
|
||||
|
||||
### Für manuelle Installation: manual-wireguard-setup.sh
|
||||
```bash
|
||||
cd deployment/scripts
|
||||
sudo ./manual-wireguard-setup.sh
|
||||
```
|
||||
- Interaktives Setup
|
||||
- Zeigt alle Schritte
|
||||
- Verifikation nach jedem Schritt
|
||||
|
||||
## 📋 Installations-Workflow
|
||||
|
||||
### Methode 1: Automatisiert (Empfohlen)
|
||||
|
||||
```bash
|
||||
# 1. Cleanup altes Setup (falls vorhanden)
|
||||
cd deployment/scripts
|
||||
sudo ./cleanup-old-wireguard.sh
|
||||
|
||||
# 2. Automatisches Deployment
|
||||
cd ../ansible
|
||||
ansible-playbook playbooks/setup-wireguard-host.yml
|
||||
|
||||
# 3. Client Config generieren
|
||||
cd ../scripts
|
||||
sudo ./generate-client-config.sh michael-laptop
|
||||
|
||||
# 4. Client verbinden und testen
|
||||
# (Siehe QUICKSTART.md)
|
||||
```
|
||||
|
||||
### Methode 2: Manuell
|
||||
|
||||
```bash
|
||||
# 1. Setup-Script ausführen
|
||||
cd deployment/scripts
|
||||
sudo ./manual-wireguard-setup.sh
|
||||
|
||||
# 2. INSTALLATION-LOG.md durchgehen
|
||||
cat ../wireguard/INSTALLATION-LOG.md
|
||||
|
||||
# 3. Client Config generieren
|
||||
sudo ./generate-client-config.sh michael-laptop
|
||||
|
||||
# 4. Client verbinden und testen
|
||||
# (Siehe QUICKSTART.md)
|
||||
```
|
||||
|
||||
## 🔍 Nach Installation
|
||||
|
||||
### Verifikation
|
||||
|
||||
```bash
|
||||
# WireGuard Status
|
||||
sudo wg show wg0
|
||||
|
||||
# Service Status
|
||||
sudo systemctl status wg-quick@wg0
|
||||
|
||||
# Firewall Rules
|
||||
sudo nft list table inet wireguard_firewall
|
||||
|
||||
# IP Forwarding
|
||||
cat /proc/sys/net/ipv4/ip_forward
|
||||
```
|
||||
|
||||
### Client Zugriff testen
|
||||
|
||||
Nach VPN-Verbindung:
|
||||
|
||||
```bash
|
||||
# VPN-Gateway ping
|
||||
ping 10.8.0.1
|
||||
|
||||
# Admin Services
|
||||
curl -k https://10.8.0.1:8080 # Traefik Dashboard
|
||||
curl http://10.8.0.1:9090 # Prometheus
|
||||
curl https://10.8.0.1:3001 # Grafana
|
||||
curl http://10.8.0.1:9000 # Portainer
|
||||
curl http://10.8.0.1:8001 # Redis Insight
|
||||
```
|
||||
|
||||
## 🛡️ Sicherheit
|
||||
|
||||
### Vor Deployment lesen
|
||||
|
||||
1. **README.md → Security Architecture**
|
||||
- Defense in Depth Strategie
|
||||
- Zero Trust Network Prinzipien
|
||||
- Moderne Kryptographie
|
||||
|
||||
2. **README.md → Security Best Practices**
|
||||
- Key Rotation
|
||||
- Client Config Sicherung
|
||||
- Firewall Monitoring
|
||||
|
||||
3. **configs/.gitignore**
|
||||
- Client Configs NIEMALS committen
|
||||
- Private Keys schützen
|
||||
|
||||
## 📊 Monitoring & Troubleshooting
|
||||
|
||||
### Logs überwachen
|
||||
|
||||
```bash
|
||||
# WireGuard Service Logs
|
||||
sudo journalctl -u wg-quick@wg0 -f
|
||||
|
||||
# Firewall Block Logs
|
||||
sudo journalctl -k | grep "BLOCKED"
|
||||
|
||||
# System Logs
|
||||
sudo dmesg | grep wireguard
|
||||
```
|
||||
|
||||
### Häufige Probleme
|
||||
|
||||
Siehe **README.md → Troubleshooting Section** für:
|
||||
- Connection refused
|
||||
- Firewall blockiert Zugriff
|
||||
- Routing-Probleme
|
||||
- Performance-Issues
|
||||
|
||||
## 🔄 Wartung
|
||||
|
||||
### Regelmäßige Tasks
|
||||
|
||||
```bash
|
||||
# Client Config generieren (neue Geräte)
|
||||
cd deployment/scripts
|
||||
sudo ./generate-client-config.sh <device-name>
|
||||
|
||||
# Client revoken
|
||||
# (Siehe README.md → Revoke Client Access)
|
||||
|
||||
# Backup durchführen
|
||||
tar -czf wireguard-backup-$(date +%Y%m%d).tar.gz /etc/wireguard/
|
||||
|
||||
# Firewall Rules updaten
|
||||
# (Siehe README.md → Firewall Configuration)
|
||||
```
|
||||
|
||||
### Updates
|
||||
|
||||
```bash
|
||||
# WireGuard Update
|
||||
sudo apt update && sudo apt upgrade wireguard wireguard-tools
|
||||
|
||||
# Konfiguration reload
|
||||
sudo systemctl reload wg-quick@wg0
|
||||
|
||||
# Oder restart
|
||||
sudo systemctl restart wg-quick@wg0
|
||||
```
|
||||
|
||||
## 📖 Weitere Ressourcen
|
||||
|
||||
### Externe Dokumentation
|
||||
|
||||
- [WireGuard Official Docs](https://www.wireguard.com/)
|
||||
- [nftables Wiki](https://wiki.nftables.org/)
|
||||
- [systemd Documentation](https://www.freedesktop.org/software/systemd/man/)
|
||||
|
||||
### Framework Integration
|
||||
|
||||
- **Event System**: WireGuard-Events können über Framework Event System geloggt werden
|
||||
- **Monitoring**: Integration mit Framework Performance Monitoring
|
||||
- **Alerts**: Benachrichtigungen bei VPN-Problemen über Framework Alert System
|
||||
|
||||
## 🎯 Nächste Schritte (Phase 2 - Optional)
|
||||
|
||||
Falls DNS gewünscht:
|
||||
|
||||
1. **CoreDNS Minimal Setup**
|
||||
- Siehe User's CoreDNS Konfigurationsbeispiel
|
||||
- Integration mit WireGuard
|
||||
- `.internal` Domain für Services
|
||||
|
||||
2. **Service Discovery**
|
||||
- Automatische DNS-Einträge für Docker Services
|
||||
- Load Balancing über DNS
|
||||
|
||||
3. **Monitoring**
|
||||
- DNS Query Logs
|
||||
- Performance Metriken
|
||||
|
||||
---
|
||||
|
||||
**Erstellt**: 2025-11-05
|
||||
**Framework Version**: 2.x
|
||||
**WireGuard Version**: 1.0.20210914
|
||||
**Zielplattform**: Debian/Ubuntu Linux mit systemd
|
||||
275
deployment/wireguard/INSTALLATION-LOG.md
Normal file
275
deployment/wireguard/INSTALLATION-LOG.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# WireGuard Installation Log
|
||||
|
||||
Dokumentation der manuellen WireGuard Installation auf dem Host-System.
|
||||
|
||||
## Systemumgebung
|
||||
|
||||
```bash
|
||||
# System prüfen
|
||||
uname -a
|
||||
# Linux hostname 6.6.87.2-microsoft-standard-WSL2 #1 SMP ...
|
||||
|
||||
# WireGuard Version
|
||||
wg --version
|
||||
# wireguard-tools v1.0.20210914
|
||||
|
||||
# Netzwerk Interface
|
||||
ip addr show
|
||||
# Haupt-Interface für WAN: eth0
|
||||
```
|
||||
|
||||
## Installation durchgeführt am
|
||||
|
||||
**Datum**: [WIRD BEIM AUSFÜHREN GESETZT]
|
||||
**Benutzer**: root (via sudo)
|
||||
**Methode**: Manual Setup Script
|
||||
|
||||
## Installationsschritte
|
||||
|
||||
### ✅ Schritt 1: Verzeichnis erstellen
|
||||
|
||||
```bash
|
||||
sudo mkdir -p /etc/wireguard
|
||||
sudo chmod 700 /etc/wireguard
|
||||
```
|
||||
|
||||
**Status**: Bereit für Ausführung
|
||||
**Zweck**: Sicheres Verzeichnis für WireGuard-Konfiguration
|
||||
|
||||
### ✅ Schritt 2: Server Keys generieren
|
||||
|
||||
```bash
|
||||
cd /etc/wireguard
|
||||
sudo wg genkey | sudo tee server_private.key | sudo wg pubkey | sudo tee server_public.key
|
||||
sudo chmod 600 server_private.key
|
||||
sudo chmod 644 server_public.key
|
||||
```
|
||||
|
||||
**Status**: Bereit für Ausführung
|
||||
**Zweck**: Kryptographische Schlüssel für Server generieren
|
||||
**Ausgabe**:
|
||||
- `server_private.key` - Privater Schlüssel (geheim!)
|
||||
- `server_public.key` - Öffentlicher Schlüssel (für Clients)
|
||||
|
||||
### ✅ Schritt 3: WireGuard Konfiguration erstellen
|
||||
|
||||
**Datei**: `/etc/wireguard/wg0.conf`
|
||||
|
||||
```ini
|
||||
[Interface]
|
||||
# Server Configuration
|
||||
PrivateKey = [GENERATED_SERVER_PRIVATE_KEY]
|
||||
Address = 10.8.0.1/24
|
||||
ListenPort = 51820
|
||||
|
||||
# Enable IP forwarding
|
||||
PostUp = sysctl -w net.ipv4.ip_forward=1
|
||||
|
||||
# NAT Configuration with nftables
|
||||
PostUp = nft add table inet wireguard
|
||||
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
|
||||
PostUp = nft add rule inet wireguard postrouting oifname "eth0" ip saddr 10.8.0.0/24 masquerade
|
||||
|
||||
# Cleanup on shutdown
|
||||
PostDown = nft delete table inet wireguard
|
||||
|
||||
# Peers will be added here via generate-client-config.sh
|
||||
```
|
||||
|
||||
**Status**: Template erstellt
|
||||
**Permissions**: `chmod 600 /etc/wireguard/wg0.conf`
|
||||
|
||||
### ✅ Schritt 4: nftables Firewall Rules
|
||||
|
||||
**Datei**: `/etc/nftables.d/wireguard.nft`
|
||||
|
||||
Features:
|
||||
- VPN Network Set: `10.8.0.0/24`
|
||||
- Admin Service Ports: `8080, 9090, 3001, 9000, 8001`
|
||||
- Public Service Ports: `80, 443, 22`
|
||||
- Rate Limiting für SSH: `10/minute`
|
||||
- Logging für blockierte Zugriffe
|
||||
|
||||
**Status**: Template erstellt
|
||||
**Anwendung**: `sudo nft -f /etc/nftables.d/wireguard.nft`
|
||||
|
||||
### ✅ Schritt 5: IP Forwarding aktivieren
|
||||
|
||||
```bash
|
||||
echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-wireguard.conf
|
||||
sudo sysctl -p /etc/sysctl.d/99-wireguard.conf
|
||||
```
|
||||
|
||||
**Status**: Bereit für Ausführung
|
||||
**Zweck**: Ermöglicht Paket-Weiterleitung zwischen VPN und Host-Netzwerk
|
||||
|
||||
### ✅ Schritt 6: WireGuard Service aktivieren
|
||||
|
||||
```bash
|
||||
sudo systemctl enable wg-quick@wg0
|
||||
sudo systemctl start wg-quick@wg0
|
||||
```
|
||||
|
||||
**Status**: Bereit für Ausführung
|
||||
**Zweck**: WireGuard als systemd Service starten und bei Boot aktivieren
|
||||
|
||||
## Verifikation
|
||||
|
||||
### WireGuard Status prüfen
|
||||
|
||||
```bash
|
||||
sudo wg show wg0
|
||||
# Erwartete Ausgabe:
|
||||
# interface: wg0
|
||||
# public key: [SERVER_PUBLIC_KEY]
|
||||
# private key: (hidden)
|
||||
# listening port: 51820
|
||||
```
|
||||
|
||||
### Service Status prüfen
|
||||
|
||||
```bash
|
||||
sudo systemctl status wg-quick@wg0
|
||||
# Erwartete Ausgabe:
|
||||
# ● wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
|
||||
# Loaded: loaded
|
||||
# Active: active (exited) since ...
|
||||
```
|
||||
|
||||
### nftables Rules prüfen
|
||||
|
||||
```bash
|
||||
sudo nft list table inet wireguard_firewall
|
||||
# Sollte alle Rules anzeigen
|
||||
```
|
||||
|
||||
### Netzwerk-Konnektivität prüfen
|
||||
|
||||
```bash
|
||||
# Interface prüfen
|
||||
ip addr show wg0
|
||||
# Sollte 10.8.0.1/24 zeigen
|
||||
|
||||
# Routing prüfen
|
||||
ip route | grep wg0
|
||||
# Sollte Route für 10.8.0.0/24 zeigen
|
||||
|
||||
# Firewall prüfen
|
||||
sudo nft list ruleset | grep wireguard
|
||||
```
|
||||
|
||||
## Nächste Schritte
|
||||
|
||||
### 1. Client-Konfiguration generieren
|
||||
|
||||
```bash
|
||||
cd /home/michael/dev/michaelschiemer/deployment/scripts
|
||||
sudo ./generate-client-config.sh michael-laptop
|
||||
```
|
||||
|
||||
### 2. Client-Config importieren
|
||||
|
||||
- **Linux/macOS**: Copy `.conf` file to `/etc/wireguard/`
|
||||
- **Windows**: Import via WireGuard GUI
|
||||
- **iOS/Android**: Scan QR code
|
||||
|
||||
### 3. Verbindung testen
|
||||
|
||||
```bash
|
||||
# Vom Client aus:
|
||||
ping 10.8.0.1
|
||||
|
||||
# Admin-Services testen:
|
||||
curl -k https://10.8.0.1:8080 # Traefik Dashboard
|
||||
curl http://10.8.0.1:9090 # Prometheus
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### WireGuard startet nicht
|
||||
|
||||
```bash
|
||||
# Logs prüfen
|
||||
sudo journalctl -u wg-quick@wg0 -f
|
||||
|
||||
# Konfiguration prüfen
|
||||
sudo wg-quick up wg0
|
||||
```
|
||||
|
||||
### Keine Verbindung möglich
|
||||
|
||||
```bash
|
||||
# Port prüfen
|
||||
sudo ss -ulnp | grep 51820
|
||||
|
||||
# Firewall prüfen
|
||||
sudo nft list ruleset | grep 51820
|
||||
|
||||
# IP Forwarding prüfen
|
||||
cat /proc/sys/net/ipv4/ip_forward
|
||||
# Sollte "1" sein
|
||||
```
|
||||
|
||||
### Client kann keine Admin-Services erreichen
|
||||
|
||||
```bash
|
||||
# nftables Rules prüfen
|
||||
sudo nft list table inet wireguard_firewall
|
||||
|
||||
# VPN-Routing prüfen
|
||||
ip route show table main | grep wg0
|
||||
|
||||
# NAT prüfen
|
||||
sudo nft list chain inet wireguard postrouting
|
||||
```
|
||||
|
||||
## Rollback-Prozedur
|
||||
|
||||
Falls etwas schiefgeht:
|
||||
|
||||
```bash
|
||||
# WireGuard stoppen
|
||||
sudo systemctl stop wg-quick@wg0
|
||||
sudo systemctl disable wg-quick@wg0
|
||||
|
||||
# nftables Rules entfernen
|
||||
sudo nft delete table inet wireguard_firewall
|
||||
sudo nft delete table inet wireguard
|
||||
|
||||
# Konfiguration entfernen
|
||||
sudo rm -rf /etc/wireguard/*
|
||||
sudo rm /etc/nftables.d/wireguard.nft
|
||||
|
||||
# IP Forwarding zurücksetzen
|
||||
sudo rm /etc/sysctl.d/99-wireguard.conf
|
||||
sudo sysctl -p
|
||||
```
|
||||
|
||||
## Sicherheitshinweise
|
||||
|
||||
- ✅ Private Keys niemals committen oder teilen
|
||||
- ✅ Regelmäßige Key-Rotation (empfohlen: jährlich)
|
||||
- ✅ Client-Configs nach Generierung sicher speichern
|
||||
- ✅ Firewall-Logs regelmäßig überprüfen
|
||||
- ✅ VPN-Zugriffe monitoren
|
||||
|
||||
## Performance-Metriken
|
||||
|
||||
Nach Installation zu überwachen:
|
||||
|
||||
- CPU-Auslastung: WireGuard ist sehr effizient (<5% bei normaler Last)
|
||||
- Netzwerk-Durchsatz: Nahezu Leitungsgeschwindigkeit
|
||||
- Latenz: Minimal (+1-2ms Overhead)
|
||||
- Speicher: ~10MB RAM für WireGuard-Prozess
|
||||
|
||||
## Status
|
||||
|
||||
**Installation Status**: ⏳ BEREIT FÜR AUSFÜHRUNG
|
||||
|
||||
**Nächster Schritt**: Script ausführen mit:
|
||||
```bash
|
||||
cd /home/michael/dev/michaelschiemer/deployment/scripts
|
||||
sudo ./manual-wireguard-setup.sh
|
||||
```
|
||||
|
||||
**Oder manuell durchführen**: Jeden Schritt einzeln wie oben dokumentiert ausführen.
|
||||
194
deployment/wireguard/QUICKSTART.md
Normal file
194
deployment/wireguard/QUICKSTART.md
Normal file
@@ -0,0 +1,194 @@
|
||||
# WireGuard VPN - Quick Start Guide
|
||||
|
||||
Minimalistisches Host-based WireGuard Setup in 5 Minuten.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Debian/Ubuntu Server mit Root-Zugriff
|
||||
- Public IP oder DynDNS
|
||||
- Ports 51820/udp offen in Firewall/Router
|
||||
|
||||
## Installation (Server)
|
||||
|
||||
### Option 1: Automated (Ansible) - Empfohlen
|
||||
|
||||
```bash
|
||||
# 1. Cleanup altes Docker-Setup (falls vorhanden)
|
||||
cd /home/michael/dev/michaelschiemer/deployment/scripts
|
||||
sudo ./cleanup-old-wireguard.sh
|
||||
|
||||
# 2. Deploy WireGuard Host-based
|
||||
cd /home/michael/dev/michaelschiemer/deployment/ansible
|
||||
ansible-playbook playbooks/setup-wireguard-host.yml
|
||||
|
||||
# 3. Verify Installation
|
||||
sudo wg show wg0
|
||||
sudo systemctl status wg-quick@wg0
|
||||
```
|
||||
|
||||
### Option 2: Manual Installation
|
||||
|
||||
```bash
|
||||
# Install WireGuard
|
||||
sudo apt update
|
||||
sudo apt install wireguard wireguard-tools qrencode nftables
|
||||
|
||||
# Generate Server Keys
|
||||
cd /etc/wireguard
|
||||
sudo wg genkey | sudo tee server_private.key | wg pubkey | sudo tee server_public.key
|
||||
|
||||
# Create Config (replace YOUR_SERVER_IP)
|
||||
sudo tee /etc/wireguard/wg0.conf <<EOF
|
||||
[Interface]
|
||||
PrivateKey = $(sudo cat server_private.key)
|
||||
Address = 10.8.0.1/24
|
||||
ListenPort = 51820
|
||||
PostUp = sysctl -w net.ipv4.ip_forward=1
|
||||
EOF
|
||||
|
||||
# Enable and Start
|
||||
sudo systemctl enable wg-quick@wg0
|
||||
sudo systemctl start wg-quick@wg0
|
||||
|
||||
# Apply Firewall
|
||||
# See: deployment/ansible/templates/wireguard-host-firewall.nft.j2
|
||||
```
|
||||
|
||||
## Client Setup
|
||||
|
||||
### Generate Client Config
|
||||
|
||||
```bash
|
||||
# On server
|
||||
cd /home/michael/dev/michaelschiemer/deployment/scripts
|
||||
sudo ./generate-client-config.sh michael-laptop
|
||||
|
||||
# Script outputs:
|
||||
# - Config file: ../wireguard/configs/michael-laptop.conf
|
||||
# - QR code (text): ../wireguard/configs/michael-laptop.qr.txt
|
||||
# - QR code (PNG): ../wireguard/configs/michael-laptop.qr.png
|
||||
```
|
||||
|
||||
### Import on Client
|
||||
|
||||
**Linux/macOS:**
|
||||
```bash
|
||||
# Copy config to client
|
||||
scp server:/path/to/michael-laptop.conf /etc/wireguard/
|
||||
|
||||
# Connect
|
||||
sudo wg-quick up michael-laptop
|
||||
|
||||
# Verify
|
||||
ping 10.8.0.1
|
||||
curl -k https://10.8.0.1:8080 # Traefik Dashboard
|
||||
```
|
||||
|
||||
**Windows:**
|
||||
1. Download WireGuard from https://www.wireguard.com/install/
|
||||
2. Open WireGuard GUI
|
||||
3. Click "Import tunnel(s) from file"
|
||||
4. Select `michael-laptop.conf`
|
||||
5. Click "Activate"
|
||||
|
||||
**iOS/Android:**
|
||||
1. Install WireGuard app from App Store/Play Store
|
||||
2. Tap "+" → "Create from QR code"
|
||||
3. Scan QR code (shown in terminal or PNG file)
|
||||
4. Tap "Activate"
|
||||
|
||||
## Service Access
|
||||
|
||||
Nach VPN-Verbindung sind folgende Services erreichbar:
|
||||
|
||||
| Service | URL | Purpose |
|
||||
|---------|-----|---------|
|
||||
| Traefik Dashboard | https://10.8.0.1:8080 | Reverse Proxy Management |
|
||||
| Prometheus | http://10.8.0.1:9090 | Metrics Collection |
|
||||
| Grafana | https://10.8.0.1:3001 | Monitoring Dashboards |
|
||||
| Portainer | http://10.8.0.1:9000 | Docker Management |
|
||||
| Redis Insight | http://10.8.0.1:8001 | Redis Debugging |
|
||||
|
||||
## Verification
|
||||
|
||||
```bash
|
||||
# On Client after connecting VPN
|
||||
|
||||
# Test VPN connectivity
|
||||
ping 10.8.0.1
|
||||
|
||||
# Test service access
|
||||
curl -k https://10.8.0.1:8080 # Traefik Dashboard (should return HTML)
|
||||
curl http://10.8.0.1:9090 # Prometheus (should return HTML)
|
||||
|
||||
# Check routing
|
||||
ip route | grep 10.8.0.0
|
||||
|
||||
# Verify WireGuard interface
|
||||
sudo wg show
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Cannot connect to VPN
|
||||
|
||||
```bash
|
||||
# On Server
|
||||
sudo wg show wg0 # Check if interface exists
|
||||
sudo systemctl status wg-quick@wg0 # Check if service running
|
||||
sudo ss -ulnp | grep 51820 # Check if listening on port
|
||||
|
||||
# Check firewall allows WireGuard port
|
||||
sudo nft list ruleset | grep 51820
|
||||
|
||||
# View logs
|
||||
sudo journalctl -u wg-quick@wg0 -f
|
||||
```
|
||||
|
||||
### VPN connected but cannot access services
|
||||
|
||||
```bash
|
||||
# On Client
|
||||
ping 10.8.0.1 # Should work
|
||||
|
||||
# On Server
|
||||
sudo nft list ruleset | grep "10.8.0.0" # Check VPN network allowed
|
||||
|
||||
# Check service is listening
|
||||
sudo ss -tlnp | grep 8080 # Traefik Dashboard
|
||||
sudo docker ps # Check containers running
|
||||
```
|
||||
|
||||
### Slow connection
|
||||
|
||||
```bash
|
||||
# Check MTU settings (on client)
|
||||
sudo wg show michael-laptop
|
||||
|
||||
# Try reducing MTU if packet loss
|
||||
# Edit config: MTU = 1420 (in [Interface] section)
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
- ✅ All admin services **only** accessible via VPN
|
||||
- ✅ Public ports limited to 80, 443, 22
|
||||
- ✅ Modern crypto (ChaCha20, Poly1305)
|
||||
- ✅ Preshared keys for quantum resistance
|
||||
- ✅ nftables firewall with explicit rules
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [ ] Add more clients: `sudo ./generate-client-config.sh <device-name>`
|
||||
- [ ] Setup monitoring alerts for VPN
|
||||
- [ ] Optional: Add minimal CoreDNS for `.internal` domains
|
||||
- [ ] Schedule key rotation (recommended: annually)
|
||||
|
||||
## Support
|
||||
|
||||
Full documentation: `deployment/wireguard/README.md`
|
||||
|
||||
For issues, check:
|
||||
- `sudo journalctl -u wg-quick@wg0`
|
||||
- `sudo dmesg | grep wireguard`
|
||||
- `sudo nft list ruleset`
|
||||
352
deployment/wireguard/README.md
Normal file
352
deployment/wireguard/README.md
Normal file
@@ -0,0 +1,352 @@
|
||||
# Minimalistic WireGuard VPN Setup
|
||||
|
||||
**Purpose**: Secure admin access to internal services (Traefik Dashboard, Prometheus, Grafana, etc.)
|
||||
|
||||
**Architecture**: Host-based WireGuard with IP-based service access (no DNS required)
|
||||
|
||||
## Overview
|
||||
|
||||
```
|
||||
Public Internet
|
||||
↓
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Server (Public IP) │
|
||||
│ │
|
||||
│ Public Ports: │
|
||||
│ 80/443 → Traefik (Public Apps) │
|
||||
│ 22 → SSH │
|
||||
│ 51820 → WireGuard │
|
||||
│ │
|
||||
│ VPN Network (10.8.0.0/24): │
|
||||
│ 10.8.0.1 → Server (VPN Gateway) │
|
||||
│ │
|
||||
│ Admin Services (VPN-only): │
|
||||
│ https://10.8.0.1:8080 → Traefik │
|
||||
│ http://10.8.0.1:9090 → Prometheus │
|
||||
│ https://10.8.0.1:3001 → Grafana │
|
||||
│ http://10.8.0.1:9000 → Portainer │
|
||||
│ http://10.8.0.1:8001 → Redis Insight│
|
||||
│ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Components
|
||||
|
||||
### 1. WireGuard (Host-based)
|
||||
- **Interface**: wg0
|
||||
- **Server IP**: 10.8.0.1/24
|
||||
- **Port**: 51820/udp
|
||||
- **Management**: systemd + wg-quick
|
||||
|
||||
### 2. nftables Firewall
|
||||
- **VPN Access**: 10.8.0.0/24 → All admin services
|
||||
- **Public Access**: Only ports 80, 443, 22
|
||||
- **Default Policy**: DROP all other traffic
|
||||
|
||||
### 3. Service Access (IP-based)
|
||||
|
||||
| Service | URL | Purpose |
|
||||
|---------|-----|---------|
|
||||
| Traefik Dashboard | https://10.8.0.1:8080 | Reverse Proxy Management |
|
||||
| Prometheus | http://10.8.0.1:9090 | Metrics Collection |
|
||||
| Grafana | https://10.8.0.1:3001 | Monitoring Dashboards |
|
||||
| Portainer | http://10.8.0.1:9000 | Docker Management |
|
||||
| Redis Insight | http://10.8.0.1:8001 | Redis Debugging |
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Server Setup (Automated)
|
||||
|
||||
```bash
|
||||
# Deploy WireGuard + Firewall
|
||||
cd deployment/ansible
|
||||
ansible-playbook playbooks/setup-wireguard-host.yml
|
||||
```
|
||||
|
||||
### Client Setup
|
||||
|
||||
```bash
|
||||
# Generate new client config
|
||||
cd deployment/scripts
|
||||
./generate-client-config.sh michael-laptop
|
||||
|
||||
# Import config (Linux/macOS)
|
||||
sudo wg-quick up ./configs/michael-laptop.conf
|
||||
|
||||
# Import config (Windows)
|
||||
# 1. Open WireGuard GUI
|
||||
# 2. Import Tunnel from File
|
||||
# 3. Select ./configs/michael-laptop.conf
|
||||
|
||||
# Import config (iOS/Android)
|
||||
# Scan QR code generated by script
|
||||
```
|
||||
|
||||
### Verify Connection
|
||||
|
||||
```bash
|
||||
# Check VPN connection
|
||||
ping 10.8.0.1
|
||||
|
||||
# Access Traefik Dashboard
|
||||
curl -k https://10.8.0.1:8080
|
||||
```
|
||||
|
||||
## Manual Server Setup
|
||||
|
||||
If you prefer manual installation:
|
||||
|
||||
### 1. Install WireGuard
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt update
|
||||
sudo apt install wireguard wireguard-tools qrencode
|
||||
|
||||
# Check kernel module
|
||||
sudo modprobe wireguard
|
||||
lsmod | grep wireguard
|
||||
```
|
||||
|
||||
### 2. Generate Server Keys
|
||||
|
||||
```bash
|
||||
# Create config directory
|
||||
sudo mkdir -p /etc/wireguard
|
||||
cd /etc/wireguard
|
||||
|
||||
# Generate keys
|
||||
umask 077
|
||||
wg genkey | tee server_private.key | wg pubkey > server_public.key
|
||||
|
||||
# Save keys
|
||||
SERVER_PRIVATE_KEY=$(cat server_private.key)
|
||||
SERVER_PUBLIC_KEY=$(cat server_public.key)
|
||||
```
|
||||
|
||||
### 3. Create Server Config
|
||||
|
||||
```bash
|
||||
sudo tee /etc/wireguard/wg0.conf <<EOF
|
||||
[Interface]
|
||||
PrivateKey = $SERVER_PRIVATE_KEY
|
||||
Address = 10.8.0.1/24
|
||||
ListenPort = 51820
|
||||
|
||||
# Firewall: Allow VPN traffic forwarding
|
||||
PostUp = nft add table inet wireguard
|
||||
PostUp = nft add chain inet wireguard postrouting { type nat hook postrouting priority srcnat\; }
|
||||
PostUp = nft add chain inet wireguard forward { type filter hook forward priority filter\; }
|
||||
PostUp = nft add rule inet wireguard postrouting oifname "eth0" ip saddr 10.8.0.0/24 masquerade
|
||||
PostUp = nft add rule inet wireguard forward iifname "wg0" accept
|
||||
PostUp = nft add rule inet wireguard forward oifname "wg0" ct state established,related accept
|
||||
|
||||
PostDown = nft delete table inet wireguard
|
||||
|
||||
# Peers will be added here
|
||||
EOF
|
||||
|
||||
# Secure permissions
|
||||
sudo chmod 600 /etc/wireguard/wg0.conf
|
||||
```
|
||||
|
||||
### 4. Enable WireGuard
|
||||
|
||||
```bash
|
||||
# Enable IP forwarding
|
||||
echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
|
||||
sudo sysctl -p
|
||||
|
||||
# Start WireGuard
|
||||
sudo systemctl enable wg-quick@wg0
|
||||
sudo systemctl start wg-quick@wg0
|
||||
|
||||
# Check status
|
||||
sudo wg show
|
||||
sudo systemctl status wg-quick@wg0
|
||||
```
|
||||
|
||||
### 5. Apply Firewall Rules
|
||||
|
||||
See `deployment/ansible/templates/wireguard-firewall.nft.j2` for complete firewall configuration.
|
||||
|
||||
```bash
|
||||
# Allow WireGuard port
|
||||
sudo nft add rule inet filter input udp dport 51820 accept
|
||||
|
||||
# Allow VPN network to access admin services
|
||||
sudo nft add rule inet filter input ip saddr 10.8.0.0/24 tcp dport { 8080, 9090, 3001, 9000, 8001 } accept
|
||||
|
||||
# Block public access to admin services
|
||||
sudo nft add rule inet filter input tcp dport { 8080, 9090, 3001, 9000, 8001 } drop
|
||||
```
|
||||
|
||||
## Client Configuration
|
||||
|
||||
### Generate Client
|
||||
|
||||
```bash
|
||||
# Generate client keys
|
||||
umask 077
|
||||
wg genkey | tee client_private.key | wg pubkey > client_public.key
|
||||
wg genpsk > client_preshared.key
|
||||
|
||||
CLIENT_PRIVATE_KEY=$(cat client_private.key)
|
||||
CLIENT_PUBLIC_KEY=$(cat client_public.key)
|
||||
CLIENT_PSK=$(cat client_preshared.key)
|
||||
```
|
||||
|
||||
### Add Client to Server
|
||||
|
||||
```bash
|
||||
# Add peer to server config
|
||||
sudo tee -a /etc/wireguard/wg0.conf <<EOF
|
||||
|
||||
[Peer]
|
||||
# michael-laptop
|
||||
PublicKey = $CLIENT_PUBLIC_KEY
|
||||
PresharedKey = $CLIENT_PSK
|
||||
AllowedIPs = 10.8.0.2/32
|
||||
EOF
|
||||
|
||||
# Reload WireGuard
|
||||
sudo systemctl reload wg-quick@wg0
|
||||
```
|
||||
|
||||
### Create Client Config File
|
||||
|
||||
```bash
|
||||
# Create client config
|
||||
cat > michael-laptop.conf <<EOF
|
||||
[Interface]
|
||||
PrivateKey = $CLIENT_PRIVATE_KEY
|
||||
Address = 10.8.0.2/32
|
||||
DNS = 1.1.1.1, 9.9.9.9
|
||||
|
||||
[Peer]
|
||||
PublicKey = $SERVER_PUBLIC_KEY
|
||||
PresharedKey = $CLIENT_PSK
|
||||
Endpoint = YOUR_SERVER_IP:51820
|
||||
AllowedIPs = 10.8.0.0/24
|
||||
PersistentKeepalive = 25
|
||||
EOF
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### VPN Not Connecting
|
||||
|
||||
```bash
|
||||
# Check WireGuard status
|
||||
sudo wg show
|
||||
|
||||
# Check firewall
|
||||
sudo nft list ruleset | grep 51820
|
||||
|
||||
# Check logs
|
||||
sudo journalctl -u wg-quick@wg0 -f
|
||||
|
||||
# Test connectivity
|
||||
ping 10.8.0.1 # From client
|
||||
```
|
||||
|
||||
### Cannot Access Services
|
||||
|
||||
```bash
|
||||
# Verify firewall allows VPN network
|
||||
sudo nft list ruleset | grep "10.8.0.0"
|
||||
|
||||
# Check service is listening
|
||||
sudo ss -tlnp | grep 8080 # Traefik Dashboard
|
||||
|
||||
# Test from VPN
|
||||
curl -k https://10.8.0.1:8080 # From client
|
||||
```
|
||||
|
||||
### Key Rotation
|
||||
|
||||
Recommended: Rotate keys annually
|
||||
|
||||
```bash
|
||||
# Generate new server keys
|
||||
cd /etc/wireguard
|
||||
wg genkey | tee server_private_new.key | wg pubkey > server_public_new.key
|
||||
|
||||
# Update server config
|
||||
# ... update PrivateKey in wg0.conf
|
||||
|
||||
# Regenerate all client configs with new server PublicKey
|
||||
# ... update clients
|
||||
|
||||
# Restart WireGuard
|
||||
sudo systemctl restart wg-quick@wg0
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
### 1. Strong Cryptography
|
||||
- ✅ WireGuard uses modern crypto (ChaCha20, Poly1305, Curve25519)
|
||||
- ✅ Preshared keys for quantum resistance
|
||||
- ✅ Perfect forward secrecy
|
||||
|
||||
### 2. Firewall Isolation
|
||||
- ✅ Admin services only accessible via VPN
|
||||
- ✅ Explicit ALLOW rules, default DROP
|
||||
- ✅ Rate limiting on VPN port (optional)
|
||||
|
||||
### 3. Key Management
|
||||
- ✅ Private keys never leave server/client
|
||||
- ✅ Preshared keys for each peer
|
||||
- ✅ Annual key rotation recommended
|
||||
|
||||
### 4. Monitoring
|
||||
- ✅ Log all VPN connections
|
||||
- ✅ Alert on unusual traffic patterns
|
||||
- ✅ Regular security audits
|
||||
|
||||
## Performance
|
||||
|
||||
- **Latency Overhead**: <1ms (kernel-native)
|
||||
- **Throughput**: Near-native (minimal encryption overhead)
|
||||
- **Concurrent Peers**: 10-20 recommended
|
||||
- **Keepalive**: 25 seconds (NAT traversal)
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Add New Client
|
||||
|
||||
```bash
|
||||
./deployment/scripts/generate-client-config.sh new-device-name
|
||||
```
|
||||
|
||||
### Remove Client
|
||||
|
||||
```bash
|
||||
# Edit server config
|
||||
sudo nano /etc/wireguard/wg0.conf
|
||||
# Remove [Peer] section
|
||||
|
||||
# Reload
|
||||
sudo systemctl reload wg-quick@wg0
|
||||
```
|
||||
|
||||
### Backup Configuration
|
||||
|
||||
```bash
|
||||
# Backup keys and configs
|
||||
sudo tar -czf wireguard-backup-$(date +%Y%m%d).tar.gz /etc/wireguard/
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [ ] Deploy WireGuard on server
|
||||
- [ ] Generate client configs for all devices
|
||||
- [ ] Test VPN connectivity
|
||||
- [ ] Verify admin service access
|
||||
- [ ] Optional: Add minimal CoreDNS for `.internal` domains (Phase 2)
|
||||
|
||||
## Support
|
||||
|
||||
- **WireGuard Docs**: https://www.wireguard.com/quickstart/
|
||||
- **nftables Wiki**: https://wiki.nftables.org/
|
||||
- **Framework Issues**: https://github.com/your-repo/issues
|
||||
11
deployment/wireguard/configs/.gitignore
vendored
Normal file
11
deployment/wireguard/configs/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
# WireGuard Client Configurations
|
||||
# These contain private keys and should NEVER be committed!
|
||||
|
||||
*.conf
|
||||
*.key
|
||||
*.qr.txt
|
||||
*.qr.png
|
||||
|
||||
# Allow README
|
||||
!README.md
|
||||
!.gitignore
|
||||
47
deployment/wireguard/configs/README.md
Normal file
47
deployment/wireguard/configs/README.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# WireGuard Client Configurations
|
||||
|
||||
This directory stores generated client configuration files.
|
||||
|
||||
## Security Notice
|
||||
|
||||
⚠️ **NEVER commit client configs to Git!**
|
||||
|
||||
Client configs contain:
|
||||
- Private keys
|
||||
- Preshared keys
|
||||
- Network topology information
|
||||
|
||||
`.gitignore` is configured to exclude all `.conf`, `.key`, `.qr.txt`, and `.qr.png` files.
|
||||
|
||||
## Generate New Client
|
||||
|
||||
```bash
|
||||
cd ../../scripts
|
||||
sudo ./generate-client-config.sh <device-name>
|
||||
```
|
||||
|
||||
Configs will be created here:
|
||||
- `<device-name>.conf` - WireGuard configuration
|
||||
- `<device-name>.qr.txt` - QR code (ASCII)
|
||||
- `<device-name>.qr.png` - QR code (PNG)
|
||||
|
||||
## Backup Client Configs
|
||||
|
||||
```bash
|
||||
# Securely backup configs (encrypted)
|
||||
tar -czf - *.conf | gpg --symmetric --cipher-algo AES256 -o wireguard-clients-backup-$(date +%Y%m%d).tar.gz.gpg
|
||||
```
|
||||
|
||||
## Revoke Client Access
|
||||
|
||||
```bash
|
||||
# On server
|
||||
sudo nano /etc/wireguard/wg0.conf
|
||||
# Remove [Peer] section for client
|
||||
|
||||
# Reload WireGuard
|
||||
sudo systemctl reload wg-quick@wg0
|
||||
|
||||
# Delete client config
|
||||
rm <device-name>.*
|
||||
```
|
||||
Reference in New Issue
Block a user