dns_one 0.4.5 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f453b1c3de16a0ad2b5554fe8523ec273d0a357b
4
- data.tar.gz: 9f1c9f5f11051b485b4240928499480e4debaea7
3
+ metadata.gz: 34e353b91f2c725a06a2bc095d1990e48e0ab914
4
+ data.tar.gz: dbed7b26aa08686cfceafd0dbd659df692dd5aef
5
5
  SHA512:
6
- metadata.gz: 3b01bc36084734be73f3261f57506e535080f386893a459bf98f16c49873a355d292d64eda5680cceaa216d23db02369518b8e22d0f3de128e1f0217112b8e6d
7
- data.tar.gz: d04807c66a45320c7a3038deae8f73011ff304bee095483ac6866226a6ef125f6125b52570210e3aded4ceeae6d57a7ac3d9bf7e4d2f35eca3630e074038579c
6
+ metadata.gz: 1e5cbbad25694937f59a0e2b4271b3ea2f180264b6f11f4d7209d2d5f4f51b1e69e2c511fbea333e0e768cb645db3160e30adfc028d2f23dc56edb2b6195c654
7
+ data.tar.gz: b59b7281f46ad5233461d07bb62ff8e6973bf51dea119a089a7d883699bb671200d79b1a7890213ca0dc71897c417409715511f837a4f32210bfe1e22c29acba
@@ -1,7 +1,7 @@
1
1
  module Backend; class BackendDB
2
2
  def initialize conf
3
3
  @query = conf.delete :query
4
- @db_conf = conf
4
+ @conf = conf
5
5
  setup_db
6
6
  end
7
7
 
@@ -44,7 +44,27 @@ module Backend; class BackendDB
44
44
 
45
45
  def setup_db
46
46
  ActiveRecord::Base.logger = Log.logger
47
- ActiveRecord::Base.establish_connection @db_conf
47
+
48
+ gem_name = {
49
+ 'postgresql' => 'pg',
50
+ 'mysql' => 'mysql',
51
+ 'mysql2' => 'mysql2'
52
+ }[ @conf[:adapter] ]
53
+
54
+ unless gem_name
55
+ Util.die "Database adapter '#{@conf[:adapter]}' not supported. Aborting."
56
+ end
57
+
58
+ begin
59
+ require gem_name.to_s
60
+
61
+ rescue LoadError => e
62
+ Util.die "Error loading database dependency.\nMake sure #{gem_name} it is installed, if it is not, install with 'gem install #{gem_name}'\nError Details: #{e.desc}"
63
+ rescue => e
64
+ Util.die "Error loading database dependency.\n#{e.desc}"
65
+ end
66
+
67
+ ActiveRecord::Base.establish_connection @conf
48
68
  end
49
69
 
50
70
  end; end
data/lib/dns_one/cache.rb CHANGED
@@ -18,5 +18,9 @@ module DnsOne; class Cache
18
18
  def find k
19
19
  @cache[k]
20
20
  end
21
+
22
+ def stat
23
+ "#{@cache.length}/#{@max_size}"
24
+ end
21
25
 
22
26
  end; end
data/lib/dns_one/cli.rb CHANGED
@@ -10,8 +10,9 @@ class DnsOne::CLI < Thor
10
10
  desc "run", "run server"
11
11
  option :conf
12
12
  option :log
13
+ option :work_dir
13
14
  def run_srv
14
- DnsOne::DnsOne.new(conf_file: options[:conf], log_file: options[:log]).start
15
+ DnsOne::DnsOne.new(conf_file: options[:conf], log_file: options[:log], work_dir: options[:work_dir]).start
15
16
  end
16
17
  default_task :run_srv
17
18
 
@@ -0,0 +1,160 @@
1
+
2
+ # activesupport-5.1.1/lib/active_support/core_ext/regexp.rb
3
+
4
+ class Regexp #:nodoc:
5
+ def multiline?
6
+ options & MULTILINE == MULTILINE
7
+ end
8
+
9
+ def match?(string, pos = 0)
10
+ !!match(string, pos)
11
+ end unless //.respond_to?(:match?)
12
+ end
13
+
14
+ # activesupport-5.1.1/lib/active_support/core_ext/object/blank.rb
15
+
16
+ class Object
17
+ # An object is blank if it's false, empty, or a whitespace string.
18
+ # For example, +false+, '', ' ', +nil+, [], and {} are all blank.
19
+ #
20
+ # This simplifies
21
+ #
22
+ # !address || address.empty?
23
+ #
24
+ # to
25
+ #
26
+ # address.blank?
27
+ #
28
+ # @return [true, false]
29
+ def blank?
30
+ respond_to?(:empty?) ? !!empty? : !self
31
+ end
32
+
33
+ # An object is present if it's not blank.
34
+ #
35
+ # @return [true, false]
36
+ def present?
37
+ !blank?
38
+ end
39
+
40
+ # Returns the receiver if it's present otherwise returns +nil+.
41
+ # <tt>object.presence</tt> is equivalent to
42
+ #
43
+ # object.present? ? object : nil
44
+ #
45
+ # For example, something like
46
+ #
47
+ # state = params[:state] if params[:state].present?
48
+ # country = params[:country] if params[:country].present?
49
+ # region = state || country || 'US'
50
+ #
51
+ # becomes
52
+ #
53
+ # region = params[:state].presence || params[:country].presence || 'US'
54
+ #
55
+ # @return [Object]
56
+ def presence
57
+ self if present?
58
+ end
59
+ end
60
+
61
+ class NilClass
62
+ # +nil+ is blank:
63
+ #
64
+ # nil.blank? # => true
65
+ #
66
+ # @return [true]
67
+ def blank?
68
+ true
69
+ end
70
+ end
71
+
72
+ class FalseClass
73
+ # +false+ is blank:
74
+ #
75
+ # false.blank? # => true
76
+ #
77
+ # @return [true]
78
+ def blank?
79
+ true
80
+ end
81
+ end
82
+
83
+ class TrueClass
84
+ # +true+ is not blank:
85
+ #
86
+ # true.blank? # => false
87
+ #
88
+ # @return [false]
89
+ def blank?
90
+ false
91
+ end
92
+ end
93
+
94
+ class Array
95
+ # An array is blank if it's empty:
96
+ #
97
+ # [].blank? # => true
98
+ # [1,2,3].blank? # => false
99
+ #
100
+ # @return [true, false]
101
+ alias_method :blank?, :empty?
102
+ end
103
+
104
+ class Hash
105
+ # A hash is blank if it's empty:
106
+ #
107
+ # {}.blank? # => true
108
+ # { key: 'value' }.blank? # => false
109
+ #
110
+ # @return [true, false]
111
+ alias_method :blank?, :empty?
112
+ end
113
+
114
+ class String
115
+ unless BLANK_RE
116
+ BLANK_RE = /\A[[:space:]]*\z/
117
+ end
118
+
119
+ # A string is blank if it's empty or contains whitespaces only:
120
+ #
121
+ # ''.blank? # => true
122
+ # ' '.blank? # => true
123
+ # "\t\n\r".blank? # => true
124
+ # ' blah '.blank? # => false
125
+ #
126
+ # Unicode whitespace is supported:
127
+ #
128
+ # "\u00a0".blank? # => true
129
+ #
130
+ # @return [true, false]
131
+ def blank?
132
+ # The regexp that matches blank strings is expensive. For the case of empty
133
+ # strings we can speed up this method (~3.5x) with an empty? call. The
134
+ # penalty for the rest of strings is marginal.
135
+ empty? || BLANK_RE.match?(self)
136
+ end
137
+ end
138
+
139
+ class Numeric #:nodoc:
140
+ # No number is blank:
141
+ #
142
+ # 1.blank? # => false
143
+ # 0.blank? # => false
144
+ #
145
+ # @return [false]
146
+ def blank?
147
+ false
148
+ end
149
+ end
150
+
151
+ class Time #:nodoc:
152
+ # No Time is blank:
153
+ #
154
+ # Time.now.blank? # => false
155
+ #
156
+ # @return [false]
157
+ def blank?
158
+ false
159
+ end
160
+ end
@@ -0,0 +1,9 @@
1
+
2
+ class Exception
3
+ def desc
4
+ "#{self.class}: #{ message }\n#{ backtrace&.join "\n" }"
5
+ end
6
+ def puts_stderr
7
+ STDERR.puts e.desc
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+
2
+ class String
3
+ def to_a
4
+ [self]
5
+ end
6
+ def strip_text
7
+ split("\n")
8
+ .map{|l| l.strip}
9
+ .join("\n")
10
+ end
11
+ end
12
+
13
+
data/lib/dns_one/log.rb CHANGED
@@ -2,6 +2,7 @@
2
2
  class Log < Logger
