Big Update: New IPSet-based Firewall Scripts + Major Improvements Across All Tools
Hi folks,
I just merged
a huge update to the script collection in the repo. Here’s a summary of what changed:
1. The old bogon script has been replaced with a much more powerful
WAN Firewall script for
ipset-based filtering and DoS protection, somewhat similar to Skynet but with a different set of features. Its default behavior is similar to the old script, though - it downloads the full list of bogons (now pulled dynamically instead of being hardcoded), adds blocking for the most common malware sources (using FireHOL Level 1), and applies filtering only to publicly exposed ports. From README:
wan_firewall.sh -
high-performance inbound firewall for Asuswrt-Merlin that applies only the TCP/UDP ports you actually forward in the GUI. It provides
country blocking, malicious IP filtering, spoofed traffic protection, and optional per-IP/per-port DoS rate limiting before packets hit DNAT, conntrack, or routing - protecting your public services with minimal overhead.
By default, it uses FireHOL Level 1 as a baseline against spoofed traffic and common attack sources for minimal false positives.
Includes predefined but commented-out rules for stronger protection (FireHOL Level 2/3, AbuseIPDB, IPsum, etc.) that you can enable as needed.
Features
ipset aggregation using
mapCIDR for maximum performance (handled by the
ipset_builder.shmodule - see details below), and
fully customizable rules for the forwarded ports. An
optional killswitchprevents your services from being exposed before the initial ipset build/restore completes on system boot.
On download or ipset build failure,
retries via cron and sends email alerts; on success, cancels retries and sends a resolution notification.
Main features
- Bogon traffic drop
- Discards spoofed traffic from reserved/unroutable IPv4 ranges (RFC 6890, 1918, 3927, 6598, etc.) before conntrack, saving CPU and avoiding table pollution.
- Country blocking with high-accuracy GeoLite2
- Uses MaxMind's free GeoLite2 database (weekly updates, multi-source verification) for some of the most accurate country-to-IP mappings available.
- Falls back to IPdeny feeds if you don't set a MAXMIND_LICENSE_KEY.
- Blocks entire countries from reaching your forwarded ports - useful for cutting off high-risk regions entirely.
- Custom ipsets for malicious source blocking
- Pulls in threat intelligence feeds you choose directly from URLs - e.g. AbuseIPDB, IPsum, DShield, Greensnow. Can also use custom hardcoded IP lists defined directly in the configuration file.
- Supports downloads from any source, including the API key protected ones by allowing you to specify custom curl arguments like headers, so you can integrate paid or authenticated feeds without modifying the script.
Notes:
- For country-based blocking with GeoLite2 (a highly accurate database), just sign up for a free MaxMind account, set your
MAXMIND_LICENSE_KEY
in the config, and the script will automatically download, parse, and load ipsets according to your rules. If you leave the key unset, the script falls back to IPdeny, which is less precise but requires no account.
- The script is fully configurable, and you can use any blocklists you want - either remote or hardcoded in the config. This is the format for custom ipsets:
Code:
# Each set starts with a name ending with a colon
blk:
https://iplists.firehol.org/files/firehol_level1.netset
# Multiple sources can be combined into one set
mal:
https://example.com/malware_feed.txt
https://another-feed.com/list.txt -H "Authorization: Bearer API_KEY"
1.2.3.4/32 # inline CIDR entry
# You can define a passlist for highly-trusted sources
pss:
4.5.6.7 # your VPS IP
11.12.13.14 # your friend's home IP
Most importantly,
you don't need to care about duplicated or overlapping ranges because this script uses
mapCIDR to optimize all ipsets.
- Then, you just need to define your firewall rules to specify what exactly you want to block:
Code:
pass:any:any:pss # unconditionally allow matches from pss
block:any:any:blk,cn,kp # drop traffic from blocklist, CN or KP
block:any:any:blk,cn,kp:exc1,exc2 # same as above, but exempt exc1/2
allow:80,443:any:rly,us # allow rly/US, drop others on 80/443
allow:1000-2000:tcp:ca # allow CA on TCP 1000-2000
log:123:udp:any # log all NTP with 5 min window, 1 IP
log:123:udp:us::2:4 # log US NTP with 2 min window, 4 IPs
- You can also define DoS protection rules to throttle traffic, which is useful for lightweight services like DNS or NTP:
Code:
per_ip:123:udp:100 # per_ip on UDP/123, burst defaults to 3
per_ip:123:udp:100:500 # per_ip on UDP/123 with explicit burst=500
per_ip:80:tcp:200:400:10:5 # per_ip with explicit window and per-rule log cap
# (5 logs across 10 minutes)
per_port:123:udp:3333 # per_port, burst defaults to 3 (log_count ignored)
2. Introducing
Tunnel Director -
outbound ipset-based policy routing for Asuswrt-Merlin. It lets you route selected LAN subnets through specific tunnels (WireGuard/OpenVPN) or the WAN based on where traffic is going (countries or custom ipsets). Similar to VPN director, but operates on the ipset level.
Perfect for anti-censorship use cases: you can force all traffic to or from entire countries or custom ipsets through a censorship-resistant VPN, or invert the logic with meta ipset any - send everything through the VPN except selected countries.
Example rules:
Code:
# 1. Inclusion policy (send all traffic from the main LAN via VPN, but only
# when destinations are in certain ipsets, excluding one LAN device):
wgc1:192.168.50.0/24:192.168.50.10/32:us,ubl
# -> Route all devices in 192.168.50.0/24 via wgc1, but only
# for destinations in the US and in the custom ipset "ubl".
# Device 192.168.50.10 is excluded and always routed via WAN.
# 2. Exclusion policy (send a specific VLAN device via VPN, except for some countries):
wgc1:192.168.52.10/32%br52::any:us,ca
# -> Route all traffic from device 192.168.52.10 (on VLAN br52) via wgc1
# for all destinations, but exclude the US and Canada.
# Packets to US/CA bypass the tunnel and follow normal WAN routing.
3.
WireGuard Client Port Forwarder was heavily reworked - it now creates about half as many firewall rules thanks to an optimized iptables chain structure, while preserving the same logic. You can also define multiple ports or ranges in a single rule, reducing rule count even further. In addition, it now supports specifying multiple subnets that will be directly reachable through your VPN client.
Example rules:
Code:
139,445:tcp:192.168.50.1 # SMB ports on the router
8080:tcp:192.168.50.1:80 # external 8080 -> internal 80 (router's Web UI)
443:any:192.168.50.2 # HTTPS with HTTP/3 support, TCP+UDP preserved
6000-6010:udp:192.168.50.3 # UDP range preserved
4.
Dual WAN handler now supports blocking multiple devices from accessing the backup link - useful when your secondary connection is an expensive one, such as LTE.
5.
SSD trimming scripts now properly handle multiple devices from the same vendor. While it's unlikely anyone will connect two or more SSDs to the router, this fix corrects the old logic and ensures proper handling.
6.
Shared utilities library has been significantly extended with new functions - especially useful for firewall-related scripts, and also available for your own custom scripting.
7.
All network-related scripts are now fully idempotent - they only make changes when needed, avoiding unnecessary deletions and recreations. This means you can run them as often as needed without causing errors or triggering redundant updates.
8.
Overall refactoring and bug fixes across all scripts in the repository - the codebase has been streamlined for better readability, consistency, and maintainability. Logging, error handling, and rule synchronization logic were improved to reduce edge cases and make debugging easier.
For full details, example configs, and installation instructions, check out the repo:
https://github.com/kuchkovsky/asuswrt-merlin-scripts/tree/main