RubyDNS & RExec Updates
Author: Samuel Williams When: Saturday, 29 August 2009I have made some improvements to RubyDNS. The primary improvements are bug fixes, but there are also a number of changes designed to improve performance.
To make it easier to make a DNS daemon, I have also improved RExec. RExec is a tool that allows you to make the daemon easily. The primary improvements center around making it easier to drop priviledges and better error reporting when starting a daemon.
#!/usr/bin/env ruby
# Copyright (c) 2009 Samuel Williams. Released under the GNU GPLv3.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
require 'rubygems'
require 'rexec'
require 'rexec/daemon'
require 'rubygems'
require 'rubydns'
# To run this command, use the standard daemon syntax as root
# ./daemon2.rb start
# You should be able to see that the server has dropped priviledges
# # ps aux | grep daemon2.rb
# daemon 16555 0.4 0.0 81392 2024 ?? S 3:35am 0:00.28 ruby ../test/daemon2.rb start
# Test using the following command
# dig @localhost test.mydomain.org
# You might need to change the user name "daemon". This can be a user name or a user id.
RUN_AS = "daemon"
# UDP Socket does per packet reverse lookups unless this is set.
UDPSocket.do_not_reverse_lookup = true
# We need to be root in order to bind to privileged port
if RExec.current_user != "root"
$stderr.puts "Sorry, this command needs to be run as root!"
exit 1
end
# The Daemon itself
class Server < RExec::Daemon::Base
@@var_directory = File.dirname(__FILE__)
def self.run
# Bind to port 53 (UDP)
socket = UDPSocket.new
socket.bind("0.0.0.0", 53)
# Drop priviledges
RExec.change_user(RUN_AS)
# Don't buffer output (for debug purposes)
$stderr.sync = true
# Use upstream DNS for name resolution (These ones are Orcon DNS in NZ)
$R = Resolv::DNS.new(:nameserver => ["60.234.1.1", "60.234.2.2"])
# Start the RubyDNS server
RubyDNS::run_server(:listen => [socket]) do
match("test.mydomain.org", :A) do |transaction|
transaction.respond!("10.0.0.80")
end
# Default DNS handler
otherwise do |transaction|
logger.info "Passthrough: #{transaction}"
transaction.passthrough!($R)
end
end
end
end
# RExec daemon runner
Server.daemonize
For more information on RubyDNS, please visit the RubyDNS page. For more information on RExec, please visit the RExec page.
Comments
Please note, you can leave a comment that uses (limited) XHTML and Textile syntax.