Skip to content

Firewall

The IPv4 firewall is a stateful ACL configured in the firewall view. The IPv6 firewall is a completely separate stateless engine with its own rule table, counters, enable gate and uRPF flag — a v4 rule never sees a v6 packet. This page covers the whole command set: global gates, the ordered filter list, rate limiting, named address lists and the v6 engine.

Global gates

Three global settings. Disabling the firewall means a default policy of ACCEPT. uRPF is BCP38 reverse-path source verification — anti-spoof. MSS clamping caps TCP MSS at MTU minus 40, which is what a 1492-byte PPPoE path needs. enable and urpf are live on commit; mss-clamp takes effect on restart.

cli
system-view
firewall enable | disable            # disable = default policy ACCEPT
firewall urpf strict | disable       # BCP38 anti-spoof (live)
firewall mss-clamp <mtu> | none      # e.g. 1492 (on restart)
firewall undo enable|mss-clamp
commit ; save

The ordered filter list

A first-match ordered list. A rule is an action — accept, drop or reject — followed by match keywords. The current grammar chains them in a fixed order: proto, then dport, then state. src-list and dst-list are each a standalone match, not yet combinable with the proto chain or with each other. The commit-time validator is the final authority. Filter-rule changes take effect on restart.

cli
firewall filter add <rule>
firewall filter insert <N> <rule>     # 1-based index
firewall filter delete <N>
firewall filter move <N> <M>

# <rule> = accept|drop|reject
#          [proto tcp|udp|icmp] [dport <port>] [state new|established]
#          | src-list <name> | dst-list <name>

firewall filter add accept state established
firewall filter add drop proto tcp dport 23 state new
commit ; save

Rate limiting

A filter rule can carry a token-bucket rate limit appended after the match keywords. limit sets packets per second the rule may match, from 1 to 1000000000. burst is the bucket depth — the momentary burst allowed before metering bites — and defaults to the rate. per-src meters each source IP independently through a per-worker direct-mapped cache; without it the limit is a per-rule aggregate across all sources. The rule matches only while a token is available, and over the limit it falls through to the next rule. That is the whole idiom: an accept with a limit, immediately followed by a drop.

cli
firewall filter add <action> [...matches...] \
    limit <rate> [burst <n>] [per-src]

# cap new inbound TCP to 20/s per source, drop the overflow
firewall filter add accept proto tcp state new limit 20 burst 40 per-src
firewall filter add drop   proto tcp state new

# throttle SSH brute-force to 3 new conns/s per source
firewall filter add accept proto tcp dport 22 state new limit 3 burst 5 per-src
firewall filter add drop   proto tcp dport 22 state new
commit ; save

The bucket is per-worker

Size the rate with this in mind. RSS spreads one source's flows across all workers, so for spread traffic the effective aggregate is roughly the worker count multiplied by the rate. For a single-flow flood — one 5-tuple landing on one worker — it is exact. Like every filter-rule edit, a limit change applies on restart: commit stages it and save persists it. show firewall prints the limit next to the rule.

Named address lists

A named list is a set of addresses that rules match with src-list or dst-list — the same idea as a RouterOS address list. One rule covers thousands of addresses and membership changes without touching the rule. A bare address is a host entry (/32); a.b.c.d/len is a subnet entry matched by longest prefix. timeout gives a host entry a TTL; without it the entry is permanent, which is how RADIUS session tags and static entries are stored. Subnets are always permanent. The list is created automatically on first use.

cli
firewall address-list add <name> <ip|cidr> [timeout <secs>]
firewall address-list remove <name> <ip|cidr>
show firewall address-list [<name>]   # no name = every list

# drop everything sourced from a RADIUS-populated quarantine set
firewall address-list add quarantine 100.64.7.12
firewall filter add drop src-list quarantine
commit

What populates a list

Three things. RADIUS: the Netvyn-Firewall-Address-List VSA, attribute 33, tags the subscriber's framed IP into the named list for the life of the session — added at session-up, removed on teardown, for both PPPoE and IPoE. The operator, with the add and remove commands. And a rule action, which can add the packet's source or destination to a list. Note that list edits are live and immediate: unlike filter rules they do not stage into the candidate and need no commit. That is deliberate — it is the same code path RADIUS uses to tag a subscriber mid-session. For entries that must survive a restart, put address-list lines in firewall.conf.

The IPv6 firewall

A completely separate stateless engine: its own rule table, per-rule counters, enable gate and uRPF flag. Because IPv6 is never translated there is no state match and no MSS clamping, and the v6 match set is richer — source and destination prefixes, source port and ICMPv6 type are all available. enable6 and urpf6 are live on commit; filter6 rule changes take effect on restart.

cli
firewall enable6 | disable6           # default disabled = ACCEPT
firewall urpf6 strict | disable       # default disable

firewall filter6 add <rule>
firewall filter6 insert <N> <rule>
firewall filter6 delete <N>
firewall filter6 move <N> <M>

# <rule> = accept|drop|reject [proto tcp|udp|icmp6|<n>]
#          [src <pfx>/<plen>] [dst <pfx>/<plen>]
#          [dport <n>] [sport <n>] [icmp6-type <n>]
commit ; save

IPv6 uRPF defaults off

Leave urpf6 disabled until subscriber v6 reverse-routes are installed in the RIB. A strict v6 check otherwise drops a legitimate static v6 host on a subscriber's circuit — which is precisely why v6 anti-spoof is a separate toggle from v4 rather than following it.

Counters and verification

show firewall lists the v4 rules with per-rule hit counters; show firewall drops adds the ACL verdict total and the uRPF anti-spoof discard total. The v6 engine has its own pair. Clearing counters is immediate and needs no commit, which makes it the right first move when you are trying to work out whether a rule is actually being hit.

cli
show firewall [drops]
show firewall6 [drops]
show firewall address-list [<name>]

clear counters firewall [<n>]         # immediate
clear counters firewall6 [<n>]