3
3
  class << self
4
4
 
5
+ # 'def [d|i|w|e|f] msg' for DEBUG INFO WARN ERROR FATAL
5
6
  Logger::Severity::constants.each_with_index do |severity, severity_num|
6
7
  next if severity == :UNKNOWN
7
8
  method_name = severity.to_s[0].downcase
@@ -10,42 +11,67 @@ class Log < Logger
10
11
  end
11
12
  end
12
13
 
13
- def setup file, syslog_name
14
+ def setup file, syslog_name, syslog_min_severity = Logger::WARN
15
+ @syslog_min_severity = syslog_min_severity
14
16
  @syslog = Syslog::Logger.new syslog_name
15
17
  @log_file = setfile file
16
18
  @logger = Logger.new @log_file
17
19
  end
18
20
 
19
- def setfile file
20
- if File.exists? file and File.writable? file
21
- file
22
- elsif File.writable? File.dirname(file)
23
- file
21
+ def change_log_file file
22
+ new_log_file = setfile file, allow_stdout: false
23
+ if new_log_file and new_log_file != @log_file
24
+ @log_file = new_log_file
25
+ @logger = Logger.new @log_file
26
+ end
27
+ end
28
+
29
+ def exc e
30
+ e e.desc
31
+ end
32
+
33
+ def logger
34
+ @logger
35
+ end
36
+
37
+ def log_file_desc
38
+ case @log_file
39
+ when STDOUT
40
+ 'STDOUT'
41
+ when STDERR
42
+ 'STDERR'
24
43
  else
44
+ @log_file
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def setfile file, allow_stdout: true
51
+ if [STDOUT, STDERR].include? file or
52
+ File.writable? file or
53
+ File.writable? File.dirname(file)
54
+ file
55
+ elsif allow_stdout
25
56
  STDOUT
26
57
  end
27
58
  end
28
59
 
29
60
  def log severity, msg
30
61
  met_name = Logger::Severity::constants[severity].downcase
62
+
31
63
  @logger.send met_name, msg
32
- if severity >= Logger::WARN
64
+
65
+ if severity >= @syslog_min_severity
33
66
  @syslog.send met_name, msg
34
67
  end
68
+
35
69
  if severity == Logger::FATAL and
36
70
  @log_file != STDOUT and
37
71
  @log_file != STDERR
38
72
  STDERR.puts msg
39
73
  end
40
74
  end
41
-
42
- def exc e
43
- e e.desc
44
- end
45
-
46
- def logger
47
- @logger
48
- end
49
75
  end
50
76
  end
51
77
 
@@ -3,21 +3,23 @@ module DnsOne; class Server # < RExec::Daemon::Base
3
3
 
4
4
  DNS_DAEMON_RUN_AS = "dnsserver"
