Skip to content

Commit

Permalink
Merge pull request #493 from gravitational/ev/491
Browse files Browse the repository at this point in the history
Adds the ability to specify non-standard HTTPS proxy port
  • Loading branch information
kontsevoy authored Aug 5, 2016
2 parents 222c7ea + 3060cf2 commit df05b9e
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 15 deletions.
16 changes: 15 additions & 1 deletion docs/user-manual.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ Run shell or execute a command on a remote SSH node.

Flags:
--user SSH proxy user [ekontsevoy]
--proxy SSH proxy host or IP address
--proxy SSH proxy host or IP address, for example --proxy=host:ssh_port,https_port
--ttl Minutes to live for a SSH session
--insecure Do not verify server certificate and host name. Use only in test environments
-d, --debug Verbose logging to stdout
Expand All @@ -158,6 +158,20 @@ using familiar SSH syntax:
> ssh -p 6122 root@host ls
```

### Note about Proxies

A Teleport proxy uses two ports: `3080` for HTTPS and `3023` for proxying SSH connections.
The HTTPS port is used to serve Web UI and also to implement 2nd factor auth for `tsh` client.

If your Teleport proxy is configured to listen on other ports, you should specify
them via `--proxy` flag as shown:

```
tsh --proxy=host:5000,5001
```

This means "connect to the port `5000` for SSH and to `5001` for HTTPS".

### Port Forwarding

`tsh ssh` supports OpenSSH `-L` flag which allows to forward incoming connections from localhost
Expand Down
39 changes: 31 additions & 8 deletions lib/client/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ type Config struct {
// HostPort is a remote host port to connect to
HostPort int

// ProxyHost is a host or IP of the proxy (with optional ":port")
// ProxyHost is a host or IP of the proxy (with optional ":ssh_port,https_port"). This parameter
// is taken from the --proxy flag and can look like --proxy=host:5025,5080
ProxyHost string

// KeyTTL is a time to live for the temporary SSH keypair to remain valid:
Expand Down Expand Up @@ -130,13 +131,32 @@ type Config struct {
Env map[string]string
}

// ProxyHostPort returns a full host:port address of the proxy or an empty string if no
// proxy is given. If 'forWeb' flag is set, returns HTTPS port, otherwise
// ProxyHostPort returns a full host:port address of the SSH proxy
// Otherwise, returns an empty string if no proxy is given.
//
// If 'forWeb' flag is set, returns HTTPS port, otherwise
// returns SSH port (proxy servers listen on both)
func (c *Config) ProxyHostPort(defaultPort int) string {
func (c *Config) ProxyHostPort(forWeb bool) string {
var defaultPort int

if c.ProxySpecified() {
if forWeb {
defaultPort = defaults.HTTPListenPort
} else {
defaultPort = defaults.SSHProxyListenPort
}
host, port, err := net.SplitHostPort(c.ProxyHost)
if err == nil && len(port) > 0 {
ports := strings.Split(port, ",")
if forWeb {
if len(ports) > 1 {
port = ports[1]
} else {
port = strconv.Itoa(defaultPort)
}
} else {
port = ports[0]
}
// c.ProxyHost was already specified as "host:port"
return net.JoinHostPort(host, port)
}
Expand Down Expand Up @@ -586,11 +606,13 @@ func (tc *TeleportClient) ListNodes() ([]services.Server, error) {
return nil, trace.Wrap(err)
}
}

// connect to the proxy and ask it to return a full list of servers
proxyClient, err := tc.ConnectToProxy()
if err != nil {
return nil, trace.Wrap(err)
}

defer proxyClient.Close()
return proxyClient.FindServersByLabels(tc.Labels)
}
Expand Down Expand Up @@ -784,7 +806,7 @@ func (tc *TeleportClient) GetKeys() ([]agent.AddedKey, error) {

// ConnectToProxy dials the proxy server and returns ProxyClient if successful
func (tc *TeleportClient) ConnectToProxy() (*ProxyClient, error) {
proxyAddr := tc.Config.ProxyHostPort(defaults.SSHProxyListenPort)
proxyAddr := tc.Config.ProxyHostPort(false)
sshConfig := &ssh.ClientConfig{
User: tc.getProxyLogin(),
HostKeyCallback: tc.HostKeyCallback,
Expand Down Expand Up @@ -924,7 +946,7 @@ func (tc *TeleportClient) AddKey(host string, key *Key) error {

// directLogin asks for a password + HOTP token, makes a request to CA via proxy
func (tc *TeleportClient) directLogin(pub []byte) (*web.SSHLoginResponse, error) {
httpsProxyHostPort := tc.Config.ProxyHostPort(defaults.HTTPListenPort)
httpsProxyHostPort := tc.Config.ProxyHostPort(true)
certPool := loopbackPool(httpsProxyHostPort)

// ping the HTTPs endpoint first:
Expand Down Expand Up @@ -954,8 +976,9 @@ func (tc *TeleportClient) directLogin(pub []byte) (*web.SSHLoginResponse, error)
func (tc *TeleportClient) oidcLogin(connectorID string, pub []byte) (*web.SSHLoginResponse, error) {
log.Infof("oidcLogin start")
// ask the CA (via proxy) to sign our public key:
response, err := web.SSHAgentOIDCLogin(tc.Config.ProxyHostPort(defaults.HTTPListenPort),
connectorID, pub, tc.KeyTTL, tc.InsecureSkipVerify, loopbackPool(tc.Config.ProxyHostPort(defaults.HTTPListenPort)))
webProxyAddr := tc.Config.ProxyHostPort(true)
response, err := web.SSHAgentOIDCLogin(webProxyAddr,
connectorID, pub, tc.KeyTTL, tc.InsecureSkipVerify, loopbackPool(webProxyAddr))
return response, trace.Wrap(err)
}

Expand Down
16 changes: 11 additions & 5 deletions lib/client/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,20 @@ func (s *APITestSuite) TestConfig(c *check.C) {
c.Assert(conf.ProxySpecified(), check.Equals, false)
conf.ProxyHost = "example.org"
c.Assert(conf.ProxySpecified(), check.Equals, true)
c.Assert(conf.ProxyHostPort(12), check.Equals, "example.org:12")
c.Assert(conf.ProxyHostPort(false), check.Equals, "example.org:3023")
c.Assert(conf.ProxyHostPort(true), check.Equals, "example.org:3080")

conf.ProxyHost = "example.org:100"
c.Assert(conf.ProxySpecified(), check.Equals, true)
c.Assert(conf.ProxyHostPort(12), check.Equals, "example.org:100")
c.Assert(conf.ProxyHostPort(false), check.Equals, "example.org:100")
c.Assert(conf.ProxyHostPort(true), check.Equals, "example.org:3080")

conf.ProxyHost = "example.org:100,200"
c.Assert(conf.ProxyHostPort(false), check.Equals, "example.org:100")
c.Assert(conf.ProxyHostPort(true), check.Equals, "example.org:200")

conf.ProxyHost = "example.org:,200"
c.Assert(conf.ProxyHostPort(true), check.Equals, "example.org:200")
}

func (s *APITestSuite) TestNew(c *check.C) {
Expand All @@ -63,10 +72,7 @@ func (s *APITestSuite) TestNew(c *check.C) {

la := tc.LocalAgent()
c.Assert(la, check.NotNil)

c.Assert(tc.NodeHostPort(), check.Equals, "localhost:22")
c.Assert(tc.ProxySpecified(), check.Equals, true)
c.Assert(tc.ProxyHostPort(12), check.Equals, "proxy:12")
}

func (s *APITestSuite) TestParseLabels(c *check.C) {
Expand Down
3 changes: 2 additions & 1 deletion tool/tsh/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ func (s *MainTestSuite) TestMakeClient(c *check.C) {
c.Assert(err, check.IsNil)
c.Assert(tc, check.NotNil)
c.Assert(tc.Config.NodeHostPort(), check.Equals, "localhost:3022")
c.Assert(tc.Config.ProxyHostPort(666), check.Equals, "proxy:666")
c.Assert(tc.Config.ProxyHostPort(false), check.Equals, "proxy:3023")
c.Assert(tc.Config.ProxyHostPort(true), check.Equals, "proxy:3080")
c.Assert(tc.Config.HostLogin, check.Equals, client.Username())
c.Assert(tc.Config.KeyTTL, check.Equals, defaults.CertDuration)

Expand Down

0 comments on commit df05b9e

Please sign in to comment.