#!/usr/bin/env python3 """Replace wg-easy iptables hooks with nftables equivalents. wg-easy images ship iptables-legacy, which cannot initialize the `nat`/`filter` tables inside a podman container netns on nftables-only kernels (fc42). Every `wg-quick up wg0` then fails at the PostUp hook, so the wg0 interface is rolled back and ALL client API calls 500 with "Unable to access interface: No such device". The official wg-easy podman+nftables tutorial replaces the hooks with nft rules. This script rewrites hooks_table in /opt/apps/wireguard/wg-easy.db when the hooks still reference iptables. Run it with the wg-easy container stopped, then restart the container so wg0.conf is regenerated. Idempotent. """ import sqlite3 import sys DB = "/opt/apps/wireguard/wg-easy.db" POSTUP = ( "nft add table inet wg_table;" " nft add chain inet wg_table prerouting { type nat hook prerouting priority 100 \\; };" " nft add chain inet wg_table postrouting { type nat hook postrouting priority 100 \\; };" " nft add rule inet wg_table postrouting ip saddr {{ipv4Cidr}} oifname {{device}} masquerade;" " nft add rule inet wg_table postrouting ip6 saddr {{ipv6Cidr}} oifname {{device}} masquerade;" " nft add chain inet wg_table input { type filter hook input priority 0 \\; policy accept \\; };" " nft add rule inet wg_table input udp dport {{port}} accept;" " nft add rule inet wg_table input tcp dport {{uiPort}} accept;" " nft add chain inet wg_table forward { type filter hook forward priority 0 \\; policy accept \\; };" ' nft add rule inet wg_table forward iifname "wg0" accept;' ' nft add rule inet wg_table forward oifname "wg0" accept;' ) POSTDOWN = "nft delete table inet wg_table" def main() -> int: con = sqlite3.connect(DB) try: rows = con.execute("SELECT id, post_up, post_down FROM hooks_table").fetchall() changed = 0 for name, post_up, post_down in rows: post_up = post_up or "" post_down = post_down or "" if "iptables" in post_up or "iptables" in post_down: con.execute( "UPDATE hooks_table SET post_up=?, post_down=?, updated_at=CURRENT_TIMESTAMP WHERE id=?", (POSTUP, POSTDOWN, name), ) print(f"patched hooks for {name!r}") changed += 1 else: print(f"hooks ok for {name!r}") con.commit() finally: con.close() print(f"changed={changed}") return 0 if changed >= 0 else 1 if __name__ == "__main__": sys.exit(main())