dns.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package dns
  2. import (
  3. "context"
  4. "encoding/binary"
  5. "errors"
  6. "github.com/xtls/xray-core/common"
  7. "github.com/xtls/xray-core/common/dice"
  8. )
  9. type DNS struct {
  10. header []byte
  11. }
  12. func (d DNS) Size() int32 {
  13. return int32(len(d.header))
  14. }
  15. // Serialize implements PacketHeader.
  16. func (d DNS) Serialize(b []byte) {
  17. copy(b, d.header)
  18. binary.BigEndian.PutUint16(b[0:], dice.RollUint16()) // random transaction ID
  19. }
  20. // NewDNS returns a new DNS instance based on given config.
  21. func NewDNS(ctx context.Context, config interface{}) (interface{}, error) {
  22. var header []byte
  23. header = binary.BigEndian.AppendUint16(header, 0x0000) // Transaction ID
  24. header = binary.BigEndian.AppendUint16(header, 0x0100) // Flags: Standard query
  25. header = binary.BigEndian.AppendUint16(header, 0x0001) // Questions
  26. header = binary.BigEndian.AppendUint16(header, 0x0000) // Answer RRs
  27. header = binary.BigEndian.AppendUint16(header, 0x0000) // Authority RRs
  28. header = binary.BigEndian.AppendUint16(header, 0x0000) // Additional RRs
  29. buf := make([]byte, 0x100)
  30. off1, err := packDomainName(config.(*Config).Domain+".", buf)
  31. if err != nil {
  32. return nil, err
  33. }
  34. header = append(header, buf[:off1]...)
  35. header = binary.BigEndian.AppendUint16(header, 0x0001) // Type: A
  36. header = binary.BigEndian.AppendUint16(header, 0x0001) // Class: IN
  37. return DNS{
  38. header: header,
  39. }, nil
  40. }
  41. // copied from github.com/miekg/dns
  42. func packDomainName(s string, msg []byte) (off1 int, err error) {
  43. off := 0
  44. ls := len(s)
  45. // Each dot ends a segment of the name.
  46. // We trade each dot byte for a length byte.
  47. // Except for escaped dots (\.), which are normal dots.
  48. // There is also a trailing zero.
  49. // Emit sequence of counted strings, chopping at dots.
  50. var (
  51. begin int
  52. bs []byte
  53. )
  54. for i := 0; i < ls; i++ {
  55. var c byte
  56. if bs == nil {
  57. c = s[i]
  58. } else {
  59. c = bs[i]
  60. }
  61. switch c {
  62. case '\\':
  63. if off+1 > len(msg) {
  64. return len(msg), errors.New("buffer size too small")
  65. }
  66. if bs == nil {
  67. bs = []byte(s)
  68. }
  69. copy(bs[i:ls-1], bs[i+1:])
  70. ls--
  71. case '.':
  72. labelLen := i - begin
  73. if labelLen >= 1<<6 { // top two bits of length must be clear
  74. return len(msg), errors.New("bad rdata")
  75. }
  76. // off can already (we're in a loop) be bigger than len(msg)
  77. // this happens when a name isn't fully qualified
  78. if off+1+labelLen > len(msg) {
  79. return len(msg), errors.New("buffer size too small")
  80. }
  81. // The following is covered by the length check above.
  82. msg[off] = byte(labelLen)
  83. if bs == nil {
  84. copy(msg[off+1:], s[begin:i])
  85. } else {
  86. copy(msg[off+1:], bs[begin:i])
  87. }
  88. off += 1 + labelLen
  89. begin = i + 1
  90. default:
  91. }
  92. }
  93. if off < len(msg) {
  94. msg[off] = 0
  95. }
  96. return off + 1, nil
  97. }
  98. func init() {
  99. common.Must(common.RegisterConfig((*Config)(nil), NewDNS))
  100. }