No, the Pi-hole example uses the XDP UDP scheme this blog post talks about: DNS packets arrive on edge servers, XDP intercepts them before they reach the IP stack, puts a proxy header on the message (we don't use HAProxy's proxy protocol, to conserve space), and relays it out WireGuard; TC BPF attached to the WireGuard interface on the other end (the worker server) strips off the header, fixes the addresses accordingly, and relays to the tap interface for the right worker.
The first cut of this feature I built, without BPF, used NFQueue (diverting packets based on iptables rules to userspace), did a sockets-based proxy from edge to worker, and used a simple raw socket to fix the addresses and write the packet to its destination. NFQueue was annoying to work with, I looked at BPF filters instead, and ultimately wound up just doing the whole thing in BPF.
You don't need to know anything about this to use UDP on Fly.io; you can just add UDP ports the same way you'd add TCP ports (the `fly.toml` in the Pi-hole blog post shows an example).