diff --git a/lib/auth/authclient/authclient.go b/lib/auth/authclient/authclient.go index fd6dee2b954..984b5378a01 100644 --- a/lib/auth/authclient/authclient.go +++ b/lib/auth/authclient/authclient.go @@ -31,7 +31,7 @@ import ( apiclient "github.com/gravitational/teleport/api/client" "github.com/gravitational/teleport/api/client/webclient" "github.com/gravitational/teleport/lib/auth" - "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/utils" ) @@ -99,7 +99,6 @@ func connectViaAuthDirect(cfg *Config) (auth.ClientI, error) { // This client didn't work for us, so we close it. _ = directDialClient.Close() return nil, trace.Wrap(err) - } return directDialClient, nil } @@ -111,21 +110,21 @@ func connectViaProxyTunnel(ctx context.Context, cfg *Config) (auth.ClientI, erro // // TODO(nic): this logic should be implemented once and reused in IoT // nodes. - resolver := reversetunnel.WebClientResolver(&webclient.Config{ + resolver := reversetunnelclient.WebClientResolver(&webclient.Config{ Context: ctx, ProxyAddr: cfg.AuthServers[0].String(), Insecure: cfg.TLS.InsecureSkipVerify, Timeout: cfg.DialTimeout, }) - resolver, err := reversetunnel.CachingResolver(ctx, resolver, nil /* clock */) + resolver, err := reversetunnelclient.CachingResolver(ctx, resolver, nil /* clock */) if err != nil { return nil, trace.Wrap(err) } // reversetunnel.TunnelAuthDialer will take care of creating a net.Conn // within an SSH tunnel. - dialer, err := reversetunnel.NewTunnelAuthDialer(reversetunnel.TunnelAuthDialerConfig{ + dialer, err := reversetunnelclient.NewTunnelAuthDialer(reversetunnelclient.TunnelAuthDialerConfig{ Resolver: resolver, ClientConfig: cfg.SSH, Log: cfg.Log, diff --git a/lib/kube/proxy/forwarder.go b/lib/kube/proxy/forwarder.go index 878bda20b67..df442ba7319 100644 --- a/lib/kube/proxy/forwarder.go +++ b/lib/kube/proxy/forwarder.go @@ -83,6 +83,7 @@ import ( kubeutils "github.com/gravitational/teleport/lib/kube/utils" "github.com/gravitational/teleport/lib/multiplexer" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/service/servicecfg" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/srv" @@ -2230,7 +2231,7 @@ func (f *Forwarder) newClusterSessionRemoteCluster(ctx context.Context, authCtx // and the targetKubernetes cluster endpoint is determined from the identity // encoded in the TLS certificate. We're setting the dial endpoint to a hardcoded // `kube.teleport.cluster.local` value to indicate this is a Kubernetes proxy request - targetAddr: reversetunnel.LocalKubernetes, + targetAddr: reversetunnelclient.LocalKubernetes, requestContext: ctx, }, nil } diff --git a/lib/kube/proxy/forwarder_test.go b/lib/kube/proxy/forwarder_test.go index 411cae503eb..18643f9c0c1 100644 --- a/lib/kube/proxy/forwarder_test.go +++ b/lib/kube/proxy/forwarder_test.go @@ -57,6 +57,7 @@ import ( "github.com/gravitational/teleport/lib/fixtures" testingkubemock "github.com/gravitational/teleport/lib/kube/proxy/testing/kube_server" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/services/local" "github.com/gravitational/teleport/lib/tlsca" @@ -1012,7 +1013,7 @@ func TestNewClusterSessionDirect(t *testing.T) { // multiple kube services for kube cluster publicKubeService := newKubeServer("public", "k8s.example.com", "kube-cluster") - tunnelKubeService := newKubeServer("tunnel", reversetunnel.LocalKubernetes, "kube-cluster") + tunnelKubeService := newKubeServer("tunnel", reversetunnelclient.LocalKubernetes, "kube-cluster") f.cfg.CachingAuthClient = mockAccessPoint{ kubeServers: []types.KubeServer{publicKubeService, otherKubeService, tunnelKubeService, otherKubeService}, diff --git a/lib/kube/proxy/transport.go b/lib/kube/proxy/transport.go index e775d83de1b..e9ec4dcedbf 100644 --- a/lib/kube/proxy/transport.go +++ b/lib/kube/proxy/transport.go @@ -40,6 +40,7 @@ import ( "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/utils" ) @@ -394,7 +395,7 @@ func (f *Forwarder) remoteClusterDialer(clusterName string) dialContextFunc { // and the targetKubernetes cluster endpoint is determined from the identity // encoded in the TLS certificate. We're setting the dial endpoint to a hardcoded // `kube.teleport.cluster.local` value to indicate this is a Kubernetes proxy request - To: &utils.NetAddr{AddrNetwork: "tcp", Addr: reversetunnel.LocalKubernetes}, + To: &utils.NetAddr{AddrNetwork: "tcp", Addr: reversetunnelclient.LocalKubernetes}, ConnType: types.KubeTunnel, }) } diff --git a/lib/kube/proxy/transport_test.go b/lib/kube/proxy/transport_test.go index c998cb06fe1..d6bffde1881 100644 --- a/lib/kube/proxy/transport_test.go +++ b/lib/kube/proxy/transport_test.go @@ -27,6 +27,7 @@ import ( "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/utils" ) @@ -187,7 +188,7 @@ func TestForwarderClusterDialer(t *testing.T) { AddrNetwork: "tcp", }, To: &utils.NetAddr{ - Addr: reversetunnel.LocalKubernetes, + Addr: reversetunnelclient.LocalKubernetes, AddrNetwork: "tcp", }, ConnType: types.KubeTunnel, diff --git a/lib/proxy/router.go b/lib/proxy/router.go index 2ba3af0ed47..33809cd8a7f 100644 --- a/lib/proxy/router.go +++ b/lib/proxy/router.go @@ -38,6 +38,7 @@ import ( "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/observability/metrics" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/teleagent" "github.com/gravitational/teleport/lib/utils" @@ -260,7 +261,7 @@ func (r *Router) DialHost(ctx context.Context, clientSrcAddr, clientDstAddr net. principals = append(principals, h) case serverAddr == "" && target.GetUseTunnel(): - serverAddr = reversetunnel.LocalNode + serverAddr = reversetunnelclient.LocalNode } targetTeleportVersion = target.GetTeleportVersion() diff --git a/lib/reversetunnel/agent.go b/lib/reversetunnel/agent.go index 5a49c4bd9e4..a0275854903 100644 --- a/lib/reversetunnel/agent.go +++ b/lib/reversetunnel/agent.go @@ -664,21 +664,3 @@ const ( chanDiscoveryReq = "discovery" reconnectRequest = "reconnect@goteleport.com" ) - -const ( - // LocalNode is a special non-resolvable address that indicates the request - // wants to connect to a dialed back node. - LocalNode = "@local-node" - // RemoteAuthServer is a special non-resolvable address that indicates client - // requests a connection to the remote auth server. - RemoteAuthServer = "@remote-auth-server" - // LocalKubernetes is a special non-resolvable address that indicates that clients - // requests a connection to the kubernetes endpoint of the local proxy. - // This has to be a valid domain name, so it lacks @ - LocalKubernetes = "remote.kube.proxy." + constants.APIDomain - // LocalWindowsDesktop is a special non-resolvable address that indicates - // that clients requests a connection to the windows service endpoint of - // the local proxy. - // This has to be a valid domain name, so it lacks @ - LocalWindowsDesktop = "remote.windows_desktop.proxy." + constants.APIDomain -) diff --git a/lib/reversetunnel/agentpool.go b/lib/reversetunnel/agentpool.go index ffd7b58c323..4f14ab7e0d6 100644 --- a/lib/reversetunnel/agentpool.go +++ b/lib/reversetunnel/agentpool.go @@ -42,6 +42,7 @@ import ( "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/multiplexer" "github.com/gravitational/teleport/lib/reversetunnel/track" + "github.com/gravitational/teleport/lib/reversetunnelclient" alpncommon "github.com/gravitational/teleport/lib/srv/alpnproxy/common" "github.com/gravitational/teleport/lib/utils" "github.com/gravitational/teleport/lib/utils/proxy" @@ -120,7 +121,7 @@ type AgentPoolConfig struct { // ReverseTunnelServer holds all reverse tunnel connections. ReverseTunnelServer Server // Resolver retrieves the reverse tunnel address - Resolver Resolver + Resolver reversetunnelclient.Resolver // Cluster is a cluster name of the proxy. Cluster string // FIPS indicates if Teleport was started in FIPS mode. @@ -737,7 +738,7 @@ func (c *agentPoolRuntimeConfig) updateRemote(ctx context.Context, addr *utils.N return nil } -func (c *agentPoolRuntimeConfig) update(ctx context.Context, netConfig types.ClusterNetworkingConfig, resolver Resolver) { +func (c *agentPoolRuntimeConfig) update(ctx context.Context, netConfig types.ClusterNetworkingConfig, resolver reversetunnelclient.Resolver) { c.mu.Lock() defer c.mu.Unlock() diff --git a/lib/reversetunnel/localsite.go b/lib/reversetunnel/localsite.go index 5328e30cdd2..6001a6c0577 100644 --- a/lib/reversetunnel/localsite.go +++ b/lib/reversetunnel/localsite.go @@ -39,6 +39,7 @@ import ( "github.com/gravitational/teleport/lib/observability/metrics" "github.com/gravitational/teleport/lib/proxy/peer" "github.com/gravitational/teleport/lib/reversetunnel/track" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/srv/forward" "github.com/gravitational/teleport/lib/teleagent" @@ -472,7 +473,7 @@ func (s *localSite) skipDirectDial(params DialParams) (bool, error) { // This node can only be reached over a tunnel, don't attempt to dial // directly. - if params.To == nil || params.To.String() == "" || params.To.String() == LocalNode { + if params.To == nil || params.To.String() == "" || params.To.String() == reversetunnelclient.LocalNode { return true, nil } diff --git a/lib/reversetunnel/rc_manager.go b/lib/reversetunnel/rc_manager.go index 1fc67878b1d..05494515706 100644 --- a/lib/reversetunnel/rc_manager.go +++ b/lib/reversetunnel/rc_manager.go @@ -31,6 +31,7 @@ import ( "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/multiplexer" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/utils" ) @@ -235,7 +236,7 @@ func realNewAgentPool(ctx context.Context, cfg RemoteClusterTunnelManagerConfig, // Configs for remote cluster. Cluster: cluster, - Resolver: StaticResolver(addr, apitypes.ProxyListenerMode_Separate), + Resolver: reversetunnelclient.StaticResolver(addr, apitypes.ProxyListenerMode_Separate), IsRemoteCluster: true, PROXYSigner: cfg.PROXYSigner, }) diff --git a/lib/reversetunnel/rc_manager_test.go b/lib/reversetunnel/rc_manager_test.go index 2de828bfd37..1b80142b9a4 100644 --- a/lib/reversetunnel/rc_manager_test.go +++ b/lib/reversetunnel/rc_manager_test.go @@ -25,6 +25,7 @@ import ( "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/auth" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/utils" ) @@ -32,7 +33,7 @@ import ( func TestRemoteClusterTunnelManagerSync(t *testing.T) { t.Parallel() - resolverFn := func(addr string) Resolver { + resolverFn := func(addr string) reversetunnelclient.Resolver { return func(context.Context) (*utils.NetAddr, types.ProxyListenerMode, error) { return &utils.NetAddr{ Addr: addr, diff --git a/lib/reversetunnel/transport.go b/lib/reversetunnel/transport.go index b76aaafa166..bc346ef11b8 100644 --- a/lib/reversetunnel/transport.go +++ b/lib/reversetunnel/transport.go @@ -18,8 +18,6 @@ package reversetunnel import ( "context" - "crypto/tls" - "crypto/x509" "encoding/json" "fmt" "io" @@ -32,104 +30,16 @@ import ( "golang.org/x/crypto/ssh" "github.com/gravitational/teleport" - "github.com/gravitational/teleport/api/client" apidefaults "github.com/gravitational/teleport/api/defaults" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/sshutils" "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/events" "github.com/gravitational/teleport/lib/multiplexer" - alpncommon "github.com/gravitational/teleport/lib/srv/alpnproxy/common" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/utils" - "github.com/gravitational/teleport/lib/utils/proxy" ) -// NewTunnelAuthDialer creates a new instance of TunnelAuthDialer -func NewTunnelAuthDialer(config TunnelAuthDialerConfig) (*TunnelAuthDialer, error) { - if err := config.CheckAndSetDefaults(); err != nil { - return nil, trace.Wrap(err) - } - return &TunnelAuthDialer{ - TunnelAuthDialerConfig: config, - }, nil -} - -// TunnelAuthDialerConfig specifies TunnelAuthDialer configuration. -type TunnelAuthDialerConfig struct { - // Resolver retrieves the address of the proxy - Resolver Resolver - // ClientConfig is SSH tunnel client config - ClientConfig *ssh.ClientConfig - // Log is used for logging. - Log logrus.FieldLogger - // InsecureSkipTLSVerify is whether to skip certificate validation. - InsecureSkipTLSVerify bool - // ClusterCAs contains cluster CAs. - ClusterCAs *x509.CertPool -} - -func (c *TunnelAuthDialerConfig) CheckAndSetDefaults() error { - if c.Resolver == nil { - return trace.BadParameter("missing tunnel address resolver") - } - if c.ClusterCAs == nil { - return trace.BadParameter("missing cluster CAs") - } - return nil -} - -// TunnelAuthDialer connects to the Auth Server through the reverse tunnel. -type TunnelAuthDialer struct { - // TunnelAuthDialerConfig is the TunnelAuthDialer configuration. - TunnelAuthDialerConfig -} - -// DialContext dials auth server via SSH tunnel -func (t *TunnelAuthDialer) DialContext(ctx context.Context, _, _ string) (net.Conn, error) { - // Connect to the reverse tunnel server. - opts := []proxy.DialerOptionFunc{ - proxy.WithInsecureSkipTLSVerify(t.InsecureSkipTLSVerify), - } - - addr, mode, err := t.Resolver(ctx) - if err != nil { - t.Log.Errorf("Failed to resolve tunnel address: %v", err) - return nil, trace.Wrap(err) - } - - if mode == types.ProxyListenerMode_Multiplex { - opts = append(opts, proxy.WithALPNDialer(client.ALPNDialerConfig{ - TLSConfig: &tls.Config{ - NextProtos: []string{string(alpncommon.ProtocolReverseTunnel)}, - InsecureSkipVerify: t.InsecureSkipTLSVerify, - }, - DialTimeout: t.ClientConfig.Timeout, - ALPNConnUpgradeRequired: client.IsALPNConnUpgradeRequired(addr.Addr, t.InsecureSkipTLSVerify), - GetClusterCAs: client.ClusterCAsFromCertPool(t.ClusterCAs), - })) - } - - dialer := proxy.DialerFromEnvironment(addr.Addr, opts...) - sconn, err := dialer.Dial(ctx, addr.AddrNetwork, addr.Addr, t.ClientConfig) - if err != nil { - return nil, trace.Wrap(err) - } - - // Build a net.Conn over the tunnel. Make this an exclusive connection: - // close the net.Conn as well as the channel upon close. - conn, _, err := sshutils.ConnectProxyTransport( - sconn.Conn, - &sshutils.DialReq{ - Address: RemoteAuthServer, - }, - true, - ) - if err != nil { - return nil, trace.NewAggregate(err, sconn.Close()) - } - return conn, nil -} - // parseDialReq parses the dial request. Is backward compatible with legacy // payload. func parseDialReq(payload []byte) *sshutils.DialReq { @@ -247,7 +157,7 @@ func (p *transport) start() { // Handle special non-resolvable addresses first. switch dreq.Address { // Connect to an Auth Server. - case RemoteAuthServer: + case reversetunnelclient.RemoteAuthServer: if len(p.authServers) == 0 { p.log.Errorf("connection rejected: no auth servers configured") p.reply(req, false, []byte("no auth servers configured")) @@ -257,7 +167,7 @@ func (p *transport) start() { directAddress = utils.ChooseRandomString(p.authServers) // Connect to the Kubernetes proxy. - case LocalKubernetes: + case reversetunnelclient.LocalKubernetes: switch p.component { case teleport.ComponentReverseTunnelServer: p.reply(req, false, []byte("connection rejected: no remote kubernetes proxy")) @@ -300,7 +210,7 @@ func (p *transport) start() { } // LocalNode requests are for the single server running in the agent pool. - case LocalNode, LocalWindowsDesktop: + case reversetunnelclient.LocalNode, reversetunnelclient.LocalWindowsDesktop: // Transport is allocated with both teleport.ComponentReverseTunnelAgent // and teleport.ComponentReverseTunnelServer. However, dialing to this address // only makes sense when running within a teleport.ComponentReverseTunnelAgent. @@ -362,7 +272,7 @@ func (p *transport) start() { clientDst = dst } var signedHeader []byte - isKubeOrAuth := dreq.ConnType == types.KubeTunnel || dreq.Address == RemoteAuthServer + isKubeOrAuth := dreq.ConnType == types.KubeTunnel || dreq.Address == reversetunnelclient.RemoteAuthServer if shouldSendSignedPROXYHeader(p.proxySigner, dreq.TeleportVersion, useTunnel, !isKubeOrAuth, clientSrc, clientDst) { signedHeader, err = p.proxySigner.SignPROXYHeader(clientSrc, clientDst) if err != nil { diff --git a/lib/reversetunnelclient/agent.go b/lib/reversetunnelclient/agent.go new file mode 100644 index 00000000000..418a8348024 --- /dev/null +++ b/lib/reversetunnelclient/agent.go @@ -0,0 +1,35 @@ +// Copyright 2023 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package reversetunnelclient + +import "github.com/gravitational/teleport/api/constants" + +const ( + // LocalNode is a special non-resolvable address that indicates the request + // wants to connect to a dialed back node. + LocalNode = "@local-node" + // RemoteAuthServer is a special non-resolvable address that indicates client + // requests a connection to the remote auth server. + RemoteAuthServer = "@remote-auth-server" + // LocalKubernetes is a special non-resolvable address that indicates that clients + // requests a connection to the kubernetes endpoint of the local proxy. + // This has to be a valid domain name, so it lacks @ + LocalKubernetes = "remote.kube.proxy." + constants.APIDomain + // LocalWindowsDesktop is a special non-resolvable address that indicates + // that clients requests a connection to the windows service endpoint of + // the local proxy. + // This has to be a valid domain name, so it lacks @ + LocalWindowsDesktop = "remote.windows_desktop.proxy." + constants.APIDomain +) diff --git a/lib/reversetunnel/resolver.go b/lib/reversetunnelclient/resolver.go similarity index 98% rename from lib/reversetunnel/resolver.go rename to lib/reversetunnelclient/resolver.go index 890c1a3775a..2ca1031f71b 100644 --- a/lib/reversetunnel/resolver.go +++ b/lib/reversetunnelclient/resolver.go @@ -1,4 +1,4 @@ -// Copyright 2022 Gravitational, Inc +// Copyright 2023 Gravitational, Inc // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package reversetunnel +package reversetunnelclient import ( "context" diff --git a/lib/reversetunnel/resolver_test.go b/lib/reversetunnelclient/resolver_test.go similarity index 99% rename from lib/reversetunnel/resolver_test.go rename to lib/reversetunnelclient/resolver_test.go index 98dba02da28..60b8d0204eb 100644 --- a/lib/reversetunnel/resolver_test.go +++ b/lib/reversetunnelclient/resolver_test.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package reversetunnel +package reversetunnelclient import ( "context" diff --git a/lib/reversetunnelclient/transport.go b/lib/reversetunnelclient/transport.go new file mode 100644 index 00000000000..6a16df585d3 --- /dev/null +++ b/lib/reversetunnelclient/transport.go @@ -0,0 +1,118 @@ +// Copyright 2023 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package reversetunnelclient + +import ( + "context" + "crypto/tls" + "crypto/x509" + "net" + + "github.com/gravitational/trace" + "github.com/sirupsen/logrus" + "golang.org/x/crypto/ssh" + + "github.com/gravitational/teleport/api/client" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/utils/sshutils" + alpncommon "github.com/gravitational/teleport/lib/srv/alpnproxy/common" + "github.com/gravitational/teleport/lib/utils/proxy" +) + +// NewTunnelAuthDialer creates a new instance of TunnelAuthDialer +func NewTunnelAuthDialer(config TunnelAuthDialerConfig) (*TunnelAuthDialer, error) { + if err := config.CheckAndSetDefaults(); err != nil { + return nil, trace.Wrap(err) + } + return &TunnelAuthDialer{ + TunnelAuthDialerConfig: config, + }, nil +} + +// TunnelAuthDialerConfig specifies TunnelAuthDialer configuration. +type TunnelAuthDialerConfig struct { + // Resolver retrieves the address of the proxy + Resolver Resolver + // ClientConfig is SSH tunnel client config + ClientConfig *ssh.ClientConfig + // Log is used for logging. + Log logrus.FieldLogger + // InsecureSkipTLSVerify is whether to skip certificate validation. + InsecureSkipTLSVerify bool + // ClusterCAs contains cluster CAs. + ClusterCAs *x509.CertPool +} + +func (c *TunnelAuthDialerConfig) CheckAndSetDefaults() error { + if c.Resolver == nil { + return trace.BadParameter("missing tunnel address resolver") + } + if c.ClusterCAs == nil { + return trace.BadParameter("missing cluster CAs") + } + return nil +} + +// TunnelAuthDialer connects to the Auth Server through the reverse tunnel. +type TunnelAuthDialer struct { + // TunnelAuthDialerConfig is the TunnelAuthDialer configuration. + TunnelAuthDialerConfig +} + +// DialContext dials auth server via SSH tunnel +func (t *TunnelAuthDialer) DialContext(ctx context.Context, _, _ string) (net.Conn, error) { + // Connect to the reverse tunnel server. + opts := []proxy.DialerOptionFunc{ + proxy.WithInsecureSkipTLSVerify(t.InsecureSkipTLSVerify), + } + + addr, mode, err := t.Resolver(ctx) + if err != nil { + t.Log.Errorf("Failed to resolve tunnel address: %v", err) + return nil, trace.Wrap(err) + } + + if mode == types.ProxyListenerMode_Multiplex { + opts = append(opts, proxy.WithALPNDialer(client.ALPNDialerConfig{ + TLSConfig: &tls.Config{ + NextProtos: []string{string(alpncommon.ProtocolReverseTunnel)}, + InsecureSkipVerify: t.InsecureSkipTLSVerify, + }, + DialTimeout: t.ClientConfig.Timeout, + ALPNConnUpgradeRequired: client.IsALPNConnUpgradeRequired(addr.Addr, t.InsecureSkipTLSVerify), + GetClusterCAs: client.ClusterCAsFromCertPool(t.ClusterCAs), + })) + } + + dialer := proxy.DialerFromEnvironment(addr.Addr, opts...) + sconn, err := dialer.Dial(ctx, addr.AddrNetwork, addr.Addr, t.ClientConfig) + if err != nil { + return nil, trace.Wrap(err) + } + + // Build a net.Conn over the tunnel. Make this an exclusive connection: + // close the net.Conn as well as the channel upon close. + conn, _, err := sshutils.ConnectProxyTransport( + sconn.Conn, + &sshutils.DialReq{ + Address: RemoteAuthServer, + }, + true, + ) + if err != nil { + return nil, trace.NewAggregate(err, sconn.Close()) + } + return conn, nil +} diff --git a/lib/service/connect.go b/lib/service/connect.go index 9e6f4a4c8f7..a66bc70f8a6 100644 --- a/lib/service/connect.go +++ b/lib/service/connect.go @@ -46,7 +46,7 @@ import ( "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/observability/metrics" "github.com/gravitational/teleport/lib/openssh" - "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/service/servicecfg" "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" @@ -1271,19 +1271,19 @@ func (process *TeleportProcess) newClient(identity *auth.Identity) (*auth.Client } func (process *TeleportProcess) newClientThroughTunnel(addr string, tlsConfig *tls.Config, sshConfig *ssh.ClientConfig) (*auth.Client, error) { - resolver := reversetunnel.WebClientResolver(&webclient.Config{ + resolver := reversetunnelclient.WebClientResolver(&webclient.Config{ Context: process.ExitContext(), ProxyAddr: addr, Insecure: lib.IsInsecureDevMode(), Timeout: process.Config.ClientTimeout, }) - resolver, err := reversetunnel.CachingResolver(process.ExitContext(), resolver, process.Clock) + resolver, err := reversetunnelclient.CachingResolver(process.ExitContext(), resolver, process.Clock) if err != nil { return nil, trace.Wrap(err) } - dialer, err := reversetunnel.NewTunnelAuthDialer(reversetunnel.TunnelAuthDialerConfig{ + dialer, err := reversetunnelclient.NewTunnelAuthDialer(reversetunnelclient.TunnelAuthDialerConfig{ Resolver: resolver, ClientConfig: sshConfig, Log: process.log, diff --git a/lib/service/desktop.go b/lib/service/desktop.go index b621c45a6fb..9abcd28be7c 100644 --- a/lib/service/desktop.go +++ b/lib/service/desktop.go @@ -34,6 +34,7 @@ import ( "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/limiter" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/srv/desktop" "github.com/gravitational/teleport/lib/utils" @@ -108,7 +109,7 @@ func (process *TeleportProcess) initWindowsDesktopServiceRegistered(log *logrus. // Dialed out to a proxy, start servicing the reverse tunnel as a listener. case useTunnel && cfg.WindowsDesktop.ListenAddr.IsEmpty(): // create an adapter, from reversetunnel.ServerHandler to net.Listener. - shtl := reversetunnel.NewServerHandlerToListener(reversetunnel.LocalWindowsDesktop) + shtl := reversetunnel.NewServerHandlerToListener(reversetunnelclient.LocalWindowsDesktop) listener = shtl agentPool, err = reversetunnel.NewAgentPool( process.ExitContext(), diff --git a/lib/service/kubernetes.go b/lib/service/kubernetes.go index b3a4419cd53..b13bd03d93a 100644 --- a/lib/service/kubernetes.go +++ b/lib/service/kubernetes.go @@ -31,6 +31,7 @@ import ( kubeproxy "github.com/gravitational/teleport/lib/kube/proxy" "github.com/gravitational/teleport/lib/labels" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" ) @@ -117,7 +118,7 @@ func (process *TeleportProcess) initKubernetesService(log *logrus.Entry, conn *C // Dialed out to a proxy, start servicing the reverse tunnel as a listener. case conn.UseTunnel() && cfg.Kube.ListenAddr.IsEmpty(): // create an adapter, from reversetunnel.ServerHandler to net.Listener. - shtl := reversetunnel.NewServerHandlerToListener(reversetunnel.LocalKubernetes) + shtl := reversetunnel.NewServerHandlerToListener(reversetunnelclient.LocalKubernetes) listener = shtl agentPool, err = reversetunnel.NewAgentPool( process.ExitContext(), diff --git a/lib/service/service.go b/lib/service/service.go index d7aefbbdccf..3c98fcbac3a 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -108,6 +108,7 @@ import ( "github.com/gravitational/teleport/lib/proxy/peer" restricted "github.com/gravitational/teleport/lib/restrictedsession" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/service/servicecfg" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/services/local" @@ -272,13 +273,13 @@ type Connector struct { // TunnelProxyResolver if non-nil, indicates that the client is connected to the Auth Server // through the reverse SSH tunnel proxy -func (c *Connector) TunnelProxyResolver() reversetunnel.Resolver { +func (c *Connector) TunnelProxyResolver() reversetunnelclient.Resolver { if c.Client == nil || c.Client.Dialer() == nil { return nil } switch dialer := c.Client.Dialer().(type) { - case *reversetunnel.TunnelAuthDialer: + case *reversetunnelclient.TunnelAuthDialer: return dialer.Resolver default: return nil @@ -2983,7 +2984,7 @@ func (process *TeleportProcess) getAdditionalPrincipals(role types.SystemRole) ( utils.NetAddr{Addr: string(teleport.PrincipalLocalhost)}, utils.NetAddr{Addr: string(teleport.PrincipalLoopbackV4)}, utils.NetAddr{Addr: string(teleport.PrincipalLoopbackV6)}, - utils.NetAddr{Addr: reversetunnel.LocalKubernetes}, + utils.NetAddr{Addr: reversetunnelclient.LocalKubernetes}, ) addrs = append(addrs, process.Config.Proxy.SSHPublicAddrs...) addrs = append(addrs, process.Config.Proxy.TunnelPublicAddrs...) @@ -3028,7 +3029,7 @@ func (process *TeleportProcess) getAdditionalPrincipals(role types.SystemRole) ( utils.NetAddr{Addr: string(teleport.PrincipalLocalhost)}, utils.NetAddr{Addr: string(teleport.PrincipalLoopbackV4)}, utils.NetAddr{Addr: string(teleport.PrincipalLoopbackV6)}, - utils.NetAddr{Addr: reversetunnel.LocalKubernetes}, + utils.NetAddr{Addr: reversetunnelclient.LocalKubernetes}, ) addrs = append(addrs, process.Config.Kube.PublicAddrs...) case types.RoleApp, types.RoleOkta: @@ -3038,7 +3039,7 @@ func (process *TeleportProcess) getAdditionalPrincipals(role types.SystemRole) ( utils.NetAddr{Addr: string(teleport.PrincipalLocalhost)}, utils.NetAddr{Addr: string(teleport.PrincipalLoopbackV4)}, utils.NetAddr{Addr: string(teleport.PrincipalLoopbackV6)}, - utils.NetAddr{Addr: reversetunnel.LocalWindowsDesktop}, + utils.NetAddr{Addr: reversetunnelclient.LocalWindowsDesktop}, utils.NetAddr{Addr: desktop.WildcardServiceDNS}, ) addrs = append(addrs, process.Config.WindowsDesktop.PublicAddrs...) @@ -5244,7 +5245,7 @@ func (process *TeleportProcess) initDebugApp() { // SingleProcessModeResolver returns the reversetunnel.Resolver that should be used when running all components needed // within the same process. It's used for development and demo purposes. -func (process *TeleportProcess) SingleProcessModeResolver(mode types.ProxyListenerMode) reversetunnel.Resolver { +func (process *TeleportProcess) SingleProcessModeResolver(mode types.ProxyListenerMode) reversetunnelclient.Resolver { return func(context.Context) (*utils.NetAddr, types.ProxyListenerMode, error) { addr, ok := process.singleProcessMode(mode) if !ok { diff --git a/lib/service/service_test.go b/lib/service/service_test.go index f3e47856ca9..8158d3084c6 100644 --- a/lib/service/service_test.go +++ b/lib/service/service_test.go @@ -57,6 +57,7 @@ import ( "github.com/gravitational/teleport/lib/limiter" "github.com/gravitational/teleport/lib/modules" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/service/servicecfg" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/utils" @@ -477,7 +478,7 @@ func TestGetAdditionalPrincipals(t *testing.T) { string(teleport.PrincipalLocalhost), string(teleport.PrincipalLoopbackV4), string(teleport.PrincipalLoopbackV6), - reversetunnel.LocalKubernetes, + reversetunnelclient.LocalKubernetes, "proxy-ssh-public-1", "proxy-ssh-public-2", "proxy-tunnel-public-1", @@ -540,7 +541,7 @@ func TestGetAdditionalPrincipals(t *testing.T) { string(teleport.PrincipalLocalhost), string(teleport.PrincipalLoopbackV4), string(teleport.PrincipalLoopbackV6), - reversetunnel.LocalKubernetes, + reversetunnelclient.LocalKubernetes, "kube-public-1", "kube-public-2", }, diff --git a/lib/srv/db/proxyserver.go b/lib/srv/db/proxyserver.go index 0d012210f8a..aa8cae904f5 100644 --- a/lib/srv/db/proxyserver.go +++ b/lib/srv/db/proxyserver.go @@ -42,6 +42,7 @@ import ( "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/limiter" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/srv/db/common" "github.com/gravitational/teleport/lib/srv/db/common/enterprise" "github.com/gravitational/teleport/lib/srv/db/dbutils" @@ -447,7 +448,7 @@ func (s *ProxyServer) Connect(ctx context.Context, proxyCtx *common.ProxyContext serviceConn, err := proxyCtx.Cluster.Dial(reversetunnel.DialParams{ From: clientSrcAddr, - To: &utils.NetAddr{AddrNetwork: "tcp", Addr: reversetunnel.LocalNode}, + To: &utils.NetAddr{AddrNetwork: "tcp", Addr: reversetunnelclient.LocalNode}, OriginalClientDstAddr: clientDstAddr, ServerID: fmt.Sprintf("%v.%v", server.GetHostID(), proxyCtx.Cluster.GetName()), ConnType: types.DatabaseTunnel, diff --git a/lib/utils/syslog_windows.go b/lib/utils/syslog_windows.go new file mode 100644 index 00000000000..0b6b7e2fbcf --- /dev/null +++ b/lib/utils/syslog_windows.go @@ -0,0 +1,27 @@ +/* +Copyright 2023 Gravitational, Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package utils + +import ( + "github.com/gravitational/trace" + log "github.com/sirupsen/logrus" +) + +// SwitchLoggerToSyslog always returns an error on Windows. +func SwitchLoggerToSyslog(logger *log.Logger) error { + return trace.NotImplemented("cannot use syslog on Windows") +} diff --git a/lib/web/app/transport.go b/lib/web/app/transport.go index cf0c5fbc0dc..db7117ebbea 100644 --- a/lib/web/app/transport.go +++ b/lib/web/app/transport.go @@ -35,6 +35,7 @@ import ( "github.com/gravitational/teleport/lib/auth" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" @@ -293,7 +294,7 @@ func dialAppServer(ctx context.Context, proxyClient reversetunnel.Tunnel, cluste conn, err := clusterClient.Dial(reversetunnel.DialParams{ From: from, - To: &utils.NetAddr{AddrNetwork: "tcp", Addr: reversetunnel.LocalNode}, + To: &utils.NetAddr{AddrNetwork: "tcp", Addr: reversetunnelclient.LocalNode}, OriginalClientDstAddr: originalDst, ServerID: fmt.Sprintf("%v.%v", server.GetHostID(), clusterName), ConnType: server.GetTunnelType(), diff --git a/tool/tctl/common/collection.go b/tool/tctl/common/collection.go index a28fe034eee..4243800b952 100644 --- a/tool/tctl/common/collection.go +++ b/tool/tctl/common/collection.go @@ -33,7 +33,7 @@ import ( apiutils "github.com/gravitational/teleport/api/utils" "github.com/gravitational/teleport/lib/asciitable" "github.com/gravitational/teleport/lib/devicetrust" - "github.com/gravitational/teleport/lib/reversetunnel" + "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/sshutils" "github.com/gravitational/teleport/lib/utils" "github.com/gravitational/teleport/tool/tctl/common/loginrule" @@ -789,7 +789,7 @@ func (c *windowsDesktopServiceCollection) writeText(w io.Writer) error { t := asciitable.MakeTable([]string{"Name", "Address", "Version"}) for _, service := range c.services { addr := service.GetAddr() - if addr == reversetunnel.LocalWindowsDesktop { + if addr == reversetunnelclient.LocalWindowsDesktop { addr = "" } t.AddRow([]string{service.GetName(), addr, service.GetTeleportVersion()})