Module: Rex::Proto::DNS::Packet

Defined in:
lib/rex/proto/dns/packet.rb

Defined Under Namespace

Modules: Raw

Class Method Summary collapse

Class Method Details

.encode_drb(packet) ⇒ Dnsruby::Message

Reads a packet into the Dnsruby::Message format

Parameters:

  • data (String, Net::DNS::Packet, Resolv::DNS::Message, Dnsruby::Message)

    Input data

Returns:

  • (Dnsruby::Message)


84
85
86
87
88
89
# File 'lib/rex/proto/dns/packet.rb', line 84

def self.encode_drb(packet)
  return packet if packet.is_a?(Dnsruby::Message)
  Dnsruby::Message.decode(
    self.encode_raw(packet)
  )
end

.encode_net(packet) ⇒ Net::DNS::Packet

Reads a packet into the Net::DNS::Packet format

Parameters:

  • data (String, Net::DNS::Packet, Resolv::DNS::Message, Dnsruby::Message)

    Input data

Returns:

  • (Net::DNS::Packet)


60
61
62
63
64
65
# File 'lib/rex/proto/dns/packet.rb', line 60

def self.encode_net(packet)
  return packet if packet.is_a?(Net::DNS::Packet)
  Net::DNS::Packet.parse(
    self.encode_raw(packet)
  )
end

.encode_raw(packet) ⇒ String

Reads a packet into the raw String format

Parameters:

  • data (String, Net::DNS::Packet, Resolv::DNS::Message, Dnsruby::Message)

    Input data

Returns:

  • (String)


96
97
98
99
# File 'lib/rex/proto/dns/packet.rb', line 96

def self.encode_raw(packet)
  return packet unless packet.respond_to?(:encode) or packet.respond_to?(:data)
  (packet.respond_to?(:data) ? packet.data : packet.encode).force_encoding('binary')
end

.encode_res(packet) ⇒ Resolv::DNS::Message

Reads a packet into the Resolv::DNS::Message format

Parameters:

  • data (String, Net::DNS::Packet, Resolv::DNS::Message, Dnsruby::Message)

    Input data

Returns:

  • (Resolv::DNS::Message)


72
73
74
75
76
77
# File 'lib/rex/proto/dns/packet.rb', line 72

def self.encode_res(packet)
  return packet if packet.is_a?(Resolv::DNS::Message)
  Resolv::DNS::Message.decode(
    self.encode_raw(packet)
  )
end

.generate_request(subject, type = Dnsruby::Types::A, cls = Dnsruby::Classes::IN, recurse = 1) ⇒ Dnsruby::Message

Generates a request packet, taken from Net::DNS::Resolver

Parameters:

  • subject (String)

    Subject name of question section

  • type (Fixnum) (defaults to: Dnsruby::Types::A)

    Type of DNS record to query

  • cls (Fixnum) (defaults to: Dnsruby::Classes::IN)

    Class of dns record to query

  • recurse (Fixnum) (defaults to: 1)

    Recursive query or not

Returns:

  • (Dnsruby::Message)

    request packet



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/rex/proto/dns/packet.rb', line 110

def self.generate_request(subject, type = Dnsruby::Types::A, cls = Dnsruby::Classes::IN, recurse = 1)
  case subject
  when IPAddr
    name = subject.reverse
    type = Dnsruby::Types::PTR
  when /\d/ # Contains a number, try to see if it's an IP or IPv6 address
    begin
      name = IPAddr.new(subject).reverse
      type = Dnsruby::Types::PTR
    rescue ArgumentError
      name = subject if self.valid_hostname?(subject)
    end
  else
    name = subject if self.valid_hostname?(subject)
  end

  # Create the packet
  packet = Dnsruby::Message.new(name, type, cls)

  if packet.header.opcode == Dnsruby::OpCode::Query
    packet.header.recursive = recurse
  end

  # DNSSEC and TSIG stuff to be inserted here

  return packet
end

.generate_response(request, answer = nil, authority = nil, additional = nil) ⇒ Dnsruby::Message

Generates a response packet for an existing request

Parameters:

  • request (String)

    Net::DNS::Packet, Resolv::DNS::Message] Original request

  • answer (Array) (defaults to: nil)

    Set of answers to provide in the response

  • authority (Array) (defaults to: nil)

    Set of authority records to provide in the response

  • additional (Array) (defaults to: nil)

    Set of additional records to provide in the response

Returns:

  • (Dnsruby::Message)

    Response packet



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/rex/proto/dns/packet.rb', line 147

def self.generate_response(request, answer = nil, authority = nil, additional = nil)
  packet = self.encode_drb(request)
  packet.answer = answer if answer
  packet.authority = authority if authority
  packet.additional = additional if additional
  packet = self.recalc_headers(packet)

  # Set error code for NXDomain or unset it if reprocessing a response
  if packet.header.ancount < 1
    packet.header.rcode = Dnsruby::RCode::NXDOMAIN
  else
    if packet.header.qr and packet.header.get_header_rcode.to_i == 3
      packet.header.rcode = Dnsruby::RCode::NOERROR
    end
  end
  # Set response bit last to allow reprocessing of responses
  packet.header.qr = true
  # Set recursion available bit if recursion desired
  packet.header.ra = true if packet.header.rd
  return packet
end

.recalc_headers(packet) ⇒ Dnsruby::Message

Sets header values to match packet content

Parameters:

  • packet (String)

    Net::DNS::Packet, Resolv::DNS::Message, Dnsruby::Message]

Returns:

  • (Dnsruby::Message)


40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/rex/proto/dns/packet.rb', line 40

def self.recalc_headers(packet)
  packet = self.encode_drb(packet)
  {
    :qdcount= => :question,
    :ancount= => :answer,
    :nscount= => :authority,
    :arcount= => :additional
  }.each do |header,body|
    packet.header.send(header,packet.send(body).count)
  end

  return packet
end

.valid_hostname?(subject = '') ⇒ TrueClass, FalseClass

Checks string to ensure it can be used as a valid hostname

Parameters:

  • subject (String) (defaults to: '')

    Subject name to check

Returns:

  • (TrueClass, FalseClass)

    Disposition on name match



19
20
21
# File 'lib/rex/proto/dns/packet.rb', line 19

def self.valid_hostname?(subject = '')
  !subject.match(Rex::Proto::DNS::Constants::MATCH_HOSTNAME).nil?
end

.validate(packet) ⇒ Dnsruby::Message

Reconstructs a packet with both standard DNS libraries Ensures that headers match the payload

Parameters:

  • packet (String, Net::DNS::Packet, Dnsruby::Message)

    Data to be validated

Returns:

  • (Dnsruby::Message)


30
31
32
# File 'lib/rex/proto/dns/packet.rb', line 30

def self.validate(packet)
    self.encode_drb(self.encode_net(self.encode_res(packet)))
end