108 lines
2.4 KiB
Ruby
108 lines
2.4 KiB
Ruby
# -*- 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
|