mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-30 18:29:21 +08:00
Make tctl build for Windows (#25447)
* Add a no-op syslog impl for Windows
* Break tctl's dependency on lib/srv
tctl's auth client depends on the lib/reversetunnel package in order
to dial the auth server via reverse tunnel. This package in turn
depends on lib/srv/forward and lib/srv, which is a bunch of
Linux-specific code for Teleport services (re-exec, etc).
By extracting the client side code for dialing via reverse tunnels
into its own package, we can now build tctl for Windows with the
following incantation:
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 CC=x86_64-w64-mingw32-gcc go build -o tctl.exe ./tool/tctl
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
+2
-1
@@ -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()
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
@@ -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"
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package reversetunnel
|
||||
package reversetunnelclient
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -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
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
@@ -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(),
|
||||
|
||||
@@ -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 = "<proxy tunnel>"
|
||||
}
|
||||
t.AddRow([]string{service.GetName(), addr, service.GetTeleportVersion()})
|
||||
|
||||
Reference in New Issue
Block a user