dns.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package route
  2. import (
  3. "context"
  4. "net"
  5. "time"
  6. "github.com/sagernet/sing-box/adapter"
  7. C "github.com/sagernet/sing-box/constant"
  8. "github.com/sagernet/sing-box/dns"
  9. dnsOutbound "github.com/sagernet/sing-box/protocol/dns"
  10. R "github.com/sagernet/sing-box/route/rule"
  11. "github.com/sagernet/sing/common/buf"
  12. E "github.com/sagernet/sing/common/exceptions"
  13. "github.com/sagernet/sing/common/logger"
  14. M "github.com/sagernet/sing/common/metadata"
  15. N "github.com/sagernet/sing/common/network"
  16. "github.com/sagernet/sing/common/udpnat2"
  17. mDNS "github.com/miekg/dns"
  18. )
  19. func (r *Router) hijackDNSStream(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
  20. metadata.Destination = M.Socksaddr{}
  21. for {
  22. conn.SetReadDeadline(time.Now().Add(C.DNSTimeout))
  23. err := dnsOutbound.HandleStreamDNSRequest(ctx, r.dns, conn, metadata)
  24. if err != nil {
  25. if !E.IsClosedOrCanceled(err) {
  26. return err
  27. } else {
  28. return nil
  29. }
  30. }
  31. }
  32. }
  33. func (r *Router) hijackDNSPacket(ctx context.Context, conn N.PacketConn, packetBuffers []*N.PacketBuffer, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) error {
  34. if natConn, isNatConn := conn.(udpnat.Conn); isNatConn {
  35. metadata.Destination = M.Socksaddr{}
  36. for _, packet := range packetBuffers {
  37. buffer := packet.Buffer
  38. destination := packet.Destination
  39. N.PutPacketBuffer(packet)
  40. go ExchangeDNSPacket(ctx, r.dns, r.logger, natConn, buffer, metadata, destination)
  41. }
  42. natConn.SetHandler(&dnsHijacker{
  43. router: r.dns,
  44. logger: r.logger,
  45. conn: conn,
  46. ctx: ctx,
  47. metadata: metadata,
  48. onClose: onClose,
  49. })
  50. return nil
  51. }
  52. err := dnsOutbound.NewDNSPacketConnection(ctx, r.dns, conn, packetBuffers, metadata)
  53. N.CloseOnHandshakeFailure(conn, onClose, err)
  54. if err != nil && !E.IsClosedOrCanceled(err) {
  55. return E.Cause(err, "process DNS packet")
  56. }
  57. return nil
  58. }
  59. func ExchangeDNSPacket(ctx context.Context, router adapter.DNSRouter, logger logger.ContextLogger, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext, destination M.Socksaddr) {
  60. err := exchangeDNSPacket(ctx, router, conn, buffer, metadata, destination)
  61. if err != nil && !R.IsRejected(err) && !E.IsClosedOrCanceled(err) {
  62. logger.ErrorContext(ctx, E.Cause(err, "process DNS packet"))
  63. }
  64. }
  65. func exchangeDNSPacket(ctx context.Context, router adapter.DNSRouter, conn N.PacketConn, buffer *buf.Buffer, metadata adapter.InboundContext, destination M.Socksaddr) error {
  66. var message mDNS.Msg
  67. err := message.Unpack(buffer.Bytes())
  68. buffer.Release()
  69. if err != nil {
  70. return E.Cause(err, "unpack request")
  71. }
  72. response, err := router.Exchange(adapter.WithContext(ctx, &metadata), &message, adapter.DNSQueryOptions{})
  73. if err != nil {
  74. return err
  75. }
  76. responseBuffer, err := dns.TruncateDNSMessage(&message, response, 1024)
  77. if err != nil {
  78. return err
  79. }
  80. err = conn.WritePacket(responseBuffer, destination)
  81. return err
  82. }
  83. type dnsHijacker struct {
  84. router adapter.DNSRouter
  85. logger logger.ContextLogger
  86. conn N.PacketConn
  87. ctx context.Context
  88. metadata adapter.InboundContext
  89. onClose N.CloseHandlerFunc
  90. }
  91. func (h *dnsHijacker) NewPacketEx(buffer *buf.Buffer, destination M.Socksaddr) {
  92. go ExchangeDNSPacket(h.ctx, h.router, h.logger, h.conn, buffer, h.metadata, destination)
  93. }
  94. func (h *dnsHijacker) Close() error {
  95. if h.onClose != nil {
  96. h.onClose(nil)
  97. }
  98. return nil
  99. }