dns-check 0.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.
- data/.gitignore +2 -0
- data/Gemfile +2 -0
- data/README.md +64 -0
- data/Rakefile +3 -0
- data/bin/dns-check +18 -0
- data/db/.gitignore +2 -0
- data/dns-check.gemspec +25 -0
- data/lib/dns-check.rb +27 -0
- data/lib/dns-check/cli.rb +99 -0
- data/lib/dns-check/core.rb +101 -0
- data/lib/dns-check/db.rb +66 -0
- data/lib/dns-check/dns.rb +32 -0
- data/lib/dns-check/errors.rb +17 -0
- data/lib/dns-check/ext.rb +31 -0
- data/lib/dns-check/node.rb +55 -0
- data/lib/dns-check/output.rb +43 -0
- data/lib/dns-check/update.rb +80 -0
- data/lib/dns-check/util.rb +266 -0
- data/lib/dns-check/version.rb +5 -0
- metadata +146 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#dns-check
|
2
|
+
|
3
|
+
CLI base DNS check propagation tool
|
4
|
+
|
5
|
+
### Note
|
6
|
+
|
7
|
+
* While the tool works - it was hacked in an hour or so with the only purpose in mind to get some work done. That being said, there are still a couple of TODO/FIXME lurking in the code and likely a couple of refactoring needed... and of course, some test units. I am releasing it in the hope it is useful to someone else.
|
8
|
+
|
9
|
+
* The upstream json feed contains sometimes empty records for city and country - NN is used for specified "No Name"
|
10
|
+
|
11
|
+
## Getting started
|
12
|
+
|
13
|
+
* gem install dns-check
|
14
|
+
* dns-check --update
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
Usage: dns-check [options] [domain]
|
18
|
+
|
19
|
+
Options:
|
20
|
+
-l, --location [name] Location can either be a country or city
|
21
|
+
-t, --timeout [sec] DNS Query timeout (Default: 5s)
|
22
|
+
--records [size] Number of nameservers to select (default: 10)
|
23
|
+
--show-ns Show nameservers
|
24
|
+
--update Perform indice update
|
25
|
+
--debug
|
26
|
+
-v, --version Show version
|
27
|
+
-h, -?, --help Show this message
|
28
|
+
|
29
|
+
### Examples
|
30
|
+
<br>
|
31
|
+
|
32
|
+
$ dns-check google.com --records 5
|
33
|
+
Hong Kong/Central District|74.125.128.100
|
34
|
+
Taiwan/NN|74.125.31.138
|
35
|
+
Saudi Arabia/NN|173.194.35.96
|
36
|
+
Afghanistan/NN|173.194.72.139
|
37
|
+
Guatemala/El Salvador|74.125.137.139
|
38
|
+
|
39
|
+
|
40
|
+
$ dns-check google.com --location Berlin --show-ns<br>
|
41
|
+
Berlin|173.194.70.101|194.77.8.1
|
42
|
+
Berlin|173.194.70.138|alhazred.hsd.de
|
43
|
+
Berlin|173.194.70.113|192.166.192.2
|
44
|
+
|
45
|
+
|
46
|
+
$ dns-check google.com --records 5 --location US --show-ns
|
47
|
+
Longmont|74.125.225.195|209.97.224.3
|
48
|
+
Burlington|74.125.226.228|64.17.101.12
|
49
|
+
Romney|74.125.140.138|resolve01.rmny.wv.frontiernet.net
|
50
|
+
Deerfield Beach|74.125.229.238|216.242.0.15
|
51
|
+
North Attleboro|173.194.34.102|207.180.2.6
|
52
|
+
|
53
|
+
|
54
|
+
$ dns-check google.com --records 5 --location US
|
55
|
+
El Paso|173.194.46.5
|
56
|
+
Atlanta|74.125.228.34
|
57
|
+
Greenville|74.125.227.128
|
58
|
+
Newark|74.125.228.64
|
59
|
+
Baltimore|74.125.228.34
|
60
|
+
|
61
|
+
|
62
|
+
$ dns-check google.com --records 2 --location Atlanta --show-ns
|
63
|
+
Atlanta|173.194.37.67|ns.echina.com
|
64
|
+
Atlanta|74.125.137.100|64.94.1.1
|
data/Rakefile
ADDED
data/bin/dns-check
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#-*- encoding: utf-8 -*-
|
3
|
+
#
|
4
|
+
|
5
|
+
STDOUT.sync = true
|
6
|
+
|
7
|
+
$PROG_PATH = File.expand_path(File.dirname(__FILE__) + '/..')
|
8
|
+
$LOAD_PATH.unshift($PROG_PATH + '/lib') if File.directory?($PROG_PATH + '/lib') && !$LOAD_PATH.include?($PROG_PATH + '/lib')
|
9
|
+
|
10
|
+
require 'dns-check'
|
11
|
+
|
12
|
+
begin
|
13
|
+
DNSCheck::CLI.instance.run
|
14
|
+
rescue => e
|
15
|
+
raise e if $DEBUG
|
16
|
+
STDERR.puts e.message
|
17
|
+
STDERR.puts e.backtrace.join("\n") if $DEBUG
|
18
|
+
end
|
data/db/.gitignore
ADDED
data/dns-check.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
$:.push File.expand_path("../lib", __FILE__)
|
4
|
+
|
5
|
+
require 'dns-check/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |gem|
|
8
|
+
gem.name = "dns-check"
|
9
|
+
gem.version = DNSCheck::VERSION
|
10
|
+
gem.authors = "Ali Abbas"
|
11
|
+
gem.email = "ali@alouche.net"
|
12
|
+
gem.description = "CLI based DNS propagation check tool"
|
13
|
+
gem.summary = "Allows you to query a bunch of random nameservers, filter per countries, cities to check the propagation of your domain or simply make sure that your geo load balancing is working"
|
14
|
+
gem.homepage = "https://github.com/alouche/dns-check"
|
15
|
+
gem.add_dependency('ipaddress')
|
16
|
+
gem.add_dependency('public_suffix')
|
17
|
+
gem.add_dependency('eventmachine')
|
18
|
+
gem.add_dependency('em-resolv-replace')
|
19
|
+
gem.add_development_dependency('rspec')
|
20
|
+
|
21
|
+
gem.files = `git ls-files`.split($/)
|
22
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
23
|
+
gem.test_files = gem.files.grep(%r{^(test|spec)/})
|
24
|
+
gem.require_paths = ["lib"]
|
25
|
+
end
|
data/lib/dns-check.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'time'
|
6
|
+
|
7
|
+
require 'dns-check/ext'
|
8
|
+
require 'dns-check/version'
|
9
|
+
require 'dns-check/errors'
|
10
|
+
require 'dns-check/util'
|
11
|
+
require 'dns-check/cli'
|
12
|
+
|
13
|
+
module DNSCheck extend self
|
14
|
+
def config
|
15
|
+
@config ||={
|
16
|
+
:timeout => 1,
|
17
|
+
:indice_location => URI.parse('http://public-dns.tk/nameservers.json'),
|
18
|
+
:indice_store => "#{$PROG_PATH}/db/indice",
|
19
|
+
:show_ns => false,
|
20
|
+
:size => 10
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def config=(opts)
|
25
|
+
@config = opts
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'singleton'
|
5
|
+
|
6
|
+
require 'dns-check/db'
|
7
|
+
require 'dns-check/update'
|
8
|
+
require 'dns-check/node'
|
9
|
+
|
10
|
+
module DNSCheck
|
11
|
+
class CLI
|
12
|
+
include Singleton
|
13
|
+
|
14
|
+
attr_reader :args
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
super
|
18
|
+
@args = ARGV
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
config.merge!(parse_options)
|
23
|
+
DNSCheck::Node.start
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def config
|
29
|
+
DNSCheck.config
|
30
|
+
end
|
31
|
+
|
32
|
+
def update!
|
33
|
+
DNSCheck.indice_location = config[:indice_location]
|
34
|
+
DNSCheck.indice_store = config[:indice_store]
|
35
|
+
DNSCheck.update!
|
36
|
+
exit 0
|
37
|
+
end
|
38
|
+
|
39
|
+
def parse_options
|
40
|
+
opts = {}
|
41
|
+
|
42
|
+
parser = OptionParser.new do |o|
|
43
|
+
o.separator ''
|
44
|
+
o.separator 'Options:'
|
45
|
+
|
46
|
+
o.on '-l', '--location [name]', String, 'Location can either be a country or city' do |loc|
|
47
|
+
opts[:location] = loc
|
48
|
+
end
|
49
|
+
|
50
|
+
o.on '-t', '--timeout [sec]', Integer, 'DNS Query timeout (Default: 5s)' do |sec|
|
51
|
+
opts[:timeout] = sec
|
52
|
+
end
|
53
|
+
|
54
|
+
o.on '--records [size]', Integer, 'Number of nameservers to select (default: 10)' do |size|
|
55
|
+
opts[:size] = size
|
56
|
+
end
|
57
|
+
|
58
|
+
o.on '--show-ns', 'Show nameservers' do
|
59
|
+
opts[:show_ns] = true
|
60
|
+
end
|
61
|
+
|
62
|
+
o.on '--update', 'Perform indice update' do
|
63
|
+
update!
|
64
|
+
end
|
65
|
+
|
66
|
+
o.on '--debug' do
|
67
|
+
$DEBUG = true
|
68
|
+
end
|
69
|
+
|
70
|
+
o.on_tail '-v', '--version', 'Show version' do
|
71
|
+
puts DNSCheck::VERSION
|
72
|
+
exit 0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
parser.banner = 'Usage: dns-check [options] [domain]'
|
77
|
+
parser.on_tail '-h', '-?', '--help', 'Show this message' do
|
78
|
+
puts parser
|
79
|
+
exit 0
|
80
|
+
end
|
81
|
+
|
82
|
+
parser.parse!(@args)
|
83
|
+
|
84
|
+
if @args.empty?
|
85
|
+
puts parser
|
86
|
+
exit 0
|
87
|
+
end
|
88
|
+
|
89
|
+
opts[:hostname] = @args[0]
|
90
|
+
opts
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
trap("SIGINT") {
|
95
|
+
EM.stop if EM.reactor_running?
|
96
|
+
|
97
|
+
exit 0
|
98
|
+
}
|
99
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'ipaddress'
|
4
|
+
require 'public_suffix'
|
5
|
+
|
6
|
+
module DNSCheck
|
7
|
+
module Core
|
8
|
+
def __init options, filter={}
|
9
|
+
is_hostname_sane? options[:hostname]
|
10
|
+
indice_file_exist? options[:indice_store]
|
11
|
+
|
12
|
+
indice_records = load_indice(options[:indice_store], options[:location])
|
13
|
+
|
14
|
+
select_random_records(options[:size], indice_records)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def is_hostname_sane? hostname
|
20
|
+
raise DNSCheck::DomainError, "Specify a correct domain name format!"\
|
21
|
+
if IPAddress.valid? hostname\
|
22
|
+
or (Float(hostname) != nil rescue false)\
|
23
|
+
or !PublicSuffix.valid? hostname
|
24
|
+
end
|
25
|
+
|
26
|
+
def indice_file_exist? indice_file
|
27
|
+
raise DNSCheck::IndiceMissing, "Download the indice by issuing dns-check --update"\
|
28
|
+
unless File.exist?(indice_file)
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_location_city? location_filter
|
32
|
+
return location_filter.resolve_country_name if location_filter.size > 2
|
33
|
+
|
34
|
+
#FIXME String#capitalize_all needs to be fixed
|
35
|
+
#to not allow FR to become Fr
|
36
|
+
return location_filter.upcase
|
37
|
+
end
|
38
|
+
|
39
|
+
def load_indice indice_file, location_filter=nil
|
40
|
+
records = DNSCheck.load indice_file
|
41
|
+
|
42
|
+
unless location_filter.nil?
|
43
|
+
location_filter = location_filter.capitalize_all
|
44
|
+
|
45
|
+
location = is_location_city? location_filter
|
46
|
+
|
47
|
+
filtered_records = []
|
48
|
+
|
49
|
+
#FIXME clean up procedure (duplicate push call)
|
50
|
+
unless location.nil?
|
51
|
+
# This will also catch unexisting cities, return general error
|
52
|
+
raise DNSCheck::LocationError, "This location could not be found"\
|
53
|
+
unless records.has_key?(location)
|
54
|
+
|
55
|
+
records = records[location]
|
56
|
+
records.each do |record|
|
57
|
+
filtered_records.push([record])
|
58
|
+
end
|
59
|
+
else
|
60
|
+
records.values.each do |record|
|
61
|
+
record.each do |k|
|
62
|
+
if k.include?(location_filter)
|
63
|
+
filtered_records.push([k])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
return DNSCheck::DB[filtered_records]
|
70
|
+
end
|
71
|
+
|
72
|
+
records
|
73
|
+
rescue => e
|
74
|
+
raise DNSCheck::IndiceLoading, e.message
|
75
|
+
end
|
76
|
+
|
77
|
+
#FIXME break method
|
78
|
+
def select_random_records(max_records, indice_records)
|
79
|
+
records = []
|
80
|
+
|
81
|
+
sliced_records = indice_records.rand_keys.slice(0..max_records-1)
|
82
|
+
|
83
|
+
sliced_records.each do |k|
|
84
|
+
if k.class == String
|
85
|
+
v = indice_records[k].sample.flatten
|
86
|
+
v.push(k)
|
87
|
+
else
|
88
|
+
v = k.flatten
|
89
|
+
end
|
90
|
+
|
91
|
+
v[1].delete_if {|x|
|
92
|
+
x == nil || x == ""
|
93
|
+
}
|
94
|
+
|
95
|
+
records.push(v)
|
96
|
+
end
|
97
|
+
|
98
|
+
records
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/dns-check/db.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module DNSCheck
|
6
|
+
class DB
|
7
|
+
|
8
|
+
extend Forwardable
|
9
|
+
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
def_delegators :@Records
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
super
|
16
|
+
@Records = Hash.new { |hash, key|
|
17
|
+
hash[key] = []
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.[](*args)
|
22
|
+
db = new
|
23
|
+
db.instance_variable_set(:@Records, Hash[*args])
|
24
|
+
db
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](key)
|
28
|
+
@Records[key]
|
29
|
+
end
|
30
|
+
|
31
|
+
def update k
|
32
|
+
@Records[k] = yield(@Records[k])
|
33
|
+
end
|
34
|
+
|
35
|
+
def add(k, v)
|
36
|
+
update(k) do |hash|
|
37
|
+
hash << v
|
38
|
+
end
|
39
|
+
end
|
40
|
+
alias_method :[]=, :add
|
41
|
+
|
42
|
+
# Can't marshal hash with default proc
|
43
|
+
def dump_all
|
44
|
+
return @Records unless @Records.default_proc
|
45
|
+
records = @Records.clone
|
46
|
+
records.default = nil
|
47
|
+
records
|
48
|
+
end
|
49
|
+
|
50
|
+
def keys
|
51
|
+
@Records.keys
|
52
|
+
end
|
53
|
+
|
54
|
+
def values
|
55
|
+
@Records.values
|
56
|
+
end
|
57
|
+
|
58
|
+
def has_key? k
|
59
|
+
@Records[k] ? true : false
|
60
|
+
end
|
61
|
+
|
62
|
+
def rand_keys
|
63
|
+
self.keys.sort_by{rand}
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'timeout'
|
4
|
+
require 'em-resolv-replace'
|
5
|
+
|
6
|
+
module DNSCheck
|
7
|
+
module DNS
|
8
|
+
|
9
|
+
def timeout= sec
|
10
|
+
@timeout = sec
|
11
|
+
end
|
12
|
+
|
13
|
+
def nameservers= ns
|
14
|
+
@query = Resolv::DNS.new(
|
15
|
+
:nameserver => ns,
|
16
|
+
:ndots => 1
|
17
|
+
)
|
18
|
+
end
|
19
|
+
|
20
|
+
def lookup hostname
|
21
|
+
Timeout::timeout(@timeout) do
|
22
|
+
@query.getaddress(hostname).to_s.colorize_to('green')
|
23
|
+
end
|
24
|
+
rescue Timeout::Error
|
25
|
+
"Nameserver Timeout".colorize_to('red')
|
26
|
+
rescue => e
|
27
|
+
e.message.colorize_to('red')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
extend DNS
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module DNSCheck
|
4
|
+
class Error < StandardError; end
|
5
|
+
|
6
|
+
class NotFoundError < RuntimeError; end
|
7
|
+
|
8
|
+
class IndiceMissing < Error; end
|
9
|
+
|
10
|
+
class IndiceLoading < Error; end
|
11
|
+
|
12
|
+
class DomainError < Error; end
|
13
|
+
|
14
|
+
class LocationError < Error; end
|
15
|
+
|
16
|
+
class UpdateError < Error; end
|
17
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
class String
|
4
|
+
|
5
|
+
def capitalize_all
|
6
|
+
self.split(' ').map do |word|
|
7
|
+
word.capitalize
|
8
|
+
end.join(' ')
|
9
|
+
end
|
10
|
+
|
11
|
+
def resolve_country_code
|
12
|
+
DNSCheck::COUNTRY_CODES[self] || self
|
13
|
+
end
|
14
|
+
|
15
|
+
def resolve_country_name
|
16
|
+
DNSCheck::COUNTRY_CODES.invert[self]
|
17
|
+
end
|
18
|
+
|
19
|
+
def colorize_to(color_name)
|
20
|
+
case color_name
|
21
|
+
when 'red'
|
22
|
+
color_code = 31
|
23
|
+
when 'green'
|
24
|
+
color_code = 32
|
25
|
+
else
|
26
|
+
color_code = 33
|
27
|
+
end
|
28
|
+
|
29
|
+
"\e[#{color_code}m#{self}\e[0m"
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'eventmachine'
|
4
|
+
require 'dns-check/output'
|
5
|
+
require 'dns-check/dns'
|
6
|
+
require 'dns-check/core'
|
7
|
+
|
8
|
+
module DNSCheck
|
9
|
+
module Node extend Core
|
10
|
+
|
11
|
+
def start
|
12
|
+
@records = __init(DNSCheck.config)
|
13
|
+
resolv_all
|
14
|
+
end
|
15
|
+
|
16
|
+
def resolv
|
17
|
+
DNSCheck
|
18
|
+
end
|
19
|
+
|
20
|
+
def hostname
|
21
|
+
DNSCheck.config[:hostname]
|
22
|
+
end
|
23
|
+
|
24
|
+
def timeout
|
25
|
+
DNSCheck.config[:timeout]
|
26
|
+
end
|
27
|
+
|
28
|
+
def output
|
29
|
+
output ||= Output.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def resolv_all
|
33
|
+
resolv.timeout = timeout
|
34
|
+
|
35
|
+
EM.run do
|
36
|
+
Fiber.new do
|
37
|
+
@records.each do |e, ns, c|
|
38
|
+
resolv.nameservers = ns
|
39
|
+
|
40
|
+
resolved_ip = resolv.lookup(hostname)
|
41
|
+
|
42
|
+
output_msg = [e, resolved_ip, ns.sample, c]
|
43
|
+
|
44
|
+
output.insert do
|
45
|
+
output.print_msg output_msg
|
46
|
+
end
|
47
|
+
end
|
48
|
+
EM.stop
|
49
|
+
end.resume
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
extend self
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
module DNSCheck
|
6
|
+
class Output
|
7
|
+
def initialize; end
|
8
|
+
|
9
|
+
def print_msg msg
|
10
|
+
pretty_print msg
|
11
|
+
end
|
12
|
+
|
13
|
+
def insert(*msg)
|
14
|
+
$stdout = StringIO.new
|
15
|
+
|
16
|
+
yield
|
17
|
+
|
18
|
+
unless $stdout.string.empty?
|
19
|
+
STDOUT.print $stdout.string
|
20
|
+
STDOUT.flush
|
21
|
+
end
|
22
|
+
ensure
|
23
|
+
$stdout = STDOUT
|
24
|
+
end
|
25
|
+
|
26
|
+
def pretty_print msg
|
27
|
+
msg[0] = "NN" if msg[0].empty?
|
28
|
+
|
29
|
+
#FIXME redundant, catch nil instead of has_key
|
30
|
+
if msg[3] && COUNTRY_CODES.has_key?(msg[3])
|
31
|
+
#FIXME cheap workaround around frozen string
|
32
|
+
msg[0] = msg[0].dup
|
33
|
+
msg[0].prepend(COUNTRY_CODES[msg[3]] + '/')
|
34
|
+
end
|
35
|
+
|
36
|
+
print msg[0] + "|" + msg[1]
|
37
|
+
|
38
|
+
print "|" + msg[2] if DNSCheck.config[:show_ns]
|
39
|
+
|
40
|
+
print "\n"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module DNSCheck
|
6
|
+
module Update
|
7
|
+
attr_accessor :indice_location, :indice_store
|
8
|
+
|
9
|
+
def update!
|
10
|
+
print "-> downloading... (please wait)"
|
11
|
+
|
12
|
+
http do |conn|
|
13
|
+
request = Net::HTTP::Get.new(indice_location.request_uri, {})
|
14
|
+
|
15
|
+
buffer = ''
|
16
|
+
|
17
|
+
conn.request request do |res|
|
18
|
+
case res
|
19
|
+
when Net::HTTPNotModified
|
20
|
+
puts "No new content available"
|
21
|
+
when Net::HTTPRedirection
|
22
|
+
# Do not expect a redirect...
|
23
|
+
puts "Redirecting to #{res['Location']}... aborting! open a github issue"
|
24
|
+
when Net::HTTPOK
|
25
|
+
begin
|
26
|
+
res.read_body do |buf|
|
27
|
+
buffer << buf
|
28
|
+
end
|
29
|
+
save buffer
|
30
|
+
rescue Exception => e
|
31
|
+
raise e
|
32
|
+
ensure
|
33
|
+
#TODO clean exit?
|
34
|
+
end
|
35
|
+
when Net::HTTPNotFound
|
36
|
+
raise DNSCheck::NotFoundError, "http code 404 - open a github issue"
|
37
|
+
else
|
38
|
+
raise RuntimeError, "Update failed... #{res.message}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
rescue => e
|
43
|
+
raise DNSCheck::UpdateError, "the indice update failed... #{e.message}"
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def save buffer
|
49
|
+
object = sanetize_indice buffer
|
50
|
+
DNSCheck.store object, indice_store
|
51
|
+
end
|
52
|
+
|
53
|
+
def http
|
54
|
+
yield Net::HTTP.new(indice_location.hostname, 80)
|
55
|
+
end
|
56
|
+
|
57
|
+
def sanetize_indice buffer
|
58
|
+
indice_records = JSON.parse(buffer)
|
59
|
+
# Create new array, faster than calling Array#delete on indice_records
|
60
|
+
new_indice_records = DNSCheck::DB.new
|
61
|
+
|
62
|
+
indice_records.each do |record|
|
63
|
+
if record['state'] == "valid" and !record['country_id'].nil?
|
64
|
+
new_indice_records[record['country_id']] = {
|
65
|
+
record['city'] => [
|
66
|
+
record['ip'],
|
67
|
+
record['name']
|
68
|
+
]
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
print " - done\n";
|
73
|
+
return new_indice_records
|
74
|
+
rescue => e
|
75
|
+
#TODO raise exception, i.e: upstream key format changed!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
extend Update
|
80
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
#-*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'zlib'
|
4
|
+
|
5
|
+
module DNSCheck
|
6
|
+
|
7
|
+
COUNTRY_CODES = {
|
8
|
+
'AF'=>'Afghanistan',
|
9
|
+
'AL'=>'Albania',
|
10
|
+
'DZ'=>'Algeria',
|
11
|
+
'AS'=>'American Samoa',
|
12
|
+
'AD'=>'Andorra',
|
13
|
+
'AO'=>'Angola',
|
14
|
+
'AI'=>'Anguilla',
|
15
|
+
'AQ'=>'Antarctica',
|
16
|
+
'AG'=>'Antigua And Barbuda',
|
17
|
+
'AR'=>'Argentina',
|
18
|
+
'AM'=>'Armenia',
|
19
|
+
'AW'=>'Aruba',
|
20
|
+
'AU'=>'Australia',
|
21
|
+
'AT'=>'Austria',
|
22
|
+
'AZ'=>'Azerbaijan',
|
23
|
+
'BS'=>'Bahamas',
|
24
|
+
'BH'=>'Bahrain',
|
25
|
+
'BD'=>'Bangladesh',
|
26
|
+
'BB'=>'Barbados',
|
27
|
+
'BY'=>'Belarus',
|
28
|
+
'BE'=>'Belgium',
|
29
|
+
'BZ'=>'Belize',
|
30
|
+
'BJ'=>'Benin',
|
31
|
+
'BM'=>'Bermuda',
|
32
|
+
'BT'=>'Bhutan',
|
33
|
+
'BO'=>'Bolivia',
|
34
|
+
'BA'=>'Bosnia And Herzegovina',
|
35
|
+
'BW'=>'Botswana',
|
36
|
+
'BV'=>'Bouvet Island',
|
37
|
+
'BR'=>'Brazil',
|
38
|
+
'IO'=>'British Indian Ocean Territory',
|
39
|
+
'BN'=>'Brunei',
|
40
|
+
'BG'=>'Bulgaria',
|
41
|
+
'BF'=>'Burkina Faso',
|
42
|
+
'BI'=>'Burundi',
|
43
|
+
'KH'=>'Cambodia',
|
44
|
+
'CM'=>'Cameroon',
|
45
|
+
'CA'=>'Canada',
|
46
|
+
'CV'=>'Cape Verde',
|
47
|
+
'KY'=>'Cayman Islands',
|
48
|
+
'CF'=>'Central African Republic',
|
49
|
+
'TD'=>'Chad',
|
50
|
+
'CL'=>'Chile',
|
51
|
+
'CN'=>'China',
|
52
|
+
'CX'=>'Christmas Island',
|
53
|
+
'CC'=>'Cocos (Keeling) Islands',
|
54
|
+
'CO'=>'Columbia',
|
55
|
+
'KM'=>'Comoros',
|
56
|
+
'CG'=>'Congo',
|
57
|
+
'CK'=>'Cook Islands',
|
58
|
+
'CR'=>'Costa Rica',
|
59
|
+
'CI'=>'Cote D\'Ivorie (Ivory Coast)',
|
60
|
+
'HR'=>'Croatia (Hrvatska)',
|
61
|
+
'CU'=>'Cuba',
|
62
|
+
'CY'=>'Cyprus',
|
63
|
+
'CZ'=>'Czech Republic',
|
64
|
+
'CD'=>'Democratic Republic Of Congo (Zaire)',
|
65
|
+
'DK'=>'Denmark',
|
66
|
+
'DJ'=>'Djibouti',
|
67
|
+
'DM'=>'Dominica',
|
68
|
+
'DO'=>'Dominican Republic',
|
69
|
+
'TP'=>'East Timor',
|
70
|
+
'EC'=>'Ecuador',
|
71
|
+
'EG'=>'Egypt',
|
72
|
+
'SV'=>'El Salvador',
|
73
|
+
'GQ'=>'Equatorial Guinea',
|
74
|
+
'ER'=>'Eritrea',
|
75
|
+
'EE'=>'Estonia',
|
76
|
+
'ET'=>'Ethiopia',
|
77
|
+
'FK'=>'Falkland Islands (Malvinas)',
|
78
|
+
'FO'=>'Faroe Islands',
|
79
|
+
'FJ'=>'Fiji',
|
80
|
+
'FI'=>'Finland',
|
81
|
+
'FR'=>'France',
|
82
|
+
'FX'=>'France, Metropolitan',
|
83
|
+
'GF'=>'French Guinea',
|
84
|
+
'PF'=>'French Polynesia',
|
85
|
+
'TF'=>'French Southern Territories',
|
86
|
+
'GA'=>'Gabon',
|
87
|
+
'GM'=>'Gambia',
|
88
|
+
'GE'=>'Georgia',
|
89
|
+
'DE'=>'Germany',
|
90
|
+
'GH'=>'Ghana',
|
91
|
+
'GI'=>'Gibraltar',
|
92
|
+
'GR'=>'Greece',
|
93
|
+
'GL'=>'Greenland',
|
94
|
+
'GD'=>'Grenada',
|
95
|
+
'GP'=>'Guadeloupe',
|
96
|
+
'GU'=>'Guam',
|
97
|
+
'GT'=>'Guatemala',
|
98
|
+
'GN'=>'Guinea',
|
99
|
+
'GW'=>'Guinea-Bissau',
|
100
|
+
'GY'=>'Guyana',
|
101
|
+
'HT'=>'Haiti',
|
102
|
+
'HM'=>'Heard And McDonald Islands',
|
103
|
+
'HN'=>'Honduras',
|
104
|
+
'HK'=>'Hong Kong',
|
105
|
+
'HU'=>'Hungary',
|
106
|
+
'IS'=>'Iceland',
|
107
|
+
'IN'=>'India',
|
108
|
+
'ID'=>'Indonesia',
|
109
|
+
'IR'=>'Iran',
|
110
|
+
'IQ'=>'Iraq',
|
111
|
+
'IE'=>'Ireland',
|
112
|
+
'IL'=>'Israel',
|
113
|
+
'IT'=>'Italy',
|
114
|
+
'JM'=>'Jamaica',
|
115
|
+
'JP'=>'Japan',
|
116
|
+
'JO'=>'Jordan',
|
117
|
+
'KZ'=>'Kazakhstan',
|
118
|
+
'KE'=>'Kenya',
|
119
|
+
'KI'=>'Kiribati',
|
120
|
+
'KW'=>'Kuwait',
|
121
|
+
'KG'=>'Kyrgyzstan',
|
122
|
+
'LA'=>'Laos',
|
123
|
+
'LV'=>'Latvia',
|
124
|
+
'LB'=>'Lebanon',
|
125
|
+
'LS'=>'Lesotho',
|
126
|
+
'LR'=>'Liberia',
|
127
|
+
'LY'=>'Libya',
|
128
|
+
'LI'=>'Liechtenstein',
|
129
|
+
'LT'=>'Lithuania',
|
130
|
+
'LU'=>'Luxembourg',
|
131
|
+
'MO'=>'Macau',
|
132
|
+
'MK'=>'Macedonia',
|
133
|
+
'MG'=>'Madagascar',
|
134
|
+
'MW'=>'Malawi',
|
135
|
+
'MY'=>'Malaysia',
|
136
|
+
'MV'=>'Maldives',
|
137
|
+
'ML'=>'Mali',
|
138
|
+
'MT'=>'Malta',
|
139
|
+
'MH'=>'Marshall Islands',
|
140
|
+
'MQ'=>'Martinique',
|
141
|
+
'MR'=>'Mauritania',
|
142
|
+
'MU'=>'Mauritius',
|
143
|
+
'YT'=>'Mayotte',
|
144
|
+
'MX'=>'Mexico',
|
145
|
+
'FM'=>'Micronesia',
|
146
|
+
'MD'=>'Moldova',
|
147
|
+
'MC'=>'Monaco',
|
148
|
+
'MN'=>'Mongolia',
|
149
|
+
'MS'=>'Montserrat',
|
150
|
+
'MA'=>'Morocco',
|
151
|
+
'MZ'=>'Mozambique',
|
152
|
+
'MM'=>'Myanmar (Burma)',
|
153
|
+
'NA'=>'Namibia',
|
154
|
+
'NR'=>'Nauru',
|
155
|
+
'NP'=>'Nepal',
|
156
|
+
'NL'=>'Netherlands',
|
157
|
+
'AN'=>'Netherlands Antilles',
|
158
|
+
'NC'=>'New Caledonia',
|
159
|
+
'NZ'=>'New Zealand',
|
160
|
+
'NI'=>'Nicaragua',
|
161
|
+
'NE'=>'Niger',
|
162
|
+
'NG'=>'Nigeria',
|
163
|
+
'NU'=>'Niue',
|
164
|
+
'NF'=>'Norfolk Island',
|
165
|
+
'KP'=>'North Korea',
|
166
|
+
'MP'=>'Northern Mariana Islands',
|
167
|
+
'NO'=>'Norway',
|
168
|
+
'OM'=>'Oman',
|
169
|
+
'PK'=>'Pakistan',
|
170
|
+
'PW'=>'Palau',
|
171
|
+
'PA'=>'Panama',
|
172
|
+
'PG'=>'Papua New Guinea',
|
173
|
+
'PY'=>'Paraguay',
|
174
|
+
'PE'=>'Peru',
|
175
|
+
'PH'=>'Philippines',
|
176
|
+
'PN'=>'Pitcairn',
|
177
|
+
'PL'=>'Poland',
|
178
|
+
'PT'=>'Portugal',
|
179
|
+
'PR'=>'Puerto Rico',
|
180
|
+
'QA'=>'Qatar',
|
181
|
+
'RE'=>'Reunion',
|
182
|
+
'RO'=>'Romania',
|
183
|
+
'RU'=>'Russia',
|
184
|
+
'RW'=>'Rwanda',
|
185
|
+
'SH'=>'Saint Helena',
|
186
|
+
'KN'=>'Saint Kitts And Nevis',
|
187
|
+
'LC'=>'Saint Lucia',
|
188
|
+
'PM'=>'Saint Pierre And Miquelon',
|
189
|
+
'VC'=>'Saint Vincent And The Grenadines',
|
190
|
+
'SM'=>'San Marino',
|
191
|
+
'ST'=>'Sao Tome And Principe',
|
192
|
+
'SA'=>'Saudi Arabia',
|
193
|
+
'SN'=>'Senegal',
|
194
|
+
'SC'=>'Seychelles',
|
195
|
+
'SL'=>'Sierra Leone',
|
196
|
+
'SG'=>'Singapore',
|
197
|
+
'SK'=>'Slovak Republic',
|
198
|
+
'SI'=>'Slovenia',
|
199
|
+
'SB'=>'Solomon Islands',
|
200
|
+
'SO'=>'Somalia',
|
201
|
+
'ZA'=>'South Africa',
|
202
|
+
'GS'=>'South Georgia And South Sandwich Islands',
|
203
|
+
'KR'=>'South Korea',
|
204
|
+
'ES'=>'Spain',
|
205
|
+
'LK'=>'Sri Lanka',
|
206
|
+
'SD'=>'Sudan',
|
207
|
+
'SR'=>'Suriname',
|
208
|
+
'SJ'=>'Svalbard And Jan Mayen',
|
209
|
+
'SZ'=>'Swaziland',
|
210
|
+
'SE'=>'Sweden',
|
211
|
+
'CH'=>'Switzerland',
|
212
|
+
'SY'=>'Syria',
|
213
|
+
'TW'=>'Taiwan',
|
214
|
+
'TJ'=>'Tajikistan',
|
215
|
+
'TZ'=>'Tanzania',
|
216
|
+
'TH'=>'Thailand',
|
217
|
+
'TG'=>'Togo',
|
218
|
+
'TK'=>'Tokelau',
|
219
|
+
'TO'=>'Tonga',
|
220
|
+
'TT'=>'Trinidad And Tobago',
|
221
|
+
'TN'=>'Tunisia',
|
222
|
+
'TR'=>'Turkey',
|
223
|
+
'TM'=>'Turkmenistan',
|
224
|
+
'TC'=>'Turks And Caicos Islands',
|
225
|
+
'TV'=>'Tuvalu',
|
226
|
+
'UG'=>'Uganda',
|
227
|
+
'UA'=>'Ukraine',
|
228
|
+
'AE'=>'United Arab Emirates',
|
229
|
+
'UK'=>'United Kingdom',
|
230
|
+
'US'=>'United States',
|
231
|
+
'UM'=>'United States Minor Outlying Islands',
|
232
|
+
'UY'=>'Uruguay',
|
233
|
+
'UZ'=>'Uzbekistan',
|
234
|
+
'VU'=>'Vanuatu',
|
235
|
+
'VA'=>'Vatican City (Holy See)',
|
236
|
+
'VE'=>'Venezuela',
|
237
|
+
'VN'=>'Vietnam',
|
238
|
+
'VG'=>'Virgin Islands (British)',
|
239
|
+
'VI'=>'Virgin Islands (US)',
|
240
|
+
'WF'=>'Wallis And Futuna Islands',
|
241
|
+
'EH'=>'Western Sahara',
|
242
|
+
'WS'=>'Western Samoa',
|
243
|
+
'YE'=>'Yemen',
|
244
|
+
'YU'=>'Yugoslavia',
|
245
|
+
'ZM'=>'Zambia',
|
246
|
+
'ZW'=>'Zimbabwe'
|
247
|
+
}
|
248
|
+
|
249
|
+
def self.store obj, file_name
|
250
|
+
marshal_dump = Marshal.dump(obj.dump_all)
|
251
|
+
file = File.new(file_name,'w')
|
252
|
+
file = Zlib::GzipWriter.new(file)
|
253
|
+
file.write marshal_dump
|
254
|
+
file.close
|
255
|
+
return true
|
256
|
+
rescue => e
|
257
|
+
raise DNSCheck::UpdateError, e.message
|
258
|
+
end
|
259
|
+
|
260
|
+
def self.load file_name
|
261
|
+
file = Zlib::GzipReader.open(file_name)
|
262
|
+
obj = Marshal.load file.read
|
263
|
+
file.close
|
264
|
+
DNSCheck::DB[obj]
|
265
|
+
end
|
266
|
+
end
|
metadata
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dns-check
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ali Abbas
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-02 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ipaddress
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: public_suffix
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: eventmachine
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: em-resolv-replace
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :runtime
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
description: CLI based DNS propagation check tool
|
95
|
+
email: ali@alouche.net
|
96
|
+
executables:
|
97
|
+
- dns-check
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- .gitignore
|
102
|
+
- Gemfile
|
103
|
+
- README.md
|
104
|
+
- Rakefile
|
105
|
+
- bin/dns-check
|
106
|
+
- db/.gitignore
|
107
|
+
- dns-check.gemspec
|
108
|
+
- lib/dns-check.rb
|
109
|
+
- lib/dns-check/cli.rb
|
110
|
+
- lib/dns-check/core.rb
|
111
|
+
- lib/dns-check/db.rb
|
112
|
+
- lib/dns-check/dns.rb
|
113
|
+
- lib/dns-check/errors.rb
|
114
|
+
- lib/dns-check/ext.rb
|
115
|
+
- lib/dns-check/node.rb
|
116
|
+
- lib/dns-check/output.rb
|
117
|
+
- lib/dns-check/update.rb
|
118
|
+
- lib/dns-check/util.rb
|
119
|
+
- lib/dns-check/version.rb
|
120
|
+
homepage: https://github.com/alouche/dns-check
|
121
|
+
licenses: []
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
none: false
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
requirements: []
|
139
|
+
rubyforge_project:
|
140
|
+
rubygems_version: 1.8.23
|
141
|
+
signing_key:
|
142
|
+
specification_version: 3
|
143
|
+
summary: Allows you to query a bunch of random nameservers, filter per countries,
|
144
|
+
cities to check the propagation of your domain or simply make sure that your geo
|
145
|
+
load balancing is working
|
146
|
+
test_files: []
|