dns.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. M "github.com/sagernet/sing/common/metadata"
  11. "github.com/sagernet/sing/common/task"
  12. mDNS "github.com/miekg/dns"
  13. )
  14. type LocalDNSTransport interface {
  15. Raw() bool
  16. Lookup(ctx *ExchangeContext, network string, domain string) error
  17. Exchange(ctx *ExchangeContext, message []byte) error
  18. }
  19. func RegisterLocalDNSTransport(transport LocalDNSTransport) {
  20. if transport == nil {
  21. dns.RegisterTransport([]string{"local"}, func(options dns.TransportOptions) (dns.Transport, error) {
  22. return dns.NewLocalTransport(options), nil
  23. })
  24. } else {
  25. dns.RegisterTransport([]string{"local"}, func(options dns.TransportOptions) (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. var group task.Group
  60. group.Append0(func(ctx context.Context) error {
  61. err = p.iif.Exchange(response, messageBytes)
  62. if err != nil {
  63. return err
  64. }
  65. if response.error != nil {
  66. return response.error
  67. }
  68. responseMessage = &response.message
  69. return nil
  70. })
  71. err = group.Run(ctx)
  72. if err != nil {
  73. return nil, err
  74. }
  75. return responseMessage, nil
  76. }
  77. func (p *platformLocalDNSTransport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
  78. var network string
  79. switch strategy {
  80. case dns.DomainStrategyUseIPv4:
  81. network = "ip4"
  82. case dns.DomainStrategyPreferIPv6:
  83. network = "ip6"
  84. default:
  85. network = "ip"
  86. }
  87. response := &ExchangeContext{
  88. context: ctx,
  89. }
  90. var responseAddr []netip.Addr
  91. var group task.Group
  92. group.Append0(func(ctx context.Context) error {
  93. err := p.iif.Lookup(response, network, domain)
  94. if err != nil {
  95. return err
  96. }
  97. if response.error != nil {
  98. return response.error
  99. }
  100. switch strategy {
  101. case dns.DomainStrategyUseIPv4:
  102. responseAddr = common.Filter(response.addresses, func(it netip.Addr) bool {
  103. return it.Is4()
  104. })
  105. case dns.DomainStrategyPreferIPv6:
  106. responseAddr = common.Filter(response.addresses, func(it netip.Addr) bool {
  107. return it.Is6()
  108. })
  109. default:
  110. responseAddr = response.addresses
  111. }
  112. /*if len(responseAddr) == 0 {
  113. response.error = dns.RCodeSuccess
  114. }*/
  115. return nil
  116. })
  117. err := group.Run(ctx)
  118. if err != nil {
  119. return nil, err
  120. }
  121. return responseAddr, nil
  122. }
  123. type Func interface {
  124. Invoke() error
  125. }
  126. type ExchangeContext struct {
  127. context context.Context
  128. message mDNS.Msg
  129. addresses []netip.Addr
  130. error error
  131. }
  132. func (c *ExchangeContext) OnCancel(callback Func) {
  133. go func() {
  134. <-c.context.Done()
  135. callback.Invoke()
  136. }()
  137. }
  138. func (c *ExchangeContext) Success(result string) {
  139. c.addresses = common.Map(common.Filter(strings.Split(result, "\n"), func(it string) bool {
  140. return !common.IsEmpty(it)
  141. }), func(it string) netip.Addr {
  142. return M.ParseSocksaddrHostPort(it, 0).Unwrap().Addr
  143. })
  144. }
  145. func (c *ExchangeContext) RawSuccess(result []byte) {
  146. err := c.message.Unpack(result)
  147. if err != nil {
  148. c.error = E.Cause(err, "parse response")
  149. }
  150. }
  151. func (c *ExchangeContext) ErrorCode(code int32) {
  152. c.error = dns.RCodeError(code)
  153. }
  154. func (c *ExchangeContext) ErrnoCode(code int32) {
  155. c.error = syscall.Errno(code)
  156. }