service.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. case adapter.StartStateStart:
  86. err := i.listener.Start()
  87. if err != nil {
  88. return err
  89. }
  90. systemBus, err := dbus.SystemBus()
  91. if err != nil {
  92. return err
  93. }
  94. i.systemBus = systemBus
  95. err = systemBus.Export((*resolve1Manager)(i), "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager")
  96. if err != nil {
  97. return err
  98. }
  99. reply, err := systemBus.RequestName("org.freedesktop.resolve1", dbus.NameFlagDoNotQueue)
  100. if err != nil {
  101. return err
  102. }
  103. switch reply {
  104. case dbus.RequestNameReplyPrimaryOwner:
  105. case dbus.RequestNameReplyExists:
  106. return E.New("D-Bus object already exists, maybe real resolved is running")
  107. default:
  108. return E.New("unknown request name reply: ", reply)
  109. }
  110. i.networkUpdateCallback = i.network.NetworkMonitor().RegisterCallback(i.onNetworkUpdate)
  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. response, err := i.dnsRouter.Exchange(adapter.WithContext(ctx, &metadata), &message, adapter.DNSQueryOptions{})
  157. if err != nil {
  158. return err
  159. }
  160. responseBuffer, err := dns.TruncateDNSMessage(&message, response, 0)
  161. if err != nil {
  162. return err
  163. }
  164. defer responseBuffer.Release()
  165. _, _, err = i.listener.UDPConn().WriteMsgUDPAddrPort(responseBuffer.Bytes(), oob, source.AddrPort())
  166. return err
  167. }
  168. func (i *Service) onNetworkUpdate() {
  169. i.linkAccess.Lock()
  170. defer i.linkAccess.Unlock()
  171. var deleteIfIndex []int
  172. for ifIndex, link := range i.links {
  173. iif, err := i.network.InterfaceFinder().ByIndex(int(ifIndex))
  174. if err != nil || iif != link.iif {
  175. deleteIfIndex = append(deleteIfIndex, int(ifIndex))
  176. }
  177. i.defaultRouteSequence = common.Filter(i.defaultRouteSequence, func(it int32) bool {
  178. return it != ifIndex
  179. })
  180. if i.deleteCallback != nil {
  181. i.deleteCallback(link)
  182. }
  183. }
  184. for _, ifIndex := range deleteIfIndex {
  185. delete(i.links, int32(ifIndex))
  186. }
  187. }
  188. func (conf *TransportLink) nameList(ndots int, name string) []string {
  189. search := common.Map(common.Filter(conf.domain, func(it LinkDomain) bool {
  190. return !it.RoutingOnly
  191. }), func(it LinkDomain) string {
  192. return it.Domain
  193. })
  194. l := len(name)
  195. rooted := l > 0 && name[l-1] == '.'
  196. if l > 254 || l == 254 && !rooted {
  197. return nil
  198. }
  199. if rooted {
  200. if avoidDNS(name) {
  201. return nil
  202. }
  203. return []string{name}
  204. }
  205. hasNdots := strings.Count(name, ".") >= ndots
  206. name += "."
  207. // l++
  208. names := make([]string, 0, 1+len(search))
  209. if hasNdots && !avoidDNS(name) {
  210. names = append(names, name)
  211. }
  212. for _, suffix := range search {
  213. fqdn := name + suffix
  214. if !avoidDNS(fqdn) && len(fqdn) <= 254 {
  215. names = append(names, fqdn)
  216. }
  217. }
  218. if !hasNdots && !avoidDNS(name) {
  219. names = append(names, name)
  220. }
  221. return names
  222. }
  223. func avoidDNS(name string) bool {
  224. if name == "" {
  225. return true
  226. }
  227. if name[len(name)-1] == '.' {
  228. name = name[:len(name)-1]
  229. }
  230. return strings.HasSuffix(name, ".onion")
  231. }