Files
sing-box-extended-mirror/experimental/libbox/service.go
T

409 lines
12 KiB
Go
Raw Normal View History

2022-10-25 12:55:00 +08:00
package libbox
import (
"crypto/rand"
"encoding/hex"
"errors"
"net"
2022-10-25 12:55:00 +08:00
"net/netip"
2023-11-15 13:05:33 +08:00
"runtime"
"strconv"
2024-11-11 16:23:45 +08:00
"sync"
2022-10-25 12:55:00 +08:00
"syscall"
2023-04-18 14:04:09 +08:00
"github.com/sagernet/sing-box/adapter"
2024-03-14 13:40:17 +08:00
C "github.com/sagernet/sing-box/constant"
2022-10-25 12:55:00 +08:00
"github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
2023-02-28 19:02:27 +08:00
"github.com/sagernet/sing-box/option"
tun "github.com/sagernet/sing-tun"
2023-04-18 14:04:09 +08:00
"github.com/sagernet/sing/common"
2022-10-25 12:55:00 +08:00
"github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
2023-07-23 14:42:19 +08:00
"github.com/sagernet/sing/common/logger"
2022-10-25 12:55:00 +08:00
)
var _ adapter.PlatformInterface = (*platformInterfaceWrapper)(nil)
2022-10-25 12:55:00 +08:00
type platformInterfaceWrapper struct {
2024-11-11 16:23:45 +08:00
iif PlatformInterface
useProcFS bool
networkManager adapter.NetworkManager
myTunName string
myTunAddress []netip.Addr
2024-11-11 16:23:45 +08:00
defaultInterfaceAccess sync.Mutex
defaultInterface *control.Interface
isExpensive bool
isConstrained bool
2023-04-18 14:04:09 +08:00
}
2024-11-10 12:11:21 +08:00
func (w *platformInterfaceWrapper) Initialize(networkManager adapter.NetworkManager) error {
w.networkManager = networkManager
2023-04-18 14:04:09 +08:00
return nil
2022-10-25 12:55:00 +08:00
}
func (w *platformInterfaceWrapper) UsePlatformAutoDetectInterfaceControl() bool {
return w.iif.UsePlatformAutoDetectInterfaceControl()
}
2024-11-06 12:51:53 +08:00
func (w *platformInterfaceWrapper) AutoDetectInterfaceControl(fd int) error {
return w.iif.AutoDetectInterfaceControl(int32(fd))
2022-10-25 12:55:00 +08:00
}
func (w *platformInterfaceWrapper) UsePlatformInterface() bool {
return true
}
func (w *platformInterfaceWrapper) OpenInterface(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) {
2022-10-25 12:55:00 +08:00
if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
2024-12-23 22:24:10 +08:00
return nil, E.New("platform: unsupported uid options")
2022-10-25 12:55:00 +08:00
}
if len(options.IncludeAndroidUser) > 0 {
2024-12-23 22:24:10 +08:00
return nil, E.New("platform: unsupported android_user option")
2022-10-25 12:55:00 +08:00
}
2023-10-30 12:00:00 +08:00
routeRanges, err := options.BuildAutoRouteRanges(true)
if err != nil {
return nil, err
}
tunFd, err := w.iif.OpenTun(&tunOptions{options, routeRanges, platformOptions})
2022-10-25 12:55:00 +08:00
if err != nil {
return nil, err
}
options.Name, err = getTunnelName(tunFd)
if err != nil {
return nil, E.Cause(err, "query tun name")
}
2025-04-12 21:26:22 +08:00
options.InterfaceMonitor.RegisterMyInterface(options.Name)
2023-04-07 21:10:16 +08:00
dupFd, err := dup(int(tunFd))
2023-03-13 19:47:00 +08:00
if err != nil {
return nil, E.Cause(err, "dup tun file descriptor")
}
options.FileDescriptor = dupFd
2024-11-11 16:23:45 +08:00
w.myTunName = options.Name
w.myTunAddress = myTunAddress(options)
w.iif.RegisterMyInterface(options.Name)
return tun.New(*options)
2022-10-25 12:55:00 +08:00
}
func (w *platformInterfaceWrapper) ProcessPlatformOptions(options option.TunPlatformOptions) error {
return nil
}
func myTunAddress(options *tun.Options) []netip.Addr {
addresses := make([]netip.Addr, 0, len(options.Inet4Address)+len(options.Inet6Address))
for _, prefix := range options.Inet4Address {
addresses = append(addresses, prefix.Addr())
}
for _, prefix := range options.Inet6Address {
addresses = append(addresses, prefix.Addr())
}
return addresses
}
func (w *platformInterfaceWrapper) MyInterfaceAddress() []netip.Addr {
return w.myTunAddress
}
func (w *platformInterfaceWrapper) UsePlatformDefaultInterfaceMonitor() bool {
return true
}
2023-07-23 14:42:19 +08:00
func (w *platformInterfaceWrapper) CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor {
2023-04-18 14:04:09 +08:00
return &platformDefaultInterfaceMonitor{
platformInterfaceWrapper: w,
2023-07-23 14:42:19 +08:00
logger: logger,
2023-04-18 14:04:09 +08:00
}
}
func (w *platformInterfaceWrapper) UsePlatformNetworkInterfaces() bool {
return true
}
func (w *platformInterfaceWrapper) NetworkInterfaces() ([]adapter.NetworkInterface, error) {
2023-04-18 14:04:09 +08:00
interfaceIterator, err := w.iif.GetInterfaces()
if err != nil {
return nil, err
}
2024-11-11 16:23:45 +08:00
var interfaces []adapter.NetworkInterface
2023-04-18 14:04:09 +08:00
for _, netInterface := range iteratorToArray[*NetworkInterface](interfaceIterator) {
2024-11-11 16:23:45 +08:00
w.defaultInterfaceAccess.Lock()
2025-03-16 14:50:44 +08:00
// (GOOS=windows) SA4006: this value of `isDefault` is never used
// Why not used?
//nolint:staticcheck
2026-04-21 15:23:05 +08:00
isDefault := netInterface.Name != w.myTunName && w.defaultInterface != nil && int(netInterface.Index) == w.defaultInterface.Index
2024-11-11 16:23:45 +08:00
w.defaultInterfaceAccess.Unlock()
interfaces = append(interfaces, adapter.NetworkInterface{
Interface: control.Interface{
Index: int(netInterface.Index),
MTU: int(netInterface.MTU),
Name: netInterface.Name,
Addresses: common.Map(iteratorToArray[string](netInterface.Addresses), netip.MustParsePrefix),
Flags: linkFlags(uint32(netInterface.Flags)),
},
2024-11-13 19:05:28 +08:00
Type: C.InterfaceType(netInterface.Type),
2024-11-11 16:23:45 +08:00
DNSServers: iteratorToArray[string](netInterface.DNSServer),
Expensive: netInterface.Metered || isDefault && w.isExpensive,
Constrained: isDefault && w.isConstrained,
2023-04-18 14:04:09 +08:00
})
}
2026-01-11 17:07:31 +08:00
interfaces = common.UniqBy(interfaces, func(it adapter.NetworkInterface) string {
return it.Name
})
2023-04-18 14:04:09 +08:00
return interfaces, nil
}
2023-06-07 21:01:29 +08:00
func (w *platformInterfaceWrapper) UnderNetworkExtension() bool {
return w.iif.UnderNetworkExtension()
}
func (w *platformInterfaceWrapper) NetworkExtensionIncludeAllNetworks() bool {
2024-05-07 20:34:24 +08:00
return w.iif.IncludeAllNetworks()
}
func (w *platformInterfaceWrapper) ClearDNSCache() {
w.iif.ClearDNSCache()
}
2023-11-15 13:05:33 +08:00
func (w *platformInterfaceWrapper) RequestPermissionForWIFIState() error {
return nil
2025-12-07 11:05:43 +08:00
}
func (w *platformInterfaceWrapper) UsePlatformWIFIMonitor() bool {
return true
}
func (w *platformInterfaceWrapper) ReadWIFIState() adapter.WIFIState {
wifiState := w.iif.ReadWIFIState()
if wifiState == nil {
return adapter.WIFIState{}
}
return (adapter.WIFIState)(*wifiState)
}
func (w *platformInterfaceWrapper) UsePlatformConnectionOwnerFinder() bool {
return true
}
func (w *platformInterfaceWrapper) FindConnectionOwner(request *adapter.FindConnectionOwnerRequest) (*adapter.ConnectionOwner, error) {
2024-06-11 21:16:33 +08:00
if w.useProcFS {
var source netip.AddrPort
var destination netip.AddrPort
sourceAddr, _ := netip.ParseAddr(request.SourceAddress)
source = netip.AddrPortFrom(sourceAddr, uint16(request.SourcePort))
destAddr, _ := netip.ParseAddr(request.DestinationAddress)
destination = netip.AddrPortFrom(destAddr, uint16(request.DestinationPort))
var network string
switch request.IpProtocol {
case int32(syscall.IPPROTO_TCP):
network = "tcp"
case int32(syscall.IPPROTO_UDP):
network = "udp"
default:
return nil, E.New("unknown protocol: ", request.IpProtocol)
}
2026-01-04 02:53:33 +08:00
uid := procfs.ResolveSocketByProcSearch(network, source, destination)
2024-06-11 21:16:33 +08:00
if uid == -1 {
return nil, E.New("procfs: not found")
}
2026-01-04 02:53:33 +08:00
return &adapter.ConnectionOwner{
UserId: uid,
}, nil
}
result, err := w.iif.FindConnectionOwner(request.IpProtocol, request.SourceAddress, request.SourcePort, request.DestinationAddress, request.DestinationPort)
if err != nil {
return nil, err
2024-06-11 21:16:33 +08:00
}
return &adapter.ConnectionOwner{
2026-03-23 18:33:03 +08:00
UserId: result.UserId,
UserName: result.UserName,
ProcessPath: result.ProcessPath,
AndroidPackageNames: result.androidPackageNames,
}, nil
2024-06-11 21:16:33 +08:00
}
2023-11-15 13:05:33 +08:00
func (w *platformInterfaceWrapper) DisableColors() bool {
return runtime.GOOS != "android"
}
func (w *platformInterfaceWrapper) UsePlatformNotification() bool {
return true
2023-11-15 13:05:33 +08:00
}
2024-11-06 12:51:53 +08:00
func (w *platformInterfaceWrapper) SendNotification(notification *adapter.Notification) error {
2024-11-06 12:51:53 +08:00
return w.iif.SendNotification((*Notification)(notification))
}
func (w *platformInterfaceWrapper) UsePlatformNeighborResolver() bool {
return true
}
func (w *platformInterfaceWrapper) StartNeighborMonitor(listener adapter.NeighborUpdateListener) error {
return w.iif.StartNeighborMonitor(&neighborUpdateListenerWrapper{listener: listener})
}
func (w *platformInterfaceWrapper) CloseNeighborMonitor(listener adapter.NeighborUpdateListener) error {
return w.iif.CloseNeighborMonitor(nil)
}
2026-05-28 18:42:58 +08:00
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) {
return w.iif.LookupSFTPServer()
2026-05-28 18:42:58 +08:00
}
func (w *platformInterfaceWrapper) ReadSystemSSHHostKey() ([]byte, error) {
result, err := w.iif.ReadSystemSSHHostKey()
if err != nil {
return nil, err
}
return []byte(result), nil
}
func (w *platformInterfaceWrapper) TailscaleHostname() string {
return w.iif.TailscaleHostname()
2026-05-28 18:42:58 +08:00
}
2026-07-08 00:10:00 +08:00
func (w *platformInterfaceWrapper) UsePlatformBridge() bool {
return w.iif.UsePlatformBridge()
}
func (w *platformInterfaceWrapper) CreateBridge(options adapter.BridgeOptions) (adapter.BridgeSession, error) {
bridgeOptions := &BridgeOptions{
BridgeName: options.BridgeName,
MTU: int32(options.MTU),
Interface: options.Interface,
RuleIndex: int32(options.RuleIndex),
RouteTable: int32(options.RouteTable),
}
if options.Inet4Port.IsValid() {
bridgeOptions.Inet4Port = options.Inet4Port.String()
}
if options.Inet6Port.IsValid() {
bridgeOptions.Inet6Port = options.Inet6Port.String()
}
session, err := w.iif.CreateBridge(bridgeOptions)
if err != nil {
return nil, err
}
return &bridgeSessionWrapper{session}, nil
}
type bridgeSessionWrapper struct {
session BridgeSession
}
func (w *bridgeSessionWrapper) FileDescriptor() int {
return int(w.session.FileDescriptor())
}
func (w *bridgeSessionWrapper) Name() string {
return w.session.Name()
}
func (w *bridgeSessionWrapper) Inet6Active() bool {
return w.session.Inet6Active()
}
func (w *bridgeSessionWrapper) SetEgress(interfaceName string) error {
return w.session.SetEgress(interfaceName)
}
func (w *bridgeSessionWrapper) Close() error {
return w.session.Close()
}
2026-05-28 18:42:58 +08:00
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
}
func (w *neighborUpdateListenerWrapper) UpdateNeighborTable(entries NeighborEntryIterator) {
var result []adapter.NeighborEntry
for entries.HasNext() {
entry := entries.Next()
if entry == nil {
continue
}
address, err := netip.ParseAddr(entry.Address)
if err != nil {
continue
}
macAddress, err := net.ParseMAC(entry.MacAddress)
if err != nil {
continue
}
result = append(result, adapter.NeighborEntry{
Address: address,
MACAddress: macAddress,
Hostname: entry.Hostname,
})
}
w.listener.UpdateNeighborTable(result)
}
func AvailablePort(startPort int32) (int32, error) {
for port := int(startPort); ; port++ {
if port > 65535 {
return 0, E.New("no available port found")
}
listener, err := net.Listen("tcp", net.JoinHostPort("127.0.0.1", strconv.Itoa(int(port))))
if err != nil {
if errors.Is(err, syscall.EADDRINUSE) {
continue
}
return 0, E.Cause(err, "find available port")
}
err = listener.Close()
if err != nil {
return 0, E.Cause(err, "close listener")
}
return int32(port), nil
}
}
func RandomHex(length int32) *StringBox {
bytes := make([]byte, length)
common.Must1(rand.Read(bytes))
return wrapString(hex.EncodeToString(bytes))
}