User Tools

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
gentoo:wireguard [2025/02/06 07:27] willygentoo:wireguard [2026/03/19 08:21] (current) – [Watchdog] willy
Line 1: Line 1:
-====== WireGuard ======+====== J) WireGuard ======
  
 [[https://en.wikipedia.org/wiki/WireGuard|WireGuard]] is a modern VPN tunnel solution which is quickly taking the place of OpenVPN. Some of the strong key points of WireGuard are, beside a supposedly more secure implementation, the ease of setup and how it simply merge with the overall linux network management. [[https://en.wikipedia.org/wiki/WireGuard|WireGuard]] is a modern VPN tunnel solution which is quickly taking the place of OpenVPN. Some of the strong key points of WireGuard are, beside a supposedly more secure implementation, the ease of setup and how it simply merge with the overall linux network management.
Line 71: Line 71:
 </code> </code>
  
-===== Remote access =====+===== Watchdog =====
  
-There are tons of WireGuard tutorials online on how to use WireGuard to connect your mobile device securely to your home networki do not plan to cover this topic here.+In my experiencewhen the main router reboots or the internet connection is switched, the wireguard tunnel might hang up for a very long time. I am not sure why this happen, it shouldn't, specially with the //PersistentKeepAlive = 25// setting, but it does anyway
  
 +To ensure this doesn't happen, i have written a small OpenRC script that pings the Wireguard remote server and restart the wg-quick interface when the ping fails. Drop the following script as **/etc/init.d/tunnel-watchdog**:
 +<file - tunnel-watchdog>
 +#!/sbin/openrc-run
  
-===== Port Forwarding =====+description="Dead‑man switch: ping a host, restart a service if ping fails"
  
-Using WireGuard for port-forwarding between an external, public accessible host, and an internal non-accessible host (like behind a CGNAT) is a less known topic and i will cover it here.+# The services you want to restart 
 +SERVICES="wg-quick.wg0 wg-quick.wg1" 
 +PING_HOST="10.70.0.2" 
 +LOG="/var/log/tunnel-watchdog.log" 
 +FAIL_COUNT_LIMIT=5 
 +PING_TIMEOUT=1 
 +PING_COUNT=1
  
-You will need to use NFTables, see [[[[gentoo:nft|here]] for more details to better understand the following.+restart_service() { 
 +    for i in ${SERVICES} 
 +    do 
 +        einfo "Restarting $i" 
 +        /etc/init.d/$i restart 
 +    done 
 +}
  
-Assumptions: +depend() { 
-  * You have one **internal** host which is behind CGNAT, and is not accessible from the internet +    need net 
-  * You have one **external** host which has a public IP address +}
-  * Both hosts have WireGuard setup according to the configuration above +
-  * Internal host expose port 22, 80 and 8443 +
-  * External host needs to route those three ports to the internal host +
-  * The WireGuard subnet is //10.100.0.0/24// with internal host being 10.100.0.1 and external host 10.100.0.2 +
-  * External host **public** network interface is called **enp1s0** +
-  * Both hosts WireGuard network iunterface is called **wg0**+
  
-What we need to do is create nftable rules to ensure that: +start() { 
-  packets reaching external host on enp1s0 on port 2022 get routed to 10.100.0.port 22 +    ebegin "Starting tunnel-watchdog daemon" 
-  * packets reaching external host on enp1s0 on port 80 get routed to 10.100.0.port 80 +    echo $(date)" Starting tunnel watchdog on IP $PING_HOST"  >> ${LOG} 
-  * packets reaching external host on enp1s0 on port 443 get routed to 10.100.0.1 port 8443 +    while : ; do 
-  * return packets from the internal host get properly re-routed to the original sender out from enp1s0+        # Perform a quick ping.  -q quiet, -c N packets, -W T timeout 
 +        if ! ping -q -c ${PING_COUNT} -W ${PING_TIMEOUT} ${PING_HOST} >/dev/null 2>&1; then 
 +            fail_count=$((fail_count + 1)) 
 +            echo $(date)" Ping to ${PING_HOST} failed (attempt ${fail_count})" >> ${LOG} 
 +        else 
 +            fail_count=
 +        fi
  
-**Note:** see [[selfhost:nginx|here]] on why i use port 8443 instead of port 443 on the internal server. This is to differentiate //internal// connections, which have lesser security, from //external// connections which get additional SSO layers.+        # If we hit the threshold, restart 
 +        if "${fail_count}" -ge "${FAIL_COUNT_LIMIT}" ]; then 
 +            echo $(date)" Consecutive failures reached ${FAIL_COUNT_LIMIT}restarting ${SERVICES}" >> ${LOG} 
 +            restart_service 
 +            fail_count=0 
 +        fi
  
-What we need: +        # Wait a bit before the next check 
-  * A dedicated table called **wg** +        sleep 5 
-  * A **prerouting** chain to apply DNAT to incoming packes  +    done & 
-  * Rules to route port 2022/80/443 to the wg tunnel ports +    PID=$! 
-  * A **postrouting** chain to ensure that all reply packets are properly SNAT back to outside +    echo ${PID} > /var/run/tunnel-watchdog.pid 
-  * Return masquerading rules to ensure the return packets get sent back out of enp1s0+    eend 0 
 +}
  
-Create the wg table: +stop() { 
-<code bash+    ebegin "Stopping ping‑restart daemon" 
-nft add table ip wg +    if [ -f /var/run/tunnel-watchdog.pid ]; then 
-</code>+        PID=$(cat /var/run/tunnel-watchdog.pid) 
 +        kill -9 "${PID}" 2>/dev/null 
 +        rm /var/run/tunnel-watchdog.pid 
 +    else 
 +        eend 255 
 +    fi 
 +    eend 0 
 +} 
 +</file>
  
-Create the base chains:+Now make it executable add to the runlevel default and start it:
 <code bash> <code bash>
-nft 'add chain ip wg prerouting { type nat hook prerouting priority -100 ; }' +chmod +x /etc/init.d/tunnel-whatchdog 
-nft 'add chain ip wg postrouting { type nat hook postrouting priority 100 ; }'+rc-update add tunnel-whatchdog default 
 +/etc/init.d/tunnel-whatchdog start
 </code> </code>
  
-Create the in-bound rules: +As a final note, don't forget to put log file **/var/log/tunnel-watchdog.log** in your logrotate facility.
-<code bash> +
-# nft 'add rule ip wg prerouting iifname enp1s0 tcp dport 80 counter' # <<optional for debugging purposes +
-# nft 'add rule ip wg prerouting iifname enp1s0 tcp dport 443 counter' # <<- optional for debugging purposes +
-# nft 'add rule ip wg prerouting iifname enp1s0 tcp dport 2022 counter' # <<- optional for debugging purposes +
-nft 'add rule ip wg prerouting iifname enp1s0 dnat to tcp dport map { 2022 : 10.100.0.1 . 22 }' +
-nft 'add rule ip wg prerouting iifname enp1s0 dnat to tcp dport map { 80 : 10.100.0.1 . 80 }' +
-nft 'add rule ip wg prerouting iifname enp1s0 dnat to tcp dport map { 443 : 10.100.0.1 . 8443 }' +
-</code>+
  
-Create the SNAT return rule (the counter rule is only for debugging, you can omit that rule): 
-<code bash> 
-# nft 'add rule ip wg postrouting ip daddr 10.100.0.1 counter' # <<- optional for debugging purposes 
-nft 'add rule ip wg postrouting ip daddr 10.100.0.1 masquerade' 
-</code> 
- 
-This is the resulting NFTables setup: 
-<code bash> 
-nft list table wg 
-table ip wg { 
-        chain prerouting { 
-                type nat hook prerouting priority dstnat; policy accept; 
-                iifname "enp1s0" tcp dport 443 counter packets 100 bytes 5712 
-                iifname "enp1s0" tcp dport 2022 counter packets 0 bytes 0 
-                iifname "enp1s0" tcp dport 80 counter packets 0 bytes 0 
-                iifname "enp1s0" dnat ip to tcp dport map { 2022 : 10.100.0.1 . 22 } 
-                iifname "enp1s0" dnat ip to tcp dport map { 80 : 10.100.0.1 . 80 } 
-                iifname "enp1s0" dnat ip to tcp dport map { 443 : 10.100.0.1 . 8443 } 
-        } 
- 
-        chain postrouting { 
-                type nat hook postrouting priority srcnat; policy accept; 
-                ip daddr 10.100.0.1 counter packets 390 bytes 25945 
-                ip daddr 10.100.0.1 masquerade 
-        } 
-} 
-</code> 
  
 +===== Remote access =====
  
 +There are tons of WireGuard tutorials online on how to use WireGuard to connect your mobile device securely to your home network, i do not plan to cover this topic here.