ronin 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. data/.gitignore +11 -0
  2. data/ChangeLog.md +28 -10
  3. data/Gemfile +1 -1
  4. data/README.md +14 -41
  5. data/Rakefile +3 -0
  6. data/gemspec.yml +14 -15
  7. data/lib/bond/completions/ronin.rb +0 -5
  8. data/lib/ronin/address.rb +17 -0
  9. data/lib/ronin/author.rb +1 -1
  10. data/lib/ronin/database/database.rb +11 -3
  11. data/lib/ronin/email_address.rb +33 -0
  12. data/lib/ronin/host_name.rb +57 -6
  13. data/lib/ronin/ip_address.rb +49 -5
  14. data/lib/ronin/license.rb +1 -1
  15. data/lib/ronin/mac_address.rb +39 -1
  16. data/lib/ronin/model/has_license.rb +12 -3
  17. data/lib/ronin/model/importable.rb +65 -0
  18. data/lib/ronin/repository.rb +12 -4
  19. data/lib/ronin/spec/database.rb +1 -1
  20. data/lib/ronin/tcp_port.rb +3 -12
  21. data/lib/ronin/udp_port.rb +2 -11
  22. data/lib/ronin/ui/cli/commands/emails.rb +0 -45
  23. data/lib/ronin/ui/cli/commands/hosts.rb +4 -31
  24. data/lib/ronin/ui/cli/commands/ips.rb +4 -30
  25. data/lib/ronin/ui/cli/commands/urls.rb +5 -45
  26. data/lib/ronin/ui/cli/model_command.rb +17 -27
  27. data/lib/ronin/ui/cli/resources_command.rb +25 -1
  28. data/lib/ronin/ui/cli/script_command.rb +1 -1
  29. data/lib/ronin/ui/console/context.rb +1 -1
  30. data/lib/ronin/url.rb +43 -1
  31. data/lib/ronin/version.rb +1 -1
  32. data/ronin.gemspec +1 -1
  33. data/spec/email_address_spec.rb +20 -0
  34. data/spec/host_name_spec.rb +20 -0
  35. data/spec/ip_address_spec.rb +104 -0
  36. data/spec/mac_address_spec.rb +20 -0
  37. data/spec/url_spec.rb +24 -0
  38. metadata +118 -155
  39. data/lib/ronin/network/mixins.rb +0 -27
  40. data/lib/ronin/network/mixins/esmtp.rb +0 -165
  41. data/lib/ronin/network/mixins/http.rb +0 -723
  42. data/lib/ronin/network/mixins/imap.rb +0 -151
  43. data/lib/ronin/network/mixins/pop3.rb +0 -141
  44. data/lib/ronin/network/mixins/smtp.rb +0 -159
  45. data/lib/ronin/network/mixins/tcp.rb +0 -331
  46. data/lib/ronin/network/mixins/telnet.rb +0 -199
  47. data/lib/ronin/network/mixins/udp.rb +0 -227
  48. data/lib/ronin/spec/ui/output.rb +0 -28
  49. data/lib/ronin/ui/output.rb +0 -21
  50. data/lib/ronin/ui/output/helpers.rb +0 -248
  51. data/lib/ronin/ui/output/output.rb +0 -146
  52. data/lib/ronin/ui/output/terminal.rb +0 -21
  53. data/lib/ronin/ui/output/terminal/color.rb +0 -118
  54. data/lib/ronin/ui/output/terminal/raw.rb +0 -103
  55. data/lib/ronin/ui/shell.rb +0 -92
  56. data/spec/ip_address.rb +0 -84
  57. data/spec/ui/output_spec.rb +0 -32
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ doc
2
+ pkg
3
+ vendor/cache
4
+ Gemfile.lock
5
+ .bundle
6
+ .DS_Store
7
+ .yardoc
8
+ *.db
9
+ *.log
10
+ *.swp
11
+ *~
data/ChangeLog.md CHANGED
@@ -1,3 +1,21 @@
1
+ ### 1.3.0 / 2011-10-16
2
+
3
+ * Require DataMapper ~> 1.2.
4
+ * Require ronin-support ~> 0.3.
5
+ * Added {Ronin::Model::Importable}.
6
+ * Added {Ronin::MACAddress.extract}.
7
+ * Added {Ronin::IPAddress.extract}.
8
+ * Added {Ronin::HostName.extract}.
9
+ * Added {Ronin::URL.extract}.
10
+ * Added {Ronin::EmailAddress.extract}.
11
+ * Renamed `license!` to `licensed_under` in
12
+ {Ronin::Model::HasLicense::InstanceMethods}.
13
+ * Moved `Ronin::UI::Output`, `Ronin::UI::Shell` and `Ronin::Network::Mixins`
14
+ into ronin-support.
15
+ * {Ronin::Author.site} and {Ronin::License.url} now use the URI property.
16
+ * Merged `Ronin::UI::CLI::ModelCommand.query_model` into
17
+ {Ronin::UI::CLI::ModelCommand.model}.
18
+
1
19
  ### 1.2.0 / 2011-08-15
