Add HostSNIRegexp rule matcher for TCP

This commit is contained in:
Romain 2022-03-18 16:04:08 +01:00 committed by GitHub
parent 0d58e8d1ad
commit 2da7fa0397
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 311 additions and 7 deletions

View file

@ -108,12 +108,66 @@ func Test_addTCPRoute(t *testing.T) {
serverName: "bar",
matchErr: true,
},
{
desc: "Empty HostSNIRegexp rule",
rule: "HostSNIRegexp()",
serverName: "foobar",
routeErr: true,
},
{
desc: "Empty HostSNIRegexp rule",
rule: "HostSNIRegexp(``)",
serverName: "foobar",
routeErr: true,
},
{
desc: "Valid HostSNIRegexp rule matching",
rule: "HostSNIRegexp(`{subdomain:[a-z]+}.foobar`)",
serverName: "sub.foobar",
},
{
desc: "Valid negative HostSNIRegexp rule matching",
rule: "!HostSNIRegexp(`bar`)",
serverName: "foobar",
},
{
desc: "Valid HostSNIRegexp rule matching with alternative case",
rule: "hostsniregexp(`foobar`)",
serverName: "foobar",
},
{
desc: "Valid HostSNIRegexp rule matching with alternative case",
rule: "HOSTSNIREGEXP(`foobar`)",
serverName: "foobar",
},
{
desc: "Valid HostSNIRegexp rule not matching",
rule: "HostSNIRegexp(`foobar`)",
serverName: "bar",
matchErr: true,
},
{
desc: "Valid negative HostSNI rule not matching",
rule: "!HostSNI(`bar`)",
serverName: "bar",
matchErr: true,
},
{
desc: "Valid HostSNIRegexp rule matching empty servername",
rule: "HostSNIRegexp(`{subdomain:[a-z]*}`)",
serverName: "",
},
{
desc: "Valid HostSNIRegexp rule with one name",
rule: "HostSNIRegexp(`{dummy}`)",
serverName: "toto",
},
{
desc: "Valid HostSNIRegexp rule with one name 2",
rule: "HostSNIRegexp(`{dummy}`)",
serverName: "toto.com",
matchErr: true,
},
{
desc: "Empty ClientIP rule",
rule: "ClientIP()",
@ -608,6 +662,123 @@ func Test_HostSNI(t *testing.T) {
}
}
func Test_HostSNIRegexp(t *testing.T) {
testCases := []struct {
desc string
pattern string
serverNames map[string]bool
buildErr bool
}{
{
desc: "unbalanced braces",
pattern: "subdomain:(foo\\.)?bar\\.com}",
buildErr: true,
},
{
desc: "empty group name",
pattern: "{:(foo\\.)?bar\\.com}",
buildErr: true,
},
{
desc: "empty capturing group",
pattern: "{subdomain:}",
buildErr: true,
},
{
desc: "malformed capturing group",
pattern: "{subdomain:(foo\\.?bar\\.com}",
buildErr: true,
},
{
desc: "not interpreted as a regexp",
pattern: "bar.com",
serverNames: map[string]bool{
"bar.com": true,
"barucom": false,
},
},
{
desc: "capturing group",
pattern: "{subdomain:(foo\\.)?bar\\.com}",
serverNames: map[string]bool{
"foo.bar.com": true,
"bar.com": true,
"fooubar.com": false,
"barucom": false,
"barcom": false,
},
},
{
desc: "non capturing group",
pattern: "{subdomain:(?:foo\\.)?bar\\.com}",
serverNames: map[string]bool{
"foo.bar.com": true,
"bar.com": true,
"fooubar.com": false,
"barucom": false,
"barcom": false,
},
},
{
desc: "regex insensitive",
pattern: "{dummy:[A-Za-z-]+\\.bar\\.com}",
serverNames: map[string]bool{
"FOO.bar.com": true,
"foo.bar.com": true,
"fooubar.com": false,
"barucom": false,
"barcom": false,
},
},
{
desc: "insensitive host",
pattern: "{dummy:[a-z-]+\\.bar\\.com}",
serverNames: map[string]bool{
"FOO.bar.com": true,
"foo.bar.com": true,
"fooubar.com": false,
"barucom": false,
"barcom": false,
},
},
{
desc: "insensitive host simple",
pattern: "foo.bar.com",
serverNames: map[string]bool{
"FOO.bar.com": true,
"foo.bar.com": true,
"fooubar.com": false,
"barucom": false,
"barcom": false,
},
},
}
for _, test := range testCases {
test := test
t.Run(test.desc, func(t *testing.T) {
t.Parallel()
matchersTree := &matchersTree{}
err := hostSNIRegexp(matchersTree, test.pattern)
if test.buildErr {
require.Error(t, err)
return
}
require.NoError(t, err)
for serverName, match := range test.serverNames {
meta := ConnData{
serverName: serverName,
}
assert.Equal(t, match, matchersTree.match(meta))
}
})
}
}
func Test_ClientIP(t *testing.T) {
testCases := []struct {
desc string