Skip to content

Commit

Permalink
Land #18662, Fix dns resolution skipping over nameservers with valid …
Browse files Browse the repository at this point in the history
…responses
  • Loading branch information
adfoster-r7 authored Jan 19, 2024
2 parents eb570f8 + 4bdff53 commit f56c9fc
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 118 deletions.
3 changes: 1 addition & 2 deletions lib/net/dns/resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,7 @@ def parse_config_file
when /^\s*search\s+(.*)/
self.searchlist = $1.split(" ")
when /^\s*nameserver\s+(.*)/
self.nameservers = $1.split(" ")
self.nameservers += $1.split(" ")
end
end
end
Expand Down Expand Up @@ -1295,4 +1295,3 @@ def key_downcase!
class Hash # :nodoc:
include ExtendHash
end

222 changes: 106 additions & 116 deletions lib/rex/proto/dns/resolver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ class Resolver < Net::DNS::Resolver
:use_tcp => false,
:ignore_truncated => false,
:packet_size => 512,
:tcp_timeout => TcpTimeout.new(30),
:udp_timeout => UdpTimeout.new(30),
:tcp_timeout => 30,
:udp_timeout => 30,
:context => {},
:comm => nil
}
Expand All @@ -46,7 +46,6 @@ def initialize(config = {})
# config.key_downcase!
@config = Defaults.merge config
@raw = false

# New logger facility
@logger = Logger.new(@config[:log_file])
@logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
Expand Down Expand Up @@ -211,85 +210,82 @@ def send_tcp(packet, packet_data, nameservers, prox = @config[:proxies])
ans = nil
length = [packet_data.size].pack("n")
nameservers.each do |ns, socket_options|
begin
socket = nil
config = {
'PeerHost' => ns.to_s,
'PeerPort' => @config[:port].to_i,
'Proxies' => prox,
'Context' => @config[:context],
'Comm' => @config[:comm]
}
config.update(socket_options)
unless config['Comm'].nil? || config['Comm'].alive?
@logger.warn("Session #{config['Comm'].sid} not active, and cannot be used to resolve DNS")
throw :next_ns
end
socket = nil
config = {
'PeerHost' => ns.to_s,
'PeerPort' => @config[:port].to_i,
'Proxies' => prox,
'Context' => @config[:context],
'Comm' => @config[:comm],
'Timeout' => @config[:tcp_timeout]
}
config.update(socket_options)
unless config['Comm'].nil? || config['Comm'].alive?
@logger.warn("Session #{config['Comm'].sid} not active, and cannot be used to resolve DNS")
next
end

suffix = " over session #{@config['Comm'].sid}" unless @config['Comm'].nil?
if @config[:source_port] > 0
config['LocalPort'] = @config[:source_port]
end
if @config[:source_host].to_s != '0.0.0.0'
config['LocalHost'] = @config[:source_host] unless @config[:source_host].nil?
suffix = " over session #{@config['Comm'].sid}" unless @config['Comm'].nil?
if @config[:source_port] > 0
config['LocalPort'] = @config[:source_port]
end
if @config[:source_host].to_s != '0.0.0.0'
config['LocalHost'] = @config[:source_host] unless @config[:source_host].nil?
end
begin
suffix = ''
begin
socket = Rex::Socket::Tcp.create(config)
rescue
@logger.warn "TCP Socket could not be established to #{ns}:#{@config[:port]} #{@config[:proxies]}#{suffix}"
next
end
@config[:tcp_timeout].timeout do
catch(:next_ns) do
suffix = ''
begin
socket = Rex::Socket::Tcp.create(config)
rescue
@logger.warn "TCP Socket could not be established to #{ns}:#{@config[:port]} #{@config[:proxies]}#{suffix}"
next unless socket #
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}#{suffix}"
socket.write(length+packet_data)
got_something = false
loop do
buffer = ""
attempts = 3
begin
ans = socket.recv(2)
rescue Errno::ECONNRESET
@logger.warn "TCP Socket got Errno::ECONNRESET from #{ns}:#{@config[:port]} #{@config[:proxies]}#{suffix}"
attempts -= 1
retry if attempts > 0
end
if ans.size == 0
if got_something
break #Proper exit from loop
else
@logger.warn "Connection reset to nameserver #{ns}#{suffix}, trying next."
throw :next_ns
end
next unless socket #
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}#{suffix}"
socket.write(length+packet_data)
got_something = false
loop do
buffer = ""
attempts = 3
begin
ans = socket.recv(2)
rescue Errno::ECONNRESET
@logger.warn "TCP Socket got Errno::ECONNRESET from #{ns}:#{@config[:port]} #{@config[:proxies]}#{suffix}"
attempts -= 1
retry if attempts > 0
end
if ans.size == 0
if got_something
break #Proper exit from loop
else
@logger.warn "Connection reset to nameserver #{ns}#{suffix}, trying next."
throw :next_ns
end
end
got_something = true
len = ans.unpack("n")[0]

