<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pavel Bashkardin</title>
    <description>The latest articles on DEV Community by Pavel Bashkardin (@ng256).</description>
    <link>https://dev.to/ng256</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4015151%2F2b8a16d4-469a-4c35-9f97-63851ff16b4f.jpg</url>
      <title>DEV Community: Pavel Bashkardin</title>
      <link>https://dev.to/ng256</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ng256"/>
    <language>en</language>
    <item>
      <title>Wan Monitor - Tiny Failover Controller for OpenWrt</title>
      <dc:creator>Pavel Bashkardin</dc:creator>
      <pubDate>Sat, 04 Jul 2026 14:48:34 +0000</pubDate>
      <link>https://dev.to/ng256/wan-monitor-tiny-failover-controller-for-openwrt-4o8e</link>
      <guid>https://dev.to/ng256/wan-monitor-tiny-failover-controller-for-openwrt-4o8e</guid>
      <description>&lt;p&gt;How I Built a Tiny WAN Failover Tool for My 8‑MB OpenWrt Router (and Why mwan3 Wasn’t an Option)&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Problem: When the Internet Goes Down, So Does My Home Network
&lt;/h2&gt;

&lt;p&gt;Like many of us, I rely on a wired broadband connection for my home internet. But things happen—the provider goes offline for maintenance, a cable gets cut, or (let’s be honest) you forget to pay the bill. When that happens, I wanted my router to automatically switch to a backup connection: a Wi‑Fi hotspot from my phone.&lt;/p&gt;

&lt;p&gt;I’m running &lt;strong&gt;OpenWrt&lt;/strong&gt; on a tiny &lt;strong&gt;Xiaomi Mi Router C4&lt;/strong&gt; . It’s a cheap, reliable device, but it comes with severe storage constraints. Here’s what the filesystem looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/root                 6912      6912         0 100% /rom
tmpfs                    28584       336     28248   1% /tmp
/dev/mtdblock9            5760      5628       132  98% /overlay
overlayfs:/overlay        5760      5628       132  98% /
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only &lt;strong&gt;~5.7 MB&lt;/strong&gt; of writable flash are available, and I’m already using 98% of it. Every kilobyte counts. I needed a solution that would fit into this cramped space and still do the job reliably.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Existing Solutions: mwan3 – The Obvious Choice
&lt;/h2&gt;

&lt;p&gt;The most popular tool for multi‑WAN management on OpenWrt is &lt;strong&gt;mwan3&lt;/strong&gt;. It’s mature, well‑documented, and offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load balancing across multiple connections&lt;/li&gt;
&lt;li&gt;Policy‑based routing (e.g., specific IPs or ports through specific interfaces)&lt;/li&gt;
&lt;li&gt;Advanced failover with custom tracking (ICMP, DNS, ARP)&lt;/li&gt;
&lt;li&gt;A full LuCI web interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On paper, mwan3 should be able to handle my failover scenario. But when I looked at its requirements, I hit a wall.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why mwan3 Didn’t Fit
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Storage footprint&lt;/strong&gt;: mwan3 itself is not huge, but its dependency chain (iptables extensions, tracking modules, and the LuCI UI) quickly grows beyond what I could comfortably afford on an 8‑MB flash device. Installing everything would have consumed the little remaining space I had.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory overhead&lt;/strong&gt;: mwan3 introduces persistent tracking processes and conntrack load, which can become noticeable on low‑memory devices (64 MB RAM) under heavy NAT usage. It’s not “several MB” per se, but the cumulative effect of conntrack and multiple trackers can strain the system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: Configuring mwan3 involves defining interfaces, members, policies, and tracking rules—powerful, but overkill for my simple “switch to backup when primary is down” use case.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also considered other lightweight options like &lt;code&gt;ifplugd&lt;/code&gt; or custom scripts that watch the default gateway, but they either lacked quality‑based switching or required too much hand‑tuning.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Why I Decided to “Reinvent the Wheel”
&lt;/h2&gt;

&lt;p&gt;I realised that my requirements were actually quite simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Periodically check if the primary interface is still usable.&lt;/li&gt;
&lt;li&gt;Measure not just “up/down”, but also &lt;strong&gt;latency&lt;/strong&gt;, &lt;strong&gt;packet loss&lt;/strong&gt;, and &lt;strong&gt;jitter&lt;/strong&gt;—so I can switch before the link becomes unusable.&lt;/li&gt;
&lt;li&gt;Automatically change the default route to the best available interface.&lt;/li&gt;
&lt;li&gt;Be &lt;em&gt;extremely&lt;/em&gt; lightweight—preferable under 100 KB of flash, with no kernel modules or extra daemons.&lt;/li&gt;
&lt;li&gt;Provide a basic web interface to see status and manually override.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing on the market met all these criteria at once. So I decided to write my own tool. I called it &lt;strong&gt;wanmon&lt;/strong&gt; (WAN Monitor).&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The Birth of Wanmon: A Minimalist Approach
&lt;/h2&gt;

