quic.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. package quic
  2. import (
  3. "context"
  4. "errors"
  5. "sync"
  6. "github.com/sagernet/quic-go"
  7. "github.com/sagernet/sing-box/adapter"
  8. "github.com/sagernet/sing-box/common/tls"
  9. C "github.com/sagernet/sing-box/constant"
  10. "github.com/sagernet/sing-box/dns"
  11. "github.com/sagernet/sing-box/dns/transport"
  12. "github.com/sagernet/sing-box/log"
  13. "github.com/sagernet/sing-box/option"
  14. sQUIC "github.com/sagernet/sing-quic"
  15. "github.com/sagernet/sing/common"
  16. "github.com/sagernet/sing/common/bufio"
  17. "github.com/sagernet/sing/common/logger"
  18. M "github.com/sagernet/sing/common/metadata"
  19. N "github.com/sagernet/sing/common/network"
  20. mDNS "github.com/miekg/dns"
  21. )
  22. var _ adapter.DNSTransport = (*Transport)(nil)
  23. func RegisterTransport(registry *dns.TransportRegistry) {
  24. dns.RegisterTransport[option.RemoteTLSDNSServerOptions](registry, C.DNSTypeQUIC, NewQUIC)
  25. }
  26. type Transport struct {
  27. dns.TransportAdapter
  28. ctx context.Context
  29. logger logger.ContextLogger
  30. dialer N.Dialer
  31. serverAddr M.Socksaddr
  32. tlsConfig tls.Config
  33. access sync.Mutex
  34. connection quic.EarlyConnection
  35. }
  36. func NewQUIC(ctx context.Context, logger log.ContextLogger, tag string, options option.RemoteTLSDNSServerOptions) (adapter.DNSTransport, error) {
  37. transportDialer, err := dns.NewRemoteDialer(ctx, options.RemoteDNSServerOptions)
  38. if err != nil {
  39. return nil, err
  40. }
  41. tlsOptions := common.PtrValueOrDefault(options.TLS)
  42. tlsOptions.Enabled = true
  43. tlsConfig, err := tls.NewClient(ctx, options.Server, tlsOptions)
  44. if err != nil {
  45. return nil, err
  46. }
  47. if len(tlsConfig.NextProtos()) == 0 {
  48. tlsConfig.SetNextProtos([]string{"doq"})
  49. }
  50. serverAddr := options.ServerOptions.Build()
  51. if serverAddr.Port == 0 {
  52. serverAddr.Port = 853
  53. }
  54. return &Transport{
  55. TransportAdapter: dns.NewTransportAdapterWithRemoteOptions(C.DNSTypeQUIC, tag, options.RemoteDNSServerOptions),
  56. ctx: ctx,
  57. logger: logger,
  58. dialer: transportDialer,
  59. serverAddr: serverAddr,
  60. tlsConfig: tlsConfig,
  61. }, nil
  62. }
  63. func (t *Transport) Reset() {
  64. t.access.Lock()
  65. defer t.access.Unlock()
  66. connection := t.connection
  67. if connection != nil {
  68. connection.CloseWithError(0, "")
  69. }
  70. }
  71. func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
  72. var (
  73. conn quic.Connection
  74. err error
  75. response *mDNS.Msg
  76. )
  77. for i := 0; i < 2; i++ {
  78. conn, err = t.openConnection()
  79. if err != nil {
  80. return nil, err
  81. }
  82. response, err = t.exchange(ctx, message, conn)
  83. if err == nil {
  84. return response, nil
  85. } else if !isQUICRetryError(err) {
  86. return nil, err
  87. } else {
  88. conn.CloseWithError(quic.ApplicationErrorCode(0), "")
  89. continue
  90. }
  91. }
  92. return nil, err
  93. }
  94. func (t *Transport) openConnection() (quic.EarlyConnection, error) {
  95. connection := t.connection
  96. if connection != nil && !common.Done(connection.Context()) {
  97. return connection, nil
  98. }
  99. t.access.Lock()
  100. defer t.access.Unlock()
  101. connection = t.connection
  102. if connection != nil && !common.Done(connection.Context()) {
  103. return connection, nil
  104. }
  105. conn, err := t.dialer.DialContext(t.ctx, N.NetworkUDP, t.serverAddr)
  106. if err != nil {
  107. return nil, err
  108. }
  109. earlyConnection, err := sQUIC.DialEarly(
  110. t.ctx,
  111. bufio.NewUnbindPacketConn(conn),
  112. t.serverAddr.UDPAddr(),
  113. t.tlsConfig,
  114. nil,
  115. )
  116. if err != nil {
  117. return nil, err
  118. }
  119. t.connection = earlyConnection
  120. return earlyConnection, nil
  121. }
  122. func (t *Transport) exchange(ctx context.Context, message *mDNS.Msg, conn quic.Connection) (*mDNS.Msg, error) {
  123. stream, err := conn.OpenStreamSync(ctx)
  124. if err != nil {
  125. return nil, err
  126. }
  127. defer stream.Close()
  128. defer stream.CancelRead(0)
  129. err = transport.WriteMessage(stream, 0, message)
  130. if err != nil {
  131. return nil, err
  132. }
  133. return transport.ReadMessage(stream)
  134. }
  135. // https://github.com/AdguardTeam/dnsproxy/blob/fd1868577652c639cce3da00e12ca548f421baf1/upstream/upstream_quic.go#L394
  136. func isQUICRetryError(err error) (ok bool) {
  137. var qAppErr *quic.ApplicationError
  138. if errors.As(err, &qAppErr) && qAppErr.ErrorCode == 0 {
  139. return true
  140. }
  141. var qIdleErr *quic.IdleTimeoutError
  142. if errors.As(err, &qIdleErr) {
  143. return true
  144. }
  145. var resetErr *quic.StatelessResetError
  146. if errors.As(err, &resetErr) {
  147. return true
  148. }
  149. var qTransportError *quic.TransportError
  150. if errors.As(err, &qTransportError) && qTransportError.ErrorCode == quic.NoError {
  151. return true
  152. }
  153. if errors.Is(err, quic.Err0RTTRejected) {
  154. return true
  155. }
  156. return false
  157. }