@logger.info "Receiving #{len} bytes..."

if len.nil? or len == 0
@logger.warn "Receiving 0 length packet from nameserver #{ns}#{suffix}, trying next."
throw :next_ns
end

while (buffer.size < len)
left = len - buffer.size
temp,from = socket.recvfrom(left)
buffer += temp
end

unless buffer.size == len
@logger.warn "Malformed packet from nameserver #{ns}#{suffix}, trying next."
throw :next_ns
end
if block_given?
yield [buffer,["",@config[:port],ns.to_s,ns.to_s]]
else
return [buffer,["",@config[:port],ns.to_s,ns.to_s]]
end
end
end
got_something = true
len = ans.unpack("n")[0]

@logger.info "Receiving #{len} bytes..."

if len.nil? or len == 0
@logger.warn "Receiving 0 length packet from nameserver #{ns}#{suffix}, trying next."
throw :next_ns
end

while (buffer.size < len)
left = len - buffer.size
temp,from = socket.recvfrom(left)
buffer += temp
end

unless buffer.size == len
@logger.warn "Malformed packet from nameserver #{ns}#{suffix}, trying next."
throw :next_ns
end
if block_given?
yield [buffer,["",@config[:port],ns.to_s,ns.to_s]]
else
return [buffer,["",@config[:port],ns.to_s,ns.to_s]]
end
end
rescue Timeout::Error
Expand All @@ -312,48 +308,42 @@ def send_tcp(packet, packet_data, nameservers, prox = @config[:proxies])
# @return ans [String] Raw DNS reply
def send_udp(packet,packet_data, nameservers)
ans = nil
response = ""
nameservers.each do |ns, socket_options|
catch(:next_ns) do
begin
@config[:udp_timeout].timeout do
begin
config = {
'PeerHost' => ns.to_s,
'PeerPort' => @config[:port].to_i,
'Context' => @config[:context],
'Comm' => @config[:comm]
}
config.update(socket_options)
unless config['Comm'].nil? || config['Comm'].alive?
@logger.warn("Session #{config['Comm'].sid} not active, and cannot be used to resolve DNS")
throw :next_ns
end

if @config[:source_port] > 0
config['LocalPort'] = @config[:source_port]
end
if @config[:source_host] != IPAddr.new('0.0.0.0')
config['LocalHost'] = @config[:source_host] unless @config[:source_host].nil?
end
socket = Rex::Socket::Udp.create(config)
rescue
@logger.warn "UDP Socket could not be established to #{ns}:#{@config[:port]}"
throw :next_ns
end
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
#socket.sendto(packet_data, ns.to_s, @config[:port].to_i, 0)
socket.write(packet_data)
ans = socket.recvfrom(@config[:packet_size])
end
break if ans
rescue Timeout::Error
@logger.warn "Nameserver #{ns} not responding within UDP timeout, trying next one"
throw :next_ds
begin
config = {
'PeerHost' => ns.to_s,
'PeerPort' => @config[:port].to_i,
'Context' => @config[:context],
'Comm' => @config[:comm],
'Timeout' => @config[:udp_timeout]
}
config.update(socket_options)
unless config['Comm'].nil? || config['Comm'].alive?
@logger.warn("Session #{config['Comm'].sid} not active, and cannot be used to resolve DNS")
next
end

if @config[:source_port] > 0
config['LocalPort'] = @config[:source_port]
end
if @config[:source_host] != IPAddr.new('0.0.0.0')
config['LocalHost'] = @config[:source_host] unless @config[:source_host].nil?
end
socket = Rex::Socket::Udp.create(config)
rescue
@logger.warn "UDP Socket could not be established to #{ns}:#{@config[:port]}"
next
end
@logger.info "Contacting nameserver #{ns} port #{@config[:port]}"
#socket.sendto(packet_data, ns.to_s, @config[:port].to_i, 0)
socket.write(packet_data)
ans = socket.recvfrom(@config[:packet_size])
break if ans
rescue Timeout::Error
@logger.warn "Nameserver #{ns} not responding within UDP timeout, trying next one"
next
end
return ans
ans
end


Expand Down

0 comments on commit f56c9fc

Please sign in to comment.