&lt;p&gt;Wanmon is a collection of shell scripts that work together in three independent stages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Measurement&lt;/strong&gt; (&lt;code&gt;wm-state.sh&lt;/code&gt;) – sends pings to a configurable host and records latency, loss, and jitter for each interface.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision&lt;/strong&gt; (&lt;code&gt;wm-select.sh&lt;/code&gt;) – computes a quality score for each interface, applies smoothing and hysteresis, and picks the best candidate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Application&lt;/strong&gt; (&lt;code&gt;wm-apply.sh&lt;/code&gt;) – updates the kernel routing table accordingly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation of concerns makes wanmon a mini‑SD‑WAN controller in its own right. The key idea is that connectivity is not binary. A WAN link can be “up” but still unusable due to high latency or packet loss. Wanmon treats network quality as a &lt;strong&gt;continuous cost function&lt;/strong&gt; rather than a reachability flag.&lt;/p&gt;

&lt;p&gt;The score for each interface is defined as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;latency&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;jitter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="err"&gt;²&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;loss_divisor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;bias&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The lowest score wins. Smoothing and hysteresis prevent flapping. The entire system uses no iptables, no conntrack, and no heavy dependencies—just &lt;code&gt;jq&lt;/code&gt; for JSON parsing (which I already had installed). The total size of all scripts and the web interface is &lt;strong&gt;~80 KB&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Wanmon Compares to mwan3
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;mwan3&lt;/th&gt;
&lt;th&gt;wanmon&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Storage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;≥1–2 MB (with dependencies)&lt;/td&gt;
&lt;td&gt;&amp;lt;100 KB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RAM usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate (daemon + conntrack + trackers)&lt;/td&gt;
&lt;td&gt;Minimal (fork‑exec loop)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configuration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complex (policies, members, trackers)&lt;/td&gt;
&lt;td&gt;Single JSON file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Primary use&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Load balancing + failover&lt;/td&gt;
&lt;td&gt;Failover only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Decision logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reachability (up/down)&lt;/td&gt;
&lt;td&gt;Latency + loss + jitter (cost‑based)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Web interface&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Heavy LuCI integration&lt;/td&gt;
&lt;td&gt;Lightweight standalone HTML or single LuCI page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Modifiability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hard (C/shell, complex architecture)&lt;/td&gt;
&lt;td&gt;Easy (simple shell, tweakable in minutes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Policy‑based routing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Per‑connection tracking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;QoS integration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Possible via scripts&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This table shows that wanmon is not a replacement for mwan3 in all scenarios—it deliberately trades flexibility for minimalism.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Wanmon in Action – A Real‑World Setup
&lt;/h2&gt;

&lt;p&gt;On my Xiaomi C4, I connected my phone’s Wi‑Fi hotspot as a second WAN interface (via a USB‑to‑Wi‑Fi dongle or a travel router). Wanmon automatically detects both the wired PPPoE interface (&lt;code&gt;wan&lt;/code&gt;) and the hotspot interface (&lt;code&gt;wwan&lt;/code&gt;). I configured a &lt;code&gt;bias&lt;/code&gt; (metric) to prefer the wired link as long as its quality is acceptable.&lt;/p&gt;

&lt;p&gt;When the wired connection degrades (e.g., ISP outage), wanmon notices the increased latency or packet loss. The score rises, and after the hysteresis threshold is crossed, it switches the default route to the hotspot. Once the wired link recovers, it switches back—smoothly and without user intervention.&lt;/p&gt;

&lt;p&gt;The web interface at &lt;code&gt;http://router-ip/wanmon.html&lt;/code&gt; gives me a clear dashboard showing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Daemon status&lt;/li&gt;
&lt;li&gt;Current default route&lt;/li&gt;
&lt;li&gt;Live scores and telemetry (latency, loss, jitter) per interface&lt;/li&gt;
&lt;li&gt;A dropdown to manually force any interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this fits within the 5.7 MB overlay—leaving room for other essential tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Conclusion: Sometimes, Less Is More
&lt;/h2&gt;

&lt;p&gt;mwan3 is a fantastic tool for routers with ample resources and complex routing needs. But for devices like the Xiaomi C4—with just 8 MB flash and 64 MB RAM—it’s often overkill. Wanmon proves that you don’t need a heavyweight solution to get reliable, intelligent WAN failover.&lt;/p&gt;

&lt;p&gt;If you’re in a similar situation—struggling to squeeze more functionality into a small OpenWrt device—I encourage you to try wanmon. It’s open source, easy to customise, and it just works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check it out on GitHub:&lt;/strong&gt; &lt;a href="https://github.com/ng256/WanMonitor" rel="noopener noreferrer"&gt;https://github.com/ng256/WanMonitor&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have questions or ideas? Feel free to open an issue or submit a pull request. Let’s keep our routers smart, even when they’re small.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>openwrt</category>
      <category>networkfailover</category>
      <category>embeddedlinux</category>
      <category>wanmon</category>
    </item>
  </channel>
</rss>
