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.
157 lines
5.5 KiB
Bash
Executable File
157 lines
5.5 KiB
Bash
Executable File
#!/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 "$@"
|