app/services/nameserver_validator.rb
module NameserverValidator
include Dnsruby
extend self
VALIDATION_NAMESERVER_PERIOD = 1.year.freeze
VALIDATION_DOMAIN_PERIOD = 8.hours.freeze
VALID_NAMESERVER_COUNT_THRESHOLD = 3
def run(domain_name:, nameserver:)
result_response = validate(domain_name: domain_name, hostname: nameserver.hostname)
unless result_response[:result] && result_response[:reason] == :exception
if result_response[:error_info].to_s.include? "Nameserver invalid!"
if nameserver.ipv4.present?
result_response = validate(domain_name: domain_name, hostname: nameserver.ipv4)
# elsif nameserver.ipv6.present?
# result_response = validate(domain_name: domain_name, hostname: nameserver.ipv6)
end
return { result: false, reason: 'glup record' } unless result_response[:result]
return result_response
end
end
result_response
end
private
def validate(domain_name:, hostname:)
resolver = setup_resolver(hostname)
result = resolver.query(domain_name, 'SOA', 'IN')
return { result: false, reason: 'answer' } if result.answer.empty?
decision = result.answer.any? do |a|
a.type == 'CNAME'
end
return { result: false, reason: 'cname' } if decision
decision = result.answer.all? do |a|
a.instance_variable_defined? '@serial'
end
return { result: false, reason: 'serial' } unless decision
logger.info "Serial number - #{result.answer[0].serial.to_s} of #{hostname} - domain name: #{domain_name}"
{ result: true, reason: '' }
rescue Dnsruby::Refused => e
logger.error e.message
logger.error "failed #{hostname} validation of #{domain_name} domain name. Domain not found"
return { result: false, reason: 'domain', error_info: e }
rescue Dnsruby::NXDomain => e
logger.error e.message
logger.error "failed #{hostname} validation of #{domain_name} domain name. Domain not found"
return { result: false, reason: 'domain', error_info: e }
rescue StandardError => e
logger.error e.message
logger.error "failed #{hostname} validation of #{domain_name} domain name"
return { result: false, reason: 'exception', error_info: e }
end
def setup_resolver(hostname)
resolver = Dnsruby::Resolver.new
timeouts = ENV['nameserver_validation_timeout'] || 4
resolver.query_timeout = timeouts.to_i
resolver.retry_times = 3
resolver.recurse = 0 # Send out non-recursive queries
# disable caching otherwise SOA is cached from first nameserver queried
resolver.do_caching = false
resolver.nameserver = hostname
resolver
end
def logger
@logger ||= Rails.logger
end
end