dns-check 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|