Replies: 2 comments 1 reply
-
|
I'm no expert here, but I doubt that either way will significantly impact it. If I had to guess it would probably only be better to do regexp if you had thousands of rules. Otherwise it would be faster to have more rules. But the likelyhood of you noticing would also be low, because if you really have enough rules for that to matter than you should reconsider what you are running on that device. |
Beta Was this translation helpful? Give feedback.
-
|
I'd imagine that this will depend on a variety of factors including complexity, traffic, and load, etc. The most accurate measurement would require testing your rules/system using the built-in trace and daemon option: But I became curious and wrote a basic test. It shows that regex processing makes a significant impact. There's much more happening with OpenSnitch during real-world rule processing but this test attempts to emulate the regex rule Test code
module local/test/opensnitch_regexp_string_bench_test
go 1.25.5
// opensnitch_regexp_string_bench.go
package main
import (
"regexp"
"sync"
"testing"
)
// Attempt to emulate OpenSnitch
type Operator struct {
re *regexp.Regexp
Data string
isCompiled bool
sync.RWMutex
}
func NewOperator(data string) (*Operator, error) {
op := Operator{
Data: data,
}
return &op, nil
}
func CompileRegex(o *Operator, b *testing.B) error {
if o.isCompiled {
return nil
}
re, err := regexp.Compile(o.Data)
if err != nil {
return err
}
o.re = re
// fmt doesn't output with bench
b.Logf("Operator compiled: %s", o.Data)
o.isCompiled = true
return nil
}
// Testing vars
var dstHostString = "internal.host.name"
// Simple regex
var simpleHostRegexString = "^(([A-Za-z0-9]+)\\.host\\.name)$"
var simpleHostRegexp = regexp.MustCompile(simpleHostRegexString)
var dstSimpleHostOperator, _ = NewOperator(
simpleHostRegexString,
)
// Complex regex
var complexHostRegexString = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"
var complexHostRegexp = regexp.MustCompile(complexHostRegexString)
var dstComplexHostOperator, _ = NewOperator(
complexHostRegexString,
)
// Benchmark basic string comparison
func BenchmarkCompareBasicStringTest(b *testing.B) {
for i := 0; i < b.N; i++ {
if dstHostString == "internal.host.name" {
_ = true
} else {
_ = false
}
}
}
// Simple regex
// Benchmark simple regex logic emulating OpenSnitch "isCompiled"
func BenchmarkCompileSimpleOperatorTest(b *testing.B) {
for i := 0; i < b.N; i++ {
CompileRegex(dstSimpleHostOperator, b)
_ = dstSimpleHostOperator.re.MatchString(dstHostString)
}
}
// Benchmark simple regex MustCompile()
func BenchmarkMustCompileSimpleRegexModuleTest(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = simpleHostRegexp.MatchString(dstHostString)
}
}
// Benchmark simple regex Compile()
func BenchmarkCompileSimpleRegexTest(b *testing.B) {
for i := 0; i < b.N; i++ {
re, _ := regexp.Compile(simpleHostRegexString)
_ = re.MatchString(dstHostString)
}
}
// Complex regex
// Benchmark complex regex logic emulating OpenSnitch "isCompiled"
func BenchmarkCompileComplexOperatorTest(b *testing.B) {
for i := 0; i < b.N; i++ {
CompileRegex(dstComplexHostOperator, b)
_ = dstComplexHostOperator.re.MatchString(dstHostString)
}
}
// Benchmark complex regex MustCompile()
func BenchmarkMustCompileComplexRegexModuleTest(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = complexHostRegexp.MatchString(dstHostString)
}
}
// Benchmark complex regex Compile()
func BenchmarkCompileComplexRegexTest(b *testing.B) {
for i := 0; i < b.N; i++ {
re, _ := regexp.Compile(complexHostRegexString)
_ = re.MatchString(dstHostString)
}
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm wondering what is more efficient for opensnitch, in terms of rules processing. Let's say I want to allow systemd-resolved to use ports 853, 5353 and 5355, but nothing else. And I want these rules to process as fast as possible.
Is it better to write one priority rule with the port as (853|5353|5355), or three priority rules with one port in each?
If the answer is regex, at what point does that scale into multiple rules, if ever?
My intuition tells me that regex is probably better always as long as you aren't using complex regex features, because you are walking less memory, but I don't know go so it's not clear from reading the code.
Beta Was this translation helpful? Give feedback.
All reactions