OPNsense WAN Watchdog with Cooldown, Log Rotation & Cron Integration. PART 1

The following guide is for OPNsense 25.7.7_4

In part 1 we will explore the creation of a cron activated recovery script.

A complete guide to automatically recover DHCP outages

Some home internet providers modem-mode DHCP server sometimes stops responding to DHCPREQUEST renewals.
OPNsense keeps the WAN “up”, but the actual connection silently dies until reboot.

This tutorial shows how to build a robust WAN watchdog that:

  • Monitors internet connectivity
  • Logs successes and failures
  • Automatically reconfigures the WAN interface
  • Reboots as last resort
  • Enforces a 30-minute cooldown to avoid reboot loops
  • Integrates cleanly with configd
  • Schedules via GUI cron
  • Rotates logs automatically at midnight

1. Create the Watchdog Script

Create the script:

nano /root/gw_watchdog.sh

Paste this full version (with cooldown protection):

#!/bin/sh
# OPNsense WAN watchdog (multi-host)
# Consider WAN "up" if ANY host responds.

WAN_IF="igb0"                             # << your WAN interface
HOSTS="1.1.1.1 8.8.8.8"                   # << add/remove as you like

LOG_OK="/var/log/gw_watchdog.log"
LOG_FAIL="/var/log/gw_watchdog.fail.log"

PING="/sbin/ping"                         # FreeBSD/OPNsense ping path

# ===========================
# COOLDOWN PROTECTION (NEW)
# ===========================
LOCK="/var/run/gwwatchdog.lock"

# >>> Change this value to adjust cooldown period <<<
COOLDOWN_SECONDS=1800    # 1800 seconds = 30 minutes
# ===========================
# END COOLDOWN SECTION
# ===========================

log_ok() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_OK"
}

log_fail() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG_FAIL"
}

check_any_host() {
  for H in $HOSTS; do
    $PING -c 1 -W 2000 "$H" >/dev/null 2>&1
    if [ $? -eq 0 ]; then
      log_ok "✔️  Reachable: $H"
      return 0
    fi
  done
  return 1
}

# ---- MAIN FLOW ----

# If WAN is working: normal log, exit
if check_any_host; then
  exit 0
fi

# ===========================
# COOLDOWN CHECK
# ===========================
if [ -f "$LOCK" ]; then
  LAST_TS=$(cat "$LOCK" 2>/dev/null || echo 0)
  NOW_TS=$(date +%s)
  DIFF=$((NOW_TS - LAST_TS))

  if [ "$DIFF" -lt "$COOLDOWN_SECONDS" ]; then
    log_fail "⏳ Cooldown active (${DIFF}s since last action, threshold ${COOLDOWN_SECONDS}s). Skipping WAN recovery."
    exit 0
  fi
fi
# ===========================
# END COOLDOWN CHECK
# ===========================

log_fail "⚠️  All probes failed ($HOSTS). Attempting WAN reconfigure on $WAN_IF..."

# Record that we attempted recovery
date +%s > "$LOCK"

/usr/local/sbin/configctl interface reconfigure wan >/dev/null 2>&1
sleep 20

# Check connectivity again
if check_any_host; then
  log_fail "✅ Internet restored after WAN reconfigure."
  exit 0
fi

# Still no internet — last resort
log_fail "❌ Still no connectivity after WAN reconfigure. Rebooting firewall..."
/sbin/shutdown -r now

Make it executable:

chmod +x /root/gw_watchdog.sh

2. Create a configd Action for GUI/Cron Use

Create a configd action so OPNsense can run the script:

nano /usr/local/opnsense/service/conf/actions.d/actions_gwwatchdog.conf

Paste:

[run]
command:/root/gw_watchdog.sh
type:script
message:running WAN watchdog script
description:Run WAN watchdog scriptCode language: JavaScript (javascript)

Restart configd:

service configd restart

Test:

configctl gwwatchdog run

Check log:

cat /var/log/gw_watchdog.logCode language: JavaScript (javascript)

3. Add Cron Job via OPNsense GUI

Go to:

System → Settings → Cron → +

Create:

  • Command: “Run WAN watchdog script” (the new configd action)
  • Minutes: */5
  • Hours: *
  • Days: *
  • Months: *
  • Weekdays: *

Save & Apply.

Cron now runs the script every 5 minutes.

Your user-generated cron file will appear at:

/var/cron/tabs/nobodyCode language: JavaScript (javascript)

With a line similar to:

*/5 * * * * /usr/local/sbin/configctl -d -- 'gwwatchdog run'Code language: JavaScript (javascript)

4. Enable Automatic Log Rotation

Create:

nano /etc/newsyslog.conf.d/gw_watchdog.conf

Paste:

/var/log/gw_watchdog.log      root:wheel  600  7   *   @T00  Z
/var/log/gw_watchdog.fail.log root:wheel  600  30  *   @T00  ZCode language: JavaScript (javascript)

Test rotation rules:

newsyslog -n -F

This will show what would happen at midnight.

5. Verifying Everything Works

Check OK log

tail -n 20 /var/log/gw_watchdog.logCode language: JavaScript (javascript)

Should show:

✔️ Reachable: 1.1.1.1Code language: CSS (css)

every 5 minutes.

Check failure log

tail -n 20 /var/log/gw_watchdog.fail.logCode language: JavaScript (javascript)

Shows only events like:

⚠️  All probes failed (1.1.1.1 8.8.8.8). Attempting WAN reconfigure...
⏳ Cooldown active (300s since last action, threshold 1800s). Skipping.
❌ Still no connectivity. Rebooting firewall...Code language: CSS (css)

Check lock file

cat /var/run/gwwatchdog.lockCode language: JavaScript (javascript)

Should show a recent UNIX timestamp only when action was taken.

6. Notes & Best Practices

  • Cooldown prevents repeated WAN resets during full ISP outages
  • LOG_OK grows slowly (1 line / 5 min)
  • LOG_FAIL stays empty unless something breaks
  • Midnight rotation keeps logs tidy
  • Script is safe even if cron runs during reconfigure
  • WAN reconfigure fixes most ISP DHCP stalls

Similar Posts

Leave a Reply