class Server
A DNS server which can be used to resolve queries.
Definitions
def self.default_endpoint(port = 53)
The default endpoint to listen on.
Signature
-
parameter
port
Integer
The port to listen on, defaults to 53.
Implementation
def self.default_endpoint(port = 53)
::IO::Endpoint.composite(
::IO::Endpoint.udp('localhost', port),
::IO::Endpoint.tcp('localhost', port)
)
end
def initialize(endpoint = self.class.default_endpoint, origin: '.')
Instantiate a server with a block.
Implementation
def initialize(endpoint = self.class.default_endpoint, origin: '.')
@endpoint = endpoint
@origin = origin
end
attr_accessor :origin
Records are relative to this origin.
def logger
- deprecated
Signature
- deprecated
Use
Console
instead.
Implementation
def logger
Console
end
def process(name, resource_class, transaction)
Give a name and a record type, try to match a rule and use it for processing the given arguments.
Implementation
def process(name, resource_class, transaction)
transaction.fail!(:NXDomain)
end
def process_query(query, options = {}, &block)
Process an incoming DNS message. Returns a serialized message to be sent back to the client.
Implementation
def process_query(query, options = {}, &block)
start_time = Time.now
# Setup response
response = Resolv::DNS::Message::new(query.id)
response.qr = 1 # 0 = Query, 1 = Response
response.opcode = query.opcode # Type of Query; copy from query
response.aa = 1 # Is this an authoritative response: 0 = No, 1 = Yes
response.rd = query.rd # Is Recursion Desired, copied from query
response.ra = 0 # Does name server support recursion: 0 = No, 1 = Yes
response.rcode = 0 # Response code: 0 = No errors
transaction = nil
begin
query.question.each do |question, resource_class|
begin
question = question.without_origin(@origin)
Console.debug(query) {"Processing question #{question} #{resource_class}..."}
transaction = Transaction.new(self, query, question, resource_class, response, **options)
transaction.process
rescue Resolv::DNS::OriginError => error
# This is triggered if the question is not part of the specified @origin:
Console::Event::Failure.for(error).emit("Skipping question #{question} #{resource_class}!")
end
end
rescue StandardError => error
Console.error(query) {error}
response.rcode = Resolv::DNS::RCode::ServFail
end
end_time = Time.now
Console.debug(query) {"Time to process request: #{end_time - start_time}s"}
return response
end
def run
Setup all specified interfaces and begin accepting incoming connections.
Implementation
def run
Console.info "Starting Async::DNS server (v#{Async::DNS::VERSION})..."
Async do |task|
@endpoint.bind do |server|
Console.info "<> Listening for connections on #{server.local_address.inspect}"
case server.local_address.socktype
when Socket::SOCK_DGRAM
DatagramHandler.new(self, server).run
when Socket::SOCK_STREAM
StreamHandler.new(self, server).run
else
raise ArgumentError.new("Don't know how to handle #{server}")
end
end
end
end