Skip to content

Instantly share code, notes, and snippets.

@tsjk
Last active September 11, 2023 06:46
Show Gist options
  • Save tsjk/65e48537d715fa2bba069ddfafbeffd6 to your computer and use it in GitHub Desktop.
Save tsjk/65e48537d715fa2bba069ddfafbeffd6 to your computer and use it in GitHub Desktop.
Fix of WireGuard routing confusion on OpenWRT
#!/bin/sh
# Intermittently, the routing of WireGuard datagrams seem to become confused, leading to temporarily hung connections.
# This script aims to remedy this - assuming that the OpenWRT system is a
# WireGuard peer that uses the port(s) listed in WG_PORTS. E.g. (/etc/config/network):
# config interface 'wg0'
# option proto 'wireguard'
# option listen_port '51820'
# ...
#
# This script can be included in /etc/firewall by e.g (assuming it is placed at /etc/wireguard/openwrt-wg0-firewall.sh):
# config include 'wireguard'
# option path '/etc/wireguard/openwrt-wg0-firewall.sh'
# option reload '1'
WAN_DEVICE=`ifstatus wan 2> /dev/null | jsonfilter -e '@["device"]'`
WAN_IP_ADDRESS=`ifstatus wan 2> /dev/null | jsonfilter -e '@["ipv4-address"][0].address'`
WAN_GATEWAY=`ifstatus wan 2> /dev/null | jsonfilter -e '@["route"][0].nexthop'`
WG_PORTS="51820"
rm_wg_mark_rules() {
t="mangle"; c="OUTPUT"
x=`iptables -t ${t} -n -v --line-numbers -L ${c} | awk '/\/\* wg0:'"${1}"' \*\// { print $1 }' | head -n 1`
while echo "${x}" | grep -q -E '^[1-9][0-9]*$'; do
iptables -t ${t} -D ${c} ${x} > /dev/null 2>&1
x=`iptables -t ${t} -n -v --line-numbers -L ${c} | awk '/\/\* wg0:'"${1}"' \*\// { print $1 }' | head -n 1`; done
}
add_wg_mark_rules() {
echo "${1}" | grep -q -E '^[1-9][0-9]*$' || return 1
t="mangle"; c="OUTPUT"
iptables -t ${t} -I ${c} 1 -m udp -p udp --sport ${1} -m set ! --match-set iana_ipv4_special_registry dst \
-m comment --comment "wg0:${1}" -j MARK --set-mark 0x1000000/0x1000000
}
rm_wg_rules() {
t="nat"; c="PREROUTING"
x=`iptables -t ${t} -n -v --line-numbers -L ${c} | awk '/\/\* wg0:'"${1}"' \*\// { print $1 }' | head -n 1`
while echo "${x}" | grep -q -E '^[1-9][0-9]*$'; do
iptables -t ${t} -D ${c} ${x} > /dev/null 2>&1
x=`iptables -t ${t} -n -v --line-numbers -L ${c} | awk '/\/\* wg0:'"${1}"' \*\// { print $1 }' | head -n 1`; done
}
add_wg_rules() {
echo "${1}" | grep -q -E '^[1-9][0-9]*$' || return 1
t="nat"; c="PREROUTING"
iptables -t ${t} -I ${c} 1 -i ${WAN_DEVICE} -d ${WAN_IP_ADDRESS} -p udp --dport ${1} \
-m comment --comment "wg0:${1}" -j ACCEPT > /dev/null 2>&1
}
if [ -s /etc/iana-ipv4-special-registry.txt ]; then
if ipset -L iana_ipv4_special_registry > /dev/null 2>&1; then
ipset -F iana_ipv4_special_registry
else
ipset -N iana_ipv4_special_registry nethash
fi
# curl -s 'https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.txt' | \
# grep -Po '(?<=^ )[0-9]+(\.[0-9]+){3}/[0-9]+(?=\s)' | iprange --optimize > /etc/iana-ipv4-special-registry.txt
cat /etc/iana-ipv4-special-registry.txt | while read -r REPLY; do ipset -A iana_ipv4_special_registry ${REPLY}; done
fi
if [ -n "${WAN_GATEWAY}" ] && ipset -L iana_ipv4_special_registry > /dev/null 2>&1; then
ip route flush table 101 > /dev/null 2>&1; ip route add default via ${WAN_GATEWAY} table 101
ip rule del fwmark 0x1000000 table 101 prio 11 > /dev/null 2>&1; ip rule add fwmark 0x1000000 table 101 prio 11
rm_wg_mark_rules
for p in ${WG_PORTS}; do
add_wg_mark_rules ${p}
done
fi
# This is not strictly necessary for remedying the hung connection problem, but helps
# if DMZ is set on the router and one wants to exclude WireGuard traffic from hitting the DMZ box.
if [ -n "${WAN_DEVICE}" -a -n "${WAN_IP_ADDRESS}" ]; then
rm_wg_rules ${p}
for p in ${WG_PORTS}; do
add_wg_rules ${p}
done
conntrack -F > /dev/null 2>&1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment