rubydns 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|