ssh is never left without a rule #24
@@ -261,8 +261,21 @@ func AsNftables(rules []Rule, mesh []string, outward bool) string {
|
||||
strings.Join(six, ", "), SSHPort))
|
||||
}
|
||||
}
|
||||
if outward {
|
||||
b.WriteString("\t\t# and from outside, because this machine faces it\n")
|
||||
// From everywhere when this machine faces outward — and also when the mesh has no addresses to
|
||||
// name yet.
|
||||
//
|
||||
// **A machine early in being adopted is the one this matters most for, and the one where the
|
||||
// rule above emits nothing.** Before the private network exists there is no mesh address to
|
||||
// allow from, so restricting to it restricts to nothing: the chain drops by default and ssh is
|
||||
// simply shut. That is the first machine anybody adopts, reached over the network, with the
|
||||
// port needed to fix it closed by the act of adopting it. Never leaving this chain without an
|
||||
// ssh rule is worth more than the narrower rule it would have had.
|
||||
if four, six := byFamily(mesh); outward || (len(four) == 0 && len(six) == 0) {
|
||||
why := "and from outside, because this machine faces it"
|
||||
if !outward {
|
||||
why = "and from anywhere, because this mesh has no addresses to narrow it to yet"
|
||||
}
|
||||
b.WriteString("\t\t# " + why + "\n")
|
||||
b.WriteString(fmt.Sprintf("\t\ttcp dport %d accept\n", SSHPort))
|
||||
}
|
||||
|
||||
|
||||
@@ -690,3 +690,15 @@ func TestSSHIsOpenFromOutsideOnAMachineThatFacesIt(t *testing.T) {
|
||||
t.Fatalf("a machine reachable from outside does not answer ssh there:\n%s", nft)
|
||||
}
|
||||
}
|
||||
|
||||
// A machine the mesh knows no addresses for still answers ssh.
|
||||
//
|
||||
// **This is the machine it matters most for.** Before the private network exists there is nothing
|
||||
// to narrow the rule to, so narrowing it shuts the port entirely — on the first machine anybody
|
||||
// adopts, reached over the network, closed by the act of adopting it.
|
||||
func TestSSHIsNeverLeftWithoutARule(t *testing.T) {
|
||||
nft := AsNftables(nil, nil, false)
|
||||
if !strings.Contains(nft, "tcp dport 22 accept") {
|
||||
t.Fatalf("a machine with no mesh addresses has no ssh rule, so adopting it locks it:\n%s", nft)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package catalogue
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPrintRehearsalRuleset(t *testing.T) {
|
||||
if os.Getenv("PRINT_RULESET") == "" {
|
||||
t.Skip("set PRINT_RULESET")
|
||||
}
|
||||
rules := mustFilter(t, Resolution{Modules: []Manifest{
|
||||
{Module: "pub", Listens: []Listening{{Port: 8099, From: FromMesh, Why: "the thing it serves"}}},
|
||||
}}, nil)
|
||||
t.Log("\n" + AsNftables(rules, []string{"192.0.2.20"}, true))
|
||||
}
|
||||
Reference in New Issue
Block a user