Create TCP TUNNELING system using Indy - delphi

Hi is it possible to create intermediary application which will act as tcp proxy server? It would be made of two components. IdTCPServer and IdTCPClient. The idea is:
Application > connects to IdTCPServer > all data is redirected to > IdTCPClient which is connected to the destination.
And the data received by TCPClient will be redirected to the IdTCPServer and Application.
I made such simple app, and it works in HTTP requests, but it fails when I tried to use it for RDP Client ( I got error that Protocol is wrong). Is it even possible? I use ReadByte method, and each single byte is sent to the other IOHandler.
I would like to create some sort of virtual tcp channel which would allow connections over NAT.
I wasn't clear enough. What I want to achieve is something like this:
RDP Server < IdTCPClient <> IdTCPclient > NAT > IdTCPServer < RDPClient.

Application > connects to IdTCPServer > all data is redirected to > IdTCPClient which is connected to the destination.
And the data received by TCPClient will be redirected to the IdTCPServer and Application.
In fact, Indy has a component specifically for that very purpose - TIdMappedPortTCP.
Set its MappedHost and MappedPort properties to point at the intended destination, then activate it, and all inbound connections will automatically be directed to the destination, and data passed back and forth in both directions.

I was going to add just a comment, but don't have enough points for that.
Your request says you want to "redirect", for which Remy supplied the answer.
However, your description sounds like you want to pass the data yourself (man-in-the-middle). RDP contains some guards against that, though earlier versions may have been more open to it.
You may want to specify the question more tightly if actual redirect is not what you are looking for.

Related

How do I distinguish between 2 Indy clients that connected from the same IP address?

Sorry, links to Indy documentation are currently not working for me. I don't know if the sites are down or whatever but they're not loading in my browser at the moment.
I have a TIdCmdTcpServer in one "server" application, and a TIdCmdTcpClient in another "client" application. I know how to get the IP address of the Client once it has connected. What I don't know is how to distinguish between 2 clients that connect from the same ip address. Can anyone help?
This isn't really an Indy question, more a general networking one.
Different clients at the same address must use distinct ports. And here I mean the port at the client end of the connection. So you distinguish between different clients at the same address by dint of them using different ports.
DO NOT use TIdCmdTCPClient with TIdCmdTCPServer. They are not meant to be used together, and it is very easy to deadlock your communications with them, as they both use internal reading threads that expect the other peer to send data. Use TIdTCPClient with TIdCmdTCPServer or TIdCmdTCPClient with TIdTCPServer.
With that said, you could use the client's remote IP/Port to differentiate, but it is generally better to make your own identifier instead, such as requiring clients to log in with a username, that you can then track as needed.

Indy TCP Client/Server with the client acting as a server

