quic.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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.DNSServerAddressOptions.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) Start(stage adapter.StartStage) error {
  64. return nil
  65. }
  66. func (t *Transport) Close() error {
  67. t.access.Lock()
  68. defer t.access.Unlock()
  69. connection := t.connection
  70. if connection != nil {
  71. connection.CloseWithError(0, "")
  72. }
  73. return nil
  74. }
  75. func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
  76. var (
  77. conn quic.Connection
  78. err error
  79. response *mDNS.Msg
  80. )
  81. for i := 0; i < 2; i++ {
  82. conn, err = t.openConnection()
  83. if err != nil {
  84. return nil, err
  85. }
  86. response, err = t.exchange(ctx, message, conn)
  87. if err == nil {
  88. return response, nil
  89. } else if !isQUICRetryError(err) {
  90. return nil, err
  91. } else {
  92. conn.CloseWithError(quic.ApplicationErrorCode(0), "")
  93. continue
  94. }
  95. }
  96. return nil, err
  97. }
  98. func (t *Transport) openConnection() (quic.EarlyConnection, error) {
  99. connection := t.connection
  100. if connection != nil && !common.Done(connection.Context()) {
  101. return connection, nil
  102. }
  103. t.access.Lock()
  104. defer t.access.Unlock()
  105. connection = t.connection
  106. if connection != nil && !common.Done(connection.Context()) {
  107. return connection, nil
  108. }
  109. conn, err := t.dialer.DialContext(t.ctx, N.NetworkUDP, t.serverAddr)
  110. if err != nil {
  111. return nil, err
  112. }
  113. earlyConnection, err := sQUIC.DialEarly(
  114. t.ctx,
  115. bufio.NewUnbindPacketConn(conn),
  116. t.serverAddr.UDPAddr(),
  117. t.tlsConfig,
  118. nil,
  119. )
  120. if err != nil {
  121. return nil, err
  122. }
  123. t.connection = earlyConnection
  124. return earlyConnection, nil
  125. }
  126. func (t *Transport) exchange(ctx context.Context, message *mDNS.Msg, conn quic.Connection) (*mDNS.Msg, error) {
  127. stream, err := conn.OpenStreamSync(ctx)
  128. if err != nil {
  129. return nil, err
  130. }
  131. err = transport.WriteMessage(stream, 0, message)
  132. if err != nil {
  133. stream.Close()
  134. return nil, err
  135. }
  136. stream.Close()
  137. return transport.ReadMessage(stream)
  138. }
  139. // https://github.com/AdguardTeam/dnsproxy/blob/fd1868577652c639cce3da00e12ca548f421baf1/upstream/upstream_quic.go#L394
  140. func isQUICRetryError(err error) (ok bool) {
  141. var qAppErr *quic.ApplicationError
  142. if errors.As(err, &qAppErr) && qAppErr.ErrorCode == 0 {
  143. return true
  144. }
  145. var qIdleErr *quic.IdleTimeoutError
  146. if errors.As(err, &qIdleErr) {
  147. return true
  148. }
  149. var resetErr *quic.StatelessResetError
  150. if errors.As(err, &resetErr) {
  151. return true
  152. }
  153. var qTransportError *quic.TransportError
  154. if errors.As(err, &qTransportError) && qTransportError.ErrorCode == quic.NoError {
  155. return true
  156. }
  157. if errors.Is(err, quic.Err0RTTRejected) {
  158. return true
  159. }
  160. return false
  161. }