Create tcp proxy with dynamic targets

Hi all,

how can i write a tcp proxy which is capable to connect dynamically to
different systems depending on information coming from a client
connecting to the proxy??

I already have a standard proxy script, which can forward an incoming
client request to a predefined server target.

Target scenario is a client with a repository of targets. This client
sends requests to some targets via this proxy. Therefore it sends the
request, together with the target ip/port, to the proxy. The proxy now
takes the information, opens a connection to target and forwards the
request.

I got stuck because when i read the incoming request from socket once,
for setting up the connection, it is not available anymore in the later
listening loop to send it via the new connection to the server.

Any idea how to achieve this??

Current code ist this:

require “socket”
require ‘json’

max_threads = 5
threads = []

Read proxy bindadress and port from configfile

conf = JSON.parse(File.read(‘hvp.conf’))

puts "starting proxy on " + conf[‘proxyip’] + ‘(’ + conf[‘proxyport’] +
‘)’

#Start proxy with data from configfile
server = TCPServer.new(conf[‘proxyip’],conf[‘proxyport’])

while true

Start a new thread for every client connection.

puts “waiting for connections”
threads << Thread.new(server.accept) do |client_socket|
begin
puts “#{Thread.current}: got a client connection”
begin
params = JSON.parse(client_socket.gets.chomp.to_s)
remote_host = params[‘agentip’]
remote_port = params[‘agentport’]
server_socket = TCPSocket.new(remote_host, remote_port)
rescue Errno::ECONNREFUSED
client_socket.close
raise
end
puts “#{Thread.current}: connected to server at
#{remote_host}:#{remote_port}”

  while true
    # Wait for data to be available on either socket.
    (ready_sockets, dummy, dummy) = IO.select([client_socket,

server_socket])
begin
ready_sockets.each do |socket|
data = socket.readpartial(4096)
if socket == client_socket
# Read from client, write to server.
puts “#{Thread.current}: client->server #{data.inspect}”
server_socket.write data
server_socket.flush
else
# Read from server, write to client.
puts “#{Thread.current}: server->client #{data.inspect}”
client_socket.write data
client_socket.flush
end
end
rescue EOFError
break
end
end
rescue StandardError => e
puts “Thread #{Thread.current} got exception #{e.inspect}”
end
puts “#{Thread.current}: closing the connections”
client_socket.close rescue StandardError
server_socket.close rescue StandardError
end

Clean up the dead threads, and wait until we have available threads.

puts “#{threads.size} threads running”
threads = threads.select { |t| t.alive? ? true : (t.join; false) }
while threads.size >= max_threads
sleep 1
threads = threads.select { |t| t.alive? ? true : (t.join; false) }
end
end

for io with socket, I prefer to use pure socket
primitives (recv,send,shutdown…)

for the first reading of one line, you can read char by char, until
line feed.

Here a version with minitcp (i am to leasy for pure socket:)

require “minitcp”
require ‘json’

max_thread=5
conf = JSON.parse(File.read(‘hvp.conf’))
puts “starting proxy on #{conf[‘proxyip’]}#{conf[‘proxyport’]}”

MServer.service(conf[‘proxyport’],conf[‘proxyip’],max_thread) do
|client_socket|
params = JSON.parse(client_socket.receive_sep("\n"))
remote_host,remote_port = params[‘agentip’],params[‘agentport’]
if remote_host && remote_port

 srv_socket=nil
 th=MClient.run_one_shot(remote_host,remote_port) do |so|
    srv_socket=so
    client_socket.on_any_receive { |data| so.send(data,0) }
    so.on_any_receive { |data| client_socket.send(data,0) }
    so.wait_end
    client_socket close
 end
 client_socket.wait_end
 srv_socket.close rescue nil

end
end.join

Gave it a try and it worked after some minor changes in the rest of the
app.

Thanks for supporting.

Moe