mirror of
https://github.com/tailscale/tailscale.git
synced 2025-07-29 07:13:44 +00:00
cmd/tailscale: allow SSH to IPs or DNS names without MagicDNS (#16591)
fixes #16381 Signed-off-by: Danni Popova <danni@tailscale.com>
This commit is contained in:
parent
2a5d9c7269
commit
c572442548
@ -70,12 +70,28 @@ func runSSH(ctx context.Context, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
prefs, err := localClient.GetPrefs(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// hostForSSH is the hostname we'll tell OpenSSH we're
|
||||
// connecting to, so we have to maintain fewer entries in the
|
||||
// known_hosts files.
|
||||
hostForSSH := host
|
||||
if v, ok := nodeDNSNameFromArg(st, host); ok {
|
||||
hostForSSH = v
|
||||
ps, ok := peerStatusFromArg(st, host)
|
||||
if ok {
|
||||
hostForSSH = ps.DNSName
|
||||
|
||||
// If MagicDNS isn't enabled on the client,
|
||||
// we will use the first IPv4 we know about
|
||||
// or fallback to the first IPv6 address
|
||||
if !prefs.CorpDNS {
|
||||
ipHost, found := ipFromPeerStatus(ps)
|
||||
if found {
|
||||
hostForSSH = ipHost
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssh, err := findSSH()
|
||||
@ -169,11 +185,40 @@ func genKnownHosts(st *ipnstate.Status) []byte {
|
||||
continue
|
||||
}
|
||||
fmt.Fprintf(&buf, "%s %s\n", ps.DNSName, hostKey)
|
||||
for _, ip := range ps.TailscaleIPs {
|
||||
fmt.Fprintf(&buf, "%s %s\n", ip.String(), hostKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.Bytes()
|
||||
}
|
||||
|
||||
// peerStatusFromArg returns the PeerStatus that matches
|
||||
// the input arg which can be a base name, full DNS name, or an IP.
|
||||
func peerStatusFromArg(st *ipnstate.Status, arg string) (*ipnstate.PeerStatus, bool) {
|
||||
if arg == "" {
|
||||
return nil, false
|
||||
}
|
||||
argIP, _ := netip.ParseAddr(arg)
|
||||
for _, ps := range st.Peer {
|
||||
if argIP.IsValid() {
|
||||
for _, ip := range ps.TailscaleIPs {
|
||||
if ip == argIP {
|
||||
return ps, true
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(strings.TrimSuffix(arg, "."), strings.TrimSuffix(ps.DNSName, ".")) {
|
||||
return ps, true
|
||||
}
|
||||
if base, _, ok := strings.Cut(ps.DNSName, "."); ok && strings.EqualFold(base, arg) {
|
||||
return ps, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// nodeDNSNameFromArg returns the PeerStatus.DNSName value from a peer
|
||||
// in st that matches the input arg which can be a base name, full
|
||||
// DNS name, or an IP.
|
||||
@ -202,6 +247,20 @@ func nodeDNSNameFromArg(st *ipnstate.Status, arg string) (dnsName string, ok boo
|
||||
return "", false
|
||||
}
|
||||
|
||||
func ipFromPeerStatus(ps *ipnstate.PeerStatus) (string, bool) {
|
||||
if len(ps.TailscaleIPs) < 1 {
|
||||
return "", false
|
||||
}
|
||||
|
||||
// Look for a IPv4 address or default to the first IP of the list
|
||||
for _, ip := range ps.TailscaleIPs {
|
||||
if ip.Is4() {
|
||||
return ip.String(), true
|
||||
}
|
||||
}
|
||||
return ps.TailscaleIPs[0].String(), true
|
||||
}
|
||||
|
||||
// getSSHClientEnvVar returns the "SSH_CLIENT" environment variable
|
||||
// for the current process group, if any.
|
||||
var getSSHClientEnvVar = func() string {
|
||||
|
Loading…
x
Reference in New Issue
Block a user