rubydns 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/rubydns/rule.rb +92 -0
- data/lib/rubydns/server.rb +76 -0
- data/lib/rubydns/version.rb +5 -20
- data/lib/rubydns.rb +29 -28
- data/license.md +37 -0
- data/readme.md +33 -0
- data/releases.md +8 -0
- data.tar.gz.sig +0 -0
- metadata +61 -108
- metadata.gz.sig +1 -0
- data/.gitignore +0 -26
- data/.rspec +0 -4
- data/.simplecov +0 -15
- data/.travis.yml +0 -13
- data/.yardopts +0 -1
- data/Gemfile +0 -13
- data/README.md +0 -167
- data/Rakefile +0 -6
- data/bin/rubydns-check +0 -374
- data/examples/Gemfile +0 -9
- data/examples/README.md +0 -137
- data/examples/basic-dns.rb +0 -24
- data/examples/cname.rb +0 -25
- data/examples/flakey-dns.rb +0 -72
- data/examples/fortune-dns.rb +0 -106
- data/examples/geoip-dns.rb +0 -115
- data/examples/simple.rb +0 -25
- data/examples/soa-dns.rb +0 -82
- data/examples/test-dns-1.rb +0 -83
- data/examples/test-dns-2.rb +0 -83
- data/examples/wikipedia-dns.rb +0 -121
- data/lib/rubydns/rule_based_server.rb +0 -180
- data/rubydns.gemspec +0 -28
- data/spec/rubydns/daemon_spec.rb +0 -114
- data/spec/rubydns/hosts.txt +0 -2
- data/spec/rubydns/injected_supervisor_spec.rb +0 -64
- data/spec/rubydns/passthrough_spec.rb +0 -85
- data/spec/rubydns/rules_spec.rb +0 -74
- data/spec/spec_helper.rb +0 -30
data/examples/wikipedia-dns.rb
DELETED
@@ -1,121 +0,0 @@
|
|
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
|
-
|
26
|
-
require 'cgi'
|
27
|
-
require 'json'
|
28
|
-
|
29
|
-
require 'digest/md5'
|
30
|
-
|
31
|
-
require 'async/logger'
|
32
|
-
require 'async/http/client'
|
33
|
-
require 'async/dns/extensions/string'
|
34
|
-
require 'async/http/url_endpoint'
|
35
|
-
|
36
|
-
# Encapsulates the logic for fetching information from Wikipedia.
|
37
|
-
module Wikipedia
|
38
|
-
ENDPOINT = Async::HTTP::URLEndpoint.parse("https://en.wikipedia.org")
|
39
|
-
|
40
|
-
def self.lookup(title, logger: nil)
|
41
|
-
client = Async::HTTP::Client.new([ENDPOINT])
|
42
|
-
url = self.summary_url(title)
|
43
|
-
|
44
|
-
logger&.info "Making request to #{ENDPOINT} for #{url}."
|
45
|
-
response = client.get(url, {'Host' => ENDPOINT.hostname})
|
46
|
-
logger&.info "Got response #{response.inspect}."
|
47
|
-
|
48
|
-
if response.status == 301
|
49
|
-
return lookup(response.headers['HTTP_LOCATION'])
|
50
|
-
else
|
51
|
-
return self.extract_summary(response.body).force_encoding('ASCII-8BIT')
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.summary_url(title)
|
56
|
-
"/api/rest_v1/page/summary/#{CGI.escape title}"
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.extract_summary(json_text)
|
60
|
-
document = JSON.parse(json_text)
|
61
|
-
|
62
|
-
return document['extract']
|
63
|
-
rescue
|
64
|
-
return 'Invalid Article.'
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# A DNS server that queries Wikipedia and returns summaries for
|
69
|
-
# specifically crafted queries.
|
70
|
-
class WikipediaDNS
|
71
|
-
Name = Resolv::DNS::Name
|
72
|
-
IN = Resolv::DNS::Resource::IN
|
73
|
-
|
74
|
-
INTERFACES = [
|
75
|
-
[:udp, '::', 5300],
|
76
|
-
[:tcp, '::', 5300],
|
77
|
-
]
|
78
|
-
|
79
|
-
def startup
|
80
|
-
# Don't buffer output (for debug purposes)
|
81
|
-
$stderr.sync = true
|
82
|
-
|
83
|
-
stats = { requested: 0 }
|
84
|
-
|
85
|
-
# Start the RubyDNS server
|
86
|
-
RubyDNS.run_server(INTERFACES) do
|
87
|
-
on(:start) do
|
88
|
-
# Process::Daemon::Privileges.change_user(RUN_AS)
|
89
|
-
|
90
|
-
if ARGV.include?('--debug')
|
91
|
-
@logger.level = Logger::DEBUG
|
92
|
-
else
|
93
|
-
@logger.level = Logger::WARN
|
94
|
-
end
|
95
|
-
|
96
|
-
@logger.info "Starting Wikipedia DNS..."
|
97
|
-
end
|
98
|
-
|
99
|
-
match(/stats\.wikipedia/, IN::TXT) do |transaction|
|
100
|
-
transaction.respond!(*stats.inspect.chunked)
|
101
|
-
end
|
102
|
-
|
103
|
-
match(/(.+)\.wikipedia/, IN::TXT) do |transaction, match_data|
|
104
|
-
title = match_data[1]
|
105
|
-
stats[:requested] += 1
|
106
|
-
|
107
|
-
summary = Wikipedia.lookup(title, logger: @logger)
|
108
|
-
|
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
|
-
wikipedia_dns = WikipediaDNS.new
|
121
|
-
wikipedia_dns.startup
|
@@ -1,180 +0,0 @@
|
|
1
|
-
# Copyright, 2009, 2012, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
2
|
-
#
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
-
# of this software and associated documentation files (the "Software"), to deal
|
5
|
-
# in the Software without restriction, including without limitation the rights
|
6
|
-
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
-
# copies of the Software, and to permit persons to whom the Software is
|
8
|
-
# furnished to do so, subject to the following conditions:
|
9
|
-
#
|
10
|
-
# The above copyright notice and this permission notice shall be included in
|
11
|
-
# all copies or substantial portions of the Software.
|
12
|
-
#
|
13
|
-
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
-
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
-
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
-
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
-
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
-
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
# THE SOFTWARE.
|
20
|
-
|
21
|
-
require 'async/dns/server'
|
22
|
-
|
23
|
-
module RubyDNS
|
24
|
-
# Provides the core of the RubyDNS domain-specific language (DSL). It contains a list of rules which are used to match against incoming DNS questions. These rules are used to generate responses which are either DNS resource records or failures.
|
25
|
-
class RuleBasedServer < Async::DNS::Server
|
26
|
-
# Represents a single rule in the server.
|
27
|
-
class Rule
|
28
|
-
def initialize(pattern, callback)
|
29
|
-
@pattern = pattern
|
30
|
-
@callback = callback
|
31
|
-
end
|
32
|
-
|
33
|
-
# Returns true if the name and resource_class are sufficient:
|
34
|
-
def match(name, resource_class)
|
35
|
-
# If the pattern doesn't specify any resource classes, we implicitly pass this test:
|
36
|
-
return true if @pattern.size < 2
|
37
|
-
|
38
|
-
# Otherwise, we try to match against some specific resource classes:
|
39
|
-
if Class === @pattern[1]
|
40
|
-
@pattern[1] == resource_class
|
41
|
-
else
|
42
|
-
@pattern[1].include?(resource_class) rescue false
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Invoke the rule, if it matches the incoming request, it is evaluated and returns `true`, otherwise returns `false`.
|
47
|
-
def call(server, name, resource_class, transaction)
|
48
|
-
unless match(name, resource_class)
|
49
|
-
server.logger.debug "<#{transaction.query.id}> Resource class #{resource_class} failed to match #{@pattern[1].inspect}!"
|
50
|
-
|
51
|
-
return false
|
52
|
-
end
|
53
|
-
|
54
|
-
# Does this rule match against the supplied name?
|
55
|
-
case @pattern[0]
|
56
|
-
when Regexp
|
57
|
-
match_data = @pattern[0].match(name)
|
58
|
-
|
59
|
-
if match_data
|
60
|
-
server.logger.debug "<#{transaction.query.id}> Regexp pattern matched with #{match_data.inspect}."
|
61
|
-
|
62
|
-
@callback[transaction, match_data]
|
63
|
-
|
64
|
-
return true
|
65
|
-
end
|
66
|
-
when String
|
67
|
-
if @pattern[0] == name
|
68
|
-
server.logger.debug "<#{transaction.query.id}> String pattern matched."
|
69
|
-
|
70
|
-
@callback[transaction]
|
71
|
-
|
72
|
-
return true
|
73
|
-
end
|
74
|
-
else
|
75
|
-
if (@pattern[0].call(name, resource_class) rescue false)
|
76
|
-
server.logger.debug "<#{transaction.query.id}> Callable pattern matched."
|
77
|
-
|
78
|
-
@callback[transaction]
|
79
|
-
|
80
|
-
return true
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
server.logger.debug "<#{transaction.query.id}> No pattern matched."
|
85
|
-
|
86
|
-
# We failed to match the pattern.
|
87
|
-
return false
|
88
|
-
end
|
89
|
-
|
90
|
-
def to_s
|
91
|
-
@pattern.inspect
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
# Instantiate a server with a block
|
96
|
-
#
|
97
|
-
# server = Server.new do
|
98
|
-
# match(/server.mydomain.com/, IN::A) do |transaction|
|
99
|
-
# transaction.respond!("1.2.3.4")
|
100
|
-
# end
|
101
|
-
# end
|
102
|
-
#
|
103
|
-
def initialize(*args, &block)
|
104
|
-
super(*args)
|
105
|
-
|
106
|
-
@events = {}
|
107
|
-
@rules = []
|
108
|
-
@otherwise = nil
|
109
|
-
|
110
|
-
if block_given?
|
111
|
-
instance_eval(&block)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
attr_accessor :logger
|
116
|
-
|
117
|
-
# This function connects a pattern with a block. A pattern is either a String or a Regex instance. Optionally, a second argument can be provided which is either a String, Symbol or Array of resource record types which the rule matches against.
|
118
|
-
#
|
119
|
-
# match("www.google.com")
|
120
|
-
# match("gmail.com", IN::MX)
|
121
|
-
# match(/g?mail.(com|org|net)/, [IN::MX, IN::A])
|
122
|
-
#
|
123
|
-
def match(*pattern, &block)
|
124
|
-
@rules << Rule.new(pattern, block)
|
125
|
-
end
|
126
|
-
|
127
|
-
# Register a named event which may be invoked later using #fire
|
128
|
-
#
|
129
|
-
# on(:start) do |server|
|
130
|
-
# Process::Daemon::Permissions.change_user(RUN_AS)
|
131
|
-
# end
|
132
|
-
def on(event_name, &block)
|
133
|
-
@events[event_name] = block
|
134
|
-
end
|
135
|
-
|
136
|
-
# Fire the named event, which must have been registered using on.
|
137
|
-
def fire(event_name)
|
138
|
-
callback = @events[event_name]
|
139
|
-
|
140
|
-
if callback
|
141
|
-
callback.call(self)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
# Specify a default block to execute if all other rules fail to match. This block is typially used to pass the request on to another server (i.e. recursive request).
|
146
|
-
#
|
147
|
-
# otherwise do |transaction|
|
148
|
-
# transaction.passthrough!($R)
|
149
|
-
# end
|
150
|
-
#
|
151
|
-
def otherwise(&block)
|
152
|
-
@otherwise = block
|
153
|
-
end
|
154
|
-
|
155
|
-
# If you match a rule, but decide within the rule that it isn't the correct one to use, you can call `next!` to evaluate the next rule - in other words, to continue falling down through the list of rules.
|
156
|
-
def next!
|
157
|
-
throw :next
|
158
|
-
end
|
159
|
-
|
160
|
-
# Give a name and a record type, try to match a rule and use it for processing the given arguments.
|
161
|
-
def process(name, resource_class, transaction)
|
162
|
-
@logger.debug {"<#{transaction.query.id}> Searching for #{name} #{resource_class.name}"}
|
163
|
-
|
164
|
-
@rules.each do |rule|
|
165
|
-
@logger.debug {"<#{transaction.query.id}> Checking rule #{rule}..."}
|
166
|
-
|
167
|
-
catch (:next) do
|
168
|
-
# If the rule returns true, we assume that it was successful and no further rules need to be evaluated.
|
169
|
-
return if rule.call(self, name, resource_class, transaction)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
if @otherwise
|
174
|
-
@otherwise.call(transaction)
|
175
|
-
else
|
176
|
-
@logger.warn "<#{transaction.query.id}> Failed to handle #{name} #{resource_class.name}!"
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
180
|
-
end
|
data/rubydns.gemspec
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
|
2
|
-
require_relative 'lib/rubydns/version'
|
3
|
-
|
4
|
-
Gem::Specification.new do |spec|
|
5
|
-
spec.name = "rubydns"
|
6
|
-
spec.version = RubyDNS::VERSION
|
7
|
-
spec.authors = ["Samuel Williams"]
|
8
|
-
spec.email = ["samuel.williams@oriontransfer.co.nz"]
|
9
|
-
spec.description = <<-EOF
|
10
|
-
RubyDNS provides a rule-based DSL for implementing DNS servers, built on top of `Async::DNS`.
|
11
|
-
EOF
|
12
|
-
spec.summary = "An easy to use DNS server and resolver for Ruby."
|
13
|
-
spec.homepage = "https://github.com/socketry/rubydns"
|
14
|
-
spec.license = "MIT"
|
15
|
-
|
16
|
-
spec.files = `git ls-files`.split($/)
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
spec.has_rdoc = "yard"
|
21
|
-
|
22
|
-
spec.add_dependency("async-dns", "~> 1.0")
|
23
|
-
spec.add_development_dependency("async-rspec", "~> 1.0")
|
24
|
-
|
25
|
-
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
-
spec.add_development_dependency "rspec", "~> 3.4"
|
27
|
-
spec.add_development_dependency "rake"
|
28
|
-
end
|
data/spec/rubydns/daemon_spec.rb
DELETED
@@ -1,114 +0,0 @@
|
|
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 'process/daemon'
|
25
|
-
|
26
|
-
class BasicTestServer < Process::Daemon
|
27
|
-
SERVER_PORTS = [[:udp, '127.0.0.1', 5350], [:tcp, '127.0.0.1', 5350]]
|
28
|
-
|
29
|
-
IN = Resolv::DNS::Resource::IN
|
30
|
-
|
31
|
-
def working_directory
|
32
|
-
File.expand_path("../tmp", __FILE__)
|
33
|
-
end
|
34
|
-
|
35
|
-
def reactor
|
36
|
-
Async::Reactor.new
|
37
|
-
end
|
38
|
-
|
39
|
-
def startup
|
40
|
-
reactor.run do
|
41
|
-
RubyDNS::run_server(SERVER_PORTS) do
|
42
|
-
match("test.local", IN::A) do |transaction|
|
43
|
-
transaction.respond!("192.168.1.1")
|
44
|
-
end
|
45
|
-
|
46
|
-
match(/foo.*/, IN::A) do |transaction|
|
47
|
-
transaction.respond!("192.168.1.2")
|
48
|
-
end
|
49
|
-
|
50
|
-
match(/peername/, IN::A) do |transaction|
|
51
|
-
transaction.respond!(transaction[:remote_address].ip_address)
|
52
|
-
end
|
53
|
-
|
54
|
-
# Default DNS handler
|
55
|
-
otherwise do |transaction|
|
56
|
-
transaction.fail!(:NXDomain)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def shutdown
|
63
|
-
@reactor.stop
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
describe "RubyDNS Daemonized Server" do
|
68
|
-
include_context Async::RSpec::Reactor
|
69
|
-
|
70
|
-
before(:all) do
|
71
|
-
# BasicTestServer.controller output: $stderr
|
72
|
-
BasicTestServer.start
|
73
|
-
end
|
74
|
-
|
75
|
-
after(:all) do
|
76
|
-
BasicTestServer.stop
|
77
|
-
end
|
78
|
-
|
79
|
-
it "should resolve local domain correctly" do
|
80
|
-
expect(BasicTestServer.status).to be == :running
|
81
|
-
|
82
|
-
resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
|
83
|
-
|
84
|
-
response = resolver.query("test.local")
|
85
|
-
|
86
|
-
answer = response.answer.first
|
87
|
-
|
88
|
-
expect(answer[0].to_s).to be == "test.local."
|
89
|
-
expect(answer[2].address.to_s).to be == "192.168.1.1"
|
90
|
-
end
|
91
|
-
|
92
|
-
it "should pattern match correctly" do
|
93
|
-
expect(BasicTestServer.status).to be == :running
|
94
|
-
|
95
|
-
resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
|
96
|
-
|
97
|
-
response = resolver.query("foobar")
|
98
|
-
answer = response.answer.first
|
99
|
-
|
100
|
-
expect(answer[0]).to be == resolver.fully_qualified_name("foobar")
|
101
|
-
expect(answer[2].address.to_s).to be == "192.168.1.2"
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should give peer ip address" do
|
105
|
-
expect(BasicTestServer.status).to be == :running
|
106
|
-
|
107
|
-
resolver = RubyDNS::Resolver.new(BasicTestServer::SERVER_PORTS)
|
108
|
-
|
109
|
-
response = resolver.query("peername")
|
110
|
-
answer = response.answer.first
|
111
|
-
|
112
|
-
expect(answer[2].address.to_s).to be == "127.0.0.1"
|
113
|
-
end
|
114
|
-
end
|
data/spec/rubydns/hosts.txt
DELETED
@@ -1,64 +0,0 @@
|
|
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 'async/dns/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::run_server(server_class: ...)" do
|
37
|
-
include_context Async::RSpec::Reactor
|
38
|
-
|
39
|
-
let(:server) do
|
40
|
-
# Start the RubyDNS server
|
41
|
-
RubyDNS::run_server(SERVER_PORTS, server_class: TestServer) do
|
42
|
-
match("test_message", IN::TXT) do |transaction|
|
43
|
-
transaction.respond!(*test_message.chunked)
|
44
|
-
end
|
45
|
-
|
46
|
-
# Default DNS handler
|
47
|
-
otherwise do |transaction|
|
48
|
-
transaction.fail!(:NXDomain)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should use the injected class" do
|
54
|
-
task = server
|
55
|
-
|
56
|
-
resolver = RubyDNS::Resolver.new(SERVER_PORTS)
|
57
|
-
response = resolver.query("test_message", IN::TXT)
|
58
|
-
text = response.answer.first
|
59
|
-
expect(text[2].strings.join).to be == 'Testing...'
|
60
|
-
|
61
|
-
task.stop
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
@@ -1,85 +0,0 @@
|
|
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::PassthroughSpec
|
26
|
-
SERVER_PORTS = [[:udp, '127.0.0.1', 5340], [:tcp, '127.0.0.1', 5340]]
|
27
|
-
Name = Resolv::DNS::Name
|
28
|
-
IN = Resolv::DNS::Resource::IN
|
29
|
-
|
30
|
-
describe "RubyDNS Passthrough Server" do
|
31
|
-
include_context Async::RSpec::Reactor
|
32
|
-
|
33
|
-
def run_server
|
34
|
-
task = RubyDNS::run_server(listen: SERVER_PORTS) do
|
35
|
-
resolver = RubyDNS::Resolver.new([[:udp, "8.8.8.8", 53], [:tcp, "8.8.8.8", 53]])
|
36
|
-
|
37
|
-
match(/.*\.com/, IN::A) do |transaction|
|
38
|
-
transaction.passthrough!(resolver)
|
39
|
-
end
|
40
|
-
|
41
|
-
match(/a-(.*\.org)/) do |transaction, match_data|
|
42
|
-
transaction.passthrough!(resolver, :name => match_data[1])
|
43
|
-
end
|
44
|
-
|
45
|
-
# Default DNS handler
|
46
|
-
otherwise do |transaction|
|
47
|
-
transaction.fail!(:NXDomain)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
yield
|
52
|
-
|
53
|
-
ensure
|
54
|
-
task.stop
|
55
|
-
end
|
56
|
-
|
57
|
-
it "should resolve domain correctly" do
|
58
|
-
run_server do
|
59
|
-
resolver = RubyDNS::Resolver.new(SERVER_PORTS, timeout: 1)
|
60
|
-
|
61
|
-
response = resolver.query("google.com")
|
62
|
-
expect(response.ra).to be == 1
|
63
|
-
|
64
|
-
answer = response.answer.first
|
65
|
-
expect(answer).not_to be == nil
|
66
|
-
expect(answer.count).to be > 0
|
67
|
-
|
68
|
-
addresses = answer.select {|record| record.kind_of? Resolv::DNS::Resource::IN::A}
|
69
|
-
expect(addresses.size).to be > 0
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should resolve prefixed domain correctly" do
|
74
|
-
run_server do
|
75
|
-
resolver = RubyDNS::Resolver.new(SERVER_PORTS)
|
76
|
-
|
77
|
-
response = resolver.query("a-slashdot.org")
|
78
|
-
answer = response.answer.first
|
79
|
-
|
80
|
-
expect(answer).not_to be == nil
|
81
|
-
expect(answer.count).to be > 0
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
data/spec/rubydns/rules_spec.rb
DELETED
@@ -1,74 +0,0 @@
|
|
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
|