chore: update VPN routing configuration and add Grafana VPN documentation

This commit is contained in:
2025-11-02 18:10:04 +01:00
parent 2dd8468d70
commit 7b7f0b41d2
41 changed files with 3727 additions and 11 deletions

2
deployment/ansible/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
# Ansible temporary directory
.ansible/

View File

@@ -81,3 +81,7 @@ wireguard_port_default: 51820
wireguard_network_default: "10.8.0.0/24"
wireguard_server_ip_default: "10.8.0.1"
wireguard_enable_ip_forwarding: true
wireguard_config_file: "{{ wireguard_config_path }}/{{ wireguard_interface }}.conf"
wireguard_private_key_file: "{{ wireguard_config_path }}/{{ wireguard_interface }}_private.key"
wireguard_public_key_file: "{{ wireguard_config_path }}/{{ wireguard_interface }}_public.key"
wireguard_client_configs_path: "{{ wireguard_config_path }}/clients"

View File

@@ -0,0 +1,78 @@
---
- name: Check Traefik Logs After Grafana Access
hosts: production
gather_facts: no
become: no
tasks:
- name: Instructions
debug:
msg:
- "=== ANWEISUNG ==="
- "Bitte mache JETZT einen Zugriff auf https://grafana.michaelschiemer.de im Browser"
- "Dann pr?fe ich die Logs und sage dir, ob Traffic ?ber VPN kommt"
- ""
- name: Wait for access
pause:
seconds: 15
- name: Get last 20 Grafana requests
shell: |
cd ~/deployment/stacks/traefik
tail -500 logs/access.log | grep -i grafana | tail -20
args:
executable: /bin/bash
register: recent_grafana_logs
ignore_errors: yes
failed_when: false
- name: Extract and display client IPs with timestamps
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -10 | while IFS= read -r line; do
time=$(echo "$line" | grep -oP '"time":"[^"]*"' | sed 's/"time":"//;s/"//' | cut -d'T' -f2 | cut -d'+' -f1)
client=$(echo "$line" | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//')
status=$(echo "$line" | grep -oP '"DownstreamStatus":[0-9]+' | sed 's/"DownstreamStatus"://')
if [[ "$client" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "$time | ClientHost: $client | Status: $status ? VPN-IP (Traffic kommt ?ber VPN!)"
elif [[ "$client" == "89.246.96.244" ]]; then
echo "$time | ClientHost: $client | Status: $status ? ?ffentliche IP (Traffic kommt NICHT ?ber VPN)"
else
echo "$time | ClientHost: $client | Status: $status ? Unbekannte IP"
fi
done
args:
executable: /bin/bash
register: analysis_result
ignore_errors: yes
failed_when: false
- name: Display analysis
debug:
msg: "{{ analysis_result.stdout_lines }}"
- name: Get unique client IPs from last 10 requests
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: unique_ips
ignore_errors: yes
failed_when: false
- name: Display unique IPs
debug:
msg: "{{ unique_ips.stdout_lines }}"
- name: Final verdict
debug:
msg:
- ""
- "=== ERGEBNIS ==="
- "Pr?fe die obigen Zeilen:"
- "- ? Wenn ClientHost: 10.8.0.7 ? Traffic kommt ?ber VPN!"
- "- ? Wenn ClientHost: 89.246.96.244 ? Traffic kommt NICHT ?ber VPN"
- ""
- "N?chster Schritt: Wenn VPN funktioniert, entfernen wir die tempor?re IP-Erlaubnis!"

View File

@@ -0,0 +1,68 @@
---
- name: Check Grafana Logs After Test
hosts: production
gather_facts: no
become: no
tasks:
- name: Check last 20 Grafana access attempts
shell: |
cd ~/deployment/stacks/traefik
tail -200 logs/access.log | grep -i grafana | tail -20
args:
executable: /bin/bash
register: latest_logs
ignore_errors: yes
failed_when: false
- name: Extract client IPs with timestamps
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -10 | while IFS= read -r line; do
time=$(echo "$line" | grep -oP '"time":"[^"]*"' | sed 's/"time":"//;s/"//' | cut -d'T' -f2 | cut -d'+' -f1)
client=$(echo "$line" | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//')
status=$(echo "$line" | grep -oP '"DownstreamStatus":[0-9]+' | sed 's/"DownstreamStatus"://')
if [[ "$client" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "$time | ClientHost: $client | Status: $status ? VPN-IP (Traffic kommt ?ber VPN!)"
elif [[ "$client" == "89.246.96.244" ]]; then
echo "$time | ClientHost: $client | Status: $status ? ?ffentliche IP (Traffic kommt NICHT ?ber VPN)"
else
echo "$time | ClientHost: $client | Status: $status ? Unbekannt"
fi
done
args:
executable: /bin/bash
register: analysis
ignore_errors: yes
failed_when: false
- name: Display analysis
debug:
msg: "{{ analysis.stdout_lines }}"
- name: Get unique client IPs
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: unique_ips
ignore_errors: yes
failed_when: false
- name: Display unique IPs
debug:
msg: "{{ unique_ips.stdout_lines }}"
- name: Final result
debug:
msg:
- ""
- "=== ERGEBNIS ==="
- "Pr?fe die obigen Zeilen:"
- ""
- "? Wenn ClientHost: 10.8.0.7 ? Traffic kommt ?ber VPN!"
- " ? Dann k?nnen wir die tempor?re IP-Erlaubnis entfernen!"
- ""
- "? Wenn ClientHost: 89.246.96.244 ? Traffic kommt NICHT ?ber VPN"
- " ? Dann m?ssen wir weiter debuggen"

View File

@@ -0,0 +1,55 @@
---
- name: Check Latest Grafana Access - Client IP Analysis
hosts: production
gather_facts: no
become: no
tasks:
- name: Get latest Grafana access logs
shell: |
cd ~/deployment/stacks/traefik
echo "=== Latest 5 Grafana Access Logs ==="
tail -100 logs/access.log | grep -i grafana | tail -5
args:
executable: /bin/bash
register: latest_logs
ignore_errors: yes
failed_when: false
- name: Extract client IPs from latest logs
shell: |
cd ~/deployment/stacks/traefik
tail -50 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: client_ips
ignore_errors: yes
failed_when: false
- name: Display latest logs
debug:
msg: "{{ latest_logs.stdout_lines }}"
- name: Display client IPs
debug:
msg: "{{ client_ips.stdout_lines }}"
- name: Analyze if traffic comes from VPN
shell: |
cd ~/deployment/stacks/traefik
if tail -20 logs/access.log | grep -i grafana | tail -5 | grep -oP '"ClientHost":"[^"]*"' | grep -q "10.8.0"; then
echo "? Traffic kommt ?ber VPN! (ClientHost: 10.8.0.x)"
elif tail -20 logs/access.log | grep -i grafana | tail -5 | grep -oP '"ClientHost":"[^"]*"' | grep -q "89.246.96.244"; then
echo "? Traffic kommt NICHT ?ber VPN (ClientHost: 89.246.96.244 - ?ffentliche IP)"
else
echo "?? Keine aktuellen Grafana-Logs gefunden. Bitte mache einen Zugriff auf https://grafana.michaelschiemer.de"
fi
args:
executable: /bin/bash
register: analysis
ignore_errors: yes
failed_when: false
- name: Display analysis
debug:
msg: "{{ analysis.stdout_lines }}"

View File

@@ -0,0 +1,63 @@
---
- name: Check VPN Routing Status - Client-Side Diagnostics
hosts: production
gather_facts: no
become: no
tasks:
- name: Instructions for client-side DNS check
debug:
msg:
- "=== CLIENT-SIDE DNS CHECK ==="
- "Bitte f?hre diese Befehle auf deinem Client-System aus (nicht auf dem Server):"
- ""
- "1. Pr?fe aktive DNS-Server:"
- " Linux/Mac: cat /etc/resolv.conf"
- " Windows: Get-DnsClientServerAddress | Select-Object InterfaceAlias, ServerAddresses"
- ""
- "2. Teste DNS-Aufl?sung:"
- " dig +short grafana.michaelschiemer.de"
- " Oder: nslookup grafana.michaelschiemer.de"
- ""
- "3. Teste DNS-Aufl?sung ?ber VPN-DNS:"
- " dig +short grafana.michaelschiemer.de @10.8.0.1"
- " Sollte zur?ckgeben: 10.8.0.1"
- ""
- "4. Pr?fe WireGuard Config:"
- " ?ffne deine WireGuard-Config und pr?fe:"
- " [Interface]"
- " DNS = 10.8.0.1"
- ""
- "Teile mir die Ergebnisse mit, dann kann ich dir helfen, das zu fixen!"
- name: Check server-side WireGuard configuration
shell: |
echo "=== Server-Side WireGuard Config ==="
sudo cat /etc/wireguard/wg0.conf | grep -A 5 "\[Interface\]" | head -10
args:
executable: /bin/bash
register: wg_server_config
ignore_errors: yes
failed_when: false
- name: Display server-side WireGuard config
debug:
msg: "{{ wg_server_config.stdout_lines }}"
- name: Check server-side DNS resolution
shell: |
echo "=== Server-Side DNS Tests ==="
echo "1. Grafana via VPN DNS (10.8.0.1):"
dig +short grafana.michaelschiemer.de @10.8.0.1 2>&1 || echo "Failed"
echo ""
echo "2. Grafana via public DNS (8.8.8.8):"
dig +short grafana.michaelschiemer.de @8.8.8.8 2>&1 || echo "Failed"
args:
executable: /bin/bash
register: server_dns
ignore_errors: yes
failed_when: false
- name: Display server-side DNS tests
debug:
msg: "{{ server_dns.stdout_lines }}"

View File

@@ -0,0 +1,116 @@
---
- name: Check VPN Test Results from Client
hosts: production
gather_facts: no
become: no
tasks:
- name: Check latest Grafana access attempts
shell: |
cd ~/deployment/stacks/traefik
echo "=== Last 20 Grafana Access Attempts ==="
tail -500 logs/access.log | grep -i grafana | tail -20 | while IFS= read -r line; do
time=$(echo "$line" | grep -oP '"time":"[^"]*"' | sed 's/"time":"//;s/"//' | cut -d'T' -f2 | cut -d'+' -f1 | cut -d':' -f1-2)
client=$(echo "$line" | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//')
status=$(echo "$line" | grep -oP '"DownstreamStatus":[0-9]+' | sed 's/"DownstreamStatus"://')
method=$(echo "$line" | grep -oP '"RequestMethod":"[^"]*"' | sed 's/"RequestMethod":"//;s/"//')
path=$(echo "$line" | grep -oP '"RequestPath":"[^"]*"' | sed 's/"RequestPath":"//;s/"//')
if [[ "$client" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "? $time | ClientHost: $client | Status: $status | $method $path ? VPN-IP (Traffic kommt ?ber VPN!)"
elif [[ "$client" == "89.246.96.244" ]]; then
echo "? $time | ClientHost: $client | Status: $status | $method $path ? ?ffentliche IP (Traffic kommt NICHT ?ber VPN)"
else
echo "? $time | ClientHost: $client | Status: $status | $method $path ? Unbekannt"
fi
done
args:
executable: /bin/bash
register: recent_access
ignore_errors: yes
failed_when: false
- name: Display recent access attempts
debug:
msg: "{{ recent_access.stdout_lines }}"
- name: Extract unique client IPs from recent requests
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -20 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: unique_ips
ignore_errors: yes
failed_when: false
- name: Display unique client IPs
debug:
msg: "{{ unique_ips.stdout_lines }}"
- name: Analyze client IP distribution
shell: |
cd ~/deployment/stacks/traefik
echo "=== Client IP Analysis (Last 20 requests) ==="
VPN_COUNT=$(tail -100 logs/access.log | grep -i grafana | tail -20 | grep -oP '"ClientHost":"10\.8\.0\.[0-9]+"' | wc -l)
PUBLIC_COUNT=$(tail -100 logs/access.log | grep -i grafana | tail -20 | grep -oP '"ClientHost":"89\.246\.96\.244"' | wc -l)
TOTAL=$(tail -100 logs/access.log | grep -i grafana | tail -20 | wc -l)
echo "Total Grafana requests (last 20): $TOTAL"
echo "VPN IP requests (10.8.0.x): $VPN_COUNT"
echo "Public IP requests (89.246.96.244): $PUBLIC_COUNT"
if [ "$VPN_COUNT" -gt 0 ]; then
echo ""
echo "? SUCCESS: Traffic is coming through VPN!"
echo " $VPN_COUNT out of $TOTAL requests used VPN IP"
elif [ "$PUBLIC_COUNT" -gt 0 ]; then
echo ""
echo "? PROBLEM: Traffic is NOT coming through VPN"
echo " $PUBLIC_COUNT out of $TOTAL requests used public IP"
echo " Check VPN routing configuration on client"
else
echo ""
echo "?? No recent Grafana requests found"
fi
args:
executable: /bin/bash
register: ip_analysis
ignore_errors: yes
failed_when: false
- name: Display IP analysis
debug:
msg: "{{ ip_analysis.stdout_lines }}"
- name: Check WireGuard peer status for test-client
shell: |
echo "=== WireGuard Peer Status ==="
sudo wg show | grep -A 5 "YbjBipkOHjLfcIYQKDReJ1swseczqHolTCRv7+LHnmw=" || echo "Peer not found or not connected"
args:
executable: /bin/bash
register: wg_peer_status
ignore_errors: yes
failed_when: false
- name: Display WireGuard peer status
debug:
msg: "{{ wg_peer_status.stdout_lines }}"
- name: Final recommendations
debug:
msg:
- ""
- "=== ERGEBNIS ==="
- ""
- "Pr?fe die obigen Zeilen:"
- ""
- "? Wenn ClientHost: 10.8.0.x ? Traffic kommt ?ber VPN!"
- " ? Dann k?nnen wir die tempor?re IP-Erlaubnis entfernen!"
- ""
- "? Wenn ClientHost: 89.246.96.244 ? Traffic kommt NICHT ?ber VPN"
- " ? Dann m?ssen wir das VPN-Routing auf dem Client pr?fen"
- ""
- "N?chste Schritte:"
- "1. Wenn VPN funktioniert: Temporary IP-Erlaubnis entfernen"
- "2. Wenn VPN nicht funktioniert: Route-Tabellen auf Client pr?fen"

View File

@@ -0,0 +1,80 @@
---
- name: Fix Grafana VPN Routing and Remove Temporary IP Allow
hosts: production
gather_facts: no
become: no
tasks:
- name: Check recent Grafana access attempts
shell: |
cd ~/deployment/stacks/traefik
echo "=== Recent Grafana Access (Last 10 attempts) ==="
tail -50 logs/access.log | grep grafana | tail -10 | while read line; do
echo "$line" | grep -oP '"ClientHost":"[^"]*"' || echo "Could not parse"
done
args:
executable: /bin/bash
register: recent_access
ignore_errors: yes
failed_when: false
- name: Display recent access attempts
debug:
msg: "{{ recent_access.stdout_lines }}"
- name: Check if traffic comes from VPN
shell: |
cd ~/deployment/stacks/traefik
echo "=== Checking if recent traffic comes from VPN (10.8.0.0/24) ==="
tail -20 logs/access.log | grep grafana | tail -5 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | while read ip; do
if [[ "$ip" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "? $ip -> VPN traffic (10.8.0.0/24)"
else
echo "? $ip -> Public IP (not VPN)"
fi
done
args:
executable: /bin/bash
register: vpn_check
ignore_errors: yes
failed_when: false
- name: Display VPN check results
debug:
msg: "{{ vpn_check.stdout_lines }}"
- name: Backup current middlewares.yml
shell: |
cd ~/deployment/stacks/traefik/dynamic
cp middlewares.yml middlewares.yml.backup.$(date +%Y%m%d_%H%M%S)
args:
executable: /bin/bash
when: false # Skip for now - we'll do this manually
- name: Check current middleware configuration
shell: |
cd ~/deployment/stacks/traefik/dynamic
echo "=== Current grafana-vpn-only Middleware ==="
grep -A 8 "grafana-vpn-only:" middlewares.yml
args:
executable: /bin/bash
register: middleware_config
ignore_errors: yes
failed_when: false
- name: Display middleware configuration
debug:
msg: "{{ middleware_config.stdout_lines }}"
- name: Instructions for removing temporary IP
debug:
msg:
- "=== TO REMOVE TEMPORARY IP ALLOWLIST ==="
- "1. Make sure VPN routing works (DNS = 10.8.0.1 or use hosts file)"
- "2. Test that traffic comes from VPN (ClientHost: 10.8.0.7)"
- "3. Remove temporary IP from middlewares.yml:"
- " cd ~/deployment/stacks/traefik/dynamic"
- " sed -i '/89.246.96.244\/32/d' middlewares.yml"
- "4. Restart Traefik:"
- " cd ~/deployment/stacks/traefik && docker compose restart traefik"
- "5. Test: With VPN = OK, Without VPN = 403"

View File

@@ -0,0 +1,95 @@
---
- name: Live Monitor Grafana Access - Watch Traefik Logs in Real-Time
hosts: production
gather_facts: no
become: no
tasks:
- name: Clear previous Grafana access attempts count
shell: |
echo "Starting live monitoring. Make a request to https://grafana.michaelschiemer.de now!"
echo "Waiting 10 seconds for you to make a request..."
sleep 10
args:
executable: /bin/bash
- name: Show recent Grafana access attempts
shell: |
cd ~/deployment/stacks/traefik
echo "=== Last 5 Grafana Access Attempts ==="
tail -100 logs/access.log | grep -i grafana | tail -5
args:
executable: /bin/bash
register: recent_access
ignore_errors: yes
failed_when: false
- name: Display recent access attempts
debug:
msg: "{{ recent_access.stdout_lines }}"
- name: Check current client IP pattern
shell: |
cd ~/deployment/stacks/traefik
echo "=== Client IPs in recent Grafana requests ==="
tail -50 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | head -5
args:
executable: /bin/bash
register: client_ips
ignore_errors: yes
failed_when: false
- name: Display client IPs
debug:
msg: "{{ client_ips.stdout_lines }}"
- name: Extract and check client IPs
shell: |
cd ~/deployment/stacks/traefik
echo "=== Checking if client IPs are in VPN range (10.8.0.0/24) ==="
tail -20 logs/access.log | grep -i grafana | tail -3 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | while read ip; do
if [[ "$ip" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "$ip -> In VPN range (10.8.0.0/24): YES"
else
echo "$ip -> In VPN range (10.8.0.0/24): NO (this is the problem!)"
fi
done
args:
executable: /bin/bash
register: vpn_check
ignore_errors: yes
failed_when: false
- name: Display VPN range check
debug:
msg: "{{ vpn_check.stdout_lines }}"
- name: Show Traefik middleware errors
shell: |
cd ~/deployment/stacks/traefik
echo "=== Traefik Middleware Errors (if any) ==="
tail -50 logs/traefik.log | grep -iE "(grafana|ipallowlist|403|middleware)" | tail -10 || echo "No middleware errors found"
args:
executable: /bin/bash
register: middleware_errors
ignore_errors: yes
failed_when: false
- name: Display middleware errors
debug:
msg: "{{ middleware_errors.stdout_lines }}"
- name: Verify middleware configuration
shell: |
cd ~/deployment/stacks/traefik/dynamic
echo "=== Current grafana-vpn-only Middleware ==="
grep -A 6 "grafana-vpn-only:" middlewares.yml
args:
executable: /bin/bash
register: middleware_config
ignore_errors: yes
failed_when: false
- name: Display middleware configuration
debug: |
msg: "{{ middleware_config.stdout_lines }}"

View File

@@ -0,0 +1,75 @@
---
- name: Monitor Grafana Client IP - Wait for Next Request
hosts: production
gather_facts: no
become: no
tasks:
- name: Instructions
debug:
msg:
- "=== LIVE MONITORING ==="
- "Bitte mache JETZT einen Zugriff auf https://grafana.michaelschiemer.de im Browser"
- "Ich warte 30 Sekunden und pr?fe dann die Logs..."
- ""
- name: Wait for access attempt
pause:
seconds: 30
- name: Check recent Grafana access attempts
shell: |
cd ~/deployment/stacks/traefik
echo "=== Last 10 Grafana Access Attempts ==="
tail -100 logs/access.log | grep -i grafana | tail -10
args:
executable: /bin/bash
register: recent_access
ignore_errors: yes
failed_when: false
- name: Extract client IPs
shell: |
cd ~/deployment/stacks/traefik
echo "=== Client IPs in recent requests ==="
tail -20 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: client_ips
ignore_errors: yes
failed_when: false
- name: Display client IPs
debug:
msg: "{{ client_ips.stdout_lines }}"
- name: Check if IP is VPN IP
shell: |
cd ~/deployment/stacks/traefik
tail -10 logs/access.log | grep -i grafana | tail -5 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | while read ip; do
if [[ "$ip" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "? $ip -> VPN IP (10.8.0.0/24) - Traffic kommt ?ber VPN!"
else
echo "? $ip -> Public IP (nicht VPN) - Traffic kommt NICHT ?ber VPN"
fi
done
args:
executable: /bin/bash
register: vpn_check
ignore_errors: yes
failed_when: false
- name: Display VPN check
debug:
msg: "{{ vpn_check.stdout_lines }}"
- name: Recommendations
debug:
msg:
- ""
- "=== ERGEBNIS ==="
- "Wenn ClientHost: 10.8.0.7 (VPN-IP) ? Traffic kommt ?ber VPN ?"
- "Dann k?nnen wir die tempor?re IP-Erlaubnis entfernen!"
- ""
- "Wenn ClientHost: 89.246.96.244 (?ffentliche IP) ? Traffic kommt NICHT ?ber VPN ?"
- "Dann m?ssen wir VPN-Routing noch weiter fixen"

View File

@@ -0,0 +1,80 @@
---
- name: Monitor Grafana Access Live - Check Latest Request
hosts: production
gather_facts: no
become: no
tasks:
- name: Get timestamp of last log entry
shell: |
cd ~/deployment/stacks/traefik
tail -1 logs/access.log | grep -oP '"time":"[^"]*"'
args:
executable: /bin/bash
register: last_log_time
ignore_errors: yes
failed_when: false
- name: Display last log time
debug:
msg: "{{ last_log_time.stdout }}"
- name: Get last 30 Grafana access attempts
shell: |
cd ~/deployment/stacks/traefik
tail -1000 logs/access.log | grep -i grafana | tail -30
args:
executable: /bin/bash
register: grafana_logs
ignore_errors: yes
failed_when: false
- name: Extract client IPs from last 10 Grafana requests
shell: |
cd ~/deployment/stacks/traefik
tail -200 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: client_ips
ignore_errors: yes
failed_when: false
- name: Display client IPs found
debug:
msg: "{{ client_ips.stdout_lines }}"
- name: Analyze last 5 Grafana requests
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -5 | while IFS= read -r line; do
time=$(echo "$line" | grep -oP '"time":"[^"]*"' | sed 's/"time":"//;s/"//' | cut -d'T' -f2 | cut -d'+' -f1)
client=$(echo "$line" | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//')
status=$(echo "$line" | grep -oP '"DownstreamStatus":[0-9]+' | sed 's/"DownstreamStatus"://')
if [[ "$client" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "$time | ClientHost: $client | Status: $status ? VPN-IP"
elif [[ "$client" == "89.246.96.244" ]]; then
echo "$time | ClientHost: $client | Status: $status ? Public IP"
else
echo "$time | ClientHost: $client | Status: $status ? Unknown"
fi
done
args:
executable: /bin/bash
register: analysis
ignore_errors: yes
failed_when: false
- name: Display analysis
debug:
msg: "{{ analysis.stdout_lines }}"
- name: Recommendations
debug:
msg:
- ""
- "=== ERGEBNIS ==="
- "Wenn ClientHost: 10.8.0.7 ? Traffic kommt ?ber VPN ?"
- "? Dann k?nnen wir die tempor?re IP-Erlaubnis entfernen!"
- ""
- "Wenn ClientHost: 89.246.96.244 ? Traffic kommt NICHT ?ber VPN ?"
- "? Dann m?ssen wir weiter debuggen (Route, AllowedIPs, etc.)"

View File

@@ -0,0 +1,86 @@
---
- name: Monitor Grafana Access After Firewall Changes
hosts: production
gather_facts: no
become: no
tasks:
- name: Instructions
debug:
msg:
- "=== LIVE MONITORING NACH FIREWALL-?NDERUNGEN ==="
- "Firewall-Regeln wurden erstellt ?"
- "WireGuard ist verbunden ?"
- ""
- "Bitte mache JETZT einen neuen Zugriff auf https://grafana.michaelschiemer.de im Browser"
- "Ich warte 20 Sekunden und pr?fe dann die Logs..."
- ""
- name: Get current log timestamp
shell: |
cd ~/deployment/stacks/traefik
tail -1 logs/access.log | grep -oP '"time":"[^"]*"'
args:
executable: /bin/bash
register: current_timestamp
failed_when: false
- name: Display current timestamp
debug:
msg: "Letztes Log: {{ current_timestamp.stdout }}"
- name: Wait for access attempt
pause:
seconds: 20
- name: Check for new Grafana access
shell: |
cd ~/deployment/stacks/traefik
tail -200 logs/access.log | grep -i grafana | tail -20 | while IFS= read -r line; do
time=$(echo "$line" | grep -oP '"time":"[^"]*"' | sed 's/"time":"//;s/"//' | cut -d'T' -f2 | cut -d'+' -f1 | cut -d':' -f1-2)
client=$(echo "$line" | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//')
status=$(echo "$line" | grep -oP '"DownstreamStatus":[0-9]+' | sed 's/"DownstreamStatus"://')
if echo "$client" | grep -q '^10\.8\.0\.'; then
echo "$time | ClientHost: $client | Status: $status ? VPN-IP (Traffic kommt ?ber VPN!)"
elif [ "$client" = "89.246.96.244" ]; then
echo "$time | ClientHost: $client | Status: $status ? Public IP (Traffic kommt NICHT ?ber VPN)"
else
echo "$time | ClientHost: $client | Status: $status ? Unknown IP"
fi
done
args:
executable: /bin/bash
register: analysis
ignore_errors: yes
failed_when: false
- name: Display analysis
debug:
msg: "{{ analysis.stdout_lines }}"
- name: Get unique client IPs from last 10 requests
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: unique_ips
ignore_errors: yes
failed_when: false
- name: Display unique IPs
debug:
msg: "{{ unique_ips.stdout_lines }}"
- name: Final verdict
debug:
msg:
- ""
- "=== ERGEBNIS ==="
- "Pr?fe die obigen Zeilen:"
- ""
- "? Wenn ClientHost: 10.8.0.7 ? Traffic kommt ?ber VPN!"
- " ? Dann k?nnen wir die tempor?re IP-Erlaubnis entfernen!"
- ""
- "? Wenn ClientHost: 89.246.96.244 ? Traffic kommt NICHT ?ber VPN"
- " ? Dann m?ssen wir weitere Optionen probieren (Route explizit setzen, etc.)"

View File

@@ -0,0 +1,70 @@
---
- name: Monitor Live Grafana Access
hosts: production
gather_facts: no
become: no
tasks:
- name: Instructions
debug:
msg:
- "=== LIVE MONITORING ==="
- "Bitte mache JETZT einen Zugriff auf https://grafana.michaelschiemer.de im Browser"
- "Ich warte 20 Sekunden und pr?fe dann die Logs..."
- ""
- name: Get current log timestamp
shell: |
cd ~/deployment/stacks/traefik
tail -1 logs/access.log | grep -oP '"time":"[^"]*"'
args:
executable: /bin/bash
register: current_timestamp
failed_when: false
- name: Display current timestamp
debug:
msg: "Letztes Log: {{ current_timestamp.stdout }}"
- name: Wait for access attempt
pause:
seconds: 20
- name: Check for new Grafana access
shell: |
cd ~/deployment/stacks/traefik
tail -500 logs/access.log | grep -i grafana | tail -10 | while IFS= read -r line; do
time=$(echo "$line" | grep -oP '"time":"[^"]*"' | sed 's/"time":"//;s/"//' | cut -d'T' -f2 | cut -d'+' -f1)
client=$(echo "$line" | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//')
status=$(echo "$line" | grep -oP '"DownstreamStatus":[0-9]+' | sed 's/"DownstreamStatus"://')
if echo "$client" | grep -q "^10\.8\.0\."; then
echo "$time | ClientHost: $client | Status: $status ? VPN-IP (Traffic kommt ?ber VPN!)"
elif [ "$client" = "89.246.96.244" ]; then
echo "$time | ClientHost: $client | Status: $status ? Public IP (Traffic kommt NICHT ?ber VPN)"
else
echo "$time | ClientHost: $client | Status: $status ? Unknown"
fi
done
args:
executable: /bin/bash
register: analysis
ignore_errors: yes
failed_when: false
- name: Display analysis
debug:
msg: "{{ analysis.stdout_lines }}"
- name: Get unique client IPs
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: unique_ips
ignore_errors: yes
failed_when: false
- name: Display unique IPs
debug:
msg: "{{ unique_ips.stdout_lines }}"

View File

@@ -0,0 +1,205 @@
---
- name: Regenerate WireGuard Client - Fresh Config
hosts: production
become: yes
gather_facts: yes
vars:
wireguard_interface: "wg0"
wireguard_config_path: "/etc/wireguard"
wireguard_config_file: "{{ wireguard_config_path }}/{{ wireguard_interface }}.conf"
wireguard_client_configs_path: "/etc/wireguard/clients"
wireguard_local_client_configs_dir: "{{ playbook_dir }}/../wireguard-clients"
tasks:
- name: Validate client name
fail:
msg: "client_name is required. Usage: ansible-playbook ... -e 'client_name=myclient'"
when: client_name is not defined or client_name == ""
- name: Check if old client config exists
stat:
path: "{{ wireguard_client_configs_path }}/{{ client_name }}.conf"
register: old_client_config
failed_when: false
- name: Backup old client config
copy:
src: "{{ wireguard_client_configs_path }}/{{ client_name }}.conf"
dest: "{{ wireguard_client_configs_path }}/{{ client_name }}.conf.backup-{{ ansible_date_time.epoch }}"
remote_src: yes
when: old_client_config.stat.exists
register: backup_result
failed_when: false
- name: Display backup info
debug:
msg: "Alte Config wurde gesichert als: {{ backup_result.dest | default('N/A') }}"
when: old_client_config.stat.exists
- name: Remove old client from WireGuard server config
shell: |
# Entferne den [Peer] Block f?r den Client aus wg0.conf
sed -i '/# BEGIN ANSIBLE MANAGED BLOCK - Client: {{ client_name }}/,/^# END ANSIBLE MANAGED BLOCK - Client: {{ client_name }}/d' {{ wireguard_config_file }}
# Fallback: Entferne auch ohne Marker
sed -i '/# Client: {{ client_name }}/,/{/d' {{ wireguard_config_file }}
sed -i '/PublicKey = .*/d' {{ wireguard_config_file }} || true
sed -i '/AllowedIPs = .*\/32$/d' {{ wireguard_config_file }} || true
args:
executable: /bin/bash
register: remove_result
failed_when: false
changed_when: false
- name: Set WireGuard network
set_fact:
wireguard_network: "{{ wireguard_network | default('10.8.0.0/24') }}"
- name: Set WireGuard other variables with defaults
set_fact:
wireguard_port: "{{ wireguard_port | default(51820) }}"
client_ip: "{{ client_ip | default('') }}"
allowed_ips: "{{ allowed_ips | default(wireguard_network) }}"
- name: Get server external IP address
uri:
url: https://api.ipify.org
return_content: yes
register: server_external_ip
changed_when: false
failed_when: false
- name: Set server external IP
set_fact:
server_external_ip_content: "{{ ansible_host | default(server_external_ip.content | default('')) }}"
- name: Read WireGuard server config
slurp:
src: "{{ wireguard_config_file }}"
register: wireguard_server_config_read
- name: Extract server IP from config
set_fact:
server_vpn_ip: "{{ (wireguard_server_config_read.content | b64decode | regex_search('Address = ([0-9.]+)')) | default(['10.8.0.1']) | first }}"
failed_when: false
- name: Set default DNS servers
set_fact:
wireguard_dns_servers: "{{ [server_vpn_ip] }}"
- name: Extract WireGuard server IP octets
set_fact:
wireguard_server_ip_octets: "{{ server_vpn_ip.split('.') }}"
when: client_ip == ""
- name: Gather existing client addresses
set_fact:
existing_client_ips: "{{ (wireguard_server_config_read.content | b64decode | regex_findall('AllowedIPs = ([0-9A-Za-z.]+)/32', '\\\\1')) }}"
when: client_ip == ""
- name: Calculate client IP if not provided
vars:
existing_last_octets: "{{ (existing_client_ips | default([])) | map('regex_replace', '^(?:\\\\d+\\\\.\\\\d+\\\\.\\\\d+\\\\.)', '') | select('match', '^[0-9]+$') | map('int') | list }}"
server_last_octet: "{{ wireguard_server_ip_octets[3] | int }}"
next_octet_candidate: "{{ (existing_last_octets + [server_last_octet]) | map('int') | list | max + 1 if (existing_client_ips | default([]) | length > 0) else server_last_octet + 1 }}"
set_fact:
client_ip: "{{ [
wireguard_server_ip_octets[0],
wireguard_server_ip_octets[1],
wireguard_server_ip_octets[2],
next_octet_candidate
] | join('.') }}"
when: client_ip == ""
- name: Generate NEW client private key
command: "wg genkey"
register: client_private_key
changed_when: true
no_log: yes
- name: Generate NEW client public key
command: "wg pubkey"
args:
stdin: "{{ client_private_key.stdout }}"
register: client_public_key
changed_when: false
no_log: yes
- name: Add NEW client to WireGuard server config
blockinfile:
path: "{{ wireguard_config_file }}"
block: |
# Client: {{ client_name }}
[Peer]
PublicKey = {{ client_public_key.stdout }}
AllowedIPs = {{ client_ip }}/32
marker: "# {mark} ANSIBLE MANAGED BLOCK - Client: {{ client_name }}"
register: wireguard_client_block
- name: Ensure client configs directory exists
file:
path: "{{ wireguard_client_configs_path }}"
state: directory
mode: '0700'
owner: root
group: root
- name: Ensure local client configs directory exists
file:
path: "{{ wireguard_local_client_configs_dir }}"
state: directory
mode: '0700'
delegate_to: localhost
become: no
run_once: true
- name: Get server public key
shell: "cat {{ wireguard_config_path }}/{{ wireguard_interface }}_private.key | wg pubkey"
register: server_public_key_cmd
changed_when: false
no_log: yes
failed_when: false
- name: Create NEW client configuration file
template:
src: "{{ playbook_dir }}/../templates/wireguard-client.conf.j2"
dest: "{{ wireguard_client_configs_path }}/{{ client_name }}.conf"
mode: '0600'
owner: root
group: root
- name: Download NEW client configuration to control machine
fetch:
src: "{{ wireguard_client_configs_path }}/{{ client_name }}.conf"
dest: "{{ wireguard_local_client_configs_dir }}/{{ client_name }}.conf"
flat: yes
mode: '0600'
- name: Restart WireGuard service
systemd:
name: "wg-quick@{{ wireguard_interface }}"
state: restarted
- name: Display NEW client configuration
debug:
msg: |
========================================
WireGuard Client REGENERATED: {{ client_name }}
========================================
Neue Client-IP: {{ client_ip }}
Server Endpoint: {{ server_external_ip_content }}:{{ wireguard_port }}
Neue Client-Konfiguration:
{{ wireguard_local_client_configs_dir }}/{{ client_name }}.conf
WICHTIG:
1. Lade die neue Config-Datei herunter
2. Importiere sie in WireGuard (ersetze die alte!)
3. Verbinde mit dem VPN
4. Teste: ping 10.8.0.1
5. Teste: https://grafana.michaelschiemer.de
Alte Config gesichert als:
{{ backup_result.dest | default('N/A') }}
========================================

View File

@@ -0,0 +1,119 @@
---
- name: Remove Temporary IP Allowlist from Grafana - Make VPN-Only
hosts: production
gather_facts: no
become: no
tasks:
- name: Check recent Grafana access attempts
shell: |
cd ~/deployment/stacks/traefik
echo "=== Recent Grafana Access (Last 5 attempts) ==="
tail -30 logs/access.log | grep grafana | tail -5 | grep -oP '"ClientHost":"[^"]*"' | head -5
args:
executable: /bin/bash
register: recent_ips
ignore_errors: yes
failed_when: false
- name: Display recent client IPs
debug:
msg: "{{ recent_ips.stdout_lines }}"
- name: Check if any traffic comes from VPN
shell: |
cd ~/deployment/stacks/traefik
tail -20 logs/access.log | grep grafana | tail -5 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | while read ip; do
if [[ "$ip" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "? Found VPN IP: $ip"
else
echo "? Found public IP: $ip (not VPN)"
fi
done
args:
executable: /bin/bash
register: vpn_check
ignore_errors: yes
failed_when: false
- name: Display VPN check
debug:
msg: "{{ vpn_check.stdout_lines }}"
- name: Backup middlewares.yml
shell: |
cd ~/deployment/stacks/traefik/dynamic
cp middlewares.yml middlewares.yml.backup.before-remove-temp-ip.$(date +%Y%m%d_%H%M%S)
echo "Backup created"
args:
executable: /bin/bash
- name: Remove temporary IP from grafana-vpn-only middleware
shell: |
cd ~/deployment/stacks/traefik/dynamic
sed -i '/89.246.96.244\/32/d' middlewares.yml
echo "Temporary IP removed"
args:
executable: /bin/bash
- name: Verify middleware configuration
shell: |
cd ~/deployment/stacks/traefik/dynamic
echo "=== Updated grafana-vpn-only Middleware ==="
grep -A 6 "grafana-vpn-only:" middlewares.yml
args:
executable: /bin/bash
register: updated_middleware
ignore_errors: yes
failed_when: false
- name: Display updated middleware
debug:
msg: "{{ updated_middleware.stdout_lines }}"
- name: Validate YAML syntax
command: python3 -c "import yaml; yaml.safe_load(open('middlewares.yml')); print('YAML valid')"
args:
chdir: ~/deployment/stacks/traefik/dynamic
register: yaml_validation
ignore_errors: yes
failed_when: false
- name: Display YAML validation
debug:
msg: "{{ yaml_validation.stdout_lines }}"
- name: Restart Traefik to apply changes
command: docker compose restart traefik
args:
chdir: ~/deployment/stacks/traefik
register: traefik_restart
- name: Wait for Traefik to restart
pause:
seconds: 5
- name: Verify Traefik status
command: docker compose ps traefik
args:
chdir: ~/deployment/stacks/traefik
register: traefik_status
- name: Display Traefik status
debug:
msg: "{{ traefik_status.stdout_lines }}"
- name: Final instructions
debug:
msg:
- "=== TEMPORARY IP REMOVED ==="
- "Grafana should now be VPN-only"
- ""
- "Test:"
- "1. With VPN: https://grafana.michaelschiemer.de should work ?"
- "2. Without VPN: https://grafana.michaelschiemer.de should give 403 ?"
- ""
- "If it doesn't work:"
- "- Check that VPN routing works (DNS = 10.8.0.1 or use hosts file)"
- "- Check Traefik logs: tail -f ~/deployment/stacks/traefik/logs/access.log | grep grafana"
- "- Restore backup if needed: cp middlewares.yml.backup.* middlewares.yml"

View File

@@ -7,9 +7,9 @@
vars:
# WireGuard variables are defined in group_vars/production.yml
# Can be overridden via -e flag if needed
wireguard_port: "{{ wireguard_port | default(wireguard_port_default) }}"
wireguard_network: "{{ wireguard_network | default(wireguard_network_default) }}"
wireguard_server_ip: "{{ wireguard_server_ip | default(wireguard_server_ip_default) }}"
wireguard_port: "{{ wireguard_port_default | default(51820) }}"
wireguard_network: "{{ wireguard_network_default | default('10.8.0.0/24') }}"
wireguard_server_ip: "{{ wireguard_server_ip_default | default('10.8.0.1') }}"
pre_tasks:

View File

@@ -0,0 +1,99 @@
---
- name: Test Grafana VPN Access - Final Verification
hosts: production
gather_facts: no
become: no
tasks:
- name: Clear instruction
debug:
msg:
- "=== WICHTIG ==="
- "Bitte f?hre diese Tests auf Windows aus (mit VPN verbunden):"
- ""
- "1. Pr?fe ob Hosts-Datei korrekt ist:"
- " type C:\\Windows\\System32\\drivers\\etc\\hosts | findstr grafana"
- " Sollte zeigen: 10.8.0.1 grafana.michaelschiemer.de"
- ""
- "2. Pr?fe ob VPN verbunden ist:"
- " ping 10.8.0.1"
- " Sollte funktionieren (wenn VPN verbunden ist)"
- ""
- "3. Teste Grafana-Zugriff:"
- " ?ffne https://grafana.michaelschiemer.de im Browser"
- ""
- "Dann pr?fe ich die Logs..."
- name: Wait for test
pause:
seconds: 15
- name: Check Traefik logs for Grafana access
shell: |
cd ~/deployment/stacks/traefik
echo "=== Last 10 Grafana Access Attempts ==="
tail -200 logs/access.log | grep -i grafana | tail -10 | while read line; do
client=$(echo "$line" | grep -oP '"ClientHost":"[^"]*"' | head -1)
time=$(echo "$line" | grep -oP '"time":"[^"]*"' | head -1)
status=$(echo "$line" | grep -oP '"DownstreamStatus":[0-9]+' | head -1)
echo "$time | $client | $status"
done
args:
executable: /bin/bash
register: recent_logs
ignore_errors: yes
failed_when: false
- name: Display recent logs
debug:
msg: "{{ recent_logs.stdout_lines }}"
- name: Extract unique client IPs
shell: |
cd ~/deployment/stacks/traefik
tail -50 logs/access.log | grep -i grafana | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: unique_ips
ignore_errors: yes
failed_when: false
- name: Display unique client IPs
debug:
msg: "{{ unique_ips.stdout_lines }}"
- name: Analyze client IPs
shell: |
cd ~/deployment/stacks/traefik
tail -20 logs/access.log | grep -i grafana | tail -5 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | while read ip; do
if [[ -z "$ip" ]]; then
continue
fi
if [[ "$ip" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "? $ip -> VPN IP (10.8.0.0/24) - Traffic kommt ?ber VPN!"
elif [[ "$ip" == "89.246.96.244" ]]; then
echo "? $ip -> Deine ?ffentliche IP - Traffic kommt NICHT ?ber VPN (Hosts-Datei funktioniert, aber VPN-Routing nicht)"
else
echo "? $ip -> Unbekannte IP"
fi
done
args:
executable: /bin/bash
register: ip_analysis
ignore_errors: yes
failed_when: false
- name: Display IP analysis
debug:
msg: "{{ ip_analysis.stdout_lines }}"
- name: Final recommendations
debug:
msg:
- ""
- "=== ERGEBNIS ==="
- "Wenn ClientHost: 10.8.0.7 ? Traffic kommt ?ber VPN ?"
- "? Dann k?nnen wir die tempor?re IP-Erlaubnis entfernen!"
- ""
- "Wenn ClientHost: 89.246.96.244 ? Traffic kommt NICHT ?ber VPN ?"
- "? Dann m?ssen wir pr?fen warum Hosts-Datei nicht ?ber VPN-Routing funktioniert"

View File

@@ -0,0 +1,78 @@
---
- name: Test Grafana VPN Access - Final Check
hosts: production
gather_facts: no
become: no
tasks:
- name: Instructions
debug:
msg:
- "=== FINALER TEST ==="
- "AllowedIPs ist korrekt (10.8.0.0/24) ?"
- ""
- "Bitte f?hre diese Schritte auf Windows aus:"
- "1. DNS-Cache leeren: ipconfig /flushdns"
- "2. Browser-Cache leeren oder Inkognito-Modus nutzen"
- "3. Stelle sicher, dass VPN verbunden ist"
- "4. ?ffne: https://grafana.michaelschiemer.de"
- "5. Warte 10 Sekunden"
- ""
- "Dann pr?fe ich die Logs..."
- name: Wait for access attempt
pause:
seconds: 20
- name: Check latest Grafana access
shell: |
cd ~/deployment/stacks/traefik
echo "=== Letzte 10 Grafana-Zugriffe ==="
tail -500 logs/access.log | grep -i grafana | tail -10 | while IFS= read -r line; do
time=$(echo "$line" | grep -oP '"time":"[^"]*"' | sed 's/"time":"//;s/"//' | cut -d'T' -f2 | cut -d'+' -f1 | cut -d':' -f1-2)
client=$(echo "$line" | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//')
status=$(echo "$line" | grep -oP '"DownstreamStatus":[0-9]+' | sed 's/"DownstreamStatus"://')
if [[ "$client" =~ ^10\.8\.0\.[0-9]+$ ]]; then
echo "$time | ClientHost: $client | Status: $status ? VPN-IP (Traffic kommt ?ber VPN!)"
elif [[ "$client" == "89.246.96.244" ]]; then
echo "$time | ClientHost: $client | Status: $status ? ?ffentliche IP (Traffic kommt NICHT ?ber VPN)"
else
echo "$time | ClientHost: $client | Status: $status ? Unbekannt"
fi
done
args:
executable: /bin/bash
register: analysis
ignore_errors: yes
failed_when: false
- name: Display analysis
debug:
msg: "{{ analysis.stdout_lines }}"
- name: Get unique client IPs from last 10 requests
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
args:
executable: /bin/bash
register: unique_ips
ignore_errors: yes
failed_when: false
- name: Display unique IPs
debug:
msg: "{{ unique_ips.stdout_lines }}"
- name: Final verdict
debug:
msg:
- ""
- "=== ERGEBNIS ==="
- "Pr?fe die obigen Zeilen:"
- ""
- "? Wenn ClientHost: 10.8.0.7 ? Traffic kommt ?ber VPN!"
- " ? Dann k?nnen wir die tempor?re IP-Erlaubnis entfernen!"
- ""
- "? Wenn ClientHost: 89.246.96.244 ? Traffic kommt NICHT ?ber VPN"
- " ? Dann m?ssen wir weitere Debugging-Schritte durchf?hren"

View File

@@ -0,0 +1,168 @@
---
- name: Test WireGuard Connection from Docker Container
hosts: production
become: yes
gather_facts: yes
vars:
test_container_name: "wireguard-test-client"
wireguard_config_path: "/tmp/wireguard-test"
tasks:
- name: Validate client name
fail:
msg: "client_name is required. Usage: ansible-playbook ... -e 'client_name=grafana-test'"
when: client_name is not defined or client_name == ""
- name: Check if WireGuard client config exists
stat:
path: "{{ playbook_dir }}/../wireguard-clients/{{ client_name }}.conf"
register: client_config_exists
delegate_to: localhost
become: no
- name: Fail if client config not found
fail:
msg: "Client config not found: {{ playbook_dir }}/../wireguard-clients/{{ client_name }}.conf"
when: not client_config_exists.stat.exists
- name: Read client config
slurp:
src: "{{ playbook_dir }}/../wireguard-clients/{{ client_name }}.conf"
register: client_config_content
delegate_to: localhost
become: no
- name: Extract client IP from config
set_fact:
client_vpn_ip: "{{ (client_config_content.content | b64decode | regex_search('Address = ([0-9.]+)')) | default(['10.8.0.7']) | first }}"
failed_when: false
- name: Display extracted client IP
debug:
msg: "Client VPN IP: {{ client_vpn_ip }}"
- name: Stop and remove existing test container
shell: |
docker stop {{ test_container_name }} || true
docker rm {{ test_container_name }} || true
args:
executable: /bin/bash
ignore_errors: yes
failed_when: false
- name: Create temporary directory for WireGuard config
file:
path: "{{ wireguard_config_path }}"
state: directory
mode: '0700'
- name: Copy client config to server
copy:
content: "{{ client_config_content.content | b64decode }}"
dest: "{{ wireguard_config_path }}/{{ client_name }}.conf"
mode: '0600'
- name: Start WireGuard test container
shell: |
docker run -d \
--name {{ test_container_name }} \
--cap-add=NET_ADMIN \
--cap-add=SYS_MODULE \
--sysctl net.ipv4.conf.all.src_valid_mark=1 \
-v {{ wireguard_config_path }}/{{ client_name }}.conf:/etc/wireguard/{{ client_name }}.conf:ro \
--device /dev/net/tun \
ghcr.io/linuxserver/wireguard:latest
args:
executable: /bin/bash
register: container_result
ignore_errors: yes
- name: Wait for container to start
pause:
seconds: 5
- name: Check container status
shell: docker ps -a --filter "name={{ test_container_name }}" --format "{{ '{{' }}.Status{{ '}}' }}"
register: container_status
failed_when: false
- name: Display container status
debug:
msg: "Container Status: {{ container_status.stdout }}"
- name: Get container logs
shell: docker logs {{ test_container_name }} --tail 50
register: container_logs
failed_when: false
- name: Display container logs
debug:
msg: "{{ container_logs.stdout_lines }}"
- name: Test ping to VPN server from container
shell: |
docker exec {{ test_container_name }} ping -c 4 10.8.0.1 || true
register: ping_result
failed_when: false
- name: Display ping result
debug:
msg: "{{ ping_result.stdout_lines }}"
- name: Test curl to Grafana from container
shell: |
docker exec {{ test_container_name }} curl -s -o /dev/null -w "%{http_code}" --max-time 10 https://grafana.michaelschiemer.de/ || echo "FAILED"
register: curl_result
failed_when: false
- name: Display curl result
debug:
msg: "HTTP Status Code: {{ curl_result.stdout }}"
- name: Get container IP
shell: |
docker exec {{ test_container_name }} ip addr show wg0 | grep "inet " | awk '{print $2}' | cut -d/ -f1 || echo "No WireGuard IP"
register: container_wg_ip
failed_when: false
- name: Display container WireGuard IP
debug:
msg: "Container WireGuard IP: {{ container_wg_ip.stdout }}"
- name: Test DNS resolution from container
shell: |
docker exec {{ test_container_name }} nslookup grafana.michaelschiemer.de || true
register: dns_result
failed_when: false
- name: Display DNS result
debug: "{{ dns_result.stdout_lines }}"
- name: Check Traefik logs for container access
shell: |
cd ~/deployment/stacks/traefik
tail -100 logs/access.log | grep -i grafana | tail -10 | grep -oP '"ClientHost":"[^"]*"' | sed 's/"ClientHost":"//;s/"//' | sort -u
register: traefik_client_ips
failed_when: false
- name: Display Traefik client IPs
debug:
msg: "{{ traefik_client_ips.stdout_lines }}"
- name: Cleanup instructions
debug:
msg: |
========================================
TEST ABGESCHLOSSEN
========================================
Container-Name: {{ test_container_name }}
Um Container zu entfernen:
docker stop {{ test_container_name }}
docker rm {{ test_container_name }}
Um Config zu entfernen:
rm -rf {{ wireguard_config_path }}
========================================

View File

@@ -0,0 +1,78 @@
#!/bin/bash
# Test VPN connection to server
# Run this script after starting the VPN with: wg-quick up test-client
set -e
echo "=== VPN Connection Test ==="
echo ""
# Check if VPN interface exists
if ! ip link show test-client > /dev/null 2>&1; then
echo "? VPN interface 'test-client' not found!"
echo " Start VPN with: wg-quick up test-client"
exit 1
fi
echo "? VPN interface 'test-client' is active"
echo ""
# Check WireGuard status
echo "=== WireGuard Status ==="
sudo wg show test-client || echo "?? Warning: Cannot show WireGuard status"
echo ""
# Test ping to server VPN IP
echo "=== Testing Ping to Server VPN IP (10.8.0.1) ==="
if ping -c 3 -W 2 10.8.0.1 > /dev/null 2>&1; then
echo "? Ping to 10.8.0.1 successful"
else
echo "? Ping to 10.8.0.1 failed"
fi
echo ""
# Check DNS resolution
echo "=== Testing DNS Resolution ==="
if host grafana.michaelschiemer.de > /dev/null 2>&1; then
echo "? DNS resolution works"
host grafana.michaelschiemer.de | head -1
else
echo "?? DNS resolution failed, but this might be OK if using VPN routing"
fi
echo ""
# Test HTTP connection to Grafana
echo "=== Testing HTTP Connection to Grafana ==="
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
--max-time 10 \
-H "User-Agent: Mozilla/5.0 (Linux; x86_64) AppleWebKit/537.36" \
--insecure \
https://grafana.michaelschiemer.de/ 2>/dev/null || echo "000")
if [ "$HTTP_CODE" = "200" ] || [ "$HTTP_CODE" = "302" ] || [ "$HTTP_CODE" = "301" ]; then
echo "? HTTP connection successful (Status: $HTTP_CODE)"
echo " Traffic is reaching Grafana through VPN!"
elif [ "$HTTP_CODE" = "000" ]; then
echo "? HTTP connection failed (could not connect)"
echo " Check if VPN is routing traffic correctly"
else
echo "?? HTTP connection returned status: $HTTP_CODE"
echo " Connection works, but got unexpected status code"
fi
echo ""
# Check routing table
echo "=== Routing Table for VPN Network ==="
ip route show | grep "10.8.0.0/24" || echo "?? No route found for 10.8.0.0/24"
echo ""
# Check which interface is used for VPN network
echo "=== Interface Route Check ==="
ip route get 10.8.0.1 2>/dev/null || echo "?? Cannot determine route to 10.8.0.1"
echo ""
echo "=== Test Complete ==="
echo ""
echo "Next step: Run Ansible playbook to check server logs:"
echo " cd deployment/ansible"
echo " ansible-playbook playbooks/check-vpn-test-from-client.yml"

View File

@@ -3,7 +3,7 @@
[Interface]
# Client private key
PrivateKey = sE81MBr64fP8YBDlhRWngwHHmlrVzIhs9NT7Dh7XbVs=
PrivateKey = iPJC8CmUegLLjV8g6MvpeVxRizS8cvL2+Uyxng1bUEo=
# Client IP address in VPN network
Address = 10.8.0.7/24

View File

@@ -56,14 +56,13 @@ http:
# 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 (e.g., 89.246.96.244), check:
# 1. VPN connection is active and traffic is routed through VPN
# 2. DNS uses 10.8.0.1 (VPN DNS server) to resolve grafana.michaelschiemer.de
# 3. Browser/system routing sends traffic through VPN interface
# 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