v0.3.0 XDP · eBPF · Apache-2.0

Packet filters you can read, compiled into 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.

$ curl -fsSL https://moatfw.dev/install.sh | sudo sh
Read the docs
web.moatmoat 1
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$ 

Everything a filter needs, and nothing it does not.

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.

Tested in 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.

No compiler to install

moat writes BPF bytecode and the object file itself. The C backend stays one flag away, and both are checked against each other.

Limits and sets that fill themselves

Per-source rate limits, by address or prefix. Rules add offenders to sets with an expiry, and variables change while the program runs.

Safe to roll out

Audit mode counts what would be dropped and lets it pass. Reloads swap the program atomically and keep sets and variables.

See what it decides

moat trace shows the packets a rule catches, live or into a pcap. moat stats and moat metrics give the counters, ready for Prometheus.

From a text file to the wire in three commands.

  1. 01 · write 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.

  2. 02 · test 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.

  3. 03 · load 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.

See where moat sits in the kernel

Already filtering with iptables or nftables? moat import turns your rules into a .moat file. From iptables or from nftables

A thousand rules verify in
≈ 1 s
Runs on
Linux 5.15+
Ships as
one binary
License
Apache-2.0

Questions people ask before they start.

What is moat?

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 →

How is moat different from iptables or nftables?

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 →

Do I need to write C or install clang?

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 →

What does moat need to run?

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 →

How do I know my rules do what I think?

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 →

Can moat stop DDoS attacks?

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 →

Can I convert my existing firewall rules?

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 →

Is moat free?

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 →

Bring the rules you have, or start from one that works.

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.