rubydns 0.8.5 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/Gemfile +0 -4
- data/README.md +16 -8
- data/Rakefile +6 -6
- data/{test/examples → examples}/dropping-dns.rb +0 -0
- data/lib/rubydns/handler.rb +133 -102
- data/lib/rubydns/message.rb +0 -1
- data/lib/rubydns/resolver.rb +135 -187
- data/lib/rubydns/server.rb +92 -86
- data/lib/rubydns/transaction.rb +24 -48
- data/lib/rubydns/{binary_string.rb → transport.rb} +38 -0
- data/lib/rubydns/version.rb +1 -1
- data/lib/rubydns.rb +15 -8
- data/rubydns.gemspec +5 -2
- data/{test/test_daemon.rb → spec/rubydns/daemon_spec.rb} +36 -48
- data/{test → spec/rubydns}/hosts.txt +0 -0
- data/{test/test_rules.rb → spec/rubydns/message_spec.rb} +26 -44
- data/spec/rubydns/passthrough_spec.rb +78 -0
- data/spec/rubydns/resolver_performance_spec.rb +110 -0
- data/spec/rubydns/resolver_spec.rb +144 -0
- data/spec/rubydns/rules_spec.rb +74 -0
- data/{test/performance → spec/rubydns/server}/benchmark.rb +0 -0
- data/{test/performance → spec/rubydns/server}/bind9/generate-local.rb +0 -0
- data/{test/performance → spec/rubydns/server}/bind9/local.zone +0 -0
- data/{test/performance → spec/rubydns/server}/bind9/named.conf +0 -0
- data/spec/rubydns/server/bind9/named.run +0 -0
- data/{test/performance → spec/rubydns/server}/million.rb +1 -3
- data/spec/rubydns/server/rubydns.stackprof +0 -0
- data/spec/rubydns/server_performance_spec.rb +136 -0
- data/spec/rubydns/slow_server_spec.rb +89 -0
- data/spec/rubydns/socket_spec.rb +77 -0
- data/{test/test_system.rb → spec/rubydns/system_spec.rb} +28 -22
- data/spec/rubydns/transaction_spec.rb +64 -0
- data/{test/test_truncation.rb → spec/rubydns/truncation_spec.rb} +22 -48
- metadata +91 -54
- data/test/examples/fortune-dns.rb +0 -107
- data/test/examples/geoip-dns.rb +0 -76
- data/test/examples/soa-dns.rb +0 -82
- data/test/examples/test-dns-1.rb +0 -77
- data/test/examples/test-dns-2.rb +0 -83
- data/test/examples/wikipedia-dns.rb +0 -112
- data/test/test_message.rb +0 -65
- data/test/test_passthrough.rb +0 -120
- data/test/test_resolver.rb +0 -106
- data/test/test_resolver_performance.rb +0 -123
- data/test/test_server_performance.rb +0 -134
- data/test/test_slow_server.rb +0 -125
@@ -0,0 +1,144 @@
|
|
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::ResolverSpec
|
26
|
+
describe RubyDNS::Resolver do
|
27
|
+
class JunkUDPServer
|
28
|
+
include Celluloid::IO
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
@socket = UDPSocket.new
|
32
|
+
@socket.bind("0.0.0.0", 6060)
|
33
|
+
|
34
|
+
async.run
|
35
|
+
end
|
36
|
+
|
37
|
+
finalizer :shutdown
|
38
|
+
|
39
|
+
def finalize
|
40
|
+
@socket.close if @socket
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
data, (_, port, host) = @socket.recvfrom(1024)
|
45
|
+
|
46
|
+
@socket.send("Foobar", 0, host, port)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class JunkTCPServer
|
51
|
+
include Celluloid::IO
|
52
|
+
|
53
|
+
def initialize
|
54
|
+
@socket = TCPServer.new("0.0.0.0", 6060)
|
55
|
+
|
56
|
+
async.run
|
57
|
+
end
|
58
|
+
|
59
|
+
finalizer :shutdown
|
60
|
+
|
61
|
+
def finalize
|
62
|
+
@socket.close if @socket
|
63
|
+
end
|
64
|
+
|
65
|
+
def run
|
66
|
+
# @logger.debug "Waiting for incoming TCP connections #{@socket.inspect}..."
|
67
|
+
loop { async.handle_connection @socket.accept }
|
68
|
+
end
|
69
|
+
|
70
|
+
def handle_connection(socket)
|
71
|
+
socket.write("\0\0obar")
|
72
|
+
ensure
|
73
|
+
socket.close
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
before(:all) do
|
78
|
+
Celluloid.shutdown
|
79
|
+
Celluloid.boot
|
80
|
+
|
81
|
+
JunkUDPServer.supervise
|
82
|
+
JunkTCPServer.supervise
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should result in non-existent domain" do
|
86
|
+
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
|
87
|
+
|
88
|
+
response = resolver.query('foobar.oriontransfer.org')
|
89
|
+
|
90
|
+
expect(response.rcode).to be == Resolv::DNS::RCode::NXDomain
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should result in some answers" do
|
94
|
+
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
|
95
|
+
|
96
|
+
response = resolver.query('google.com')
|
97
|
+
|
98
|
+
expect(response.class).to be == RubyDNS::Message
|
99
|
+
expect(response.answer.size).to be > 0
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should return no results" do
|
103
|
+
resolver = RubyDNS::Resolver.new([])
|
104
|
+
|
105
|
+
response = resolver.query('google.com')
|
106
|
+
|
107
|
+
expect(response).to be == nil
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should fail to get addresses" do
|
111
|
+
resolver = RubyDNS::Resolver.new([])
|
112
|
+
|
113
|
+
expect{resolver.addresses_for('google.com')}.to raise_error(RubyDNS::ResolutionFailure)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should fail with decode error from bad udp server" do
|
117
|
+
resolver = RubyDNS::Resolver.new([[:udp, "0.0.0.0", 6060]])
|
118
|
+
|
119
|
+
response = resolver.query('google.com')
|
120
|
+
|
121
|
+
expect(response).to be == nil
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should fail with decode error from bad tcp server" do
|
125
|
+
resolver = RubyDNS::Resolver.new([[:tcp, "0.0.0.0", 6060]])
|
126
|
+
|
127
|
+
response = resolver.query('google.com')
|
128
|
+
|
129
|
+
expect(response).to be == nil
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should return some IPv4 and IPv6 addresses" do
|
133
|
+
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
|
134
|
+
|
135
|
+
addresses = resolver.addresses_for("www.google.com.")
|
136
|
+
|
137
|
+
expect(addresses.size).to be > 0
|
138
|
+
|
139
|
+
addresses.each do |address|
|
140
|
+
expect(address).to be_kind_of(Resolv::IPv4) | be_kind_of(Resolv::IPv6)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,74 @@
|
|
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::RulesSpec
|
26
|
+
describe RubyDNS::RuleBasedServer do
|
27
|
+
IN = Resolv::DNS::Resource::IN
|
28
|
+
|
29
|
+
true_callback = Proc.new { true }
|
30
|
+
|
31
|
+
it "should match string patterns correctly" do
|
32
|
+
server = double(:logger => Logger.new("/dev/null"))
|
33
|
+
transaction = double(:query => Resolv::DNS::Message.new(0))
|
34
|
+
|
35
|
+
rule = RubyDNS::RuleBasedServer::Rule.new(["foobar", IN::A], true_callback)
|
36
|
+
|
37
|
+
expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
|
38
|
+
expect(rule.call(server, "barfoo", IN::A, transaction)).to be == false
|
39
|
+
expect(rule.call(server, "foobar", IN::TXT, transaction)).to be == false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should match regular expression patterns correctly" do
|
43
|
+
server = double(:logger => Logger.new("/dev/null"))
|
44
|
+
transaction = double(:query => Resolv::DNS::Message.new(0))
|
45
|
+
|
46
|
+
rule = RubyDNS::RuleBasedServer::Rule.new([/foo/, IN::A], true_callback)
|
47
|
+
|
48
|
+
expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
|
49
|
+
expect(rule.call(server, "barbaz", IN::A, transaction)).to be == false
|
50
|
+
expect(rule.call(server, "foobar", IN::TXT, transaction)).to be == false
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should match callback patterns correctly" do
|
54
|
+
server = double(:logger => Logger.new("/dev/null"))
|
55
|
+
transaction = double(:query => Resolv::DNS::Message.new(0))
|
56
|
+
|
57
|
+
calls = 0
|
58
|
+
|
59
|
+
callback = Proc.new do |name, resource_class|
|
60
|
+
# A counter used to check the number of times this block was invoked.
|
61
|
+
calls += 1
|
62
|
+
|
63
|
+
name.size == 6
|
64
|
+
end
|
65
|
+
|
66
|
+
rule = RubyDNS::RuleBasedServer::Rule.new([callback], true_callback)
|
67
|
+
|
68
|
+
expect(rule.call(server, "foobar", IN::A, transaction)).to be == true
|
69
|
+
expect(rule.call(server, "foobarbaz", IN::A, transaction)).to be == false
|
70
|
+
|
71
|
+
expect(calls).to be == 2
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -56,8 +56,6 @@ StackProf.run(mode: :cpu, out: 'rubydns.stackprof') do
|
|
56
56
|
otherwise do |transaction|
|
57
57
|
logger.info "Passing DNS request upstream..."
|
58
58
|
transaction.fail!(:NXDomain)
|
59
|
-
|
60
|
-
EventMachine::stop
|
61
59
|
end
|
62
60
|
end
|
63
61
|
end
|
@@ -84,4 +82,4 @@ end
|
|
84
82
|
# ;; SERVER: 127.0.0.1#5300(127.0.0.1)
|
85
83
|
# ;; WHEN: Fri May 16 19:17:48 2014
|
86
84
|
# ;; MSG SIZE rcvd: 47
|
87
|
-
#
|
85
|
+
#
|
Binary file
|
@@ -0,0 +1,136 @@
|
|
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 'benchmark'
|
25
|
+
require 'process/daemon'
|
26
|
+
|
27
|
+
module RubyDNS::ServerPerformanceSpec
|
28
|
+
describe RubyDNS::Server do
|
29
|
+
context 'benchmark' do
|
30
|
+
class ServerPerformanceRubyDNS < Process::Daemon
|
31
|
+
IN = Resolv::DNS::Resource::IN
|
32
|
+
|
33
|
+
def working_directory
|
34
|
+
File.expand_path("../tmp", __FILE__)
|
35
|
+
end
|
36
|
+
|
37
|
+
def startup
|
38
|
+
puts "Booting celluloid..."
|
39
|
+
Celluloid.boot
|
40
|
+
|
41
|
+
million = {}
|
42
|
+
|
43
|
+
puts "Generating domains..."
|
44
|
+
(1..5_000).each do |i|
|
45
|
+
domain = "domain#{i}.local"
|
46
|
+
|
47
|
+
million[domain] = "#{69}.#{(i >> 16)%256}.#{(i >> 8)%256}.#{i%256}"
|
48
|
+
end
|
49
|
+
|
50
|
+
puts "Starting DNS server..."
|
51
|
+
RubyDNS::run_server(:listen => [[:udp, '0.0.0.0', 5300]]) do
|
52
|
+
@logger.level = Logger::WARN
|
53
|
+
|
54
|
+
match(//, IN::A) do |transaction|
|
55
|
+
puts "Responding to #{transaction.name}"
|
56
|
+
transaction.respond!(million[transaction.name])
|
57
|
+
end
|
58
|
+
|
59
|
+
# Default DNS handler
|
60
|
+
otherwise do |transaction|
|
61
|
+
transaction.fail!(:NXDomain)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class ServerPerformanceBind9 < Process::Daemon
|
68
|
+
def working_directory
|
69
|
+
File.expand_path("../server/bind9", __FILE__)
|
70
|
+
end
|
71
|
+
|
72
|
+
def startup
|
73
|
+
exec(self.class.named_executable, "-c", "named.conf", "-f", "-p", "5400", "-g")
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.named_executable
|
77
|
+
# Check if named executable is available:
|
78
|
+
@named ||= `which named`.chomp
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
before do
|
83
|
+
Celluloid.shutdown
|
84
|
+
|
85
|
+
@servers = []
|
86
|
+
@servers << ["RubyDNS::Server", 5300]
|
87
|
+
|
88
|
+
@domains = (1..1000).collect do |i|
|
89
|
+
"domain#{i}.local"
|
90
|
+
end
|
91
|
+
|
92
|
+
ServerPerformanceRubyDNS.start
|
93
|
+
|
94
|
+
unless ServerPerformanceBind9.named_executable.empty?
|
95
|
+
ServerPerformanceBind9.start
|
96
|
+
@servers << ["Bind9", 5400]
|
97
|
+
end
|
98
|
+
|
99
|
+
sleep 2
|
100
|
+
|
101
|
+
Celluloid.boot
|
102
|
+
end
|
103
|
+
|
104
|
+
after do
|
105
|
+
ServerPerformanceRubyDNS.stop
|
106
|
+
|
107
|
+
unless ServerPerformanceBind9.named_executable.empty?
|
108
|
+
ServerPerformanceBind9.stop
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'it takes time' do
|
113
|
+
Celluloid.logger.level = Logger::ERROR
|
114
|
+
|
115
|
+
Benchmark.bm(20) do |x|
|
116
|
+
@servers.each do |name, port|
|
117
|
+
resolver = RubyDNS::Resolver.new([[:udp, '127.0.0.1', port]])
|
118
|
+
|
119
|
+
x.report(name) do
|
120
|
+
# Number of requests remaining since this is an asynchronous event loop:
|
121
|
+
5.times do
|
122
|
+
pending = @domains.size
|
123
|
+
|
124
|
+
futures = @domains.collect{|domain| resolver.future.addresses_for(domain)}
|
125
|
+
|
126
|
+
futures.collect do |future|
|
127
|
+
expect(future.value).to_not be nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,89 @@
|
|
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::SlowServerSpec
|
26
|
+
SERVER_PORTS = [[:udp, '127.0.0.1', 5330], [:tcp, '127.0.0.1', 5330]]
|
27
|
+
IN = Resolv::DNS::Resource::IN
|
28
|
+
|
29
|
+
describe "RubyDNS Slow Server" do
|
30
|
+
before(:all) do
|
31
|
+
Celluloid.shutdown
|
32
|
+
Celluloid.boot
|
33
|
+
|
34
|
+
@server = RubyDNS::run_server(:listen => SERVER_PORTS, asynchronous: true) do
|
35
|
+
match(/\.*.com/, IN::A) do |transaction|
|
36
|
+
sleep 2
|
37
|
+
|
38
|
+
transaction.fail!(:NXDomain)
|
39
|
+
end
|
40
|
+
|
41
|
+
otherwise do |transaction|
|
42
|
+
transaction.fail!(:NXDomain)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "get no answer after 2 seconds" do
|
48
|
+
start_time = Time.now
|
49
|
+
|
50
|
+
resolver = RubyDNS::Resolver.new(SERVER_PORTS, :timeout => 10)
|
51
|
+
|
52
|
+
response = resolver.query("apple.com", IN::A)
|
53
|
+
|
54
|
+
expect(response.answer.length).to be == 0
|
55
|
+
|
56
|
+
end_time = Time.now
|
57
|
+
|
58
|
+
expect(end_time - start_time).to be_within(0.1).of(2.0)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "times out after 1 second" do
|
62
|
+
start_time = Time.now
|
63
|
+
|
64
|
+
resolver = RubyDNS::Resolver.new(SERVER_PORTS, :timeout => 0.5)
|
65
|
+
|
66
|
+
response = resolver.query("apple.com", IN::A)
|
67
|
+
|
68
|
+
expect(response).to be nil
|
69
|
+
|
70
|
+
end_time = Time.now
|
71
|
+
|
72
|
+
expect(end_time - start_time).to be_within(0.1).of(1.0)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "gets no answer immediately" do
|
76
|
+
start_time = Time.now
|
77
|
+
|
78
|
+
resolver = RubyDNS::Resolver.new(SERVER_PORTS, :timeout => 0.5)
|
79
|
+
|
80
|
+
response = resolver.query("oriontransfer.org", IN::A)
|
81
|
+
|
82
|
+
expect(response.answer.length).to be 0
|
83
|
+
|
84
|
+
end_time = Time.now
|
85
|
+
|
86
|
+
expect(end_time - start_time).to be_within(0.1).of(0.0)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright, 2014, 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/system'
|
25
|
+
|
26
|
+
module RubyDNS::SocketSpec
|
27
|
+
IN = Resolv::DNS::Resource::IN
|
28
|
+
|
29
|
+
describe RubyDNS::TCPSocketHandler do
|
30
|
+
before(:all) do
|
31
|
+
Celluloid.shutdown
|
32
|
+
Celluloid.boot
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should create server with existing TCP socket" do
|
36
|
+
socket = TCPServer.new('127.0.0.1', 2002)
|
37
|
+
|
38
|
+
# Start the RubyDNS server
|
39
|
+
@server = RubyDNS::run_server(:listen => [socket], asynchronous: true) do
|
40
|
+
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
|
41
|
+
|
42
|
+
match(/.*\.com/, IN::A) do |transaction|
|
43
|
+
transaction.passthrough!(resolver)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
resolver = RubyDNS::Resolver.new([[:tcp, '127.0.0.1', 2002]])
|
48
|
+
response = resolver.query('google.com')
|
49
|
+
expect(response.class).to be == RubyDNS::Message
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe RubyDNS::UDPSocketHandler do
|
54
|
+
before(:all) do
|
55
|
+
Celluloid.shutdown
|
56
|
+
Celluloid.boot
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should create server with existing UDP socket" do
|
60
|
+
socket = UDPSocket.new
|
61
|
+
socket.bind('127.0.0.1', 2002)
|
62
|
+
|
63
|
+
# Start the RubyDNS server
|
64
|
+
@server = RubyDNS::run_server(:listen => [socket], asynchronous: true) do
|
65
|
+
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
|
66
|
+
|
67
|
+
match(/.*\.com/, IN::A) do |transaction|
|
68
|
+
transaction.passthrough!(resolver)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
resolver = RubyDNS::Resolver.new([[:udp, '127.0.0.1', 2002]])
|
73
|
+
response = resolver.query('google.com')
|
74
|
+
expect(response.class).to be == RubyDNS::Message
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -20,35 +20,41 @@
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
21
|
# THE SOFTWARE.
|
22
22
|
|
23
|
-
require 'minitest/autorun'
|
24
|
-
|
25
23
|
require 'rubydns'
|
26
24
|
require 'rubydns/system'
|
27
25
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
EventMachine::stop
|
39
|
-
end
|
26
|
+
module RubyDNS::SystemSpec
|
27
|
+
describe RubyDNS::System do
|
28
|
+
before(:all) do
|
29
|
+
Celluloid.shutdown
|
30
|
+
Celluloid.boot
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have at least one namesever" do
|
34
|
+
expect(RubyDNS::System::nameservers.length).to be > 0
|
40
35
|
end
|
41
|
-
end
|
42
36
|
|
43
|
-
|
44
|
-
|
37
|
+
it "should respond to query for google.com" do
|
38
|
+
resolver = RubyDNS::Resolver.new(RubyDNS::System::nameservers)
|
45
39
|
|
46
|
-
|
47
|
-
|
48
|
-
|
40
|
+
response = resolver.query('google.com')
|
41
|
+
|
42
|
+
expect(response.class).to be == RubyDNS::Message
|
43
|
+
expect(response.rcode).to be == Resolv::DNS::RCode::NoError
|
49
44
|
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe RubyDNS::System::Hosts do
|
48
|
+
it "should parse the hosts file" do
|
49
|
+
hosts = RubyDNS::System::Hosts.new
|
50
50
|
|
51
|
-
|
52
|
-
|
51
|
+
# Load the test hosts data:
|
52
|
+
File.open(File.expand_path("../hosts.txt", __FILE__)) do |file|
|
53
|
+
hosts.parse_hosts(file)
|
54
|
+
end
|
55
|
+
|
56
|
+
expect(hosts.call('testing')).to be == true
|
57
|
+
expect(hosts['testing']).to be == '1.2.3.4'
|
58
|
+
end
|
53
59
|
end
|
54
60
|
end
|
@@ -0,0 +1,64 @@
|
|
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 'yaml'
|
25
|
+
|
26
|
+
module RubyDNS::TransactionSpec
|
27
|
+
SERVER_PORTS = [[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]]
|
28
|
+
IN = Resolv::DNS::Resource::IN
|
29
|
+
|
30
|
+
describe RubyDNS::Transaction do
|
31
|
+
let(:server) { RubyDNS::Server.new }
|
32
|
+
let(:query) { RubyDNS::Message.new(0) }
|
33
|
+
let(:question) { Resolv::DNS::Name.create("www.google.com") }
|
34
|
+
let(:response) { RubyDNS::Message.new(0) }
|
35
|
+
let(:resolver) { RubyDNS::Resolver.new([[:udp, '8.8.8.8', 53], [:tcp, '8.8.8.8', 53]])}
|
36
|
+
|
37
|
+
it "should append an address" do
|
38
|
+
transaction = RubyDNS::Transaction.new(server, query, question, IN::A, response)
|
39
|
+
|
40
|
+
transaction.respond!("1.2.3.4")
|
41
|
+
|
42
|
+
expect(transaction.response.answer[0][0].to_s).to be == question.to_s
|
43
|
+
expect(transaction.response.answer[0][2].address.to_s).to be == "1.2.3.4"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should passthrough the request" do
|
47
|
+
transaction = RubyDNS::Transaction.new(server, query, question, IN::A, response)
|
48
|
+
|
49
|
+
expect(transaction.response.answer.size).to be 0
|
50
|
+
|
51
|
+
transaction.passthrough!(resolver)
|
52
|
+
|
53
|
+
expect(transaction.response.answer.size).to be > 0
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should fail the request" do
|
57
|
+
transaction = RubyDNS::Transaction.new(server, query, question, IN::A, response)
|
58
|
+
|
59
|
+
transaction.fail! :NXDomain
|
60
|
+
|
61
|
+
expect(transaction.response.rcode).to be Resolv::DNS::RCode::NXDomain
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|