Class: Ddig::Resolver::Dot

Inherits:
Object
  • Object
show all
Defined in:
lib/ddig/resolver/dot.rb

Overview

DNS over TLS/TCP

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hostname:, server:, server_name: nil, port: 853) ⇒ Dot

Returns a new instance of Dot.



14
15
16
17
18
19
20
21
# File 'lib/ddig/resolver/dot.rb', line 14

def initialize(hostname:, server:, server_name: nil, port: 853)
  @hostname = hostname
  @server = server
  @server_name = server_name
  @port = port || 853

  @open_timeout = 3
end

Instance Attribute Details

#aObject (readonly)

Returns the value of attribute a.



12
13
14
# File 'lib/ddig/resolver/dot.rb', line 12

def a
  @a
end

#aaaaObject (readonly)

Returns the value of attribute aaaa.



12
13
14
# File 'lib/ddig/resolver/dot.rb', line 12

def aaaa
  @aaaa
end

#hostnameObject (readonly)

Returns the value of attribute hostname.



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

def hostname
  @hostname
end

#portObject (readonly)

Returns the value of attribute port.



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

def port
  @port
end

#serverObject (readonly)

Returns the value of attribute server.



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

def server
  @server
end

#server_nameObject (readonly)

Returns the value of attribute server_name.



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

def server_name
  @server_name
end

Instance Method Details

#as_jsonObject



79
80
81
82
83
84
85
86
87
88
# File 'lib/ddig/resolver/dot.rb', line 79

def as_json(*)
  {
    a: @a,
    aaaa: @aaaa,
    hostname: @hostname,
    server: @server,
    server_name: @server_name,
    port: @port,
  }
end

#get_resources(hostname, typeclass) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/ddig/resolver/dot.rb', line 35

def get_resources(hostname, typeclass)
  ssl_socket = get_socket

  # send query
  payload = DnsMessage.encode(hostname, typeclass)
  request = [payload.length].pack('n') + payload

  ssl_socket.write(request)

  # recive answer
  len = ssl_socket.read(2).unpack1('n')
  resources = DnsMessage.getresources(ssl_socket.read(len))

  resources
end

#get_socketObject



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
# File 'lib/ddig/resolver/dot.rb', line 51

def get_socket
  begin
    socket = Timeout.timeout(@open_timeout) {
      TCPSocket.open(@server, @port)
    }

    ctx = OpenSSL::SSL::SSLContext.new
    ctx.set_params
    ctx.alpn_protocols = ['dot']

    ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
    ssl_socket.sync_close = true
    unless @server_name.nil?
      ssl_socket.hostname = @server_name
    end

    # connect
    Timeout.timeout(@open_timeout) {
      ssl_socket.connect
      unless @server_name.nil?
        ssl_socket.post_connection_check(@server_name)
      end
    }

    ssl_socket
  end
end

#lookupObject



23
24
25
26
27
28
29
30
31
32
33
# File 'lib/ddig/resolver/dot.rb', line 23

def lookup
  if @server.nil?
    return nil
  end

  @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

  @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

  self
end

#to_cliObject



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/ddig/resolver/dot.rb', line 94

def to_cli
  @a.each do |address|
    rr_type = 'A'
    puts "#{@hostname}\t#{rr_type}\t#{address}"
  end
  @aaaa.each do |address|
    rr_type = 'AAAA'
    puts "#{@hostname}\t#{rr_type}\t#{address}"
  end

  puts
  puts "# SERVER(Address): #{@server}"
  #puts "# SERVER(Hostname): #{@server_name}"
  puts "# PORT: #{@port}"
end

#to_json(*args) ⇒ Object



90
91
92
# File 'lib/ddig/resolver/dot.rb', line 90

def to_json(*args)
  as_json.to_json
end