C++ TCP Proxy Server

 www.partow.net  .: Home :.   .: Links :.   .: Search :.   .: Contact :. 


Description

The C++ TCP Proxy server is a simple and high performance utility using the ASIO networking library, for proxying (tunneling or redirecting) connections from external clients to a designated server. Some of the tasks the TCP Proxy Server can be used to easily and efficiently accomplish are as follows:

  • Limit the number of client connections to the server
  • Load balance client connections between multiple server instances
  • Provide IP or connection time based filtering and access control mechanisms
  • Inspect (log), filter or otherwise modify data flowing between the clients and the server

How does it work?

The TCP proxy server acts as an intermediary in order to 'forward' TCP based connections from external clients onto a singular remote server. The communication flow in the direction from the client to the proxy to the server is called the upstream flow, and the communication flow in the direction from the server to the proxy to the client is called the downstream flow.

Furthermore the up and down stream connections are consolidated into a single concept known as a bridge. In the event either the downstream or upstream end points disconnect, the proxy server will proceed to disconnect the other end-point and eventually destroy the associated bridge.

Usage: ./tcpproxy_server <proxy machine ip> <proxy machine port> <server ip> <server port>


TCP Proxy Server Diagram - Copyright Arash Partow


Example Use-Case (Simple Proxy Server)

A simple scenario is as follows: There exists a server at 192.168.0.100 that accepts connections on port 20000, however due to firewall rules external clients can only access a host at 192.168.20.200 on port 8080 (eth0), which coincidentally has access to the 192.168.0 network segment via a second NIC (eth1). A solution for allowing the external clients access to the server is to run the TCP proxy server on the host at 192.168.0.200 with the following configuration:

tcpproxy_server 192.168.20.200 8080 192.168.0.100 20000

The above command when run upon the proxy machine at 192.168.20.200, will bind to port 8080 on eth0 in order to accept connections from external clients - which presumbly will originate from the firewall. Upon a new client connecting, the proxy will make a connection on behalf of the client to the server residing at 192.168.0.100 on port 20000 via eth1, and then proceed to send all incoming data from the client to the server and vice versa. Once either party (client or server) disconnects, the proxy will immediately disconnect the other party.


C++ TCP Proxy License

Free use of the C++ TCP Proxy is permitted under the guidelines and in accordance with the Boost Software License

Compatibility

The C++ TCP Proxy implementation is compatible with the following C++ compilers:

  • GNU Compiler Collection (3.5+)
  • Clang/LLVM (1.1+)
  • Microsoft Visual Studio C++ Compiler (7.1+)
  • Intel® C++ Compiler (8.x+)
  • AMD Optimizing C++ Compiler (1.2+)
  • Nvidia C++ Compiler (19.x+)
  • PGI C++ (10.x+)
  • IBM XL C/C++ (9.x+)
  • C++ Builder (XE4+)

C++ TCP Proxy Server - Copyright Arash Partow Download


The Internals Of The Proxy

The proxy from an implementation aspect is primarily composed of three components named the Acceptor, Session and the ASIO I/O Service proactor. The acceptor and session components register with the I/O service requests and associated completion handlers (callbacks) for reading and writing from socket(s). The state diagram below depicts the the various completion handlers and their relationship to the I/O service component. The turquoise blocks are associated with the Acceptor, where as the purple blocks are associated with the Session. For exposition purposes let's assume that the completion handlers and the I/O service component are each a unique state in a state machine that represents the TCP proxy.

TCP Proxy State Diagram - Copyright Arash Partow

The TCP proxy server is broken down into three functional 'groupings' denoted in the diagram by the colours blue, green and red attached to the transitions between the states (completion handlers) and the I/O service. The groupings are summarised as follows:

PhaseTransitionsDefinition
Blue1 - 8 Start-up and client connection instantiation phase.
Associated completion handlers:
  • handle_accept
  • handle_upstream_connect
GreenA1 - A4 Process data flow from remote server to proxy to client.
Associated completion handlers:
  • handle_upstream_read
  • handle_downstream_write
RedB1 - B4 Process data flow from client to proxy to remote server.
Associated completion handlers:
  • handle_downstream_read
  • handle_upstream_write

The Blue Phase - Startup and Initialisation

Associated completion handlers:

  • handle_accept
  • handle_upstream_connect
In this phase the proxy itself is setup, which includes instantiating the Acceptor, binding-to and listening in on the given IP and port number, and invoking the accept_connections method, which in turn will register a completion handler with the I/O service, that will later on be invoked when new connections are made to the proxy server.

When a client makes a connection to the proxy server, the handle_accept completion handler will be invoked by the I/O service. This handler will then proceed to instantiate and start a client session (bridge) instance. Once that is complete, it will then invoke accept_connections which will complete the cycle by re-registering the handle_accept method with the I/O service as the completion handler for any new connections.

Meanwhile when the start method on the client session was invoked during the handle_accept call, it immediately attempted to asynchronously establish a connection with the remote server. When the remote server accepts the connection, the I/O service will then invoke the handle_upstream_connect completion handler. This handler will in turn proceed to register two asynchronous read requests coupled with the completion handlers handle_downstream_read and handle_upstream_read with the I/O service, one for data coming from the client, the other being for data coming from the remote server respectively.

TCP Proxy Server Blue Phase Diagram - Copyright Arash Partow


Based on which end-point data arrives at the proxy, one of the following phases will be engaged:

  • Green Phase
  • Red Phase

The Green Phase - Remote Server To Proxy To Client Data Flow

Associated completion handlers:

  • handle_upstream_read
  • handle_downstream_write
This phase is engaged when data from the Remote Server (aka up-stream end point) arrives at the proxy. Once some amount of data is ready, the I/O service will invoke the handle_upstream_read completion handler. This handler will in turn take the data and register an asynchronous write request with the I/O service in order to send the data to the Client end-point. Once the write request has completed, the I/O service will invoke the handle_downstream_write completion handler. This handler will complete the cycle for the green phase by re-registering with the I/O service an asynchronous read request from the upstream end-point coupled with the handle_upstream_read method as the associated completion handler.

TCP Proxy Server Green Phase Diagram - Copyright Arash Partow


The Red Phase - Client To Proxy To Remote Server Data Flow

Associated completion handlers:

  • handle_downstream_read
  • handle_upstream_write
This phase is engaged when data from the Client (aka down-stream end point) arrives at the proxy. Once some amount of data is ready, the I/O service will invoke the handle_downstream_read completion handler. This handler will in turn take the data and register an asynchronous write request with the I/O service in order to send the data to the Remote Server end-point. Once the write request has been completed, the I/O service will invoke the handle_upstream_write completion handler. This handler will complete the cycle for the red phase by re-registering with the I/O service an asynchronous read request from the downstream end-point coupled with the handle_downstream_read method as the associated completion handler.

TCP Proxy Server Red Phase Diagram - Copyright Arash Partow


Bridge Shutdown Process

When either of the end points terminate their respective connection to the proxy, the proxy will proceed to close (or shutdown) the other corresponding connection. This includes releasing any outstanding asynchronous requests, culminating in the reference count of the bridge (client session) reaching zero at which point the bridge instance itself will subsequently have its destructor called.





© Arash Partow. All Rights Reserved.