Reject Tailscale SSH user switch without privilege

This commit is contained in:
世界 committed 2026-10-23 19:57:05 +08:00
1 parent c064173870
commit c8ba005e84
3 files changed
+49 -4

No files matched your search

@@ -11,6 +11,7 @@ import (
gliderssh "github.com/sagernet/gliderssh"
"github.com/sagernet/sing-box/adapter"
E "github.com/sagernet/sing/common/exceptions"
)
func isPrivilegedUser() bool {
@@ -21,10 +22,21 @@ func requestedUserMatchesProcess(localUser *adapter.PlatformUser) (bool, error)
return localUser.Uid == os.Getuid() && localUser.Gid == os.Getgid(), nil
}
// verifyShellIdentity is a no-op on Unix: spawned shells and sftp-server drop to the
// requested user via setCredential, so the child already runs as that user.
func verifyShellIdentity(_ adapter.PlatformInterface, _ *adapter.PlatformUser) error {
return nil
func verifyShellIdentity(platformInterface adapter.PlatformInterface, localUser *adapter.PlatformUser) error {
if platformInterface != nil && platformInterface.UsePlatformShell() {
return nil
}
match, err := requestedUserMatchesProcess(localUser)
if err != nil {
return err
}
if match {
return nil
}
if !isPrivilegedUser() {
return E.New("switching to local user ", localUser.Username, " requires sing-box to run as root")
}
return checkSwitchUserPrivilege(localUser)
}
func systemHostKeyPath() string {
@@ -0,0 +1,24 @@
//go:build with_gvisor && linux
package tailssh
import (
"github.com/sagernet/sing-box/adapter"
E "github.com/sagernet/sing/common/exceptions"
"golang.org/x/sys/unix"
)
func checkSwitchUserPrivilege(localUser *adapter.PlatformUser) error {
header := unix.CapUserHeader{Version: unix.LINUX_CAPABILITY_VERSION_3}
var data [2]unix.CapUserData
err := unix.Capget(&header, &data[0])
if err != nil {
return E.Cause(err, "query process capabilities")
}
const required = 1<<unix.CAP_SETUID | 1<<unix.CAP_SETGID
if data[0].Effective&required != required {
return E.New("switching to local user ", localUser.Username, " requires CAP_SETUID and CAP_SETGID")
}
return nil
}
@@ -0,0 +1,9 @@
//go:build with_gvisor && !windows && !linux
package tailssh
import "github.com/sagernet/sing-box/adapter"
func checkSwitchUserPrivilege(_ *adapter.PlatformUser) error {
return nil
}