=== Context === In the context of a middlebox, fragmented packets are tricky to handle. The full 5-tuple of a packet is often only available in the first fragment which makes enforcing consistent policy difficult. There are really only two stateless options, neither of which are very nice: 1. Enforce policy on first fragment and accept all subsequent fragments. This works but may let in certain attacks or allow data exfiltration. 2. Enforce policy on first fragment and drop all subsequent fragments. This does not really work b/c some protocols may rely on fragmentation. For example, DNS may rely on oversized UDP packets for large responses. So stateful tracking is the only sane option. RFC 8900 [0] calls this out as well in section 6.3: Middleboxes [...] should process IP fragments in a manner that is consistent with [RFC0791] and [RFC8200]. In many cases, middleboxes must maintain state in order to achieve this goal. === BPF related bits === Policy has traditionally been enforced from XDP/TC hooks. Both hooks run before kernel reassembly facilities. However, with the new BPF_PROG_TYPE_NETFILTER, we can rather easily hook into existing netfilter reassembly infra. The basic idea is we bump a refcnt on the netfilter defrag module and then run the bpf prog after the defrag module runs. This allows bpf progs to transparently see full, reassembled packets. The nice thing about this is that progs don't have to carry around logic to detect fragments. === Patchset details === There was an earlier attempt at providing defrag via kfuncs [1]. The feedback was that we could end up doing too much stuff in prog execution context (like sending ICMP error replies). However, I think there are still some outstanding discussion w.r.t. performance when it comes to netfilter vs the previous approach. I'll schedule some time during office hours for this. Patches 1 & 2 are stolenfrom Florian. Hopefully he doesn't mind. There were some outstanding comments on the v2 [2] but it doesn't look like a v3 was ever submitted. I've addressed the comments and put them in this patchset cuz I needed them. Finally, the new selftest seems to be a little flaky. I'm not quite sure why the server will fail to `recvfrom()` occassionaly. I'm fairly sure it's a timing related issue with creating veths. I'll keep debugging but I didn't want that to hold up discussion on this patchset. [0]: https://datatracker.ietf.org/doc/html/rfc8900 [1]: https://lore.kernel.org/bpf/cover.1677526810.git.dxu@xxxxxxxxx/ [2]: https://lore.kernel.org/bpf/20230525110100.8212-1-fw@xxxxxxxxx/ Daniel Xu (7): tools: libbpf: add netfilter link attach helper selftests/bpf: Add bpf_program__attach_netfilter helper test netfilter: defrag: Add glue hooks for enabling/disabling defrag netfilter: bpf: Support BPF_F_NETFILTER_IP_DEFRAG in netfilter link bpf: selftests: Support not connecting client socket bpf: selftests: Support custom type and proto for client sockets bpf: selftests: Add defrag selftests include/linux/netfilter.h | 12 + include/uapi/linux/bpf.h | 5 + net/ipv4/netfilter/nf_defrag_ipv4.c | 8 + net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | 10 + net/netfilter/core.c | 6 + net/netfilter/nf_bpf_link.c | 108 ++++++- tools/include/uapi/linux/bpf.h | 5 + tools/lib/bpf/bpf.c | 8 + tools/lib/bpf/bpf.h | 6 + tools/lib/bpf/libbpf.c | 47 +++ tools/lib/bpf/libbpf.h | 15 + tools/lib/bpf/libbpf.map | 1 + tools/testing/selftests/bpf/Makefile | 4 +- .../selftests/bpf/generate_udp_fragments.py | 90 ++++++ .../selftests/bpf/ip_check_defrag_frags.h | 57 ++++ tools/testing/selftests/bpf/network_helpers.c | 26 +- tools/testing/selftests/bpf/network_helpers.h | 3 + .../bpf/prog_tests/ip_check_defrag.c | 282 ++++++++++++++++++ .../bpf/prog_tests/netfilter_basic.c | 78 +++++ .../selftests/bpf/progs/ip_check_defrag.c | 104 +++++++ .../bpf/progs/test_netfilter_link_attach.c | 14 + 21 files changed, 868 insertions(+), 21 deletions(-) create mode 100755 tools/testing/selftests/bpf/generate_udp_fragments.py create mode 100644 tools/testing/selftests/bpf/ip_check_defrag_frags.h create mode 100644 tools/testing/selftests/bpf/prog_tests/ip_check_defrag.c create mode 100644 tools/testing/selftests/bpf/prog_tests/netfilter_basic.c create mode 100644 tools/testing/selftests/bpf/progs/ip_check_defrag.c create mode 100644 tools/testing/selftests/bpf/progs/test_netfilter_link_attach.c -- 2.40.1