From a08a8f7408277c598f2f17a60561c88fedb7a006 Mon Sep 17 00:00:00 2001 From: Lukas Date: Sun, 17 May 2026 18:57:12 +0200 Subject: [PATCH] backup --- Docker/entrypoint.sh | 97 +++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 51 deletions(-) diff --git a/Docker/entrypoint.sh b/Docker/entrypoint.sh index 6eb7b6f..fad34d6 100644 --- a/Docker/entrypoint.sh +++ b/Docker/entrypoint.sh @@ -130,10 +130,8 @@ start_vpn() { ip link add "$INTERFACE" type wireguard # Apply the WireGuard config (keys, peer, endpoint) - # We filter out Address/DNS/MTU/PreUp/PostUp/PreDown/PostDown/SaveConfig - # AllowedIPs is kept because WireGuard needs it to know which traffic to tunnel. - # We remove the auto-created default route afterwards and set our own. - wg setconf "$INTERFACE" <(grep -v -i '^\(Address\|DNS\|MTU\|PreUp\|PostUp\|PreDown\|PostDown\|SaveConfig\)' "$CONFIG_FILE") + # Filter out wg-quick directives that wg setconf doesn't understand + wg setconf "$INTERFACE" <(grep -v -i '^\(Address\|DNS\|MTU\|Table\|PreUp\|PostUp\|PreDown\|PostDown\|SaveConfig\)' "$CONFIG_FILE") # Log public key so it can be verified against the server's peer list local PUBKEY @@ -143,38 +141,35 @@ start_vpn() { # Assign the address ip -4 address add "$VPN_ADDRESS" dev "$INTERFACE" - # Set MTU + # Set MTU and bring up ip link set mtu 1420 up dev "$INTERFACE" - # Remove the auto-created default route by wg setconf (if AllowedIPs = 0.0.0.0/0) - # We set our own routes manually to avoid breaking the endpoint connection + # ── fwmark-based routing (mirrors wg-quick behavior) ── + # WireGuard marks its own encapsulated UDP packets with this fwmark. + # Policy rules then ensure: + # - Normal packets (no mark) → VPN routing table → wg0 + # - WireGuard-encapsulated packets (marked) → main table → eth0 + local FW_MARK=51820 + local FW_TABLE=51820 + wg set "$INTERFACE" fwmark "$FW_MARK" + + # Remove any auto-created default route on wg0 ip route del default dev "$INTERFACE" 2>/dev/null || true - # Find default gateway/interface for the endpoint route + # VPN routing table: send everything through the tunnel + ip -4 route add default dev "$INTERFACE" table "$FW_TABLE" + + # Policy rules: + # 1. Packets NOT marked by WireGuard use the VPN table (→ wg0) + # 2. suppress_prefixlength 0: ignore bare default routes in main table, + # but keep more-specific routes (e.g. LAN, endpoint) working + ip -4 rule add not fwmark "$FW_MARK" table "$FW_TABLE" + ip -4 rule add table main suppress_prefixlength 0 + + # Find default gateway/interface DEFAULT_GW=$(ip route | grep '^default' | head -1 | awk '{print $3}') DEFAULT_IF=$(ip route | grep '^default' | head -1 | awk '{print $5}') - # Route VPN endpoint through the container's default gateway - if [ -n "$DEFAULT_GW" ] && [ -n "$DEFAULT_IF" ]; then - ip route add "$VPN_ENDPOINT/32" via "$DEFAULT_GW" dev "$DEFAULT_IF" 2>/dev/null || true - fi - - # Parse AllowedIPs from config and add routes dynamically - ALLOWED_IPS=$(grep -i '^AllowedIPs' "$CONFIG_FILE" | head -1 | sed 's/.*= *//;s/ //g') - - if [ -n "$ALLOWED_IPS" ]; then - for ip in $(echo "$ALLOWED_IPS" | tr ',' ' '); do - if [ "$ip" = "0.0.0.0/0" ]; then - # Use the split route trick to avoid overriding the default route - # (which would break the endpoint connection) - ip route add 0.0.0.0/1 dev "$INTERFACE" 2>/dev/null || true - ip route add 128.0.0.0/1 dev "$INTERFACE" 2>/dev/null || true - else - ip route add "$ip" dev "$INTERFACE" 2>/dev/null || true - fi - done - fi - # ── Policy routing: ensure responses to incoming LAN traffic go back via eth0 ── if [ -n "$DEFAULT_GW" ] && [ -n "$DEFAULT_IF" ]; then # Get the container's eth0 IP address (BusyBox-compatible, no grep -P) @@ -201,8 +196,12 @@ start_vpn() { fi echo "[vpn] WireGuard interface ${INTERFACE} is up." - echo "[vpn] Routes:" + echo "[vpn] Main routes:" ip route show | sed 's/^/[vpn] /' + echo "[vpn] VPN table ($FW_TABLE):" + ip route show table "$FW_TABLE" 2>/dev/null | sed 's/^/[vpn] /' + echo "[vpn] Policy rules:" + ip rule show | sed 's/^/[vpn] /' echo "[vpn] WireGuard status:" wg show "$INTERFACE" 2>/dev/null | sed 's/^/[vpn] /' } @@ -213,23 +212,19 @@ start_vpn() { stop_vpn() { echo "[vpn] Stopping WireGuard interface ${INTERFACE}..." - # Remove routes added for AllowedIPs - ALLOWED_IPS=$(grep -i '^AllowedIPs' "$CONFIG_FILE" | head -1 | sed 's/.*= *//;s/ //g') - if [ -n "$ALLOWED_IPS" ]; then - for ip in $(echo "$ALLOWED_IPS" | tr ',' ' '); do - if [ "$ip" = "0.0.0.0/0" ]; then - ip route del 0.0.0.0/1 dev "$INTERFACE" 2>/dev/null || true - ip route del 128.0.0.0/1 dev "$INTERFACE" 2>/dev/null || true - else - ip route del "$ip" dev "$INTERFACE" 2>/dev/null || true - fi - done - fi + local FW_MARK=51820 + local FW_TABLE=51820 - # Remove endpoint route - if [ -n "$VPN_ENDPOINT" ]; then - ip route del "$VPN_ENDPOINT/32" 2>/dev/null || true - fi + # Remove fwmark-based policy rules + ip -4 rule del not fwmark "$FW_MARK" table "$FW_TABLE" 2>/dev/null || true + ip -4 rule del table main suppress_prefixlength 0 2>/dev/null || true + + # Flush VPN routing table + ip -4 route flush table "$FW_TABLE" 2>/dev/null || true + + # Remove LAN policy routing + ip -4 rule del table 100 2>/dev/null || true + ip -4 route flush table 100 2>/dev/null || true ip link del "$INTERFACE" 2>/dev/null || true } @@ -246,14 +241,14 @@ health_loop() { while true; do sleep "$CHECK_INTERVAL" - if curl -sf --max-time 5 "http://$CHECK_HOST" > /dev/null 2>&1; then + if ping -c 1 -W 5 "$CHECK_HOST" > /dev/null 2>&1; then if [ "$failures" -gt 0 ]; then echo "[health] VPN recovered." failures=0 fi else failures=$((failures + 1)) - echo "[health] Check failed ($failures/$max_failures) — curl http://${CHECK_HOST} timed out" + echo "[health] Check failed ($failures/$max_failures) — ping ${CHECK_HOST} failed" # Dump WireGuard stats to show if handshake is stale and how much data flows echo "[health] wg stats:" wg show "$INTERFACE" 2>/dev/null | grep -E 'latest handshake|transfer|endpoint' | sed 's/^/[health] /' || echo "[health] wg0 not found" @@ -316,16 +311,16 @@ check_vpn_connectivity() { fi # 2. Check whether traffic actually flows through the tunnel - echo "[check] Testing traffic through tunnel (http://${CHECK_HOST})..." + echo "[check] Testing traffic through tunnel (ping ${CHECK_HOST})..." local rx_before rx_before=$(wg show "$INTERFACE" transfer 2>/dev/null | awk '{print $2}' | head -1) - if curl -sf --max-time 8 "http://${CHECK_HOST}" > /dev/null 2>&1; then + if ping -c 1 -W 8 "${CHECK_HOST}" > /dev/null 2>&1; then echo "[check] OK Traffic flows — tunnel is fully working" else local rx_after rx_after=$(wg show "$INTERFACE" transfer 2>/dev/null | awk '{print $2}' | head -1) - echo "[check] FAIL http://${CHECK_HOST} unreachable through tunnel" + echo "[check] FAIL ping ${CHECK_HOST} unreachable through tunnel" if [ -n "$rx_before" ] && [ -n "$rx_after" ]; then if [ "$rx_after" -le "$rx_before" ]; then