Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/corazawaf/coraza-caddy into…
Browse files Browse the repository at this point in the history
… improves_test
  • Loading branch information
jcchavezs committed Jan 9, 2025
2 parents f7b06c0 + 0959a59 commit 9bfe50f
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 13 deletions.
14 changes: 13 additions & 1 deletion coraza_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,21 @@ func TestPostMultipart(t *testing.T) {
tester.AssertResponseCode(req, 200)
}

func TestClientIpRule(t *testing.T) {
tester := newTester("test.init.config", t)

// client_ip will be 127.0.0.1
req, _ := http.NewRequest("GET", baseURL+"/", nil)
tester.AssertResponseCode(req, 200)

// client_ip will be 127.0.0.2
req, _ = http.NewRequest("GET", baseURL+"/", nil)
req.Header.Add("X-Forwarded-For", "127.0.0.2")
tester.AssertResponseCode(req, 403)
}

func multipartRequest(t *testing.T, req *http.Request) error {
t.Helper()

var b bytes.Buffer
w := multipart.NewWriter(&b)
tempfile, err := os.CreateTemp(t.TempDir(), "tmpfile*")
Expand Down
14 changes: 2 additions & 12 deletions http.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,15 @@ import (
"io"
"net"
"net/http"
"strconv"
"strings"

"github.com/corazawaf/coraza/v3/types"
)

// Copied from https://github.com/corazawaf/coraza/blob/main/http/middleware.go

func processRequest(tx types.Transaction, req *http.Request) (*types.Interruption, error) {
var (
client string
cport int
)
// IMPORTANT: Some http.Request.RemoteAddr implementations will not contain port or contain IPV6: [2001:db8::1]:8080
idx := strings.LastIndexByte(req.RemoteAddr, ':')
if idx != -1 {
client = req.RemoteAddr[:idx]
cport, _ = strconv.Atoi(req.RemoteAddr[idx+1:])
}

client, cport := getClientAddress(req)

var in *types.Interruption
// There is no socket access in the request object, so we neither know the server client nor port.
Expand Down
6 changes: 6 additions & 0 deletions test.init.config
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
debug
auto_https off
order coraza_waf first
servers {
# Enable trusted_proxies to make Caddy populate client_ip variable from X-Forwarded-For header, in the case Caddy is behind a reverse proxy
# See : https://caddyserver.com/docs/caddyfile/options#trusted-proxies
trusted_proxies static private_ranges
}
}

:8080 {
Expand All @@ -11,6 +16,7 @@
SecAction "id:149,pass,log, msg:'Some test msg',logdata:'logdata'"
SecRule REQUEST_URI "test5" "id:2, deny, log, phase:1,status:403"
SecRule REQUEST_URI "test6" "id:4, deny, log, phase:3,status:403"
SecRule REMOTE_ADDR "@ipMatch 127.0.0.2" "id:5, deny, log, phase:1,status:403"
Include testdata/sample1.conf
Include testdata/sample2.conf
`
Expand Down
35 changes: 35 additions & 0 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ package coraza

import (
"math/rand"
"net"
"net/http"
"strconv"
"strings"
"sync"
"time"

"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)

const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
Expand Down Expand Up @@ -45,3 +50,33 @@ func randomString(n int) string {

return sb.String()
}

func getClientAddress(req *http.Request) (string, int) {

var (
clientIp string
clientPort int
)

if address, ok := caddyhttp.GetVar(req.Context(), caddyhttp.ClientIPVarKey).(string); ok && len(address) > 0 {
ip, port, _ := net.SplitHostPort(address)
if ip != "" {
clientIp = ip
} else {
clientIp = address
}
clientPort, _ = strconv.Atoi(port)
} else {
idx := strings.LastIndexByte(req.RemoteAddr, ':')
if idx != -1 {
clientIp = req.RemoteAddr[:idx]
clientPort, _ = strconv.Atoi(req.RemoteAddr[idx+1:])
} else {
clientIp = req.RemoteAddr
clientPort = 0
}
}

return clientIp, clientPort

}
51 changes: 51 additions & 0 deletions utils_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2023 The OWASP Coraza contributors
// SPDX-License-Identifier: Apache-2.0

package coraza

import (
"context"
"fmt"
"net/http"
"testing"

"github.com/caddyserver/caddy/v2/modules/caddyhttp"
"github.com/stretchr/testify/require"
)

func TestParsegClientAddress(t *testing.T) {

remoteIp := "127.0.0.1"
remotePort := 9090
clientIp := "127.0.0.2"
clientPort := 8080

req, _ := http.NewRequest("GET", "/", nil)

req.RemoteAddr = fmt.Sprintf("%v:%v", remoteIp, remotePort)
ip, port := getClientAddress(req)
require.Equal(t, remoteIp, ip)
require.Equal(t, remotePort, port)

req.RemoteAddr = remoteIp
ip, port = getClientAddress(req)
require.Equal(t, remoteIp, ip)
require.Equal(t, 0, port)

req = req.WithContext(context.WithValue(req.Context(), caddyhttp.VarsCtxKey, make(map[string]any)))
req.RemoteAddr = fmt.Sprintf("%v:%v", remoteIp, remotePort)

ip, port = getClientAddress(req)
require.Equal(t, remoteIp, ip)
require.Equal(t, remotePort, port)

caddyhttp.SetVar(req.Context(), caddyhttp.ClientIPVarKey, fmt.Sprintf("%v:%v", clientIp, clientPort))
ip, port = getClientAddress(req)
require.Equal(t, clientIp, ip)
require.Equal(t, clientPort, port)

caddyhttp.SetVar(req.Context(), caddyhttp.ClientIPVarKey, clientIp)
ip, port = getClientAddress(req)
require.Equal(t, clientIp, ip)
require.Equal(t, 0, port)
}

0 comments on commit 9bfe50f

Please sign in to comment.