From 7eb7a19b3fdec87758d6b9854fce9d58786a4ade Mon Sep 17 00:00:00 2001 From: gyurix Date: Sun, 22 Mar 2026 09:41:17 +0100 Subject: [PATCH] Enhance WireGuard startup and keepalive monitoring logic in entrypoint and persistentkeepalive scripts --- Dockerfile | 2 +- entrypoint.sh | 40 +++++++++++++++++++++++++++------------- persistentkeepalive.sh | 39 +++++++++++++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index 700a9bc..696530d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,4 +25,4 @@ VOLUME ["/etc/wireguard"] ENV WG_QUICK_USERSPACE_IMPLEMENTATION=boringtun LOGNAME=nobody INTERFACE=wg0 COPY set_gateway.sh /etc/wireguard/ COPY persistentkeepalive.sh /etc/wireguard/ -ENTRYPOINT ["/sbin/tini", "--", "/bin/sh", "-c", "test -f \"/etc/wireguard/$INTERFACE.conf\" || ( umask 077 && printf '%s\\n' '[Interface]' 'Address = 10.8.0.1/24' 'PostUp = iptables --table nat --append POSTROUTING --jump MASQUERADE' 'PostDown = iptables --table nat --delete POSTROUTING --jump MASQUERADE' 'ListenPort = 51820' \"PrivateKey = $(wg genkey)\" | tee \"/etc/wireguard/$INTERFACE.conf\" ) && test -c /dev/net/tun || { mkdir -p /dev/net && mknod -m 666 /dev/net/tun c 10 200; } && exec wg-quick up \"$INTERFACE\"", "--"] +ENTRYPOINT ["/sbin/tini", "--", "/bin/sh", "-c", "test -f \"/etc/wireguard/$INTERFACE.conf\" || ( umask 077 && printf '%s\\n' '[Interface]' 'Address = 10.8.0.1/24' 'PostUp = iptables --table nat --append POSTROUTING --jump MASQUERADE' 'PostDown = iptables --table nat --delete POSTROUTING --jump MASQUERADE' 'ListenPort = 51820' \"PrivateKey = $(wg genkey)\" | tee \"/etc/wireguard/$INTERFACE.conf\" ) && test -c /dev/net/tun || { mkdir -p /dev/net && mknod -m 666 /dev/net/tun c 10 200; } && /etc/wireguard/persistentkeepalive.sh & exec wg-quick up \"$INTERFACE\"", "--"] diff --git a/entrypoint.sh b/entrypoint.sh index eb43fc3..7efd2e5 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,29 +4,43 @@ set -e declare -r WG_INTERFACE=${1:-wg0} -function infinite_loop() { - # Handle shutdown behavior - trap 'shutdown_wg "$1"' SIGTERM SIGINT SIGQUIT - - sleep infinity & - wait $! -} +KEEPALIVE_PID="" +WG_PID="" function shutdown_wg() { - echo "Shutting down Wireguard (boringtun)" + echo "Shutting down WireGuard (boringtun)" + [ -n "$KEEPALIVE_PID" ] && kill "$KEEPALIVE_PID" 2>/dev/null || true wg-quick down "$1" exit 0 } function start_wg() { - echo "Starting up Wireguard (boringtun)" - wg-quick up "$1" - infinite_loop "$1" + echo "Starting WireGuard (boringtun)" + # Run wg-quick in the background so we retain control of this shell + wg-quick up "$1" & + WG_PID=$! + + echo "Starting keepalive connection monitor" + /etc/wireguard/persistentkeepalive.sh & + KEEPALIVE_PID=$! + + # Handle clean shutdown signals + trap 'shutdown_wg "$1"' SIGTERM SIGINT SIGQUIT + + # Block until the keepalive monitor exits. + # It exits with code 1 only when the connection is stuck — trigger a restart. + if ! wait "$KEEPALIVE_PID"; then + echo "WireGuard keepalive monitor detected a stuck connection — forcing container restart (exit 1)" + [ -n "$WG_PID" ] && kill -9 "$WG_PID" 2>/dev/null || true + exit 1 + fi + + # Keepalive exited cleanly (shouldn't happen); wait for wg process too + wait "$WG_PID" || exit $? } -#if [[ "$1" =~ ^wg.*$ ]]; then if [ -f "/etc/wireguard/${WG_INTERFACE}.conf" ]; then - start_wg ${WG_INTERFACE} + start_wg "${WG_INTERFACE}" else exec "$@" fi diff --git a/persistentkeepalive.sh b/persistentkeepalive.sh index 817b682..9412b5d 100755 --- a/persistentkeepalive.sh +++ b/persistentkeepalive.sh @@ -1,6 +1,37 @@ #!/bin/sh -sleep 15; -PERSISTENT_KEEP_ALIVE=$(cat /etc/wireguard/wg0.conf | grep PersistentKeepalive | awk '{print $3}'); -WG_SERVER_IP="$(cat /etc/wireguard/wg0.conf | grep Address | awk '{print $3}' | cut -d . -f1-3).1"; -ping -s 0 -I wg0 -i $PERSISTENT_KEEP_ALIVE $WG_SERVER_IP +CONF="/etc/wireguard/${INTERFACE:-wg0}.conf" +IFACE="${INTERFACE:-wg0}" + +# Wait for the WireGuard interface to be fully up +echo "WireGuard keepalive monitor: waiting 15s for interface $IFACE to come up..." +sleep 15 + +PERSISTENT_KEEP_ALIVE=$(grep PersistentKeepalive "$CONF" | awk '{print $3}') +# Prefer the Endpoint IP; fall back to the Address-derived gateway +WG_SERVER_IP=$(grep Endpoint "$CONF" | awk '{print $3}' | cut -d: -f1) +if [ -z "$WG_SERVER_IP" ]; then + WG_SERVER_IP="$(grep Address "$CONF" | awk '{print $3}' | cut -d. -f1-3).1" +fi + +PING_INTERVAL=${PERSISTENT_KEEP_ALIVE:-25} +MAX_FAILURES=3 +fail_count=0 + +echo "WireGuard keepalive monitor started (target: $WG_SERVER_IP, interval: ${PING_INTERVAL}s, threshold: $MAX_FAILURES)" + +while true; do + if ping -c 1 -W 5 -I "$IFACE" "$WG_SERVER_IP" > /dev/null 2>&1; then + fail_count=0 + else + fail_count=$((fail_count + 1)) + echo "WireGuard keepalive ping failed ($fail_count/$MAX_FAILURES) to $WG_SERVER_IP via $IFACE" + if [ "$fail_count" -ge "$MAX_FAILURES" ]; then + echo "WireGuard connection is stuck after $MAX_FAILURES consecutive failures — forcing container restart..." + # SIGKILL tini (PID 1) so the container exits with code 137 and Docker restarts it + kill -9 1 + exit 1 + fi + fi + sleep "$PING_INTERVAL" +done