gluon-ebtables: unconditionally segment IGMP/MLD

We must ensure that each node becomes IGMP/MLD querier for its local
clients; having only a single querier for the whole mesh is generally
unreliable, leading to frequent "IGMP/MLD querier appeared/disappeared"
messages from batman-adv and unreliable snooping.

In smaller meshes it might be interesting only segment querier domains, but
allow membership reports to pass through the mesh, in order to support
snooping switches outside the mesh without special configuration. A
site.conf switch is provided to control this behaviour.

Fixes #1320
This commit is contained in:
Matthias Schiffer 2018-03-02 23:51:48 +01:00
parent 7c9e1e1007
commit 17370d8462
No known key found for this signature in database
GPG Key ID: 16EF3F64CB201D9C
13 changed files with 59 additions and 94 deletions

View File

@ -60,7 +60,6 @@ Several Freifunk communities in Germany use Gluon as the foundation of their Fre
package/gluon-config-mode-geo-location package/gluon-config-mode-geo-location
package/gluon-ebtables-filter-multicast package/gluon-ebtables-filter-multicast
package/gluon-ebtables-filter-ra-dhcp package/gluon-ebtables-filter-ra-dhcp
package/gluon-ebtables-segment-mld
package/gluon-ebtables-source-filter package/gluon-ebtables-source-filter
package/gluon-radv-filterd package/gluon-radv-filterd
package/gluon-web-admin package/gluon-web-admin

View File

@ -1,16 +0,0 @@
gluon-ebtables-segment-mld
==========================
These filters drop IGMP/MLD packets before they enter the mesh and
filter any IGMP/MLD packets coming from the mesh.
IGMP/MLD have the concept of a local, elected Querier. For more
decentralization and increased robustness, the idea of this package is
to split the IGMP/MLD domain a querier is responsible for, allowing to
have a querier per node. The split IGMP/MLD domain will also reduce
overhead for this packet type, increasing scalability.
Beware of the consequences of using this package though: You might need
to explicitly, manually mark ports on snooping switches leading towards
your mesh node as multicast router ports for now (Multicast Router
Discovery, MRD, not implemented yet).

View File

@ -183,20 +183,36 @@ next_node \: package
in the ``name`` field. in the ``name`` field.
mesh \: optional mesh \: optional
Options specific to routing protocols. Configuration of general mesh functionality.
At the moment, only the ``batman_adv`` routing protocol has such options: Gluon generally segments layer-2 meshes so that each node becomes IGMP/MLD
querier for its own local clients. This is necessary for reliable multicast
snooping. The segmentation is realized by preventing IGMP/MLD queries from
passing through the mesh.
The optional value ``gw_sel_class`` sets the gateway selection class. The default By default, not only queries are filtered, but also membership report and
class 20 is based on the link quality (TQ) only, class 1 is calculated from leave packets, as they add to the background noise of the mesh. As a
both the TQ and the announced bandwidth. consequence, snooping switches outside the mesh that are connected to a
Gluon node need to be configured to forward all multicast traffic towards
the mesh; this is usually not a problem, as such setups are unusual. If
you run a special-purpose mesh that requires membership reports to be
working, this filtering can be disabled by setting the
*filter_membership_reports* option to ``false``.
In addition, options specific to the batman-adv routing protocol can be set
in the *batman_adv* section:
The optional value *gw_sel_class* sets the gateway selection class. The
default is class 20, which is based on the link quality (TQ) only; class 1
is calculated from both the TQ and the announced bandwidth.
:: ::
mesh = { mesh = {
batman_adv = { filter_membership_reports = false,
gw_sel_class = 1, batman_adv = {
}, gw_sel_class = 1,
} },
}
mesh_vpn mesh_vpn

View File

@ -1,51 +0,0 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gluon-ebtables-segment-mld
PKG_VERSION:=1
PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk
define Package/gluon-ebtables-segment-mld
SECTION:=gluon
CATEGORY:=Gluon
TITLE:=Ebtables filters for IGMP/MLD packets
DEPENDS:=+gluon-core +gluon-ebtables gluon-mesh-batman-adv
endef
define Package/gluon-ebtables-segment-mld/description
Gluon community wifi mesh firmware framework: Ebtables filters for
IGMP/MLD packets
These filters drop IGMP/MLD packets before they enter the mesh and
filter any IGMP/MLD packets coming from the mesh.
IGMP/MLD have the concept of a local, elected Querier. For more
decentralization and increased robustness, the idea of this package is
to split the IGMP/MLD domain a querier is responsible for, allowing to
have a querier per node. The split IGMP/MLD domain will also reduce
overhead for this packet type, increasing scalability.
Beware of the consequences of using this package though: You might need
to explicitly, manually mark ports on snooping switches leading towards
your mesh node as multicast router ports for now (Multicast Router
Discovery, MRD, not implemented yet).
endef
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
endef
define Build/Configure
endef
define Build/Compile
endef
define Package/gluon-ebtables-segment-mld/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,gluon-ebtables-segment-mld))

