service.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //go:build linux || darwin
  2. package libbox
  3. import (
  4. "context"
  5. "net/netip"
  6. "syscall"
  7. "github.com/sagernet/sing-box"
  8. "github.com/sagernet/sing-box/common/process"
  9. "github.com/sagernet/sing-box/experimental/libbox/internal/procfs"
  10. "github.com/sagernet/sing-box/experimental/libbox/platform"
  11. "github.com/sagernet/sing-box/option"
  12. "github.com/sagernet/sing-tun"
  13. "github.com/sagernet/sing/common/control"
  14. E "github.com/sagernet/sing/common/exceptions"
  15. N "github.com/sagernet/sing/common/network"
  16. )
  17. type BoxService struct {
  18. ctx context.Context
  19. cancel context.CancelFunc
  20. instance *box.Box
  21. }
  22. func NewService(configContent string, platformInterface PlatformInterface) (*BoxService, error) {
  23. options, err := parseConfig(configContent)
  24. if err != nil {
  25. return nil, err
  26. }
  27. ctx, cancel := context.WithCancel(context.Background())
  28. instance, err := box.New(ctx, options, &platformInterfaceWrapper{platformInterface, platformInterface.UseProcFS()})
  29. if err != nil {
  30. cancel()
  31. return nil, E.Cause(err, "create service")
  32. }
  33. return &BoxService{
  34. ctx: ctx,
  35. cancel: cancel,
  36. instance: instance,
  37. }, nil
  38. }
  39. func (s *BoxService) Start() error {
  40. return s.instance.Start()
  41. }
  42. func (s *BoxService) Close() error {
  43. s.cancel()
  44. return s.instance.Close()
  45. }
  46. var _ platform.Interface = (*platformInterfaceWrapper)(nil)
  47. type platformInterfaceWrapper struct {
  48. iif PlatformInterface
  49. useProcFS bool
  50. }
  51. func (w *platformInterfaceWrapper) AutoDetectInterfaceControl() control.Func {
  52. return func(network, address string, conn syscall.RawConn) error {
  53. return control.Raw(conn, func(fd uintptr) error {
  54. return w.iif.AutoDetectInterfaceControl(int32(fd))
  55. })
  56. }
  57. }
  58. func (w *platformInterfaceWrapper) OpenTun(options tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error) {
  59. if len(options.IncludeUID) > 0 || len(options.ExcludeUID) > 0 {
  60. return nil, E.New("android: unsupported uid options")
  61. }
  62. if len(options.IncludeAndroidUser) > 0 {
  63. return nil, E.New("android: unsupported android_user option")
  64. }
  65. tunFd, err := w.iif.OpenTun(&tunOptions{options, platformOptions})
  66. if err != nil {
  67. return nil, err
  68. }
  69. dupFd, err := syscall.Dup(int(tunFd))
  70. if err != nil {
  71. return nil, E.Cause(err, "dup tun file descriptor")
  72. }
  73. options.FileDescriptor = dupFd
  74. return tun.New(options)
  75. }
  76. func (w *platformInterfaceWrapper) Write(p []byte) (n int, err error) {
  77. w.iif.WriteLog(string(p))
  78. return len(p), nil
  79. }
  80. func (w *platformInterfaceWrapper) FindProcessInfo(ctx context.Context, network string, source netip.AddrPort, destination netip.AddrPort) (*process.Info, error) {
  81. var uid int32
  82. if w.useProcFS {
  83. uid = procfs.ResolveSocketByProcSearch(network, source, destination)
  84. if uid == -1 {
  85. return nil, E.New("procfs: not found")
  86. }
  87. } else {
  88. var ipProtocol int32
  89. switch N.NetworkName(network) {
  90. case N.NetworkTCP:
  91. ipProtocol = syscall.IPPROTO_TCP
  92. case N.NetworkUDP:
  93. ipProtocol = syscall.IPPROTO_UDP
  94. default:
  95. return nil, E.New("unknown network: ", network)
  96. }
  97. var err error
  98. uid, err = w.iif.FindConnectionOwner(ipProtocol, source.Addr().String(), int32(source.Port()), destination.Addr().String(), int32(destination.Port()))
  99. if err != nil {
  100. return nil, err
  101. }
  102. }
  103. packageName, _ := w.iif.PackageNameByUid(uid)
  104. return &process.Info{UserId: uid, PackageName: packageName}, nil
  105. }