dns.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package inbound
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "io"
  6. "net"
  7. "github.com/sagernet/sing-box/adapter"
  8. "github.com/sagernet/sing-box/log"
  9. "github.com/sagernet/sing/common"
  10. "github.com/sagernet/sing/common/buf"
  11. N "github.com/sagernet/sing/common/network"
  12. "golang.org/x/net/dns/dnsmessage"
  13. )
  14. func NewDNSConnection(ctx context.Context, router adapter.Router, logger log.Logger, conn net.Conn, metadata adapter.InboundContext) error {
  15. _buffer := buf.StackNewSize(1024)
  16. defer common.KeepAlive(_buffer)
  17. buffer := common.Dup(_buffer)
  18. defer buffer.Release()
  19. for {
  20. var queryLength uint16
  21. err := binary.Read(conn, binary.BigEndian, &queryLength)
  22. if err != nil {
  23. return err
  24. }
  25. if queryLength > 1024 {
  26. return io.ErrShortBuffer
  27. }
  28. buffer.FullReset()
  29. _, err = buffer.ReadFullFrom(conn, int(queryLength))
  30. if err != nil {
  31. return err
  32. }
  33. var message dnsmessage.Message
  34. err = message.Unpack(buffer.Bytes())
  35. if err != nil {
  36. return err
  37. }
  38. if len(message.Questions) > 0 {
  39. question := message.Questions[0]
  40. metadata.Domain = string(question.Name.Data[:question.Name.Length-1])
  41. logger.WithContext(ctx).Debug("inbound dns query ", formatDNSQuestion(question), " from ", metadata.Source)
  42. }
  43. response, err := router.Exchange(adapter.WithContext(ctx, &metadata), &message)
  44. if err != nil {
  45. return err
  46. }
  47. buffer.FullReset()
  48. responseBuffer, err := response.AppendPack(buffer.Index(0))
  49. if err != nil {
  50. return err
  51. }
  52. err = binary.Write(conn, binary.BigEndian, uint16(len(responseBuffer)))
  53. if err != nil {
  54. return err
  55. }
  56. _, err = conn.Write(responseBuffer)
  57. if err != nil {
  58. return err
  59. }
  60. }
  61. }
  62. func NewDNSPacketConnection(ctx context.Context, router adapter.Router, logger log.Logger, conn N.PacketConn, metadata adapter.InboundContext) error {
  63. for {
  64. buffer := buf.StackNewSize(1024)
  65. destination, err := conn.ReadPacket(buffer)
  66. if err != nil {
  67. buffer.Release()
  68. return err
  69. }
  70. var message dnsmessage.Message
  71. err = message.Unpack(buffer.Bytes())
  72. if err != nil {
  73. return err
  74. }
  75. if len(message.Questions) > 0 {
  76. question := message.Questions[0]
  77. metadata.Domain = string(question.Name.Data[:question.Name.Length-1])
  78. logger.WithContext(ctx).Debug("inbound dns query ", formatDNSQuestion(question), " from ", metadata.Source)
  79. }
  80. go func() error {
  81. defer buffer.Release()
  82. response, err := router.Exchange(adapter.WithContext(ctx, &metadata), &message)
  83. if err != nil {
  84. return err
  85. }
  86. buffer.FullReset()
  87. responseBuffer, err := response.AppendPack(buffer.Index(0))
  88. if err != nil {
  89. return err
  90. }
  91. buffer.Truncate(len(responseBuffer))
  92. err = conn.WritePacket(buffer, destination)
  93. return err
  94. }()
  95. }
  96. }
  97. func formatDNSQuestion(question dnsmessage.Question) string {
  98. return string(question.Name.Data[:question.Name.Length-1]) + " " + question.Type.String()[4:] + " " + question.Class.String()[5:]
  99. }