5
5
  DNS_DAEMON_INTERFACES = [
6
- [:udp, "0.0.0.0", 153],
7
- [:tcp, "0.0.0.0", 153],
8
- [:udp, "::", 15300],
9
- [:tcp, "::", 15300]
6
+ [:udp, "0.0.0.0", 53],
7
+ [:tcp, "0.0.0.0", 53],
8
+ [:udp, "::", 5300],
9
+ [:tcp, "::", 5300]
10
10
  ]
11
11
 
12
- def initialize conf
13
- ZoneSearch.instance.setup conf
12
+ def initialize conf, conf_zone_search
13
+ @conf = conf
14
+ ZoneSearch.instance.setup conf_zone_search
14
15
  end
15
16
 
16
17
  def run
18
+ conf = @conf
17
19
  RubyDNS::run_server(listen: dns_daemon_interfaces, logger: Log.logger) do
18
20
  on(:start) do
19
- if RExec.current_user == 'root' and @conf.config.run_as
20
- RExec.change_user @conf.config.run_as
21
+ if RExec.current_user == 'root' and conf[:run_as]
22
+ RExec.change_user conf[:run_as]
21
23
  end
22
24
  Log.i "Running as #{RExec.current_user}"
23
25
  end
@@ -42,7 +44,7 @@ module DnsOne; class Server # < RExec::Daemon::Base
42
44
  end
43
45
 
44
46
  def dns_daemon_interfaces
45
- if Process.pid == 0
47
+ if RExec.current_user == 'root'
46
48
  DNS_DAEMON_INTERFACES
47
49
  else
48
50
  ports = DNS_DAEMON_INTERFACES.map do |port|
data/lib/dns_one/util.rb CHANGED
@@ -22,4 +22,8 @@ module DnsOne; class Util; class << self
22
22
  end
23
23
  end
24
24
 
25
+ def match_root stat
26
+ stat.uid == 0 && stat.gid == 0
27
+ end
28
+
25
29
  end; end; end
@@ -1,3 +1,3 @@
1
1
  module DnsOne
2
- VERSION = "0.4.5"
2
+ VERSION = "0.4.7"
3
3
  end
@@ -9,10 +9,10 @@ module DnsOne; class ZoneSearch
9
9
  @conf = conf
10
10
  check_record_sets
11
11
  @backend = set_backend
12
- @cache = Cache.new @conf.config[:cache_max]
12
+ @cache = Cache.new @conf[:cache_max]
13
13
 
14
14
  @ignore_subdomains_re = nil
15
- if ignore_subdomains = @conf.config[:ignore_subdomains]
15
+ if ignore_subdomains = @conf[:ignore_subdomains]
16
16
  unless ignore_subdomains.empty?
17
17
  subdoms = ignore_subdomains.strip.split(/\s+/).map(&:downcase).join('|')
