mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
79 lines
2.2 KiB
Go
79 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"os/exec"
|
|
"os/user"
|
|
"strings"
|
|
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
|
|
"github.com/spf13/cobra"
|
|
)
|
|
|
|
var commandAPITailscaleSSH = &cobra.Command{
|
|
Use: "ssh [user@]<peer>",
|
|
Short: "SSH into a Tailscale peer",
|
|
Long: "SSH into a Tailscale peer.\n\n" +
|
|
"The local ssh binary is executed against the Tailscale address of the peer, so the machine running " +
|
|
"this command must be able to route Tailscale addresses into the Tailscale endpoint itself, " +
|
|
"usually by running behind a sing-box instance with a tun inbound.\n\n" +
|
|
"The user defaults to the current user, and Tailscale SSH authentication is not available: " +
|
|
"the peer is reached as an ordinary SSH server.",
|
|
Args: cobra.ExactArgs(1),
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
return runAPITailscaleSSH(args[0])
|
|
},
|
|
}
|
|
|
|
func init() {
|
|
commandAPITailscaleSSH.Flags().StringVar(&commandAPITailscaleFlagEndpoint, "endpoint", "", commandAPITailscaleEndpointUsage)
|
|
commandAPITailscale.AddCommand(commandAPITailscaleSSH)
|
|
}
|
|
|
|
func runAPITailscaleSSH(target string) error {
|
|
loginName := ""
|
|
selector := target
|
|
nameIndex := strings.LastIndex(target, "@")
|
|
if nameIndex != -1 {
|
|
loginName = target[:nameIndex]
|
|
selector = target[nameIndex+1:]
|
|
}
|
|
if loginName == "" {
|
|
currentUser, userErr := user.Current()
|
|
if userErr == nil {
|
|
loginName = currentUser.Username
|
|
_, domainUserName, isDomainUser := strings.Cut(loginName, "\\")
|
|
if isDomainUser {
|
|
loginName = domainUserName
|
|
}
|
|
}
|
|
}
|
|
clientConn, client, err := createAPIClient()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer clientConn.Close()
|
|
endpoint, err := fetchTailscaleEndpoint(client)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
entry, err := resolveTailscalePeer(tailscalePeerEntries(endpoint), selector)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
peerAddress := tailscalePeerAddress(entry.peer)
|
|
if peerAddress == "" {
|
|
return E.New("peer has no tailscale address: ", tailscalePeerName(entry.peer))
|
|
}
|
|
clientConn.Close()
|
|
sshPath, err := exec.LookPath("ssh")
|
|
if err != nil {
|
|
return E.New("ssh not found in PATH")
|
|
}
|
|
destination := peerAddress
|
|
if loginName != "" {
|
|
destination = loginName + "@" + peerAddress
|
|
}
|
|
return executeSSH(sshPath, []string{"ssh", destination})
|
|
}
|