Wanmon is a lightweight daemon that continuously monitors the quality of your WAN/WWAN interfaces (latency, packet loss, jitter) and automatically switches the default route to the best available link. It prevents flapping via smoothing and hysteresis, and includes a clean web interface with LuCI integration.
- Multi‑interface monitoring – automatically detects all active WAN interfaces from the firewall zone.
- Quality metrics – measures median RTT, packet loss, and jitter (MAD) via ICMP pings.
- Intelligent decision engine – computes a score for each interface, applies smoothing and hysteresis to avoid unnecessary switching.
- Automatic failover – sets a primary default route and a backup route with a higher metric.
- Manual override – force a specific interface via CLI or web UI.
- Web interface – standalone HTML page + LuCI module for real‑time status and control.
- Lightweight – written in POSIX shell, depends only on
jq(and the standard OpenWrt toolset).
- OpenWrt 22.03 or later (tested on 22.03, 23.05)
jq– installed automatically by the IPK packageip(BusyBoxipor full version) – usually presentuci,ubus,logread– standard OpenWrt utilities
- Download the
.ipkfile from the Releases page. - Copy it to your router (e.g., via
scp). - Install it:
opkg install wanmon_1.0-1_all.ipk
The daemon will start automatically and enable itself on boot.
Clone this repository and run the build script:
git clone https://github.com/yourusername/wanmon.git
cd wanmon
chmod +x build-ipk.sh
./build-ipk.sh
This creates wanmon_1.0-1_all.ipk in the current directory. Install it with opkg install.
If you prefer to install files manually, use the provided wm-install.sh script (requires root):
chmod +x wm-install.sh
./wm-install.sh
The main configuration file is /etc/wanmon/config.json. It is created automatically on first start. You can edit it at any time – the daemon will pick up changes on the next cycle.
{
"interval": 60, # check interval (seconds)
"ping_host": "1.1.1.1", # target host for latency/loss tests
"ping_timeout": 2, # ping timeout (seconds)
"ping_samples": 5, # number of pings per measurement
"smooth_window": 5, # averaging window for scores
"hysteresis_threshold": 20, # minimum score difference to switch
"loss_divisor": 10, # divisor for loss penalty in score
"hard_loss_limit": 80, # loss% above which interface is "dead"
"dead_score": 99999, # artificially high score for dead iface
"default_metric": 100, # default bias (metric) for new interfaces
"backup_metric": 20 # metric for the backup default route
}
Understanding the parameters:
smooth_window– larger values make the system more conservative.hysteresis_threshold– prevents flapping; increase it to reduce unnecessary switches.loss_divisor– controls how much packet loss affects the score.hard_loss_limit– if packet loss exceeds this, the interface is considered dead regardless of latency.
Interface weights (/etc/wanmon/ifaces.json)
This file is automatically generated from your active WAN interfaces. You can manually edit it to assign a bias (less = more preferred). For example:
{
"wan": 0,
"wwan": 20
}
This tells wanmon to prefer wan unless its quality degrades significantly.
/etc/init.d/wanmon {start|stop|restart|status}
Or use the direct script:
/usr/bin/wm-daemon.sh [--start|--stop|--status|--init|--remove]
To force a specific interface as the default route:
/usr/bin/wm-apply.sh <iface>
Example: wm-apply.sh wwan
The wm-help.sh tool provides detailed information:
wm-help.sh --all # show everything
wm-help.sh --route --pretty # show current routes in human-friendly format
wm-help.sh --decision # show scores and preferred interface
Access http://<router-ip>/wanmon.html in your browser. It shows real‑time status, telemetry, scores, logs, and allows start/stop/restart and manual switching.
If you have LuCI installed, a new menu item appears under Services → WAN Monitor with the same functionality.
- Measurement – every
intervalseconds,wm-state.shpingsping_hostthrough each interface, collecting RTT and loss. - Smoothing – scores are stored per interface and averaged over
smooth_windowmeasurements. - Decision –
wm-select.shcomputes a score for each interface:
score = (latency + jitter) + (loss² / loss_divisor) + bias
Ifloss >= hard_loss_limit, score =dead_score.
The interface with the lowest score becomes the preferred one, unless hysteresis prevents the switch. - Application –
wm-apply.shupdates the kernel routing table: primary default route via the preferred interface, and a backup route via the first other interface (withbackup_metric).
All state files are stored in /tmp/wanmon/ and are cleaned on reboot.
All messages are logged to the system log with tag wm-*. View them with:
logread | grep wm-
If you installed via IPK:
opkg remove wanmon
If manually installed, run the built‑in removal script:
/usr/bin/wm-remove.sh
- Prevent false positives under heavy load – increase
smooth_window,hysteresis_threshold,ping_samples. - Prefer wired over wireless – set a higher
biasfor the wired interface. - Use a local ping target – choose a reliable host (e.g., your next‑hop router or a well‑known DNS) close to you.
Bug reports, feature requests, and pull requests are welcome. Please use the issue tracker.
This project is licensed under the MIT License – see the LICENSE file for details.
Developed by Pavel Bashkardin. Special thanks to the OpenWrt community for their invaluable tools and documentation.
Enjoy stable, automatic WAN failover! 🚀