From f91a0f3b1aba95bcf3b248e02a89709ce0274fa7 Mon Sep 17 00:00:00 2001 From: "Aleksandr V. Piskunov" Date: Sun, 1 Jul 2018 15:40:31 +0300 Subject: [PATCH] wireguard-tools: add wireguard_watchdog script This watchdog script tries to re-resolve hostnames for inactive WireGuard peers. Use it for peers with a frequently changing dynamic IP. persistent_keepalive must be set, recommended value is 25 seconds. Run this script from cron every minute: echo '* * * * * /usr/bin/wireguard_watchdog' >> /etc/crontabs/root Signed-off-by: Aleksandr V. Piskunov [bump the package release] Signed-off-by: Kevin Darbyshire-Bryant (cherry picked from commit 20c4819c7baf6f9b91420849caf30e5137bd75d6) --- package/network/services/wireguard/Makefile | 5 +- .../wireguard/files/wireguard_watchdog | 60 +++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 package/network/services/wireguard/files/wireguard_watchdog diff --git a/package/network/services/wireguard/Makefile b/package/network/services/wireguard/Makefile index 9965002712..a88dca1e7f 100644 --- a/package/network/services/wireguard/Makefile +++ b/package/network/services/wireguard/Makefile @@ -12,7 +12,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=wireguard PKG_VERSION:=0.0.20180718 -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_SOURCE:=WireGuard-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=https://git.zx2c4.com/WireGuard/snapshot/ @@ -84,12 +84,13 @@ define Package/wireguard-tools/description $(call Package/wireguard/Default/description) This package provides the userspace control program for WireGuard, - `wg(8)`, and a netifd protocol helper. + `wg(8)`, a netifd protocol helper, and a re-resolve watchdog script. endef define Package/wireguard-tools/install $(INSTALL_DIR) $(1)/usr/bin/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/src/tools/wg $(1)/usr/bin/ + $(INSTALL_BIN) ./files/wireguard_watchdog $(1)/usr/bin/ $(INSTALL_DIR) $(1)/lib/netifd/proto/ $(INSTALL_BIN) ./files/wireguard.sh $(1)/lib/netifd/proto/ endef diff --git a/package/network/services/wireguard/files/wireguard_watchdog b/package/network/services/wireguard/files/wireguard_watchdog new file mode 100644 index 0000000000..5fbbeafec1 --- /dev/null +++ b/package/network/services/wireguard/files/wireguard_watchdog @@ -0,0 +1,60 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2018 Aleksandr V. Piskunov . +# Copyright (C) 2015-2018 Jason A. Donenfeld . All Rights Reserved. +# +# This watchdog script tries to re-resolve hostnames for inactive WireGuard peers. +# Use it for peers with a frequently changing dynamic IP. +# persistent_keepalive must be set, recommended value is 25 seconds. +# +# Run this script from cron every minute: +# echo '* * * * * /usr/bin/wireguard_watchdog' >> /etc/crontabs/root + + +. /lib/functions.sh + +check_peer_activity() { + local cfg=$1 + local iface=$2 + local public_key + local endpoint_host + local endpoint_port + local persistent_keepalive + local last_handshake + local idle_seconds + + config_get public_key "${cfg}" "public_key" + config_get endpoint_host "${cfg}" "endpoint_host" + config_get endpoint_port "${cfg}" "endpoint_port" + persistent_keepalive=`wg show ${iface} persistent-keepalive | grep ${public_key} | awk '{print $2}'` + + # only process peers with endpoints and keepalive set + [ -z ${endpoint_host} ] && return 0; + [ -z ${persistent_keepalive} -o ${persistent_keepalive} = "off" ] && return 0; + + # skip IP addresses + # check taken from packages/net/ddns-scripts/files/dynamic_dns_functions.sh + local IPV4_REGEX="[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}" + local IPV6_REGEX="\(\([0-9A-Fa-f]\{1,4\}:\)\{1,\}\)\(\([0-9A-Fa-f]\{1,4\}\)\{0,1\}\)\(\(:[0-9A-Fa-f]\{1,4\}\)\{1,\}\)" + local IPV4=$(echo ${endpoint_host} | grep -m 1 -o "$IPV4_REGEX$") # do not detect ip in 0.0.0.0.example.com + local IPV6=$(echo ${endpoint_host} | grep -m 1 -o "$IPV6_REGEX") + [ -n "${IPV4}" -o -n "${IPV6}" ] && return 0; + + # re-resolve endpoint hostname if not responding for too long + last_handshake=`wg show ${iface} latest-handshakes | grep ${public_key} | awk '{print $2}'` + [ -z ${last_handshake} ] && return 0; + idle_seconds=$((`date +%s`-${last_handshake})) + [ ${idle_seconds} -lt 150 ] && return 0; + logger -t "wireguard_monitor" "${iface} endpoint ${endpoint_host}:${endpoint_port} is not responding for ${idle_seconds} seconds, trying to re-resolve hostname" + wg set ${iface} peer ${public_key} endpoint "${endpoint_host}:${endpoint_port}" +} + +# query ubus for all active wireguard interfaces +wg_ifaces=`ubus -S call network.interface dump | jsonfilter -e '@.interface[@.up=true]' | jsonfilter -a -e '@[@.proto="wireguard"].interface' | tr "\n" " "` + +# check every peer in every active wireguard interface +config_load network +for iface in $wg_ifaces; do + config_foreach check_peer_activity "wireguard_${iface}" "${iface}" +done