quic.go 4.5 KB

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