dns.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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) Close() error {
  43. return nil
  44. }
  45. func (p *platformLocalDNSTransport) Raw() bool {
  46. return p.iif.Raw()
  47. }
  48. func (p *platformLocalDNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
  49. messageBytes, err := message.Pack()
  50. if err != nil {
  51. return nil, err
  52. }
  53. response := &ExchangeContext{
  54. context: ctx,
  55. }
  56. var responseMessage *mDNS.Msg
  57. return responseMessage, task.Run(ctx, func() error {
  58. err = p.iif.Exchange(response, messageBytes)
  59. if err != nil {
  60. return err
  61. }
  62. if response.error != nil {
  63. return response.error
  64. }
  65. responseMessage = &response.message
  66. return nil
  67. })
  68. }
  69. func (p *platformLocalDNSTransport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
  70. var network string
  71. switch strategy {
  72. case dns.DomainStrategyUseIPv4:
  73. network = "ip4"
  74. case dns.DomainStrategyPreferIPv6:
  75. network = "ip6"
  76. default:
  77. network = "ip"
  78. }
  79. response := &ExchangeContext{
  80. context: ctx,
  81. }
  82. var responseAddr []netip.Addr
  83. return responseAddr, task.Run(ctx, func() error {
  84. err := p.iif.Lookup(response, network, domain)
  85. if err != nil {
  86. return err
  87. }
  88. if response.error != nil {
  89. return response.error
  90. }
  91. switch strategy {
  92. case dns.DomainStrategyUseIPv4:
  93. responseAddr = common.Filter(response.addresses, func(it netip.Addr) bool {
  94. return it.Is4()
  95. })
  96. case dns.DomainStrategyPreferIPv6:
  97. responseAddr = common.Filter(response.addresses, func(it netip.Addr) bool {
  98. return it.Is6()
  99. })
  100. default:
  101. responseAddr = response.addresses
  102. }
  103. /*if len(responseAddr) == 0 {
  104. response.error = dns.RCodeSuccess
  105. }*/
  106. return nil
  107. })
  108. }
  109. type ExchangeContext struct {
  110. context context.Context
  111. message mDNS.Msg
  112. addresses []netip.Addr
  113. error error
  114. }
  115. func (c *ExchangeContext) OnCancel(callback Func) {
  116. go func() {
  117. <-c.context.Done()
  118. callback.Invoke()
  119. }()
  120. }
  121. func (c *ExchangeContext) Success(result string) {
  122. c.addresses = common.Map(common.Filter(strings.Split(result, "\n"), func(it string) bool {
  123. return !common.IsEmpty(it)
  124. }), func(it string) netip.Addr {
  125. return M.ParseSocksaddrHostPort(it, 0).Unwrap().Addr
  126. })
  127. }
  128. func (c *ExchangeContext) RawSuccess(result []byte) {
  129. err := c.message.Unpack(result)
  130. if err != nil {
  131. c.error = E.Cause(err, "parse response")
  132. }
  133. }
  134. func (c *ExchangeContext) ErrorCode(code int32) {
  135. c.error = dns.RCodeError(code)
  136. }
  137. func (c *ExchangeContext) Errno(errno int32) {
  138. c.error = syscall.Errno(errno)
  139. }