Class: Rex::Services::LocalRelay

Inherits:
Object
  • Object
show all
Includes:
Rex::Service
Defined in:
lib/rex/services/local_relay.rb

Overview

This service acts as a local TCP relay whereby clients can connect to a local listener that forwards to an arbitrary remote endpoint. Interaction with the remote endpoint socket requires that it implement the Rex::IO::Stream interface.

Defined Under Namespace

Modules: Stream, StreamServer Classes: Relay

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Rex::Service

#cleanup, #deref

Methods included from Ref

#cleanup, #deref, #ref, #refinit

Constructor Details

#initializeLocalRelay

Initializes the local tcp relay monitor.


113
114
115
116
117
118
# File 'lib/rex/services/local_relay.rb', line 113

def initialize
  self.relays       = Hash.new
  self.rfds         = Array.new
  self.relay_thread = nil
  self.relay_mutex  = Mutex.new
end

Class Method Details

.hardcore_alias(*args) ⇒ Object

Returns the hardcore alias for the local relay service.


129
130
131
# File 'lib/rex/services/local_relay.rb', line 129

def self.hardcore_alias(*args)
  "__#{args}"
end

Instance Method Details

#aliasObject

Returns the alias for this service.


136
137
138
# File 'lib/rex/services/local_relay.rb', line 136

def alias
  super || "Local Relay"
end

#each_tcp_relay(&block) ⇒ Object

Enumerate each TCP relay


251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/rex/services/local_relay.rb', line 251

def each_tcp_relay(&block)
  self.relays.each_pair { |name, relay|
    next if (relay.opts['__RelayType'] != 'tcp')

    yield(
      relay.opts['LocalHost'] || '0.0.0.0',
      relay.opts['LocalPort'],
      relay.opts['PeerHost'],
      relay.opts['PeerPort'],
      relay.opts)
  }
end

#startObject

Starts the thread that monitors the local relays.


143
144
145
146
147
148
149
150
151
152
153
# File 'lib/rex/services/local_relay.rb', line 143

def start
  if (!self.relay_thread)
    self.relay_thread = Rex::ThreadFactory.spawn("LocalRelay", false) {
      begin
        monitor_relays
      rescue ::Exception
        elog("Error in #{self} monitor_relays: #{$!}", 'rex')
      end
    }
  end
end

#start_relay(stream_server, name, opts = {}) ⇒ Object

Starts a local relay on the supplied local port. This listener will call the supplied callback procedures when various events occur.


207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/rex/services/local_relay.rb', line 207

def start_relay(stream_server, name, opts = {})
  # Create a Relay instance with the local stream and remote stream
  relay = Relay.new(name, stream_server, opts)

  # Extend the stream_server so that we can associate it with this relay
  stream_server.extend(StreamServer)
  stream_server.relay = relay

  # Add the stream associations the appropriate lists and hashes
  self.relay_mutex.synchronize {
    self.relays[name] = relay

    self.rfds << stream_server
  }
end

#start_tcp_relay(lport, opts = {}) ⇒ Object

Starts a local TCP relay.


187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/rex/services/local_relay.rb', line 187

def start_tcp_relay(lport, opts = {})
  # Make sure our options are valid
  if ((opts['PeerHost'] == nil or opts['PeerPort'] == nil) and (opts['Stream'] != true))
    raise ArgumentError, "Missing peer host or peer port.", caller
  end

  listener = Rex::Socket.create_tcp_server(
    'LocalHost' => opts['LocalHost'],
    'LocalPort' => lport)

  opts['LocalPort']   = lport
  opts['__RelayType'] = 'tcp'

  start_relay(listener, lport.to_s + (opts['LocalHost'] || '0.0.0.0'), opts)
end

#stopObject

Stops the thread that monitors the local relays and destroys all local listeners.


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/rex/services/local_relay.rb', line 159

def stop
  if (self.relay_thread)
    self.relay_thread.kill
    self.relay_thread = nil
  end

  self.relay_mutex.synchronize {
    self.relays.delete_if { |k, v|
      v.shutdown
      v.close
      true
    }
  }

  # Flush the relay list and read fd list
  self.relays.clear
  self.rfds.clear
end

#stop_relay(name) ⇒ Object

Stops a relay with a given name.


233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/rex/services/local_relay.rb', line 233

def stop_relay(name)
  rv = false

  self.relay_mutex.synchronize {
    relay = self.relays[name]

    if (relay)
      close_relay(relay)
      rv = true
    end
  }

  rv
end

#stop_tcp_relay(lport, lhost = nil) ⇒ Object

Stops relaying on a given local port.


226
227
228
# File 'lib/rex/services/local_relay.rb', line 226

def stop_tcp_relay(lport, lhost = nil)
  stop_relay(lport.to_s + (lhost || '0.0.0.0'))
end