gluon-ebtables-limit-arp: switch to nftables
This commit is contained in:
parent
3a7115149c
commit
72a9a2a042
@ -1,3 +0,0 @@
|
|||||||
chain('ARP_LIMIT', 'DROP')
|
|
||||||
chain('ARP_LIMIT_DATCHECK', 'RETURN')
|
|
||||||
chain('ARP_LIMIT_TLCHECK', 'RETURN')
|
|
@ -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')
|
|
@ -1,4 +1,4 @@
|
|||||||
include('mesh_vpn_dns', {
|
include('mesh_vpn_dns', {
|
||||||
position = 'chain-prepend',
|
position = 'chain-pre',
|
||||||
chain = 'dstnat',
|
chain = 'dstnat',
|
||||||
})
|
})
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=gluon-ebtables-limit-arp
|
PKG_NAME:=gluon-nftables-limit-arp
|
||||||
|
|
||||||
include ../gluon.mk
|
include ../gluon.mk
|
||||||
|
|
||||||
define Package/gluon-ebtables-limit-arp
|
define Package/gluon-nftables-limit-arp
|
||||||
TITLE:=Ebtables limiter for ARP packets
|
TITLE:=nftables limiter for ARP packets
|
||||||
DEPENDS:=+gluon-core +gluon-ebtables gluon-mesh-batman-adv
|
DEPENDS:=+gluon-core +gluon-nftables +gluon-mesh-batman-adv
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-ebtables-limit-arp/description
|
define Package/gluon-nftables-limit-arp/description
|
||||||
Gluon community wifi mesh firmware framework: Ebtables rules to
|
Gluon community wifi mesh firmware framework: nftables rules to
|
||||||
rate-limit ARP packets.
|
rate-limit ARP packets.
|
||||||
|
|
||||||
This package adds filters to limit the amount of ARP Requests
|
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.
|
node in total.
|
||||||
|
|
||||||
A burst of up to 50 ARP Requests is allowed until the rate-limiting
|
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
|
Furthermore, ARP Requests with a target IP already present in the
|
||||||
batman-adv DAT Cache are excluded from the rate-limiting,
|
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
|
However it should mitigate the problem of curious people or
|
||||||
smart devices scanning the whole IP range. Which could create
|
smart devices scanning the whole IP range. Which could create
|
||||||
a significant amount of overhead for all participants so far.
|
a significant amount of overhead for all participants so far.
|
||||||
|
|
||||||
|
Note that this package currently only supports batman.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/gluon-ebtables-limit-arp/install
|
define Package/gluon-nftables-limit-arp/install
|
||||||
$(Gluon/Build/Install)
|
$(Gluon/Build/Install)
|
||||||
|
|
||||||
$(INSTALL_DIR) $(1)/usr/sbin/
|
$(INSTALL_DIR) $(1)/usr/sbin/
|
||||||
$(CP) $(PKG_BUILD_DIR)/gluon-arp-limiter $(1)/usr/sbin/gluon-arp-limiter
|
$(CP) $(PKG_BUILD_DIR)/gluon-arp-limiter $(1)/usr/sbin/gluon-arp-limiter
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(eval $(call BuildPackageGluon,gluon-ebtables-limit-arp))
|
$(eval $(call BuildPackageGluon,gluon-nftables-limit-arp))
|
@ -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
|
@ -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')
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#define BATCTL_DC "/usr/sbin/batctl dc -H -n"
|
#define BATCTL_DC "/usr/sbin/batctl dc -H -n"
|
||||||
#define BATCTL_TL "/usr/sbin/batctl tl -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)]))
|
#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;
|
int ret;
|
||||||
|
|
||||||
snprintf(str, sizeof(str),
|
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));
|
mod, inet_ntoa(ip));
|
||||||
|
|
||||||
ret = system(str);
|
ret = system(str);
|
||||||
if (ret)
|
if (ret)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"%i: Calling ebtables for DAT failed with status %i\n",
|
"%i: Calling nft for DAT failed with status %i\n",
|
||||||
clock, ret);
|
clock, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ static void ip_node_destructor(struct addr_list *node)
|
|||||||
{
|
{
|
||||||
struct in_addr *ip = (struct in_addr *)node->addr;
|
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)
|
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;
|
int ret;
|
||||||
|
|
||||||
snprintf(str, sizeof(str),
|
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));
|
mod, mac_ntoa(mac));
|
||||||
|
|
||||||
ret = system(str);
|
ret = system(str);
|
||||||
if (ret)
|
if (ret)
|
||||||
fprintf(stderr,
|
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_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",
|
|
||||||
clock, ret);
|
clock, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ebt_mac_call(char *mod, struct mac_addr *mac)
|
static void ebt_mac_call(char *mod, struct mac_addr *mac)
|
||||||
{
|
{
|
||||||
if (!strncmp(mod, "-D", strlen(mod))) {
|
if (!strncmp(mod, "delete", strlen(mod))) {
|
||||||
ebt_mac_ret_call(mod, mac, 0);
|
|
||||||
ebt_mac_limit_call(mod, mac);
|
ebt_mac_limit_call(mod, mac);
|
||||||
} else {
|
} else {
|
||||||
ebt_mac_limit_call(mod, mac);
|
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;
|
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)
|
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)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ebt_ip_call("-I", ip);
|
ebt_ip_call("add", ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ebt_add_mac(struct mac_addr *mac)
|
static void ebt_add_mac(struct mac_addr *mac)
|
||||||
@ -152,7 +134,7 @@ static void ebt_add_mac(struct mac_addr *mac)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ebt_mac_call("-I", mac);
|
ebt_mac_call("add", mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ebt_dat_update(void)
|
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);
|
fprintf(stderr, "%i: Error: Could not call batctl dc\n", clock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
pline = fgets(line, sizeof(line), fp);
|
pline = fgets(line, sizeof(line), fp);
|
||||||
if (!pline) {
|
if (!pline) {
|
||||||
@ -257,18 +239,18 @@ static void ebt_tl_update(void)
|
|||||||
|
|
||||||
static void ebt_dat_flush(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)
|
if (ret)
|
||||||
fprintf(stderr, "Error flushing ARP_LIMIT_DATCHECK\n");
|
fprintf(stderr, "Error flushing arplimit datips set\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ebt_tl_flush(void)
|
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)
|
if (ret)
|
||||||
fprintf(stderr, "Error flushing ARP_LIMIT_TLCHECK\n");
|
fprintf(stderr, "Error flushing arplimit limitmac\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
Loading…
Reference in New Issue
Block a user