From 0861923c216d463ec8118c851933953d632dafdf Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 22 Mar 2022 17:36:55 -0700 Subject: [PATCH] ssh/tailssh, tailcfg: add more HoldAndDelegate expansions, document Updates #3802 Change-Id: I447f06b49e2a917bffe36881d0634c9195085512 Signed-off-by: Brad Fitzpatrick --- ssh/tailssh/tailssh.go | 11 +++++++---- tailcfg/tailcfg.go | 9 +++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ssh/tailssh/tailssh.go b/ssh/tailssh/tailssh.go index df94d7dd7..def871370 100644 --- a/ssh/tailssh/tailssh.go +++ b/ssh/tailssh/tailssh.go @@ -18,6 +18,7 @@ import ( "io/ioutil" "net" "net/http" + "net/url" "os" "os/exec" "os/user" @@ -272,18 +273,20 @@ func (ss *sshSession) resolveTerminalAction(action *tailcfg.SSHAction) (*tailcfg } } -func (ss *sshSession) expandDelegateURL(url string) string { +func (ss *sshSession) expandDelegateURL(actionURL string) string { nm := ss.srv.lb.NetMap() var dstNodeID string if nm != nil { dstNodeID = fmt.Sprint(int64(nm.SelfNode.ID)) } return strings.NewReplacer( + "$SRC_NODE_IP", url.QueryEscape(ss.connInfo.src.IP().String()), "$SRC_NODE_ID", fmt.Sprint(int64(ss.connInfo.node.ID)), + "$DST_NODE_IP", url.QueryEscape(ss.connInfo.dst.IP().String()), "$DST_NODE_ID", dstNodeID, - "$SSH_USER", ss.connInfo.sshUser, - "$LOCAL_USER", ss.localUser.Username, - ).Replace(url) + "$SSH_USER", url.QueryEscape(ss.connInfo.sshUser), + "$LOCAL_USER", url.QueryEscape(ss.localUser.Username), + ).Replace(actionURL) } // sshSession is an accepted Tailscale SSH session. diff --git a/tailcfg/tailcfg.go b/tailcfg/tailcfg.go index c4ec0d44b..b39f04135 100644 --- a/tailcfg/tailcfg.go +++ b/tailcfg/tailcfg.go @@ -1635,6 +1635,15 @@ type SSHAction struct { // If the long poll breaks before returning a complete HTTP // response, it should be re-fetched as long as the SSH // session is open. + // + // The following variables in the URL are expanded by tailscaled: + // + // * $SRC_NODE_IP (URL escaped) + // * $SRC_NODE_ID (Node.ID as int64 string) + // * $DST_NODE_IP (URL escaped) + // * $DST_NODE_ID (Node.ID as int64 string) + // * $SSH_USER (URL escaped, ssh user requested) + // * $LOCAL_USER (URL escaped, local user mapped) HoldAndDelegate string `json:"holdAndDelegate,omitempty"` // AllowLocalPortForwarding, if true, allows accepted connections