util/linuxfw: add additional nftable detection logic

We were previously using the netlink API to see if there are chains/rules that
already exist. This works fine in environments where there is either full
nftable support or no support at all. However, we have identified certain
environments which have partial nftable support and the only feasible way of
detecting such an environment is to try to create some of the chains that we
need.

This adds a check to create a dummy postrouting chain which is immediately
deleted. The goal of the check is to ensure we are able to use nftables and
that it won't error out later. This check is only done in the path where we
detected that the system has no preexisting nftable rules.

Updates #5621
Updates #8555
Updates #8762

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali
2023-10-17 19:51:40 +00:00
committed by Maisem Ali
parent b47cf04624
commit c3a8e63100
3 changed files with 119 additions and 20 deletions

View File

@@ -851,6 +851,26 @@ func (t *testFWDetector) nftDetect() (int, error) {
return t.nftRuleCount, t.nftErr
}
// TestCreateDummyPostroutingChains tests that on a system with nftables
// available, the function does not return an error and that the dummy
// postrouting chains are cleaned up.
func TestCreateDummyPostroutingChains(t *testing.T) {
conn := newSysConn(t)
runner := newFakeNftablesRunner(t, conn)
if err := runner.createDummyPostroutingChains(); err != nil {
t.Fatalf("createDummyPostroutingChains() failed: %v", err)
}
for _, table := range runner.getNATTables() {
nt, err := getTableIfExists(conn, table.Proto, tsDummyTableName)
if err != nil {
t.Fatalf("getTableIfExists() failed: %v", err)
}
if nt != nil {
t.Fatalf("expected table to be nil, got %v", nt)
}
}
}
func TestPickFirewallModeFromInstalledRules(t *testing.T) {
tests := []struct {
name string