ddig 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|