This is a network architecture prototype which illustrates the way HTTP tunneling (forwarding of TCP connections) is used to handle the internet traffic. It emulates how internet clients communicate with a production server through a public-facing reverse proxy that uses HTTP tunneling to manages the connections as well as the incoming and outgoing traffic on behalf of the server.
It comes with a full, user-friendly monitoring interface and will provide useful insights on what's actually happening at the transport layer level during http or network transactions at large.
This project was designed with the goal of emulating some actual internet traffic :
- Node.js processes are used to emulate each network host :
client
,proxy
andserver
. - Each process runs inside a dedicated Docker container with its own network interface and IP address.
- Two Docker
bridge
networks are used as well, each with their own subnet mask and gateway:ntw-internet
: emulates the internet, to which theclient
containers are connected.ntw-local
: emulates the local isolated network of a business/cloud provider, to which theserver
container is connected.
- The
proxy
container is connected to bothntw-internet
andntw-local
in order to function as a reverse proxy (thus having 2 network interfaces).
The purpose is also to illustrate the fundamentals of proxied client/server communication, so :
- At startup, the
client
process issues arequest
toproxy
to open a proxied connection toserver
. - It then waits for the request to emit the
connect
event, thus indicating that the connection is established. - From there, all communications between the
client
andserver
processes happen by reading from and writing to the proxied connection's TCP socket. - All events occuring on the different processes are written to their respective container's logs in a user-friendly manner.
- A custom tmux session is used to visualize
client
,proxy
andserver
containers logs on a single screen and monitor the traffic.
The server container emulates a production server running in an isolated network.
The server
process can run in two modes :
-
HTTP mode
- A Node.js
instance runs on top of the proxied connections.http.Server
- Each time a valid HTTP request is received, the instance returns a valid HTTP response with code
200 (OK)
. - When an invalid HTTP request is received, the instance returns a valid HTTP response with code
400 (Bad Request)
and closes the proxied connection.
- A Node.js
-
TCP mode
- A Node.js
instance runs on top of the proxied connections.net.Server
- Each time some data is read from a connection's TCP socket, the instance echoes the received bytes.
- A Node.js
The proxy container emulates a public facing reverse proxy, running in an isolated network but also connected to the internet
- It is a Node.js
instance.http.Server
- The instance establishes a connection between
client
andserver
containers when issued a HTTPCONNECT
request. - Once connected, it returns a TCP socket (Node.js
) to thestream.Duplex
client
.
Note: all traffic between client
and proxy
containers is secured by TLSv1.3 (a TLS layer has been added between the clients TCP sockets and the Node.js http.Server
instance handling them inside the proxy). As a result, the traffic between the clients and the server that would be publicly exposed in a real world situation is encrypted.
The client container emulates a host connected to the internet, sending requests to and receiving responses from the production server through the reverse proxy
- The process uses
to issue a HTTPhttp.request
CONNECT
request to theproxy
container at startup. - It retrieves a TCP socket (Node.js
) once the connection tostream.Duplex
server
is established. - Afterwards, it performs continuous reads from a specific named pipe using this module and write whatever bytes are read to the TCP socket (thus sending it to
server
).
- Linux distro or WLS2 (debian 11 recommended)
- GNU Bash shell (version 5.1.4 recommended)
- Docker (version 20.10.16 recommended)
- Openssl (version 1.1.1 recommended)
- Tmux (version 3.1 recommended)
- Git (version 2.30.2 recommended)
Navigate to your install directory and type the following commands sequence :
git clone https://github.com/mulekick/node-http-tunnel.git
to clone the repository.cd node-http-tunnel
to cd into it.. tunnel.sh tls
to configure the TLS layer by generating a certificate and a private key that will be used by theproxy
process.. tunnel.sh build
to build the Docker images for theclient
,proxy
andserver
containers.
When in the node-http-tunnel
directory, type one of the following commands :
-
. tunnel.sh start http
- creates networks
ntw-internet
andntw-local
. - starts container
server
in HTTP mode (web server) and attaches it tontw-local
. - starts container
proxy
and attaches it tontw-local
andntw-internet
. - starts containers
client-1
andclient-2
and attaches them tontw-internet
. - starts a custom tmux session displaying all the containers logs and a spare shell.
- creates networks
-
. tunnel.sh start tcp
- creates networks
ntw-internet
andntw-local
. - starts container
server
in TCP mode (echo server) and attaches it tontw-local
. - starts container
proxy
and attaches it tontw-local
andntw-internet
. - starts containers
client-1
andclient-2
and attaches them tontw-internet
. - starts a custom tmux session displaying all the containers logs and a spare shell.
- creates networks
Once the containers are started and the tmux session is up :
- Use tmux commands to navigate the session to the bottom window and access the spare shell.
- Type
docker exec -it client-1 /bin/bash
to open a shell inside containerclient-1
(orclient-2
). - Once inside the container, echo or cat whatever you want into the named pipe
/src/client-pipe
to have the client send it to the server through the proxied connection. - See the traffic taking place at the TCP socket level between the
client
andserver
containers. - Once you're done, type
exit
orCtrl-D
to exit the container and return to the spare shell.
Note: dont forget that your proxied connection will be terminated if you send anything that is not a valid HTTP message when the server
container runs in HTTP mode. Some sample well-formatted HTTP messages are provided in /HTTPMSGS, cat these into /src/client-pipe
to have the server respond with nice Pepe the Frog ASCII art.
When in the node-http-tunnel
directory (in the spare shell or elsewhere), type the following command:
. tunnel.sh stop
- stops and removes containers
client-1
,client-2
,server
andproxy
(thus terminating all network connections) - removes networks
ntw-internet
andntw-local
- kills the tmux session (thus terminating all foreground processes)
- stops and removes containers
- Basic knowledge of the bash/sh shell commands (at least
cd
,echo
andcat
) is required. - Basic knowledge of tmux navigation commands (C-b up, down, etc ...) is required.
- Reminder : IETF defined that line endings for HTTP messages must be CRLF. The Node.js HTTP parser won't have it if you do otherwise.
- What is HTTP tunneling.
- In the event you need an npm module which exports Pepe the Frog ASCII art.
- The next step in this project should probably be to setup a firewall inside the
proxy
container to block irrelevant/malicious connection attempts. I may do it later using iptables.