Changelog what changed, release by release.
All notable changes are listed here. The project follows semantic
versioning; the language version (version 1 in rule files) is separate
from the tool version.
-
- Debian and Ubuntu packages are published to an apt repository:
apt install moatfwafter adding apt.moatfw.dev (see the install instructions). Every release lands there. - Packages name moat maintainers maintainers@moatfw.dev as their maintainer.
moat statusnotices when the pinned counters, events or variables map was removed by hand, and names the missing map, as it already did for sets and the configuration.vlan.idmatches with rx VLAN offload on, when the kernel is 6.8 or newer, the program runs in native mode and the driver reports the tags it strips (veth, mlx5, ice):moat loadthen asks the driver for the tag and loads the program bound to the interface. In the other casesloadstill warns, andmoat doctor --ifacesays which case applies.- moat now needs Go 1.24 to build from source (cilium/ebpf v0.21).
stats,status,var listand the set listings wait while a load, reload or set change is running on the interface, so they never show one program's rule names with another program's counters.
- Debian and Ubuntu packages are published to an apt repository:
-
moat import iptablesalso reads the PREROUTING chains of the raw and mangle tables, where anti-DDoS rulesets usually live, in the order the kernel runs them.-m stringbecomespayload contains, and chains it does not read are listed.moat import iptables --ipsets FILEreadsipset saveoutput and writes the ipsets the rules use as set files, loaded with the rules.moat import nftablestranslates the JSON ofnft -j list ruleset: the filter base chains on the ingress, prerouting and input hooks, named sets, meters, limits and raw payload matches.moat test --modelruns case files and captures in a model of the program written in Go: no kernel, no root, any system. Off Linux,moat testuses it on its own. The differential tests check it against the kernel packet by packet.moat doctor --ifacesays whether the interface already runs an XDP program, and whether moat attached it.moat loadexplains a program another tool attached instead of failing with "device or resource busy". In a namespace entered with nsenter, doctor finds the namespace's interfaces.moat explainsays, rule by rule, why each case's packet got its verdict: the test that failed and what the packet had instead.moat fmt --checklists the files that are not in canonical form and exits with 1, for CI.- Fixed:
moat loadafter the interface was removed and came back (what the unitmoat enableinstalls does) failed with "already loaded"; it now attaches afresh and keeps the sets, asreloaddoes too. - Fixed: a failure after the program was attached (writing the manifest) removed the pins of the maps the running program uses.
- Fixed: a reload that failed could leave the running program with the new file's set contents; shared maps now change only once the new program runs.
- Fixed: a variable kept across a reload could hold a value the new rules cannot use; it goes back to the file's value, with a note.
- Fixed:
set syncinto a set too small to hold the old and new entries at once failed; it now removes the leaving entries first in that case. - Fixed:
set addwithout--ttlcould shorten a permanent entry to the set's ttl; like a rule's add, it never shortens an entry now. - Fixed:
moat tracerunning across a reload waited forever; it ends and says why.stats --watchfollowsmoat auditchanges. - Fixed in
moat import: a non-terminating iptables target such as SET or MARK counted as an accept, so a final DROP after it was left out;! --icmp-type anylost its negation;-p udpalone (and! -p tcp) now becomesip.proto, which holds for fragments as iptables does; an ipset with a netmask now writes networks; an nft match after a limit or set statement stays a comment; input the importers refuse exits with 2. - Fixed:
::ffff:0:0/96in a set file became0.0.0.0/0and matched every IPv4 packet; the whole IPv4-mapped range now stays IPv6, as it does in a rule. - Fixed: a limit with a variable rate accepted a burst of 0 or one so large that the burst in nanoseconds overflowed, and dropped every packet; both are refused now, and so is a packet rate above 1e9/s next to a variable burst.
- Fixed: on IPv6,
ip.lenwrapped to a small number for the largest payload lengths; it is now held at 65535. - Fixed:
moat test --pcapignored the case file's[vars]andaudit, and its[[case]]entries; it applies the first two now and refuses the cases. In case files, a 0 written for a port, TTL or window is 0. moat loadwarns, andmoat doctor --ifacenotes, when the interface strips VLAN tags before XDP (rx VLAN offload), which makesvlan.idrules never match.- Fixed:
moat import nftablesleftmeter NAME { ip saddr limit rate over R }as a comment, the form nft 1.0.9 prints; it becomes a limit per source. - Fixed: the C backend could pass garbage arguments to a block of rules that clang proved can never match, and the kernel refused the program.
moat lspcompletes: declaration keywords,stdmodules, fields, protocols, sets, constants, variables, TCP flags and actions, each where it can go.moat lspoffers quick fixes: a misspelled field or name becomes the onemoat checksuggests, and a prefix with host bits set its network.moat lspfinds the references to a set, constant, variable or rule, and renames one everywhere in the file.
-
First public version.
- The moat language: protocol tests, header fields for Ethernet, VLAN,
IPv4, IPv6, TCP, UDP and ICMP, payload slices, constants, lists and
ranges, prefix and address sets,
pass,drop,limitandadd. moat checkwith static warnings (unused names, conditions that are never true, rules that never match, misleadingnot, small bursts) andmoat fmt.moat buildcompiles to a BPF object with no compiler involved: moat generates the instructions and writes the object file itself.--backend ccompiles through C and clang instead, and--emit-cwrites the C for reading. Random packets through both builds of random rule files must agree on every verdict.moat testruns the program in the kernel against case files with simulated time, or against pcap and pcapng captures.moat load,reload,unload,status,audit,set,stats,enableanddisableattach rules to an interface and manage them.- Runtime variables (
var,moat var set) change rates and switch rules on and off without reloading. - Standard modules:
use std.bogons,std.private_sources,std.amplification,std.tcp_sanity. moat traceshows or captures the packets a rule decides, andmoat benchtimes the rules per packet.moat metricsprints or serves counters, sets and variables in the Prometheus format.moat import iptablestranslates the INPUT chain of iptables-save output and keeps what it cannot translate as comments.moat lsp, a VS Code extension and a tree-sitter grammar.payload contains "text"(andnot contains) finds text or bytes anywhere in a window of the payload.moat doctorchecks that a machine can run moat, and releases include Debian and RPM packages namedmoatfw.
- The moat language: protocol tests, header fields for Ethernet, VLAN,
IPv4, IPv6, TCP, UDP and ICMP, payload slices, constants, lists and
ranges, prefix and address sets,
The same list is in CHANGELOG.md in the repository.