A language, not a config
Rules test header fields, prefixes, sets, TCP flags and payload bytes. The checker explains mistakes before anything reaches the kernel.
moat is a small language for XDP. Write rules in a .moat file, test them against real packets in the kernel, then attach them to an interface. One binary, no compiler to install.
version 1 default pass use std.bogons set banned addresses ttl 10m rule known_bad { when ip.src in banned then drop } # one /24 opening connections too fast rule syn_flood { when tcp.dport in {80, 443} and tcp.flags == {syn} then limit 100/s per ip.src/24 burst 200 on exceed add ip.src to banned, drop } rule admin_probe { when tcp.dport == 80 and payload contains "GET /admin" then drop }
$ moat test web.moat web.tomlok a normal visitor passesok a SYN flood from one /24 is cut after the burstok the flooding source is banned for ten minutesok probing /admin is dropped4 of 4 cases passed$ sudo moat load web.moat --iface eth0 --auditloaded web.moat on eth0 (3 rules, 1 sets)audit mode is on: drops are counted but packets pass$ sudo moat stats --iface eth0RULE VERDICT PACKETSknown_bad drop 1824syn_flood drop 93117admin_probe drop 41default pass 2650392$
Rules test header fields, prefixes, sets, TCP flags and payload bytes. The checker explains mistakes before anything reaches the kernel.
moat test runs your cases through the real verifier and BPF_PROG_TEST_RUN, with a simulated clock, or replays a pcap. Nothing is attached. Without a kernel, --model runs them in a model of the program.
moat writes BPF bytecode and the object file itself. The C backend stays one flag away, and both are checked against each other.
Per-source rate limits, by address or prefix. Rules add offenders to sets with an expiry, and variables change while the program runs.
Audit mode counts what would be dropped and lets it pass. Reloads swap the program atomically and keep sets and variables.
moat trace shows the packets a rule catches, live or into a pcap. moat stats and moat metrics give the counters, ready for Prometheus.
moat check rules.moat Errors and warnings with the line and column, and a hint when a field is misspelled. Editors get the same, and completion, through moat lsp.
moat test rules.moat cases.toml Describe packets and the verdict you expect. moat builds them, runs them in the kernel and tells you which rule decided.
moat load rules.moat --iface eth0 Attaches the program with a pinned link. moat enable keeps it there across reboots; moat reload swaps it without a gap.
Already filtering with iptables or nftables? moat import turns
your rules into a .moat file. From iptables or from nftables
moat is an open source language and toolchain for XDP packet filters. You write rules in a .moat file, moat checks them, tests them against real packets in the Linux kernel and compiles them to an eBPF program that runs on a network interface, before the kernel network stack sees the packet.
Your first rules →moat runs at XDP, the earliest point a packet reaches in Linux, before routing, NAT and connection tracking. That makes dropping floods cheap, but moat keeps no connection state. Keep iptables or nftables behind it for stateful rules, and use moat to cut the volume first.
moat next to iptables and nftables →No. moat generates the BPF bytecode and the object file itself, so it is one binary with no compiler to install. A C backend is one flag away (--backend c) for those who want to read or compile the generated C.
Building objects →Loading rules needs Linux 5.15 or newer with BTF, and root or CAP_BPF, CAP_NET_ADMIN and CAP_PERFMON. moat check, fmt, build and test --model run on any system, macOS included. sudo moat doctor says whether a machine and its network driver are ready.
Install →moat test runs a case file of packets through the compiled program in the kernel, with a simulated clock for rate limits, and moat explain shows rule by rule why a packet got its verdict. On a live interface, audit mode counts what would be dropped and lets it pass.
Testing with cases →moat drops attack traffic per source or per network with rate limits, sets that fill themselves and payload matches, at a cost of tens to hundreds of nanoseconds a packet. It filters what reaches the machine: traffic that fills the link before that has to be stopped upstream.
Examples by attack →Yes. moat import iptables reads iptables-save and ipset save output, and moat import nftables reads nft -j list ruleset. Each translates what can be expressed exactly and leaves the rest as comments with the reason.
Importing nftables rules →Yes. moat is open source under the Apache-2.0 license, created by PlaySafe Networks from the filters it runs in front of its own network.
Source on GitHub →moat import turns an iptables or nftables ruleset into a .moat file you can read and test. Or start from a ready ruleset for SSH, web servers, admin access or a known flood, each with the cases that prove what it drops.