mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 15:26:40 +00:00
add TLS
This commit is contained in:
@@ -8,6 +8,7 @@ Load testing tool for the NetBird signal server.
|
||||
- **Two exchange modes**:
|
||||
- **Single message**: Each pair exchanges one message for validation
|
||||
- **Continuous exchange**: Pairs continuously exchange messages for a specified duration (e.g., 30 seconds, 10 minutes)
|
||||
- **TLS/HTTPS support**: Connect to TLS-enabled signal servers with optional certificate verification
|
||||
- **Configurable message interval**: Control message send rate in continuous mode
|
||||
- **Message exchange validation**: Validates encrypted body size > 0
|
||||
- **Comprehensive metrics**: Tracks throughput, success/failure rates, and latency statistics
|
||||
@@ -53,18 +54,34 @@ go build -o signal-loadtest
|
||||
-test-duration 15m \
|
||||
-log-level debug
|
||||
|
||||
# TLS server with valid certificate
|
||||
./signal-loadtest \
|
||||
-server https://signal.example.com:443 \
|
||||
-pairs-per-sec 10 \
|
||||
-total-pairs 50 \
|
||||
-message-size 100
|
||||
|
||||
# TLS server with self-signed certificate
|
||||
./signal-loadtest \
|
||||
-server https://localhost:443 \
|
||||
-pairs-per-sec 5 \
|
||||
-total-pairs 10 \
|
||||
-insecure-skip-verify \
|
||||
-log-level debug
|
||||
|
||||
# Show help
|
||||
./signal-loadtest -h
|
||||
```
|
||||
|
||||
**Available Flags:**
|
||||
- `-server`: Signal server URL (default: `http://localhost:10000`)
|
||||
- `-server`: Signal server URL (http:// or https://) (default: `http://localhost:10000`)
|
||||
- `-pairs-per-sec`: Peer pairs created per second (default: 10)
|
||||
- `-total-pairs`: Total number of peer pairs (default: 100)
|
||||
- `-message-size`: Message size in bytes (default: 100)
|
||||
- `-test-duration`: Maximum test duration, 0 = unlimited (default: 0)
|
||||
- `-exchange-duration`: Continuous exchange duration per pair, 0 = single message (default: 0)
|
||||
- `-message-interval`: Interval between messages in continuous mode (default: 100ms)
|
||||
- `-insecure-skip-verify`: Skip TLS certificate verification for self-signed certificates (default: false)
|
||||
- `-log-level`: Log level: trace, debug, info, warn, error (default: info)
|
||||
|
||||
### Running Tests
|
||||
@@ -156,6 +173,7 @@ func main() {
|
||||
- **TestDuration**: Maximum test duration (optional, 0 = no limit)
|
||||
- **ExchangeDuration**: Duration for continuous message exchange per pair (0 = single message)
|
||||
- **MessageInterval**: Interval between messages in continuous mode (default: 100ms)
|
||||
- **InsecureSkipVerify**: Skip TLS certificate verification (for self-signed certificates)
|
||||
- **RampUpDuration**: Gradual ramp-up period (not yet implemented)
|
||||
|
||||
## Metrics
|
||||
|
||||
@@ -2,11 +2,13 @@ package loadtest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
"google.golang.org/grpc/credentials/insecure"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
@@ -24,9 +26,23 @@ type Client struct {
|
||||
msgChannel chan *proto.EncryptedMessage
|
||||
}
|
||||
|
||||
// ClientConfig holds optional configuration for the client
|
||||
type ClientConfig struct {
|
||||
InsecureSkipVerify bool
|
||||
}
|
||||
|
||||
// NewClient creates a new signal client for load testing
|
||||
func NewClient(serverURL, peerID string) (*Client, error) {
|
||||
addr, opts, err := parseServerURL(serverURL)
|
||||
return NewClientWithConfig(serverURL, peerID, nil)
|
||||
}
|
||||
|
||||
// NewClientWithConfig creates a new signal client with custom TLS configuration
|
||||
func NewClientWithConfig(serverURL, peerID string, config *ClientConfig) (*Client, error) {
|
||||
if config == nil {
|
||||
config = &ClientConfig{}
|
||||
}
|
||||
|
||||
addr, opts, err := parseServerURL(serverURL, config.InsecureSkipVerify)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse server URL: %w", err)
|
||||
}
|
||||
@@ -124,7 +140,7 @@ func (c *Client) receiveMessages() {
|
||||
}
|
||||
}
|
||||
|
||||
func parseServerURL(serverURL string) (string, []grpc.DialOption, error) {
|
||||
func parseServerURL(serverURL string, insecureSkipVerify bool) (string, []grpc.DialOption, error) {
|
||||
serverURL = strings.TrimSpace(serverURL)
|
||||
if serverURL == "" {
|
||||
return "", nil, fmt.Errorf("server URL is empty")
|
||||
@@ -135,7 +151,11 @@ func parseServerURL(serverURL string) (string, []grpc.DialOption, error) {
|
||||
|
||||
if strings.HasPrefix(serverURL, "https://") {
|
||||
addr = strings.TrimPrefix(serverURL, "https://")
|
||||
return "", nil, fmt.Errorf("TLS support not yet implemented")
|
||||
tlsConfig := &tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
InsecureSkipVerify: insecureSkipVerify,
|
||||
}
|
||||
opts = append(opts, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
|
||||
} else if strings.HasPrefix(serverURL, "http://") {
|
||||
addr = strings.TrimPrefix(serverURL, "http://")
|
||||
opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
|
||||
@@ -12,24 +12,26 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
serverURL string
|
||||
pairsPerSecond int
|
||||
totalPairs int
|
||||
messageSize int
|
||||
testDuration time.Duration
|
||||
exchangeDuration time.Duration
|
||||
messageInterval time.Duration
|
||||
logLevel string
|
||||
serverURL string
|
||||
pairsPerSecond int
|
||||
totalPairs int
|
||||
messageSize int
|
||||
testDuration time.Duration
|
||||
exchangeDuration time.Duration
|
||||
messageInterval time.Duration
|
||||
insecureSkipVerify bool
|
||||
logLevel string
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&serverURL, "server", "http://localhost:10000", "Signal server URL")
|
||||
flag.StringVar(&serverURL, "server", "http://localhost:10000", "Signal server URL (http:// or https://)")
|
||||
flag.IntVar(&pairsPerSecond, "pairs-per-sec", 10, "Number of peer pairs to create per second")
|
||||
flag.IntVar(&totalPairs, "total-pairs", 100, "Total number of peer pairs to create")
|
||||
flag.IntVar(&messageSize, "message-size", 100, "Size of test message in bytes")
|
||||
flag.DurationVar(&testDuration, "test-duration", 0, "Maximum test duration (0 = unlimited)")
|
||||
flag.DurationVar(&exchangeDuration, "exchange-duration", 0, "Duration for continuous message exchange per pair (0 = single message)")
|
||||
flag.DurationVar(&messageInterval, "message-interval", 100*time.Millisecond, "Interval between messages in continuous mode")
|
||||
flag.BoolVar(&insecureSkipVerify, "insecure-skip-verify", false, "Skip TLS certificate verification (use with self-signed certificates)")
|
||||
flag.StringVar(&logLevel, "log-level", "info", "Log level (trace, debug, info, warn, error)")
|
||||
}
|
||||
|
||||
@@ -44,13 +46,14 @@ func main() {
|
||||
log.SetLevel(level)
|
||||
|
||||
config := loadtest.LoadTestConfig{
|
||||
ServerURL: serverURL,
|
||||
PairsPerSecond: pairsPerSecond,
|
||||
TotalPairs: totalPairs,
|
||||
MessageSize: messageSize,
|
||||
TestDuration: testDuration,
|
||||
ExchangeDuration: exchangeDuration,
|
||||
MessageInterval: messageInterval,
|
||||
ServerURL: serverURL,
|
||||
PairsPerSecond: pairsPerSecond,
|
||||
TotalPairs: totalPairs,
|
||||
MessageSize: messageSize,
|
||||
TestDuration: testDuration,
|
||||
ExchangeDuration: exchangeDuration,
|
||||
MessageInterval: messageInterval,
|
||||
InsecureSkipVerify: insecureSkipVerify,
|
||||
}
|
||||
|
||||
if err := validateConfig(config); err != nil {
|
||||
@@ -64,6 +67,9 @@ func main() {
|
||||
log.Infof(" Pairs per second: %d", config.PairsPerSecond)
|
||||
log.Infof(" Total pairs: %d", config.TotalPairs)
|
||||
log.Infof(" Message size: %d bytes", config.MessageSize)
|
||||
if config.InsecureSkipVerify {
|
||||
log.Warnf(" TLS certificate verification: DISABLED (insecure)")
|
||||
}
|
||||
if config.TestDuration > 0 {
|
||||
log.Infof(" Test duration: %v", config.TestDuration)
|
||||
}
|
||||
|
||||
@@ -12,14 +12,15 @@ import (
|
||||
|
||||
// LoadTestConfig configuration for the load test
|
||||
type LoadTestConfig struct {
|
||||
ServerURL string
|
||||
PairsPerSecond int
|
||||
TotalPairs int
|
||||
MessageSize int
|
||||
TestDuration time.Duration
|
||||
ExchangeDuration time.Duration
|
||||
MessageInterval time.Duration
|
||||
RampUpDuration time.Duration
|
||||
ServerURL string
|
||||
PairsPerSecond int
|
||||
TotalPairs int
|
||||
MessageSize int
|
||||
TestDuration time.Duration
|
||||
ExchangeDuration time.Duration
|
||||
MessageInterval time.Duration
|
||||
RampUpDuration time.Duration
|
||||
InsecureSkipVerify bool
|
||||
}
|
||||
|
||||
// LoadTestMetrics metrics collected during the load test
|
||||
@@ -138,13 +139,17 @@ func (lt *LoadTest) executePairExchange(pairID int) error {
|
||||
senderID := fmt.Sprintf("sender-%d", pairID)
|
||||
receiverID := fmt.Sprintf("receiver-%d", pairID)
|
||||
|
||||
sender, err := NewClient(lt.config.ServerURL, senderID)
|
||||
clientConfig := &ClientConfig{
|
||||
InsecureSkipVerify: lt.config.InsecureSkipVerify,
|
||||
}
|
||||
|
||||
sender, err := NewClientWithConfig(lt.config.ServerURL, senderID, clientConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create sender: %w", err)
|
||||
}
|
||||
defer sender.Close()
|
||||
|
||||
receiver, err := NewClient(lt.config.ServerURL, receiverID)
|
||||
receiver, err := NewClientWithConfig(lt.config.ServerURL, receiverID, clientConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("create receiver: %w", err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user