mwan4 - Multi-WAN with nftables
mwan4 - Multi-WAN with nftables
Migration from mwan3 to mwan4
Configuration File Changes
The mwan4 configuration file format is mostly backward compatible with mwan3, with the following changes:
1. flush_conntrack Option Format (Breaking Change)
mwan3 format:
config interface 'wan'
option flush_conntrack 'always' # or 'never'
mwan4 format:
config interface 'wan'
list flush_conntrack 'ifup' # optional
list flush_conntrack 'ifdown' # optional
Migration: The uci-defaults script (/etc/uci-defaults/90-mwan4) automatically converts:
always→ adds bothifupandifdownto the listnever→ removes the option entirely
This change provides more granular control over when connection tracking is flushed.
2. family Configuration on Interfaces - Dual-Stack Support (New)
Single family per interface (legacy approach):
config interface 'wan'
option enabled '1'
list family 'ipv4'
list track_ip '1.1.1.1'
config interface 'wan6'
option enabled '1'
list family 'ipv6'
list track_ip '2606:4700:4700::1111'
Dual-stack on single interface (NEW - recommended):
config interface 'wan'
option enabled '1'
list family 'ipv4'
list family 'ipv6'
list track_ip '1.1.1.1' # IPv4 tracking
list track_ip '2606:4700:4700::1111' # IPv6 tracking
option reliability '2'
Benefits of dual-stack configuration:
- Single configuration for both IPv4 and IPv6
- No duplicate settings to maintain
- Automatic family detection from track IPs
- Independent tracking per family
- Single interface ID with family-specific internal chains
Backward compatibility: The old option family format is automatically migrated to list family by the uci-defaults script.
3. Renamed Config Sections: member → route, policy → strategy (Breaking Change)
mwan3 / old mwan4 format:
config member 'wan_m1_w3'
option interface 'wan'
option metric '1'
option weight '3'
config policy 'balanced'
list use_member 'wan_m1_w3'
config rule 'https'
option use_policy 'balanced'
New mwan4 format:
config route 'wan_m1_w3'
option interface 'wan'
option metric '1'
option weight '3'
config strategy 'balanced'
list use_route 'wan_m1_w3'
config rule 'https'
option use_strategy 'balanced'
Summary of renames:
| Old | New | Description |
|—–|—–|————-|
| config member | config route | Weighted route entry (interface + metric + weight) |
| config policy | config strategy | Routing strategy (how to distribute/failover traffic) |
| list use_member | list use_route | Route references within a strategy |
| option use_policy | option use_strategy | Strategy reference within a rule |
Migration: The uci-defaults script (/etc/uci-defaults/92-mwan4-rename) automatically converts old section types and option names in-place.
4. family on Rules Uses List Format (New)
Allows rules to be IPv4 or IPv6 specific (using list format):
config rule 'default_rule_v4'
option dest_ip '0.0.0.0/0'
option use_strategy 'balanced'
list family 'ipv4'
config rule 'default_rule_v6'
option dest_ip '::/0'
option use_strategy 'balanced'
list family 'ipv6'
Rules without a family list will apply to both IPv4 and IPv6 (if the rule is compatible with both).
Migration: The uci-defaults script automatically converts the old option family format to list family.
5. mmx_mask Now Configurable (New)
Customizable packet marking mask:
config globals 'globals'
option mmx_mask '0x3F00'
Previously hardcoded, the marking mask can now be customized in the globals section. This allows integration with other routing systems that may use different parts of the packet mark.
Default value: 0x3F00 (supports up to 63 interfaces)
Unchanged Configuration Sections
The following configuration sections remain fully compatible:
- Interface tracking options:
track_ip,reliability,count,timeout,interval,down,up,size,max_ttl,failure_interval,recovery_interval,check_quality,failure_latency,recovery_latency,failure_loss,recovery_loss - Route definitions (formerly member):
interface,metric,weight - Strategy definitions (formerly policy):
use_routelists,last_resort - Rule structure:
sticky,timeout,dest_port,src_port,dest_ip,src_ip,proto,use_strategy,ipset,logging
Example Migration
mwan3 config:
config interface 'wan'
option enabled '1'
list track_ip '1.1.1.1'
option flush_conntrack 'always'
mwan4 config (after automatic migration):
config interface 'wan'
option enabled '1'
list family 'ipv4'
list track_ip '1.1.1.1'
list flush_conntrack 'ifup'
list flush_conntrack 'ifdown'
Dual-Stack Configuration Example
Here’s a complete example showing how to configure a dual-stack WAN interface with both IPv4 and IPv6:
config interface 'wan'
option enabled '1'
list family 'ipv4'
list family 'ipv6'
list track_ip '1.1.1.1'
list track_ip '8.8.8.8'
list track_ip '2606:4700:4700::1111'
list track_ip '2001:4860:4860::8888'
option reliability '2'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config route 'wan_m1_w1'
option interface 'wan'
option metric '1'
option weight '1'
config strategy 'balanced'
list use_route 'wan_m1_w1'
config rule 'default_rule_v4'
option dest_ip '0.0.0.0/0'
option use_strategy 'balanced'
list family 'ipv4'
config rule 'default_rule_v6'
option dest_ip '::/0'
option use_strategy 'balanced'
list family 'ipv6'
How it works:
- The interface spawns two tracking instances:
track_wan_ipv4andtrack_wan_ipv6 - IPv4 track IPs (1.1.1.1, 8.8.8.8) are automatically used for IPv4 tracking
- IPv6 track IPs (2606:…, 2001:…) are automatically used for IPv6 tracking
- Each family maintains independent online/offline status
- nftables chains are created per family:
mwan4_iface_in_wan_ipv4andmwan4_iface_in_wan_ipv6 - Status is reported separately per family:
mwan4 statuswill show both
nftables Integration
mwan4 integrates with firewall4 by writing nftables rules into the shared inet fw4 table. All chains and sets use the mwan4_ prefix.
Generated nft Files
mwan4 generates two persistent nftables files that are loaded by fw4 via the ruleset-post mechanism:
| File | Description |
|---|---|
/usr/share/nftables.d/ruleset-post/10-mwan4.nft |
Dynamic content rebuilt on hotplug events. Combines base chains and sets (mwan4_prerouting, mwan4_output, mwan4_ifaces_in, connected/custom/dynamic IP sets for both IPv4 and IPv6), per-interface chains (e.g. mwan4_iface_in_wan_ipv4, mwan4_iface_in_wan_ipv6), and strategy chains (e.g. mwan4_strategy_balanced_ipv4). |
/usr/share/nftables.d/ruleset-post/11-mwan4-rules.nft |
User rule chains (mwan4_rules_ipv4, mwan4_rules_ipv6) that map traffic matching criteria (dest/src IP, port, protocol) to strategy chains. Generated at init time and includes sticky session sets when configured. |
Runtime Temp File
| File | Description |
|---|---|
/var/run/mwan4.nft.combined |
Temporary file used to validate the combined ruleset (nft -c -f) before installing the per-target files. Removed after each operation. |
nftables Chain Naming
| Chain Pattern | Purpose |
|---|---|
mwan4_prerouting |
Main hook at mangle priority — restores marks, processes interfaces, checks sets, applies rules |
mwan4_output |
Output hook at mangle priority — same logic for locally-generated traffic |
mwan4_ifaces_in |
Dispatches to per-interface chains based on input device |
mwan4_iface_in_{iface}_{family} |
Marks traffic arriving on a specific interface/family |
mwan4_strategy_{name}_{family} |
Implements a routing strategy (load balance / failover) |
mwan4_rules_{family} |
Evaluates user-defined rules and jumps to strategy chains |
mwan4_rule_{name}_{family} |
Per-rule sticky session chain (only when sticky is enabled) |
nftables Set Naming
| Set Pattern | Purpose |
|---|---|
mwan4_connected_{family} |
Directly connected networks — traffic to these is marked default |
mwan4_custom_{family} |
Networks from custom routing table lookups (rt_table_lookup) |
mwan4_dynamic_{family} |
Dynamically added networks |
mwan4_rule_{family}_{rule} |
Sticky session map (IP + mark → timeout) for a specific rule |
Documentation
For full mwan3 configuration documentation (still largely applicable): https://openwrt.org/docs/guide-user/network/wan/multiwan/mwan3#mwan3_configuration
Getting Help
If things are not working as intended, please run the following commands and include their output in your post/issue (you can mask sensitive information):
ubus call system board
uci export network
uci export mwan4
mwan4 status
nft list table inet fw4
mwan4 integrates with firewall4 and writes its rules, chains and sets (all mwan4_-prefixed) into the shared inet fw4 table — that’s why nft list table inet fw4 is the relevant dump rather than a separate mwan4 table.
If the issue is specific to interface tracking or failover, also include:
ls /var/run/mwan4/
logread -e mwan4 | tail -100