mirror of
https://github.com/evilsocket/opensnitch.git
synced 2025-03-04 08:34:40 +01:00
tests: updated sys fw tests
This commit is contained in:
parent
344819eb30
commit
18e583d20e
8 changed files with 278 additions and 205 deletions
|
@ -1,26 +1,27 @@
|
|||
package nftables
|
||||
package nftables_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/exprs"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/nftest"
|
||||
"github.com/google/nftables"
|
||||
)
|
||||
|
||||
func TestChains(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
if nft.addInterceptionTables() != nil {
|
||||
if nftest.Fw.AddInterceptionTables() != nil {
|
||||
t.Error("Error adding interception tables")
|
||||
}
|
||||
|
||||
t.Run("AddChain", func(t *testing.T) {
|
||||
filterPolicy := nftables.ChainPolicyAccept
|
||||
chn := nft.AddChain(
|
||||
chn := nftest.Fw.AddChain(
|
||||
exprs.NFT_HOOK_INPUT,
|
||||
exprs.NFT_CHAIN_FILTER,
|
||||
exprs.NFT_FAMILY_INET,
|
||||
|
@ -31,54 +32,54 @@ func TestChains(t *testing.T) {
|
|||
if chn == nil {
|
||||
t.Error("chain input-filter-inet not created")
|
||||
}
|
||||
if !nft.Commit() {
|
||||
if !nftest.Fw.Commit() {
|
||||
t.Error("error adding input-filter-inet chain")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("getChain", func(t *testing.T) {
|
||||
tblfilter := nft.getTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
tblfilter := nftest.Fw.GetTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
if tblfilter == nil {
|
||||
t.Error("table filter-inet not created")
|
||||
}
|
||||
|
||||
chn := nft.getChain(exprs.NFT_HOOK_INPUT, tblfilter, exprs.NFT_FAMILY_INET)
|
||||
chn := nftest.Fw.GetChain(exprs.NFT_HOOK_INPUT, tblfilter, exprs.NFT_FAMILY_INET)
|
||||
if chn == nil {
|
||||
t.Error("chain input-filter-inet not added")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("delChain", func(t *testing.T) {
|
||||
tblfilter := nft.getTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
tblfilter := nftest.Fw.GetTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
if tblfilter == nil {
|
||||
t.Error("table filter-inet not created")
|
||||
}
|
||||
|
||||
chn := nft.getChain(exprs.NFT_HOOK_INPUT, tblfilter, exprs.NFT_FAMILY_INET)
|
||||
chn := nftest.Fw.GetChain(exprs.NFT_HOOK_INPUT, tblfilter, exprs.NFT_FAMILY_INET)
|
||||
if chn == nil {
|
||||
t.Error("chain input-filter-inet not added")
|
||||
}
|
||||
|
||||
if err := nft.delChain(chn); err != nil {
|
||||
if err := nftest.Fw.DelChain(chn); err != nil {
|
||||
t.Error("error deleting chain input-filter-inet")
|
||||
}
|
||||
})
|
||||
|
||||
nft.delSystemTables()
|
||||
nftest.Fw.DelSystemTables()
|
||||
}
|
||||
|
||||
// TestAddInterceptionChains checks if the needed tables and chains have been created.
|
||||
// We use 2: output-mangle-inet for intercepting outbound connections, and input-filter-inet for DNS responses interception
|
||||
func TestAddInterceptionChains(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
if err := nft.addInterceptionTables(); err != nil {
|
||||
if err := nftest.Fw.AddInterceptionTables(); err != nil {
|
||||
t.Errorf("Error adding interception tables: %s", err)
|
||||
}
|
||||
|
||||
if err := nft.addInterceptionChains(); err != nil {
|
||||
if err := nftest.Fw.AddInterceptionChains(); err != nil {
|
||||
t.Errorf("Error adding interception chains: %s", err)
|
||||
}
|
||||
|
||||
nft.delSystemTables()
|
||||
nftest.Fw.DelSystemTables()
|
||||
}
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
package nftables
|
||||
package nftables_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/common"
|
||||
nftb "github.com/evilsocket/opensnitch/daemon/firewall/nftables"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/exprs"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/nftest"
|
||||
"github.com/google/nftables"
|
||||
)
|
||||
|
||||
// mimic EnableInterception() but without NewRulesChecker()
|
||||
func addInterceptionRules(nft *Nft, t *testing.T) {
|
||||
if err := nft.addInterceptionTables(); err != nil {
|
||||
func addInterceptionRules(nft *nftb.Nft, t *testing.T) {
|
||||
if err := nft.AddInterceptionTables(); err != nil {
|
||||
t.Errorf("Error while adding interception tables: %s", err)
|
||||
return
|
||||
}
|
||||
if err := nft.addInterceptionChains(); err != nil {
|
||||
if err := nft.AddInterceptionChains(); err != nil {
|
||||
t.Errorf("Error while adding interception chains: %s", err)
|
||||
return
|
||||
}
|
||||
|
@ -28,12 +30,12 @@ func addInterceptionRules(nft *Nft, t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func _testMonitorReload(t *testing.T, conn *nftables.Conn, nft *Nft) {
|
||||
tblfilter := nft.getTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
func _testMonitorReload(t *testing.T, conn *nftables.Conn, nft *nftb.Nft) {
|
||||
tblfilter := nft.GetTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
if tblfilter == nil || tblfilter.Name != exprs.NFT_CHAIN_FILTER {
|
||||
t.Error("table filter-inet not in the list")
|
||||
}
|
||||
chnFilterInput := nft.getChain(exprs.NFT_HOOK_INPUT, tblfilter, exprs.NFT_FAMILY_INET)
|
||||
chnFilterInput := nftest.Fw.GetChain(exprs.NFT_HOOK_INPUT, tblfilter, exprs.NFT_FAMILY_INET)
|
||||
if chnFilterInput == nil {
|
||||
t.Error("chain input-filter-inet not in the list")
|
||||
}
|
||||
|
@ -42,12 +44,12 @@ func _testMonitorReload(t *testing.T, conn *nftables.Conn, nft *Nft) {
|
|||
t.Error("DNS interception rule not added")
|
||||
}
|
||||
conn.FlushChain(chnFilterInput)
|
||||
nft.Commit()
|
||||
nftest.Fw.Commit()
|
||||
|
||||
// the rules checker checks the rules every 10s
|
||||
reloaded := false
|
||||
for i := 0; i < 15; i++ {
|
||||
if r, _ := getRule(t, conn, tblfilter.Name, exprs.NFT_HOOK_INPUT, interceptionRuleKey, 0); r != nil {
|
||||
if r, _ := getRule(t, conn, tblfilter.Name, exprs.NFT_HOOK_INPUT, nftb.InterceptionRuleKey, 0); r != nil {
|
||||
reloaded = true
|
||||
break
|
||||
}
|
||||
|
@ -59,35 +61,35 @@ func _testMonitorReload(t *testing.T, conn *nftables.Conn, nft *Nft) {
|
|||
}
|
||||
|
||||
func TestAreRulesLoaded(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
addInterceptionRules(nft, t)
|
||||
if !nft.AreRulesLoaded() {
|
||||
addInterceptionRules(nftest.Fw, t)
|
||||
if !nftest.Fw.AreRulesLoaded() {
|
||||
t.Error("interception rules not loaded, and they should")
|
||||
}
|
||||
|
||||
nft.delInterceptionRules()
|
||||
if nft.AreRulesLoaded() {
|
||||
nftest.Fw.DelInterceptionRules()
|
||||
if nftest.Fw.AreRulesLoaded() {
|
||||
t.Error("interception rules are loaded, and the shouldn't")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonitorReload(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
nft.EnableInterception()
|
||||
nftest.Fw.EnableInterception()
|
||||
|
||||
// test that rules are reloaded after being deleted, but also
|
||||
// that the monitor is not stopped after the first reload.
|
||||
_testMonitorReload(t, conn, nft)
|
||||
_testMonitorReload(t, conn, nft)
|
||||
_testMonitorReload(t, conn, nft)
|
||||
_testMonitorReload(t, conn, nftest.Fw)
|
||||
_testMonitorReload(t, conn, nftest.Fw)
|
||||
_testMonitorReload(t, conn, nftest.Fw)
|
||||
}
|
||||
|
|
63
daemon/firewall/nftables/nftest/nftest.go
Normal file
63
daemon/firewall/nftables/nftest/nftest.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package nftest
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
nftb "github.com/evilsocket/opensnitch/daemon/firewall/nftables"
|
||||
"github.com/google/nftables"
|
||||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
var (
|
||||
conn *nftables.Conn
|
||||
newNS netns.NsHandle
|
||||
|
||||
// Fw represents the nftables Fw object.
|
||||
Fw, _ = nftb.Fw()
|
||||
)
|
||||
|
||||
func init() {
|
||||
nftb.InitMapsStore()
|
||||
}
|
||||
|
||||
// SkipIfNotPrivileged will skip the test from where it's invoked,
|
||||
// to skip the test if we don't have root privileges.
|
||||
// This may occur when executing the tests on restricted environments,
|
||||
// such as containers, chroots, etc.
|
||||
func SkipIfNotPrivileged(t *testing.T) {
|
||||
if os.Getenv("PRIVILEGED_TESTS") == "" {
|
||||
t.Skip("Set PRIVILEGED_TESTS to 1 to launch these tests, and launch them as root, or as a user allowed to create new namespaces.")
|
||||
}
|
||||
}
|
||||
|
||||
// OpenSystemConn opens a new connection with the kernel in a new namespace.
|
||||
// https://github.com/google/nftables/blob/8f2d395e1089dea4966c483fbeae7e336917c095/internal/nftest/system_conn.go#L15
|
||||
func OpenSystemConn(t *testing.T) (*nftables.Conn, netns.NsHandle) {
|
||||
t.Helper()
|
||||
// We lock the goroutine into the current thread, as namespace operations
|
||||
// such as those invoked by `netns.New()` are thread-local. This is undone
|
||||
// in nftest.CleanupSystemConn().
|
||||
runtime.LockOSThread()
|
||||
|
||||
ns, err := netns.New()
|
||||
if err != nil {
|
||||
t.Fatalf("netns.New() failed: %v", err)
|
||||
}
|
||||
t.Log("OpenSystemConn() with NS:", ns)
|
||||
c, err := nftables.New(nftables.WithNetNSFd(int(ns)))
|
||||
if err != nil {
|
||||
t.Fatalf("nftables.New() failed: %v", err)
|
||||
}
|
||||
return c, ns
|
||||
}
|
||||
|
||||
// CleanupSystemConn closes the given namespace.
|
||||
func CleanupSystemConn(t *testing.T, newNS netns.NsHandle) {
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
if err := newNS.Close(); err != nil {
|
||||
t.Fatalf("newNS.Close() failed: %v", err)
|
||||
}
|
||||
}
|
44
daemon/firewall/nftables/nftest/utils.go
Normal file
44
daemon/firewall/nftables/nftest/utils.go
Normal file
|
@ -0,0 +1,44 @@
|
|||
package nftest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/exprs"
|
||||
"github.com/google/nftables"
|
||||
"github.com/google/nftables/expr"
|
||||
)
|
||||
|
||||
func AddTestRule(t *testing.T, conn *nftables.Conn, exp *[]expr.Any) (*nftables.Rule, *nftables.Chain) {
|
||||
|
||||
_, err := Fw.AddTable("yyy", exprs.NFT_FAMILY_INET)
|
||||
if err != nil {
|
||||
t.Error("pre step add_table() yyy-inet failed")
|
||||
return nil, nil
|
||||
}
|
||||
chn := Fw.AddChain(
|
||||
exprs.NFT_HOOK_INPUT,
|
||||
"yyy",
|
||||
exprs.NFT_FAMILY_INET,
|
||||
nftables.ChainPriorityFilter,
|
||||
nftables.ChainTypeFilter,
|
||||
nftables.ChainHookInput,
|
||||
nftables.ChainPolicyAccept)
|
||||
if chn == nil {
|
||||
t.Error("pre step add_chain() input-yyy-inet failed")
|
||||
return nil, nil
|
||||
}
|
||||
//nft.Commit()
|
||||
|
||||
r, err := Fw.AddRule(
|
||||
exprs.NFT_HOOK_INPUT, "yyy", exprs.NFT_FAMILY_INET,
|
||||
0,
|
||||
"key-yyy",
|
||||
exp)
|
||||
if err != nil {
|
||||
t.Errorf("Error adding rule: %s", err)
|
||||
return nil, nil
|
||||
}
|
||||
t.Logf("Rule: %+v", r)
|
||||
|
||||
return r, chn
|
||||
}
|
|
@ -1,9 +1,11 @@
|
|||
package nftables
|
||||
package nftables_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
nftb "github.com/evilsocket/opensnitch/daemon/firewall/nftables"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/exprs"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/nftest"
|
||||
"github.com/google/nftables"
|
||||
)
|
||||
|
||||
|
@ -14,7 +16,7 @@ func getRulesList(t *testing.T, conn *nftables.Conn, family, tblName, chnName st
|
|||
}
|
||||
|
||||
for rdx, c := range chains {
|
||||
if c.Table.Family == getFamilyCode(family) && c.Table.Name == tblName && c.Name == chnName {
|
||||
if c.Table.Family == nftb.GetFamilyCode(family) && c.Table.Name == tblName && c.Name == chnName {
|
||||
rules, err := conn.GetRule(c.Table, c)
|
||||
if err != nil {
|
||||
return nil, -1
|
||||
|
@ -54,12 +56,15 @@ func getRule(t *testing.T, conn *nftables.Conn, tblName, chnName, key string, ru
|
|||
}
|
||||
|
||||
func TestAddRule(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
r, chn := nftest.AddTestRule(t, conn, exprs.NewNoTrack())
|
||||
|
||||
/*
|
||||
_, err := nft.AddTable("yyy", exprs.NFT_FAMILY_INET)
|
||||
if err != nil {
|
||||
t.Error("pre step add_table() yyy-inet failed")
|
||||
|
@ -84,6 +89,8 @@ func TestAddRule(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf("Error adding rule: %s", err)
|
||||
}
|
||||
*/
|
||||
|
||||
rules, err := conn.GetRules(chn.Table, chn)
|
||||
if err != nil || len(rules) != 1 {
|
||||
t.Errorf("Rule not added, total: %d", len(rules))
|
||||
|
@ -92,17 +99,17 @@ func TestAddRule(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInsertRule(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
_, err := nft.AddTable("yyy", exprs.NFT_FAMILY_INET)
|
||||
_, err := nftest.Fw.AddTable("yyy", exprs.NFT_FAMILY_INET)
|
||||
if err != nil {
|
||||
t.Error("pre step add_table() yyy-inet failed")
|
||||
}
|
||||
chn := nft.AddChain(
|
||||
chn := nftest.Fw.AddChain(
|
||||
exprs.NFT_HOOK_INPUT,
|
||||
"yyy",
|
||||
exprs.NFT_FAMILY_INET,
|
||||
|
@ -114,7 +121,7 @@ func TestInsertRule(t *testing.T) {
|
|||
t.Error("pre step add_chain() input-yyy-inet failed")
|
||||
}
|
||||
|
||||
err = nft.insertRule(
|
||||
err = nftest.Fw.InsertRule(
|
||||
exprs.NFT_HOOK_INPUT, "yyy", exprs.NFT_FAMILY_INET,
|
||||
0,
|
||||
exprs.NewNoTrack())
|
||||
|
@ -128,17 +135,17 @@ func TestInsertRule(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestQueueConnections(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
_, err := nft.AddTable(exprs.NFT_CHAIN_MANGLE, exprs.NFT_FAMILY_INET)
|
||||
_, err := nftest.Fw.AddTable(exprs.NFT_CHAIN_MANGLE, exprs.NFT_FAMILY_INET)
|
||||
if err != nil {
|
||||
t.Error("pre step add_table() mangle-inet failed")
|
||||
}
|
||||
chn := nft.AddChain(
|
||||
chn := nftest.Fw.AddChain(
|
||||
exprs.NFT_HOOK_OUTPUT, exprs.NFT_CHAIN_MANGLE, exprs.NFT_FAMILY_INET,
|
||||
nftables.ChainPriorityFilter,
|
||||
nftables.ChainTypeFilter,
|
||||
|
@ -148,31 +155,31 @@ func TestQueueConnections(t *testing.T) {
|
|||
t.Error("pre step add_chain() output-mangle-inet failed")
|
||||
}
|
||||
|
||||
if err1, err2 := nft.QueueConnections(true, true); err1 != nil && err2 != nil {
|
||||
if err1, err2 := nftest.Fw.QueueConnections(true, true); err1 != nil && err2 != nil {
|
||||
t.Errorf("rule to queue connections not added: %s, %s", err1, err2)
|
||||
}
|
||||
|
||||
r, _ := getRule(t, conn, exprs.NFT_CHAIN_MANGLE, exprs.NFT_HOOK_OUTPUT, interceptionRuleKey, 0)
|
||||
r, _ := getRule(t, conn, exprs.NFT_CHAIN_MANGLE, exprs.NFT_HOOK_OUTPUT, nftb.InterceptionRuleKey, 0)
|
||||
if r == nil {
|
||||
t.Error("rule to queue connections not in the list")
|
||||
}
|
||||
if string(r.UserData) != interceptionRuleKey {
|
||||
if string(r.UserData) != nftb.InterceptionRuleKey {
|
||||
t.Errorf("invalid UserData: %s", string(r.UserData))
|
||||
}
|
||||
}
|
||||
|
||||
func TestQueueDNSResponses(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
_, err := nft.AddTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
_, err := nftest.Fw.AddTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
if err != nil {
|
||||
t.Error("pre step add_table() filter-inet failed")
|
||||
}
|
||||
chn := nft.AddChain(
|
||||
chn := nftest.Fw.AddChain(
|
||||
exprs.NFT_HOOK_INPUT, exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET,
|
||||
nftables.ChainPriorityFilter,
|
||||
nftables.ChainTypeFilter,
|
||||
|
@ -182,15 +189,15 @@ func TestQueueDNSResponses(t *testing.T) {
|
|||
t.Error("pre step add_chain() input-filter-inet failed")
|
||||
}
|
||||
|
||||
if err1, err2 := nft.QueueDNSResponses(true, true); err1 != nil && err2 != nil {
|
||||
if err1, err2 := nftest.Fw.QueueDNSResponses(true, true); err1 != nil && err2 != nil {
|
||||
t.Errorf("rule to queue DNS responses not added: %s, %s", err1, err2)
|
||||
}
|
||||
|
||||
r, _ := getRule(t, conn, exprs.NFT_CHAIN_FILTER, exprs.NFT_HOOK_INPUT, interceptionRuleKey, 0)
|
||||
r, _ := getRule(t, conn, exprs.NFT_CHAIN_FILTER, exprs.NFT_HOOK_INPUT, nftb.InterceptionRuleKey, 0)
|
||||
if r == nil {
|
||||
t.Error("rule to queue DNS responses not in the list")
|
||||
}
|
||||
if string(r.UserData) != interceptionRuleKey {
|
||||
if string(r.UserData) != nftb.InterceptionRuleKey {
|
||||
t.Errorf("invalid UserData: %s", string(r.UserData))
|
||||
}
|
||||
|
||||
|
@ -201,7 +208,7 @@ func TestQueueDNSResponses(t *testing.T) {
|
|||
/*if err1, err2 := nft.QueueDNSResponses(false, true); err1 != nil && err2 != nil {
|
||||
t.Errorf("rule to queue DNS responses not deleted: %s, %s", err1, err2)
|
||||
}
|
||||
r, _ = getRule(t, conn, exprs.NFT_CHAIN_FILTER, exprs.NFT_HOOK_INPUT, interceptionRuleKey, 0)
|
||||
r, _ = getRule(t, conn, exprs.NFT_CHAIN_FILTER, exprs.NFT_HOOK_INPUT, nftb.InterceptionRuleKey, 0)
|
||||
if r != nil {
|
||||
t.Error("rule to queue DNS responses should have been deleted")
|
||||
}*/
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package nftables
|
||||
package nftables_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/exprs"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/nftest"
|
||||
)
|
||||
|
||||
type sysChainsListT struct {
|
||||
|
@ -14,13 +15,13 @@ type sysChainsListT struct {
|
|||
}
|
||||
|
||||
func TestAddSystemRules(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
cfg, err := nft.NewSystemFwConfig(nft.preloadConfCallback, nft.reloadConfCallback)
|
||||
cfg, err := nftest.Fw.NewSystemFwConfig(nftest.Fw.PreloadConfCallback, nftest.Fw.ReloadConfCallback)
|
||||
if err != nil {
|
||||
t.Logf("Error creating fw config: %s", err)
|
||||
}
|
||||
|
@ -30,7 +31,7 @@ func TestAddSystemRules(t *testing.T) {
|
|||
t.Errorf("Error loading config from disk: %s", err)
|
||||
}
|
||||
|
||||
nft.AddSystemRules(false, false)
|
||||
nftest.Fw.AddSystemRules(false, false)
|
||||
|
||||
rules, _ := getRulesList(t, conn, exprs.NFT_FAMILY_INET, exprs.NFT_CHAIN_FILTER, exprs.NFT_HOOK_INPUT)
|
||||
// 3 rules in total, 1 disabled.
|
||||
|
@ -62,13 +63,13 @@ func TestAddSystemRules(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestFwConfDisabled(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
cfg, err := nft.NewSystemFwConfig(nft.preloadConfCallback, nft.reloadConfCallback)
|
||||
cfg, err := nftest.Fw.NewSystemFwConfig(nftest.Fw.PreloadConfCallback, nftest.Fw.ReloadConfCallback)
|
||||
if err != nil {
|
||||
t.Logf("Error creating fw config: %s", err)
|
||||
}
|
||||
|
@ -78,7 +79,7 @@ func TestFwConfDisabled(t *testing.T) {
|
|||
t.Errorf("Error loading config from disk: %s", err)
|
||||
}
|
||||
|
||||
nft.AddSystemRules(false, false)
|
||||
nftest.Fw.AddSystemRules(false, false)
|
||||
|
||||
tests := []sysChainsListT{
|
||||
{
|
||||
|
@ -101,13 +102,13 @@ func TestFwConfDisabled(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestDeleteSystemRules(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
cfg, err := nft.NewSystemFwConfig(nft.preloadConfCallback, nft.reloadConfCallback)
|
||||
cfg, err := nftest.Fw.NewSystemFwConfig(nftest.Fw.PreloadConfCallback, nftest.Fw.ReloadConfCallback)
|
||||
if err != nil {
|
||||
t.Logf("Error creating fw config: %s", err)
|
||||
}
|
||||
|
@ -117,7 +118,7 @@ func TestDeleteSystemRules(t *testing.T) {
|
|||
t.Errorf("Error loading config from disk: %s", err)
|
||||
}
|
||||
|
||||
nft.AddSystemRules(false, false)
|
||||
nftest.Fw.AddSystemRules(false, false)
|
||||
|
||||
tests := []sysChainsListT{
|
||||
{
|
||||
|
@ -138,14 +139,14 @@ func TestDeleteSystemRules(t *testing.T) {
|
|||
}
|
||||
|
||||
t.Run("test-delete-system-rules", func(t *testing.T) {
|
||||
nft.DeleteSystemRules(false, false, true)
|
||||
nftest.Fw.DeleteSystemRules(false, false, true)
|
||||
for _, tt := range tests {
|
||||
rules, _ := getRulesList(t, conn, tt.family, tt.table, tt.chain)
|
||||
if len(rules) != 0 {
|
||||
t.Errorf("%d rules found, there should be 0", len(rules))
|
||||
}
|
||||
|
||||
tbl := nft.getTable(tt.table, tt.family)
|
||||
tbl := nftest.Fw.GetTable(tt.table, tt.family)
|
||||
if tbl == nil {
|
||||
t.Errorf("table %s-%s should exist", tt.table, tt.family)
|
||||
}
|
||||
|
|
|
@ -1,63 +1,17 @@
|
|||
package nftables
|
||||
package nftables_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
nftb "github.com/evilsocket/opensnitch/daemon/firewall/nftables"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/exprs"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/nftest"
|
||||
"github.com/google/nftables"
|
||||
"github.com/vishvananda/netns"
|
||||
)
|
||||
|
||||
var (
|
||||
conn *nftables.Conn
|
||||
newNS netns.NsHandle
|
||||
|
||||
nft, _ = Fw()
|
||||
)
|
||||
|
||||
func init() {
|
||||
initMapsStore()
|
||||
}
|
||||
|
||||
func skipIfNotPrivileged(t *testing.T) {
|
||||
if os.Getenv("PRIVILEGED_TESTS") == "" {
|
||||
t.Skip("Set PRIVILEGED_TESTS to 1 to launch these tests, and launch them as root, or as a user allowed to create new namespaces.")
|
||||
}
|
||||
}
|
||||
|
||||
// https://github.com/google/nftables/blob/8f2d395e1089dea4966c483fbeae7e336917c095/internal/nftest/system_conn.go#L15
|
||||
func OpenSystemConn(t *testing.T) (*nftables.Conn, netns.NsHandle) {
|
||||
t.Helper()
|
||||
// We lock the goroutine into the current thread, as namespace operations
|
||||
// such as those invoked by `netns.New()` are thread-local. This is undone
|
||||
// in nftest.CleanupSystemConn().
|
||||
runtime.LockOSThread()
|
||||
|
||||
ns, err := netns.New()
|
||||
if err != nil {
|
||||
t.Fatalf("netns.New() failed: %v", err)
|
||||
}
|
||||
t.Log("OpenSystemConn() with NS:", ns)
|
||||
c, err := nftables.New(nftables.WithNetNSFd(int(ns)))
|
||||
if err != nil {
|
||||
t.Fatalf("nftables.New() failed: %v", err)
|
||||
}
|
||||
return c, ns
|
||||
}
|
||||
|
||||
func CleanupSystemConn(t *testing.T, newNS netns.NsHandle) {
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
if err := newNS.Close(); err != nil {
|
||||
t.Fatalf("newNS.Close() failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func tableExists(t *testing.T, origtbl *nftables.Table, family string) bool {
|
||||
func tableExists(t *testing.T, conn *nftables.Conn, origtbl *nftables.Table, family string) bool {
|
||||
tables, err := conn.ListTablesOfFamily(
|
||||
getFamilyCode(family),
|
||||
nftb.GetFamilyCode(family),
|
||||
)
|
||||
if err != nil {
|
||||
return false
|
||||
|
@ -73,54 +27,54 @@ func tableExists(t *testing.T, origtbl *nftables.Table, family string) bool {
|
|||
}
|
||||
|
||||
func TestAddTable(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
t.Run("inet family", func(t *testing.T) {
|
||||
tblxxx, err := nft.AddTable("xxx", exprs.NFT_FAMILY_INET)
|
||||
tblxxx, err := nftest.Fw.AddTable("xxx", exprs.NFT_FAMILY_INET)
|
||||
if err != nil {
|
||||
t.Error("table xxx-inet not added:", err)
|
||||
}
|
||||
if tableExists(t, tblxxx, exprs.NFT_FAMILY_INET) == false {
|
||||
if tableExists(t, nftest.Fw.Conn, tblxxx, exprs.NFT_FAMILY_INET) == false {
|
||||
t.Error("table xxx-inet not in the list")
|
||||
}
|
||||
|
||||
nft.delSystemTables()
|
||||
if tableExists(t, tblxxx, exprs.NFT_FAMILY_INET) {
|
||||
t.Errorf("table xxx-inet still exists: %+v", sysTables)
|
||||
nftest.Fw.DelSystemTables()
|
||||
if tableExists(t, nftest.Fw.Conn, tblxxx, exprs.NFT_FAMILY_INET) {
|
||||
t.Error("table xxx-inet still exists")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ip family", func(t *testing.T) {
|
||||
tblxxx, err := nft.AddTable("xxx", exprs.NFT_FAMILY_IP)
|
||||
tblxxx, err := nftest.Fw.AddTable("xxx", exprs.NFT_FAMILY_IP)
|
||||
if err != nil {
|
||||
t.Error("table xxx-ip not added:", err)
|
||||
}
|
||||
if tableExists(t, tblxxx, exprs.NFT_FAMILY_IP) == false {
|
||||
if tableExists(t, nftest.Fw.Conn, tblxxx, exprs.NFT_FAMILY_IP) == false {
|
||||
t.Error("table xxx-ip not in the list")
|
||||
}
|
||||
|
||||
nft.delSystemTables()
|
||||
if tableExists(t, tblxxx, exprs.NFT_FAMILY_IP) {
|
||||
t.Errorf("table xxx-ip still exists: %+v", sysTables)
|
||||
nftest.Fw.DelSystemTables()
|
||||
if tableExists(t, nftest.Fw.Conn, tblxxx, exprs.NFT_FAMILY_IP) {
|
||||
t.Errorf("table xxx-ip still exists:") // %+v", sysTables)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ip6 family", func(t *testing.T) {
|
||||
tblxxx, err := nft.AddTable("xxx", exprs.NFT_FAMILY_IP6)
|
||||
tblxxx, err := nftest.Fw.AddTable("xxx", exprs.NFT_FAMILY_IP6)
|
||||
if err != nil {
|
||||
t.Error("table xxx-ip6 not added:", err)
|
||||
}
|
||||
if tableExists(t, tblxxx, exprs.NFT_FAMILY_IP6) == false {
|
||||
if tableExists(t, nftest.Fw.Conn, tblxxx, exprs.NFT_FAMILY_IP6) == false {
|
||||
t.Error("table xxx-ip6 not in the list")
|
||||
}
|
||||
|
||||
nft.delSystemTables()
|
||||
if tableExists(t, tblxxx, exprs.NFT_FAMILY_IP6) {
|
||||
t.Errorf("table xxx-ip6 still exists: %+v", sysTables)
|
||||
nftest.Fw.DelSystemTables()
|
||||
if tableExists(t, nftest.Fw.Conn, tblxxx, exprs.NFT_FAMILY_IP6) {
|
||||
t.Errorf("table xxx-ip6 still exists:") // %+v", sysTables)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -128,31 +82,31 @@ func TestAddTable(t *testing.T) {
|
|||
// TestAddInterceptionTables checks if the needed tables have been created.
|
||||
// We use 2: mangle-inet for intercepting outbound connections, and filter-inet for DNS responses interception
|
||||
func TestAddInterceptionTables(t *testing.T) {
|
||||
skipIfNotPrivileged(t)
|
||||
nftest.SkipIfNotPrivileged(t)
|
||||
|
||||
conn, newNS = OpenSystemConn(t)
|
||||
defer CleanupSystemConn(t, newNS)
|
||||
nft.conn = conn
|
||||
conn, newNS := nftest.OpenSystemConn(t)
|
||||
defer nftest.CleanupSystemConn(t, newNS)
|
||||
nftest.Fw.Conn = conn
|
||||
|
||||
if err := nft.addInterceptionTables(); err != nil {
|
||||
if err := nftest.Fw.AddInterceptionTables(); err != nil {
|
||||
t.Errorf("addInterceptionTables() error: %s", err)
|
||||
}
|
||||
|
||||
t.Run("mangle-inet", func(t *testing.T) {
|
||||
tblmangle := nft.getTable(exprs.NFT_CHAIN_MANGLE, exprs.NFT_FAMILY_INET)
|
||||
tblmangle := nftest.Fw.GetTable(exprs.NFT_CHAIN_MANGLE, exprs.NFT_FAMILY_INET)
|
||||
if tblmangle == nil {
|
||||
t.Error("interception table mangle-inet not in the list")
|
||||
}
|
||||
if tableExists(t, tblmangle, exprs.NFT_FAMILY_INET) == false {
|
||||
if tableExists(t, nftest.Fw.Conn, tblmangle, exprs.NFT_FAMILY_INET) == false {
|
||||
t.Error("table mangle-inet not in the list")
|
||||
}
|
||||
})
|
||||
t.Run("filter-inet", func(t *testing.T) {
|
||||
tblfilter := nft.getTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
tblfilter := nftest.Fw.GetTable(exprs.NFT_CHAIN_FILTER, exprs.NFT_FAMILY_INET)
|
||||
if tblfilter == nil {
|
||||
t.Error("interception table filter-inet not in the list")
|
||||
}
|
||||
if tableExists(t, tblfilter, exprs.NFT_FAMILY_INET) == false {
|
||||
if tableExists(t, nftest.Fw.Conn, tblfilter, exprs.NFT_FAMILY_INET) == false {
|
||||
t.Error("table filter-inet not in the list")
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package nftables
|
||||
package nftables_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
nftb "github.com/evilsocket/opensnitch/daemon/firewall/nftables"
|
||||
"github.com/evilsocket/opensnitch/daemon/firewall/nftables/exprs"
|
||||
"github.com/google/nftables"
|
||||
)
|
||||
|
@ -23,28 +24,28 @@ type chainPrioT struct {
|
|||
func TestGetConntrackPriority(t *testing.T) {
|
||||
|
||||
t.Run("hook-prerouting", func(t *testing.T) {
|
||||
cprio, ctype := getConntrackPriority(exprs.NFT_HOOK_PREROUTING)
|
||||
cprio, ctype := nftb.GetConntrackPriority(exprs.NFT_HOOK_PREROUTING)
|
||||
if cprio != nftables.ChainPriorityConntrack && ctype != nftables.ChainTypeFilter {
|
||||
t.Errorf("invalid conntrack priority or type for hook PREROUTING: %+v, %+v", cprio, ctype)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("hook-output", func(t *testing.T) {
|
||||
cprio, ctype := getConntrackPriority(exprs.NFT_HOOK_OUTPUT)
|
||||
cprio, ctype := nftb.GetConntrackPriority(exprs.NFT_HOOK_OUTPUT)
|
||||
if cprio != nftables.ChainPriorityNATSource && ctype != nftables.ChainTypeFilter {
|
||||
t.Errorf("invalid conntrack priority or type for hook OUTPUT: %+v, %+v", cprio, ctype)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("hook-postrouting", func(t *testing.T) {
|
||||
cprio, ctype := getConntrackPriority(exprs.NFT_HOOK_POSTROUTING)
|
||||
cprio, ctype := nftb.GetConntrackPriority(exprs.NFT_HOOK_POSTROUTING)
|
||||
if cprio != nftables.ChainPriorityConntrackHelper && ctype != nftables.ChainTypeNAT {
|
||||
t.Errorf("invalid conntrack priority or type for hook POSTROUTING: %+v, %+v", cprio, ctype)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("hook-input", func(t *testing.T) {
|
||||
cprio, ctype := getConntrackPriority(exprs.NFT_HOOK_INPUT)
|
||||
cprio, ctype := nftb.GetConntrackPriority(exprs.NFT_HOOK_INPUT)
|
||||
if cprio != nftables.ChainPriorityConntrackConfirm && ctype != nftables.ChainTypeFilter {
|
||||
t.Errorf("invalid conntrack priority or type for hook INPUT: %+v, %+v", cprio, ctype)
|
||||
}
|
||||
|
@ -146,7 +147,7 @@ func TestGetChainPriority(t *testing.T) {
|
|||
|
||||
for _, testChainPrio := range matrixTests {
|
||||
t.Run(testChainPrio.test, func(t *testing.T) {
|
||||
chainPrio, chainType := getChainPriority(testChainPrio.family, testChainPrio.chain, testChainPrio.hook)
|
||||
chainPrio, chainType := nftb.GetChainPriority(testChainPrio.family, testChainPrio.chain, testChainPrio.hook)
|
||||
|
||||
if testChainPrio.checkEqual {
|
||||
if chainPrio != testChainPrio.chainPrio && chainType != testChainPrio.chainType {
|
||||
|
@ -204,7 +205,7 @@ func TestInvalidChainPriority(t *testing.T) {
|
|||
|
||||
for _, testChainPrio := range matrixTests {
|
||||
t.Run(testChainPrio.test, func(t *testing.T) {
|
||||
chainPrio, chainType := getChainPriority(testChainPrio.family, testChainPrio.chain, testChainPrio.hook)
|
||||
chainPrio, chainType := nftb.GetChainPriority(testChainPrio.family, testChainPrio.chain, testChainPrio.hook)
|
||||
|
||||
if testChainPrio.checkEqual {
|
||||
if chainPrio != testChainPrio.chainPrio && chainType != testChainPrio.chainType {
|
||||
|
|
Loading…
Add table
Reference in a new issue