From 72a9a2a0428545a785db326fde6a6f09e8b0f34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20Kr=C3=BCger?= Date: Wed, 26 Apr 2023 00:39:03 +0200 Subject: [PATCH] gluon-ebtables-limit-arp: switch to nftables --- .../lib/gluon/ebtables/100-arp-limit-chains | 3 - .../lib/gluon/ebtables/320-arp-limit-rules | 6 -- .../luasrc/lib/gluon/nftables/mesh_vpn.lua | 2 +- .../Makefile | 20 +++--- .../files/etc/init.d/gluon-arp-limiter | 0 .../lib/gluon/nftables/limit_arp_chain.nft | 61 +++++++++++++++++++ .../gluon/reload.d/380-gluon-arp-limiter-stop | 0 .../reload.d/720-gluon-arp-limiter-start | 0 .../luasrc/lib/gluon/nftables/limit_arp.lua | 6 ++ .../src/Makefile | 0 .../src/addr_store.c | 0 .../src/addr_store.h | 0 .../src/gluon-arp-limiter.c | 48 +++++---------- .../src/gluon-arp-limiter.h | 0 .../src/lookup3.c | 0 .../src/lookup3.h | 0 .../src/mac.c | 0 .../src/mac.h | 0 18 files changed, 94 insertions(+), 52 deletions(-) delete mode 100644 package/gluon-ebtables-limit-arp/luasrc/lib/gluon/ebtables/100-arp-limit-chains delete mode 100644 package/gluon-ebtables-limit-arp/luasrc/lib/gluon/ebtables/320-arp-limit-rules rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/Makefile (66%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/files/etc/init.d/gluon-arp-limiter (100%) create mode 100644 package/gluon-nftables-limit-arp/files/lib/gluon/nftables/limit_arp_chain.nft rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/files/lib/gluon/reload.d/380-gluon-arp-limiter-stop (100%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/files/lib/gluon/reload.d/720-gluon-arp-limiter-start (100%) create mode 100644 package/gluon-nftables-limit-arp/luasrc/lib/gluon/nftables/limit_arp.lua rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/Makefile (100%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/addr_store.c (100%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/addr_store.h (100%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/gluon-arp-limiter.c (80%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/gluon-arp-limiter.h (100%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/lookup3.c (100%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/lookup3.h (100%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/mac.c (100%) rename package/{gluon-ebtables-limit-arp => gluon-nftables-limit-arp}/src/mac.h (100%) diff --git a/package/gluon-ebtables-limit-arp/luasrc/lib/gluon/ebtables/100-arp-limit-chains b/package/gluon-ebtables-limit-arp/luasrc/lib/gluon/ebtables/100-arp-limit-chains deleted file mode 100644 index b39b35c8..00000000 --- a/package/gluon-ebtables-limit-arp/luasrc/lib/gluon/ebtables/100-arp-limit-chains +++ /dev/null @@ -1,3 +0,0 @@ -chain('ARP_LIMIT', 'DROP') -chain('ARP_LIMIT_DATCHECK', 'RETURN') -chain('ARP_LIMIT_TLCHECK', 'RETURN') diff --git a/package/gluon-ebtables-limit-arp/luasrc/lib/gluon/ebtables/320-arp-limit-rules b/package/gluon-ebtables-limit-arp/luasrc/lib/gluon/ebtables/320-arp-limit-rules deleted file mode 100644 index 416bdd96..00000000 --- a/package/gluon-ebtables-limit-arp/luasrc/lib/gluon/ebtables/320-arp-limit-rules +++ /dev/null @@ -1,6 +0,0 @@ -rule('ARP_LIMIT -j ARP_LIMIT_DATCHECK') -rule('ARP_LIMIT --mark 0x2/0x2 -j RETURN') -rule('ARP_LIMIT -j ARP_LIMIT_TLCHECK') -rule('ARP_LIMIT --limit 1/sec --limit-burst 50 -j RETURN') - -rule('FORWARD -p ARP --logical-out br-client -o bat0 --arp-op Request -j ARP_LIMIT') diff --git a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/nftables/mesh_vpn.lua b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/nftables/mesh_vpn.lua index 88dba355..337ca5dd 100644 --- a/package/gluon-mesh-vpn-core/luasrc/lib/gluon/nftables/mesh_vpn.lua +++ b/package/gluon-mesh-vpn-core/luasrc/lib/gluon/nftables/mesh_vpn.lua @@ -1,4 +1,4 @@ include('mesh_vpn_dns', { - position = 'chain-prepend', + position = 'chain-pre', chain = 'dstnat', }) diff --git a/package/gluon-ebtables-limit-arp/Makefile b/package/gluon-nftables-limit-arp/Makefile similarity index 66% rename from package/gluon-ebtables-limit-arp/Makefile rename to package/gluon-nftables-limit-arp/Makefile index 5f71b1c8..a842cfca 100644 --- a/package/gluon-ebtables-limit-arp/Makefile +++ b/package/gluon-nftables-limit-arp/Makefile @@ -1,16 +1,16 @@ include $(TOPDIR)/rules.mk -PKG_NAME:=gluon-ebtables-limit-arp +PKG_NAME:=gluon-nftables-limit-arp include ../gluon.mk -define Package/gluon-ebtables-limit-arp - TITLE:=Ebtables limiter for ARP packets - DEPENDS:=+gluon-core +gluon-ebtables gluon-mesh-batman-adv +define Package/gluon-nftables-limit-arp + TITLE:=nftables limiter for ARP packets + DEPENDS:=+gluon-core +gluon-nftables +gluon-mesh-batman-adv endef -define Package/gluon-ebtables-limit-arp/description - Gluon community wifi mesh firmware framework: Ebtables rules to +define Package/gluon-nftables-limit-arp/description + Gluon community wifi mesh firmware framework: nftables rules to rate-limit ARP packets. This package adds filters to limit the amount of ARP Requests @@ -19,7 +19,7 @@ define Package/gluon-ebtables-limit-arp/description node in total. A burst of up to 50 ARP Requests is allowed until the rate-limiting - takes effect (see --limit-burst in the ebtables manpage). + takes effect (see burst in the nft manpage). Furthermore, ARP Requests with a target IP already present in the batman-adv DAT Cache are excluded from the rate-limiting, @@ -30,13 +30,15 @@ define Package/gluon-ebtables-limit-arp/description However it should mitigate the problem of curious people or smart devices scanning the whole IP range. Which could create a significant amount of overhead for all participants so far. + + Note that this package currently only supports batman. endef -define Package/gluon-ebtables-limit-arp/install +define Package/gluon-nftables-limit-arp/install $(Gluon/Build/Install) $(INSTALL_DIR) $(1)/usr/sbin/ $(CP) $(PKG_BUILD_DIR)/gluon-arp-limiter $(1)/usr/sbin/gluon-arp-limiter endef -$(eval $(call BuildPackageGluon,gluon-ebtables-limit-arp)) +$(eval $(call BuildPackageGluon,gluon-nftables-limit-arp)) diff --git a/package/gluon-ebtables-limit-arp/files/etc/init.d/gluon-arp-limiter b/package/gluon-nftables-limit-arp/files/etc/init.d/gluon-arp-limiter similarity index 100% rename from package/gluon-ebtables-limit-arp/files/etc/init.d/gluon-arp-limiter rename to package/gluon-nftables-limit-arp/files/etc/init.d/gluon-arp-limiter diff --git a/package/gluon-nftables-limit-arp/files/lib/gluon/nftables/limit_arp_chain.nft b/package/gluon-nftables-limit-arp/files/lib/gluon/nftables/limit_arp_chain.nft new file mode 100644 index 00000000..b048d251 --- /dev/null +++ b/package/gluon-nftables-limit-arp/files/lib/gluon/nftables/limit_arp_chain.nft @@ -0,0 +1,61 @@ +set limitmac { + type ether_addr +} + +set datips { + type ipv4_addr +} + +# Rewrite arp packet target hardware address if target protocol address matches a given address. +# input meta iifname enp2s0 arp ptype 0x0800 arp htype 1 arp hlen 6 arp plen 4 @nh,192,32 0xc0a88f10 @nh,144,48 set 0x112233445566 accept + +# chain('ARP_LIMIT', 'DROP') +chain arplimit { + # obrname "br-client" \ + # oifname "bat0" \ + # arp operation request \ + # counter + + # match everything which will land on bridge br-client + # protocol type: ipv4 + # hardware type: ethernet + # hardware address length: 6 byte mac + # protocol address length: 4 byte ipv4 + # arp request + # source address is mac to be limited + # target address is not in DAT + # we're over the limit + # count + # obrname "br-client" \ + # oifname "bat0" \ + arp ptype 0x0800 \ + arp htype 1 \ + arp hlen 6 \ + arp plen 4 \ + arp operation request \ + arp saddr ether @limitmac \ + arp daddr ip != @datips \ + limit rate over 6/minute burst 50 packets \ + counter \ + drop + + # obrname "br-client" \ + # oifname "bat0" \ + arp ptype 0x0800 \ + arp htype 1 \ + arp hlen 6 \ + arp plen 4 \ + arp operation request \ + arp saddr ether != @limitmac \ + arp daddr ip != @datips \ + limit rate over 1/second burst 50 packets \ + counter \ + drop +} + +# chain('ARP_LIMIT_DATCHECK', 'RETURN') +# %s ARP_LIMIT_DATCHECK -p ARP --arp-ip-dst %s -j mark --mark-or 0x2 --mark-target RETURN + +# chain('ARP_LIMIT_TLCHECK', 'RETURN') +# %s ARP_LIMIT_TLCHECK --source %s --limit 6/min --limit-burst 50 -j RETURN" +# %s ARP_LIMIT_TLCHECK (add ? "2" : "") --source %s -j DROP diff --git a/package/gluon-ebtables-limit-arp/files/lib/gluon/reload.d/380-gluon-arp-limiter-stop b/package/gluon-nftables-limit-arp/files/lib/gluon/reload.d/380-gluon-arp-limiter-stop similarity index 100% rename from package/gluon-ebtables-limit-arp/files/lib/gluon/reload.d/380-gluon-arp-limiter-stop rename to package/gluon-nftables-limit-arp/files/lib/gluon/reload.d/380-gluon-arp-limiter-stop diff --git a/package/gluon-ebtables-limit-arp/files/lib/gluon/reload.d/720-gluon-arp-limiter-start b/package/gluon-nftables-limit-arp/files/lib/gluon/reload.d/720-gluon-arp-limiter-start similarity index 100% rename from package/gluon-ebtables-limit-arp/files/lib/gluon/reload.d/720-gluon-arp-limiter-start rename to package/gluon-nftables-limit-arp/files/lib/gluon/reload.d/720-gluon-arp-limiter-start diff --git a/package/gluon-nftables-limit-arp/luasrc/lib/gluon/nftables/limit_arp.lua b/package/gluon-nftables-limit-arp/luasrc/lib/gluon/nftables/limit_arp.lua new file mode 100644 index 00000000..caa142af --- /dev/null +++ b/package/gluon-nftables-limit-arp/luasrc/lib/gluon/nftables/limit_arp.lua @@ -0,0 +1,6 @@ +-- include('limit_arp', { +-- position = 'ruleset-pre' +-- }) + +bridge_include_table('pre', 'limit_arp_chain') +bridge_rule('FORWARD', 'oifname "bat0" obrname "br-client" arp operation request counter jump arplimit') diff --git a/package/gluon-ebtables-limit-arp/src/Makefile b/package/gluon-nftables-limit-arp/src/Makefile similarity index 100% rename from package/gluon-ebtables-limit-arp/src/Makefile rename to package/gluon-nftables-limit-arp/src/Makefile diff --git a/package/gluon-ebtables-limit-arp/src/addr_store.c b/package/gluon-nftables-limit-arp/src/addr_store.c similarity index 100% rename from package/gluon-ebtables-limit-arp/src/addr_store.c rename to package/gluon-nftables-limit-arp/src/addr_store.c diff --git a/package/gluon-ebtables-limit-arp/src/addr_store.h b/package/gluon-nftables-limit-arp/src/addr_store.h similarity index 100% rename from package/gluon-ebtables-limit-arp/src/addr_store.h rename to package/gluon-nftables-limit-arp/src/addr_store.h diff --git a/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.c b/package/gluon-nftables-limit-arp/src/gluon-arp-limiter.c similarity index 80% rename from package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.c rename to package/gluon-nftables-limit-arp/src/gluon-arp-limiter.c index 71d31440..99d16e5c 100644 --- a/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.c +++ b/package/gluon-nftables-limit-arp/src/gluon-arp-limiter.c @@ -14,7 +14,7 @@ #define BATCTL_DC "/usr/sbin/batctl dc -H -n" #define BATCTL_TL "/usr/sbin/batctl tl -H -n" -#define EBTABLES "/usr/sbin/ebtables" +#define NFTABLES "/usr/sbin/nft" #define BUILD_BUG_ON(check) ((void)sizeof(int[1-2*!!(check)])) @@ -39,13 +39,13 @@ static void ebt_ip_call(char *mod, struct in_addr ip) int ret; snprintf(str, sizeof(str), - EBTABLES " %s ARP_LIMIT_DATCHECK -p ARP --arp-ip-dst %s -j mark --mark-or 0x2 --mark-target RETURN", + NFTABLES " %s element bridge gluon datips { %s }", mod, inet_ntoa(ip)); ret = system(str); if (ret) fprintf(stderr, - "%i: Calling ebtables for DAT failed with status %i\n", + "%i: Calling nft for DAT failed with status %i\n", clock, ret); } @@ -53,7 +53,7 @@ static void ip_node_destructor(struct addr_list *node) { struct in_addr *ip = (struct in_addr *)node->addr; - ebt_ip_call("-D", *ip); + ebt_ip_call("delete", *ip); } static void ebt_mac_limit_call(char *mod, struct mac_addr *mac) @@ -62,40 +62,22 @@ static void ebt_mac_limit_call(char *mod, struct mac_addr *mac) int ret; snprintf(str, sizeof(str), - EBTABLES " %s ARP_LIMIT_TLCHECK --source %s --limit 6/min --limit-burst 50 -j RETURN", + NFTABLES " %s element bridge gluon limitmac { %s }", mod, mac_ntoa(mac)); ret = system(str); if (ret) fprintf(stderr, - "%i: Calling ebtables for TL failed with status %i\n", - clock, ret); -} - -static void ebt_mac_ret_call(char *mod, struct mac_addr *mac, int add) -{ - char str[128]; - int ret; - - snprintf(str, sizeof(str), - EBTABLES " %s ARP_LIMIT_TLCHECK %s --source %s -j DROP", - mod, add ? "2" : "", mac_ntoa(mac)); - - ret = system(str); - if (ret) - fprintf(stderr, - "%i: Calling ebtables for TL failed with status %i\n", + "%i: Calling nft for TL failed with status %i\n", clock, ret); } static void ebt_mac_call(char *mod, struct mac_addr *mac) { - if (!strncmp(mod, "-D", strlen(mod))) { - ebt_mac_ret_call(mod, mac, 0); + if (!strncmp(mod, "delete", strlen(mod))) { ebt_mac_limit_call(mod, mac); } else { ebt_mac_limit_call(mod, mac); - ebt_mac_ret_call(mod, mac, 1); } } @@ -103,7 +85,7 @@ static void mac_node_destructor(struct addr_list *node) { struct mac_addr *mac = (struct mac_addr *)node->addr; - ebt_mac_call("-D", mac); + ebt_mac_call("delete", mac); } static int dat_parse_line(const char *line, struct in_addr *ip) @@ -141,7 +123,7 @@ static void ebt_add_ip(struct in_addr ip) if (ret) return; - ebt_ip_call("-I", ip); + ebt_ip_call("add", ip); } static void ebt_add_mac(struct mac_addr *mac) @@ -152,7 +134,7 @@ static void ebt_add_mac(struct mac_addr *mac) if (ret) return; - ebt_mac_call("-I", mac); + ebt_mac_call("add", mac); } static void ebt_dat_update(void) @@ -168,7 +150,7 @@ static void ebt_dat_update(void) fprintf(stderr, "%i: Error: Could not call batctl dc\n", clock); return; } - + while (1) { pline = fgets(line, sizeof(line), fp); if (!pline) { @@ -257,18 +239,18 @@ static void ebt_tl_update(void) static void ebt_dat_flush(void) { - int ret = system(EBTABLES " -F ARP_LIMIT_DATCHECK"); + int ret = system(NFTABLES " flush set bridge gluon datips"); if (ret) - fprintf(stderr, "Error flushing ARP_LIMIT_DATCHECK\n"); + fprintf(stderr, "Error flushing arplimit datips set\n"); } static void ebt_tl_flush(void) { - int ret = system(EBTABLES " -F ARP_LIMIT_TLCHECK"); + int ret = system(NFTABLES " flush set bridge gluon limitmac"); if (ret) - fprintf(stderr, "Error flushing ARP_LIMIT_TLCHECK\n"); + fprintf(stderr, "Error flushing arplimit limitmac\n"); } int main(int argc, char *argv[]) diff --git a/package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.h b/package/gluon-nftables-limit-arp/src/gluon-arp-limiter.h similarity index 100% rename from package/gluon-ebtables-limit-arp/src/gluon-arp-limiter.h rename to package/gluon-nftables-limit-arp/src/gluon-arp-limiter.h diff --git a/package/gluon-ebtables-limit-arp/src/lookup3.c b/package/gluon-nftables-limit-arp/src/lookup3.c similarity index 100% rename from package/gluon-ebtables-limit-arp/src/lookup3.c rename to package/gluon-nftables-limit-arp/src/lookup3.c diff --git a/package/gluon-ebtables-limit-arp/src/lookup3.h b/package/gluon-nftables-limit-arp/src/lookup3.h similarity index 100% rename from package/gluon-ebtables-limit-arp/src/lookup3.h rename to package/gluon-nftables-limit-arp/src/lookup3.h diff --git a/package/gluon-ebtables-limit-arp/src/mac.c b/package/gluon-nftables-limit-arp/src/mac.c similarity index 100% rename from package/gluon-ebtables-limit-arp/src/mac.c rename to package/gluon-nftables-limit-arp/src/mac.c diff --git a/package/gluon-ebtables-limit-arp/src/mac.h b/package/gluon-nftables-limit-arp/src/mac.h similarity index 100% rename from package/gluon-ebtables-limit-arp/src/mac.h rename to package/gluon-nftables-limit-arp/src/mac.h