A mesh on both address families renders both
nftables matches ip and ip6 separately and one set holding both is a syntax error, so the file would not load: the service reports a configuration fault and the machine filters nothing. Also a make target for the builder image, which the lab now stocks.
This commit is contained in:
@@ -168,8 +168,15 @@ func AsNftables(rules []Rule, mesh []string) string {
|
||||
rule.Protocol, rule.Port))
|
||||
break
|
||||
}
|
||||
b.WriteString(fmt.Sprintf("\t\tip saddr { %s } %s dport %d accept\n",
|
||||
strings.Join(mesh, ", "), rule.Protocol, rule.Port))
|
||||
four, six := byFamily(mesh)
|
||||
if len(four) > 0 {
|
||||
b.WriteString(fmt.Sprintf("\t\tip saddr { %s } %s dport %d accept\n",
|
||||
strings.Join(four, ", "), rule.Protocol, rule.Port))
|
||||
}
|
||||
if len(six) > 0 {
|
||||
b.WriteString(fmt.Sprintf("\t\tip6 saddr { %s } %s dport %d accept\n",
|
||||
strings.Join(six, ", "), rule.Protocol, rule.Port))
|
||||
}
|
||||
case FromEverywhere:
|
||||
b.WriteString(fmt.Sprintf("\t\t%s dport %d accept\n", rule.Protocol, rule.Port))
|
||||
}
|
||||
@@ -190,3 +197,20 @@ func AsNftables(rules []Rule, mesh []string) string {
|
||||
b.WriteString("}\n")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// byFamily splits addresses into the two nftables understands separately.
|
||||
//
|
||||
// `ip saddr` and `ip6 saddr` are different matches, and one set holding both families is a syntax
|
||||
// error — which means the whole file fails to load and the machine filters nothing while the
|
||||
// service reports a configuration fault. A mesh that is entirely one family renders one line, and
|
||||
// a mixed one renders both rather than dropping half its nodes.
|
||||
func byFamily(addresses []string) (four []string, six []string) {
|
||||
for _, a := range addresses {
|
||||
if strings.Contains(a, ":") {
|
||||
six = append(six, a)
|
||||
continue
|
||||
}
|
||||
four = append(four, a)
|
||||
}
|
||||
return four, six
|
||||
}
|
||||
|
||||
@@ -219,3 +219,21 @@ func TestAskingForTheRuleSetWithNowhereToPutItIsRefused(t *testing.T) {
|
||||
t.Fatal("a module asked for the rule set and named no path; it would receive nothing")
|
||||
}
|
||||
}
|
||||
|
||||
// nftables matches the two address families separately, and one set holding both is a syntax
|
||||
// error — so the file fails to load, the service reports a fault, and the machine filters nothing.
|
||||
func TestAMeshOnBothAddressFamiliesRendersBoth(t *testing.T) {
|
||||
nft := AsNftables((Resolution{Modules: []Manifest{
|
||||
{Module: "store", Listens: []Listening{{Port: 5432, From: FromMesh}}},
|
||||
}}).Filtering(), []string{"198.51.100.2", "2001:db8::2"})
|
||||
if !strings.Contains(nft, "ip saddr { 198.51.100.2 } tcp dport 5432 accept") {
|
||||
t.Fatalf("the machines with v4 addresses were dropped:\n%s", nft)
|
||||
}
|
||||
if !strings.Contains(nft, "ip6 saddr { 2001:db8::2 } tcp dport 5432 accept") {
|
||||
t.Fatalf("the machines with v6 addresses were dropped:\n%s", nft)
|
||||
}
|
||||
// And never in one set, which is the syntax error this exists to avoid.
|
||||
if strings.Contains(nft, "198.51.100.2, 2001:db8::2") {
|
||||
t.Fatalf("both families are in one set, so the file will not load:\n%s", nft)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user