RubyDNS & RExec Updates

Author: Samuel Williams When: Saturday, 29 August 2009

I 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

There are currently no comments.
Your Icon:
[City], [Country]
Publicly displayed.
Your email won't be displayed.
The following tags are preserved: <pre>, <em> and <a>. All comments are moderated.

Please note, you can leave a comment that uses (limited) XHTML and Textile syntax.