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

303 lines
8.8 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 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)
}
2025-01-08 10:34:45 +08:00
func (w *platformInterfaceWrapper) SystemCertificates() []string {
return iteratorToArray[string](w.iif.SystemCertificates())
}
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)
}
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))
}