# frozen_string_literal: true # # Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com) # # ronin-support is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published # by the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # ronin-support is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with ronin-support. If not, see . # require 'ronin/support/network/dns' require 'ronin/support/network/dns/idn' require 'ronin/support/network/ip' require 'ronin/support/network/tld' require 'ronin/support/network/public_suffix' module Ronin module Support module Network # # Represents a host or host name. # # ## Examples # # host = Host.new('www.example.com') # # Resolve parent domain: # # host.domain # # => # # # Resolve IP addresses: # # host.get_address # # => "172.67.128.149" # host.get_addresses # # => ["104.21.2.18", "172.67.128.149"] # host.get_ip # # => # # host.get_ips # # => [#, #] # host.ip # # => # # host.ips # # => [#, #] # # Other DNS queries: # # host = Host.new('www.github.com') # host.get_record(:txt) # # => # # host.get_records(:txt) # # => [#, ...] # host.get_cname_record # # => #, @ttl=3500> # host.get_cname # # => "github.com" # host.cname # # => "github.com" # host.get_mx_records # # => [#, @preference=1, @ttl=3600>, ...] # host.get_mailservers # # => ["alt1.aspmx.l.google.com", # # "alt4.aspmx.l.google.com", # # "alt3.aspmx.l.google.com", # # "alt2.aspmx.l.google.com", # # "aspmx.l.google.com"] # host.mailservers # # => ["alt1.aspmx.l.google.com", # # "alt4.aspmx.l.google.com", # # "alt3.aspmx.l.google.com", # # "alt2.aspmx.l.google.com", # # "aspmx.l.google.com"] # host.get_ns_records # # => [#, @ttl=900>, ...] # host.get_nameservers # # => ["dns3.p08.nsone.net", # # "ns-1707.awsdns-21.co.uk", # # "dns2.p08.nsone.net", # # "ns-1283.awsdns-32.org", # # "dns4.p08.nsone.net", # # "ns-421.awsdns-52.com", # # "dns1.p08.nsone.net", # # "ns-520.awsdns-01.net"] # host.nameservers # # => ["dns3.p08.nsone.net", # # "ns-1707.awsdns-21.co.uk", # # "dns2.p08.nsone.net", # # "ns-1283.awsdns-32.org", # # "dns4.p08.nsone.net", # # "ns-421.awsdns-52.com", # # "dns1.p08.nsone.net", # # "ns-520.awsdns-01.net"] # host.get_soa_record # # => #, @rname=#, @serial=1, @refresh=7200, @retry=900, @expire=1209600, @minimum=86400, @ttl=880> # host.soa_record # # => #, @rname=#, @serial=1, @refresh=7200, @retry=900, @expire=1209600, @minimum=86400, @ttl=880> # host.get_txt_record # # => # # host.get_txt_string # # => "stripe-verification=f88ef17321660a01bab1660454192e014defa29ba7b8de9633c69d6b4912217f" # host.get_txt_records # # => [#, ...] # host.get_txt_strings # # => ["apple-domain-verification=RyQhdzTl6Z6x8ZP4", # # "MS=ms58704441", # # "atlassian-domain-verification=jjgw98AKv2aeoYFxiL/VFaoyPkn3undEssTRuMg6C/3Fp/iqhkV4HVV7WjYlVeF8", # # "MS=6BF03E6AF5CB689E315FB6199603BABF2C88D805", # # "v=spf1 ip4:192.30.252.0/22 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com include:spf.protection.outlook.com include:mail.zendesk.com include:_spf.salesforce.com include:servers.mcsv.net ip4:166.78.69.169 ip4:1", # # "66.78.69.170 ip4:166.78.71.131 ip4:167.89.101.2 ip4:167.89.101.192/28 ip4:192.254.112.60 ip4:192.254.112.98/31 ip4:192.254.113.10 ip4:192.254.113.101 ip4:192.254.114.176 ip4:62.253.227.114 ~all", # # "docusign=087098e3-3d46-47b7-9b4e-8a23028154cd", # # "google-site-verification=UTM-3akMgubp6tQtgEuAkYNYLyYAvpTnnSrDMWoDR3o", # # "stripe-verification=f88ef17321660a01bab1660454192e014defa29ba7b8de9633c69d6b4912217f", # # "adobe-idp-site-verification=b92c9e999aef825edc36e0a3d847d2dbad5b2fc0e05c79ddd7a16139b48ecf4b", # # "MS=ms44452932"] # host.txt_strings # # => ["apple-domain-verification=RyQhdzTl6Z6x8ZP4", # # "MS=ms58704441", # # "atlassian-domain-verification=jjgw98AKv2aeoYFxiL/VFaoyPkn3undEssTRuMg6C/3Fp/iqhkV4HVV7WjYlVeF8", # # "MS=6BF03E6AF5CB689E315FB6199603BABF2C88D805", # # "v=spf1 ip4:192.30.252.0/22 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com include:spf.protection.outlook.com include:mail.zendesk.com include:_spf.salesforce.com include:servers.mcsv.net ip4:166.78.69.169 ip4:1", # # "66.78.69.170 ip4:166.78.71.131 ip4:167.89.101.2 ip4:167.89.101.192/28 ip4:192.254.112.60 ip4:192.254.112.98/31 ip4:192.254.113.10 ip4:192.254.113.101 ip4:192.254.114.176 ip4:62.253.227.114 ~all", # # "docusign=087098e3-3d46-47b7-9b4e-8a23028154cd", # # "google-site-verification=UTM-3akMgubp6tQtgEuAkYNYLyYAvpTnnSrDMWoDR3o", # # "stripe-verification=f88ef17321660a01bab1660454192e014defa29ba7b8de9633c69d6b4912217f", # # "adobe-idp-site-verification=b92c9e999aef825edc36e0a3d847d2dbad5b2fc0e05c79ddd7a16139b48ecf4b", # # "MS=ms44452932"] # # @api public # # @since 1.0.0 # class Host # The host name. # # @return [String] attr_reader :name # # Initializes the host. # # @param [String] name # The host's hostname. # # @example # host = Host.new('www.example.com') # def initialize(name) @name = name end # # Determines if the hostname is an [IDN] hostname. # # [IDN]: https://en.wikipedia.org/wiki/Internationalized_domain_name # # @return [Boolean] # # @example # host = Network::Host.new("www.詹姆斯.com') # host.idn? # # => true # def idn? @name !~ /\A[A-Za-z0-9._-]+\z/ end alias unicode? idn? # # Determines if the hostname is a [punycode] hostnmae. # # [punycode]: https://en.wikipedia.org/wiki/Punycode # # @return [Boolean] # # @example # host = Network::Host.new("www.xn--8ws00zhy3a.com") # host.punycode? # # => true # def punycode? @name.include?('xn--') end # # Converts the hostname to it's [punycode] version. # # [punycode]: https://en.wikipedia.org/wiki/Punycode # # @return [Host] # The new host containing the punycode version of the hostname. # # @example # host = Network::Host.new("www.詹姆斯.com") # host.punycode # # => # # def punycode self.class.new(DNS::IDN.to_ascii(@name)) end # # The Top-Level Domain of the hostnmae. # # @return [String] # The last component of the hostname. # # @raise [InvalidHostname] # The hostname does not end with a valid TLD. # # @example # host = Host.new('foo.bar.example.co.uk') # host.tld # # => "uk" # def tld @tld ||= TLD.list.split(@name).last end # # The public suffix of the hostname. # # @return [String] # The suffix of the hostname (ex: `.co.uk`). # # @raise [InvalidHostname] # The hostname does not end with a valid suffix. # # @example # host = Host.new('foo.bar.example.co.uk') # host.suffix # # => "co.uk" # def suffix @suffix ||= PublicSuffix.list.split(@name).last end # # Returns the associated domain for the hostname. # # @return [Domain] # The domain object derived from the hostname, without any sub-domain # components (ex: `www`). # # @raise [InvalidHostname] # The hostname does not end with a valid suffix. # # @example # host = Host.new('foo.bar.example.co.uk') # host.domain # # => # # # @note This method returns memoized data. # def domain @domain ||= begin domain, suffix = PublicSuffix.list.split(@name) if (last_dot = domain.rindex('.')) domain = domain[(last_dot + 1)..] end Domain.new("#{domain}.#{suffix}") end end # # Creates a sub-domain under the hostname. # # @param [String] subname # The sub-name to add under the hostname. # # @return [Host] # The new sub-domain. # # @example # host = Network::Host.new('example.com') # host.subdomain('www') # # => # # def subdomain(subname) Host.new("#{subname}.#{@name}") end # # Changes the suffix of the hostname. # # @param [String] new_suffix # The new suffix for the hostname. # # @return [Host] # The new host object with the new suffix. # # @raise [PublicSuffix::InvalidHostname] # The hostname does not end with a valid suffix. # # @example # host = Host.new('www.example.co.uk') # host.change_suffix('.com') # # => # # def change_suffix(new_suffix) name, _suffix = PublicSuffix.list.split(@name) new_suffix = new_suffix.to_s if new_suffix.start_with?('.') return self.class.new("#{name}#{new_suffix}") else return self.class.new("#{name}.#{new_suffix}") end end alias change_tld change_suffix # # Enumerates over every hostname with a different TLD. # # @yield [host] # The given block will be passed each hostname with a different TLD. # # @yieldparam [Host] host # The new host object with a different TLD. # # @return [Enumerator] # If no block is given, an enumerator will be returned. # def each_tld return enum_for(__method__) unless block_given? TLD.list.each do |tld| yield change_suffix(tld) end return nil end # # Enumerates over every hostname with a different public suffix. # # @param [:icann, :private, nil] type # The optional specific type of suffixes to enumerate. # # @yield [host] # The given block will be passed each hostname with a different # public suffix. # # @yieldparam [Host] host # The new host object with a different public suffix. # # @return [Enumerator] # If no block is given, an enumerator will be returned. # def each_suffix(type: nil) return enum_for(__method__, type: type) unless block_given? PublicSuffix.list.each do |suffix| unless suffix.wildcard? if type.nil? || (suffix.type == type) yield change_suffix(suffix) end end end return nil end # # Looks up the address of a hostname. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [String, nil] # The address of the hostname. # # @example # host = Host.new('www.example.com') # host.get_address # # => "172.67.128.149" # def get_address(**kwargs) DNS.resolver(**kwargs).get_address(@name) end alias lookup get_address # # Looks up all addresses of a hostname. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # The addresses of the hostname. # # @example # host = Host.new('www.example.com') # host.get_addresses # # => ["104.21.2.18", "172.67.128.149"] # def get_addresses(**kwargs) DNS.resolver(**kwargs).get_addresses(@name) end # # The addreses of the hostname. # # @return [Array] # The addresses associated with the hostname. # # @example # host = Host.new('www.example.com') # host.addresses # # => ["104.21.2.18", "172.67.128.149"] # # @note This method returns memoized data. # def addresses @addresses ||= get_addresses end # # Determines if the hostname has any addresses. # # @return [Boolean] # # @example # host = Host.new('www.example.com') # host.has_addresses? # # => trun # host = Host.new('www.does-not-exist.com') # host.has_addresses? # # => false # def has_addresses? !addresses.empty? end # # Looks up the IPs of the host. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [String, nil] # The IP for the host. # # @example # host = Host.new('www.example.com') # host.get_ip # # => # # def get_ip(**kwargs) if (address = get_address(**kwargs)) IP.new(address) end end # # Looks up all IPs for the host. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # The IPs for the host. # # @example # host = Host.new('www.example.com') # host.get_ips # # => [#, #] # def get_ips(**kwargs) get_addresses(**kwargs).map { |address| IP.new(address) } end # # The IPs for the host. # # @return [Array] # The IPs of the host or an empty Array if the host has no IP # addresses. # # @example # host = Host.new('www.example.com') # host.ips # # => [#, #] # # @note This method returns memoized data. # def ips @ips ||= get_ips end # # The IP for the host. # # @return [IP, nil] # The IP for the host or `nil` if the host has no IP addresses. # # @example # host = Host.new('www.example.com') # host.ip # # => # # def ip ips.first end # # Queries a single matching DNS record for the host name. # # @param [String, nil] name # The optional record name to query. # # @param [:a, :aaaa, :any, :cname, :hinfo, :loc, :minfo, :mx, :ns, :ptr, :soa, :srv, :txt, :wks] record_type # The record type to query for. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource, nil] # The matching DNS records or `nil` if no matching DNS records # could be found. # # @example # host = Host.new('www.example.com') # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource # @see DNS::Resolver#get_record # def get_record(name=nil,record_type,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_record(name,record_type) end # # Queries all matching DNS records for the host name. # # @param [String, nil] name # The optional record name to query. # # @param [:a, :aaaa, :any, :cname, :hinfo, :loc, :minfo, :mx, :ns, :ptr, :soa, :srv, :txt, :wks] record_type # The record type to query for. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All matching DNS records. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource # @see DNS::Resolver#get_records # def get_records(name=nil,record_type,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_records(name,record_type) end # # Queries all records of the host name using the `ANY` DNS query. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All of the DNS records belonging to the host name. # # @see DNS::Resolver#get_any_records # def get_any_records(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_any_records(name) end # # Queries the `CNAME` record for the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource::IN::CNAME, nil] # The `CNAME` record or `nil` if the host name has no `CNAME` # record. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/CNAME # @see DNS::Resolver#get_cname_record # def get_cname_record(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_cname_record(name) end # # Queries the canonical name for the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [String, nil] # The canonical name for the host or `nil` if the host has no # `CNAME` record. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/CNAME # @see DNS::Resolver#get_cname # def get_cname(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_cname(name) end # # The `CNAME` record for the host. # # @return [String, nil] # The `CNAME` host name. # # @note This method returns memoized data. # # @see #get_cname # def cname @cname ||= get_cname end # # Queries the `HINFO` record for the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource::IN::HINFO, nil] # The `HINFO` DNS record or `nil` if the host name has no `HINFO` # record. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/HINFO # @see DNS::Resolver#get_hinfo_record # def get_hinfo_record(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_hinfo_record(name) end # # The `HINFO` record for the host. # # @return [Resolv::DNS::Resource::IN::HINFO, nil] # The `HINFO` DNS record or `nil` if the host name has no `HINFO` # record. # # @note This method returns memoized data. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/HINFO # @see #get_hinfo_record # def hinfo_record @hinfo_record ||= get_hinfo_record end # # Queries the first `A` record belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource::IN::A, nil] # The first `A` DNS record or `nil` if the host name has no `A` # records. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/IN/A # @see DNS::Resolver#get_a_record # def get_a_record(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_a_record(name) end # # Queries the first IPv4 address belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [String, nil] # The first IPv4 address belonging to the host name. # # @see DNS::Resolver#get_a_address # def get_a_address(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_a_address(name) end # # Queries all `A` records belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All of the `A` DNS records belonging to the host name. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/IN/A # @see DNS::Resolver#get_a_records # def get_a_records(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_a_records(name) end # # Queries all IPv4 addresses belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All of the IPv4 addresses belonging to the host name. # # @see DNS::Resolver#get_a_addresses # def get_a_addresses(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_a_addresses(name) end # # Queries the first `AAAA` DNS records belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource::IN::AAAA, nil] # The first `AAAA` DNS record or `nil` if the host name has no # `AAAA` records. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/IN/AAAA # @see DNS::Resolver#get_aaaa_record # def get_aaaa_record(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_aaaa_record(name) end # # Queries the first IPv6 address belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [String, nil] # The first IPv6 address or `nil` if the host name has no IPv6 # addresses. # # @see DNS::Resolver#get_aaaa_address # def get_aaaa_address(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_aaaa_address(name) end # # Queries all `AAAA` DNS records belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All of the `AAAA` DNS records belonging to the host name. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/IN/AAAA # @see DNS::Resolver#get_aaaa_records # def get_aaaa_records(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_aaaa_records(name) end # # Queries all IPv6 addresses belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All IPv6 addresses belonging to the host name. # # @see DNS::Resolver#get_aaaa_addresses # def get_aaaa_addresses(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_aaaa_addresses(name) end # # Queries all `SRV` DNS records belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All `SRV` DNS records belonging to the host name. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/IN/SRV # @see DNS::Resolver#get_srv_records # def get_srv_records(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_srv_records(name) end # # Queries all `WKS` (Well-Known-Service) DNS records belonging to the # host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All `WKS` DNS records belonging to the host name. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/IN/WKS # @see DNS::Resolver#get_wks_records # def get_wks_records(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_wks_records(name) end # # Queries the `LOC` (Location) DNS record of the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource::LOC, nil] # The `LOC` DNS record of the host name or `nil` if the host name # has no `LOC` record. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/LOC # @see DNS::Resolver#get_loc_record # def get_loc_record(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_loc_record(name) end # # Queries the `MINFO` (Machine-Info) DNS record of the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource::MINFO, nil] # The `MINFO` DNS record of the host name or `nil` if the host name # has no `MINFO` record. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/MINFO # @see DNS::Resolver#get_minfo_record # def get_minfo_record(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_minfo_record(name) end # # Queries all `MX` DNS records belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All `MX` DNS records belonging to the host name. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/MX # @see DNS::Resolver#get_mx_records # def get_mx_records(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_mx_records(name) end # # Queries the mailservers for the host name. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # The host names of the mailservers serving the given host name. # # @see DNS::Resolver#get_mailservers # def get_mailservers(**kwargs) DNS.resolver(**kwargs).get_mailservers(@name) end # # The mailservers for the host. # # @return [Array] # The mailserver host names for the host. # # @note This method returns memoized data. # # @see #get_mailservers # def mailservers @mailservers ||= get_mailservers end # # Determines if the hostname has any associated mailservers? # # @return [Boolean] # def has_mailservers? !mailservers.empty? end # # Queries all `NS` DNS records belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All `NS` DNS records belonging to the host name. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/NS # @see DNS::Resolver#get_ns_records # def get_ns_records(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_ns_records(name) end # # Queries the nameservers for the host name. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # The host names of the nameservers serving the given host name. # # @see DNS::Resolver#get_nameservers # def get_nameservers(**kwargs) DNS.resolver(**kwargs).get_nameservers(@name) end # # The nameservers for the host. # # @return [Array] # The nameserver IP addresses for the host. # # @note This method returns memoized data. # # @see #get_nameservers # def nameservers @nameservers ||= get_nameservers end # # Determines if the hostname has any associated nameservers? # # @return [Boolean] # def has_nameservers? !nameservers.empty? end # # Queries the first `SOA` DNS record belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource::SOA, nil] # The first `SOA` DNS record for the host name or `nil` if the host # name has no `SOA` records. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/SOA # @see DNS::Resolver#get_soa_record # def get_soa_record(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_soa_record(name) end # # The `SOA` record for the host. # # @return [Resolv::DNS::Resource::SOA, nil] # The first `SOA` DNS record for the host name or `nil` if the host # name has no `SOA` records. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/SOA # @see #get_soa_record # # @note This method returns memoized data. # def soa_record @soa_record ||= get_soa_record end # # Queiries the first `TXT` DNS record belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Resolv::DNS::Resource::TXT, nil] # The first `TXT` DNS record for the host name or `nil` if the host # name has no `TXT` records. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/TXT # @see DNS::Resolver#get_txt_record # def get_txt_record(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_txt_record(name) end # # Queries the first `TXT` string belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [String, nil] # The first `TXT` string belonging to the host name or `nil` if the # host name has no `TXT` records. # # @see DNS::Resolver#get_txt_string # def get_txt_string(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_txt_string(name) end # # Queries all `TXT` DNS records belonging to the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All of the `TXT` DNS records belonging to the host name. # # @see https://rubydoc.info/stdlib/resolv/Resolv/DNS/Resource/TXT # @see DNS::Resolver#get_txt_records # def get_txt_records(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_txt_records(name) end # # Queries all of the `TXT` string values of the host name. # # @param [String, nil] name # The optional record name to query. # # @param [Hash{Symbol => Object}] kwargs # Additional keyword arguments. # # @option [Array, String, nil] :nameservers # Optional DNS nameserver(s) to query. # # @option [String, nil] :nameserver # Optional DNS nameserver to query. # # @return [Array] # All `TXT` string values belonging of the host name. # # @see DNS::Resolver#get_txt_strings # def get_txt_strings(name=nil,**kwargs) name = if name then "#{name}.#{@name}" else @name end DNS.resolver(**kwargs).get_txt_strings(name) end # # The `TXT` strings for the host. # # @return [Array] # All `TXT` string values belonging of the host name. # # @note This method returns memoized data. # # @see #get_txt_strings # def txt_strings @txt_strings ||= get_txt_strings end # # Determines if the host name is registered. # # @return [Boolean] # # @note This method will query `8.8.8.8` which supports `ANY` queries. # # @example # host = Network::Host.new('www.example.com') # host.registered? # # => true # bad_host = Network::Host.new('foo.example.com') # bad_host.registered? # # => false # def registered? !get_any_records(nameserver: '8.8.8.8').empty? end # # Determines if the host name is not registered. # # @return [Boolean] # # @see #registered? # def unregistered? !registered? end # # Converts the host to a String. # # @return [String] # The host's hostname. # # @example # host = Host.new('www.example.com') # host.to_s # # => "www.example.com" # def to_s @name.to_s end # # Converts the host to a String. # # @return [String] # def to_str @name.to_str end # # Inspects the host. # # @return [String] # The inspected host object. # def inspect "#<#{self.class}: #{@name}>" end end end end end require 'ronin/support/network/domain'