18
18
  @ignore_subdomains_re = /^(#{ subdoms })\./i
@@ -26,22 +26,24 @@ module DnsOne; class ZoneSearch
26
26
  Log.d "searching #{ dom_name }..."
27
27
 
28
28
  rec_set_name = find_record_set dom_name
29
- Log.d "record set name #{ rec_set_name ? 'found' : 'not_found' }"
29
+ Log.d "record set name #{ rec_set_name ? 'found' : 'not found' } for #{dom_name} #{res_class}"
30
30
  rec_set_name or return
31
31
 
32
32
  if rec_set_name == ''
33
- rec_set_name = @conf.record_sets.keys.first.to_s
33
+ rec_set_name = @conf[:ecord_sets].keys.first.to_s
34
34
  end
35
35
 
36
- rec_set = @conf.record_sets[rec_set_name.to_sym]
37
- Log.d "record set #{ rec_set ? 'found' : 'not found' }"
36
+ rec_set = @conf[:record_sets][rec_set_name.to_sym]
37
+ Log.d "record set #{ rec_set ? 'found' : 'not found' } for #{dom_name} #{res_class}"
38
38
  rec_set or return
39
39
 
40
40
  answer = nil
41
41
 
42
42
  unless res_class == IN::NS
43
- answer = rec_set[ res_class.to_s.split('::').last.to_sym ]
44
- answer = [answer] unless answer.is_a? Array
43
+ if rec = rec_set[ res_class.to_s.split('::').last.to_sym ]
44
+ answer = rec
45
+ answer = [answer] unless answer.is_a? Array
46
+ end
45
47
  end
46
48
 
47
49
  other_records = []
@@ -57,13 +59,13 @@ module DnsOne; class ZoneSearch
57
59
  private
58
60
 
59
61
  def set_backend
60
- if file = @conf.backend[:file]
62
+ if file = @conf[:backend][:file]
61
63
  unless File.exists? file
62
64
  Util.die "Domain list file #{file} not found."
63
65
  end
64
66
  Backend::BackendFile.new file
65
67
  else
66
- Backend::BackendDB.new @conf.backend
68
+ Backend::BackendDB.new @conf[:backend]
67
69
  end
68
70
  end
69
71
 
@@ -83,7 +85,7 @@ module DnsOne; class ZoneSearch
83
85
  enabled_cache = use_cache && @backend.allow_cache
84
86
 
85
87
  if enabled_cache and rec_set = @cache.find(dom_name)
86
- Log.d "found in cache"
88
+ Log.d "found in cache (#{@cache.stat})"
87
89
  rec_set
88
90
  else
89
91
  if rec_set = @backend.find(dom_name)
@@ -96,11 +98,11 @@ module DnsOne; class ZoneSearch
96
98
  end
97
99
 
98
100
  def check_record_sets
99
- unless @conf.record_sets and not @conf.record_sets.empty?
101
+ if @conf[:record_sets].blank?
100
102
  Util.die "Record sets cannot be empty. Check file."
101
103
  end
102
104
 
103
- @conf.record_sets.each_pair do |rec_set_name, records|
105
+ @conf[:record_sets].each_pair do |rec_set_name, records|
104
106
  unless records[:NS] and records[:NS].length >= 1
105
107
  Util.die "Record set #{rec_set_name} is invalid. It must have at least 1 NS record."
106
108
  end
data/lib/dns_one.rb CHANGED
@@ -10,7 +10,10 @@ require 'rexec'
10
10
 
11
11
  # DnsOne
12
12
 
13
- require "dns_one/core_extensions"
13
+ require "dns_one/core_ext/exception"
14
+ require "dns_one/core_ext/string"
15
+ require "dns_one/core_ext/blank"
16
+
14
17
  require "dns_one/log"
15
18
  require "dns_one/util"
16
19
 
@@ -24,30 +27,42 @@ require 'dns_one/backend/db'
24
27
 
25
28
  module DnsOne; class DnsOne
26
29
 
27
- DEFAULT_LOG_FILE = "/var/log/dns_server.log"
30
+ DEFAULT_LOG_FILE = "/var/log/dns_one.log"
28
31
  DEFAULT_CONF_FILE = '/etc/dns_one/conf.yml'
29
- WORK_DIR = "/var/local/dnsserver"
32
+ WORK_DIR = "/var/local/dns_one"
30
33
 
31
34
  CONF_DIR = "/etc/dns_one"
32
35
  SYSLOG_NAME = 'dns_one'
33
36
 
34
- def initialize conf_file: nil, log_file: nil
35
- log_file ||= DEFAULT_LOG_FILE
36
- conf_file ||= DEFAULT_CONF_FILE
37
-
37
+ def initialize conf_file: nil, log_file: nil, work_dir: nil
38
+ cmd_log_file = log_file
39
+ log_file ||= DEFAULT_LOG_FILE
38
40
  Log.setup log_file, SYSLOG_NAME
39
- @conf = parse_conf conf_file
40
41
 
41
- # check_root
42
+ conf_file ||= DEFAULT_CONF_FILE
43
+ @conf_all = parse_conf conf_file
44
+ @conf = @conf_all.main
45
+
46
+ work_dir ||= WORK_DIR
47
+
48
+ # Redefine log file if set in conf file
49
+ unless cmd_log_file
50
+ if f = @conf[:log_file].presence
51
+ unless Log.change_log_file f
52
+ Log.w "Unable to change logfile to #{f}. Will continue with #{Log.log_file_desc}."
53
+ end
54
+ end
55
+ end
56
+
42
57
  begin
43
- Dir.chdir (@conf.config[:work_dir] || WORK_DIR)
58
+ Dir.chdir work_dir
44
59
  rescue => e
45
60
  Log.w "Cannot change working dir to #{WORK_DIR}. Will continue in #{Dir.pwd}."
46
61
  end
47
62
  end
48
63
 
49
64
  def start
50
- Server.new(@conf).run
65
+ Server.new(@conf_all.server, @conf_all.zone_search).run
51
66
  end
52
67
 
53
68
  private
@@ -58,9 +73,21 @@ module DnsOne; class DnsOne
58
73
  conf = YAML.load_file conf_file
59
74
  conf.deep_symbolize_keys!
60
75
 
61
- conf[:config] ||= {}
62
-
63
- OpenStruct.new conf
76
+ OpenStruct.new(
77
+ main: {
78
+ work_dir: conf[:work_dir],
79
+ log_file: conf[:log_file]
80
+ },
81
+ server: {
82
+ run_as: conf[:run_as]
83
+ },
84
+ zone_search: {
85
+ ignore_subdomains: conf[:ignore_subdomains],
86
+ cache_max: conf[:cache_max],
87
+ record_sets: conf[:record_sets],
88
+ backend: conf[:backend]
89
+ }
90
+ )
64
91
  end
65
92
 
66
93
  def check_conf_file conf_file
@@ -74,7 +101,7 @@ module DnsOne; class DnsOne
74
101
  # Util.die "Conf file #{conf_file} must have mode 0600. Aborting."
75
102
  end
76
103
 
77
- unless match_root conf_stat
104
+ unless Util.match_root conf_stat
78
105
  # Util.die "Conf file #{conf_file} must have uid/gid set to root. Aborting."
79
106
  end
80
107
  end
data/util/sample_conf.yml CHANGED
@@ -1,8 +1,9 @@
1
1
 
2
2
  config:
3
3
  run_as: dnsserver # optional, but highly recommended! adduser --system dnsserver
4
- ignore_subdomains: www en it es pt ru fr at # optional
4
+ ignore_subdomains: www en it es pt ru fr at # optional, defaults to an empty list
5
5
  # cache_max: 100000 # optional, defaults to 10000
6
+ # log_file: /var/log/dns_one.log # optional, defaults to /var/log/dns_one.log
6
7
 
7
8
  backend:
8
9
  ##############
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dns_one
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Lobato
@@ -136,7 +136,9 @@ files:
136
136
  - lib/dns_one/backend/file.rb
137
137
  - lib/dns_one/cache.rb
138
138
  - lib/dns_one/cli.rb
139
- - lib/dns_one/core_extensions.rb
139
+ - lib/dns_one/core_ext/blank.rb
140
+ - lib/dns_one/core_ext/exception.rb
141
+ - lib/dns_one/core_ext/string.rb
140
142
  - lib/dns_one/log.rb
141
143
  - lib/dns_one/server.rb
142
144
  - lib/dns_one/setup.rb
@@ -1,24 +0,0 @@
1
-
2
- class String
3
- def to_a
4
- [self]
5
- end
6
- def strip_text
7
- split("\n")
8
- .map{|l| l.strip}
9
- .join("\n")
10
- end
11
- end
12
-
13
- class Exception
14
- def desc
15
- "#{e.class}: #{ message }\n#{ backtrace&.join "\n" }"
16
- end
17
- def puts_stderr
18
- STDERR.puts e.desc
19
- end
20
- end
21
-
22
- def match_root stat
23
- stat.uid == 0 && stat.gid == 0
24
- end