mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-22 10:42:30 +00:00
54 lines
2.1 KiB
Go
54 lines
2.1 KiB
Go
// Copyright 2026 Beacon Contributors
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
package router
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/netip"
|
|
"testing"
|
|
|
|
"github.com/MeshCore-Beacon/beacon-server/internal/config"
|
|
)
|
|
|
|
func TestWebSocketAttemptClientIdentity(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
name, firstPeer, secondPeer, firstHeader, secondHeader string
|
|
trusted, shared bool
|
|
}{
|
|
{"untrusted rotation", "198.51.100.1:1", "198.51.100.1:2", "192.0.2.1", "192.0.2.2", false, true},
|
|
{"independent peers", "198.51.100.1:1", "198.51.100.2:1", "192.0.2.1", "192.0.2.1", false, false},
|
|
{"trusted independent clients", "127.0.0.1:1", "127.0.0.1:2", "198.51.100.1", "198.51.100.2", true, false},
|
|
{"trusted shared client", "127.0.0.1:1", "127.0.0.1:2", "198.51.100.1", "198.51.100.1", true, true},
|
|
{"IPv6 shared prefix", "[2001:db8:1::1]:1", "[2001:db8:1::2]:2", "", "", false, true},
|
|
{"IPv6 independent prefixes", "[2001:db8:1::1]:1", "[2001:db8:2::1]:2", "", "", false, false},
|
|
} {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
cfg := config.ServerConfig{}
|
|
if tc.trusted {
|
|
cfg.TrustedProxies = []netip.Prefix{netip.MustParsePrefix("127.0.0.1/32")}
|
|
}
|
|
handler := New(nil, nil, nil, Options{MaxConnsPerIP: 5, MaxConnectsPerMinute: 1, Server: cfg})
|
|
attempt := func(peer, header string) int {
|
|
request := httptest.NewRequest(http.MethodGet, "/ws", nil)
|
|
request.RemoteAddr = peer
|
|
request.Header.Set("X-Real-IP", header)
|
|
request.Header.Set("X-Forwarded-For", header)
|
|
request.Header.Set("True-Client-IP", header)
|
|
response := httptest.NewRecorder()
|
|
handler.ServeHTTP(response, request)
|
|
return response.Code
|
|
}
|
|
first := attempt(tc.firstPeer, tc.firstHeader)
|
|
if first < 400 || first == http.StatusTooManyRequests {
|
|
t.Fatalf("first failed handshake: %d", first)
|
|
}
|
|
second := attempt(tc.secondPeer, tc.secondHeader)
|
|
if (second == http.StatusTooManyRequests) != tc.shared || second < 400 {
|
|
t.Fatalf("second handshake status %d; shared budget=%v", second, tc.shared)
|
|
}
|
|
})
|
|
}
|
|
}
|