mirror of
https://github.com/cloudflare/cloudflared.git
synced 2025-07-27 19:19:57 +00:00
TUN-9319: Add dynamic loading of features to connections via ConnectionOptionsSnapshot
Make sure to enforce snapshots of features and client information for each connection so that the feature information can change in the background. This allows for new features to only be applied to a connection if it completely disconnects and attempts a reconnect. Updates the feature refresh time to 1 hour from previous cloudflared versions which refreshed every 6 hours. Closes TUN-9319
This commit is contained in:
74
client/config.go
Normal file
74
client/config.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/rs/zerolog"
|
||||
|
||||
"github.com/cloudflare/cloudflared/features"
|
||||
"github.com/cloudflare/cloudflared/tunnelrpc/pogs"
|
||||
)
|
||||
|
||||
// Config captures the local client runtime configuration.
|
||||
type Config struct {
|
||||
ConnectorID uuid.UUID
|
||||
Version string
|
||||
Arch string
|
||||
|
||||
featureSelector features.FeatureSelector
|
||||
}
|
||||
|
||||
func NewConfig(version string, arch string, featureSelector features.FeatureSelector) (*Config, error) {
|
||||
connectorID, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to generate a connector UUID: %w", err)
|
||||
}
|
||||
return &Config{
|
||||
ConnectorID: connectorID,
|
||||
Version: version,
|
||||
Arch: arch,
|
||||
featureSelector: featureSelector,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ConnectionOptionsSnapshot is a snapshot of the current client information used to initialize a connection.
|
||||
//
|
||||
// The FeatureSnapshot is the features that are available for this connection. At the client level they may
|
||||
// change, but they will not change within the scope of this struct.
|
||||
type ConnectionOptionsSnapshot struct {
|
||||
client pogs.ClientInfo
|
||||
originLocalIP net.IP
|
||||
numPreviousAttempts uint8
|
||||
FeatureSnapshot features.FeatureSnapshot
|
||||
}
|
||||
|
||||
func (c *Config) ConnectionOptionsSnapshot(originIP net.IP, previousAttempts uint8) *ConnectionOptionsSnapshot {
|
||||
snapshot := c.featureSelector.Snapshot()
|
||||
return &ConnectionOptionsSnapshot{
|
||||
client: pogs.ClientInfo{
|
||||
ClientID: c.ConnectorID[:],
|
||||
Version: c.Version,
|
||||
Arch: c.Arch,
|
||||
Features: snapshot.FeaturesList,
|
||||
},
|
||||
originLocalIP: originIP,
|
||||
numPreviousAttempts: previousAttempts,
|
||||
FeatureSnapshot: snapshot,
|
||||
}
|
||||
}
|
||||
|
||||
func (c ConnectionOptionsSnapshot) ConnectionOptions() *pogs.ConnectionOptions {
|
||||
return &pogs.ConnectionOptions{
|
||||
Client: c.client,
|
||||
OriginLocalIP: c.originLocalIP,
|
||||
ReplaceExisting: false,
|
||||
CompressionQuality: 0,
|
||||
NumPreviousAttempts: c.numPreviousAttempts,
|
||||
}
|
||||
}
|
||||
|
||||
func (c ConnectionOptionsSnapshot) LogFields(event *zerolog.Event) *zerolog.Event {
|
||||
return event.Strs("features", c.client.Features)
|
||||
}
|
50
client/config_test.go
Normal file
50
client/config_test.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/cloudflare/cloudflared/features"
|
||||
)
|
||||
|
||||
func TestGenerateConnectionOptions(t *testing.T) {
|
||||
version := "1234"
|
||||
arch := "linux_amd64"
|
||||
originIP := net.ParseIP("192.168.1.1")
|
||||
var previousAttempts uint8 = 4
|
||||
|
||||
config, err := NewConfig(version, arch, &mockFeatureSelector{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, version, config.Version)
|
||||
require.Equal(t, arch, config.Arch)
|
||||
|
||||
// Validate ConnectionOptionsSnapshot fields
|
||||
connOptions := config.ConnectionOptionsSnapshot(originIP, previousAttempts)
|
||||
require.Equal(t, version, connOptions.client.Version)
|
||||
require.Equal(t, arch, connOptions.client.Arch)
|
||||
require.Equal(t, config.ConnectorID[:], connOptions.client.ClientID)
|
||||
|
||||
// Vaidate snapshot feature fields against the connOptions generated
|
||||
snapshot := config.featureSelector.Snapshot()
|
||||
require.Equal(t, features.DatagramV3, snapshot.DatagramVersion)
|
||||
require.Equal(t, features.DatagramV3, connOptions.FeatureSnapshot.DatagramVersion)
|
||||
|
||||
pogsConnOptions := connOptions.ConnectionOptions()
|
||||
require.Equal(t, connOptions.client, pogsConnOptions.Client)
|
||||
require.Equal(t, originIP, pogsConnOptions.OriginLocalIP)
|
||||
require.False(t, pogsConnOptions.ReplaceExisting)
|
||||
require.Equal(t, uint8(0), pogsConnOptions.CompressionQuality)
|
||||
require.Equal(t, previousAttempts, pogsConnOptions.NumPreviousAttempts)
|
||||
}
|
||||
|
||||
type mockFeatureSelector struct{}
|
||||
|
||||
func (m *mockFeatureSelector) Snapshot() features.FeatureSnapshot {
|
||||
return features.FeatureSnapshot{
|
||||
PostQuantum: features.PostQuantumPrefer,
|
||||
DatagramVersion: features.DatagramV3,
|
||||
FeaturesList: []string{features.FeaturePostQuantum, features.FeatureDatagramV3_1},
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user