service.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //go:build linux
  2. package resolved
  3. import (
  4. "context"
  5. "net"
  6. "strings"
  7. "sync"
  8. "time"
  9. "github.com/sagernet/sing-box/adapter"
  10. boxService "github.com/sagernet/sing-box/adapter/service"
  11. "github.com/sagernet/sing-box/common/listener"
  12. C "github.com/sagernet/sing-box/constant"
  13. "github.com/sagernet/sing-box/dns"
  14. "github.com/sagernet/sing-box/log"
  15. "github.com/sagernet/sing-box/option"
  16. dnsOutbound "github.com/sagernet/sing-box/protocol/dns"
  17. tun "github.com/sagernet/sing-tun"
  18. "github.com/sagernet/sing/common"
  19. "github.com/sagernet/sing/common/buf"
  20. "github.com/sagernet/sing/common/control"
  21. E "github.com/sagernet/sing/common/exceptions"
  22. M "github.com/sagernet/sing/common/metadata"
  23. N "github.com/sagernet/sing/common/network"
  24. "github.com/sagernet/sing/common/x/list"
  25. "github.com/sagernet/sing/service"
  26. "github.com/godbus/dbus/v5"
  27. mDNS "github.com/miekg/dns"
  28. )
  29. func RegisterService(registry *boxService.Registry) {
  30. boxService.Register[option.ResolvedServiceOptions](registry, C.TypeResolved, NewService)
  31. }
  32. type Service struct {
  33. boxService.Adapter
  34. ctx context.Context
  35. logger log.ContextLogger
  36. network adapter.NetworkManager
  37. dnsRouter adapter.DNSRouter
  38. listener *listener.Listener
  39. systemBus *dbus.Conn
  40. linkAccess sync.RWMutex
  41. links map[int32]*TransportLink
  42. defaultRouteSequence []int32
  43. networkUpdateCallback *list.Element[tun.NetworkUpdateCallback]
  44. updateCallback func(*TransportLink) error
  45. deleteCallback func(*TransportLink)
  46. }
  47. type TransportLink struct {
  48. iif *control.Interface
  49. address []LinkDNS
  50. addressEx []LinkDNSEx
  51. domain []LinkDomain
  52. defaultRoute bool
  53. dnsOverTLS bool
  54. // dnsOverTLSFallback bool
  55. }
  56. func NewService(ctx context.Context, logger log.ContextLogger, tag string, options option.ResolvedServiceOptions) (adapter.Service, error) {
  57. inbound := &Service{
  58. Adapter: boxService.NewAdapter(C.TypeResolved, tag),
  59. ctx: ctx,
  60. logger: logger,
  61. network: service.FromContext[adapter.NetworkManager](ctx),
  62. dnsRouter: service.FromContext[adapter.DNSRouter](ctx),
  63. links: make(map[int32]*TransportLink),
  64. }
  65. inbound.listener = listener.New(listener.Options{
  66. Context: ctx,
  67. Logger: logger,
  68. Network: []string{N.NetworkTCP, N.NetworkUDP},
  69. Listen: options.ListenOptions,
  70. ConnectionHandler: inbound,
  71. OOBPacketHandler: inbound,
  72. ThreadUnsafePacketWriter: true,
  73. })
  74. return inbound, nil
  75. }
  76. func (i *Service) Start(stage adapter.StartStage) error {
  77. switch stage {
  78. case adapter.StartStateInitialize:
  79. inboundManager := service.FromContext[adapter.ServiceManager](i.ctx)
  80. for _, transport := range inboundManager.Services() {
  81. if transport.Type() == C.TypeResolved && transport != i {
  82. return E.New("multiple resolved service are not supported")
  83. }
  84. }
  85. systemBus, err := dbus.SystemBus()
  86. if err != nil {
  87. return err
  88. }
  89. i.systemBus = systemBus
  90. err = systemBus.Export((*resolve1Manager)(i), "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager")
  91. if err != nil {
  92. return err
  93. }
  94. reply, err := systemBus.RequestName("org.freedesktop.resolve1", dbus.NameFlagDoNotQueue)
  95. if err != nil {
  96. return err
  97. }
  98. switch reply {
  99. case dbus.RequestNameReplyPrimaryOwner:
  100. case dbus.RequestNameReplyExists:
  101. return E.New("D-Bus object already exists, maybe real resolved is running")
  102. default:
  103. return E.New("unknown request name reply: ", reply)
  104. }
  105. i.networkUpdateCallback = i.network.NetworkMonitor().RegisterCallback(i.onNetworkUpdate)
  106. case adapter.StartStateStart:
  107. err := i.listener.Start()
  108. if err != nil {
  109. return err
  110. }
  111. }
  112. return nil
  113. }
  114. func (i *Service) Close() error {
  115. if i.networkUpdateCallback != nil {
  116. i.network.NetworkMonitor().UnregisterCallback(i.networkUpdateCallback)
  117. }
  118. if i.systemBus != nil {
  119. i.systemBus.ReleaseName("org.freedesktop.resolve1")
  120. i.systemBus.Close()
  121. }
  122. return i.listener.Close()
  123. }
  124. func (i *Service) NewConnectionEx(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
  125. metadata.Inbound = i.Tag()
  126. metadata.InboundType = i.Type()
  127. metadata.Destination = M.Socksaddr{}
  128. for {
  129. conn.SetReadDeadline(time.Now().Add(C.DNSTimeout))
  130. err := dnsOutbound.HandleStreamDNSRequest(ctx, i.dnsRouter, conn, metadata)
  131. if err != nil {
  132. N.CloseOnHandshakeFailure(conn, onClose, err)
  133. return
  134. }
  135. }
  136. }
  137. func (i *Service) NewPacketEx(buffer *buf.Buffer, oob []byte, source M.Socksaddr) {
  138. go i.exchangePacket(buffer, oob, source)
  139. }
  140. func (i *Service) exchangePacket(buffer *buf.Buffer, oob []byte, source M.Socksaddr) {
  141. ctx := log.ContextWithNewID(i.ctx)
  142. err := i.exchangePacket0(ctx, buffer, oob, source)
  143. if err != nil {
  144. i.logger.ErrorContext(ctx, "process DNS packet: ", err)
  145. }
  146. }
  147. func (i *Service) exchangePacket0(ctx context.Context, buffer *buf.Buffer, oob []byte, source M.Socksaddr) error {
  148. var message mDNS.Msg
  149. err := message.Unpack(buffer.Bytes())
  150. buffer.Release()
  151. if err != nil {
  152. return E.Cause(err, "unpack request")
  153. }
  154. var metadata adapter.InboundContext
  155. metadata.Source = source
  156. metadata.InboundType = i.Type()
  157. metadata.Inbound = i.Tag()
  158. response, err := i.dnsRouter.Exchange(adapter.WithContext(ctx, &metadata), &message, adapter.DNSQueryOptions{})
  159. if err != nil {
  160. return err
  161. }
  162. responseBuffer, err := dns.TruncateDNSMessage(&message, response, 0)
  163. if err != nil {
  164. return err
  165. }
  166. defer responseBuffer.Release()
  167. _, _, err = i.listener.UDPConn().WriteMsgUDPAddrPort(responseBuffer.Bytes(), oob, source.AddrPort())
  168. return err
  169. }
  170. func (i *Service) onNetworkUpdate() {
  171. i.linkAccess.Lock()
  172. defer i.linkAccess.Unlock()
  173. var deleteIfIndex []int
  174. for ifIndex, link := range i.links {
  175. iif, err := i.network.InterfaceFinder().ByIndex(int(ifIndex))
  176. if err != nil || iif != link.iif {
  177. deleteIfIndex = append(deleteIfIndex, int(ifIndex))
  178. }
  179. i.defaultRouteSequence = common.Filter(i.defaultRouteSequence, func(it int32) bool {
  180. return it != ifIndex
  181. })
  182. if i.deleteCallback != nil {
  183. i.deleteCallback(link)
  184. }
  185. }
  186. for _, ifIndex := range deleteIfIndex {
  187. delete(i.links, int32(ifIndex))
  188. }
  189. }
  190. func (conf *TransportLink) nameList(ndots int, name string) []string {
  191. search := common.Map(common.Filter(conf.domain, func(it LinkDomain) bool {
  192. return !it.RoutingOnly
  193. }), func(it LinkDomain) string {
  194. return it.Domain
  195. })
  196. l := len(name)
  197. rooted := l > 0 && name[l-1] == '.'
  198. if l > 254 || l == 254 && !rooted {
  199. return nil
  200. }
  201. if rooted {
  202. if avoidDNS(name) {
  203. return nil
  204. }
  205. return []string{name}
  206. }
  207. hasNdots := strings.Count(name, ".") >= ndots
  208. name += "."
  209. // l++
  210. names := make([]string, 0, 1+len(search))
  211. if hasNdots && !avoidDNS(name) {
  212. names = append(names, name)
  213. }
  214. for _, suffix := range search {
  215. fqdn := name + suffix
  216. if !avoidDNS(fqdn) && len(fqdn) <= 254 {
  217. names = append(names, fqdn)
  218. }
  219. }
  220. if !hasNdots && !avoidDNS(name) {
  221. names = append(names, name)
  222. }
  223. return names
  224. }
  225. func avoidDNS(name string) bool {
  226. if name == "" {
  227. return true
  228. }
  229. if name[len(name)-1] == '.' {
  230. name = name[:len(name)-1]
  231. }
  232. return strings.HasSuffix(name, ".onion")
  233. }