rubydns 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +23 -14
- data/README.md +6 -4
- data/examples/Gemfile +7 -0
- data/examples/README.md +137 -0
- data/examples/{dropping-dns.rb → flakey-dns.rb} +22 -15
- data/examples/fortune-dns.rb +106 -0
- data/examples/geoip-dns.rb +117 -0
- data/examples/wikipedia-dns.rb +120 -0
- data/lib/rubydns.rb +5 -5
- data/lib/rubydns/resolver.rb +5 -0
- data/lib/rubydns/version.rb +1 -1
- data/rubydns.gemspec +2 -2
- data/spec/rubydns/celluloid_bug_spec.rb +92 -0
- data/spec/rubydns/injected_supervisor_spec.rb +61 -0
- metadata +15 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4deb19b1b3f2428b941ec102d2cc15a640ad8211
|
4
|
+
data.tar.gz: 13c3d5e62e811bbb25c2eee5123195c608b30303
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 532c64c0de7e2893704ff62e1cd523a155dacbc42e332aef20c44723d5fce08218cbfa371cb458049a94cf30a4d885b3787a8ee1ee2b525f21afa7d4dad5e0d0
|
7
|
+
data.tar.gz: 250674b3f8554f7ceb493fdd0b0f7a4b8d1cee949ce27b16276db5ef83fe5ab2868fce3a8e4037976f8a307538bf116b0775271a6b07445f29f909448f4b3c4d
|
data/.gitignore
CHANGED
@@ -1,17 +1,26 @@
|
|
1
1
|
*.gem
|
2
2
|
*.rbc
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
doc/
|
11
|
-
lib/bundler/man
|
12
|
-
pkg
|
13
|
-
rdoc
|
14
|
-
spec/reports
|
15
|
-
test/tmp
|
16
|
-
test/version_tmp
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/test/tmp/
|
9
|
+
/test/version_tmp/
|
17
10
|
tmp
|
11
|
+
|
12
|
+
/.yardoc/
|
13
|
+
/_yardoc/
|
14
|
+
/doc/
|
15
|
+
/rdoc/
|
16
|
+
|
17
|
+
/.bundle/
|
18
|
+
/lib/bundler/man/
|
19
|
+
|
20
|
+
Gemfile.lock
|
21
|
+
.ruby-version
|
22
|
+
.ruby-gemset
|
23
|
+
|
24
|
+
/examples/log
|
25
|
+
/examples/run
|
26
|
+
/spec/rubydns/server/bind9/log/
|
data/README.md
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# RubyDNS
|
2
|
+
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/ioquatix/rubydns?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
2
3
|
|
3
4
|
RubyDNS is a high-performance DNS server which can be easily integrated into other projects or used as a stand-alone daemon. By default it uses rule-based pattern matching. Results can be hard-coded, computed, fetched from a remote DNS server or fetched from a local cache, depending on requirements.
|
4
5
|
|
5
|
-
In addition, RubyDNS includes a high-performance asynchronous DNS resolver built on top of
|
6
|
+
In addition, RubyDNS includes a high-performance asynchronous DNS resolver built on top of [Celluloid][1]. This module can be used by itself in client applications without using the full RubyDNS server stack.
|
6
7
|
|
7
|
-
For examples and documentation please see the main [project page][
|
8
|
+
For examples and documentation please see the main [project page][2].
|
8
9
|
|
9
|
-
[1]:
|
10
|
+
[1]: https://celluloid.io
|
11
|
+
[2]: http://www.codeotaku.com/projects/rubydns/
|
10
12
|
|
11
13
|
[![Build Status](https://travis-ci.org/ioquatix/rubydns.svg?branch=master)](https://travis-ci.org/ioquatix/rubydns)
|
12
14
|
[![Code Climate](https://codeclimate.com/github/ioquatix/rubydns.png)](https://codeclimate.com/github/ioquatix/rubydns)
|
@@ -44,7 +46,7 @@ This is copied from `test/examples/test-dns-2.rb`. It has been simplified slight
|
|
44
46
|
|
45
47
|
# Start the RubyDNS server
|
46
48
|
RubyDNS::run_server(:listen => INTERFACES) do
|
47
|
-
match(/test
|
49
|
+
match(/test\.mydomain\.org/, IN::A) do |transaction|
|
48
50
|
transaction.respond!("10.0.0.80")
|
49
51
|
end
|
50
52
|
|
data/examples/Gemfile
ADDED
data/examples/README.md
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# RubyDNS Examples
|
2
|
+
|
3
|
+
This directory contains several examples of customized RubyDNS servers,
|
4
|
+
intended to demonstrate how RubyDNS can be easily customized to specific
|
5
|
+
needs.
|
6
|
+
|
7
|
+
## FlakeyDNS (flakey-dns.rb)
|
8
|
+
|
9
|
+
A DNS server that selectively drops queries based on the requested domain name. Queries for domains that match specified regular expressions (like 'microsoft.com' or 'sco.com') return NXDomain, while all other queries are passed to upstream resolvers.
|
10
|
+
|
11
|
+
By default this server will listen for UDP requests on port 5300 and does not need to be started as root.
|
12
|
+
|
13
|
+
To start the server, ensure that you're in the examples subdirectory and type
|
14
|
+
|
15
|
+
bundle
|
16
|
+
bundle exec ./flakey-dns.rb
|
17
|
+
|
18
|
+
To see it in action you can then query some domains. For example,
|
19
|
+
|
20
|
+
dig @localhost -p 5300 slashdot.org -t A
|
21
|
+
dig @localhost -p 5300 www.hackernews.com -t A
|
22
|
+
|
23
|
+
give the correct results. But
|
24
|
+
|
25
|
+
dig @localhost -p 5300 microsoft.com -t A
|
26
|
+
dig @localhost -p 5300 www.microsoft.com -t A
|
27
|
+
dig @localhost -p 5300 www.microsoft.com
|
28
|
+
|
29
|
+
all give an NXDomain result.
|
30
|
+
|
31
|
+
## FortuneDNS (fortune-dns.rb)
|
32
|
+
|
33
|
+
A DNS server that allows a client to generate fortunes and fetch them with subsequent requests. The server
|
34
|
+
'remembers' the fortunes it generates, and can serve them to future requests. The reason for this is because most fortunes won't fit over UDP (maximum size 512 bytes) and the client will request the same fortune via TCP.
|
35
|
+
|
36
|
+
You will need to have the `fortune` app installed on your system. It comes installed by default on
|
37
|
+
most Linux distributions, and can be installed on a Mac with Homebrew by typing:
|
38
|
+
|
39
|
+
# Homebrew
|
40
|
+
brew install fortune
|
41
|
+
# MacPorts
|
42
|
+
sudo port install fortune
|
43
|
+
# Arch Linux
|
44
|
+
sudo pacman -S fortune-mod
|
45
|
+
|
46
|
+
By default this server will listen for UDP and TCP requests on port 53, and needs to be started as root. It
|
47
|
+
assumes the existence of a user 'daemon', as whom the process will run. If such a user doesn't exist on your
|
48
|
+
system, you will need to either create such a user or update the script to use a user that exists on your
|
49
|
+
system.
|
50
|
+
|
51
|
+
To start the server, ensure that you're in the examples subdirectory and type
|
52
|
+
|
53
|
+
bundle
|
54
|
+
sudo bundle exec ./fortune-dns.rb
|
55
|
+
|
56
|
+
To create a new fortune type
|
57
|
+
|
58
|
+
dig @localhost fortune -t TXT
|
59
|
+
|
60
|
+
This will result in an DNS answer that looks something like this:
|
61
|
+
|
62
|
+
fortune. 0 IN TXT "Text Size: 714 Byte Size: 714"
|
63
|
+
fortune. 0 IN CNAME 32bf3bf2b0a2255f2df00ed9e95c8185.fortune.
|
64
|
+
|
65
|
+
Take the CNAME from this result and query it. For our example this would be:
|
66
|
+
|
67
|
+
dig @localhost 32bf3bf2b0a2255f2df00ed9e95c8185.fortune -t TXT
|
68
|
+
|
69
|
+
And your answer will be a fortune.
|
70
|
+
|
71
|
+
You can also generate a 'short' fortune by typing the following:
|
72
|
+
|
73
|
+
dig @localhost short.fortune -t TXT
|
74
|
+
|
75
|
+
or view the fortune stats with:
|
76
|
+
|
77
|
+
dig @localhost stats.fortune -t TXT
|
78
|
+
|
79
|
+
## GeoIPDNS (geoip-dns.rb)
|
80
|
+
|
81
|
+
A sample DNS daemon that demonstrates how to use RubyDNS to build responses
|
82
|
+
that vary based on the geolocation of the requesting peer. Clients of this
|
83
|
+
server who request A records will get an answer IP address based on the
|
84
|
+
continent of the client IP address.
|
85
|
+
|
86
|
+
Please note that use of this example requires that the peer have a public
|
87
|
+
IP address. IP addresses on private networks or the localhost IP (127.0.0.1)
|
88
|
+
cannot be resolved to a location, and so will always yield the unknown result.
|
89
|
+
|
90
|
+
This daemon requires the file downloaded from
|
91
|
+
[MaxMind](http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz)
|
92
|
+
For more information on the GeoIP library, please click [here](http://www.maxmind.com/en/geolite)
|
93
|
+
or [here](https://github.com/cjheath/geoip). This file should be unzipped and placed in the
|
94
|
+
examples root directory, i.e. `examples/GeoLiteCountry.dat`.
|
95
|
+
|
96
|
+
By default this server will listen for UDP requests on port 5300 and does not need to be started as root.
|
97
|
+
|
98
|
+
To start the server, ensure that you're in the examples subdirectory and type
|
99
|
+
|
100
|
+
bundle
|
101
|
+
sudo bundle exec ./geoip-dns.rb
|
102
|
+
|
103
|
+
To see the behavior, run a DNS query against the server where you are running the GeoIPDNS
|
104
|
+
daemon. Depending on the continent to which the client machine's IP address is mapped,
|
105
|
+
you will receive a different IP address in the answer section:
|
106
|
+
|
107
|
+
Africa - 1.1.1.1
|
108
|
+
Antarctica - 1.1.2.1
|
109
|
+
Asia - 1.1.3.1
|
110
|
+
Europe - 1.1.4.1
|
111
|
+
North America - 1.1.5.1
|
112
|
+
Oceania - 1.1.6.1
|
113
|
+
South America - 1.1.7.1
|
114
|
+
|
115
|
+
## WikipediaDNS (wikipedia-dns.rb)
|
116
|
+
|
117
|
+
A DNS server that queries Wikipedia and returns summaries for specifically crafted queries.
|
118
|
+
|
119
|
+
By default this server will listen for UDP and TCP requests on port 53, and needs to be started as root. It
|
120
|
+
assumes the existence of a user 'daemon', as whom the process will run. If such a user doesn't exist on your
|
121
|
+
system, you will need to either create such a user or update the script to use a user that exists on your
|
122
|
+
system.
|
123
|
+
|
124
|
+
To start the server, ensure that you're in the examples subdirectory and type
|
125
|
+
|
126
|
+
bundle
|
127
|
+
sudo bundle exec ./wikipedia-dns.rb
|
128
|
+
|
129
|
+
To query Wikipedia, pick a term - say, 'helium' - and make a DNS query like
|
130
|
+
|
131
|
+
dig @localhost helium.wikipedia -t TXT
|
132
|
+
|
133
|
+
The answer section should contain the summary for this topic from Wikipedia
|
134
|
+
|
135
|
+
helium.wikipedia. 86400 IN TXT "Helium is a chemical element with symbol He and atomic number 2. It is a colorless, odorless, tasteless, non-toxic, inert, monatomic gas that heads the noble gas group in the periodic table. Its boiling and melting points are the lowest among the elements" " and it exists only as a gas except in extreme conditions."
|
136
|
+
|
137
|
+
Long blocks of text cannot be easily replied in DNS as they must be chunked into segments at most 255 bytes. Long replies must be sent back using TCP.
|
@@ -1,17 +1,17 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
# Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
# of this software and associated documentation files (the "Software"), to deal
|
7
7
|
# in the Software without restriction, including without limitation the rights
|
8
8
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
9
|
# copies of the Software, and to permit persons to whom the Software is
|
10
10
|
# furnished to do so, subject to the following conditions:
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# The above copyright notice and this permission notice shall be included in
|
13
13
|
# all copies or substantial portions of the Software.
|
14
|
-
#
|
14
|
+
#
|
15
15
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
16
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
17
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
@@ -26,40 +26,47 @@ require 'rubydns'
|
|
26
26
|
require 'rubydns/system'
|
27
27
|
|
28
28
|
INTERFACES = [
|
29
|
-
[:udp,
|
29
|
+
[:udp, '0.0.0.0', 5300]
|
30
30
|
]
|
31
31
|
|
32
|
-
|
32
|
+
# A DNS server that selectively drops queries based on the requested domain
|
33
|
+
# name. Queries for domains that match specified regular expresssions
|
34
|
+
# (like 'microsoft.com' or 'sco.com') return NXDomain, while all other
|
35
|
+
# queries are passed to upstream resolvers.
|
36
|
+
class FlakeyDNS < Process::Daemon
|
33
37
|
Name = Resolv::DNS::Name
|
34
38
|
IN = Resolv::DNS::Resource::IN
|
35
|
-
|
36
|
-
|
39
|
+
|
37
40
|
def startup
|
38
|
-
RubyDNS
|
41
|
+
RubyDNS.run_server(listen: INTERFACES) do
|
39
42
|
# Fail the resolution of certain domains ;)
|
40
43
|
match(/(m?i?c?r?o?s?o?f?t)/) do |transaction, match_data|
|
41
44
|
if match_data[1].size > 7
|
42
|
-
logger.info
|
45
|
+
logger.info 'Dropping domain MICROSOFT...'
|
43
46
|
transaction.fail!(:NXDomain)
|
44
47
|
else
|
45
48
|
# Pass the request to the otherwise handler
|
46
49
|
false
|
47
50
|
end
|
48
51
|
end
|
49
|
-
|
52
|
+
|
50
53
|
# Hmm....
|
51
54
|
match(/^(.+\.)?sco\./) do |transaction|
|
52
|
-
logger.info
|
55
|
+
logger.info 'Dropping domain SCO...'
|
53
56
|
transaction.fail!(:NXDomain)
|
54
57
|
end
|
55
58
|
|
56
59
|
# Default DNS handler
|
57
60
|
otherwise do |transaction|
|
58
|
-
logger.info
|
59
|
-
transaction.passthrough!(
|
61
|
+
logger.info 'Passing DNS request upstream...'
|
62
|
+
transaction.passthrough!(FlakeyDNS.fallback_resolver)
|
60
63
|
end
|
61
64
|
end
|
62
|
-
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.fallback_resolver
|
68
|
+
@resolver ||= RubyDNS::Resolver.new(RubyDNS::System.nameservers)
|
69
|
+
end
|
63
70
|
end
|
64
71
|
|
65
|
-
|
72
|
+
FlakeyDNS.daemonize
|
@@ -0,0 +1,106 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
|
24
|
+
require 'process/daemon'
|
25
|
+
require 'process/daemon/privileges'
|
26
|
+
|
27
|
+
require 'rubydns'
|
28
|
+
require 'rubydns/extensions/string'
|
29
|
+
|
30
|
+
require 'digest/md5'
|
31
|
+
|
32
|
+
# You might need to change the user name "daemon". This can be a user name
|
33
|
+
# or a user id.
|
34
|
+
RUN_AS = 'daemon'
|
35
|
+
|
36
|
+
if Process::Daemon::Privileges.current_user != 'root'
|
37
|
+
$stderr.puts 'Sorry, this command needs to be run as root!'
|
38
|
+
exit 1
|
39
|
+
end
|
40
|
+
|
41
|
+
# A DNS server that allows a client to generate fortunes and fetch them with
|
42
|
+
# subsequent requests. The server 'remembers' the fortunes it generates,
|
43
|
+
# and can serve them to future requests.
|
44
|
+
class FortuneDNS < Process::Daemon
|
45
|
+
Name = Resolv::DNS::Name
|
46
|
+
IN = Resolv::DNS::Resource::IN
|
47
|
+
|
48
|
+
def startup
|
49
|
+
cache = {}
|
50
|
+
stats = { requested: 0 }
|
51
|
+
|
52
|
+
# Start the RubyDNS server
|
53
|
+
RubyDNS.run_server do
|
54
|
+
on(:start) do
|
55
|
+
Process::Daemon::Privileges.change_user(RUN_AS)
|
56
|
+
|
57
|
+
if ARGV.include?('--debug')
|
58
|
+
@logger.level = Logger::DEBUG
|
59
|
+
$stderr.sync = true
|
60
|
+
else
|
61
|
+
@logger.level = Logger::WARN
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
match(/short\.fortune/, IN::TXT) do |transaction|
|
66
|
+
fortune = `fortune -s`.gsub(/\s+/, ' ').strip
|
67
|
+
|
68
|
+
transaction.respond!(*fortune.chunked, ttl: 0)
|
69
|
+
end
|
70
|
+
|
71
|
+
match(/stats\.fortune/, IN::TXT) do |transaction|
|
72
|
+
$stderr.puts "Sending stats: #{stats.inspect}"
|
73
|
+
transaction.respond!(stats.inspect)
|
74
|
+
end
|
75
|
+
|
76
|
+
match(/([a-f0-9]*)\.fortune/, IN::TXT) do |transaction, match|
|
77
|
+
fortune = cache[match[1]]
|
78
|
+
stats[:requested] += 1
|
79
|
+
|
80
|
+
if fortune
|
81
|
+
transaction.respond!(*fortune.chunked)
|
82
|
+
else
|
83
|
+
transaction.fail!(:NXDomain)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
match(/fortune/, [IN::CNAME, IN::TXT]) do |transaction|
|
88
|
+
fortune = `fortune`.gsub(/\s+/, ' ').strip
|
89
|
+
checksum = Digest::MD5.hexdigest(fortune)
|
90
|
+
cache[checksum] = fortune
|
91
|
+
|
92
|
+
answer_txt = "Text Size: #{fortune.size} Byte Size: #{fortune.bytesize}"
|
93
|
+
transaction.respond!(answer_txt, resource_class: IN::TXT, ttl: 0)
|
94
|
+
answer_cname = Name.create(checksum + '.fortune')
|
95
|
+
transaction.respond!(answer_cname, resource_class: IN::CNAME, ttl: 0)
|
96
|
+
end
|
97
|
+
|
98
|
+
# Default DNS handler
|
99
|
+
otherwise do |transaction|
|
100
|
+
transaction.fail!(:NXDomain)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
FortuneDNS.daemonize
|
@@ -0,0 +1,117 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'geoip'
|
24
|
+
|
25
|
+
require 'process/daemon'
|
26
|
+
|
27
|
+
require 'rubydns'
|
28
|
+
require 'rubydns/system'
|
29
|
+
|
30
|
+
INTERFACES = [
|
31
|
+
[:udp, '0.0.0.0', 5300]
|
32
|
+
]
|
33
|
+
|
34
|
+
# Path to the GeoIP file downloaded from
|
35
|
+
# http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
|
36
|
+
# If you have renamed the ungzipped file, or have placed it somewhere other than
|
37
|
+
# the repository root directory you will need to update this path.
|
38
|
+
PATH_TO_GEOIP_DAT_FILE =
|
39
|
+
File.expand_path('../GeoIP.dat', File.dirname(__FILE__))
|
40
|
+
|
41
|
+
# A sample DNS daemon that demonstrates how to use RubyDNS to build responses
|
42
|
+
# that vary based on the geolocation of the requesting peer. Clients of
|
43
|
+
# this server who request A records will get an answer IP address based
|
44
|
+
# on the continent of the client IP address.
|
45
|
+
#
|
46
|
+
# Please note that use of this example requires that the peer have a public
|
47
|
+
# IP address. IP addresses on private networks or the localhost IP (127.0.0.1)
|
48
|
+
# cannot be resolved to a location, and so will always yield the unknown result.
|
49
|
+
# This daemon requires the file downloaded from
|
50
|
+
# http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
|
51
|
+
# For more information, please see http://www.maxmind.com/en/geolite and
|
52
|
+
# http://geoip.rubyforge.org
|
53
|
+
class GeoIPDNS < Process::Daemon
|
54
|
+
GEO = GeoIP.new(PATH_TO_GEOIP_DAT_FILE)
|
55
|
+
|
56
|
+
Name = Resolv::DNS::Name
|
57
|
+
IN = Resolv::DNS::Resource::IN
|
58
|
+
|
59
|
+
def startup
|
60
|
+
RubyDNS.run_server(listen: INTERFACES) do
|
61
|
+
match(//, IN::A) do |transaction|
|
62
|
+
logger.debug 'In block'
|
63
|
+
|
64
|
+
# The IP Address of the peer is stored in the transaction options
|
65
|
+
# with the key :peer
|
66
|
+
ip_address = transaction.options[:peer]
|
67
|
+
logger.debug "Looking up geographic information for peer #{ip_address}"
|
68
|
+
location = GeoIPDNS.ip_to_location(ip_address)
|
69
|
+
|
70
|
+
if location
|
71
|
+
logger.debug "Found location #{location} for #{ip_address}"
|
72
|
+
else
|
73
|
+
logger.debug "Could not resolve location for #{ip_address}"
|
74
|
+
end
|
75
|
+
|
76
|
+
code = location ? location.continent_code : nil
|
77
|
+
answer = GeoIPDNS.answer_for_continent_code(code)
|
78
|
+
logger.debug "Answer is #{answer}"
|
79
|
+
transaction.respond!(answer)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Default DNS handler
|
83
|
+
otherwise do |transaction|
|
84
|
+
logger.debug 'In otherwise'
|
85
|
+
transaction.passthrough!(GeoIPDNS.fallback_resolver)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.fallback_resolver
|
91
|
+
@resolver ||= RubyDNS::Resolver.new(RubyDNS::System.nameservers)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Maps each continent code to a fixed IP address for the response.
|
95
|
+
# A simple mapper to demonstrate the behavior.
|
96
|
+
def self.answer_for_continent_code(code)
|
97
|
+
case code
|
98
|
+
when 'AF' then '1.1.1.1'
|
99
|
+
when 'AN' then '1.1.2.1'
|
100
|
+
when 'AS' then '1.1.3.1'
|
101
|
+
when 'EU' then '1.1.4.1'
|
102
|
+
when 'NA' then '1.1.5.1'
|
103
|
+
when 'OC' then '1.1.6.1'
|
104
|
+
when 'SA' then '1.1.7.1'
|
105
|
+
else '1.1.8.1'
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Finds the continent code for the specified IP address.
|
110
|
+
# Returns nil if the IP address cannot be mapped to a location.
|
111
|
+
def self.ip_to_location(ip_address)
|
112
|
+
return nil unless ip_address
|
113
|
+
GEO.country(ip_address)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
GeoIPDNS.daemonize
|
@@ -0,0 +1,120 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
# Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
5
|
+
#
|
6
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
# of this software and associated documentation files (the "Software"), to deal
|
8
|
+
# in the Software without restriction, including without limitation the rights
|
9
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
10
|
+
# copies of the Software, and to permit persons to whom the Software is
|
11
|
+
# furnished to do so, subject to the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be included in
|
14
|
+
# all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
+
# THE SOFTWARE.
|
23
|
+
|
24
|
+
require 'rubydns'
|
25
|
+
require 'rubydns/extensions/string'
|
26
|
+
|
27
|
+
require 'process/daemon'
|
28
|
+
require 'process/daemon/privileges'
|
29
|
+
|
30
|
+
require 'cgi'
|
31
|
+
require 'nokogiri'
|
32
|
+
require 'json'
|
33
|
+
|
34
|
+
require 'digest/md5'
|
35
|
+
|
36
|
+
# You might need to change the user name "daemon". This can be a user name
|
37
|
+
# or a user id.
|
38
|
+
RUN_AS = 'daemon'
|
39
|
+
|
40
|
+
if Process::Daemon::Privileges.current_user != 'root'
|
41
|
+
$stderr.puts 'Sorry, this command needs to be run as root!'
|
42
|
+
exit 1
|
43
|
+
end
|
44
|
+
|
45
|
+
require 'http'
|
46
|
+
|
47
|
+
# Celluloid::IO fetcher to retrieve URLs.
|
48
|
+
class HttpFetcher
|
49
|
+
include Celluloid::IO
|
50
|
+
|
51
|
+
def get(url)
|
52
|
+
# Note: For SSL support specify:
|
53
|
+
# ssl_socket_class: Celluloid::IO::SSLSocket
|
54
|
+
HTTP.get(url, socket_class: Celluloid::IO::TCPSocket)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Encapsulates the logic for fetching information from Wikipedia.
|
59
|
+
module Wikipedia
|
60
|
+
def self.summary_url(title)
|
61
|
+
"http://en.wikipedia.org/w/api.php?action=parse&page=#{CGI.escape title}&prop=text§ion=0&format=json"
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.extract_summary(json_text)
|
65
|
+
document = JSON.parse(json_text)
|
66
|
+
return Nokogiri::HTML(document['parse']['text']['*']).css('p')[0].text
|
67
|
+
rescue
|
68
|
+
return 'Invalid Article.'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# A DNS server that queries Wikipedia and returns summaries for
|
73
|
+
# specifically crafted queries.
|
74
|
+
class WikipediaDNS < Process::Daemon
|
75
|
+
Name = Resolv::DNS::Name
|
76
|
+
IN = Resolv::DNS::Resource::IN
|
77
|
+
|
78
|
+
def startup
|
79
|
+
# Don't buffer output (for debug purposes)
|
80
|
+
$stderr.sync = true
|
81
|
+
|
82
|
+
stats = { requested: 0 }
|
83
|
+
|
84
|
+
fetcher = HttpFetcher.new
|
85
|
+
|
86
|
+
# Start the RubyDNS server
|
87
|
+
RubyDNS.run_server do
|
88
|
+
on(:start) do
|
89
|
+
Process::Daemon::Privileges.change_user(RUN_AS)
|
90
|
+
if ARGV.include?('--debug')
|
91
|
+
@logger.level = Logger::DEBUG
|
92
|
+
else
|
93
|
+
@logger.level = Logger::WARN
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
match(/stats\.wikipedia/, IN::TXT) do |transaction|
|
98
|
+
transaction.respond!(*stats.inspect.chunked)
|
99
|
+
end
|
100
|
+
|
101
|
+
match(/(.+)\.wikipedia/, IN::TXT) do |transaction, match_data|
|
102
|
+
title = match_data[1]
|
103
|
+
stats[:requested] += 1
|
104
|
+
|
105
|
+
response = fetcher.get(Wikipedia.summary_url(title))
|
106
|
+
|
107
|
+
summary =
|
108
|
+
Wikipedia.extract_summary(response).force_encoding('ASCII-8BIT')
|
109
|
+
transaction.respond!(*summary.chunked)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Default DNS handler
|
113
|
+
otherwise do |transaction|
|
114
|
+
transaction.fail!(:NXDomain)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
WikipediaDNS.daemonize
|
data/lib/rubydns.rb
CHANGED
@@ -29,21 +29,21 @@ require_relative 'rubydns/logger'
|
|
29
29
|
module RubyDNS
|
30
30
|
# Run a server with the given rules.
|
31
31
|
def self.run_server (options = {}, &block)
|
32
|
-
|
32
|
+
supervisor_class = options[:supervisor_class] || RuleBasedServer
|
33
33
|
|
34
|
-
supervisor.
|
34
|
+
supervisor = supervisor_class.supervise(options, &block)
|
35
35
|
|
36
|
+
supervisor.actors.first.run
|
36
37
|
if options[:asynchronous]
|
37
38
|
return supervisor
|
38
39
|
else
|
39
40
|
read, write = IO.pipe
|
40
|
-
|
41
|
+
|
41
42
|
trap(:INT) {
|
42
43
|
write.puts
|
43
44
|
}
|
44
|
-
|
45
|
-
IO.select([read])
|
46
45
|
|
46
|
+
IO.select([read])
|
47
47
|
supervisor.terminate
|
48
48
|
end
|
49
49
|
end
|
data/lib/rubydns/resolver.rb
CHANGED
@@ -95,6 +95,9 @@ module RubyDNS
|
|
95
95
|
begin
|
96
96
|
response = nil
|
97
97
|
|
98
|
+
# This may be causing a problem, perhaps try:
|
99
|
+
# after(timeout) { socket.close }
|
100
|
+
# https://github.com/celluloid/celluloid-io/issues/121
|
98
101
|
timeout(request_timeout) do
|
99
102
|
response = try_server(request, server)
|
100
103
|
end
|
@@ -165,6 +168,8 @@ module RubyDNS
|
|
165
168
|
begin
|
166
169
|
socket = TCPSocket.new(host, port)
|
167
170
|
rescue Errno::EALREADY
|
171
|
+
# This is a hack to work around faulty behaviour in celluloid-io:
|
172
|
+
# https://github.com/celluloid/celluloid/issues/436
|
168
173
|
raise IOError.new("Could not connect to remote host!")
|
169
174
|
end
|
170
175
|
|
data/lib/rubydns/version.rb
CHANGED
data/rubydns.gemspec
CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |spec|
|
|
15
15
|
a remote DNS server or fetched from a local cache, depending on requirements.
|
16
16
|
|
17
17
|
In addition, RubyDNS includes a high-performance asynchronous DNS resolver
|
18
|
-
built on top of
|
18
|
+
built on top of Celluloid. This module can be used by itself in client
|
19
19
|
applications without using the full RubyDNS server stack.
|
20
20
|
EOF
|
21
21
|
spec.summary = "An easy to use DNS server and resolver for Ruby."
|
@@ -36,6 +36,6 @@ Gem::Specification.new do |spec|
|
|
36
36
|
|
37
37
|
spec.add_development_dependency "bundler", "~> 1.3"
|
38
38
|
spec.add_development_dependency "process-daemon", "~> 0.5.5"
|
39
|
-
spec.add_development_dependency "rspec", "~> 3.
|
39
|
+
spec.add_development_dependency "rspec", "~> 3.1.0"
|
40
40
|
spec.add_development_dependency "rake"
|
41
41
|
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'rubydns'
|
24
|
+
|
25
|
+
module RubyDNS::CelluloidBugSpec
|
26
|
+
describe RubyDNS::Resolver do
|
27
|
+
context 'benchmark' do
|
28
|
+
domains = %W(
|
29
|
+
Facebook.com
|
30
|
+
Twitter.com
|
31
|
+
Google.com
|
32
|
+
Youtube.com
|
33
|
+
Wordpress.org
|
34
|
+
Adobe.com
|
35
|
+
Blogspot.com
|
36
|
+
Wikipedia.org
|
37
|
+
Linkedin.com
|
38
|
+
Wordpress.com
|
39
|
+
Yahoo.com
|
40
|
+
Amazon.com
|
41
|
+
Flickr.com
|
42
|
+
Pinterest.com
|
43
|
+
Tumblr.com
|
44
|
+
W3.org
|
45
|
+
Apple.com
|
46
|
+
Myspace.com
|
47
|
+
Vimeo.com
|
48
|
+
Microsoft.com
|
49
|
+
Youtu.be
|
50
|
+
Qq.com
|
51
|
+
Digg.com
|
52
|
+
Baidu.com
|
53
|
+
Stumbleupon.com
|
54
|
+
Addthis.com
|
55
|
+
Statcounter.com
|
56
|
+
Feedburner.com
|
57
|
+
TradeMe.co.nz
|
58
|
+
Delicious.com
|
59
|
+
Nytimes.com
|
60
|
+
Reddit.com
|
61
|
+
Weebly.com
|
62
|
+
Bbc.co.uk
|
63
|
+
Blogger.com
|
64
|
+
Msn.com
|
65
|
+
Macromedia.com
|
66
|
+
Goo.gl
|
67
|
+
Instagram.com
|
68
|
+
Gov.uk
|
69
|
+
Icio.us
|
70
|
+
Yandex.ru
|
71
|
+
Cnn.com
|
72
|
+
Webs.com
|
73
|
+
Google.de
|
74
|
+
T.co
|
75
|
+
Livejournal.com
|
76
|
+
Imdb.com
|
77
|
+
Mail.ru
|
78
|
+
Jimdo.com
|
79
|
+
)
|
80
|
+
|
81
|
+
it 'should be faster than native resolver' do
|
82
|
+
Celluloid.logger.level = Logger::ERROR
|
83
|
+
|
84
|
+
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]], timeout: 0.1)
|
85
|
+
|
86
|
+
futures = domains.map { |domain| resolver.future.addresses_for(domain) }
|
87
|
+
|
88
|
+
futures.map { |future| future.value }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
require 'rubydns'
|
24
|
+
require 'rubydns/extensions/string'
|
25
|
+
|
26
|
+
module RubyDNS::InjectedSupervisorSpec
|
27
|
+
class TestServer < RubyDNS::RuleBasedServer
|
28
|
+
def test_message
|
29
|
+
'Testing...'
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
SERVER_PORTS = [[:udp, '127.0.0.1', 5520]]
|
34
|
+
IN = Resolv::DNS::Resource::IN
|
35
|
+
|
36
|
+
describe "RubyDNS Injected Supervisor" do
|
37
|
+
before(:all) do
|
38
|
+
Celluloid.shutdown
|
39
|
+
Celluloid.boot
|
40
|
+
|
41
|
+
# Start the RubyDNS server
|
42
|
+
RubyDNS::run_server(listen: SERVER_PORTS, supervisor_class: TestServer, asynchronous: true) do
|
43
|
+
match("test_message", IN::TXT) do |transaction|
|
44
|
+
transaction.respond!(*test_message.chunked)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Default DNS handler
|
48
|
+
otherwise do |transaction|
|
49
|
+
transaction.fail!(:NXDomain)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should use the injected class" do
|
55
|
+
resolver = RubyDNS::Resolver.new(SERVER_PORTS)
|
56
|
+
response = resolver.query("test_message", IN::TXT)
|
57
|
+
text = response.answer.first
|
58
|
+
expect(text[2].strings.join).to be == 'Testing...'
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubydns
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 3.
|
89
|
+
version: 3.1.0
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 3.
|
96
|
+
version: 3.1.0
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rake
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,7 +113,7 @@ description: "\t\tRubyDNS is a high-performance DNS server which can be easily i
|
|
113
113
|
pattern matching. Results can be hard-coded, computed, fetched from\n\t\ta remote
|
114
114
|
DNS server or fetched from a local cache, depending on requirements.\n\n\t\tIn addition,
|
115
115
|
RubyDNS includes a high-performance asynchronous DNS resolver\n\t\tbuilt on top
|
116
|
-
of
|
116
|
+
of Celluloid. This module can be used by itself in client\n\t\tapplications without
|
117
117
|
using the full RubyDNS server stack.\n"
|
118
118
|
email:
|
119
119
|
- samuel.williams@oriontransfer.co.nz
|
@@ -129,7 +129,12 @@ files:
|
|
129
129
|
- README.md
|
130
130
|
- Rakefile
|
131
131
|
- bin/rubydns-check
|
132
|
-
- examples/
|
132
|
+
- examples/Gemfile
|
133
|
+
- examples/README.md
|
134
|
+
- examples/flakey-dns.rb
|
135
|
+
- examples/fortune-dns.rb
|
136
|
+
- examples/geoip-dns.rb
|
137
|
+
- examples/wikipedia-dns.rb
|
133
138
|
- lib/rubydns.rb
|
134
139
|
- lib/rubydns/chunked.rb
|
135
140
|
- lib/rubydns/extensions/resolv.rb
|
@@ -144,8 +149,10 @@ files:
|
|
144
149
|
- lib/rubydns/transport.rb
|
145
150
|
- lib/rubydns/version.rb
|
146
151
|
- rubydns.gemspec
|
152
|
+
- spec/rubydns/celluloid_bug_spec.rb
|
147
153
|
- spec/rubydns/daemon_spec.rb
|
148
154
|
- spec/rubydns/hosts.txt
|
155
|
+
- spec/rubydns/injected_supervisor_spec.rb
|
149
156
|
- spec/rubydns/message_spec.rb
|
150
157
|
- spec/rubydns/passthrough_spec.rb
|
151
158
|
- spec/rubydns/resolver_performance_spec.rb
|
@@ -189,8 +196,10 @@ signing_key:
|
|
189
196
|
specification_version: 4
|
190
197
|
summary: An easy to use DNS server and resolver for Ruby.
|
191
198
|
test_files:
|
199
|
+
- spec/rubydns/celluloid_bug_spec.rb
|
192
200
|
- spec/rubydns/daemon_spec.rb
|
193
201
|
- spec/rubydns/hosts.txt
|
202
|
+
- spec/rubydns/injected_supervisor_spec.rb
|
194
203
|
- spec/rubydns/message_spec.rb
|
195
204
|
- spec/rubydns/passthrough_spec.rb
|
196
205
|
- spec/rubydns/resolver_performance_spec.rb
|