View File

@ -1,2 +0,0 @@
chain('MULTICAST_IN', 'RETURN', 'nat')
chain('MULTICAST_IN_ICMPV6', 'RETURN', 'nat')

View File

@ -1,2 +0,0 @@
rule ('PREROUTING -d Multicast --logical-in br-client -i bat0 -j MULTICAST_IN', 'nat')
rule ('MULTICAST_IN -p IPv6 --ip6-protocol ipv6-icmp -j MULTICAST_IN_ICMPV6', 'nat')

View File

@ -1,2 +0,0 @@
rule('MULTICAST_OUT -p IPv4 --ip-protocol igmp -j DROP')
rule('MULTICAST_IN -p IPv4 --ip-protocol igmp -j DROP', 'nat')

View File

@ -1,9 +0,0 @@
rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 130 -j DROP') -- MLD Query
rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 131 -j DROP') -- MLDv1 Report
rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 132 -j DROP') -- MLDv1 Done
rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 143 -j DROP') -- MLDv2 Report
rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 130 -j DROP', 'nat') -- MLD Query
rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 131 -j DROP', 'nat') -- MLDv1 Report
rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 132 -j DROP', 'nat') -- MLDv1 Done
rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 143 -j DROP', 'nat') -- MLDv2 Report

View File

@ -6,7 +6,7 @@ PKG_RELEASE:=1
PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME) PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
include $(INCLUDE_DIR)/package.mk include ../gluon.mk
define Package/gluon-ebtables define Package/gluon-ebtables
@ -34,4 +34,9 @@ define Package/gluon-ebtables/install
$(CP) ./files/* $(1)/ $(CP) ./files/* $(1)/
endef endef
define Package/gluon-ebtables/postinst
#!/bin/sh
$(call GluonCheckSite,check_site.lua)
endef
$(eval $(call BuildPackage,gluon-ebtables)) $(eval $(call BuildPackage,gluon-ebtables))

View File

@ -0,0 +1 @@
need_boolean({'mesh', 'filter_membership_reports'}, false)

View File

@ -1,5 +1,9 @@
chain('IN_ONLY', 'RETURN') chain('IN_ONLY', 'RETURN')
chain('OUT_ONLY', 'RETURN') chain('OUT_ONLY', 'RETURN')
-- nat chain runs early, so we can drop IGMP/MLD
chain('MULTICAST_IN', 'RETURN', 'nat')
chain('MULTICAST_IN_ICMPV6', 'RETURN', 'nat')
chain('MULTICAST_OUT', 'RETURN') chain('MULTICAST_OUT', 'RETURN')
chain('MULTICAST_OUT_ICMPV6', 'RETURN') chain('MULTICAST_OUT_ICMPV6', 'RETURN')

View File

@ -0,0 +1,20 @@
local site = require 'gluon.site'
rule('MULTICAST_IN -p IPv4 --ip-protocol igmp --ip-igmp-type membership-query -j DROP', 'nat')
rule('MULTICAST_OUT -p IPv4 --ip-protocol igmp --ip-igmp-type membership-query -j DROP')
rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 130 -j DROP') -- MLD Query
rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 130 -j DROP', 'nat') -- MLD Query
if site.mesh.filter_membership_reports(true) then
rule('MULTICAST_IN -p IPv4 --ip-protocol igmp -j DROP', 'nat')
rule('MULTICAST_OUT -p IPv4 --ip-protocol igmp -j DROP')
rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 131 -j DROP') -- MLDv1 Report
rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 132 -j DROP') -- MLDv1 Done
rule('MULTICAST_OUT_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 143 -j DROP') -- MLDv2 Report
rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 131 -j DROP', 'nat') -- MLDv1 Report
rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 132 -j DROP', 'nat') -- MLDv1 Done
rule('MULTICAST_IN_ICMPV6 -p IPv6 --ip6-protocol ipv6-icmp --ip6-icmp-type 143 -j DROP', 'nat') -- MLDv2 Report
end

View File

@ -1,4 +1,6 @@
rule ('PREROUTING -d Multicast --logical-in br-client -i bat0 -j MULTICAST_IN', 'nat')
rule 'OUTPUT -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT' rule 'OUTPUT -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT'
rule 'FORWARD -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT' rule 'FORWARD -d Multicast --logical-out br-client -o bat0 -j MULTICAST_OUT'
rule ('MULTICAST_IN -p IPv6 --ip6-protocol ipv6-icmp -j MULTICAST_IN_ICMPV6', 'nat')
rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp -j MULTICAST_OUT_ICMPV6' rule 'MULTICAST_OUT -p IPv6 --ip6-protocol ipv6-icmp -j MULTICAST_OUT_ICMPV6'