dns.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. package libbox
  2. import (
  3. "context"
  4. "net/netip"
  5. "strings"
  6. "syscall"
  7. "github.com/sagernet/sing-dns"
  8. "github.com/sagernet/sing/common"
  9. E "github.com/sagernet/sing/common/exceptions"
  10. "github.com/sagernet/sing/common/logger"
  11. M "github.com/sagernet/sing/common/metadata"
  12. N "github.com/sagernet/sing/common/network"
  13. "github.com/sagernet/sing/common/task"
  14. mDNS "github.com/miekg/dns"
  15. )
  16. type LocalDNSTransport interface {
  17. Raw() bool
  18. Lookup(ctx *ExchangeContext, network string, domain string) error
  19. Exchange(ctx *ExchangeContext, message []byte) error
  20. }
  21. func RegisterLocalDNSTransport(transport LocalDNSTransport) {
  22. if transport == nil {
  23. dns.RegisterTransport([]string{"local"}, dns.CreateLocalTransport)
  24. } else {
  25. dns.RegisterTransport([]string{"local"}, func(name string, ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
  26. return &platformLocalDNSTransport{
  27. iif: transport,
  28. }, nil
  29. })
  30. }
  31. }
  32. var _ dns.Transport = (*platformLocalDNSTransport)(nil)
  33. type platformLocalDNSTransport struct {
  34. iif LocalDNSTransport
  35. }
  36. func (p *platformLocalDNSTransport) Name() string {
  37. return "local"
  38. }
  39. func (p *platformLocalDNSTransport) Start() error {
  40. return nil
  41. }
  42. func (p *platformLocalDNSTransport) Reset() {
  43. }
  44. func (p *platformLocalDNSTransport) Close() error {
  45. return nil
  46. }
  47. func (p *platformLocalDNSTransport) Raw() bool {
  48. return p.iif.Raw()
  49. }
  50. func (p *platformLocalDNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
  51. messageBytes, err := message.Pack()
  52. if err != nil {
  53. return nil, err
  54. }
  55. response := &ExchangeContext{
  56. context: ctx,
  57. }
  58. var responseMessage *mDNS.Msg
  59. return responseMessage, task.Run(ctx, func() error {
  60. err = p.iif.Exchange(response, messageBytes)
  61. if err != nil {
  62. return err
  63. }
  64. if response.error != nil {
  65. return response.error
  66. }
  67. responseMessage = &response.message
  68. return nil
  69. })
  70. }
  71. func (p *platformLocalDNSTransport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
  72. var network string
  73. switch strategy {
  74. case dns.DomainStrategyUseIPv4:
  75. network = "ip4"
  76. case dns.DomainStrategyPreferIPv6:
  77. network = "ip6"
  78. default:
  79. network = "ip"
  80. }
  81. response := &ExchangeContext{
  82. context: ctx,
  83. }
  84. var responseAddr []netip.Addr
  85. return responseAddr, task.Run(ctx, func() error {
  86. err := p.iif.Lookup(response, network, domain)
  87. if err != nil {
  88. return err
  89. }
  90. if response.error != nil {
  91. return response.error
  92. }
  93. switch strategy {
  94. case dns.DomainStrategyUseIPv4:
  95. responseAddr = common.Filter(response.addresses, func(it netip.Addr) bool {
  96. return it.Is4()
  97. })
  98. case dns.DomainStrategyPreferIPv6:
  99. responseAddr = common.Filter(response.addresses, func(it netip.Addr) bool {
  100. return it.Is6()
  101. })
  102. default:
  103. responseAddr = response.addresses
  104. }
  105. /*if len(responseAddr) == 0 {
  106. response.error = dns.RCodeSuccess
  107. }*/
  108. return nil
  109. })
  110. }
  111. type Func interface {
  112. Invoke() error
  113. }
  114. type ExchangeContext struct {
  115. context context.Context
  116. message mDNS.Msg
  117. addresses []netip.Addr
  118. error error
  119. }
  120. func (c *ExchangeContext) OnCancel(callback Func) {
  121. go func() {
  122. <-c.context.Done()
  123. callback.Invoke()
  124. }()
  125. }
  126. func (c *ExchangeContext) Success(result string) {
  127. c.addresses = common.Map(common.Filter(strings.Split(result, "\n"), func(it string) bool {
  128. return !common.IsEmpty(it)
  129. }), func(it string) netip.Addr {
  130. return M.ParseSocksaddrHostPort(it, 0).Unwrap().Addr
  131. })
  132. }
  133. func (c *ExchangeContext) RawSuccess(result []byte) {
  134. err := c.message.Unpack(result)
  135. if err != nil {
  136. c.error = E.Cause(err, "parse response")
  137. }
  138. }
  139. func (c *ExchangeContext) ErrorCode(code int32) {
  140. c.error = dns.RCodeError(code)
  141. }
  142. func (c *ExchangeContext) ErrnoCode(code int32) {
  143. c.error = syscall.Errno(code)
  144. }