Skip to content

Commit e9fbd11

Browse files
[v17] Preparation for the QUIC proxy peering implementation (#48906)
* Move the QUIC proxy peering envvar check to lib/config * Move lib/proxy/clusterdial to lib/peer/dial * Move peer.clientConn to lib/proxy/peer/internal * Require QUIC peering label to be set to "yes" * Move peer TLS verification funcs to lib/proxy/peer/internal * Move QUICServer to lib/proxy/peer/quic * Avoid stuttering in lib/proxy/peer/quic * Remove useless quic.ServerConfig.CipherSuites param * Fix log style in proxy.peer.quic * Move duplicatePeerMsg into the function scope Co-authored-by: Alan Parra <alan.parra@goteleport.com> --------- Co-authored-by: Alan Parra <alan.parra@goteleport.com>
1 parent 83b9e89 commit e9fbd11

File tree

17 files changed

+362
-235
lines changed

17 files changed

+362
-235
lines changed

api/types/constants.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,10 +1066,10 @@ const (
10661066
// group they should attempt to be connected to.
10671067
ProxyGroupGenerationLabel = TeleportInternalLabelPrefix + "proxygroup-gen"
10681068

1069-
// ProxyPeerQUICLabel is the internal-user label for proxy heartbeats that's
1070-
// used to signal that the proxy supports receiving proxy peering
1071-
// connections over QUIC.
1072-
ProxyPeerQUICLabel = TeleportInternalLabelPrefix + "proxy-peer-quic"
1069+
// UnstableProxyPeerQUICLabel is the internal-use label for proxy heartbeats
1070+
// that's used to signal that the proxy supports receiving proxy peering
1071+
// connections over QUIC. The value should be "yes".
1072+
UnstableProxyPeerQUICLabel = TeleportInternalLabelPrefix + "proxy-peer-quic"
10731073

10741074
// OktaAppNameLabel is the individual app name label.
10751075
OktaAppNameLabel = TeleportInternalLabelPrefix + "okta-app-name"

lib/config/configuration.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2730,6 +2730,11 @@ func Configure(clf *CommandLineFlags, cfg *servicecfg.Config, legacyAppFlags boo
27302730
cfg.DebugService.Enabled = false
27312731
}
27322732

2733+
// TODO(espadolini): allow this when the implementation is merged
2734+
if false && os.Getenv("TELEPORT_UNSTABLE_QUIC_PROXY_PEERING") == "yes" {
2735+
cfg.Proxy.QUICProxyPeering = true
2736+
}
2737+
27332738
return nil
27342739
}
27352740

lib/proxy/clusterdial/dial.go

Lines changed: 0 additions & 60 deletions
This file was deleted.

lib/proxy/peer/client.go

Lines changed: 32 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ import (
4444
streamutils "github.com/gravitational/teleport/api/utils/grpc/stream"
4545
"github.com/gravitational/teleport/lib/auth/authclient"
4646
"github.com/gravitational/teleport/lib/defaults"
47+
"github.com/gravitational/teleport/lib/proxy/peer/internal"
4748
"github.com/gravitational/teleport/lib/services"
4849
"github.com/gravitational/teleport/lib/utils"
4950
)
@@ -94,11 +95,11 @@ type ClientConfig struct {
9495
}
9596

9697
// connShuffler shuffles the order of client connections.
97-
type connShuffler func([]clientConn)
98+
type connShuffler func([]internal.ClientConn)
9899

99100
// randomConnShuffler returns a conn shuffler that randomizes the order of connections.
100101
func randomConnShuffler() connShuffler {
101-
return func(conns []clientConn) {
102+
return func(conns []internal.ClientConn) {
102103
rand.Shuffle(len(conns), func(i, j int) {
103104
conns[i], conns[j] = conns[j], conns[i]
104105
})
@@ -107,7 +108,7 @@ func randomConnShuffler() connShuffler {
107108

108109
// noopConnShutffler returns a conn shuffler that keeps the original connection ordering.
109110
func noopConnShuffler() connShuffler {
110-
return func([]clientConn) {}
111+
return func([]internal.ClientConn) {}
111112
}
112113

113114
// checkAndSetDefaults checks and sets default values
@@ -163,32 +164,6 @@ func (c *ClientConfig) checkAndSetDefaults() error {
163164
return nil
164165
}
165166

166-
// clientConn manages client connections to a specific peer proxy (with a fixed
167-
// host ID and address).
168-
type clientConn interface {
169-
// peerID returns the host ID of the peer proxy.
170-
peerID() string
171-
// peerAddr returns the address of the peer proxy.
172-
peerAddr() string
173-
174-
// dial opens a connection of a given tunnel type to a node with the given
175-
// ID through the peer proxy managed by the clientConn.
176-
dial(
177-
nodeID string,
178-
src net.Addr,
179-
dst net.Addr,
180-
tunnelType types.TunnelType,
181-
) (net.Conn, error)
182-
183-
// close closes all connections and releases any background resources
184-
// immediately.
185-
close() error
186-
187-
// shutdown waits until all connections are closed or the context is done,
188-
// then acts like close.
189-
shutdown(context.Context)
190-
}
191-
192167
// grpcClientConn manages client connections to a specific peer proxy over gRPC.
193168
type grpcClientConn struct {
194169
cc *grpc.ClientConn
@@ -205,13 +180,13 @@ type grpcClientConn struct {
205180
count int
206181
}
207182

208-
var _ clientConn = (*grpcClientConn)(nil)
183+
var _ internal.ClientConn = (*grpcClientConn)(nil)
209184

210-
// peerID implements [clientConn].
211-
func (c *grpcClientConn) peerID() string { return c.id }
185+
// PeerID implements [internal.ClientConn].
186+
func (c *grpcClientConn) PeerID() string { return c.id }
212187

213-
// peerAddr implements [clientConn].
214-
func (c *grpcClientConn) peerAddr() string { return c.addr }
188+
// PeerAddr implements [internal.ClientConn].
189+
func (c *grpcClientConn) PeerAddr() string { return c.addr }
215190

216191
// maybeAcquire returns a non-nil release func if the grpcClientConn is
217192
// currently allowed to open connections; i.e., if it hasn't fully shut down.
@@ -234,8 +209,8 @@ func (c *grpcClientConn) maybeAcquire() (release func()) {
234209
})
235210
}
236211

237-
// shutdown implements [clientConn].
238-
func (c *grpcClientConn) shutdown(ctx context.Context) {
212+
// Shutdown implements [internal.ClientConn].
213+
func (c *grpcClientConn) Shutdown(ctx context.Context) {
239214
defer c.cc.Close()
240215

241216
c.mu.Lock()
@@ -255,13 +230,13 @@ func (c *grpcClientConn) shutdown(ctx context.Context) {
255230
}
256231
}
257232

258-
// close implements [clientConn].
259-
func (c *grpcClientConn) close() error {
233+
// Close implements [internal.ClientConn].
234+
func (c *grpcClientConn) Close() error {
260235
return c.cc.Close()
261236
}
262237

263-
// dial implements [clientConn].
264-
func (c *grpcClientConn) dial(
238+
// Dial implements [internal.ClientConn].
239+
func (c *grpcClientConn) Dial(
265240
nodeID string,
266241
src net.Addr,
267242
dst net.Addr,
@@ -335,7 +310,7 @@ type Client struct {
335310
cancel context.CancelFunc
336311

337312
config ClientConfig
338-
conns map[string]clientConn
313+
conns map[string]internal.ClientConn
339314
metrics *clientMetrics
340315
reporter *reporter
341316
}
@@ -360,7 +335,7 @@ func NewClient(config ClientConfig) (*Client, error) {
360335
config: config,
361336
ctx: closeContext,
362337
cancel: cancel,
363-
conns: make(map[string]clientConn),
338+
conns: make(map[string]internal.ClientConn),
364339
metrics: metrics,
365340
reporter: reporter,
366341
}
@@ -453,7 +428,7 @@ func (c *Client) updateConnections(proxies []types.Server) error {
453428
}
454429

455430
var toDelete []string
456-
toKeep := make(map[string]clientConn)
431+
toKeep := make(map[string]internal.ClientConn)
457432
for id, conn := range c.conns {
458433
proxy, ok := toDial[id]
459434

@@ -464,7 +439,7 @@ func (c *Client) updateConnections(proxies []types.Server) error {
464439
}
465440

466441
// peer address changed
467-
if conn.peerAddr() != proxy.GetPeerAddr() {
442+
if conn.PeerAddr() != proxy.GetPeerAddr() {
468443
toDelete = append(toDelete, id)
469444
continue
470445
}
@@ -485,8 +460,8 @@ func (c *Client) updateConnections(proxies []types.Server) error {
485460
}
486461

487462
// establish new connections
488-
_, supportsQuic := proxy.GetLabel(types.ProxyPeerQUICLabel)
489-
conn, err := c.connect(id, proxy.GetPeerAddr(), supportsQuic)
463+
supportsQUIC, _ := proxy.GetLabel(types.UnstableProxyPeerQUICLabel)
464+
conn, err := c.connect(id, proxy.GetPeerAddr(), supportsQUIC == "yes")
490465
if err != nil {
491466
c.metrics.reportTunnelError(errorProxyPeerTunnelDial)
492467
c.config.Log.DebugContext(c.ctx, "error dialing peer proxy", "peer_id", id, "peer_addr", proxy.GetPeerAddr())
@@ -503,7 +478,7 @@ func (c *Client) updateConnections(proxies []types.Server) error {
503478

504479
for _, id := range toDelete {
505480
if conn, ok := c.conns[id]; ok {
506-
go conn.shutdown(c.ctx)
481+
go conn.Shutdown(c.ctx)
507482
}
508483
}
509484
c.conns = toKeep
@@ -556,9 +531,9 @@ func (c *Client) Shutdown(ctx context.Context) {
556531
var wg sync.WaitGroup
557532
for _, conn := range c.conns {
558533
wg.Add(1)
559-
go func(conn clientConn) {
534+
go func(conn internal.ClientConn) {
560535
defer wg.Done()
561-
conn.shutdown(ctx)
536+
conn.Shutdown(ctx)
562537
}(conn)
563538
}
564539
wg.Wait()
@@ -572,7 +547,7 @@ func (c *Client) Stop() error {
572547

573548
var errs []error
574549
for _, conn := range c.conns {
575-
if err := conn.close(); err != nil {
550+
if err := conn.Close(); err != nil {
576551
errs = append(errs, err)
577552
}
578553
}
@@ -627,7 +602,7 @@ func (c *Client) dial(
627602

628603
var errs []error
629604
for _, clientConn := range conns {
630-
conn, err := clientConn.dial(nodeID, src, dst, tunnelType)
605+
conn, err := clientConn.Dial(nodeID, src, dst, tunnelType)
631606
if err != nil {
632607
errs = append(errs, trace.Wrap(err))
633608
continue
@@ -643,13 +618,13 @@ func (c *Client) dial(
643618
// otherwise.
644619
// The boolean returned in the second argument is intended for testing purposes,
645620
// to indicates whether the connection was cached or newly established.
646-
func (c *Client) getConnections(proxyIDs []string) ([]clientConn, bool, error) {
621+
func (c *Client) getConnections(proxyIDs []string) ([]internal.ClientConn, bool, error) {
647622
if len(proxyIDs) == 0 {
648623
return nil, false, trace.BadParameter("failed to dial: no proxy ids given")
649624
}
650625

651626
ids := make(map[string]struct{})
652-
var conns []clientConn
627+
var conns []internal.ClientConn
653628

654629
// look for existing matching connections.
655630
c.RLock()
@@ -686,8 +661,8 @@ func (c *Client) getConnections(proxyIDs []string) ([]clientConn, bool, error) {
686661
continue
687662
}
688663

689-
_, supportsQuic := proxy.GetLabel(types.ProxyPeerQUICLabel)
690-
conn, err := c.connect(id, proxy.GetPeerAddr(), supportsQuic)
664+
supportsQUIC, _ := proxy.GetLabel(types.UnstableProxyPeerQUICLabel)
665+
conn, err := c.connect(id, proxy.GetPeerAddr(), supportsQUIC == "yes")
691666
if err != nil {
692667
c.metrics.reportTunnelError(errorProxyPeerTunnelDirectDial)
693668
c.config.Log.DebugContext(c.ctx, "error direct dialing peer proxy", "peer_id", id, "peer_addr", proxy.GetPeerAddr())
@@ -707,15 +682,15 @@ func (c *Client) getConnections(proxyIDs []string) ([]clientConn, bool, error) {
707682
defer c.Unlock()
708683

709684
for _, conn := range conns {
710-
c.conns[conn.peerID()] = conn
685+
c.conns[conn.PeerID()] = conn
711686
}
712687

713688
c.config.connShuffler(conns)
714689
return conns, false, nil
715690
}
716691

717692
// connect dials a new connection to proxyAddr.
718-
func (c *Client) connect(peerID string, peerAddr string, supportsQUIC bool) (clientConn, error) {
693+
func (c *Client) connect(peerID string, peerAddr string, supportsQUIC bool) (internal.ClientConn, error) {
719694
if supportsQUIC && c.config.QUICTransport != nil {
720695
panic("QUIC proxy peering is not implemented")
721696
}

lib/proxy/peer/client_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/gravitational/teleport/api/client/proto"
3131
clientapi "github.com/gravitational/teleport/api/client/proto"
3232
"github.com/gravitational/teleport/api/types"
33+
"github.com/gravitational/teleport/lib/proxy/peer/internal"
3334
"github.com/gravitational/teleport/lib/utils"
3435
)
3536

@@ -208,7 +209,7 @@ func TestBackupClient(t *testing.T) {
208209
require.True(t, dialCalled)
209210
}
210211

211-
func waitForGRPCConns(t *testing.T, conns map[string]clientConn, d time.Duration) {
212+
func waitForGRPCConns(t *testing.T, conns map[string]internal.ClientConn, d time.Duration) {
212213
require.Eventually(t, func() bool {
213214
for _, conn := range conns {
214215
// panic if we hit a non-grpc client conn

lib/proxy/peer/credentials.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"google.golang.org/grpc/credentials"
2828

2929
"github.com/gravitational/teleport/api/types"
30+
"github.com/gravitational/teleport/lib/proxy/peer/internal"
3031
"github.com/gravitational/teleport/lib/tlsca"
3132
)
3233

@@ -74,15 +75,13 @@ func (c *clientCredentials) ClientHandshake(ctx context.Context, laddr string, c
7475
}
7576

7677
if err := validatePeer(c.peerID, identity); err != nil {
77-
c.log.ErrorContext(ctx, duplicatePeerMsg, "peer_addr", c.peerAddr, "peer_id", c.peerID)
78+
internal.LogDuplicatePeer(ctx, c.log, slog.LevelError, "peer_addr", c.peerAddr, "peer_id", c.peerID)
7879
return nil, nil, trace.Wrap(err)
7980
}
8081

8182
return conn, authInfo, nil
8283
}
8384

84-
const duplicatePeerMsg = "Detected multiple Proxy Peers with the same public address when connecting to a Proxy which can lead to inconsistent state and problems establishing sessions. For best results ensure that `peer_public_addr` is unique per proxy and not a load balancer."
85-
8685
// getIdentity returns a [tlsca.Identity] that is created from the certificate
8786
// presented during the TLS handshake.
8887
func getIdentity(authInfo credentials.AuthInfo) (*tlsca.Identity, error) {
@@ -121,5 +120,5 @@ func validatePeer(peerID string, identity *tlsca.Identity) error {
121120
return nil
122121
}
123122

124-
return trace.AccessDenied("connected to unexpected proxy")
123+
return trace.Wrap(internal.WrongProxyError{})
125124
}

0 commit comments

Comments
 (0)