lib/rex/proto/proxy/socks5/server.rb
# -*- coding: binary -*-
require 'thread'
require 'rex/socket'
module Rex
module Proto
module Proxy
module Socks5
#
# A SOCKS5 proxy server.
#
class Server
#
# Create a new SOCKS5 server.
#
def initialize(opts={})
@opts = { 'ServerHost' => '0.0.0.0', 'ServerPort' => 1080 }
@opts = @opts.merge(opts)
@server = nil
@clients = ::Array.new
@running = false
@server_thread = nil
end
#
# Check if the server is running.
#
def is_running?
return @running
end
#
# Start the SOCKS5 server.
#
def start
begin
# create the servers main socket (ignore the context here because we don't want a remote bind)
@server = Rex::Socket::TcpServer.create(
'LocalHost' => @opts['ServerHost'],
'LocalPort' => @opts['ServerPort'],
'Comm' => @opts['Comm']
)
# signal we are now running
@running = true
# start the servers main thread to pick up new clients
@server_thread = Rex::ThreadFactory.spawn("SOCKS5ProxyServer", false) do
while @running
begin
# accept the client connection
sock = @server.accept
# and fire off a new client instance to handle it
ServerClient.new(self, sock, @opts).start
rescue
wlog("SOCKS5.start - server_thread - #{$!}")
end
end
end
rescue
wlog("SOCKS5.start - #{$!}")
return false
end
return true
end
#
# Block while the server is running.
#
def join
@server_thread.join if @server_thread
end
#
# Stop the SOCKS5 server.
#
def stop
if @running
# signal we are no longer running
@running = false
# stop any clients we have (create a new client array as client.stop will delete from @clients)
clients = @clients.dup
clients.each do | client |
client.stop
end
# close the server socket
@server.close if @server
# if the server thread did not terminate gracefully, kill it.
@server_thread.kill if @server_thread and @server_thread.alive?
end
return !@running
end
def add_client(client)
@clients << client
end
def remove_client(client)
@clients.delete(client)
end
attr_reader :opts
end
end
end
end
end