Module: Rex::Proto::DNS::CustomNameserverProvider
- Defined in:
- lib/rex/proto/dns/custom_nameserver_provider.rb
Overview
Provides a DNS resolver the ability to use different nameservers for different requests, based on the domain being queried.
Defined Under Namespace
Classes: CommSink
Constant Summary collapse
Class Method Summary collapse
Instance Method Summary collapse
-
#add_upstream_rule(resolvers, comm: nil, wildcard: '*', index: -1)) ⇒ Object
Add a custom nameserver entry to the custom provider.
- #flush ⇒ Object
-
#has_config? ⇒ Boolean
Check whether or not there is configuration data in Metasploit’s configuration file which is persisted on disk.
- #init ⇒ Object
-
#load_config ⇒ Object
Load the custom settings from the MSF config file.
-
#reinit ⇒ Object
Reinitialize the configuration to its original state.
-
#remove_ids(ids) ⇒ Array<UpstreamRule>
Remove upstream rules with the given indexes Ignore entries that are not found.
-
#save_config ⇒ Object
Save the custom settings to the MSF config file.
- #set_framework(framework) ⇒ Object
-
#upstream_resolvers_for_packet(packet) ⇒ Array<Array>
The nameservers that match the given packet.
- #upstream_rules ⇒ Object
Class Method Details
.extended(mod) ⇒ Object
187 188 189 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 187 def self.extended(mod) mod.init end |
Instance Method Details
#add_upstream_rule(resolvers, comm: nil, wildcard: '*', index: -1)) ⇒ Object
Add a custom nameserver entry to the custom provider.
124 125 126 127 128 129 130 131 132 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 124 def add_upstream_rule(resolvers, comm: nil, wildcard: '*', index: -1) resolvers = [resolvers] if resolvers.is_a?(String) # coerce into an array of strings @upstream_rules.insert(index, UpstreamRule.new( wildcard: wildcard, resolvers: resolvers, comm: comm )) end |
#flush ⇒ Object
149 150 151 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 149 def flush @upstream_rules.clear end |
#has_config? ⇒ Boolean
Check whether or not there is configuration data in Metasploit’s configuration file which is persisted on disk.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 70 def has_config? config = Msf::Config.load version = config.fetch(CONFIG_KEY_BASE, {}).fetch('configuration_version', nil) if version.nil? @logger.info 'DNS configuration can not be loaded because the version is missing' return false end their_version = Rex::Version.new(version) if their_version > CONFIG_VERSION # if the config is newer, it's incompatible (we only guarantee backwards compat) @logger.info "DNS configuration version #{their_version} can not be loaded because it is too new" return false end my_minimum_version = Rex::Version.new(CONFIG_VERSION.canonical_segments.first.to_s) if their_version < my_minimum_version # can not be older than our major version @logger.info "DNS configuration version #{their_version} can not be loaded because it is too old" return false end true end |
#init ⇒ Object
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 36 def init @upstream_rules = [] resolvers = [UpstreamResolver.create_static] if @config[:nameservers].empty? # if no nameservers are specified, fallback to the system resolvers << UpstreamResolver.create_system else # migrate the originally configured name servers resolvers += @config[:nameservers].map(&:to_s) @config[:nameservers].clear end add_upstream_rule(resolvers) nil end |
#load_config ⇒ Object
Load the custom settings from the MSF config file
109 110 111 112 113 114 115 116 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 109 def load_config unless has_config? raise ResolverError.new('There is no compatible configuration data to load') end load_config_entries load_config_static_hostnames end |
#reinit ⇒ Object
Reinitialize the configuration to its original state.
55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 55 def reinit parse_config_file parse_environment_variables self.static_hostnames.flush self.static_hostnames.parse_hosts_file init cache.flush if respond_to?(:cache) nil end |
#remove_ids(ids) ⇒ Array<UpstreamRule>
Remove upstream rules with the given indexes Ignore entries that are not found
139 140 141 142 143 144 145 146 147 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 139 def remove_ids(ids) removed = [] ids.sort.reverse.each do |id| upstream_rule = @upstream_rules.delete_at(id) removed << upstream_rule if upstream_rule end removed.reverse end |
#save_config ⇒ Object
Save the custom settings to the MSF config file
96 97 98 99 100 101 102 103 104 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 96 def save_config new_config = { 'configuration_version' => CONFIG_VERSION.to_s } Msf::Config.save(CONFIG_KEY_BASE => new_config) save_config_upstream_rules save_config_static_hostnames end |
#set_framework(framework) ⇒ Object
191 192 193 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 191 def set_framework(framework) self.feature_set = framework.features end |
#upstream_resolvers_for_packet(packet) ⇒ Array<Array>
The nameservers that match the given packet
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 158 def upstream_resolvers_for_packet(packet) unless feature_set.enabled?(Msf::FeatureManager::DNS) return super end # Leaky abstraction: a packet could have multiple question entries, # and each of these could have different nameservers, or travel via # different comm channels. We can't allow DNS leaks, so for now, we # will throw an error here. results_from_all_questions = [] packet.question.each do |question| name = question.qname.to_s upstream_rule = self.upstream_rules.find { |ur| ur.matches_name?(name) } if upstream_rule upstream_resolvers = upstream_rule.resolvers else # Fall back to default nameservers upstream_resolvers = super end results_from_all_questions << upstream_resolvers.uniq end results_from_all_questions.uniq! if results_from_all_questions.size != 1 raise ResolverError.new('Inconsistent nameserver entries attempted to be sent in the one packet') end results_from_all_questions[0] end |
#upstream_rules ⇒ Object
195 196 197 |
# File 'lib/rex/proto/dns/custom_nameserver_provider.rb', line 195 def upstream_rules @upstream_rules.dup end |