Files
n0mad1k d687423c22 Add service accounts and systemd hardening
- cloudflared: create dedicated service account, run as non-root with
  ProtectSystem=strict and full hardening directives
- cloudflared: skip credentials overwrite when existing tunnel has valid
  credentials on disk; delete and recreate if credentials are missing
- wireguard: add systemd drop-in with ProtectHome, ProtectClock,
  ProtectHostname, ProtectKernelLogs, PrivateTmp

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:46:24 -04:00

146 lines
5.4 KiB
YAML

---
# WireGuard server and client configuration
- name: Detect primary network interface
shell: ip route get 1.1.1.1 | awk '{for(i=1;i<=NF;i++) if($i=="dev") print $(i+1)}'
register: primary_interface
changed_when: false
- name: Set computed vars
set_fact:
_iface: "{{ primary_interface.stdout | trim }}"
_subnet_base: "{{ wg_subnet.split('.')[0:3] | join('.') }}"
- name: Generate client keys
shell: |
mkdir -p /etc/wireguard/clients
for i in $(seq 1 {{ wg_clients }}); do
if [ ! -f /etc/wireguard/clients/client${i}_private.key ]; then
wg genkey | tee /etc/wireguard/clients/client${i}_private.key | wg pubkey > /etc/wireguard/clients/client${i}_public.key
wg genpsk > /etc/wireguard/clients/client${i}_psk.key
chmod 600 /etc/wireguard/clients/client${i}_*.key
fi
done
args:
creates: /etc/wireguard/clients/client1_private.key
- name: Ensure ip6tables nat module is available
modprobe:
name: ip6table_nat
state: present
ignore_errors: true
- name: Build WireGuard server config
shell: |
SERVER_PRIVKEY=$(cat /etc/wireguard/server_private.key)
# Header + PrivateKey (needs shell expansion)
echo "[Interface]" > /etc/wireguard/wg0.conf
echo "Address = {{ _subnet_base }}.1/24" >> /etc/wireguard/wg0.conf
echo "ListenPort = {{ wg_port }}" >> /etc/wireguard/wg0.conf
echo "PrivateKey = ${SERVER_PRIVKEY}" >> /etc/wireguard/wg0.conf
echo "SaveConfig = false" >> /etc/wireguard/wg0.conf
# PostUp/PostDown rules (Jinja2 vars, no shell expansion needed)
cat >> /etc/wireguard/wg0.conf << 'RULESEOF'
PostUp = iptables -A FORWARD -i wg0 -o {{ _iface }} -j ACCEPT
PostUp = iptables -A FORWARD -i {{ _iface }} -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostUp = iptables -t nat -A POSTROUTING -o {{ _iface }} -s {{ wg_subnet }} -j MASQUERADE
PostUp = ip6tables -A FORWARD -i wg0 -o {{ _iface }} -j ACCEPT || true
PostUp = ip6tables -A FORWARD -i {{ _iface }} -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT || true
PostUp = ip6tables -t nat -A POSTROUTING -o {{ _iface }} -j MASQUERADE || true
PostUp = iptables -I INPUT -i wg0 -p tcp --dport 22 -j DROP
PostUp = iptables -I INPUT -i wg0 -p tcp --dport 80 -j DROP
PostUp = iptables -I INPUT -i wg0 -p tcp --dport 443 -j DROP
PostDown = iptables -D FORWARD -i wg0 -o {{ _iface }} -j ACCEPT
PostDown = iptables -D FORWARD -i {{ _iface }} -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
PostDown = iptables -t nat -D POSTROUTING -o {{ _iface }} -s {{ wg_subnet }} -j MASQUERADE
PostDown = ip6tables -D FORWARD -i wg0 -o {{ _iface }} -j ACCEPT || true
PostDown = ip6tables -D FORWARD -i {{ _iface }} -o wg0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT || true
PostDown = ip6tables -t nat -D POSTROUTING -o {{ _iface }} -j MASQUERADE || true
PostDown = iptables -D INPUT -i wg0 -p tcp --dport 22 -j DROP
PostDown = iptables -D INPUT -i wg0 -p tcp --dport 80 -j DROP
PostDown = iptables -D INPUT -i wg0 -p tcp --dport 443 -j DROP
RULESEOF
# Peers
for i in $(seq 1 {{ wg_clients }}); do
CLIENT_PUBKEY=$(cat /etc/wireguard/clients/client${i}_public.key)
CLIENT_PSK=$(cat /etc/wireguard/clients/client${i}_psk.key)
echo "" >> /etc/wireguard/wg0.conf
echo "[Peer]" >> /etc/wireguard/wg0.conf
echo "PublicKey = ${CLIENT_PUBKEY}" >> /etc/wireguard/wg0.conf
echo "PresharedKey = ${CLIENT_PSK}" >> /etc/wireguard/wg0.conf
echo "AllowedIPs = {{ _subnet_base }}.$(( i + 1 ))/32" >> /etc/wireguard/wg0.conf
done
chmod 600 /etc/wireguard/wg0.conf
args:
creates: /etc/wireguard/wg0.conf
- name: Verify WireGuard config
shell: cat /etc/wireguard/wg0.conf
register: wg_config_check
changed_when: false
- name: Show generated config (debug)
debug:
var: wg_config_check.stdout_lines
- name: Generate client config files
shell: |
SERVER_PUBKEY=$(echo '{{ server_privkey_content.content | b64decode | trim }}' | wg pubkey)
SERVER_ENDPOINT="{{ target_host }}:{{ wg_port }}"
for i in $(seq 1 {{ wg_clients }}); do
CLIENT_PRIVKEY=$(cat /etc/wireguard/clients/client${i}_private.key)
CLIENT_PSK=$(cat /etc/wireguard/clients/client${i}_psk.key)
CLIENT_IP="{{ _subnet_base }}.$(( i + 1 ))"
cat > /etc/wireguard/clients/client${i}.conf << CLIENTEOF
[Interface]
PrivateKey = ${CLIENT_PRIVKEY}
Address = ${CLIENT_IP}/32
DNS = {{ wg_dns }}
[Peer]
PublicKey = ${SERVER_PUBKEY}
PresharedKey = ${CLIENT_PSK}
Endpoint = ${SERVER_ENDPOINT}
AllowedIPs = {{ wg_allowed_ips }}
PersistentKeepalive = 25
CLIENTEOF
qrencode -t ansiutf8 < /etc/wireguard/clients/client${i}.conf > /etc/wireguard/clients/client${i}_qr.txt 2>/dev/null || true
done
args:
creates: /etc/wireguard/clients/client1.conf
- name: Create WireGuard systemd override directory
file:
path: /etc/systemd/system/wg-quick@wg0.service.d
state: directory
mode: "0755"
- name: Deploy WireGuard systemd hardening override
copy:
dest: /etc/systemd/system/wg-quick@wg0.service.d/hardening.conf
content: |
[Service]
ProtectHome=true
ProtectClock=true
ProtectHostname=true
ProtectKernelLogs=true
PrivateTmp=true
mode: "0644"
- name: Reload systemd daemon
systemd:
daemon_reload: true
- name: Enable and start WireGuard
systemd:
name: wg-quick@wg0
state: started
enabled: true