Class: Ddig::Ddr

Inherits:
Object
  • Object
show all
Defined in:
lib/ddig/ddr.rb,
lib/ddig/ddr/verify_cert.rb,
lib/ddig/ddr/designated_resolver.rb

Overview

DDR client (Discovery of Designated Resolvers)

Defined Under Namespace

Classes: DesignatedResolver, VerifyCert

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(nameservers: nil, ip: nil) ⇒ Ddr

Returns a new instance of Ddr.



13
14
15
16
17
18
19
20
21
22
23
# File 'lib/ddig/ddr.rb', line 13

def initialize(nameservers: nil, ip: nil)
  @ip = ip

  @nameserver = Ddig::Nameserver.new(nameservers: nameservers)
  set_nameservers

  # discover designated resolvers
  query_svcb_records
  discover_designated_resolvers
  verify_discovery
end

Instance Attribute Details

#designated_resolversObject (readonly)

Returns the value of attribute designated_resolvers.



11
12
13
# File 'lib/ddig/ddr.rb', line 11

def designated_resolvers
  @designated_resolvers
end

#ipObject (readonly)

Returns the value of attribute ip.



10
11
12
# File 'lib/ddig/ddr.rb', line 10

def ip
  @ip
end

#nameserversObject (readonly)

Returns the value of attribute nameservers.



10
11
12
# File 'lib/ddig/ddr.rb', line 10

def nameservers
  @nameservers
end

#svcb_recordsObject (readonly)

Returns the value of attribute svcb_records.



11
12
13
# File 'lib/ddig/ddr.rb', line 11

def svcb_records
  @svcb_records
end

Instance Method Details

#as_jsonObject



133
134
135
136
137
138
139
140
# File 'lib/ddig/ddr.rb', line 133

def as_json(*)
  {
    designated_resolvers: @designated_resolvers.map { |designated_resolver| designated_resolver.as_json },
    hostname: @hostname,
    nameservers: @nameservers,
    ip: @ip,
  }
end

#discover_designated_resolversObject

Discovery Designated Resolvers from SVCB RR Set ref. www.rfc-editor.org/rfc/rfc9461.html



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/ddig/ddr.rb', line 47

def discover_designated_resolvers
  @designated_resolvers = []

  @svcb_records.each do |item|
    unencrypted_resolver = item[:unencrypted_resolver]
    svcb_record = item[:svcb_record]

    target = svcb_record.target.to_s
    priority = svcb_record.priority
    protocols = svcb_record.params[:alpn].protocol_ids
    port = svcb_record.params[:port]&.port
    dohpath = svcb_record.params[:dohpath]&.template
    ipv4hint = svcb_record.params[:ipv4hint]&.addresses
    ipv6hint = svcb_record.params[:ipv6hint]&.addresses

    # Skip AliasMode of SVCB RR
    if priority.zero?
      next
    end

    protocols.each do |protocol|
      do53_v4 = ::Ddig::Resolver::Do53.new(hostname: target, nameservers: [unencrypted_resolver], ip: :ipv4).lookup
      do53_v6 = ::Ddig::Resolver::Do53.new(hostname: target, nameservers: [unencrypted_resolver], ip: :ipv6).lookup

      # ipv4
      unless @ip == :ipv6
        unless do53_v4.nil? || do53_v4.a.nil?
          do53_v4.a.each do |address|
            designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: :ipv4)
            @designated_resolvers << designated_resolver
          end
        end
        unless do53_v6.nil? || do53_v6.a.nil?
          do53_v6.a.each do |address|
            designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: :ipv4)
            @designated_resolvers << designated_resolver
          end
        end
      end

      # ipv6
      unless @ip == :ipv4
        unless do53_v4.nil? || do53_v4.aaaa.nil?
          do53_v4.aaaa.each do |address|
            designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: :ipv6)
            @designated_resolvers << designated_resolver
          end
        end
        unless do53_v6.nil? || do53_v6.aaaa.nil?
          do53_v6.aaaa.each do |address|
            designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: :ipv6)
            @designated_resolvers << designated_resolver
          end
        end
      end

      # ipv4hint
      unless ipv4hint.nil? || @ip == :ipv6
        ipv4hint.each do |address|
          ip = :ipv4
          designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: ip)
          @designated_resolvers << designated_resolver
        end
      end

      # ipv6hint
      unless ipv6hint.nil? || @ip == :ipv4
        ipv6hint.each do |address|
          ip = :ipv6
          designated_resolver = ::Ddig::Ddr::DesignatedResolver.new(unencrypted_resolver: unencrypted_resolver, target: target, protocol: protocol, port: port, dohpath: dohpath, address: address.to_s, ip: ip)
          @designated_resolvers << designated_resolver
        end
      end
    end
  end

  @designated_resolvers.uniq! { |designated_resolver| designated_resolver.uniq_key }
end

#query_svcb_recordsObject



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/ddig/ddr.rb', line 25

def query_svcb_records
  @svcb_records = []

  if @nameservers.empty?
    return @svcb_records
  end

  @nameservers.each do |nameserver|
    svcb_rrset = Resolv::DNS.open(nameserver: nameserver) do |dns|
      dns.getresources('_dns.resolver.arpa', Resolv::DNS::Resource::IN::SVCB)
    end

    svcb_rrset.sort_by!(&:priority)

    @svcb_records += svcb_rrset.map { |svcb_record| { unencrypted_resolver: nameserver, svcb_record: svcb_record } }
  end

  @svcb_records
end

#set_nameserversObject



155
156
157
158
159
160
161
162
163
164
165
# File 'lib/ddig/ddr.rb', line 155

def set_nameservers
  @nameservers = @nameserver.servers

  if @ip == :ipv4
    @nameservers = @nameserver.servers_ipv4
  end

  if @ip == :ipv6
    @nameservers = @nameserver.servers_ipv6
  end
end

#to_cliObject



146
147
148
149
150
151
152
153
# File 'lib/ddig/ddr.rb', line 146

def to_cli
  @designated_resolvers.each do |designated_resolver|
    puts designated_resolver.to_s
  end

  puts
  puts "# SERVER: #{@nameservers.join(', ')}"
end

#to_json(*args) ⇒ Object



142
143
144
# File 'lib/ddig/ddr.rb', line 142

def to_json(*args)
  as_json.to_json
end

#verify_discoveryObject



126
127
128
129
130
131
# File 'lib/ddig/ddr.rb', line 126

def verify_discovery
  @designated_resolvers.map! do |designated_resolver|
    designated_resolver.verify
    designated_resolver
  end
end