Use a MockDnsClient object for request state

In order to handle TCP and UDP clients in a common manner, the
DNS server created a Rex::Socket::Udp object to represent the
client object allowing for a client.write(response) approach to
returning results for both TCP and UDP clients. During work on
the common socket abstractions (#6692) it became apparent that
remote pivoted sockets cannot be created with the same exact param
set used on the server socket - sockets dont reuse with localhost
and localport params being the same, an exception is raised from
the Windows side of the pivot abstraction. Creating a new socket
for every request is also needless overhead and noise.

Create the MockDnsClient class to  consume peerhost, peerport, and
the DNS server's UDP socket as arguments in order to execute a
sendto() from the existing socket when sending a response. A write
method is provided in the class for common interface between the
UDP and TCP request handlers.

This has been tested in conjunction with #6692 and shown to be
successful as serving remote requests from the IO.select polled
pivot socket running on a Windows host via Meterpreter.
This commit is contained in:
RageLtMan
2016-03-21 13:53:44 -04:00
parent fec23cf0fd
commit b60990c19c
+28 -7
View File
@@ -127,6 +127,32 @@ class Server
end
end # Cache
class MockDnsClient
attr_reader :peerhost, :peerport, :srvsock
#
# Create mock DNS client
#
# @param host [String] PeerHost IP address
# @param port [Fixnum] PeerPort integer
def initialize(host, port, sock)
@peerhost = host
@peerport = port
@srvsock = sock
end
#
# Test method to prevent GC/ObjectSpace abuse via class lookups
#
def mock_dns_client?
true
end
def write(data)
srvsock.sendto(data, peerhost, peerport)
end
end
include Rex::IO::GramServer
Packet = Rex::Proto::DNS::Packet
@@ -292,13 +318,8 @@ protected
if (r != nil and r[0] == self.udp_sock)
buf,host,port = self.udp_sock.recvfrom(65535)
# Mock up a client object as a Rex Socket for sending back data
cli = Rex::Socket::Udp.create(
'PeerHost' => host,
'PeerPort' => port,
'LocalHost' => self.udp_sock.localhost,
'LocalPort' => self.udp_sock.localport
)
# Mock up a client object for sending back data
cli = MockDnsClient.new(host, port, r[0])
dispatch_request(cli, buf)
end
end