listener.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package listener
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "runtime"
  7. "strings"
  8. "sync/atomic"
  9. "github.com/sagernet/sing-box/adapter"
  10. "github.com/sagernet/sing-box/common/settings"
  11. "github.com/sagernet/sing-box/option"
  12. "github.com/sagernet/sing/common"
  13. E "github.com/sagernet/sing/common/exceptions"
  14. "github.com/sagernet/sing/common/logger"
  15. M "github.com/sagernet/sing/common/metadata"
  16. N "github.com/sagernet/sing/common/network"
  17. "github.com/vishvananda/netns"
  18. )
  19. type Listener struct {
  20. ctx context.Context
  21. logger logger.ContextLogger
  22. network []string
  23. listenOptions option.ListenOptions
  24. connHandler adapter.ConnectionHandlerEx
  25. packetHandler adapter.PacketHandlerEx
  26. oobPacketHandler adapter.OOBPacketHandlerEx
  27. threadUnsafePacketWriter bool
  28. disablePacketOutput bool
  29. setSystemProxy bool
  30. systemProxySOCKS bool
  31. tproxy bool
  32. tcpListener net.Listener
  33. systemProxy settings.SystemProxy
  34. udpConn *net.UDPConn
  35. udpAddr M.Socksaddr
  36. packetOutbound chan *N.PacketBuffer
  37. packetOutboundClosed chan struct{}
  38. shutdown atomic.Bool
  39. }
  40. type Options struct {
  41. Context context.Context
  42. Logger logger.ContextLogger
  43. Network []string
  44. Listen option.ListenOptions
  45. ConnectionHandler adapter.ConnectionHandlerEx
  46. PacketHandler adapter.PacketHandlerEx
  47. OOBPacketHandler adapter.OOBPacketHandlerEx
  48. ThreadUnsafePacketWriter bool
  49. DisablePacketOutput bool
  50. SetSystemProxy bool
  51. SystemProxySOCKS bool
  52. TProxy bool
  53. }
  54. func New(
  55. options Options,
  56. ) *Listener {
  57. return &Listener{
  58. ctx: options.Context,
  59. logger: options.Logger,
  60. network: options.Network,
  61. listenOptions: options.Listen,
  62. connHandler: options.ConnectionHandler,
  63. packetHandler: options.PacketHandler,
  64. oobPacketHandler: options.OOBPacketHandler,
  65. threadUnsafePacketWriter: options.ThreadUnsafePacketWriter,
  66. disablePacketOutput: options.DisablePacketOutput,
  67. setSystemProxy: options.SetSystemProxy,
  68. systemProxySOCKS: options.SystemProxySOCKS,
  69. tproxy: options.TProxy,
  70. }
  71. }
  72. func (l *Listener) Start() error {
  73. if common.Contains(l.network, N.NetworkTCP) {
  74. _, err := l.ListenTCP()
  75. if err != nil {
  76. return err
  77. }
  78. go l.loopTCPIn()
  79. }
  80. if common.Contains(l.network, N.NetworkUDP) {
  81. _, err := l.ListenUDP()
  82. if err != nil {
  83. return err
  84. }
  85. l.packetOutboundClosed = make(chan struct{})
  86. l.packetOutbound = make(chan *N.PacketBuffer, 64)
  87. go l.loopUDPIn()
  88. if !l.disablePacketOutput {
  89. go l.loopUDPOut()
  90. }
  91. }
  92. if l.setSystemProxy {
  93. listenPort := M.SocksaddrFromNet(l.tcpListener.Addr()).Port
  94. var listenAddrString string
  95. listenAddr := l.listenOptions.Listen.Build(netip.IPv4Unspecified())
  96. if listenAddr.IsUnspecified() {
  97. listenAddrString = "127.0.0.1"
  98. } else {
  99. listenAddrString = listenAddr.String()
  100. }
  101. systemProxy, err := settings.NewSystemProxy(l.ctx, M.ParseSocksaddrHostPort(listenAddrString, listenPort), l.systemProxySOCKS)
  102. if err != nil {
  103. return E.Cause(err, "initialize system proxy")
  104. }
  105. err = systemProxy.Enable()
  106. if err != nil {
  107. return E.Cause(err, "set system proxy")
  108. }
  109. l.systemProxy = systemProxy
  110. }
  111. return nil
  112. }
  113. func (l *Listener) Close() error {
  114. l.shutdown.Store(true)
  115. var err error
  116. if l.systemProxy != nil && l.systemProxy.IsEnabled() {
  117. err = l.systemProxy.Disable()
  118. }
  119. return E.Errors(err, common.Close(
  120. l.tcpListener,
  121. common.PtrOrNil(l.udpConn),
  122. ))
  123. }
  124. func (l *Listener) TCPListener() net.Listener {
  125. return l.tcpListener
  126. }
  127. func (l *Listener) UDPConn() *net.UDPConn {
  128. return l.udpConn
  129. }
  130. func (l *Listener) ListenOptions() option.ListenOptions {
  131. return l.listenOptions
  132. }
  133. func ListenNetworkNamespace[T any](nameOrPath string, block func() (T, error)) (T, error) {
  134. if nameOrPath != "" {
  135. runtime.LockOSThread()
  136. defer runtime.UnlockOSThread()
  137. currentNs, err := netns.Get()
  138. if err != nil {
  139. return common.DefaultValue[T](), E.Cause(err, "get current netns")
  140. }
  141. defer netns.Set(currentNs)
  142. var targetNs netns.NsHandle
  143. if strings.HasPrefix(nameOrPath, "/") {
  144. targetNs, err = netns.GetFromPath(nameOrPath)
  145. } else {
  146. targetNs, err = netns.GetFromName(nameOrPath)
  147. }
  148. if err != nil {
  149. return common.DefaultValue[T](), E.Cause(err, "get netns ", nameOrPath)
  150. }
  151. defer targetNs.Close()
  152. err = netns.Set(targetNs)
  153. if err != nil {
  154. return common.DefaultValue[T](), E.Cause(err, "set netns to ", nameOrPath)
  155. }
  156. }
  157. return block()
  158. }