2
20
 
3
21
  * Require dm-is-predefined ~> 0.4.
@@ -35,11 +53,11 @@
35
53
  * Added {Ronin::URLQueryParamName}.
36
54
  * Added timestamps to {Ronin::Campaign}.
37
55
  * Added the `created_at` timestamp to {Ronin::Target}.
38
- * Added {Ronin::Network::Mixins::HTTP#http_status}.
39
- * Added {Ronin::Network::Mixins::HTTP#http_ok?}.
40
- * Added {Ronin::Network::Mixins::HTTP#http_server}.
41
- * Added {Ronin::Network::Mixins::HTTP#http_powered_by}.
42
- * Added `print_info` method calls to {Ronin::Network::Mixins::HTTP}.
56
+ * Added `Ronin::Network::Mixins::HTTP#http_status`.
57
+ * Added `Ronin::Network::Mixins::HTTP#http_ok?`.
58
+ * Added `Ronin::Network::Mixins::HTTP#http_server`.
59
+ * Added `Ronin::Network::Mixins::HTTP#http_powered_by`.
60
+ * Added `print_info` method calls to `Ronin::Network::Mixins::HTTP`.
43
61
  * Added {Ronin::Script::InstanceMethods#run}.
44
62
  * Added {Ronin::Script::Exception}.
45
63
  * Added {Ronin::Script::Path#to_s}.
@@ -59,7 +77,7 @@
59
77
  * Renamed `Ronin::UI::CLI::ModelCommand.model=` to
60
78
  {Ronin::UI::CLI::ModelCommand.model}.
61
79
  * Renamed `Ronin::UI::CLI::ModelCommand#model` to
62
- {Ronin::UI::CLI::ModelCommand.query_model}.
80
+ `Ronin::UI::CLI::ModelCommand.query_model`.
63
81
  * Renamed `Ronin::UI::CLI::ModelCommand#new_query` to
64
82
  {Ronin::UI::CLI::ModelCommand#query}.
65
83
  * Renamed `Ronin::UI::CLI::ModelCommand#print_resource` to
@@ -84,9 +102,9 @@
84
102
  * Disable {Ronin::UI::Console.short_errors?} if the `VERBOSE` environment
85
103
  variable is set.
86
104
  * Disable {Ronin::UI::Console.color?} if the `STDOUT` is a tty.
87
- * Set {Ronin::UI::Output.handler} to {Ronin::UI::Output::Terminal::Raw},
105
+ * Set `Ronin::UI::Output.handler` to `Ronin::UI::Output::Terminal::Raw`,
88
106
  when `STDOUT` is not a tty.
89
- * Enable {Ronin::UI::Output.verbose?} if `$VERBOSE` or `$DEBUG` are set.
107
+ * Enable `Ronin::UI::Output.verbose?` if `$VERBOSE` or `$DEBUG` are set.
90
108
  * {Ronin::UI::CLI::ModelCommand#setup} now automatically calls
91
109
  {Ronin::Database.setup}, before executing the command.
92
110
  * Merged `query_method` into {Ronin::UI::CLI::ModelCommand#query}.
@@ -150,8 +168,8 @@
150
168
  * Added {Ronin::Campaign}.
151
169
  * Added {Ronin::Target}.
152
170
  * Added `Ronin::Engine`.
153
- * Added {Ronin::UI::Output::Terminal::Raw}.
154
- * Added {Ronin::UI::Output::Terminal::Color}.
171
+ * Added `Ronin::UI::Output::Terminal::Raw`.
172
+ * Added `Ronin::UI::Output::Terminal::Color`.
155
173
  * Added the `ronin-repos` command for listing, adding, installing and
156
174
  uninstalling Repositories.
157
175
  * Added the `ronin-exec` command for running Ruby scripts (local files
data/Gemfile CHANGED
@@ -22,7 +22,7 @@ gemspec
22
22
  # gem 'dm-timestamps', DM_VERSION, :git => "#{DM_URI}/dm-timestamps.git"
23
23
 
24
24
  # Library dependencies
25
- # gem 'ronin-support', '~> 0.2', :git => "#{RONIN_URI}/ronin-support.git"
25
+ # gem 'ronin-support', '~> 0.3', :git => "#{RONIN_URI}/ronin-support.git"
26
26
 
27
27
  group :development do
28
28
  gem 'rake', '~> 0.8'
data/README.md CHANGED
@@ -131,28 +131,26 @@ Remove a Database:
131
131
  * [Ruby](http://www.ruby-lang.org/) >= 1.8.7
132
132
  * [DataMapper](http://datamapper.org/):
133
133
  * [dm-sqlite-adapter](http://github.com/datamapper/dm-sqlite-adapter#readme)
134
- ~> 1.1
134
+ ~> 1.2
135
135
  * [libsqlite3](http://sqlite.org/)
136
136
  * [dm-core](http://github.com/datamapper/dm-core#readme)
137
- ~> 1.1
137
+ ~> 1.2
138
138
  * [dm-types](http://github.com/datamapper/dm-types#readme)
139
- ~> 1.1
139
+ ~> 1.2
140
140
  * [dm-migrations](http://github.com/datamapper/dm-migrations#readme)
141
- ~> 1.1
141
+ ~> 1.2
142
142
  * [dm-validations](http://github.com/datamapper/dm-validations#readme)
143
- ~> 1.1
143
+ ~> 1.2
144
144
  * [dm-aggregates](http://github.com/datamapper/dm-aggregates#readme)
145
- ~> 1.1
145
+ ~> 1.2
146
146
  * [dm-timestamps](http://github.com/datamapper/dm-timestamps#readme)
147
- ~> 1.1
147
+ ~> 1.2
148
148
  * [dm-is-predefined](http://github.com/postmodern/dm-is-predefined#readme)
149
149
  ~> 0.4
150
150
  * [uri-query_params](http://github.com/postmodern/uri-query_params#readme)
151
151
  ~> 0.5, >= 0.5.2
152
152
  * [open_namespace](http://github.com/postmodern/open_namespace#readme)
153
153
  ~> 0.3
154
- * [parameters](http://github.com/postmodern/parameters#readme)
155
- ~> 0.2, >= 0.2.3
156
154
  * [data_paths](http://github.com/postmodern/data_paths#readme)
157
155
  ~> 0.3
158
156
  * [object_loader](http://github.com/postmodern/object_loader#readme)
@@ -174,7 +172,7 @@ Remove a Database:
174
172
  * [thor](http://github.com/wycats/thor#readme)
175
173
  ~> 0.14.3
176
174
  * [ronin-support](http://github.com/ronin-ruby/ronin-support#readme)
177
- ~> 0.2
175
+ ~> 0.3
178
176
 
179
177
  ## Install
180
178
 
@@ -182,16 +180,15 @@ Remove a Database:
182
180
 
183
181
  ## Additional Libraries
184
182
 
185
- ### Ronin ASM
183
+ ### Ronin Gen
186
184
 
187
- [Ronin ASM](http://github.com/ronin-ruby/ronin-asm#readme) is a
188
- Ruby library for Ronin that provides dynamic Assembly (ASM) generation of
189
- programs or shellcode.
185
+ [Ronin Gen](http://github.com/ronin-ruby/ronin-gen#readme) is a Ruby library
186
+ for Ronin that provides various generators.
190
187
 
191
- ### Ronin Dorks
188
+ ### Ronin Web
192
189
 
193
- [Ronin Dorks](http://github.com/ronin-ruby/ronin-dorks#readme) is a
194
- Ruby library for Ronin that provides support for various Google (tm) Dorks
190
+ [Ronin Web](http://github.com/ronin-ruby/ronin-web#readme) is a Ruby library
191
+ for Ronin that provides support for web scraping and spidering
195
192
  functionality.
196
193
 
197
194
  ### Ronin Exploits
@@ -200,36 +197,12 @@ functionality.
200
197
  Ruby library for Ronin that provides exploitation and payload crafting
201
198
  functionality.
202
199
 
203
- ### Ronin Gen
204
-
205
- [Ronin Gen](http://github.com/ronin-ruby/ronin-gen#readme) is a Ruby library
206
- for Ronin that provides various generators.
207
-
208
200
  ### Ronin Scanners
209
201
 
210
202
  [Ronin Scanners](http://github.com/ronin-ruby/ronin-scanners#readme)
211
203
  is a Ruby library for Ronin that provides Ruby interfaces to
212
204
  various third-party security scanners.
213
205
 
214
- ### Ronin SQL
215
-
216
- [Ronin SQL](http://github.com/ronin-ruby/ronin-sql#readme) is a Ruby library
217
- for Ronin that provides support for SQL related security tasks, such as
218
- scanning for and exploiting SQL injections.
219
-
220
- ### Ronin PHP
221
-
222
- [Ronin PHP](http://github.com/ronin-ruby/ronin-php#readme) is a Ruby library
223
- for Ronin that provides support for PHP related security tasks, such as
224
- finding and exploiting Local File Inclusion (LFI) and
225
- Remote File Inclusion (RFI).
226
-
227
- ### Ronin Web
228
-
229
- [Ronin Web](http://github.com/ronin-ruby/ronin-web#readme) is a Ruby library
230
- for Ronin that provides support for web scraping and spidering
231
- functionality.
232
-
233
206
  ## License
234
207
 
235
208
  Copyright (c) 2006-2011 Hal Brodigan (postmodern.mod3 at gmail.com)
data/Rakefile CHANGED
@@ -68,3 +68,6 @@ DataMapper::Visualizer::Rake::GraphVizTask.new(
68
68
 
69
69
  require 'yard'
70
70
  YARD::Rake::YardocTask.new
71
+
72
+ desc "Generates all documentation"
73
+ task :docs => [:yard, 'dm:doc:graphviz']
data/gemspec.yml CHANGED
@@ -26,10 +26,10 @@ post_install_message: |
26
26
  Additional functionality can be added to Ronin by installing additional
27
27
  libraries:
28
28
 
29
- * ronin-asm * ronin-php
30
- * ronin-dorks * ronin-scanners
31
- * ronin-exploits * ronin-sql
32
- * ronin-gen * ronin-web
29
+ * ronin-gen
30
+ * ronin-web
31
+ * ronin-exploits
32
+ * ronin-scanners
33
33
 
34
34
  *************************************************************************
35
35
 
@@ -37,22 +37,21 @@ required_ruby_version: ">= 1.8.7"
37
37
 
38
38
  dependencies:
39
39
  # DataMapper adapters:
40
- dm-sqlite-adapter: ~> 1.1
40
+ dm-sqlite-adapter: ~> 1.2
41
41
  # DataMapper dependencies:
42
- dm-core: ~> 1.1
43
- dm-types: ~> 1.1
44
- dm-constraints: ~> 1.1
45
- dm-migrations: ~> 1.1
46
- dm-validations: ~> 1.1
47
- dm-serializer: ~> 1.1
48
- dm-aggregates: ~> 1.1
49
- dm-timestamps: ~> 1.1
42
+ dm-core: ~> 1.2
43
+ dm-types: ~> 1.2
44
+ dm-constraints: ~> 1.2
45
+ dm-migrations: ~> 1.2
46
+ dm-validations: ~> 1.2
47
+ dm-serializer: ~> 1.2
48
+ dm-aggregates: ~> 1.2
49
+ dm-timestamps: ~> 1.2
50
50
  # DataMapper plugins:
51
51
  dm-is-predefined: ~> 0.4
52
52
  # Library dependencies:
53
53
  uri-query_params: ~> 0.5, >= 0.5.2
54
54
  open_namespace: ~> 0.3
55
- parameters: ~> 0.2, >= 0.2.3
56
55
  data_paths: ~> 0.3
57
56
  object_loader: ~> 1.0
58
57
  env: ~> 0.2
@@ -64,7 +63,7 @@ dependencies:
64
63
  ripl-color_result: ~> 0.3
65
64
  thor: ~> 0.14.3
66
65
  # Ronin dependencies:
67
- ronin-support: ~> 0.2
66
+ ronin-support: ~> 0.3
68
67
 
69
68
  development_dependencies:
70
69
  bundler: ~> 1.0.10
@@ -18,11 +18,6 @@
18
18
  #
19
19
 
20
20
  require 'ronin/ui/console/commands'
21
- require 'ronin/address'
22
- require 'ronin/ip_address'
23
- require 'ronin/host_name'
24
- require 'ronin/email_address'
25
- require 'ronin/url'
26
21
 
27
22
  require 'set'
28
23
  require 'env'
data/lib/ronin/address.rb CHANGED
@@ -57,6 +57,23 @@ module Ronin
57
57
  # Tracks when the IP Address was first created
58
58
  timestamps :created_at
59
59
 
60
+ #
61
+ # Parses the address.
62
+ #
63
+ # @param [String] address
64
+ # The address to parse.
65
+ #
66
+ # @return [Address]
67
+ # The parsed address.
68
+ #
69
+ # @since 1.3.0
70
+ #
71
+ # @api public
72
+ #
73
+ def self.parse(address)
74
+ first_or_new(:address => address)
75
+ end
76
+
60
77
  #
61
78
  # Finds an address.
62
79
  #
data/lib/ronin/author.rb CHANGED
@@ -43,7 +43,7 @@ module Ronin
43
43
  property :email, String
44
44
 
45
45
  # Author's site
46
- property :site, String
46
+ property :site, URI, :length => 256
47
47
 
48
48
  # Author's biography
49
49
  property :biography, Text
@@ -142,8 +142,13 @@ module Ronin
142
142
  # The stream to use for the log.
143
143
  #
144
144
  # @option options [Symbol] :level
145
- # The level of messages to log.
146
- # May be either `:fatal`, `:error`, `:warn`, `:info` or `:debug`.
145
+ # The level of messages to log. May one of:
146
+ #
147
+ # * `:fatal`
148
+ # * `:error`
149
+ # * `:warn`
150
+ # * `:info`
151
+ # * `:debug`
147
152
  #
148
153
  # @return [true]
149
154
  # Specifies that the log has been setup.
@@ -166,7 +171,7 @@ module Ronin
166
171
  # The database repository name.
167
172
  #
168
173
  # @return [Boolean]
169
- # Specifies wether or not the Database is setup.
174
+ # Specifies whether or not the Database is setup.
170
175
  #
171
176
  # @api semipublic
172
177
  #
@@ -216,6 +221,9 @@ module Ronin
216
221
  DataMapper.setup(name,uri)
217
222
  end
218
223
 
224
+ # finalize the Models
225
+ DataMapper.finalize
226
+
219
227
  # apply any new migrations to the database
220
228
  upgrade!
221
229
  end
@@ -17,7 +17,9 @@
17
17
  # along with Ronin. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
+ require 'ronin/extensions/regexp'
20
21
  require 'ronin/model'
22
+ require 'ronin/model/importable'
21
23
  require 'ronin/user_name'
22
24
  require 'ronin/host_name'
23
25
 
@@ -53,6 +55,37 @@ module Ronin
53
55
  # Validates the uniqueness of the user-name and the host-name.
54
56
  validates_uniqueness_of :user_name, :scope => [:host_name]
55
57
 
58
+ #
59
+ # Extracts email addresses from the given text.
60
+ #
61
+ # @param [String] text
62
+ # The text to parse.
63
+ #
64
+ # @yield [email]
65
+ # The given block will be passed each extracted email address.
66
+ #
67
+ # @yieldparam [EmailAddress] email
68
+ # An extracted host-name.
69
+ #
70
+ # @return [Array<EmailAddress>]
71
+ # If no block is given, an Array of email address will be returned.
72
+ #
73
+ # @see 1.3.0
74
+ #
75
+ # @api public
76
+ #
77
+ def self.extract(text)
78
+ return enum_for(:extract,text).to_a unless block_given?
79
+
80
+ scanner = StringScanner.new(text)
81
+
82
+ while scanner.skip_until(Regexp::EMAIL_ADDR)
83
+ yield parse(scanner.matched)
84
+ end
85
+
86
+ return nil
87
+ end
88
+
56
89
  #
57
90
  # Searches for email addresses associated with the given host names.
58
91
  #
@@ -17,11 +17,16 @@
17
17
  # along with Ronin. If not, see <http://www.gnu.org/licenses/>.
18
18
  #
19
19
 
20
+ require 'ronin/extensions/regexp'
21
+ require 'ronin/extensions/resolv'
22
+ require 'ronin/model/importable'
20
23
  require 'ronin/address'
21
24
  require 'ronin/host_name_ip_address'
22
- require 'ronin/url'
23
25
  require 'ronin/email_address'
26
+ require 'ronin/url'
24
27
 
28
+ require 'uri/generic'
29
+ require 'strscan'
25
30
  require 'resolv'
26
31
 
27
32
  module Ronin
@@ -30,10 +35,16 @@ module Ronin
30
35
  #
31
36
  class HostName < Address
32
37
 
38
+ include Model::Importable
39
+
33
40
  # The address of the host name
34
41
  property :address, String, :length => 256,
35
42
  :required => true,
36
- :unique => true
43
+ :unique => true,
44
+ :format => /^#{Regexp::HOST_NAME}$/,
45
+ :messages => {
46
+ :format => 'Must be a valid host-name'
47
+ }
37
48
 
38
49
  # The IP Address associations
39
50
  has 0..n, :host_name_ip_addresses, :model => 'HostNameIPAddress'
@@ -54,6 +65,37 @@ module Ronin
54
65
  # URLs that point to this host name
55
66
  has 0..n, :urls, :model => 'URL'
56
67
 
68
+ #
69
+ # Extracts host-names from the given text.
70
+ #
71
+ # @param [String] text
72
+ # The text to parse.
73
+ #
74
+ # @yield [host]
75
+ # The given block will be passed each extracted host-name.
76
+ #
77
+ # @yieldparam [HostName] host
78
+ # An extracted host-name.
79
+ #
80
+ # @return [Array<HostName>]
81
+ # If no block is given, an Array of host-names will be returned.
82
+ #
83
+ # @see 1.3.0
84
+ #
85
+ # @api public
86
+ #
87
+ def self.extract(text)
88
+ return enum_for(:extract,text).to_a unless block_given?
89
+
90
+ scanner = StringScanner.new(text)
91
+
92
+ while scanner.skip_until(Regexp::HOST_NAME)
93
+ yield parse(scanner.matched)
94
+ end
95
+
96
+ return nil
97
+ end
98
+
57
99
  #
58
100
  # Searches for host names associated with the given IP address(es).
59
101
  #
@@ -129,6 +171,9 @@ module Ronin
129
171
  # @param [IPAddr, String] addr
130
172
  # The IP address to lookup.
131
173
  #
174
+ # @param [String] nameserver
175
+ # The optional nameserver to query.
176
+ #
132
177
  # @return [Array<HostName>]
133
178
  # The host names associated with the IP address.
134
179
  #
@@ -136,11 +181,13 @@ module Ronin
136
181
  #
137
182
  # @api public
138
183
  #
139
- def self.lookup(addr)
184
+ def self.lookup(addr,nameserver=nil)
140
185
  addr = addr.to_s
141
186
  ip = IPAddress.first_or_new(:address => addr)
187
+
188
+ resolver = Resolv.resolver(nameserver)
142
189
  hosts = begin
143
- Resolv.getnames(addr)
190
+ resolver.getnames(addr)
144
191
  rescue
145
192
  []
146
193
  end
@@ -160,6 +207,9 @@ module Ronin
160
207
  #
161
208
  # Looks up all IP Addresses for the host name.
162
209
  #
210
+ # @param [String] nameserver
211
+ # The optional nameserver to query.
212
+ #
163
213
  # @return [Array<IPAddress>]
164
214
  # The IP Addresses for the host name.
165
215
  #
@@ -167,9 +217,10 @@ module Ronin
167
217
  #
168
218
  # @api public
169
219
  #
170
- def lookup!
220
+ def lookup!(nameserver=nil)
221
+ resolver = Resolv.resolver(nameserver)
171
222
  ips = begin
172
- Resolv.getaddresses(self.address)
223
+ resolver.getaddresses(self.address)
173
224
  rescue
174
225
  []
175
226
  end