ddig 0.1.0 → 0.2.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
- data/README.md +96 -5
- data/lib/ddig/cli.rb +91 -5
- data/lib/ddig/ddr.rb +24 -20
- data/lib/ddig/ip.rb +57 -0
- data/lib/ddig/resolver/dns_message.rb +40 -0
- data/lib/ddig/resolver/doh_h1.rb +61 -0
- data/lib/ddig/resolver/dot.rb +6 -21
- data/lib/ddig/version.rb +1 -1
- data/lib/ddig.rb +9 -4
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1a65973ea90a0410cf7c2bd8846431d1b46f6bfec521cde944deba86c83effc
|
4
|
+
data.tar.gz: 4eaf90cdfabfe53095f4a5f4ca5f034b0d79296e0ff64da53a00cd4c71de6d04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 675a844c854c9bb5d63cac33742cc88e7a712356b41dc1fd61c4a646112ee1080a887218b3f8a6c949c0277c2d7f01851d1f30f3258138c2a57c467f4570c448
|
7
|
+
data.tar.gz: bdf9aa4945b93c190716a5809829cc11e2fd58584d0620b48f0793ae5085b3cb5e77b6f0cac2c28303f2dbb3e1c988e3b5f989f80de49049cb6fe5d3420212a8
|
data/README.md
CHANGED
@@ -7,10 +7,13 @@ ddig is DNS lookup utility for Ruby.
|
|
7
7
|
- DNS Resolvers
|
8
8
|
- UDP (Do53)
|
9
9
|
- DoT (DNS over TLS)
|
10
|
-
- https://
|
11
|
-
-
|
12
|
-
-
|
13
|
-
- https://
|
10
|
+
- https://www.rfc-editor.org/rfc/rfc7858.html
|
11
|
+
- DoH (DNS over HTTPS)
|
12
|
+
- Support only HTTP/1.1
|
13
|
+
- https://www.rfc-editor.org/rfc/rfc8484.html
|
14
|
+
- ~~DoQ (DNS over QUIC)~~
|
15
|
+
- Not Supported
|
16
|
+
- https://www.rfc-editor.org/rfc/rfc9250.html
|
14
17
|
- DDR (Discovery of Designated Resolvers)
|
15
18
|
- https://www.rfc-editor.org/rfc/rfc9462.html
|
16
19
|
|
@@ -25,6 +28,7 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
25
28
|
$ gem install ddig
|
26
29
|
|
27
30
|
## Usage
|
31
|
+
### Ruby
|
28
32
|
|
29
33
|
```ruby
|
30
34
|
ddig = Ddig.lookup('dns.google', nameservers: ['8.8.8.8', '2001:4860:4860::8888'])
|
@@ -83,9 +87,96 @@ ddig[:ddr]
|
|
83
87
|
]
|
84
88
|
```
|
85
89
|
|
90
|
+
- Do53
|
91
|
+
```ruby
|
92
|
+
do53 = Ddig::Resolver::Do53.new(hostname: 'dns.google', nameservers: '8.8.8.8').lookup
|
93
|
+
=> #<Ddig::Resolver::Do53:0x0000000121717b78 @a=["8.8.8.8", "8.8.4.4"], @aaaa=["2001:4860:4860::8844", "2001:4860:4860::8888"], @hostname="dns.google", @ip=nil, @nameserver=#<Ddig::Nameserver:0x00000001211fb108 @nameservers="8.8.8.8", @servers=["8.8.8.8"]>, @nameservers=["8.8.8.8"]>
|
94
|
+
|
95
|
+
do53.a
|
96
|
+
=> ["8.8.4.4", "8.8.8.8"]
|
97
|
+
do53.aaaa
|
98
|
+
=> ["2001:4860:4860::8844", "2001:4860:4860::8888"]
|
99
|
+
```
|
100
|
+
|
101
|
+
- DoT
|
102
|
+
```ruby
|
103
|
+
dot = Ddig::Resolver::Dot.new(hostname: 'dns.google', server: '8.8.8.8').lookup
|
104
|
+
=> #<Ddig::Resolver::Dot:0x000000012145da90 @a=["8.8.8.8", "8.8.4.4"], @aaaa=["2001:4860:4860::8844", "2001:4860:4860::8888"], @hostname="dns.google", @open_timeout=3, @port=853, @server="8.8.8.8", @server_name=nil>
|
105
|
+
|
106
|
+
dot.a
|
107
|
+
=> ["8.8.4.4", "8.8.8.8"]
|
108
|
+
dot.aaaa
|
109
|
+
=> ["2001:4860:4860::8844", "2001:4860:4860::8888"]
|
110
|
+
```
|
111
|
+
|
112
|
+
- DoH (HTTP/1.1)
|
113
|
+
```ruby
|
114
|
+
doh = Ddig::Resolver::DohH1.new(hostname: 'dns.google', server: 'dns.google', dohpath: '/dns-query{?dns}').lookup
|
115
|
+
=> #<Ddig::Resolver::DohH1:0x00000001023ed020 @a=["8.8.4.4", "8.8.8.8"], @aaaa=["2001:4860:4860::8888", "2001:4860:4860::8844"], @address=nil, @dohpath="/dns-query{?dns}", @hostname="dns.google", @open_timeout=10, @port=443, @server="dns.google">
|
116
|
+
|
117
|
+
doh.a
|
118
|
+
=> ["8.8.4.4", "8.8.8.8"]
|
119
|
+
doh.aaaa
|
120
|
+
=> ["2001:4860:4860::8844", "2001:4860:4860::8888"]
|
121
|
+
```
|
122
|
+
|
86
123
|
### CLI
|
124
|
+
- Usage
|
125
|
+
```
|
126
|
+
$ ddig --help
|
127
|
+
Usage: ddig [options] hostname
|
128
|
+
-d, --dns-type={all|do53|dot} resolve type (default: all)
|
129
|
+
--udp use resolve type of udp(do53)
|
130
|
+
--dot use resolve type of dot
|
131
|
+
--doh-h1 use resolve type of doh (http/1.1)
|
132
|
+
--doh-path=doh-path doh service path
|
133
|
+
-4, --ipv4 use IPv4 query transport only
|
134
|
+
-6, --ipv6 use IPv6 query transport only
|
135
|
+
-@ipaddress|doh-hostname, nameserver
|
136
|
+
--nameserver
|
137
|
+
-p, --port=port port
|
138
|
+
--format={text|json} output format (default: text)
|
139
|
+
|
140
|
+
-v, --verbose run verbosely
|
141
|
+
-h, --help show this help message.
|
142
|
+
--version show version.
|
143
|
+
```
|
144
|
+
|
145
|
+
- UDP(Do53)
|
146
|
+
```sh
|
147
|
+
$ ddig --udp --nameserver 8.8.8.8 dns.google
|
148
|
+
dns.google A 8.8.8.8
|
149
|
+
dns.google A 8.8.4.4
|
150
|
+
dns.google AAAA 2001:4860:4860::8844
|
151
|
+
dns.google AAAA 2001:4860:4860::8888
|
152
|
+
|
153
|
+
# SERVER: 8.8.8.8
|
154
|
+
```
|
155
|
+
|
156
|
+
- DoT
|
157
|
+
```sh
|
158
|
+
$ ddig --dot --nameserver 8.8.8.8 dns.google
|
159
|
+
dns.google A 8.8.8.8
|
160
|
+
dns.google A 8.8.4.4
|
161
|
+
dns.google AAAA 2001:4860:4860::8888
|
162
|
+
dns.google AAAA 2001:4860:4860::8844
|
87
163
|
|
88
|
-
(
|
164
|
+
# SERVER(Address): 8.8.8.8
|
165
|
+
# PORT: 853
|
166
|
+
```
|
167
|
+
|
168
|
+
- DoH (HTTP/1.1)
|
169
|
+
```sh
|
170
|
+
$ ddig --doh-h1 --nameserver dns.google --doh-path /dns-query{?dns} dns.google
|
171
|
+
dns.google A 8.8.8.8
|
172
|
+
dns.google A 8.8.4.4
|
173
|
+
dns.google AAAA 2001:4860:4860::8888
|
174
|
+
dns.google AAAA 2001:4860:4860::8844
|
175
|
+
|
176
|
+
# SERVER(Hostname): dns.google
|
177
|
+
# SERVER(Path): /dns-query{?dns}
|
178
|
+
# PORT: 443
|
179
|
+
```
|
89
180
|
|
90
181
|
## Development
|
91
182
|
|
data/lib/ddig/cli.rb
CHANGED
@@ -7,6 +7,7 @@ module Ddig
|
|
7
7
|
def initialize(args)
|
8
8
|
@args = args
|
9
9
|
@options = {
|
10
|
+
dns_type: 'all',
|
10
11
|
format: 'text',
|
11
12
|
}
|
12
13
|
|
@@ -22,7 +23,15 @@ module Ddig
|
|
22
23
|
@option_parser = OptionParser.new do |opts|
|
23
24
|
opts.banner = "Usage: ddig [options] hostname"
|
24
25
|
|
25
|
-
opts.on("--
|
26
|
+
opts.on("-d", "--dns-type={all|do53|dot}", "resolve type (default: all)") { |v| @options[:dns_type] = v }
|
27
|
+
opts.on("--udp", "use resolve type of udp(do53)") { |v| @options[:dns_type] = 'do53' }
|
28
|
+
opts.on("--dot", "use resolve type of dot") { |v| @options[:dns_type] = 'dot' }
|
29
|
+
opts.on("--doh-h1", "use resolve type of doh (http/1.1)") { |v| @options[:dns_type] = 'doh_h1' }
|
30
|
+
opts.on("--doh-path=doh-path", "doh service path") { |v| @options[:doh_path] = v }
|
31
|
+
opts.on("-4", "--ipv4", "use IPv4 query transport only") { |v| @options[:ipv4] = v }
|
32
|
+
opts.on("-6", "--ipv6", "use IPv6 query transport only") { |v| @options[:ipv6] = v }
|
33
|
+
opts.on("-@", "--nameserver=ipaddress|doh-hostname", "nameserver") { |v| @options[:nameserver] = v }
|
34
|
+
opts.on("-p", "--port=port", "port") { |v| @options[:port] = v }
|
26
35
|
opts.on("--format={text|json}", "output format (default: text)") { |v| @options[:format] = v }
|
27
36
|
|
28
37
|
opts.separator ""
|
@@ -38,18 +47,95 @@ module Ddig
|
|
38
47
|
end
|
39
48
|
|
40
49
|
def exec
|
41
|
-
|
50
|
+
if @options[:ipv4] || @options[:ipv6]
|
51
|
+
@use_ipv4 = @options[:ipv4] || false
|
52
|
+
@use_ipv6 = @options[:ipv6] || false
|
53
|
+
end
|
54
|
+
|
55
|
+
case @options[:dns_type]
|
56
|
+
when "all"
|
57
|
+
resolve_all
|
58
|
+
when "do53"
|
59
|
+
resolve_do53
|
60
|
+
when "dot"
|
61
|
+
resolve_dot
|
62
|
+
when "doh_h1"
|
63
|
+
resolve_doh_h1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def resolve_all
|
68
|
+
@ddig = Ddig.lookup(@hostname, nameservers: @options[:nameserver], use_ipv4: @use_ipv4, use_ipv6: @use_ipv6)
|
42
69
|
|
43
70
|
if @options[:format] == 'json'
|
44
71
|
# TODO: to_json
|
45
72
|
puts @ddig
|
46
73
|
else
|
47
|
-
|
74
|
+
puts @ddig
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def resolve_do53
|
79
|
+
ip = Ddig::Ip.new(use_ipv4: @use_ipv4, use_ipv6: @use_ipv6)
|
80
|
+
do53 = Ddig::Resolver::Do53.new(hostname: @hostname, nameservers: @options[:nameserver], ip: ip.ip_type).lookup
|
81
|
+
|
82
|
+
if do53.nil?
|
83
|
+
puts "Error: Could not lookup wit nameserver: #{@options[:nameserver]}"
|
84
|
+
exit
|
85
|
+
end
|
86
|
+
|
87
|
+
do53.a.each do |address|
|
88
|
+
rr_type = 'A'
|
89
|
+
puts "#{@hostname}\t#{rr_type}\t#{address}"
|
90
|
+
end
|
91
|
+
do53.aaaa.each do |address|
|
92
|
+
rr_type = 'AAAA'
|
93
|
+
puts "#{@hostname}\t#{rr_type}\t#{address}"
|
48
94
|
end
|
95
|
+
|
96
|
+
puts
|
97
|
+
puts "# SERVER: #{do53.nameservers.join(', ')}"
|
98
|
+
end
|
99
|
+
|
100
|
+
def resolve_dot
|
101
|
+
dot = Ddig::Resolver::Dot.new(hostname: @hostname, server: @options[:nameserver], port: @options[:port]).lookup
|
102
|
+
|
103
|
+
dot.a.each do |address|
|
104
|
+
rr_type = 'A'
|
105
|
+
puts "#{@hostname}\t#{rr_type}\t#{address}"
|
106
|
+
end
|
107
|
+
dot.aaaa.each do |address|
|
108
|
+
rr_type = 'AAAA'
|
109
|
+
puts "#{@hostname}\t#{rr_type}\t#{address}"
|
110
|
+
end
|
111
|
+
|
112
|
+
puts
|
113
|
+
puts "# SERVER(Address): #{dot.server}"
|
114
|
+
#puts "# SERVER(Hostname): #{dot.server_name}"
|
115
|
+
puts "# PORT: #{dot.port}"
|
49
116
|
end
|
50
117
|
|
51
|
-
def
|
52
|
-
|
118
|
+
def resolve_doh_h1
|
119
|
+
if @options[:nameserver].nil? || @options[:doh_path].nil?
|
120
|
+
puts 'ddig: doh needs option of --doh-path=doh-path'
|
121
|
+
exit
|
122
|
+
end
|
123
|
+
|
124
|
+
doh = Ddig::Resolver::DohH1.new(hostname: @hostname, server: @options[:nameserver], dohpath: @options[:doh_path], port: @options[:port]).lookup
|
125
|
+
|
126
|
+
doh.a.each do |address|
|
127
|
+
rr_type = 'A'
|
128
|
+
puts "#{@hostname}\t#{rr_type}\t#{address}"
|
129
|
+
end
|
130
|
+
doh.aaaa.each do |address|
|
131
|
+
rr_type = 'AAAA'
|
132
|
+
puts "#{@hostname}\t#{rr_type}\t#{address}"
|
133
|
+
end
|
134
|
+
|
135
|
+
puts
|
136
|
+
puts "# SERVER(Hostname): #{doh.server}"
|
137
|
+
puts "# SERVER(Path): #{doh.dohpath}"
|
138
|
+
puts "# PORT: #{doh.port}"
|
53
139
|
end
|
54
140
|
end
|
55
141
|
end
|
data/lib/ddig/ddr.rb
CHANGED
@@ -68,35 +68,39 @@ module Ddig
|
|
68
68
|
do53_v6 = ::Ddig::Resolver::Do53.new(hostname: target, nameservers: [unencrypted_resolver], ip: :ipv6).lookup
|
69
69
|
|
70
70
|
# ipv4
|
71
|
-
unless
|
72
|
-
do53_v4.a.
|
73
|
-
|
74
|
-
|
71
|
+
unless @ip == :ipv6
|
72
|
+
unless do53_v4.nil? || do53_v4.a.nil?
|
73
|
+
do53_v4.a.each do |address|
|
74
|
+
designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: :ipv4)
|
75
|
+
@designated_resolvers << designated_resolver
|
76
|
+
end
|
75
77
|
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
unless do53_v6.nil? || do53_v6.a.nil?
|
79
|
+
do53_v6.a.each do |address|
|
80
|
+
designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: :ipv4)
|
81
|
+
@designated_resolvers << designated_resolver
|
82
|
+
end
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
84
86
|
# ipv6
|
85
|
-
unless
|
86
|
-
do53_v4.aaaa.
|
87
|
-
|
88
|
-
|
87
|
+
unless @ip == :ipv4
|
88
|
+
unless do53_v4.nil? || do53_v4.aaaa.nil?
|
89
|
+
do53_v4.aaaa.each do |address|
|
90
|
+
designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: :ipv6)
|
91
|
+
@designated_resolvers << designated_resolver
|
92
|
+
end
|
89
93
|
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
94
|
+
unless do53_v6.nil? || do53_v6.aaaa.nil?
|
95
|
+
do53_v6.aaaa.each do |address|
|
96
|
+
designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: :ipv6)
|
97
|
+
@designated_resolvers << designated_resolver
|
98
|
+
end
|
95
99
|
end
|
96
100
|
end
|
97
101
|
|
98
102
|
# ipv4hint
|
99
|
-
unless ipv4hint.nil?
|
103
|
+
unless ipv4hint.nil? || @ip == :ipv6
|
100
104
|
ipv4hint.each do |address|
|
101
105
|
ip = :ipv4
|
102
106
|
designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: ip)
|
@@ -105,7 +109,7 @@ module Ddig
|
|
105
109
|
end
|
106
110
|
|
107
111
|
# ipv6hint
|
108
|
-
unless ipv6hint.nil?
|
112
|
+
unless ipv6hint.nil? || @ip == :ipv4
|
109
113
|
ipv6hint.each do |address|
|
110
114
|
ip = :ipv6
|
111
115
|
designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: ip)
|
data/lib/ddig/ip.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ddig
|
4
|
+
class Ip
|
5
|
+
attr_reader :ip_type
|
6
|
+
|
7
|
+
def initialize(use_ipv4: nil, use_ipv6: nil)
|
8
|
+
@use_ipv4 = use_ipv4
|
9
|
+
@use_ipv6 = use_ipv6
|
10
|
+
|
11
|
+
set_ip_type
|
12
|
+
end
|
13
|
+
|
14
|
+
def set_ip_type
|
15
|
+
if @use_ipv4.nil? && self.class.enable_ipv4?
|
16
|
+
@use_ipv4 = true
|
17
|
+
end
|
18
|
+
|
19
|
+
if @use_ipv6.nil? && self.class.enable_ipv6?
|
20
|
+
@use_ipv6 = true
|
21
|
+
end
|
22
|
+
|
23
|
+
if @use_ipv4 && @use_ipv6
|
24
|
+
@ip_type = :all
|
25
|
+
elsif @use_ipv4
|
26
|
+
@ip_type = :ipv4
|
27
|
+
elsif @use_ipv6
|
28
|
+
@ip_type = :ipv6
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.enable_ipv4?
|
33
|
+
ip_list.any? { |addr| addr.ipv4? }
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.enable_ipv6?
|
37
|
+
ip_list.any? { |addr| addr.ipv6? }
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def self.ip_list
|
43
|
+
Socket.ip_address_list.map do |addrinfo|
|
44
|
+
if RUBY_VERSION < '3.1'
|
45
|
+
# for ipaddr gem <= v1.2.2, Not support zone identifiers in IPv6 addresses
|
46
|
+
addr = IPAddr.new(addrinfo.ip_address.split('%').first)
|
47
|
+
else
|
48
|
+
addr = IPAddr.new(addrinfo.ip_address)
|
49
|
+
end
|
50
|
+
|
51
|
+
if !addr.loopback? && !addr.link_local?
|
52
|
+
addr
|
53
|
+
end
|
54
|
+
end.compact
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'resolv'
|
2
|
+
|
3
|
+
module Ddig
|
4
|
+
module Resolver
|
5
|
+
class DnsMessage
|
6
|
+
def self.encode(hostname, typeclass)
|
7
|
+
if hostname.nil?
|
8
|
+
return nil
|
9
|
+
end
|
10
|
+
if typeclass.nil?
|
11
|
+
return nil
|
12
|
+
end
|
13
|
+
|
14
|
+
message = Resolv::DNS::Message.new
|
15
|
+
message.rd = 1 # recursive query
|
16
|
+
message.add_question(hostname, typeclass)
|
17
|
+
|
18
|
+
message.encode
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.decode(payload)
|
22
|
+
if payload.nil?
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
|
26
|
+
Resolv::DNS::Message.decode(payload)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.getresources(payload)
|
30
|
+
if payload.nil?
|
31
|
+
return []
|
32
|
+
end
|
33
|
+
|
34
|
+
response = self.decode(payload)
|
35
|
+
|
36
|
+
return response.answer.map { |name, ttl, resource| resource }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'resolv'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
require_relative 'dns_message'
|
6
|
+
|
7
|
+
module Ddig
|
8
|
+
module Resolver
|
9
|
+
# DNS over HTTPS (HTTP/1.1)
|
10
|
+
class DohH1
|
11
|
+
attr_reader :hostname, :server, :address, :dohpath, :port
|
12
|
+
attr_reader :a, :aaaa
|
13
|
+
|
14
|
+
def initialize(hostname:, server:, address: nil, dohpath:, port: 443)
|
15
|
+
@hostname = hostname
|
16
|
+
@server = server
|
17
|
+
@address = address
|
18
|
+
@dohpath = dohpath
|
19
|
+
@port = port || 443
|
20
|
+
|
21
|
+
@open_timeout = 10
|
22
|
+
end
|
23
|
+
|
24
|
+
def lookup
|
25
|
+
if @server.nil?
|
26
|
+
return nil
|
27
|
+
end
|
28
|
+
|
29
|
+
@a = get_resources(@hostname, Resolv::DNS::Resource::IN::A).map { |resource| resource.address.to_s if resource.is_a?(Resolv::DNS::Resource::IN::A) }.compact
|
30
|
+
|
31
|
+
@aaaa = get_resources(@hostname, Resolv::DNS::Resource::IN::AAAA).map { |resource| resource.address.to_s if resource.is_a?(Resolv::DNS::Resource::IN::AAAA) }.compact
|
32
|
+
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_resources(hostname, typeclass)
|
37
|
+
# send query
|
38
|
+
payload = DnsMessage.encode(hostname, typeclass)
|
39
|
+
|
40
|
+
path_with_query = @dohpath.gsub('{?dns}', '?dns=' + Base64.urlsafe_encode64(payload, padding: false))
|
41
|
+
|
42
|
+
http_response = Net::HTTP.start(@server, @port, use_ssl: true, ipaddr: @address) do |http|
|
43
|
+
header = {}
|
44
|
+
header['Accept'] = 'application/dns-message'
|
45
|
+
#http.open_timeout = @open_timeout
|
46
|
+
|
47
|
+
http.get(path_with_query, header)
|
48
|
+
end
|
49
|
+
|
50
|
+
case http_response
|
51
|
+
when Net::HTTPSuccess
|
52
|
+
# recive answer
|
53
|
+
return DnsMessage.getresources(http_response.body)
|
54
|
+
else
|
55
|
+
http_response.value
|
56
|
+
return []
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/ddig/resolver/dot.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'openssl'
|
2
2
|
require 'resolv'
|
3
3
|
|
4
|
+
require_relative 'dns_message'
|
5
|
+
|
4
6
|
module Ddig
|
5
7
|
module Resolver
|
6
8
|
# DNS over TLS/TCP
|
@@ -12,7 +14,7 @@ module Ddig
|
|
12
14
|
@hostname = hostname
|
13
15
|
@server = server
|
14
16
|
@server_name = server_name
|
15
|
-
@port = port
|
17
|
+
@port = port || 853
|
16
18
|
|
17
19
|
@open_timeout = 3
|
18
20
|
end
|
@@ -33,16 +35,14 @@ module Ddig
|
|
33
35
|
ssl_socket = get_socket
|
34
36
|
|
35
37
|
# send query
|
36
|
-
|
38
|
+
payload = DnsMessage.encode(hostname, typeclass)
|
39
|
+
request = [payload.length].pack('n') + payload
|
37
40
|
|
38
|
-
request = [message.encode.length].pack('n') + message.encode
|
39
41
|
ssl_socket.write(request)
|
40
42
|
|
41
43
|
# recive answer
|
42
44
|
len = ssl_socket.read(2).unpack1('n')
|
43
|
-
|
44
|
-
|
45
|
-
resources = response.answer.map { |name, ttl, resource| resource }
|
45
|
+
resources = DnsMessage.getresources(ssl_socket.read(len))
|
46
46
|
|
47
47
|
resources
|
48
48
|
end
|
@@ -74,21 +74,6 @@ module Ddig
|
|
74
74
|
ssl_socket
|
75
75
|
end
|
76
76
|
end
|
77
|
-
|
78
|
-
def dns_message(hostname, typeclass)
|
79
|
-
if hostname.nil?
|
80
|
-
return nil
|
81
|
-
end
|
82
|
-
if typeclass.nil?
|
83
|
-
return nil
|
84
|
-
end
|
85
|
-
|
86
|
-
message = Resolv::DNS::Message.new
|
87
|
-
message.rd = 1 # recursive query
|
88
|
-
message.add_question(hostname, typeclass)
|
89
|
-
|
90
|
-
message
|
91
|
-
end
|
92
77
|
end
|
93
78
|
end
|
94
79
|
end
|
data/lib/ddig/version.rb
CHANGED
data/lib/ddig.rb
CHANGED
@@ -2,23 +2,28 @@
|
|
2
2
|
|
3
3
|
require_relative "ddig/version"
|
4
4
|
require_relative "ddig/nameserver"
|
5
|
+
require_relative "ddig/ip"
|
5
6
|
require_relative "ddig/resolver/do53"
|
6
7
|
require_relative "ddig/resolver/dot"
|
8
|
+
require_relative "ddig/resolver/doh_h1"
|
7
9
|
require_relative "ddig/ddr"
|
8
10
|
|
9
11
|
module Ddig
|
10
12
|
class Error < StandardError; end
|
11
13
|
|
12
|
-
def self.lookup(hostname, nameservers: nil)
|
14
|
+
def self.lookup(hostname, nameservers: nil, use_ipv4: nil, use_ipv6: nil)
|
13
15
|
@hostname = hostname
|
14
16
|
@nameservers = nameservers
|
17
|
+
@use_ipv4 = use_ipv4
|
18
|
+
@use_ipv6 = use_ipv6
|
15
19
|
|
16
20
|
@nameserver = Ddig::Nameserver.new(nameservers: @nameservers)
|
21
|
+
@ip = Ddig::Ip.new(use_ipv4: @use_ipv4, use_ipv6: @use_ipv6)
|
17
22
|
|
18
|
-
@do53_ipv4 = Ddig::Resolver::Do53.new(hostname: @hostname, nameservers: @nameserver.servers, ip: :ipv4).lookup
|
19
|
-
@do53_ipv6 = Ddig::Resolver::Do53.new(hostname: @hostname, nameservers: @nameserver.servers, ip: :ipv6).lookup
|
23
|
+
@do53_ipv4 = Ddig::Resolver::Do53.new(hostname: @hostname, nameservers: @nameserver.servers, ip: :ipv4).lookup unless @ip.ip_type == :ipv6
|
24
|
+
@do53_ipv6 = Ddig::Resolver::Do53.new(hostname: @hostname, nameservers: @nameserver.servers, ip: :ipv6).lookup unless @ip.ip_type == :ipv4
|
20
25
|
|
21
|
-
@ddr = Ddig::Ddr.new(nameservers: @nameservers)
|
26
|
+
@ddr = Ddig::Ddr.new(nameservers: @nameservers, ip: @ip.ip_type)
|
22
27
|
|
23
28
|
{
|
24
29
|
do53: {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ddig
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Taketo Takashima
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: resolv
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.3.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: base64
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
description: DNS lookup utility for Ruby
|
28
42
|
email:
|
29
43
|
- t.taketo1113@gmail.com
|
@@ -42,8 +56,11 @@ files:
|
|
42
56
|
- lib/ddig/ddr.rb
|
43
57
|
- lib/ddig/ddr/designated_resolver.rb
|
44
58
|
- lib/ddig/ddr/verify_cert.rb
|
59
|
+
- lib/ddig/ip.rb
|
45
60
|
- lib/ddig/nameserver.rb
|
61
|
+
- lib/ddig/resolver/dns_message.rb
|
46
62
|
- lib/ddig/resolver/do53.rb
|
63
|
+
- lib/ddig/resolver/doh_h1.rb
|
47
64
|
- lib/ddig/resolver/dot.rb
|
48
65
|
- lib/ddig/version.rb
|
49
66
|
- sig/ddig.rbs
|