tailscale: Add tailssh server
This commit is contained in:
@@ -167,6 +167,30 @@ func (s *platformInterfaceStub) CloseNeighborMonitor(listener adapter.NeighborUp
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) UsePlatformShell() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) CheckPlatformShell() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) OpenShellSession(user *adapter.PlatformUser, command string, env []string, term string, rows int32, cols int32) (adapter.ShellSession, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) LookupSFTPServer() (string, error) {
|
||||
return "", os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) ReadSystemSSHHostKey() ([]byte, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) LookupUser(username string) (*adapter.PlatformUser, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
|
||||
func (s *platformInterfaceStub) UsePlatformLocalDNSTransport() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
//go:build linux || android || (darwin && !ios)
|
||||
|
||||
package libbox
|
||||
|
||||
import (
|
||||
"github.com/sagernet/sing-box/protocol/tailscale/tailssh"
|
||||
"github.com/sagernet/sing/common"
|
||||
)
|
||||
|
||||
type nativeShellSession struct {
|
||||
shell *tailssh.Shell
|
||||
}
|
||||
|
||||
func OpenNativeShellSession(
|
||||
shell, cwd string,
|
||||
args, environ StringIterator,
|
||||
term string,
|
||||
rows, cols, uid, gid int32,
|
||||
groups Int32Iterator,
|
||||
) (ShellSession, error) {
|
||||
sh, err := tailssh.OpenPtyShell(
|
||||
shell,
|
||||
iteratorToArray[string](args),
|
||||
iteratorToArray[string](environ),
|
||||
cwd,
|
||||
int(uid), int(gid),
|
||||
common.Map(iteratorToArray[int32](groups), func(g int32) int { return int(g) }),
|
||||
uint16(rows), uint16(cols),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &nativeShellSession{shell: sh}, nil
|
||||
}
|
||||
|
||||
func OpenNativePipeSession(
|
||||
shell, cwd string,
|
||||
args, environ StringIterator,
|
||||
uid, gid int32,
|
||||
groups Int32Iterator,
|
||||
) (ShellSession, error) {
|
||||
sh, err := tailssh.OpenSocketpairShell(
|
||||
shell,
|
||||
iteratorToArray[string](args),
|
||||
iteratorToArray[string](environ),
|
||||
cwd,
|
||||
int(uid), int(gid),
|
||||
common.Map(iteratorToArray[int32](groups), func(g int32) int { return int(g) }),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &nativeShellSession{shell: sh}, nil
|
||||
}
|
||||
|
||||
func (s *nativeShellSession) MasterFD() int32 {
|
||||
return int32(s.shell.MasterFD())
|
||||
}
|
||||
|
||||
func (s *nativeShellSession) Resize(rows, cols int32) error {
|
||||
return s.shell.Resize(uint16(rows), uint16(cols))
|
||||
}
|
||||
|
||||
func (s *nativeShellSession) Signal(sig int32) error {
|
||||
return s.shell.Signal(int(sig))
|
||||
}
|
||||
|
||||
func (s *nativeShellSession) WaitExit() (int32, error) {
|
||||
status, err := s.shell.Wait()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(status), nil
|
||||
}
|
||||
|
||||
func (s *nativeShellSession) Close() error {
|
||||
return s.shell.Close()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
//go:build !linux && !android && (!darwin || ios)
|
||||
|
||||
package libbox
|
||||
|
||||
import (
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
)
|
||||
|
||||
func OpenNativeShellSession(
|
||||
shell, cwd string,
|
||||
args, environ StringIterator,
|
||||
term string,
|
||||
rows, cols, uid, gid int32,
|
||||
groups Int32Iterator,
|
||||
) (ShellSession, error) {
|
||||
return nil, E.New("native shell session not supported on this platform")
|
||||
}
|
||||
|
||||
func OpenNativePipeSession(
|
||||
shell, cwd string,
|
||||
args, environ StringIterator,
|
||||
uid, gid int32,
|
||||
groups Int32Iterator,
|
||||
) (ShellSession, error) {
|
||||
return nil, E.New("native pipe session not supported on this platform")
|
||||
}
|
||||
@@ -21,6 +21,30 @@ type PlatformInterface interface {
|
||||
StartNeighborMonitor(listener NeighborUpdateListener) error
|
||||
CloseNeighborMonitor(listener NeighborUpdateListener) error
|
||||
RegisterMyInterface(name string)
|
||||
UsePlatformShell() bool
|
||||
CheckPlatformShell() error
|
||||
OpenShellSession(user *PlatformUser, command string, environ StringIterator, term string, rows int32, cols int32) (ShellSession, error)
|
||||
LookupUser(username string) (*PlatformUser, error)
|
||||
LookupSFTPServer() (*StringBox, error)
|
||||
ReadSystemSSHHostKey() (*StringBox, error)
|
||||
}
|
||||
|
||||
type PlatformUser struct {
|
||||
Username string
|
||||
Uid int32
|
||||
Gid int32
|
||||
HomeDir string
|
||||
Shell string
|
||||
|
||||
groups []int32
|
||||
}
|
||||
|
||||
func (u *PlatformUser) SetGroups(groups Int32Iterator) {
|
||||
u.groups = iteratorToArray[int32](groups)
|
||||
}
|
||||
|
||||
func (u *PlatformUser) Groups() Int32Iterator {
|
||||
return newIterator(u.groups)
|
||||
}
|
||||
|
||||
type NeighborUpdateListener interface {
|
||||
|
||||
@@ -247,6 +247,63 @@ func (w *platformInterfaceWrapper) CloseNeighborMonitor(listener adapter.Neighbo
|
||||
return w.iif.CloseNeighborMonitor(nil)
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) UsePlatformShell() bool {
|
||||
return w.iif.UsePlatformShell()
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) CheckPlatformShell() error {
|
||||
return w.iif.CheckPlatformShell()
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) OpenShellSession(user *adapter.PlatformUser, command string, environ []string, term string, rows int32, cols int32) (adapter.ShellSession, error) {
|
||||
libboxUser := &PlatformUser{
|
||||
Username: user.Username,
|
||||
Uid: int32(user.Uid),
|
||||
Gid: int32(user.Gid),
|
||||
HomeDir: user.HomeDir,
|
||||
Shell: user.Shell,
|
||||
}
|
||||
if len(user.Groups) > 0 {
|
||||
libboxUser.SetGroups(newIterator(common.Map(user.Groups, func(g int) int32 { return int32(g) })))
|
||||
}
|
||||
session, err := w.iif.OpenShellSession(libboxUser, command, newIterator(environ), term, rows, cols)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) LookupSFTPServer() (string, error) {
|
||||
result, err := w.iif.LookupSFTPServer()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return result.Value, nil
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) ReadSystemSSHHostKey() ([]byte, error) {
|
||||
result, err := w.iif.ReadSystemSSHHostKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []byte(result.Value), nil
|
||||
}
|
||||
|
||||
func (w *platformInterfaceWrapper) LookupUser(username string) (*adapter.PlatformUser, error) {
|
||||
platformUser, err := w.iif.LookupUser(username)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &adapter.PlatformUser{
|
||||
Username: platformUser.Username,
|
||||
Uid: int(platformUser.Uid),
|
||||
Gid: int(platformUser.Gid),
|
||||
HomeDir: platformUser.HomeDir,
|
||||
Shell: platformUser.Shell,
|
||||
Groups: common.Map(iteratorToArray[int32](platformUser.Groups()), func(g int32) int { return int(g) }),
|
||||
}, nil
|
||||
}
|
||||
|
||||
type neighborUpdateListenerWrapper struct {
|
||||
listener adapter.NeighborUpdateListener
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package libbox
|
||||
|
||||
type ShellSession interface {
|
||||
MasterFD() int32
|
||||
Resize(rows int32, cols int32) error
|
||||
Signal(signal int32) error
|
||||
WaitExit() (int32, error)
|
||||
Close() error
|
||||
}
|
||||
Reference in New Issue
Block a user