How can Indy's TIdTCPClient and TIdTCPServer be used in the following scenario:
Client ---------- initate connection -----------> Server
...
Client <---------------command------------------- Server
Client ----------------response-----------------> Server
...
Client <---------------command------------------- Server
Client ----------------response-----------------> Server
The client initiates the connection, but acts as a "server" (waiting for commands and executing them).
The OnExecute approach of TIdTCPServer does not work well in this case (at least I am not getting it to work well). How could I do this?
I hope the question is clear enough.
There is nothing preventing you from doing this with Indy's TIdTCPServer component.
A TIdTCPServer only sets up the connection. You'll need to implement the rest. So the sequence of the actual sending and receiving can be whatever you want.
Put this code in your TIdTCPServer component's OnExecute event:
var
sName: String;
begin
// Send command to client immediately after connection
AContext.Connection.Socket.WriteLn('What is your name?');
// Receive response from client
sName := AContext.Connection.Socket.ReadLn;
// Send a response to the client
AContext.Connection.Socket.WriteLn('Hello, ' + sName + '.');
AContext.Connection.Socket.WriteLn('Would you like to play a game?');
// We're done with our session
AContext.Connection.Disconnect;
end;
Here's how you can setup the TIdTCPServer really simply:
IdTCPServer1.Bindings.Clear;
IdTCPServer1.Bindings.Add.SetBinding('127.0.0.1', 8080);
IdTCPServer1.Active := True;
This tells the server to listen on the loopback address only, at port 8080. This prevents anyone outside of your computer from connecting to it.
Then, to connect your client, you can go to a Windows command prompt and type the following:
telnet 127.0.0.1 8080
Here's the output:
What is your name?
Marcus
Hello, Marcus.
Would you like to play a game?
Connection to host lost.
Don't have telnet? Here's how to install telnet client on Vista and 7.
Or with a TIdTCP Client, you can do this:
var
sPrompt: String;
sResponse: String;
begin
// Set port to connect to
IdTCPClient1.Port := 8080;
// Set host to connect to
IdTCPClient1.Host := '127.0.0.1';
// Now actually connect
IdTCPClient1.Connect;
// Read the prompt text from the server
sPrompt := IdTCPClient1.Socket.ReadLn;
// Show it to the user and ask the user to respond
sResponse := InputBox('Prompt', sPrompt, '');
// Send user's response back to server
IdTCPClient1.Socket.WriteLn(sResponse);
// Show the user the server's final message
ShowMessage(IdTCPClient1.Socket.AllData);
end;
An important thing to note here is that the ReadLn statements wait until there is data. That's the magic behind it all.
If your commands are textual in nature, then have a look at the TIdCmdTCPClient component, it is specifically designed for situations when the server is sending commands instead of the client. The server can use TIdContext.Connection.IOHandler.WriteLn() or TIdContext.Connection.IOHandler.SendCmd() to send the commands.
When the client connects to the server, the server has an OnConnect event with an AContext: TIdContext parameter.
A property of this is AContext.Connection, which you can store outside of that event (say, in an Array). If you pair it with the IP or better yet a generated Session ID, then reference that Connection by that criteria, you can then have the server send adhoc commands or messages to the client.
Hope this helps!
normally the client and the server side have a thread that is reading incoming telegrams, and sending pending telegrams...but this kind of protocols (send/receive, when and what) depend of the application.
A very good starting point how the client side can be implemented using a thread, listening for messages from the server, is the Indy Telnet client component (TIdTelnet in the Protocols folder).
The Indy telnet client connects to the telnet server and uses only one socket to write and read data. Reading happens in a listener thread.
This design can easily be adapted to build distributed messaging software like chat etc., and also shows how easy the protocol can be decoupled from the network layer using blocking sockets.
With Indy this is not possible by design:
Indy supports only Client-initiated communication, what means the server can only send a response to requests by the client.
The easiest way (but not the smartest) to get what you want is to use a pull-process. Controlled by a timer the clients ask the server if there is a new command. Of course this will cause a lot of traffic-overhead and depending on your pull-intervall there is a delay.
Alternatively you could use another library like ICS (http://www.overbyte.be/eng/products/ics.html)

Transferring Data Directly between 2 Connections in Indy (TIdContext)

ive a sever running TIdTCPServer, and Client Using Web Browser (or any other software) to Communicate, i dunno the protocol, but what im trying to do is to Send The Data between the client and another Connection (Both Connected to the same TIdTCPServer) for example the data sent by the first client is transmitted to the second client, and the data sent by the second client is transmitted to the first client, like a proxy (i cant really use a proxy server since its just this one condition) and the TIdTCPServer should still be receiving other clients and processing their data.
i stumbled upon the first line of code, since TIdContext.Connection.Socket.ReadLn requires a Delimiter, and the Client's Protocol is unknown to the server.
any ideas?
thanks.
You can look at the source code for TIdMappedPortTCP and TIdHTTPProxyServer to see how they pass arbitrary data between connections in both directions. Both components use TIdSocketList.SelectReadList() to detect when either connection has data to read. TIdMappedPortTCP then uses TIdBuffer.ExtractToBytes() and TIdIOHandler.Write(TIdBytes), whereas TIdHTTPProxyServer uses TIdTCPStream and TIdBuffer.ExtractToStream() instead.

How does a HTTP response find its way to the correct browser window?

If you have two browser windows open and you use each to navigate to a different website, then how does the software know which HTTP response belongs to which browser instance?
Update
It seems that the distinction is made by the inbound TCP port numbers. But what about network messages that don't involve TCP/UDP? For example, if you open two terminal applications and use both send a ping message to the same remote server, how does the reply find its way to its terminal instance?
Typically, each browser instance creates its own socket to communicate with the server. Though the outbound port of all the sockets is the same (usually TCP 80 or 443), their inbound ports are different. Thus, there are no conflicts when the server responds to the requests, since the responses are sent to different inbound ports.
Tools like ping use ICMP packets, which provide their own way to uniquely identify the calling application (a unique identifier and a sequence number).
They're usually associated with different TCP connections, which between them have used different ports on the client end. This means that the TCP stack at the client end knows the different and passes them via the sockets API the client used in an easily distinguishable way. (Typically different file descriptors)
The exception to this is pipelining where multiple http request can be sent over one connection, as an optimisation. Requests sent like this are received in the order they were sent however, making it trivial to match them to the requests.

how can i manage connections in Indy ? (Delphi)

i am writing a simple client/server chat program with indy 10 (blocking mode) and there is a question that how can i manage connections ?
for example imagine a user that is online on server , we must make a connection tunnel for future requests . In other words, when a user is online server should not need username and password for future user requests . and it will be do with the tunnel that we created when user has came .
how can we manage connections ?
[sorry for my bad english] if you can't understand me please tell me to send a new post agian .
Thank you
For the scenario described in the question, there isn't really much management to do. To avoid having to re-authenticate on every request, simply don't close the connection. In a chat server, especially, it's quite likely that each participant will establish a connection and then continue using that same connection for the duration of the chat.
Indy server objects already keep a list of their open connections, so when you want to broadcast a chat message to the other participants, you can just iterate over that list.
I think 100000 checks per second will be the less resource consuming thing, than having 10000 persistent TCP connections. And anyway you will need to process somehow these 100000 commands, so those checks would not be the bottleneck.
Try to use the UDP messages instead. For example, most MMO games use both TCP and UDP connections. TCP only for critical data, and UDP for any other data. In your case UDP seems to be acceptable. The client can send UDP packets with some autoincrement IDs, and the server can periodically send back the list of IDs it doesn't receive, so the client can resend them.
One option would be to create a unique session ID (or "token") on the server side, for example a GUID, if a client logs in. And in every request, the client includes this token.
The server would maintain a list of client sessions and associated session data, and looks up the token in this list.
Even if a client is temporary disconnected from the Internet but still knows its token, the application can reconnect and continue the session with the server.

Resources