mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-03 15:00:26 +08:00
734 lines
13 KiB
Go
734 lines
13 KiB
Go
package waf
|
|
|
|
import (
|
|
"github.com/TeaOSLab/EdgeNode/internal/waf/checkpoints"
|
|
"github.com/TeaOSLab/EdgeNode/internal/waf/requests"
|
|
"github.com/iwind/TeaGo/assert"
|
|
"github.com/iwind/TeaGo/maps"
|
|
"net/http"
|
|
"net/url"
|
|
"testing"
|
|
)
|
|
|
|
func TestRule_Init_Single(t *testing.T) {
|
|
rule := NewRule()
|
|
rule.Param = "${arg.name}"
|
|
rule.Operator = RuleOperatorEqString
|
|
rule.Value = "lu"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Log(rule.singleParam, rule.singleCheckpoint)
|
|
rawReq, err := http.NewRequest(http.MethodGet, "http://teaos.cn/hello?name=lu&age=20", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
req := requests.NewTestRequest(rawReq)
|
|
t.Log(rule.MatchRequest(req))
|
|
}
|
|
|
|
func TestRule_Init_Composite(t *testing.T) {
|
|
rule := NewRule()
|
|
rule.Param = "${arg.name} ${arg.age}"
|
|
rule.Operator = RuleOperatorContains
|
|
rule.Value = "lu"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Log(rule.singleParam, rule.singleCheckpoint)
|
|
|
|
rawReq, err := http.NewRequest(http.MethodGet, "http://teaos.cn/hello?name=lu&age=20", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
req := requests.NewTestRequest(rawReq)
|
|
t.Log(rule.MatchRequest(req))
|
|
}
|
|
|
|
func TestRule_Test(t *testing.T) {
|
|
a := assert.NewAssertion(t)
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorGt
|
|
rule.Value = "123"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("124"))
|
|
a.IsFalse(rule.Test("123"))
|
|
a.IsFalse(rule.Test("122"))
|
|
a.IsFalse(rule.Test("abcdef"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorGte
|
|
rule.Value = "123"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("124"))
|
|
a.IsTrue(rule.Test("123"))
|
|
a.IsFalse(rule.Test("122"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorLt
|
|
rule.Value = "123"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("124"))
|
|
a.IsFalse(rule.Test("123"))
|
|
a.IsTrue(rule.Test("122"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorLte
|
|
rule.Value = "123"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("124"))
|
|
a.IsTrue(rule.Test("123"))
|
|
a.IsTrue(rule.Test("122"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorEq
|
|
rule.Value = "123"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("124"))
|
|
a.IsTrue(rule.Test("123"))
|
|
a.IsFalse(rule.Test("122"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorNeq
|
|
rule.Value = "123"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("124"))
|
|
a.IsFalse(rule.Test("123"))
|
|
a.IsTrue(rule.Test("122"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorEqString
|
|
rule.Value = "123"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("124"))
|
|
a.IsTrue(rule.Test("123"))
|
|
a.IsFalse(rule.Test("122"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorEqString
|
|
rule.Value = "abc"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("ABC"))
|
|
a.IsTrue(rule.Test("abc"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorEqString
|
|
rule.IsCaseInsensitive = true
|
|
rule.Value = "abc"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("ABC"))
|
|
a.IsTrue(rule.Test("abc"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorNeqString
|
|
rule.Value = "abc"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("124"))
|
|
a.IsFalse(rule.Test("abc"))
|
|
a.IsTrue(rule.Test("122"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorNeqString
|
|
rule.IsCaseInsensitive = true
|
|
rule.Value = "abc"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("ABC"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorMatch
|
|
rule.Value = "^\\d+"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("123"))
|
|
a.IsFalse(rule.Test("abc123"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorMatch
|
|
rule.Value = "abc"
|
|
rule.IsCaseInsensitive = true
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("ABC"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorMatch
|
|
rule.Value = "^\\d+"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test([]string{"123", "456", "abc"}))
|
|
a.IsFalse(rule.Test([]string{"abc123"}))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorNotMatch
|
|
rule.Value = "\\d+"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("123"))
|
|
a.IsTrue(rule.Test("abc"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorNotMatch
|
|
rule.Value = "abc"
|
|
rule.IsCaseInsensitive = true
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("ABC"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorNotMatch
|
|
rule.Value = "^\\d+"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test([]string{"123", "456", "abc"}))
|
|
a.IsTrue(rule.Test([]string{"abc123"}))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorMatch
|
|
rule.Value = "^(?i)[a-z]+$"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("ABC"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorContains
|
|
rule.Value = "Hello"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("Hello, World"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorContains
|
|
rule.Value = "hello"
|
|
rule.IsCaseInsensitive = true
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("Hello, World"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorContains
|
|
rule.Value = "Hello"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test([]string{"Hello", "World"}))
|
|
a.IsTrue(rule.Test(maps.Map{
|
|
"a": "World", "b": "Hello",
|
|
}))
|
|
a.IsFalse(rule.Test(maps.Map{
|
|
"a": "World", "b": "Hello2",
|
|
}))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorNotContains
|
|
rule.Value = "Hello"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("Hello, World"))
|
|
a.IsTrue(rule.Test("World"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorNotContains
|
|
rule.Value = "hello"
|
|
rule.IsCaseInsensitive = true
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("Hello, World"))
|
|
a.IsTrue(rule.Test("World"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorPrefix
|
|
rule.Value = "Hello"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("Hello, World"))
|
|
a.IsFalse(rule.Test("World, Hello"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorPrefix
|
|
rule.Value = "hello"
|
|
rule.IsCaseInsensitive = true
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsTrue(rule.Test("Hello, World"))
|
|
a.IsFalse(rule.Test("World, Hello"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorSuffix
|
|
rule.Value = "Hello"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("Hello, World"))
|
|
a.IsTrue(rule.Test("World, Hello"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorSuffix
|
|
rule.Value = "hello"
|
|
rule.IsCaseInsensitive = true
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("Hello, World"))
|
|
a.IsTrue(rule.Test("World, Hello"))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorHasKey
|
|
rule.Value = "Hello"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("Hello, World"))
|
|
a.IsTrue(rule.Test(maps.Map{
|
|
"Hello": "World",
|
|
}))
|
|
a.IsFalse(rule.Test(maps.Map{
|
|
"Hello1": "World",
|
|
}))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorHasKey
|
|
rule.Value = "hello"
|
|
rule.IsCaseInsensitive = true
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("Hello, World"))
|
|
a.IsTrue(rule.Test(maps.Map{
|
|
"Hello": "World",
|
|
}))
|
|
a.IsFalse(rule.Test(maps.Map{
|
|
"Hello1": "World",
|
|
}))
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorHasKey
|
|
rule.Value = "3"
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a.IsFalse(rule.Test("Hello, World"))
|
|
a.IsFalse(rule.Test(maps.Map{
|
|
"Hello": "World",
|
|
}))
|
|
a.IsTrue(rule.Test([]int{1, 2, 3, 4}))
|
|
}
|
|
}
|
|
|
|
func TestRule_MatchStar(t *testing.T) {
|
|
{
|
|
rule := NewRule()
|
|
rule.Operator = RuleOperatorMatch
|
|
rule.Value = `/\*(!|\x00)`
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Log(rule.Test("/*!"))
|
|
t.Log(rule.Test(url.QueryEscape("/*!")))
|
|
t.Log(url.QueryEscape("/*!"))
|
|
}
|
|
}
|
|
|
|
func TestRule_SetCheckpointFinder(t *testing.T) {
|
|
{
|
|
rule := NewRule()
|
|
rule.Param = "${arg.abc}"
|
|
rule.Operator = RuleOperatorMatch
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Logf("%#v", rule.singleCheckpoint)
|
|
}
|
|
|
|
{
|
|
rule := NewRule()
|
|
rule.Param = "${arg.abc}"
|
|
rule.Operator = RuleOperatorMatch
|
|
rule.checkpointFinder = func(prefix string) checkpoints.CheckpointInterface {
|
|
return new(checkpoints.SampleRequestCheckpoint)
|
|
}
|
|
err := rule.Init()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Logf("%#v", rule.singleCheckpoint)
|
|
}
|
|
}
|
|
|
|
func TestRule_Version(t *testing.T) {
|
|
a := assert.NewAssertion(t)
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorVersionRange,
|
|
Value: `1.0,1.1`,
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("1.0"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorVersionRange,
|
|
Value: `1.0,`,
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("1.0"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorVersionRange,
|
|
Value: `,1.1`,
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("1.0"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorVersionRange,
|
|
Value: `1.0,1.1`,
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsFalse(rule.Test("0.9"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorVersionRange,
|
|
Value: `1.0`,
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsFalse(rule.Test("0.9"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorVersionRange,
|
|
Value: `1.0`,
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("1.1"))
|
|
}
|
|
}
|
|
|
|
func TestRule_IP(t *testing.T) {
|
|
a := assert.NewAssertion(t)
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorEqIP,
|
|
Value: "hello",
|
|
}
|
|
a.IsNotNil(rule.Init())
|
|
a.IsFalse(rule.Test("hello"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorEqIP,
|
|
Value: "hello",
|
|
}
|
|
a.IsNotNil(rule.Init())
|
|
a.IsFalse(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorEqIP,
|
|
Value: "192.168.1.100",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorGtIP,
|
|
Value: "192.168.1.90",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorGteIP,
|
|
Value: "192.168.1.90",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorLtIP,
|
|
Value: "192.168.1.90",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.1.80"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorLteIP,
|
|
Value: "192.168.1.90",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.0.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPRange,
|
|
Value: "192.168.0.90,",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.0.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPRange,
|
|
Value: "192.168.0.90,192.168.1.100",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.0.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPRange,
|
|
Value: ",192.168.1.100",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.0.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPRange,
|
|
Value: "192.168.0.90,192.168.1.99",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsFalse(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPRange,
|
|
Value: "192.168.0.90/24",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsFalse(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPRange,
|
|
Value: "192.168.0.90/18",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPRange,
|
|
Value: "a/18",
|
|
}
|
|
a.IsNotNil(rule.Init())
|
|
a.IsFalse(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPMod10,
|
|
Value: "6",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPMod100,
|
|
Value: "76",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorIPMod,
|
|
Value: "10,6",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.1.100"))
|
|
}
|
|
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorNotIPRange,
|
|
Value: "192.168.0.90,192.168.1.100",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsFalse(rule.Test("192.168.0.100"))
|
|
}
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorNotIPRange,
|
|
Value: "192.168.0.90,192.168.1.100",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.168.2.100"))
|
|
}
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorNotIPRange,
|
|
Value: "192.168.0.90/8",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsFalse(rule.Test("192.168.2.100"))
|
|
}
|
|
{
|
|
rule := Rule{
|
|
Operator: RuleOperatorNotIPRange,
|
|
Value: "192.168.0.90/16",
|
|
}
|
|
a.IsNil(rule.Init())
|
|
a.IsTrue(rule.Test("192.169.2.100"))
|
|
}
|
|
}
|